[llvm] 8eeabba - [ConstantFold] Handle identity folds at top of ConstantFoldBinaryInst

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 17 13:30:44 PST 2019


Author: Florian Hahn
Date: 2019-11-17T21:30:14Z
New Revision: 8eeabbaf5da31f44b42f0ef7d625640570b0a620

URL: https://github.com/llvm/llvm-project/commit/8eeabbaf5da31f44b42f0ef7d625640570b0a620
DIFF: https://github.com/llvm/llvm-project/commit/8eeabbaf5da31f44b42f0ef7d625640570b0a620.diff

LOG: [ConstantFold] Handle identity folds at top of ConstantFoldBinaryInst

Currently we miss folds with undef and identity values for binary ops
that do not fold to undef in general.

We can generalize the identity simplifications and do them before
checking for undef in particular.

Alive checks:
 * OR - https://rise4fun.com/Alive/8OsK
 * AND - https://rise4fun.com/Alive/e3tE

This will also allow us to remove some now redundant cases throughout
the function, but I would like to do this as follow-up. That should make
tracking down potential issues easier.

Reviewers: spatel, RKSimon, lebedev.ri

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D70169

Added: 
    

Modified: 
    llvm/lib/IR/ConstantFold.cpp
    llvm/test/Analysis/ConstantFolding/binop-identity-undef.ll
    llvm/test/Transforms/InstCombine/vec_shuffle.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index a6cd83310088..f6dbe9b5ea93 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -988,6 +988,19 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
                                               Constant *C2) {
   assert(Instruction::isBinaryOp(Opcode) && "Non-binary instruction detected");
 
+  // Simplify BinOps with their identity values first. They are no-ops and we
+  // can always return the other value, including undef or poison values.
+  // FIXME: remove unnecessary duplicated identity patterns below.
+  // FIXME: Use AllowRHSConstant with getBinOpIdentity to handle additional ops,
+  //        like X << 0 = X.
+  Constant *Identity = ConstantExpr::getBinOpIdentity(Opcode, C1->getType());
+  if (Identity) {
+    if (C1 == Identity)
+      return C2;
+    if (C2 == Identity)
+      return C1;
+  }
+
   // Handle scalar UndefValue. Vectors are always evaluated per element.
   bool HasScalarUndef = !C1->getType()->isVectorTy() &&
                         (isa<UndefValue>(C1) || isa<UndefValue>(C2));

diff  --git a/llvm/test/Analysis/ConstantFolding/binop-identity-undef.ll b/llvm/test/Analysis/ConstantFolding/binop-identity-undef.ll
index 7bb824dfb465..68307892187c 100644
--- a/llvm/test/Analysis/ConstantFolding/binop-identity-undef.ll
+++ b/llvm/test/Analysis/ConstantFolding/binop-identity-undef.ll
@@ -3,7 +3,7 @@
 
 define i32 @and1() {
 ; CHECK-LABEL: @and1(
-; CHECK-NEXT:    ret i32 0
+; CHECK-NEXT:    ret i32 undef
 ;
   %r = and i32 undef, -1
   ret i32 %r
@@ -11,7 +11,7 @@ define i32 @and1() {
 
 define i32 @and2() {
 ; CHECK-LABEL: @and2(
-; CHECK-NEXT:    ret i32 0
+; CHECK-NEXT:    ret i32 undef
 ;
   %r = and i32 -1, undef
   ret i32 %r
@@ -27,7 +27,7 @@ define i32 @and3_no_identity() {
 
 define i32 @or1() {
 ; CHECK-LABEL: @or1(
-; CHECK-NEXT:    ret i32 -1
+; CHECK-NEXT:    ret i32 undef
 ;
   %r = or i32 0, undef
   ret i32 %r
@@ -35,7 +35,7 @@ define i32 @or1() {
 
 define i32 @or2() {
 ; CHECK-LABEL: @or2(
-; CHECK-NEXT:    ret i32 -1
+; CHECK-NEXT:    ret i32 undef
 ;
   %r = or i32 undef, 0
   ret i32 %r

diff  --git a/llvm/test/Transforms/InstCombine/vec_shuffle.ll b/llvm/test/Transforms/InstCombine/vec_shuffle.ll
index 07c888ac6ae0..b7b02a597d21 100644
--- a/llvm/test/Transforms/InstCombine/vec_shuffle.ll
+++ b/llvm/test/Transforms/InstCombine/vec_shuffle.ll
@@ -1034,13 +1034,11 @@ entry:
   ret <4 x i16> %and
 }
 
-; FIXME: We should be able to move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes.
+; We can move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes.
 define <4 x i16> @and_constant_mask_undef_3(<4 x i16> %add) {
 ; CHECK-LABEL: @and_constant_mask_undef_3(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> undef, <4 x i32> <i32 0, i32 1, i32 1, i32 undef>
-; CHECK-NEXT:    [[AND:%.*]] = and <4 x i16> [[SHUFFLE]], <i16 0, i16 0, i16 0, i16 -1>
-; CHECK-NEXT:    ret <4 x i16> [[AND]]
+; CHECK-NEXT:    ret <4 x i16> <i16 0, i16 0, i16 0, i16 undef>
 ;
 entry:
   %shuffle = shufflevector <4 x i16> %add, <4 x i16> undef, <4 x i32> <i32 0, i32 1, i32 1, i32 undef>
@@ -1048,12 +1046,12 @@ entry:
   ret <4 x i16> %and
 }
 
-; FIXME: We should be able to move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes.
+; We can move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes.
 define <4 x i16> @and_constant_mask_undef_4(<4 x i16> %add) {
 ; CHECK-LABEL: @and_constant_mask_undef_4(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> undef, <4 x i32> <i32 0, i32 1, i32 1, i32 undef>
-; CHECK-NEXT:    [[AND:%.*]] = and <4 x i16> [[SHUFFLE]], <i16 9, i16 20, i16 20, i16 -1>
+; CHECK-NEXT:    [[TMP0:%.*]] = and <4 x i16> [[ADD:%.*]], <i16 9, i16 20, i16 undef, i16 undef>
+; CHECK-NEXT:    [[AND:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> undef, <4 x i32> <i32 0, i32 1, i32 1, i32 undef>
 ; CHECK-NEXT:    ret <4 x i16> [[AND]]
 ;
 entry:
@@ -1105,13 +1103,11 @@ entry:
   ret <4 x i16> %or
 }
 
-; FIXME: We should be able to move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes.
+; We can move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes.
 define <4 x i16> @or_constant_mask_undef_3(<4 x i16> %in) {
 ; CHECK-LABEL: @or_constant_mask_undef_3(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> undef, <4 x i32> <i32 undef, i32 1, i32 1, i32 undef>
-; CHECK-NEXT:    [[OR:%.*]] = or <4 x i16> [[SHUFFLE]], <i16 0, i16 -1, i16 -1, i16 0>
-; CHECK-NEXT:    ret <4 x i16> [[OR]]
+; CHECK-NEXT:    ret <4 x i16> <i16 undef, i16 -1, i16 -1, i16 undef>
 ;
 entry:
   %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 undef, i32 1, i32 1, i32 undef>
@@ -1119,12 +1115,12 @@ entry:
   ret <4 x i16> %or
 }
 
-; FIXME: We should be able to move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes.
+; We can move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes.
 define <4 x i16> @or_constant_mask_undef_4(<4 x i16> %in) {
 ; CHECK-LABEL: @or_constant_mask_undef_4(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> undef, <4 x i32> <i32 undef, i32 1, i32 1, i32 undef>
-; CHECK-NEXT:    [[OR:%.*]] = or <4 x i16> [[SHUFFLE]], <i16 0, i16 99, i16 99, i16 0>
+; CHECK-NEXT:    [[TMP0:%.*]] = or <4 x i16> [[IN:%.*]], <i16 undef, i16 99, i16 undef, i16 undef>
+; CHECK-NEXT:    [[OR:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> undef, <4 x i32> <i32 undef, i32 1, i32 1, i32 undef>
 ; CHECK-NEXT:    ret <4 x i16> [[OR]]
 ;
 entry:


        


More information about the llvm-commits mailing list