Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ValueTracking: Handle compare gt to -inf in class identification #72086

Merged
merged 1 commit into from
Nov 14, 2023

Conversation

arsenm
Copy link
Contributor

@arsenm arsenm commented Nov 13, 2023

This apparently shows up somewhere in chromium. We also are missing a canonicalization to an equality compare with inf.

…fication

This apparently shows up somewhere in chromium. We also are missing a
canonicalization to an equality compare with inf.
@llvmbot
Copy link
Collaborator

llvmbot commented Nov 13, 2023

@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-llvm-analysis

Author: Matt Arsenault (arsenm)

Changes

…fication

This apparently shows up somewhere in chromium. We also are missing a canonicalization to an equality compare with inf.


Full diff: https://github.com/llvm/llvm-project/pull/72086.diff

3 Files Affected:

  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+16-4)
  • (modified) llvm/test/Transforms/InstSimplify/assume-fcmp-constant-implies-class.ll (+3-6)
  • (modified) llvm/unittests/Analysis/ValueTrackingTest.cpp (+69-4)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 923ff043fe71057..dc3c90ba9db1664 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -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
@@ -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;
diff --git a/llvm/test/Transforms/InstSimplify/assume-fcmp-constant-implies-class.ll b/llvm/test/Transforms/InstSimplify/assume-fcmp-constant-implies-class.ll
index ec4e3c3092414aa..7970f3ce6bf09d8 100644
--- a/llvm/test/Transforms/InstSimplify/assume-fcmp-constant-implies-class.ll
+++ b/llvm/test/Transforms/InstSimplify/assume-fcmp-constant-implies-class.ll
@@ -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)
@@ -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)
@@ -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
diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp
index 5bd1bb37e678e96..1190550340efbb6 100644
--- a/llvm/unittests/Analysis/ValueTrackingTest.cpp
+++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp
@@ -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");
 
@@ -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) {

Copy link
Contributor

@andykaylor andykaylor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@arsenm arsenm changed the title ValueTracking: Handle compare gt to negative infinity in class identi… ValueTracking: Handle compare gt to -inf in class identi… Nov 14, 2023
@arsenm arsenm changed the title ValueTracking: Handle compare gt to -inf in class identi… ValueTracking: Handle compare gt to -inf in class identification Nov 14, 2023
@arsenm arsenm merged commit 0e1a52f into llvm:main Nov 14, 2023
6 checks passed
@arsenm arsenm deleted the class-compare-with-neg-infinity branch November 14, 2023 01:05
zahiraam pushed a commit to zahiraam/llvm-project that referenced this pull request Nov 20, 2023
…m#72086)

This apparently shows up somewhere in chromium. We also are missing a
canonicalization to an equality compare with inf.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants