Skip to content

Commit 58ead2c

Browse files
authored
[ValueTracking] Support trunc nuw condition in isImpliedCondition (#141528)
Proof: https://alive2.llvm.org/ce/z/oqQyxC
1 parent 5ab017a commit 58ead2c

File tree

2 files changed

+105
-10
lines changed

2 files changed

+105
-10
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9165,15 +9165,13 @@ isImpliedCondCommonOperandWithCR(CmpPredicate LPred, const ConstantRange &LCR,
91659165
/// is true. Return false if LHS implies RHS is false. Otherwise, return
91669166
/// std::nullopt if we can't infer anything.
91679167
static std::optional<bool>
9168-
isImpliedCondICmps(const ICmpInst *LHS, CmpPredicate RPred, const Value *R0,
9169-
const Value *R1, const DataLayout &DL, bool LHSIsTrue) {
9170-
Value *L0 = LHS->getOperand(0);
9171-
Value *L1 = LHS->getOperand(1);
9172-
9168+
isImpliedCondICmps(CmpPredicate LPred, const Value *L0, const Value *L1,
9169+
CmpPredicate RPred, const Value *R0, const Value *R1,
9170+
const DataLayout &DL, bool LHSIsTrue) {
91739171
// The rest of the logic assumes the LHS condition is true. If that's not the
91749172
// case, invert the predicate to make it so.
9175-
CmpPredicate LPred =
9176-
LHSIsTrue ? LHS->getCmpPredicate() : LHS->getInverseCmpPredicate();
9173+
if (!LHSIsTrue)
9174+
LPred = ICmpInst::getInverseCmpPredicate(LPred);
91779175

91789176
// We can have non-canonical operands, so try to normalize any common operand
91799177
// to L0/R0.
@@ -9314,9 +9312,15 @@ llvm::isImpliedCondition(const Value *LHS, CmpPredicate RHSPred,
93149312
LHSIsTrue = !LHSIsTrue;
93159313

93169314
// Both LHS and RHS are icmps.
9317-
const ICmpInst *LHSCmp = dyn_cast<ICmpInst>(LHS);
9318-
if (LHSCmp)
9319-
return isImpliedCondICmps(LHSCmp, RHSPred, RHSOp0, RHSOp1, DL, LHSIsTrue);
9315+
if (const auto *LHSCmp = dyn_cast<ICmpInst>(LHS))
9316+
return isImpliedCondICmps(LHSCmp->getCmpPredicate(), LHSCmp->getOperand(0),
9317+
LHSCmp->getOperand(1), RHSPred, RHSOp0, RHSOp1,
9318+
DL, LHSIsTrue);
9319+
const Value *V;
9320+
if (match(LHS, m_NUWTrunc(m_Value(V))))
9321+
return isImpliedCondICmps(CmpInst::ICMP_NE, V,
9322+
ConstantInt::get(V->getType(), 0), RHSPred,
9323+
RHSOp0, RHSOp1, DL, LHSIsTrue);
93209324

93219325
/// The LHS should be an 'or', 'and', or a 'select' instruction. We expect
93229326
/// the RHS to be an icmp.
@@ -9354,6 +9358,15 @@ std::optional<bool> llvm::isImpliedCondition(const Value *LHS, const Value *RHS,
93549358
return std::nullopt;
93559359
}
93569360

9361+
const Value *V;
9362+
if (match(RHS, m_NUWTrunc(m_Value(V)))) {
9363+
if (auto Implied = isImpliedCondition(LHS, CmpInst::ICMP_NE, V,
9364+
ConstantInt::get(V->getType(), 0), DL,
9365+
LHSIsTrue, Depth))
9366+
return InvertRHS ? !*Implied : *Implied;
9367+
return std::nullopt;
9368+
}
9369+
93579370
if (Depth == MaxAnalysisRecursionDepth)
93589371
return std::nullopt;
93599372

llvm/test/Transforms/InstCombine/select-safe-impliedcond-transforms.ll

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,85 @@ define i1 @a_false_implies_b_false2_comm(i8 %z, i1 %X, i1 %Y) {
176176
%res = or i1 %sel, %a
177177
ret i1 %res
178178
}
179+
180+
define i1 @trunc_nuw_implies_icmp_eq(i8 %x, i1 %c) {
181+
; CHECK-LABEL: @trunc_nuw_implies_icmp_eq(
182+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X:%.*]] to i1
183+
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[TRUNC]], i1 true, i1 [[C:%.*]]
184+
; CHECK-NEXT: ret i1 [[SEL2]]
185+
;
186+
%trunc = trunc nuw i8 %x to i1
187+
%cmp = icmp eq i8 %x, 0
188+
%sel1 = select i1 %cmp, i1 %c, i1 false
189+
%sel2 = select i1 %trunc, i1 true, i1 %sel1
190+
ret i1 %sel2
191+
}
192+
193+
define i1 @icmp_eq_implies_trunc_nuw(i8 %x, i1 %c) {
194+
; CHECK-LABEL: @icmp_eq_implies_trunc_nuw(
195+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 0
196+
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[CMP]], i1 true, i1 [[C:%.*]]
197+
; CHECK-NEXT: ret i1 [[SEL2]]
198+
;
199+
%trunc = trunc nuw i8 %x to i1
200+
%cmp = icmp eq i8 %x, 0
201+
%sel1 = select i1 %trunc, i1 %c, i1 false
202+
%sel2 = select i1 %cmp, i1 true, i1 %sel1
203+
ret i1 %sel2
204+
}
205+
206+
define <2 x i1> @trunc_nuw_implies_icmp_eq_vec(<2 x i8> %x, <2 x i1> %c) {
207+
; CHECK-LABEL: @trunc_nuw_implies_icmp_eq_vec(
208+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw <2 x i8> [[X:%.*]] to <2 x i1>
209+
; CHECK-NEXT: [[SEL2:%.*]] = select <2 x i1> [[TRUNC]], <2 x i1> splat (i1 true), <2 x i1> [[C:%.*]]
210+
; CHECK-NEXT: ret <2 x i1> [[SEL2]]
211+
;
212+
%trunc = trunc nuw <2 x i8> %x to <2 x i1>
213+
%cmp = icmp eq <2 x i8> %x, splat (i8 0)
214+
%sel1 = select <2 x i1> %cmp, <2 x i1> %c, <2 x i1> splat (i1 false)
215+
%sel2 = select <2 x i1> %trunc, <2 x i1> splat (i1 true), <2 x i1> %sel1
216+
ret <2 x i1> %sel2
217+
}
218+
219+
define <2 x i1> @icmp_eq_implies_trunc_nuw_vec(<2 x i8> %x, <2 x i1> %c) {
220+
; CHECK-LABEL: @icmp_eq_implies_trunc_nuw_vec(
221+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer
222+
; CHECK-NEXT: [[SEL2:%.*]] = select <2 x i1> [[CMP]], <2 x i1> splat (i1 true), <2 x i1> [[C:%.*]]
223+
; CHECK-NEXT: ret <2 x i1> [[SEL2]]
224+
;
225+
%trunc = trunc nuw <2 x i8> %x to <2 x i1>
226+
%cmp = icmp eq <2 x i8> %x, splat (i8 0)
227+
%sel1 = select <2 x i1> %trunc, <2 x i1> %c, <2 x i1> splat (i1 false)
228+
%sel2 = select <2 x i1> %cmp, <2 x i1> splat (i1 true), <2 x i1> %sel1
229+
ret <2 x i1> %sel2
230+
}
231+
232+
define i1 @neg_trunc_implies_icmp_eq(i8 %x, i1 %c) {
233+
; CHECK-LABEL: @neg_trunc_implies_icmp_eq(
234+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[X:%.*]] to i1
235+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 0
236+
; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CMP]], i1 [[C:%.*]], i1 false
237+
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[TRUNC]], i1 true, i1 [[SEL1]]
238+
; CHECK-NEXT: ret i1 [[SEL2]]
239+
;
240+
%trunc = trunc i8 %x to i1
241+
%cmp = icmp eq i8 %x, 0
242+
%sel1 = select i1 %cmp, i1 %c, i1 false
243+
%sel2 = select i1 %trunc, i1 true, i1 %sel1
244+
ret i1 %sel2
245+
}
246+
247+
define i1 @neg_icmp_eq_implies_trunc(i8 %x, i1 %c) {
248+
; CHECK-LABEL: @neg_icmp_eq_implies_trunc(
249+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[X:%.*]] to i1
250+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 0
251+
; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[TRUNC]], i1 [[C:%.*]], i1 false
252+
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[CMP]], i1 true, i1 [[SEL1]]
253+
; CHECK-NEXT: ret i1 [[SEL2]]
254+
;
255+
%trunc = trunc i8 %x to i1
256+
%cmp = icmp eq i8 %x, 0
257+
%sel1 = select i1 %trunc, i1 %c, i1 false
258+
%sel2 = select i1 %cmp, i1 true, i1 %sel1
259+
ret i1 %sel2
260+
}

0 commit comments

Comments
 (0)