From d1cf1b458a952e9d8a28ea50bef165eee093b569 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 20 Sep 2002 23:26:33 +0000 Subject: [PATCH] Fix cwriter to not output FP constants in ascii, output them in hex instead. 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 | 45 ++++++++++++++++++++++++++++---- lib/Target/CBackend/Writer.cpp | 45 ++++++++++++++++++++++++++++---- 2 files changed, 80 insertions(+), 10 deletions(-) diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index e993b740f41..f0f5507897c 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -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 TypeNames; std::set MangledGlobals; + map FPConstantMap; public: CWriter(ostream &o) : Out(o) {} @@ -377,8 +377,19 @@ void CWriter::printConstant(Constant *CPV) { Out << cast(CPV)->getValue() << "ull"; break; case Type::FloatTyID: - case Type::DoubleTyID: - Out << cast(CPV)->getValue(); break; + case Type::DoubleTyID: { + ConstantFP *FPC = cast(CPV); + map::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(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(*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 diff --git a/lib/Target/CBackend/Writer.cpp b/lib/Target/CBackend/Writer.cpp index e993b740f41..f0f5507897c 100644 --- a/lib/Target/CBackend/Writer.cpp +++ b/lib/Target/CBackend/Writer.cpp @@ -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 TypeNames; std::set MangledGlobals; + map FPConstantMap; public: CWriter(ostream &o) : Out(o) {} @@ -377,8 +377,19 @@ void CWriter::printConstant(Constant *CPV) { Out << cast(CPV)->getValue() << "ull"; break; case Type::FloatTyID: - case Type::DoubleTyID: - Out << cast(CPV)->getValue(); break; + case Type::DoubleTyID: { + ConstantFP *FPC = cast(CPV); + map::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(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(*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