Fix constant fold of div by zero and rem by zero to match IEEE 754
[oota-llvm.git] / lib / VMCore / ConstantFold.cpp
index 0d27a880eb462ef5d75d9c1af6c07a24a7874424..d7e51956e4d274031f77253b75037d5c03745f69 100644 (file)
@@ -86,9 +86,9 @@ static Constant *CastConstantVector(ConstantVector *CV,
     
     if (SrcEltTy->getTypeID() == Type::DoubleTyID) {
       for (unsigned i = 0; i != SrcNumElts; ++i) {
-        double V =
+        uint64_t V =
           DoubleToBits(cast<ConstantFP>(CV->getOperand(i))->getValue());
-        Constant *C = ConstantInt::get(APIntOps::RoundDoubleToAPInt(V));
+        Constant *C = ConstantInt::get(Type::Int64Ty, V);
         Result.push_back(ConstantExpr::getBitCast(C, DstEltTy ));
       }
       return ConstantVector::get(Result);
@@ -651,17 +651,27 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
       case Instruction::Mul:     
         return ConstantFP::get(CFP1->getType(), C1Val * C2Val);
       case Instruction::FDiv:
-        if (CFP2->isExactlyValue(0.0)) 
-          return ConstantFP::get(CFP1->getType(),
-                                 std::numeric_limits<double>::infinity());
-        if (CFP2->isExactlyValue(-0.0))
-          return ConstantFP::get(CFP1->getType(),
-                                 -std::numeric_limits<double>::infinity());
+        if (CFP2->isExactlyValue(0.0) || CFP2->isExactlyValue(-0.0))
+          if (CFP1->isExactlyValue(0.0) || CFP1->isExactlyValue(-0.0))
+            // IEEE 754, Section 7.1, #4
+            return ConstantFP::get(CFP1->getType(),
+                                   std::numeric_limits<double>::quiet_NaN());
+          else if (CFP2->isExactlyValue(-0.0) || C1Val < 0.0)
+            // IEEE 754, Section 7.2, negative infinity case
+            return ConstantFP::get(CFP1->getType(),
+                                   -std::numeric_limits<double>::infinity());
+          else
+            // IEEE 754, Section 7.2, positive infinity case
+            return ConstantFP::get(CFP1->getType(),
+                                   std::numeric_limits<double>::infinity());
         return ConstantFP::get(CFP1->getType(), C1Val / C2Val);
       case Instruction::FRem:
-        if (CFP2->isNullValue()) 
-          return 0;
+        if (CFP2->isExactlyValue(0.0) || CFP2->isExactlyValue(-0.0))
+          // IEEE 754, Section 7.1, #5
+          return ConstantFP::get(CFP1->getType(), 
+                                 std::numeric_limits<double>::quiet_NaN());
         return ConstantFP::get(CFP1->getType(), std::fmod(C1Val, C2Val));
+
       }
     }
   } else if (const ConstantVector *CP1 = dyn_cast<ConstantVector>(C1)) {