[llvm] [InstCombine] Improve select simplification based on known bits (PR #97289)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 4 07:02:48 PDT 2024
https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/97289
>From f11c7ce2a2fbda0e6c7f9cf7de7a7bdba2c27340 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 18 Jun 2024 15:12:54 +0200
Subject: [PATCH 1/2] Use demanded bits simplification
---
.../InstCombine/InstCombineSelect.cpp | 42 ++++++++++++-------
llvm/test/Transforms/InstCombine/select.ll | 11 ++---
2 files changed, 32 insertions(+), 21 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 3f780285efe423..be2f2fdd669979 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -4213,22 +4213,36 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
});
SimplifyQuery Q = SQ.getWithInstruction(&SI).getWithCondContext(CC);
if (!CC.AffectedValues.empty()) {
- if (!isa<Constant>(TrueVal) &&
- hasAffectedValue(TrueVal, CC.AffectedValues, /*Depth=*/0)) {
- KnownBits Known = llvm::computeKnownBits(TrueVal, /*Depth=*/0, Q);
- if (Known.isConstant())
- return replaceOperand(SI, 1,
- ConstantInt::get(SelType, Known.getConstant()));
- }
+ std::optional<bool> NotUndef;
+ auto SimplifyOp = [&](unsigned OpNum) -> Instruction * {
+ Value *V = SI.getOperand(OpNum);
+ if (isa<Constant>(V) ||
+ !hasAffectedValue(V, CC.AffectedValues, /*Depth=*/0))
+ return nullptr;
+
+ if (!NotUndef)
+ NotUndef = isGuaranteedNotToBeUndef(CondVal);
+ if (*NotUndef) {
+ unsigned BitWidth = SelType->getScalarSizeInBits();
+ KnownBits Known(BitWidth);
+ if (SimplifyDemandedBits(&SI, OpNum, APInt::getAllOnes(BitWidth),
+ Known, /*Depth=*/0, Q))
+ return &SI;
+ } else {
+ KnownBits Known = llvm::computeKnownBits(V, /*Depth=*/0, Q);
+ if (Known.isConstant())
+ return replaceOperand(
+ SI, OpNum, ConstantInt::get(SelType, Known.getConstant()));
+ }
+ return nullptr;
+ };
+
+ if (Instruction *Res = SimplifyOp(1))
+ return Res;
CC.Invert = true;
- if (!isa<Constant>(FalseVal) &&
- hasAffectedValue(FalseVal, CC.AffectedValues, /*Depth=*/0)) {
- KnownBits Known = llvm::computeKnownBits(FalseVal, /*Depth=*/0, Q);
- if (Known.isConstant())
- return replaceOperand(SI, 2,
- ConstantInt::get(SelType, Known.getConstant()));
- }
+ if (Instruction *Res = SimplifyOp(2))
+ return Res;
}
}
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index 7d62b419424405..d66bab4c0b4e3a 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -2989,9 +2989,8 @@ define i8 @select_replacement_loop3(i32 noundef %x) {
define i16 @select_replacement_loop4(i16 noundef %p_12) {
; CHECK-LABEL: @select_replacement_loop4(
-; CHECK-NEXT: [[AND1:%.*]] = and i16 [[P_12:%.*]], 1
-; CHECK-NEXT: [[CMP21:%.*]] = icmp ult i16 [[P_12]], 2
-; CHECK-NEXT: [[AND3:%.*]] = select i1 [[CMP21]], i16 [[AND1]], i16 0
+; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i16 [[P_12:%.*]], 2
+; CHECK-NEXT: [[AND3:%.*]] = select i1 [[CMP1]], i16 [[P_12]], i16 0
; CHECK-NEXT: ret i16 [[AND3]]
;
%cmp1 = icmp ult i16 %p_12, 2
@@ -4671,8 +4670,7 @@ define i8 @select_knownbits_simplify(i8 noundef %x) {
; CHECK-LABEL: @select_knownbits_simplify(
; CHECK-NEXT: [[X_LO:%.*]] = and i8 [[X:%.*]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X_LO]], 0
-; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], -2
-; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i8 [[AND]], i8 0
+; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i8 [[X]], i8 0
; CHECK-NEXT: ret i8 [[RES]]
;
%x.lo = and i8 %x, 1
@@ -4686,8 +4684,7 @@ define i8 @select_knownbits_simplify_nested(i8 noundef %x) {
; CHECK-LABEL: @select_knownbits_simplify_nested(
; CHECK-NEXT: [[X_LO:%.*]] = and i8 [[X:%.*]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X_LO]], 0
-; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], -2
-; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[AND]], [[AND]]
+; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[X]], [[X]]
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i8 [[MUL]], i8 0
; CHECK-NEXT: ret i8 [[RES]]
;
>From 8c00ff4b7117e4404245d5d3a31af059ecd66157 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Fri, 4 Oct 2024 16:02:28 +0200
Subject: [PATCH 2/2] Try to disable fold
---
.../InstCombine/InstCombineSimplifyDemanded.cpp | 2 ++
llvm/test/Transforms/InstCombine/add.ll | 10 +++++-----
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index ee6b60f7f70d68..29efd8462cb289 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -320,6 +320,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
// bits on that side are also known to be set on the other side, turn this
// into an AND, as we know the bits will be cleared.
// e.g. (X | C1) ^ C2 --> (X | C1) & ~C2 iff (C1&C2) == C2
+#if 0
if (DemandedMask.isSubsetOf(RHSKnown.Zero|RHSKnown.One) &&
RHSKnown.One.isSubsetOf(LHSKnown.One)) {
Constant *AndC = Constant::getIntegerValue(VTy,
@@ -327,6 +328,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
Instruction *And = BinaryOperator::CreateAnd(I->getOperand(0), AndC);
return InsertNewInstWith(And, I->getIterator());
}
+#endif
// If the RHS is a constant, see if we can change it. Don't alter a -1
// constant because that's a canonical 'not' op, and that is better for
diff --git a/llvm/test/Transforms/InstCombine/add.ll b/llvm/test/Transforms/InstCombine/add.ll
index 417c3a950d7805..12e55557d504a6 100644
--- a/llvm/test/Transforms/InstCombine/add.ll
+++ b/llvm/test/Transforms/InstCombine/add.ll
@@ -1196,8 +1196,8 @@ define i32 @add_to_sub2(i32 %A, i32 %M) {
; (X | C1) + C2 --> (X | C1) ^ C1 iff (C1 == -C2)
define i32 @test44(i32 %A) {
; CHECK-LABEL: @test44(
-; CHECK-NEXT: [[C:%.*]] = and i32 [[A:%.*]], -124
-; CHECK-NEXT: ret i32 [[C]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], -124
+; CHECK-NEXT: ret i32 [[TMP1]]
;
%B = or i32 %A, 123
%C = add i32 %B, -123
@@ -1207,7 +1207,7 @@ define i32 @test44(i32 %A) {
define i32 @test44_extra_use(i32 %A) {
; CHECK-LABEL: @test44_extra_use(
; CHECK-NEXT: [[B:%.*]] = or i32 [[A:%.*]], 123
-; CHECK-NEXT: [[C:%.*]] = and i32 [[A]], -124
+; CHECK-NEXT: [[C:%.*]] = xor i32 [[B]], 123
; CHECK-NEXT: [[D:%.*]] = mul i32 [[B]], [[C]]
; CHECK-NEXT: ret i32 [[D]]
;
@@ -1230,8 +1230,8 @@ define i32 @test44_non_matching(i32 %A) {
define <2 x i32> @test44_vec(<2 x i32> %A) {
; CHECK-LABEL: @test44_vec(
-; CHECK-NEXT: [[C:%.*]] = and <2 x i32> [[A:%.*]], <i32 -124, i32 -124>
-; CHECK-NEXT: ret <2 x i32> [[C]]
+; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[A:%.*]], <i32 -124, i32 -124>
+; CHECK-NEXT: ret <2 x i32> [[TMP1]]
;
%B = or <2 x i32> %A, <i32 123, i32 123>
%C = add <2 x i32> %B, <i32 -123, i32 -123>
More information about the llvm-commits
mailing list