Fix PR2907 by digging through constant expressions to find FP constants that
are their operands.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@57956 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp
index 72bc920..6e69b9e 100644
--- a/lib/Target/CBackend/CBackend.cpp
+++ b/lib/Target/CBackend/CBackend.cpp
@@ -88,12 +88,15 @@
     std::map<const ConstantFP *, unsigned> FPConstantMap;
     std::set<Function*> intrinsicPrototypesAlreadyGenerated;
     std::set<const Argument*> ByValParams;
+    unsigned FPCounter;
 
   public:
     static char ID;
     explicit CWriter(raw_ostream &o)
       : FunctionPass(&ID), Out(o), IL(0), Mang(0), LI(0), 
-        TheModule(0), TAsm(0), TD(0) {}
+        TheModule(0), TAsm(0), TD(0) {
+      FPCounter = 0;
+    }
 
     virtual const char *getPassName() const { return "C backend"; }
 
@@ -181,6 +184,7 @@
     void printModuleTypes(const TypeSymbolTable &ST);
     void printContainedStructs(const Type *Ty, std::set<const Type *> &);
     void printFloatingPointConstants(Function &F);
+    void printFloatingPointConstants(const Constant *C);
     void printFunctionSignature(const Function *F, bool Prototype);
 
     void printFunction(Function &);
@@ -834,10 +838,10 @@
 static bool isFPCSafeToPrint(const ConstantFP *CFP) {
   bool ignored;
   // Do long doubles in hex for now.
-  if (CFP->getType()!=Type::FloatTy && CFP->getType()!=Type::DoubleTy)
+  if (CFP->getType() != Type::FloatTy && CFP->getType() != Type::DoubleTy)
     return false;
   APFloat APF = APFloat(CFP->getValueAPF());  // copy
-  if (CFP->getType()==Type::FloatTy)
+  if (CFP->getType() == Type::FloatTy)
     APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored);
 #if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A
   char Buffer[100];
@@ -2029,51 +2033,68 @@
   // the precision of the printed form, unless the printed form preserves
   // precision.
   //
-  static unsigned FPCounter = 0;
   for (constant_iterator I = constant_begin(&F), E = constant_end(&F);
        I != E; ++I)
-    if (const ConstantFP *FPC = dyn_cast<ConstantFP>(*I))
-      if (!isFPCSafeToPrint(FPC) && // Do not put in FPConstantMap if safe.
-          !FPConstantMap.count(FPC)) {
-        FPConstantMap[FPC] = FPCounter;  // Number the FP constants
-
-        if (FPC->getType() == Type::DoubleTy) {
-          double Val = FPC->getValueAPF().convertToDouble();
-          uint64_t i = FPC->getValueAPF().bitcastToAPInt().getZExtValue();
-          Out << "static const ConstantDoubleTy FPConstant" << FPCounter++
-              << " = 0x" << utohexstr(i)
-              << "ULL;    /* " << Val << " */\n";
-        } else if (FPC->getType() == Type::FloatTy) {
-          float Val = FPC->getValueAPF().convertToFloat();
-          uint32_t i = (uint32_t)FPC->getValueAPF().bitcastToAPInt().
-                                    getZExtValue();
-          Out << "static const ConstantFloatTy FPConstant" << FPCounter++
-              << " = 0x" << utohexstr(i)
-              << "U;    /* " << Val << " */\n";
-        } else if (FPC->getType() == Type::X86_FP80Ty) {
-          // api needed to prevent premature destruction
-          APInt api = FPC->getValueAPF().bitcastToAPInt();
-          const uint64_t *p = api.getRawData();
-          Out << "static const ConstantFP80Ty FPConstant" << FPCounter++
-              << " = { 0x"
-              << utohexstr((uint16_t)p[1] | (p[0] & 0xffffffffffffLL)<<16)
-              << "ULL, 0x" << utohexstr((uint16_t)(p[0] >> 48)) << ",{0,0,0}"
-              << "}; /* Long double constant */\n";
-        } else if (FPC->getType() == Type::PPC_FP128Ty) {
-          APInt api = FPC->getValueAPF().bitcastToAPInt();
-          const uint64_t *p = api.getRawData();
-          Out << "static const ConstantFP128Ty FPConstant" << FPCounter++
-              << " = { 0x"
-              << utohexstr(p[0]) << ", 0x" << utohexstr(p[1])
-              << "}; /* Long double constant */\n";
-
-        } else
-          assert(0 && "Unknown float type!");
-      }
+    printFloatingPointConstants(*I);
 
   Out << '\n';
 }
 
+void CWriter::printFloatingPointConstants(const Constant *C) {
+  // If this is a constant expression, recursively check for constant fp values.
+  if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
+    for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i)
+      printFloatingPointConstants(CE->getOperand(i));
+    return;
+  }
+    
+  // Otherwise, check for a FP constant that we need to print.
+  const ConstantFP *FPC = dyn_cast<ConstantFP>(C);
+  if (FPC == 0 ||
+      // Do not put in FPConstantMap if safe.
+      isFPCSafeToPrint(FPC) ||
+      // Already printed this constant?
+      FPConstantMap.count(FPC))
+    return;
+
+  FPConstantMap[FPC] = FPCounter;  // Number the FP constants
+  
+  if (FPC->getType() == Type::DoubleTy) {
+    double Val = FPC->getValueAPF().convertToDouble();
+    uint64_t i = FPC->getValueAPF().bitcastToAPInt().getZExtValue();
+    Out << "static const ConstantDoubleTy FPConstant" << FPCounter++
+    << " = 0x" << utohexstr(i)
+    << "ULL;    /* " << Val << " */\n";
+  } else if (FPC->getType() == Type::FloatTy) {
+    float Val = FPC->getValueAPF().convertToFloat();
+    uint32_t i = (uint32_t)FPC->getValueAPF().bitcastToAPInt().
+    getZExtValue();
+    Out << "static const ConstantFloatTy FPConstant" << FPCounter++
+    << " = 0x" << utohexstr(i)
+    << "U;    /* " << Val << " */\n";
+  } else if (FPC->getType() == Type::X86_FP80Ty) {
+    // api needed to prevent premature destruction
+    APInt api = FPC->getValueAPF().bitcastToAPInt();
+    const uint64_t *p = api.getRawData();
+    Out << "static const ConstantFP80Ty FPConstant" << FPCounter++
+    << " = { 0x"
+    << utohexstr((uint16_t)p[1] | (p[0] & 0xffffffffffffLL)<<16)
+    << "ULL, 0x" << utohexstr((uint16_t)(p[0] >> 48)) << ",{0,0,0}"
+    << "}; /* Long double constant */\n";
+  } else if (FPC->getType() == Type::PPC_FP128Ty) {
+    APInt api = FPC->getValueAPF().bitcastToAPInt();
+    const uint64_t *p = api.getRawData();
+    Out << "static const ConstantFP128Ty FPConstant" << FPCounter++
+    << " = { 0x"
+    << utohexstr(p[0]) << ", 0x" << utohexstr(p[1])
+    << "}; /* Long double constant */\n";
+    
+  } else {
+    assert(0 && "Unknown float type!");
+  }
+}
+
+
 
 /// printSymbolTable - Run through symbol table looking for type names.  If a
 /// type name is found, emit its declaration...