Skip to content

Commit b80a7db

Browse files
committed
[ValueTracking] Compute known FPClass from dominating condition
1 parent 044604c commit b80a7db

File tree

3 files changed

+80
-40
lines changed

3 files changed

+80
-40
lines changed

llvm/lib/Analysis/DomConditionCache.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ static void findAffectedValues(Value *Cond,
5353
AddAffected(X);
5454
}
5555
}
56+
// Handle patterns that computeKnownFPClass() support.
57+
if (match(Cond, m_FCmp(Pred, m_Value(A), m_Constant())))
58+
AddAffected(A);
59+
if (match(Cond, m_Intrinsic<Intrinsic::is_fpclass>(m_Value(A), m_Constant())))
60+
AddAffected(A);
5661
}
5762

5863
void DomConditionCache::registerBranch(BranchInst *BI) {

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 67 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4213,9 +4213,56 @@ llvm::fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
42134213
return fcmpImpliesClass(Pred, F, LHS, *ConstRHS, LookThroughSrc);
42144214
}
42154215

4216-
static FPClassTest computeKnownFPClassFromAssumes(const Value *V,
4217-
const SimplifyQuery &Q) {
4218-
FPClassTest KnownFromAssume = fcAllFlags;
4216+
static void computeKnownFPClassFromCond(const Value *V, Value *Cond,
4217+
bool CondIsTrue,
4218+
const Instruction *CxtI,
4219+
KnownFPClass &KnownFromContext) {
4220+
CmpInst::Predicate Pred;
4221+
Value *LHS;
4222+
Value *RHS;
4223+
uint64_t ClassVal = 0;
4224+
// TODO: handle sign-bit check idiom
4225+
if (match(Cond, m_FCmp(Pred, m_Value(LHS), m_Value(RHS)))) {
4226+
const APFloat *CRHS;
4227+
if (match(RHS, m_APFloat(CRHS))) {
4228+
auto [CmpVal, MaskIfTrue, MaskIfFalse] = fcmpImpliesClass(
4229+
Pred, *CxtI->getParent()->getParent(), LHS, *CRHS, LHS != V);
4230+
if (CmpVal == V)
4231+
KnownFromContext.knownNot(~(CondIsTrue ? MaskIfTrue : MaskIfFalse));
4232+
}
4233+
} else if (match(Cond, m_Intrinsic<Intrinsic::is_fpclass>(
4234+
m_Value(LHS), m_ConstantInt(ClassVal)))) {
4235+
FPClassTest Mask = static_cast<FPClassTest>(ClassVal);
4236+
KnownFromContext.knownNot(CondIsTrue ? ~Mask : Mask);
4237+
}
4238+
}
4239+
4240+
static KnownFPClass computeKnownFPClassFromContext(const Value *V,
4241+
const SimplifyQuery &Q) {
4242+
KnownFPClass KnownFromContext;
4243+
4244+
if (!Q.CxtI)
4245+
return KnownFromContext;
4246+
4247+
if (Q.DC && Q.DT) {
4248+
// Handle dominating conditions.
4249+
for (BranchInst *BI : Q.DC->conditionsFor(V)) {
4250+
Value *Cond = BI->getCondition();
4251+
4252+
BasicBlockEdge Edge0(BI->getParent(), BI->getSuccessor(0));
4253+
if (Q.DT->dominates(Edge0, Q.CxtI->getParent()))
4254+
computeKnownFPClassFromCond(V, Cond, /*CondIsTrue=*/true, Q.CxtI,
4255+
KnownFromContext);
4256+
4257+
BasicBlockEdge Edge1(BI->getParent(), BI->getSuccessor(1));
4258+
if (Q.DT->dominates(Edge1, Q.CxtI->getParent()))
4259+
computeKnownFPClassFromCond(V, Cond, /*CondIsTrue=*/false, Q.CxtI,
4260+
KnownFromContext);
4261+
}
4262+
}
4263+
4264+
if (!Q.AC)
4265+
return KnownFromContext;
42194266

42204267
// Try to restrict the floating-point classes based on information from
42214268
// assumptions.
@@ -4233,25 +4280,11 @@ static FPClassTest computeKnownFPClassFromAssumes(const Value *V,
42334280
if (!isValidAssumeForContext(I, Q.CxtI, Q.DT))
42344281
continue;
42354282

4236-
CmpInst::Predicate Pred;
4237-
Value *LHS, *RHS;
4238-
uint64_t ClassVal = 0;
4239-
if (match(I->getArgOperand(0), m_FCmp(Pred, m_Value(LHS), m_Value(RHS)))) {
4240-
const APFloat *CRHS;
4241-
if (match(RHS, m_APFloat(CRHS))) {
4242-
auto [CmpVal, MaskIfTrue, MaskIfFalse] =
4243-
fcmpImpliesClass(Pred, *F, LHS, *CRHS, LHS != V);
4244-
if (CmpVal == V)
4245-
KnownFromAssume &= MaskIfTrue;
4246-
}
4247-
} else if (match(I->getArgOperand(0),
4248-
m_Intrinsic<Intrinsic::is_fpclass>(
4249-
m_Value(LHS), m_ConstantInt(ClassVal)))) {
4250-
KnownFromAssume &= static_cast<FPClassTest>(ClassVal);
4251-
}
4283+
computeKnownFPClassFromCond(V, I->getArgOperand(0), /*CondIsTrue=*/true,
4284+
Q.CxtI, KnownFromContext);
42524285
}
42534286

4254-
return KnownFromAssume;
4287+
return KnownFromContext;
42554288
}
42564289

42574290
void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
@@ -4359,17 +4392,21 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
43594392
KnownNotFromFlags |= fcInf;
43604393
}
43614394

4362-
if (Q.AC) {
4363-
FPClassTest AssumedClasses = computeKnownFPClassFromAssumes(V, Q);
4364-
KnownNotFromFlags |= ~AssumedClasses;
4365-
}
4395+
KnownFPClass AssumedClasses = computeKnownFPClassFromContext(V, Q);
4396+
KnownNotFromFlags |= ~AssumedClasses.KnownFPClasses;
43664397

43674398
// We no longer need to find out about these bits from inputs if we can
43684399
// assume this from flags/attributes.
43694400
InterestedClasses &= ~KnownNotFromFlags;
43704401

43714402
auto ClearClassesFromFlags = make_scope_exit([=, &Known] {
43724403
Known.knownNot(KnownNotFromFlags);
4404+
if (!Known.SignBit && AssumedClasses.SignBit) {
4405+
if (*AssumedClasses.SignBit)
4406+
Known.signBitMustBeOne();
4407+
else
4408+
Known.signBitMustBeZero();
4409+
}
43734410
});
43744411

43754412
if (!Op)
@@ -5271,7 +5308,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
52715308

52725309
bool First = true;
52735310

5274-
for (Value *IncValue : P->incoming_values()) {
5311+
for (const Use &U : P->operands()) {
5312+
Value *IncValue = U.get();
52755313
// Skip direct self references.
52765314
if (IncValue == P)
52775315
continue;
@@ -5280,8 +5318,10 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
52805318
// Recurse, but cap the recursion to two levels, because we don't want
52815319
// to waste time spinning around in loops. We need at least depth 2 to
52825320
// detect known sign bits.
5283-
computeKnownFPClass(IncValue, DemandedElts, InterestedClasses, KnownSrc,
5284-
PhiRecursionLimit, Q);
5321+
computeKnownFPClass(
5322+
IncValue, DemandedElts, InterestedClasses, KnownSrc,
5323+
PhiRecursionLimit,
5324+
Q.getWithInstruction(P->getIncomingBlock(U)->getTerminator()));
52855325

52865326
if (First) {
52875327
Known = KnownSrc;

llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ define i1 @test1(float %x) {
1010
; CHECK: if.then:
1111
; CHECK-NEXT: ret i1 false
1212
; CHECK: if.else:
13-
; CHECK-NEXT: [[RET:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X]], i32 783)
13+
; CHECK-NEXT: [[RET:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X]], i32 780)
1414
; CHECK-NEXT: ret i1 [[RET]]
1515
;
1616
entry:
@@ -34,8 +34,7 @@ define i1 @test2(double %x) {
3434
; CHECK: if.then:
3535
; CHECK-NEXT: ret i1 false
3636
; CHECK: if.end:
37-
; CHECK-NEXT: [[CMP_I:%.*]] = fcmp oeq double [[X]], 0.000000e+00
38-
; CHECK-NEXT: ret i1 [[CMP_I]]
37+
; CHECK-NEXT: ret i1 false
3938
;
4039
entry:
4140
%cmp = fcmp olt double %x, 0x3EB0C6F7A0000000
@@ -54,8 +53,7 @@ define i1 @test3(float %x) {
5453
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X]], 3.000000e+00
5554
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
5655
; CHECK: if.then:
57-
; CHECK-NEXT: [[ABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
58-
; CHECK-NEXT: [[RET:%.*]] = fcmp oeq float [[ABS]], 0x7FF0000000000000
56+
; CHECK-NEXT: [[RET:%.*]] = fcmp oeq float [[X]], 0x7FF0000000000000
5957
; CHECK-NEXT: ret i1 [[RET]]
6058
; CHECK: if.else:
6159
; CHECK-NEXT: ret i1 false
@@ -80,10 +78,8 @@ define float @test4(float %x) {
8078
; CHECK: if.then:
8179
; CHECK-NEXT: ret float 1.000000e+00
8280
; CHECK: if.end:
83-
; CHECK-NEXT: [[CMP_I:%.*]] = fcmp oeq float [[X]], 0.000000e+00
8481
; CHECK-NEXT: [[DIV:%.*]] = fdiv float 1.000000e+00, [[X]]
85-
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP_I]], float 1.000000e+00, float [[DIV]]
86-
; CHECK-NEXT: ret float [[RET]]
82+
; CHECK-NEXT: ret float [[DIV]]
8783
;
8884
entry:
8985
%cmp = fcmp olt float %x, 0x3EB0C6F7A0000000
@@ -113,7 +109,7 @@ define i1 @test5(double %x, i1 %cond) {
113109
; CHECK-NEXT: br label [[EXIT]]
114110
; CHECK: exit:
115111
; CHECK-NEXT: [[Y:%.*]] = phi double [ -1.000000e+00, [[ENTRY:%.*]] ], [ [[X]], [[IF_END]] ]
116-
; CHECK-NEXT: [[RET:%.*]] = tail call i1 @llvm.is.fpclass.f64(double [[Y]], i32 411)
112+
; CHECK-NEXT: [[RET:%.*]] = tail call i1 @llvm.is.fpclass.f64(double [[Y]], i32 408)
117113
; CHECK-NEXT: ret i1 [[RET]]
118114
;
119115
entry:
@@ -138,8 +134,7 @@ define i1 @test6(double %x) {
138134
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[X]], 0.000000e+00
139135
; CHECK-NEXT: br i1 [[CMP]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]]
140136
; CHECK: land.rhs:
141-
; CHECK-NEXT: [[ABS:%.*]] = tail call double @llvm.fabs.f64(double [[X]])
142-
; CHECK-NEXT: [[AND_I:%.*]] = bitcast double [[ABS]] to i64
137+
; CHECK-NEXT: [[AND_I:%.*]] = bitcast double [[X]] to i64
143138
; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq i64 [[AND_I]], 9218868437227405312
144139
; CHECK-NEXT: br label [[LAND_END]]
145140
; CHECK: land.end:
@@ -167,10 +162,10 @@ define i1 @test7(float %x) {
167162
; CHECK-NEXT: [[COND:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X]], i32 345)
168163
; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
169164
; CHECK: if.then:
170-
; CHECK-NEXT: [[RET1:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X]], i32 456)
165+
; CHECK-NEXT: [[RET1:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X]], i32 328)
171166
; CHECK-NEXT: ret i1 [[RET1]]
172167
; CHECK: if.else:
173-
; CHECK-NEXT: [[RET2:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X]], i32 456)
168+
; CHECK-NEXT: [[RET2:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X]], i32 128)
174169
; CHECK-NEXT: ret i1 [[RET2]]
175170
;
176171
%cond = call i1 @llvm.is.fpclass.f32(float %x, i32 345)

0 commit comments

Comments
 (0)