Skip to content

Commit 39fea1f

Browse files
committed
[InstSimplify] Handle trunc to i1 in Select with bit test folds.
1 parent 1c3c655 commit 39fea1f

File tree

3 files changed

+30
-20
lines changed

3 files changed

+30
-20
lines changed

llvm/lib/Analysis/CmpInstAnalysis.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ llvm::decomposeBitTestICmp(Value *LHS, Value *RHS, CmpInst::Predicate Pred,
168168

169169
std::optional<DecomposedBitTest>
170170
llvm::decomposeBitTest(Value *Cond, bool LookThruTrunc, bool AllowNonZeroC) {
171+
using namespace PatternMatch;
171172
if (auto *ICmp = dyn_cast<ICmpInst>(Cond)) {
172173
// Don't allow pointers. Splat vectors are fine.
173174
if (!ICmp->getOperand(0)->getType()->isIntOrIntVectorTy())
@@ -176,6 +177,24 @@ llvm::decomposeBitTest(Value *Cond, bool LookThruTrunc, bool AllowNonZeroC) {
176177
ICmp->getPredicate(), LookThruTrunc,
177178
AllowNonZeroC);
178179
}
180+
Value *X;
181+
if (Cond->getType()->isIntOrIntVectorTy(1) &&
182+
(match(Cond, m_Trunc(m_Value(X))) ||
183+
match(Cond, m_Not(m_Trunc(m_Value(X)))))) {
184+
DecomposedBitTest Result;
185+
Result.X = X;
186+
unsigned BitWidth = X->getType()->getScalarSizeInBits();
187+
Result.Mask = APInt(BitWidth, 1);
188+
Result.C = APInt::getZero(BitWidth);
189+
Result.Pred = isa<TruncInst>(Cond) ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ;
190+
191+
if (LookThruTrunc && match(Result.X, m_Trunc(m_Value(X)))) {
192+
Result.X = X;
193+
Result.Mask = Result.Mask.zext(X->getType()->getScalarSizeInBits());
194+
Result.C = Result.C.zext(X->getType()->getScalarSizeInBits());
195+
}
196+
return Result;
197+
}
179198

180199
return std::nullopt;
181200
}

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4612,12 +4612,11 @@ static Value *simplifyCmpSelOfMaxMin(Value *CmpLHS, Value *CmpRHS,
46124612
return nullptr;
46134613
}
46144614

4615-
/// An alternative way to test if a bit is set or not uses sgt/slt instead of
4616-
/// eq/ne.
4617-
static Value *simplifySelectWithFakeICmpEq(Value *CmpLHS, Value *CmpRHS,
4618-
CmpPredicate Pred, Value *TrueVal,
4619-
Value *FalseVal) {
4620-
if (auto Res = decomposeBitTestICmp(CmpLHS, CmpRHS, Pred))
4615+
/// An alternative way to test if a bit is set or not.
4616+
/// uses e.g. sgt/slt or trunc instead of eq/ne.
4617+
static Value *simplifySelectWithBitTest(Value *CondVal, Value *TrueVal,
4618+
Value *FalseVal) {
4619+
if (auto Res = decomposeBitTest(CondVal))
46214620
return simplifySelectBitTest(TrueVal, FalseVal, Res->X, &Res->Mask,
46224621
Res->Pred == ICmpInst::ICMP_EQ);
46234622

@@ -4728,11 +4727,6 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
47284727
return FalseVal;
47294728
}
47304729

4731-
// Check for other compares that behave like bit test.
4732-
if (Value *V =
4733-
simplifySelectWithFakeICmpEq(CmpLHS, CmpRHS, Pred, TrueVal, FalseVal))
4734-
return V;
4735-
47364730
// If we have a scalar equality comparison, then we know the value in one of
47374731
// the arms of the select. See if substituting this value into the arm and
47384732
// simplifying the result yields the same value as the other arm.
@@ -4984,6 +4978,9 @@ static Value *simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
49844978
simplifySelectWithICmpCond(Cond, TrueVal, FalseVal, Q, MaxRecurse))
49854979
return V;
49864980

4981+
if (Value *V = simplifySelectWithBitTest(Cond, TrueVal, FalseVal))
4982+
return V;
4983+
49874984
if (Value *V = simplifySelectWithFCmp(Cond, TrueVal, FalseVal, Q, MaxRecurse))
49884985
return V;
49894986

llvm/test/Transforms/InstSimplify/select.ll

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1752,10 +1752,7 @@ define <4 x i32> @select_vector_cmp_with_bitcasts(<2 x i64> %x, <4 x i32> %y) {
17521752

17531753
define i8 @bittest_trunc_or(i8 %x) {
17541754
; CHECK-LABEL: @bittest_trunc_or(
1755-
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[X1:%.*]] to i1
1756-
; CHECK-NEXT: [[OR:%.*]] = or i8 [[X1]], 1
1757-
; CHECK-NEXT: [[X:%.*]] = select i1 [[TRUNC]], i8 [[OR]], i8 [[X1]]
1758-
; CHECK-NEXT: ret i8 [[X]]
1755+
; CHECK-NEXT: ret i8 [[X:%.*]]
17591756
;
17601757
%trunc = trunc i8 %x to i1
17611758
%or = or i8 %x, 1
@@ -1765,11 +1762,8 @@ define i8 @bittest_trunc_or(i8 %x) {
17651762

17661763
define i8 @bittest_trunc_not_or(i8 %x) {
17671764
; CHECK-LABEL: @bittest_trunc_not_or(
1768-
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[X:%.*]] to i1
1769-
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[TRUNC]], true
1770-
; CHECK-NEXT: [[OR:%.*]] = or i8 [[X]], 1
1771-
; CHECK-NEXT: [[COND:%.*]] = select i1 [[NOT]], i8 [[OR]], i8 [[X]]
1772-
; CHECK-NEXT: ret i8 [[COND]]
1765+
; CHECK-NEXT: [[OR:%.*]] = or i8 [[X:%.*]], 1
1766+
; CHECK-NEXT: ret i8 [[OR]]
17731767
;
17741768
%trunc = trunc i8 %x to i1
17751769
%not = xor i1 %trunc, true

0 commit comments

Comments
 (0)