Skip to content

Commit 7ef6f5b

Browse files
dtcxzywllvmbot
authored andcommitted
[IR] Handle fabs LHS in fcmpImpliesClass (#152913)
Closes #152824. (cherry picked from commit d8b1b46)
1 parent 0fb2434 commit 7ef6f5b

File tree

3 files changed

+69
-12
lines changed

3 files changed

+69
-12
lines changed

llvm/include/llvm/IR/GenericFloatingPointPredicateUtils.h

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ template <typename ContextT> class GenericFloatingPointPredicateUtils {
135135
if (Mode.Input != DenormalMode::IEEE)
136136
return {Invalid, fcAllFlags, fcAllFlags};
137137

138+
auto ExactClass = [IsFabs, Src](FPClassTest Mask) {
139+
if (IsFabs)
140+
Mask = llvm::inverse_fabs(Mask);
141+
return exactClass(Src, Mask);
142+
};
143+
138144
switch (Pred) {
139145
case FCmpInst::FCMP_OEQ: // Match x == 0.0
140146
return exactClass(Src, fcZero);
@@ -151,26 +157,24 @@ template <typename ContextT> class GenericFloatingPointPredicateUtils {
151157
case FCmpInst::FCMP_UNO:
152158
return exactClass(Src, fcNan);
153159
case FCmpInst::FCMP_OGT: // x > 0
154-
return exactClass(Src, fcPosSubnormal | fcPosNormal | fcPosInf);
160+
return ExactClass(fcPosSubnormal | fcPosNormal | fcPosInf);
155161
case FCmpInst::FCMP_UGT: // isnan(x) || x > 0
156-
return exactClass(Src, fcPosSubnormal | fcPosNormal | fcPosInf | fcNan);
162+
return ExactClass(fcPosSubnormal | fcPosNormal | fcPosInf | fcNan);
157163
case FCmpInst::FCMP_OGE: // x >= 0
158-
return exactClass(Src, fcPositive | fcNegZero);
164+
return ExactClass(fcPositive | fcNegZero);
159165
case FCmpInst::FCMP_UGE: // isnan(x) || x >= 0
160-
return exactClass(Src, fcPositive | fcNegZero | fcNan);
166+
return ExactClass(fcPositive | fcNegZero | fcNan);
161167
case FCmpInst::FCMP_OLT: // x < 0
162-
return exactClass(Src, fcNegSubnormal | fcNegNormal | fcNegInf);
168+
return ExactClass(fcNegSubnormal | fcNegNormal | fcNegInf);
163169
case FCmpInst::FCMP_ULT: // isnan(x) || x < 0
164-
return exactClass(Src, fcNegSubnormal | fcNegNormal | fcNegInf | fcNan);
170+
return ExactClass(fcNegSubnormal | fcNegNormal | fcNegInf | fcNan);
165171
case FCmpInst::FCMP_OLE: // x <= 0
166-
return exactClass(Src, fcNegative | fcPosZero);
172+
return ExactClass(fcNegative | fcPosZero);
167173
case FCmpInst::FCMP_ULE: // isnan(x) || x <= 0
168-
return exactClass(Src, fcNegative | fcPosZero | fcNan);
174+
return ExactClass(fcNegative | fcPosZero | fcNan);
169175
default:
170176
llvm_unreachable("all compare types are handled");
171177
}
172-
173-
return {Invalid, fcAllFlags, fcAllFlags};
174178
}
175179

176180
const bool IsDenormalRHS = (OrigClass & fcSubnormal) == OrigClass;

llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,15 +213,15 @@ define double @fmul_nnan_ninf_nneg_n0.0_commute(i127 %x) {
213213

214214
define float @fmul_ninf_nnan_mul_zero_nsz(float nofpclass(inf nan) %f) {
215215
; CHECK-LABEL: @fmul_ninf_nnan_mul_zero_nsz(
216-
; CHECK-NEXT: ret float 0.000000e+00
216+
; CHECK-NEXT: ret float 0.000000e+00
217217
;
218218
%r = fmul nsz float %f, 0.0
219219
ret float %r
220220
}
221221

222222
define float @fmul_ninf_nnan_mul_nzero_nsz(float nofpclass(inf nan) %f) {
223223
; CHECK-LABEL: @fmul_ninf_nnan_mul_nzero_nsz(
224-
; CHECK-NEXT: ret float 0.000000e+00
224+
; CHECK-NEXT: ret float 0.000000e+00
225225
;
226226
%r = fmul nsz float %f, -0.0
227227
ret float %r
@@ -1255,3 +1255,20 @@ define i1 @fptrunc_round_unknown_positive(double %unknown) {
12551255
%cmp = fcmp nnan oge float %op, 0.0
12561256
ret i1 %cmp
12571257
}
1258+
1259+
define half @fabs_select_fabs(half noundef %x) {
1260+
; CHECK-LABEL: @fabs_select_fabs(
1261+
; CHECK-NEXT: entry:
1262+
; CHECK-NEXT: [[ABS1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
1263+
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt half [[ABS1]], 0xH0000
1264+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], half [[X]], half 0xH0000
1265+
; CHECK-NEXT: [[ABS2:%.*]] = call half @llvm.fabs.f16(half [[SEL]])
1266+
; CHECK-NEXT: ret half [[ABS2]]
1267+
;
1268+
entry:
1269+
%abs1 = call half @llvm.fabs.f16(half %x)
1270+
%cmp = fcmp ogt half %abs1, 0xH0000
1271+
%sel = select i1 %cmp, half %x, half 0xH0000
1272+
%abs2 = call half @llvm.fabs.f16(half %sel)
1273+
ret half %abs2
1274+
}

llvm/unittests/Analysis/ValueTrackingTest.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/Analysis/ValueTracking.h"
10+
#include "llvm/ADT/FloatingPointMode.h"
1011
#include "llvm/Analysis/AssumptionCache.h"
1112
#include "llvm/Analysis/FloatingPointPredicateUtils.h"
1213
#include "llvm/AsmParser/Parser.h"
@@ -2208,6 +2209,41 @@ TEST_F(ComputeKnownFPClassTest, Constants) {
22082209
}
22092210
}
22102211

2212+
TEST_F(ComputeKnownFPClassTest, fcmpImpliesClass_fabs_zero) {
2213+
parseAssembly("define float @test(float %x) {\n"
2214+
" %A = call float @llvm.fabs.f32(float %x)\n"
2215+
" ret float %A\n"
2216+
"}\n");
2217+
EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_OEQ, *F, A, fcZero)),
2218+
fcZero);
2219+
EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_UEQ, *F, A, fcZero)),
2220+
fcZero | fcNan);
2221+
EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_UNE, *F, A, fcZero)),
2222+
~fcZero);
2223+
EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_ONE, *F, A, fcZero)),
2224+
~fcNan & ~fcZero);
2225+
EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_ORD, *F, A, fcZero)),
2226+
~fcNan);
2227+
EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_UNO, *F, A, fcZero)),
2228+
fcNan);
2229+
EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_OGT, *F, A, fcZero)),
2230+
fcSubnormal | fcNormal | fcInf);
2231+
EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_UGT, *F, A, fcZero)),
2232+
fcSubnormal | fcNormal | fcInf | fcNan);
2233+
EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_OGE, *F, A, fcZero)),
2234+
~fcNan);
2235+
EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_UGE, *F, A, fcZero)),
2236+
fcAllFlags);
2237+
EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_OLT, *F, A, fcZero)),
2238+
fcNone);
2239+
EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_ULT, *F, A, fcZero)),
2240+
fcNan);
2241+
EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_OLE, *F, A, fcZero)),
2242+
fcZero);
2243+
EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_ULE, *F, A, fcZero)),
2244+
fcZero | fcNan);
2245+
}
2246+
22112247
TEST_F(ValueTrackingTest, isNonZeroRecurrence) {
22122248
parseAssembly(R"(
22132249
define i1 @test(i8 %n, i8 %r) {

0 commit comments

Comments
 (0)