]> granicus.if.org Git - llvm/commitdiff
[InstSimplify] add nsw/nuw (xor X, signbit), signbit --> X
authorSanjay Patel <spatel@rotateright.com>
Sat, 18 Feb 2017 21:59:09 +0000 (21:59 +0000)
committerSanjay Patel <spatel@rotateright.com>
Sat, 18 Feb 2017 21:59:09 +0000 (21:59 +0000)
The change to InstCombine in:
https://reviews.llvm.org/D29729
...exposes this missing fold in InstSimplify, so adding this
first to avoid a regression.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@295573 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/InstructionSimplify.cpp
test/Transforms/InstCombine/add.ll
test/Transforms/InstSimplify/AndOrXor.ll

index 2c7ca6210ada7c4c0af7f2804709c51b0d38ce84..8fce1630aeec5ec6c0e5be27a451b6a4065676a4 100644 (file)
@@ -557,9 +557,19 @@ static Value *SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
     return Y;
 
   // X + ~X -> -1   since   ~X = -X-1
+  Type *Ty = Op0->getType();
   if (match(Op0, m_Not(m_Specific(Op1))) ||
       match(Op1, m_Not(m_Specific(Op0))))
-    return Constant::getAllOnesValue(Op0->getType());
+    return Constant::getAllOnesValue(Ty);
+
+  // add nsw/nuw (xor Y, signbit), signbit --> Y
+  // The no-wrapping add guarantees that the top bit will be set by the add.
+  // Therefore, the xor must be clearing the already set sign bit of Y.
+  Constant *SignBit =
+      ConstantInt::get(Ty, APInt::getSignBit(Ty->getScalarSizeInBits()));
+  if ((isNSW || isNUW) && match(Op1, m_Specific(SignBit)) &&
+      match(Op0, m_Xor(m_Value(Y), m_Specific(SignBit))))
+    return Y;
 
   /// i1 add -> xor.
   if (MaxRecurse && Op0->getType()->isIntegerTy(1))
index 03b2c3e857120ad1797cb6e7ea74f0f82d47dfd9..c04953d1a4101f5035d97844cadf83912cc7112b 100644 (file)
@@ -244,7 +244,9 @@ define i32 @test19(i1 %C) {
   ret i32 %V
 }
 
-; Add of sign bit -> xor of sign bit.
+; This is an InstSimplify fold, but test it here to make sure that
+; InstCombine does not prevent the fold.
+; With NSW, add of sign bit -> or of sign bit.
 
 define i32 @test20(i32 %x) {
 ; CHECK-LABEL: @test20(
index 35fbb88eab230c5e93f2e285283de4a2a8722717..33fd978277d4ce477c78087429944c2c93ec804e 100644 (file)
@@ -5,9 +5,7 @@
 
 define <2 x i32> @add_nsw_signbit(<2 x i32> %x) {
 ; CHECK-LABEL: @add_nsw_signbit(
-; CHECK-NEXT:    [[Y:%.*]] = xor <2 x i32> %x, <i32 -2147483648, i32 -2147483648>
-; CHECK-NEXT:    [[Z:%.*]] = add nsw <2 x i32> [[Y]], <i32 -2147483648, i32 -2147483648>
-; CHECK-NEXT:    ret <2 x i32> [[Z]]
+; CHECK-NEXT:    ret <2 x i32> %x
 ;
   %y = xor <2 x i32> %x, <i32 -2147483648, i32 -2147483648>
   %z = add nsw <2 x i32> %y, <i32 -2147483648, i32 -2147483648>
@@ -18,9 +16,7 @@ define <2 x i32> @add_nsw_signbit(<2 x i32> %x) {
 
 define <2 x i5> @add_nuw_signbit(<2 x i5> %x) {
 ; CHECK-LABEL: @add_nuw_signbit(
-; CHECK-NEXT:    [[Y:%.*]] = xor <2 x i5> %x, <i5 -16, i5 -16>
-; CHECK-NEXT:    [[Z:%.*]] = add nuw <2 x i5> [[Y]], <i5 -16, i5 -16>
-; CHECK-NEXT:    ret <2 x i5> [[Z]]
+; CHECK-NEXT:    ret <2 x i5> %x
 ;
   %y = xor <2 x i5> %x, <i5 -16, i5 -16>
   %z = add nuw <2 x i5> %y, <i5 -16, i5 -16>