Skip to content

Commit 9fc28b7

Browse files
committed
[ValueTracking] Compute known FPClass from dominating condition
1 parent f475b6d commit 9fc28b7

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
@@ -69,6 +69,11 @@ static void findAffectedValues(Value *Cond,
6969
}
7070
}
7171
}
72+
// Handle patterns that computeKnownFPClass() support.
73+
if (match(Cond, m_FCmp(Pred, m_Value(A), m_Constant())))
74+
AddAffected(A);
75+
if (match(Cond, m_Intrinsic<Intrinsic::is_fpclass>(m_Value(A), m_Constant())))
76+
AddAffected(A);
7277
}
7378

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

llvm/lib/Analysis/ValueTracking.cpp

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

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

42324279
// Try to restrict the floating-point classes based on information from
42334280
// assumptions.
@@ -4245,25 +4292,11 @@ static FPClassTest computeKnownFPClassFromAssumes(const Value *V,
42454292
if (!isValidAssumeForContext(I, Q.CxtI, Q.DT))
42464293
continue;
42474294

4248-
CmpInst::Predicate Pred;
4249-
Value *LHS, *RHS;
4250-
uint64_t ClassVal = 0;
4251-
if (match(I->getArgOperand(0), m_FCmp(Pred, m_Value(LHS), m_Value(RHS)))) {
4252-
const APFloat *CRHS;
4253-
if (match(RHS, m_APFloat(CRHS))) {
4254-
auto [CmpVal, MaskIfTrue, MaskIfFalse] =
4255-
fcmpImpliesClass(Pred, *F, LHS, *CRHS, LHS != V);
4256-
if (CmpVal == V)
4257-
KnownFromAssume &= MaskIfTrue;
4258-
}
4259-
} else if (match(I->getArgOperand(0),
4260-
m_Intrinsic<Intrinsic::is_fpclass>(
4261-
m_Value(LHS), m_ConstantInt(ClassVal)))) {
4262-
KnownFromAssume &= static_cast<FPClassTest>(ClassVal);
4263-
}
4295+
computeKnownFPClassFromCond(V, I->getArgOperand(0), /*CondIsTrue=*/true,
4296+
Q.CxtI, KnownFromContext);
42644297
}
42654298

4266-
return KnownFromAssume;
4299+
return KnownFromContext;
42674300
}
42684301

42694302
void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
@@ -4371,17 +4404,21 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
43714404
KnownNotFromFlags |= fcInf;
43724405
}
43734406

4374-
if (Q.AC) {
4375-
FPClassTest AssumedClasses = computeKnownFPClassFromAssumes(V, Q);
4376-
KnownNotFromFlags |= ~AssumedClasses;
4377-
}
4407+
KnownFPClass AssumedClasses = computeKnownFPClassFromContext(V, Q);
4408+
KnownNotFromFlags |= ~AssumedClasses.KnownFPClasses;
43784409

43794410
// We no longer need to find out about these bits from inputs if we can
43804411
// assume this from flags/attributes.
43814412
InterestedClasses &= ~KnownNotFromFlags;
43824413

43834414
auto ClearClassesFromFlags = make_scope_exit([=, &Known] {
43844415
Known.knownNot(KnownNotFromFlags);
4416+
if (!Known.SignBit && AssumedClasses.SignBit) {
4417+
if (*AssumedClasses.SignBit)
4418+
Known.signBitMustBeOne();
4419+
else
4420+
Known.signBitMustBeZero();
4421+
}
43854422
});
43864423

43874424
if (!Op)
@@ -5283,7 +5320,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
52835320

52845321
bool First = true;
52855322

5286-
for (Value *IncValue : P->incoming_values()) {
5323+
for (const Use &U : P->operands()) {
5324+
Value *IncValue = U.get();
52875325
// Skip direct self references.
52885326
if (IncValue == P)
52895327
continue;
@@ -5292,8 +5330,10 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
52925330
// Recurse, but cap the recursion to two levels, because we don't want
52935331
// to waste time spinning around in loops. We need at least depth 2 to
52945332
// detect known sign bits.
5295-
computeKnownFPClass(IncValue, DemandedElts, InterestedClasses, KnownSrc,
5296-
PhiRecursionLimit, Q);
5333+
computeKnownFPClass(
5334+
IncValue, DemandedElts, InterestedClasses, KnownSrc,
5335+
PhiRecursionLimit,
5336+
Q.getWithInstruction(P->getIncomingBlock(U)->getTerminator()));
52975337

52985338
if (First) {
52995339
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)