[llvm] r345734 - [InstCombine] refactor fabs+fcmp fold; NFC

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 31 09:34:44 PDT 2018


Author: spatel
Date: Wed Oct 31 09:34:43 2018
New Revision: 345734

URL: http://llvm.org/viewvc/llvm-project?rev=345734&view=rev
Log:
[InstCombine] refactor fabs+fcmp fold; NFC

Also, remove/replace/minimize/enhance the tests for this fold.
The code drops FMF, so it needs more tests and at least 1 fix.


Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/trunk/test/Transforms/InstCombine/fcmp.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=345734&r1=345733&r2=345734&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Wed Oct 31 09:34:43 2018
@@ -5288,6 +5288,46 @@ static Instruction *foldFCmpReciprocalAn
   return NewFCI;
 }
 
+/// Optimize fabs(X) compared with zero.
+static Instruction *foldFabsWithFcmpZero(FCmpInst &I) {
+  Value *X;
+  if (!match(I.getOperand(0), m_Intrinsic<Intrinsic::fabs>(m_Value(X))) ||
+      !match(I.getOperand(1), m_PosZeroFP()))
+    return nullptr;
+
+  switch (I.getPredicate()) {
+  case FCmpInst::FCMP_UGE:
+  case FCmpInst::FCMP_OLT:
+    // fabs(X) >= 0.0 --> true
+    // fabs(X) <  0.0 --> false
+    llvm_unreachable("fcmp should have simplified");
+
+  case FCmpInst::FCMP_OGT:
+    // fabs(X) > 0.0 --> X != 0.0
+    return new FCmpInst(FCmpInst::FCMP_ONE, X, I.getOperand(1));
+
+  case FCmpInst::FCMP_OLE:
+    // fabs(X) <= 0.0 --> X == 0.0
+    return new FCmpInst(FCmpInst::FCMP_OEQ, X, I.getOperand(1));
+
+  case FCmpInst::FCMP_OGE:
+    // fabs(X) >= 0.0 --> !isnan(X)
+    assert(!I.hasNoNaNs() && "fcmp should have simplified");
+    return new FCmpInst(FCmpInst::FCMP_ORD, X, I.getOperand(1));
+
+  case FCmpInst::FCMP_OEQ:
+  case FCmpInst::FCMP_UEQ:
+  case FCmpInst::FCMP_ONE:
+  case FCmpInst::FCMP_UNE:
+    // fabs(X) == 0.0 --> X == 0.0
+    // fabs(X) != 0.0 --> X != 0.0
+    return new FCmpInst(I.getPredicate(), X, I.getOperand(1));
+
+  default:
+    return nullptr;
+  }
+}
+
 Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
   bool Changed = false;
 
@@ -5418,45 +5458,11 @@ Instruction *InstCombiner::visitFCmpInst
             if (Instruction *Res = foldCmpLoadFromIndexedGlobal(GEP, GV, I))
               return Res;
       break;
-    case Instruction::Call: {
-      if (!RHSC->isNullValue())
-        break;
-
-      CallInst *CI = cast<CallInst>(LHSI);
-      Intrinsic::ID IID = getIntrinsicForCallSite(CI, &TLI);
-      if (IID != Intrinsic::fabs)
-        break;
-
-      // Various optimization for fabs compared with zero.
-      switch (Pred) {
-      default:
-        break;
-      case FCmpInst::FCMP_UGE:
-      case FCmpInst::FCMP_OLT:
-        // fabs(x) >= 0.0 --> true
-        // fabs(x) <  0.0 --> false
-        llvm_unreachable("fcmp should have simplified");
-
-      // fabs(x) > 0 --> x != 0
-      case FCmpInst::FCMP_OGT:
-        return new FCmpInst(FCmpInst::FCMP_ONE, CI->getArgOperand(0), RHSC);
-      // fabs(x) <= 0 --> x == 0
-      case FCmpInst::FCMP_OLE:
-        return new FCmpInst(FCmpInst::FCMP_OEQ, CI->getArgOperand(0), RHSC);
-      // fabs(x) >= 0 --> !isnan(x)
-      case FCmpInst::FCMP_OGE:
-        assert(!I.hasNoNaNs() && "fcmp should have simplified");
-        return new FCmpInst(FCmpInst::FCMP_ORD, CI->getArgOperand(0), RHSC);
-      // fabs(x) == 0 --> x == 0
-      // fabs(x) != 0 --> x != 0
-      case FCmpInst::FCMP_OEQ:
-      case FCmpInst::FCMP_UEQ:
-      case FCmpInst::FCMP_ONE:
-      case FCmpInst::FCMP_UNE:
-        return new FCmpInst(Pred, CI->getArgOperand(0), RHSC);
-      }
-    }
-    }
+    case Instruction::Call:
+      if (Instruction *X = foldFabsWithFcmpZero(I))
+        return X;
+      break;
+  }
   }
 
   // fcmp pred (fneg x), (fneg y) -> fcmp swap(pred) x, y

Modified: llvm/trunk/test/Transforms/InstCombine/fcmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/fcmp.ll?rev=345734&r1=345733&r2=345734&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/fcmp.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/fcmp.ll Wed Oct 31 09:34:43 2018
@@ -1,7 +1,9 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt -S -instcombine < %s | FileCheck %s
 
-declare double @llvm.fabs.f64(double) readnone
+declare half @llvm.fabs.f16(half)
+declare double @llvm.fabs.f64(double)
+declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
 
 define i1 @test1(float %x, float %y) {
 ; CHECK-LABEL: @test1(
@@ -133,194 +135,92 @@ define float @test8(float %x) {
 ; Float comparison to zero shouldn't cast to double.
 }
 
-declare double @fabs(double) readnone
-
-define i32 @test9(double %a) {
-; CHECK-LABEL: @test9(
-; CHECK-NEXT:    ret i32 0
-;
-  %call = tail call double @fabs(double %a)
-  %cmp = fcmp olt double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
-}
-
-define i32 @test9_intrinsic(double %a) {
-; CHECK-LABEL: @test9_intrinsic(
-; CHECK-NEXT:    ret i32 0
-;
-  %call = tail call double @llvm.fabs.f64(double %a)
-  %cmp = fcmp olt double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
-}
-
-define i32 @test10(double %a) {
-; CHECK-LABEL: @test10(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    ret i32 [[CONV]]
+define i1 @fabs_uge(double %a) {
+; CHECK-LABEL: @fabs_uge(
+; CHECK-NEXT:    ret i1 true
 ;
-  %call = tail call double @fabs(double %a)
-  %cmp = fcmp ole double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
+  %call = call double @llvm.fabs.f64(double %a)
+  %cmp = fcmp uge double %call, 0.0
+  ret i1 %cmp
 }
 
-define i32 @test10_intrinsic(double %a) {
-; CHECK-LABEL: @test10_intrinsic(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    ret i32 [[CONV]]
+define i1 @fabs_olt(half %a) {
+; CHECK-LABEL: @fabs_olt(
+; CHECK-NEXT:    ret i1 false
 ;
-  %call = tail call double @llvm.fabs.f64(double %a)
-  %cmp = fcmp ole double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
+  %call = call half @llvm.fabs.f16(half %a)
+  %cmp = fcmp olt half %call, 0.0
+  ret i1 %cmp
 }
 
-define i32 @test11(double %a) {
-; CHECK-LABEL: @test11(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    ret i32 [[CONV]]
+define <2 x i1> @fabs_ole(<2 x float> %a) {
+; CHECK-LABEL: @fabs_ole(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq <2 x float> [[A:%.*]], zeroinitializer
+; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
-  %call = tail call double @fabs(double %a)
-  %cmp = fcmp ogt double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
+  %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
+  %cmp = fcmp ole <2 x float> %call, zeroinitializer
+  ret <2 x i1> %cmp
 }
 
-define i32 @test11_intrinsic(double %a) {
-; CHECK-LABEL: @test11_intrinsic(
+define i1 @fabs_ogt(double %a) {
+; CHECK-LABEL: @fabs_ogt(
 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    ret i32 [[CONV]]
-;
-  %call = tail call double @llvm.fabs.f64(double %a)
-  %cmp = fcmp ogt double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
-}
-
-define i32 @test12(double %a) {
-; CHECK-LABEL: @test12(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ord double [[A:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    ret i32 [[CONV]]
+; CHECK-NEXT:    ret i1 [[CMP]]
 ;
-  %call = tail call double @fabs(double %a)
-  %cmp = fcmp oge double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
+  %call = call double @llvm.fabs.f64(double %a)
+  %cmp = fcmp ogt double %call, 0.0
+  ret i1 %cmp
 }
 
-define i32 @test12_intrinsic(double %a) {
-; CHECK-LABEL: @test12_intrinsic(
+define i1 @fabs_oge(double %a) {
+; CHECK-LABEL: @fabs_oge(
 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp ord double [[A:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    ret i32 [[CONV]]
-;
-  %call = tail call double @llvm.fabs.f64(double %a)
-  %cmp = fcmp oge double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
-}
-
-define i32 @test13(double %a) {
-; CHECK-LABEL: @test13(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[A:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    ret i32 [[CONV]]
-;
-  %call = tail call double @fabs(double %a)
-  %cmp = fcmp une double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
-}
-
-define i32 @test13_intrinsic(double %a) {
-; CHECK-LABEL: @test13_intrinsic(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[A:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    ret i32 [[CONV]]
+; CHECK-NEXT:    ret i1 [[CMP]]
 ;
-  %call = tail call double @llvm.fabs.f64(double %a)
-  %cmp = fcmp une double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
+  %call = call double @llvm.fabs.f64(double %a)
+  %cmp = fcmp oge double %call, 0.0
+  ret i1 %cmp
 }
 
-define i32 @test14(double %a) {
-; CHECK-LABEL: @test14(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    ret i32 [[CONV]]
+define i1 @fabs_une(half %a) {
+; CHECK-LABEL: @fabs_une(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp une half [[A:%.*]], 0xH0000
+; CHECK-NEXT:    ret i1 [[CMP]]
 ;
-  %call = tail call double @fabs(double %a)
-  %cmp = fcmp oeq double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
+  %call = call half @llvm.fabs.f16(half %a)
+  %cmp = fcmp une half %call, 0.0
+  ret i1 %cmp
 }
 
-define i32 @test14_intrinsic(double %a) {
-; CHECK-LABEL: @test14_intrinsic(
+define i1 @fabs_oeq(double %a) {
+; CHECK-LABEL: @fabs_oeq(
 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    ret i32 [[CONV]]
+; CHECK-NEXT:    ret i1 [[CMP]]
 ;
-  %call = tail call double @llvm.fabs.f64(double %a)
-  %cmp = fcmp oeq double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
+  %call = call double @llvm.fabs.f64(double %a)
+  %cmp = fcmp oeq double %call, 0.0
+  ret i1 %cmp
 }
 
-define i32 @test15(double %a) {
-; CHECK-LABEL: @test15(
+define i1 @fabs_one(double %a) {
+; CHECK-LABEL: @fabs_one(
 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    ret i32 [[CONV]]
+; CHECK-NEXT:    ret i1 [[CMP]]
 ;
-  %call = tail call double @fabs(double %a)
-  %cmp = fcmp one double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
+  %call = call double @llvm.fabs.f64(double %a)
+  %cmp = fcmp one double %call, 0.0
+  ret i1 %cmp
 }
 
-define i32 @test15_intrinsic(double %a) {
-; CHECK-LABEL: @test15_intrinsic(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    ret i32 [[CONV]]
+define <2 x i1> @fabs_ueq(<2 x float> %a) {
+; CHECK-LABEL: @fabs_ueq(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ueq <2 x float> [[A:%.*]], zeroinitializer
+; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
-  %call = tail call double @llvm.fabs.f64(double %a)
-  %cmp = fcmp one double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
-}
-
-define i32 @test16(double %a) {
-; CHECK-LABEL: @test16(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ueq double [[A:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    ret i32 [[CONV]]
-;
-  %call = tail call double @fabs(double %a)
-  %cmp = fcmp ueq double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
-}
-
-define i32 @test16_intrinsic(double %a) {
-; CHECK-LABEL: @test16_intrinsic(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ueq double [[A:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    ret i32 [[CONV]]
-;
-  %call = tail call double @llvm.fabs.f64(double %a)
-  %cmp = fcmp ueq double %call, 0.000000e+00
-  %conv = zext i1 %cmp to i32
-  ret i32 %conv
+  %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
+  %cmp = fcmp ueq <2 x float> %call, zeroinitializer
+  ret <2 x i1> %cmp
 }
 
 ; Don't crash.




More information about the llvm-commits mailing list