Skip to content

Commit 87dd67f

Browse files
[ConstantFold][RFC] Fold special constant value with binop absorber folding
Return the consant value C if C op X = C, X can be every value including undef and poison vaule, and remove redurdant flods later in the code. Signed-off-by: eric.tang <[email protected]>
1 parent eca5949 commit 87dd67f

File tree

7 files changed

+62
-45
lines changed

7 files changed

+62
-45
lines changed

llvm/include/llvm/IR/Constants.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,8 +1210,11 @@ class ConstantExpr : public Constant {
12101210
/// Return the absorbing element for the given binary
12111211
/// operation, i.e. a constant C such that X op C = C and C op X = C for
12121212
/// every X. For example, this returns zero for integer multiplication.
1213-
/// It returns null if the operator doesn't have an absorbing element.
1214-
static Constant *getBinOpAbsorber(unsigned Opcode, Type *Ty);
1213+
/// If AllowLHSConstant is true, operand 0 is a constant C that must be
1214+
/// defined as C op X = C. It returns null if the operator doesn't have
1215+
/// an absorbing element.
1216+
static Constant *getBinOpAbsorber(unsigned Opcode, Type *Ty,
1217+
bool AllowLHSConstant = false);
12151218

12161219
/// Transparently provide more efficient getOperand methods.
12171220
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);

llvm/lib/IR/ConstantFold.cpp

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,14 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
624624
return C1;
625625
}
626626

627+
if (Constant *Absorber = ConstantExpr::getBinOpAbsorber(
628+
Opcode, C1->getType(), /*AllowLHSAbsorber*/ true)) {
629+
if (C1 == Absorber)
630+
return C1;
631+
if (C2 == Absorber)
632+
return C2;
633+
}
634+
627635
// Binary operations propagate poison.
628636
if (isa<PoisonValue>(C1) || isa<PoisonValue>(C2))
629637
return PoisonValue::get(C1->getType());
@@ -733,8 +741,7 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
733741
if (ConstantInt *CI2 = dyn_cast<ConstantInt>(C2)) {
734742
switch (Opcode) {
735743
case Instruction::Mul:
736-
if (CI2->isZero())
737-
return C2; // X * 0 == 0
744+
assert(!CI2->isZero() && "Mul zero handled above");
738745
break;
739746
case Instruction::UDiv:
740747
case Instruction::SDiv:
@@ -749,9 +756,7 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
749756
return PoisonValue::get(CI2->getType()); // X % 0 == poison
750757
break;
751758
case Instruction::And:
752-
if (CI2->isZero())
753-
return C2; // X & 0 == 0
754-
759+
assert(!CI2->isZero() && "And zero handled above");
755760
if (ConstantExpr *CE1 = dyn_cast<ConstantExpr>(C1)) {
756761
// If and'ing the address of a global with a constant, fold it.
757762
if (CE1->getOpcode() == Instruction::PtrToInt &&
@@ -792,8 +797,7 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
792797
}
793798
break;
794799
case Instruction::Or:
795-
if (CI2->isMinusOne())
796-
return C2; // X | -1 == -1
800+
assert(!CI2->isMinusOne() && "Or MinusOne handled above");
797801
break;
798802
}
799803
} else if (isa<ConstantInt>(C1)) {
@@ -840,33 +844,22 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
840844
case Instruction::Xor:
841845
return ConstantInt::get(CI1->getContext(), C1V ^ C2V);
842846
case Instruction::Shl:
847+
assert(!CI1->isZero() && "Zero Shl handled above");
843848
if (C2V.ult(C1V.getBitWidth()))
844849
return ConstantInt::get(CI1->getContext(), C1V.shl(C2V));
845850
return PoisonValue::get(C1->getType()); // too big shift is poison
846851
case Instruction::LShr:
852+
assert(!CI1->isZero() && "Zero LShr handled above");
847853
if (C2V.ult(C1V.getBitWidth()))
848854
return ConstantInt::get(CI1->getContext(), C1V.lshr(C2V));
849855
return PoisonValue::get(C1->getType()); // too big shift is poison
850856
case Instruction::AShr:
857+
assert(!CI1->isZero() && "Zero AShr handled above");
851858
if (C2V.ult(C1V.getBitWidth()))
852859
return ConstantInt::get(CI1->getContext(), C1V.ashr(C2V));
853860
return PoisonValue::get(C1->getType()); // too big shift is poison
854861
}
855862
}
856-
857-
switch (Opcode) {
858-
case Instruction::SDiv:
859-
case Instruction::UDiv:
860-
case Instruction::URem:
861-
case Instruction::SRem:
862-
case Instruction::LShr:
863-
case Instruction::AShr:
864-
case Instruction::Shl:
865-
if (CI1->isZero()) return C1;
866-
break;
867-
default:
868-
break;
869-
}
870863
} else if (ConstantFP *CFP1 = dyn_cast<ConstantFP>(C1)) {
871864
if (ConstantFP *CFP2 = dyn_cast<ConstantFP>(C2)) {
872865
const APFloat &C1V = CFP1->getValueAPF();

llvm/lib/IR/Constants.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2735,17 +2735,30 @@ Constant *ConstantExpr::getIdentity(Instruction *I, Type *Ty,
27352735
return nullptr;
27362736
}
27372737

2738-
Constant *ConstantExpr::getBinOpAbsorber(unsigned Opcode, Type *Ty) {
2738+
Constant *ConstantExpr::getBinOpAbsorber(unsigned Opcode, Type *Ty,
2739+
bool AllowLHSConstant) {
27392740
switch (Opcode) {
27402741
default:
2741-
// Doesn't have an absorber.
2742-
return nullptr;
2742+
break;
27432743

2744-
case Instruction::Or:
2744+
case Instruction::Or: // -1 | X = -1
27452745
return Constant::getAllOnesValue(Ty);
27462746

2747-
case Instruction::And:
2748-
case Instruction::Mul:
2747+
case Instruction::And: // 0 & X = 0
2748+
case Instruction::Mul: // 0 * X = 0
2749+
return Constant::getNullValue(Ty);
2750+
}
2751+
2752+
// AllowLHSConstant must be set.
2753+
if (!AllowLHSConstant)
2754+
return nullptr;
2755+
2756+
switch (Opcode) {
2757+
default:
2758+
return nullptr;
2759+
case Instruction::Shl: // 0 << X = 0
2760+
case Instruction::LShr: // 0 >>l X = 0
2761+
case Instruction::AShr: // 0 >>a X = 0
27492762
return Constant::getNullValue(Ty);
27502763
}
27512764
}

llvm/test/Transforms/InstCombine/vec_shuffle-inseltpoison.ll

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -691,8 +691,8 @@ define <4 x i16> @widening_shuffle_shl_constant_op1_non0(<2 x i16> %v) {
691691

692692
define <4 x i16> @widening_shuffle_or(<2 x i16> %v) {
693693
; CHECK-LABEL: @widening_shuffle_or(
694-
; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i16> [[V:%.*]], <i16 42, i16 -42>
695-
; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
694+
; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i16> [[V:%.*]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
695+
; CHECK-NEXT: [[BO:%.*]] = or <4 x i16> [[SHUF]], <i16 42, i16 -42, i16 -1, i16 -1>
696696
; CHECK-NEXT: ret <4 x i16> [[BO]]
697697
;
698698
%shuf = shufflevector <2 x i16> %v, <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
@@ -1035,7 +1035,8 @@ define <2 x i32> @and_splat_constant(<2 x i32> %x) {
10351035
define <4 x i16> @and_constant_mask_poison(<4 x i16> %add) {
10361036
; CHECK-LABEL: @and_constant_mask_poison(
10371037
; CHECK-NEXT: entry:
1038-
; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
1038+
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
1039+
; CHECK-NEXT: [[AND:%.*]] = and <4 x i16> [[SHUFFLE]], <i16 0, i16 0, i16 -1, i16 -1>
10391040
; CHECK-NEXT: ret <4 x i16> [[AND]]
10401041
;
10411042
entry:
@@ -1047,7 +1048,8 @@ entry:
10471048
define <4 x i16> @and_constant_mask_poison_2(<4 x i16> %add) {
10481049
; CHECK-LABEL: @and_constant_mask_poison_2(
10491050
; CHECK-NEXT: entry:
1050-
; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 poison>
1051+
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 poison>
1052+
; CHECK-NEXT: [[AND:%.*]] = and <4 x i16> [[SHUFFLE]], <i16 -1, i16 -1, i16 -1, i16 0>
10511053
; CHECK-NEXT: ret <4 x i16> [[AND]]
10521054
;
10531055
entry:
@@ -1098,7 +1100,8 @@ entry:
10981100
define <4 x i16> @or_constant_mask_poison(<4 x i16> %in) {
10991101
; CHECK-LABEL: @or_constant_mask_poison(
11001102
; CHECK-NEXT: entry:
1101-
; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
1103+
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
1104+
; CHECK-NEXT: [[OR:%.*]] = or <4 x i16> [[SHUFFLE]], <i16 -1, i16 -1, i16 0, i16 0>
11021105
; CHECK-NEXT: ret <4 x i16> [[OR]]
11031106
;
11041107
entry:
@@ -1110,7 +1113,8 @@ entry:
11101113
define <4 x i16> @or_constant_mask_poison_2(<4 x i16> %in) {
11111114
; CHECK-LABEL: @or_constant_mask_poison_2(
11121115
; CHECK-NEXT: entry:
1113-
; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison>
1116+
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison>
1117+
; CHECK-NEXT: [[OR:%.*]] = or <4 x i16> [[SHUFFLE]], <i16 -1, i16 0, i16 0, i16 -1>
11141118
; CHECK-NEXT: ret <4 x i16> [[OR]]
11151119
;
11161120
entry:

llvm/test/Transforms/InstCombine/vec_shuffle.ll

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -685,8 +685,8 @@ define <4 x i16> @widening_shuffle_shl_constant_op1_non0(<2 x i16> %v) {
685685

686686
define <4 x i16> @widening_shuffle_or(<2 x i16> %v) {
687687
; CHECK-LABEL: @widening_shuffle_or(
688-
; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i16> [[V:%.*]], <i16 42, i16 -42>
689-
; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
688+
; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i16> [[V:%.*]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
689+
; CHECK-NEXT: [[BO:%.*]] = or <4 x i16> [[SHUF]], <i16 42, i16 -42, i16 -1, i16 -1>
690690
; CHECK-NEXT: ret <4 x i16> [[BO]]
691691
;
692692
%shuf = shufflevector <2 x i16> %v, <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
@@ -1029,7 +1029,8 @@ define <2 x i32> @and_splat_constant(<2 x i32> %x) {
10291029
define <4 x i16> @and_constant_mask_poison(<4 x i16> %add) {
10301030
; CHECK-LABEL: @and_constant_mask_poison(
10311031
; CHECK-NEXT: entry:
1032-
; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
1032+
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
1033+
; CHECK-NEXT: [[AND:%.*]] = and <4 x i16> [[SHUFFLE]], <i16 0, i16 0, i16 -1, i16 -1>
10331034
; CHECK-NEXT: ret <4 x i16> [[AND]]
10341035
;
10351036
entry:
@@ -1041,7 +1042,8 @@ entry:
10411042
define <4 x i16> @and_constant_mask_poison_2(<4 x i16> %add) {
10421043
; CHECK-LABEL: @and_constant_mask_poison_2(
10431044
; CHECK-NEXT: entry:
1044-
; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 poison>
1045+
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 poison>
1046+
; CHECK-NEXT: [[AND:%.*]] = and <4 x i16> [[SHUFFLE]], <i16 -1, i16 -1, i16 -1, i16 0>
10451047
; CHECK-NEXT: ret <4 x i16> [[AND]]
10461048
;
10471049
entry:
@@ -1092,7 +1094,8 @@ entry:
10921094
define <4 x i16> @or_constant_mask_poison(<4 x i16> %in) {
10931095
; CHECK-LABEL: @or_constant_mask_poison(
10941096
; CHECK-NEXT: entry:
1095-
; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
1097+
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
1098+
; CHECK-NEXT: [[OR:%.*]] = or <4 x i16> [[SHUFFLE]], <i16 -1, i16 -1, i16 0, i16 0>
10961099
; CHECK-NEXT: ret <4 x i16> [[OR]]
10971100
;
10981101
entry:
@@ -1104,7 +1107,8 @@ entry:
11041107
define <4 x i16> @or_constant_mask_poison_2(<4 x i16> %in) {
11051108
; CHECK-LABEL: @or_constant_mask_poison_2(
11061109
; CHECK-NEXT: entry:
1107-
; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison>
1110+
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison>
1111+
; CHECK-NEXT: [[OR:%.*]] = or <4 x i16> [[SHUFFLE]], <i16 -1, i16 0, i16 0, i16 -1>
11081112
; CHECK-NEXT: ret <4 x i16> [[OR]]
11091113
;
11101114
entry:

llvm/test/Transforms/InstSimplify/undef.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,23 +244,23 @@ define i32 @test24() {
244244

245245
define i32 @test25() {
246246
; CHECK-LABEL: @test25(
247-
; CHECK-NEXT: ret i32 poison
247+
; CHECK-NEXT: ret i32 0
248248
;
249249
%b = lshr i32 0, undef
250250
ret i32 %b
251251
}
252252

253253
define i32 @test26() {
254254
; CHECK-LABEL: @test26(
255-
; CHECK-NEXT: ret i32 poison
255+
; CHECK-NEXT: ret i32 0
256256
;
257257
%b = ashr i32 0, undef
258258
ret i32 %b
259259
}
260260

261261
define i32 @test27() {
262262
; CHECK-LABEL: @test27(
263-
; CHECK-NEXT: ret i32 poison
263+
; CHECK-NEXT: ret i32 0
264264
;
265265
%b = shl i32 0, undef
266266
ret i32 %b

llvm/test/Transforms/VectorCombine/X86/insert-binop-inseltpoison.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ define <16 x i8> @ins1_ins0_add(i8 %x, i8 %y) {
100100
define <4 x i32> @ins0_ins0_mul(i32 %x, i32 %y) {
101101
; CHECK-LABEL: @ins0_ins0_mul(
102102
; CHECK-NEXT: [[R_SCALAR:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]
103-
; CHECK-NEXT: [[R:%.*]] = insertelement <4 x i32> poison, i32 [[R_SCALAR]], i64 0
103+
; CHECK-NEXT: [[R:%.*]] = insertelement <4 x i32> zeroinitializer, i32 [[R_SCALAR]], i64 0
104104
; CHECK-NEXT: ret <4 x i32> [[R]]
105105
;
106106
%i0 = insertelement <4 x i32> zeroinitializer, i32 %x, i32 0

0 commit comments

Comments
 (0)