[llvm-commits] [llvm] r58929 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/2008-11-08-FCmp.ll

Bill Wendling isanbard at gmail.com
Sat Nov 8 20:26:52 PST 2008


Author: void
Date: Sat Nov  8 22:26:50 2008
New Revision: 58929

URL: http://llvm.org/viewvc/llvm-project?rev=58929&view=rev
Log:
If the LHS of the FCMP is coming from a UIToFP instruction, then we don't want
to generate signed ICMP instructions to replace the FCMP. This would violate
the following:

define i1 @test1(i32 %val) {
  %1 = uitofp i32 %val to double
  %2 = fcmp ole double %1, 0.000000e+00
  ret i1 %2
}

would be transformed into:

define i1 @test1(i32 %val) {
  %1 = icmp slt i33 %val, 1
  ret i1 %1
}

which is obviously wrong. This patch modifes InstCombiner::FoldFCmp_IntToFP_Cst
to handle when the LHS comes from UIToFP.

Added:
    llvm/trunk/test/Transforms/InstCombine/2008-11-08-FCmp.ll
Modified:
    llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=58929&r1=58928&r2=58929&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Sat Nov  8 22:26:50 2008
@@ -5317,7 +5317,8 @@
   unsigned InputSize = LHSI->getOperand(0)->getType()->getPrimitiveSizeInBits();
   
   // If this is a uitofp instruction, we need an extra bit to hold the sign.
-  if (isa<UIToFPInst>(LHSI))
+  bool LHSUnsigned = isa<UIToFPInst>(LHSI);
+  if (LHSUnsigned)
     ++InputSize;
   
   // If the conversion would lose info, don't hack on this.
@@ -5333,17 +5334,29 @@
   switch (I.getPredicate()) {
   default: assert(0 && "Unexpected predicate!");
   case FCmpInst::FCMP_UEQ:
-  case FCmpInst::FCMP_OEQ: Pred = ICmpInst::ICMP_EQ; break;
+  case FCmpInst::FCMP_OEQ:
+    Pred = ICmpInst::ICMP_EQ;
+    break;
   case FCmpInst::FCMP_UGT:
-  case FCmpInst::FCMP_OGT: Pred = ICmpInst::ICMP_SGT; break;
+  case FCmpInst::FCMP_OGT:
+    Pred = LHSUnsigned ? ICmpInst::ICMP_UGT : ICmpInst::ICMP_SGT;
+    break;
   case FCmpInst::FCMP_UGE:
-  case FCmpInst::FCMP_OGE: Pred = ICmpInst::ICMP_SGE; break;
+  case FCmpInst::FCMP_OGE:
+    Pred = LHSUnsigned ? ICmpInst::ICMP_UGE : ICmpInst::ICMP_SGE;
+    break;
   case FCmpInst::FCMP_ULT:
-  case FCmpInst::FCMP_OLT: Pred = ICmpInst::ICMP_SLT; break;
+  case FCmpInst::FCMP_OLT:
+    Pred = LHSUnsigned ? ICmpInst::ICMP_ULT : ICmpInst::ICMP_SLT;
+    break;
   case FCmpInst::FCMP_ULE:
-  case FCmpInst::FCMP_OLE: Pred = ICmpInst::ICMP_SLE; break;
+  case FCmpInst::FCMP_OLE:
+    Pred = LHSUnsigned ? ICmpInst::ICMP_ULE : ICmpInst::ICMP_SLE;
+    break;
   case FCmpInst::FCMP_UNE:
-  case FCmpInst::FCMP_ONE: Pred = ICmpInst::ICMP_NE; break;
+  case FCmpInst::FCMP_ONE:
+    Pred = ICmpInst::ICMP_NE;
+    break;
   case FCmpInst::FCMP_ORD:
     return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
   case FCmpInst::FCMP_UNO:
@@ -5358,63 +5371,105 @@
   // comparing an i8 to 300.0.
   unsigned IntWidth = IntTy->getPrimitiveSizeInBits();
   
-  // If the RHS value is > SignedMax, fold the comparison.  This handles +INF
-  // and large values. 
-  APFloat SMax(RHS.getSemantics(), APFloat::fcZero, false);
-  SMax.convertFromAPInt(APInt::getSignedMaxValue(IntWidth), true,
-                        APFloat::rmNearestTiesToEven);
-  if (SMax.compare(RHS) == APFloat::cmpLessThan) {  // smax < 13123.0
-    if (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_SLT ||
-        Pred == ICmpInst::ICMP_SLE)
-      return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
-    return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
+  if (!LHSUnsigned) {
+    // If the RHS value is > SignedMax, fold the comparison.  This handles +INF
+    // and large values.
+    APFloat SMax(RHS.getSemantics(), APFloat::fcZero, false);
+    SMax.convertFromAPInt(APInt::getSignedMaxValue(IntWidth), true,
+                          APFloat::rmNearestTiesToEven);
+    if (SMax.compare(RHS) == APFloat::cmpLessThan) {  // smax < 13123.0
+      if (Pred == ICmpInst::ICMP_NE  || Pred == ICmpInst::ICMP_SLT ||
+          Pred == ICmpInst::ICMP_SLE)
+        return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
+      return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
+    }
+  } else {
+    // If the RHS value is > UnsignedMax, fold the comparison. This handles
+    // +INF and large values.
+    APFloat UMax(RHS.getSemantics(), APFloat::fcZero, false);
+    UMax.convertFromAPInt(APInt::getMaxValue(IntWidth), false,
+                          APFloat::rmNearestTiesToEven);
+    if (UMax.compare(RHS) == APFloat::cmpLessThan) {  // umax < 13123.0
+      if (Pred == ICmpInst::ICMP_NE  || Pred == ICmpInst::ICMP_ULT ||
+          Pred == ICmpInst::ICMP_ULE)
+        return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
+      return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
+    }
   }
   
-  // See if the RHS value is < SignedMin.
-  APFloat SMin(RHS.getSemantics(), APFloat::fcZero, false);
-  SMin.convertFromAPInt(APInt::getSignedMinValue(IntWidth), true,
-                        APFloat::rmNearestTiesToEven);
-  if (SMin.compare(RHS) == APFloat::cmpGreaterThan) { // smin > 12312.0
-    if (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_SGT ||
-        Pred == ICmpInst::ICMP_SGE)
-      return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
-    return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
+  if (!LHSUnsigned) {
+    // See if the RHS value is < SignedMin.
+    APFloat SMin(RHS.getSemantics(), APFloat::fcZero, false);
+    SMin.convertFromAPInt(APInt::getSignedMinValue(IntWidth), true,
+                          APFloat::rmNearestTiesToEven);
+    if (SMin.compare(RHS) == APFloat::cmpGreaterThan) { // smin > 12312.0
+      if (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_SGT ||
+          Pred == ICmpInst::ICMP_SGE)
+        return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
+      return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
+    }
   }
 
-  // Okay, now we know that the FP constant fits in the range [SMIN, SMAX] but
-  // it may still be fractional.  See if it is fractional by casting the FP
-  // value to the integer value and back, checking for equality.  Don't do this
-  // for zero, because -0.0 is not fractional.
+  // Okay, now we know that the FP constant fits in the range [SMIN, SMAX] or
+  // [0, UMAX], but it may still be fractional.  See if it is fractional by
+  // casting the FP value to the integer value and back, checking for equality.
+  // Don't do this for zero, because -0.0 is not fractional.
   Constant *RHSInt = ConstantExpr::getFPToSI(RHSC, IntTy);
   if (!RHS.isZero() &&
       ConstantExpr::getSIToFP(RHSInt, RHSC->getType()) != RHSC) {
-    // If we had a comparison against a fractional value, we have to adjust
-    // the compare predicate and sometimes the value.  RHSC is rounded towards
-    // zero at this point.
+    // If we had a comparison against a fractional value, we have to adjust the
+    // compare predicate and sometimes the value.  RHSC is rounded towards zero
+    // at this point.
     switch (Pred) {
     default: assert(0 && "Unexpected integer comparison!");
     case ICmpInst::ICMP_NE:  // (float)int != 4.4   --> true
       return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
     case ICmpInst::ICMP_EQ:  // (float)int == 4.4   --> false
       return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
+    case ICmpInst::ICMP_ULE:
+      // (float)int <= 4.4   --> int <= 4
+      // (float)int <= -4.4  --> false
+      if (RHS.isNegative())
+        return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
+      break;
     case ICmpInst::ICMP_SLE:
       // (float)int <= 4.4   --> int <= 4
       // (float)int <= -4.4  --> int < -4
       if (RHS.isNegative())
         Pred = ICmpInst::ICMP_SLT;
       break;
+    case ICmpInst::ICMP_ULT:
+      // (float)int < -4.4   --> false
+      // (float)int < 4.4    --> int <= 4
+      if (RHS.isNegative())
+        return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
+      Pred = ICmpInst::ICMP_ULE;
+      break;
     case ICmpInst::ICMP_SLT:
       // (float)int < -4.4   --> int < -4
       // (float)int < 4.4    --> int <= 4
       if (!RHS.isNegative())
         Pred = ICmpInst::ICMP_SLE;
       break;
+    case ICmpInst::ICMP_UGT:
+      // (float)int > 4.4    --> int > 4
+      // (float)int > -4.4   --> true
+      if (RHS.isNegative())
+        return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
+      break;
     case ICmpInst::ICMP_SGT:
       // (float)int > 4.4    --> int > 4
       // (float)int > -4.4   --> int >= -4
       if (RHS.isNegative())
         Pred = ICmpInst::ICMP_SGE;
       break;
+    case ICmpInst::ICMP_UGE:
+      // (float)int >= -4.4   --> true
+      // (float)int >= 4.4    --> int > 4
+      if (!RHS.isNegative())
+        return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
+      Pred = ICmpInst::ICMP_UGT;
+      break;
     case ICmpInst::ICMP_SGE:
       // (float)int >= -4.4   --> int >= -4
       // (float)int >= 4.4    --> int > 4

Added: llvm/trunk/test/Transforms/InstCombine/2008-11-08-FCmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2008-11-08-FCmp.ll?rev=58929&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2008-11-08-FCmp.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2008-11-08-FCmp.ll Sat Nov  8 22:26:50 2008
@@ -0,0 +1,46 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis > %t
+; RUN: grep {icmp eq} %t
+; RUN: grep {ret i1 false} %t | count 2
+; RUN: grep {ret i1 true} %t | count 2
+; RUN: grep {icmp ne} %t
+; RUN: not grep {icmp slt} %t
+; PR3021
+
+; When inst combining an FCMP with the LHS coming from a uitofp instruction, we
+; can't lower it to signed ICMP instructions.
+
+define i1 @test1(i32 %val) {
+  %1 = uitofp i32 %val to double
+  %2 = fcmp ole double %1, 0.000000e+00
+  ret i1 %2
+}
+
+define i1 @test2(i32 %val) {
+  %1 = uitofp i32 %val to double
+  %2 = fcmp olt double %1, 0.000000e+00
+  ret i1 %2
+}
+
+define i1 @test3(i32 %val) {
+  %1 = uitofp i32 %val to double
+  %2 = fcmp oge double %1, 0.000000e+00
+  ret i1 %2
+}
+
+define i1 @test4(i32 %val) {
+  %1 = uitofp i32 %val to double
+  %2 = fcmp ogt double %1, 0.000000e+00
+  ret i1 %2
+}
+
+define i1 @test5(i32 %val) {
+  %1 = uitofp i32 %val to double
+  %2 = fcmp ogt double %1, -4.400000e+00
+  ret i1 %2
+}
+
+define i1 @test6(i32 %val) {
+  %1 = uitofp i32 %val to double
+  %2 = fcmp olt double %1, -4.400000e+00
+  ret i1 %2
+}





More information about the llvm-commits mailing list