Skip to content

Commit

Permalink
ValueTracking: Handle compare gt to -inf in class identification (llv…
Browse files Browse the repository at this point in the history
…m#72086)

This apparently shows up somewhere in chromium. We also are missing a
canonicalization to an equality compare with inf.
  • Loading branch information
arsenm authored Nov 14, 2023
1 parent 45a92ac commit 0e1a52f
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 14 deletions.
20 changes: 16 additions & 4 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4181,8 +4181,14 @@ llvm::fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
}
case FCmpInst::FCMP_OGE:
case FCmpInst::FCMP_ULT: {
if (ConstRHS->isNegative()) // TODO
return {nullptr, fcAllFlags};
if (ConstRHS->isNegative()) {
// fcmp oge x, -inf -> ~fcNan
// fcmp oge fabs(x), -inf -> ~fcNan
// fcmp ult x, -inf -> fcNan
// fcmp ult fabs(x), -inf -> fcNan
Mask = ~fcNan;
break;
}

// fcmp oge fabs(x), +inf -> fcInf
// fcmp oge x, +inf -> fcPosInf
Expand All @@ -4195,8 +4201,14 @@ llvm::fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
}
case FCmpInst::FCMP_OGT:
case FCmpInst::FCMP_ULE: {
if (ConstRHS->isNegative())
return {nullptr, fcAllFlags};
if (ConstRHS->isNegative()) {
// fcmp ogt x, -inf -> fcmp one x, -inf
// fcmp ogt fabs(x), -inf -> fcmp ord x, x
// fcmp ule x, -inf -> fcmp ueq x, -inf
// fcmp ule fabs(x), -inf -> fcmp uno x, x
Mask = IsFabs ? ~fcNan : ~(fcNegInf | fcNan);
break;
}

// No value is ordered and greater than infinity.
Mask = fcNone;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3047,8 +3047,7 @@ define i1 @assume_ogt_neginf_one_neginf(float %arg) {
; CHECK-SAME: float [[ARG:%.*]]) {
; CHECK-NEXT: [[CMP_OGT_NEGINF:%.*]] = fcmp ogt float [[ARG]], 0xFFF0000000000000
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_OGT_NEGINF]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp one float [[ARG]], 0xFFF0000000000000
; CHECK-NEXT: ret i1 [[CMP]]
; CHECK-NEXT: ret i1 true
;
%cmp.ogt.neginf = fcmp ogt float %arg, 0xFFF0000000000000
call void @llvm.assume(i1 %cmp.ogt.neginf)
Expand Down Expand Up @@ -3089,8 +3088,7 @@ define i1 @assume_ult_neginf_oeq_neginf(float %arg) {
; CHECK-SAME: float [[ARG:%.*]]) {
; CHECK-NEXT: [[CMP_ULT_NEGINF:%.*]] = fcmp ult float [[ARG]], 0xFFF0000000000000
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ULT_NEGINF]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[ARG]], 0xFFF0000000000000
; CHECK-NEXT: ret i1 [[CMP]]
; CHECK-NEXT: ret i1 false
;
%cmp.ult.neginf = fcmp ult float %arg, 0xFFF0000000000000
call void @llvm.assume(i1 %cmp.ult.neginf)
Expand Down Expand Up @@ -3136,8 +3134,7 @@ define i1 @assume_fabs_ule_neginf_oeq_neginf(float %arg) {
; CHECK-NEXT: [[FABS_ARG:%.*]] = call float @llvm.fabs.f32(float [[ARG]])
; CHECK-NEXT: [[CMP_OGT_NEGINF:%.*]] = fcmp ule float [[FABS_ARG]], 0xFFF0000000000000
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_OGT_NEGINF]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[ARG]], 0xFFF0000000000000
; CHECK-NEXT: ret i1 [[CMP]]
; CHECK-NEXT: ret i1 false
;
%fabs.arg = call float @llvm.fabs.f32(float %arg)
%cmp.ogt.neginf = fcmp ule float %fabs.arg, 0xFFF0000000000000
Expand Down
73 changes: 69 additions & 4 deletions llvm/unittests/Analysis/ValueTrackingTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1830,6 +1830,8 @@ TEST_F(ComputeKnownFPClassTest, FCmpToClassTest_NInf) {
" %A2 = fcmp uge double %arg, 0xFFF0000000000000"
" %A3 = fcmp ogt double %arg, 0xFFF0000000000000"
" %A4 = fcmp ule double %arg, 0xFFF0000000000000"
" %A5 = fcmp oge double %arg, 0xFFF0000000000000"
" %A6 = fcmp ult double %arg, 0xFFF0000000000000"
" ret i1 %A\n"
"}\n");

Expand All @@ -1847,14 +1849,77 @@ TEST_F(ComputeKnownFPClassTest, FCmpToClassTest_NInf) {
auto [OgtVal, OgtClass] =
fcmpToClassTest(CmpInst::FCMP_OGT, *A3->getFunction(), A3->getOperand(0),
A3->getOperand(1));
EXPECT_EQ(nullptr, OgtVal);
EXPECT_EQ(fcAllFlags, OgtClass);
EXPECT_EQ(A3->getOperand(0), OgtVal);
EXPECT_EQ(~(fcNegInf | fcNan), OgtClass);

auto [UleVal, UleClass] =
fcmpToClassTest(CmpInst::FCMP_ULE, *A4->getFunction(), A4->getOperand(0),
A4->getOperand(1));
EXPECT_EQ(nullptr, UleVal);
EXPECT_EQ(fcAllFlags, UleClass);
EXPECT_EQ(A4->getOperand(0), UleVal);
EXPECT_EQ(fcNegInf | fcNan, UleClass);

auto [OgeVal, OgeClass] =
fcmpToClassTest(CmpInst::FCMP_OGE, *A5->getFunction(), A5->getOperand(0),
A5->getOperand(1));
EXPECT_EQ(A5->getOperand(0), OgeVal);
EXPECT_EQ(~fcNan, OgeClass);

auto [UltVal, UltClass] =
fcmpToClassTest(CmpInst::FCMP_ULT, *A6->getFunction(), A6->getOperand(0),
A6->getOperand(1));
EXPECT_EQ(A6->getOperand(0), UltVal);
EXPECT_EQ(fcNan, UltClass);
}

TEST_F(ComputeKnownFPClassTest, FCmpToClassTest_FabsNInf) {
parseAssembly("declare double @llvm.fabs.f64(double)\n"
"define i1 @test(double %arg) {\n"
" %fabs.arg = call double @llvm.fabs.f64(double %arg)\n"
" %A = fcmp olt double %fabs.arg, 0xFFF0000000000000"
" %A2 = fcmp uge double %fabs.arg, 0xFFF0000000000000"
" %A3 = fcmp ogt double %fabs.arg, 0xFFF0000000000000"
" %A4 = fcmp ule double %fabs.arg, 0xFFF0000000000000"
" %A5 = fcmp oge double %fabs.arg, 0xFFF0000000000000"
" %A6 = fcmp ult double %fabs.arg, 0xFFF0000000000000"
" ret i1 %A\n"
"}\n");

Value *ArgVal = F->getArg(0);

auto [OltVal, OltClass] = fcmpToClassTest(
CmpInst::FCMP_OLT, *A->getFunction(), A->getOperand(0), A->getOperand(1));
EXPECT_EQ(ArgVal, OltVal);
EXPECT_EQ(fcNone, OltClass);

auto [UgeVal, UgeClass] =
fcmpToClassTest(CmpInst::FCMP_UGE, *A2->getFunction(), A2->getOperand(0),
A2->getOperand(1));
EXPECT_EQ(ArgVal, UgeVal);
EXPECT_EQ(fcAllFlags, UgeClass);

auto [OgtVal, OgtClass] =
fcmpToClassTest(CmpInst::FCMP_OGT, *A3->getFunction(), A3->getOperand(0),
A3->getOperand(1));
EXPECT_EQ(ArgVal, OgtVal);
EXPECT_EQ(~fcNan, OgtClass);

auto [UleVal, UleClass] =
fcmpToClassTest(CmpInst::FCMP_ULE, *A4->getFunction(), A4->getOperand(0),
A4->getOperand(1));
EXPECT_EQ(ArgVal, UleVal);
EXPECT_EQ(fcNan, UleClass);

auto [OgeVal, OgeClass] =
fcmpToClassTest(CmpInst::FCMP_OGE, *A5->getFunction(), A5->getOperand(0),
A5->getOperand(1));
EXPECT_EQ(ArgVal, OgeVal);
EXPECT_EQ(~fcNan, OgeClass);

auto [UltVal, UltClass] =
fcmpToClassTest(CmpInst::FCMP_ULT, *A6->getFunction(), A6->getOperand(0),
A6->getOperand(1));
EXPECT_EQ(ArgVal, UltVal);
EXPECT_EQ(fcNan, UltClass);
}

TEST_F(ComputeKnownFPClassTest, FCmpToClassTest_PInf) {
Expand Down

0 comments on commit 0e1a52f

Please sign in to comment.