[llvm] 3a3c951 - [InstCombine] Negator: 0 - (X + Y) --> (-X) - Y iff a single operand negated

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 5 10:01:59 PDT 2020


Author: Roman Lebedev
Date: 2020-08-05T20:01:13+03:00
New Revision: 3a3c9519e272e664172a0a90e8abf84b6d400106

URL: https://github.com/llvm/llvm-project/commit/3a3c9519e272e664172a0a90e8abf84b6d400106
DIFF: https://github.com/llvm/llvm-project/commit/3a3c9519e272e664172a0a90e8abf84b6d400106.diff

LOG: [InstCombine] Negator: 0 - (X + Y)  -->  (-X) - Y  iff a single operand negated

This was the most obvious regression in
f5df5cd5586ae9cfb2d9e53704dfc76f47aff149.f5df5cd5586ae9cfb2d9e53704dfc76f47aff149

We really don't want to do this if the original/outermost subtraction
isn't a negation, and therefore doesn't go away - just sinking negation
isn't a win. We are actually appear to be missing folds so hoist it.

https://rise4fun.com/Alive/tiVe

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
    llvm/test/Transforms/InstCombine/sub-of-negatible.ll
    llvm/test/Transforms/InstCombine/sub.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
index b684016b6a29..be69061b3947 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
@@ -347,13 +347,32 @@ LLVM_NODISCARD Value *Negator::visitImpl(Value *V, unsigned Depth) {
     LLVM_FALLTHROUGH;
   case Instruction::Add: {
     // `add` is negatible if both of its operands are negatible.
-    Value *NegOp0 = negate(I->getOperand(0), Depth + 1);
-    if (!NegOp0) // Early return.
-      return nullptr;
-    Value *NegOp1 = negate(I->getOperand(1), Depth + 1);
-    if (!NegOp1)
+    SmallVector<Value *, 2> NegatedOps, NonNegatedOps;
+    for (Value *Op : I->operands()) {
+      // Can we sink the negation into this operand?
+      if (Value *NegOp = negate(Op, Depth + 1)) {
+        NegatedOps.emplace_back(NegOp); // Successfully negated operand!
+        continue;
+      }
+      // Failed to sink negation into this operand. IFF we started from negation
+      // and we manage to sink negation into one operand, we can still do this.
+      if (!IsTrulyNegation)
+        return nullptr;
+      NonNegatedOps.emplace_back(Op); // Just record which operand that was.
+    }
+    assert((NegatedOps.size() + NonNegatedOps.size()) == 2 &&
+           "Internal consistency sanity check.");
+    // Did we manage to sink negation into both of the operands?
+    if (NegatedOps.size() == 2) // Then we get to keep the `add`!
+      return Builder.CreateAdd(NegatedOps[0], NegatedOps[1],
+                               I->getName() + ".neg");
+    assert(IsTrulyNegation && "We should have early-exited then.");
+    // Completely failed to sink negation?
+    if (NonNegatedOps.size() == 2)
       return nullptr;
-    return Builder.CreateAdd(NegOp0, NegOp1, I->getName() + ".neg");
+    // 0-(a+b) --> (-a)-b
+    return Builder.CreateSub(NegatedOps[0], NonNegatedOps[0],
+                             I->getName() + ".neg");
   }
   case Instruction::Xor:
     // `xor` is negatible if one of its operands is invertible.

diff  --git a/llvm/test/Transforms/InstCombine/sub-of-negatible.ll b/llvm/test/Transforms/InstCombine/sub-of-negatible.ll
index 478724dc5207..f1f0609c924a 100644
--- a/llvm/test/Transforms/InstCombine/sub-of-negatible.ll
+++ b/llvm/test/Transforms/InstCombine/sub-of-negatible.ll
@@ -1106,9 +1106,8 @@ define i8 @negate_left_shift_by_constant_extrause(i8 %x, i8 %y, i8 %z, i8 %k) {
 ; `add` with single negatible operand is still negatible
 define i8 @negate_add_with_single_negatible_operand(i8 %x, i8 %y) {
 ; CHECK-LABEL: @negate_add_with_single_negatible_operand(
-; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], 42
-; CHECK-NEXT:    [[T1:%.*]] = sub i8 0, [[T0]]
-; CHECK-NEXT:    ret i8 [[T1]]
+; CHECK-NEXT:    [[T0_NEG:%.*]] = sub i8 -42, [[X:%.*]]
+; CHECK-NEXT:    ret i8 [[T0_NEG]]
 ;
   %t0 = add i8 %x, 42
   %t1 = sub i8 0, %t0
@@ -1126,6 +1125,7 @@ define i8 @negate_add_with_single_negatible_operand_extrause(i8 %x, i8 %y) {
   %t1 = sub i8 0, %t0
   ret i8 %t1
 }
+; But don't do this if that means just sinking the negation.
 define i8 @negate_add_with_single_negatible_operand_non_negation(i8 %x, i8 %y) {
 ; CHECK-LABEL: @negate_add_with_single_negatible_operand_non_negation(
 ; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], 42

diff  --git a/llvm/test/Transforms/InstCombine/sub.ll b/llvm/test/Transforms/InstCombine/sub.ll
index 4116a79d66d9..d2e566be3411 100644
--- a/llvm/test/Transforms/InstCombine/sub.ll
+++ b/llvm/test/Transforms/InstCombine/sub.ll
@@ -839,10 +839,9 @@ define i64 @test29(i8* %foo, i64 %i, i64 %j) {
 
 define i64 @test30(i8* %foo, i64 %i, i64 %j) {
 ; CHECK-LABEL: @test30(
-; CHECK-NEXT:    [[GEP1_IDX_NEG:%.*]] = mul i64 [[I:%.*]], -4
-; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[GEP1_IDX_NEG]], [[J:%.*]]
-; CHECK-NEXT:    [[DIFF_NEG:%.*]] = sub i64 0, [[TMP1]]
-; CHECK-NEXT:    ret i64 [[DIFF_NEG]]
+; CHECK-NEXT:    [[GEP1_IDX_NEG_NEG:%.*]] = shl i64 [[I:%.*]], 2
+; CHECK-NEXT:    [[DOTNEG:%.*]] = sub i64 [[GEP1_IDX_NEG_NEG]], [[J:%.*]]
+; CHECK-NEXT:    ret i64 [[DOTNEG]]
 ;
   %bit = bitcast i8* %foo to i32*
   %gep1 = getelementptr inbounds i32, i32* %bit, i64 %i
@@ -855,10 +854,9 @@ define i64 @test30(i8* %foo, i64 %i, i64 %j) {
 
 define i16 @test30_as1(i8 addrspace(1)* %foo, i16 %i, i16 %j) {
 ; CHECK-LABEL: @test30_as1(
-; CHECK-NEXT:    [[GEP1_IDX_NEG:%.*]] = mul i16 [[I:%.*]], -4
-; CHECK-NEXT:    [[TMP1:%.*]] = add i16 [[GEP1_IDX_NEG]], [[J:%.*]]
-; CHECK-NEXT:    [[DIFF_NEG:%.*]] = sub i16 0, [[TMP1]]
-; CHECK-NEXT:    ret i16 [[DIFF_NEG]]
+; CHECK-NEXT:    [[GEP1_IDX_NEG_NEG:%.*]] = shl i16 [[I:%.*]], 2
+; CHECK-NEXT:    [[DOTNEG:%.*]] = sub i16 [[GEP1_IDX_NEG_NEG]], [[J:%.*]]
+; CHECK-NEXT:    ret i16 [[DOTNEG]]
 ;
   %bit = bitcast i8 addrspace(1)* %foo to i32 addrspace(1)*
   %gep1 = getelementptr inbounds i32, i32 addrspace(1)* %bit, i16 %i


        


More information about the llvm-commits mailing list