[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