Fix cwriter to not output FP constants in ascii, output them in hex instead.
authorChris Lattner <sabre@nondot.org>
Fri, 20 Sep 2002 23:26:33 +0000 (23:26 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 20 Sep 2002 23:26:33 +0000 (23:26 +0000)
This fixes a number of FP precision problems, making the output of the
power benchmark closer to the right answer.

Unfortunately, this only addresses FP constants used directly in functions.
Constants referred to by global constants (such as an array of FP values)
aren't helped by this.  Until this happens power won't work.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@3871 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/CBackend/CBackend.cpp
lib/Target/CBackend/Writer.cpp

index e993b740f412f620b9fe79f21aecffbbae6afd85..f0f5507897c1ce45451e99805da812e7680c77ac 100644 (file)
@@ -1,8 +1,6 @@
 //===-- Writer.cpp - Library for converting LLVM code to C ----------------===//
 //
-// This library implements the functionality defined in llvm/Assembly/CWriter.h
-//
-// TODO : Recursive types.
+// This library converts LLVM code to C code, compilable by GCC.
 //
 //===-----------------------------------------------------------------------==//
 
@@ -19,6 +17,7 @@
 #include "llvm/SymbolTable.h"
 #include "llvm/SlotCalculator.h"
 #include "llvm/Analysis/FindUsedTypes.h"
+#include "llvm/Analysis/ConstantsScanner.h"
 #include "llvm/Support/InstVisitor.h"
 #include "llvm/Support/InstIterator.h"
 #include "Support/StringExtras.h"
@@ -37,6 +36,7 @@ namespace {
     map<const Type *, string> TypeNames;
     std::set<const Value*> MangledGlobals;
 
+    map<const ConstantFP *, unsigned> FPConstantMap;
   public:
     CWriter(ostream &o) : Out(o) {}
 
@@ -377,8 +377,19 @@ void CWriter::printConstant(Constant *CPV) {
     Out << cast<ConstantUInt>(CPV)->getValue() << "ull"; break;
 
   case Type::FloatTyID:
-  case Type::DoubleTyID:
-    Out << cast<ConstantFP>(CPV)->getValue(); break;
+  case Type::DoubleTyID: {
+    ConstantFP *FPC = cast<ConstantFP>(CPV);
+    map<const ConstantFP *, unsigned>::iterator I = FPConstantMap.find(FPC);
+    if (I != FPConstantMap.end()) {
+      // Because of FP precision problems we must load from a stack allocated
+      // value that holds the value in hex.
+      Out << "(*(" << (FPC->getType() == Type::FloatTy ? "float" : "double")
+          << "*)&FloatConstant" << I->second << ")";
+    } else {
+      Out << FPC->getValue();
+    }
+    break;
+  }
 
   case Type::ArrayTyID:
     printConstantArray(cast<ConstantArray>(CPV));
@@ -509,6 +520,9 @@ void CWriter::printModule(Module *M) {
       << "#ifndef NULL\n#define NULL 0\n#endif\n\n"
       << "#ifndef __cplusplus\ntypedef unsigned char bool;\n#endif\n"
 
+      << "\n\n/* Support for floating point constants */\n"
+      << "typedef unsigned long long ConstantDoubleTy;\n"
+
       << "\n\n/* Global Declarations */\n";
 
   // First output all the declarations for the program, because C requires
@@ -709,6 +723,26 @@ void CWriter::printFunction(Function *F) {
       printType((*I)->getType(), getValueName(*I));
       Out << ";\n";
     }
+
+  Out << "\n";
+
+  // Scan the function for floating point constants.  If any FP constant is used
+  // in the function, we want to redirect it here so that we do not depend on
+  // the precision of the printed form.
+  //
+  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 (FPConstantMap.find(FPC) == FPConstantMap.end()) {
+        double Val = FPC->getValue();
+        
+        FPConstantMap[FPC] = FPCounter;  // Number the FP constants
+        Out << "  const ConstantDoubleTy FloatConstant" << FPCounter++
+            << " = 0x" << std::hex << *(unsigned long long*)&Val << std::dec
+            << ";    /* " << Val << " */\n";
+      }
+
+  Out << "\n";
  
   // print the basic blocks
   for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
@@ -748,6 +782,7 @@ void CWriter::printFunction(Function *F) {
   
   Out << "}\n\n";
   Table->purgeFunction();
+  FPConstantMap.clear();
 }
 
 // Specific Instruction type classes... note that all of the casts are
index e993b740f412f620b9fe79f21aecffbbae6afd85..f0f5507897c1ce45451e99805da812e7680c77ac 100644 (file)
@@ -1,8 +1,6 @@
 //===-- Writer.cpp - Library for converting LLVM code to C ----------------===//
 //
-// This library implements the functionality defined in llvm/Assembly/CWriter.h
-//
-// TODO : Recursive types.
+// This library converts LLVM code to C code, compilable by GCC.
 //
 //===-----------------------------------------------------------------------==//
 
@@ -19,6 +17,7 @@
 #include "llvm/SymbolTable.h"
 #include "llvm/SlotCalculator.h"
 #include "llvm/Analysis/FindUsedTypes.h"
+#include "llvm/Analysis/ConstantsScanner.h"
 #include "llvm/Support/InstVisitor.h"
 #include "llvm/Support/InstIterator.h"
 #include "Support/StringExtras.h"
@@ -37,6 +36,7 @@ namespace {
     map<const Type *, string> TypeNames;
     std::set<const Value*> MangledGlobals;
 
+    map<const ConstantFP *, unsigned> FPConstantMap;
   public:
     CWriter(ostream &o) : Out(o) {}
 
@@ -377,8 +377,19 @@ void CWriter::printConstant(Constant *CPV) {
     Out << cast<ConstantUInt>(CPV)->getValue() << "ull"; break;
 
   case Type::FloatTyID:
-  case Type::DoubleTyID:
-    Out << cast<ConstantFP>(CPV)->getValue(); break;
+  case Type::DoubleTyID: {
+    ConstantFP *FPC = cast<ConstantFP>(CPV);
+    map<const ConstantFP *, unsigned>::iterator I = FPConstantMap.find(FPC);
+    if (I != FPConstantMap.end()) {
+      // Because of FP precision problems we must load from a stack allocated
+      // value that holds the value in hex.
+      Out << "(*(" << (FPC->getType() == Type::FloatTy ? "float" : "double")
+          << "*)&FloatConstant" << I->second << ")";
+    } else {
+      Out << FPC->getValue();
+    }
+    break;
+  }
 
   case Type::ArrayTyID:
     printConstantArray(cast<ConstantArray>(CPV));
@@ -509,6 +520,9 @@ void CWriter::printModule(Module *M) {
       << "#ifndef NULL\n#define NULL 0\n#endif\n\n"
       << "#ifndef __cplusplus\ntypedef unsigned char bool;\n#endif\n"
 
+      << "\n\n/* Support for floating point constants */\n"
+      << "typedef unsigned long long ConstantDoubleTy;\n"
+
       << "\n\n/* Global Declarations */\n";
 
   // First output all the declarations for the program, because C requires
@@ -709,6 +723,26 @@ void CWriter::printFunction(Function *F) {
       printType((*I)->getType(), getValueName(*I));
       Out << ";\n";
     }
+
+  Out << "\n";
+
+  // Scan the function for floating point constants.  If any FP constant is used
+  // in the function, we want to redirect it here so that we do not depend on
+  // the precision of the printed form.
+  //
+  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 (FPConstantMap.find(FPC) == FPConstantMap.end()) {
+        double Val = FPC->getValue();
+        
+        FPConstantMap[FPC] = FPCounter;  // Number the FP constants
+        Out << "  const ConstantDoubleTy FloatConstant" << FPCounter++
+            << " = 0x" << std::hex << *(unsigned long long*)&Val << std::dec
+            << ";    /* " << Val << " */\n";
+      }
+
+  Out << "\n";
  
   // print the basic blocks
   for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
@@ -748,6 +782,7 @@ void CWriter::printFunction(Function *F) {
   
   Out << "}\n\n";
   Table->purgeFunction();
+  FPConstantMap.clear();
 }
 
 // Specific Instruction type classes... note that all of the casts are