diff options
40 files changed, 1010 insertions, 611 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 6af569b..ba63484 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,8 @@ This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. Please delete them.") endif() +string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE) + include(FindPerl) set(LLVM_MAIN_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) @@ -55,6 +57,16 @@ endif( MSVC ) option(LLVM_ENABLE_THREADS "Use threads if available." ON) +if( uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE" ) + option(LLVM_ENABLE_ASSERTS "Enable asserts" OFF) +else() + option(LLVM_ENABLE_ASSERTS "Enable asserts" ON) +endif() + +if( LLVM_ENABLE_ASSERTS ) + add_definitions( -D_DEBUG -UNDEBUG ) +endif() + if( LLVM_TARGETS_TO_BUILD STREQUAL "all" ) set( LLVM_TARGETS_TO_BUILD ${LLVM_ALL_TARGETS} ) endif() diff --git a/docs/CMake.html b/docs/CMake.html index 27ec88e..b329ca4 100644 --- a/docs/CMake.html +++ b/docs/CMake.html @@ -248,6 +248,10 @@ <dt><b>LLVM_ENABLE_THREADS</b>:BOOL</dt> <dd>Build with threads support, if available. Defaults to ON.</dd> + <dt><b>LLVM_ENABLE_ASSERTS</b>:BOOL</dt> + <dd>Enables code asserts. Defaults to ON if and only if + CMAKE_BUILD_TYPE is <i>Release</i>.</dd> + <dt><b>LLVM_ENABLE_PIC</b>:BOOL</dt> <dd>Add the <i>-fPIC</i> flag to the compiler command-line, if the compiler supports this flag. Some systems, like Windows, does not diff --git a/docs/GoldPlugin.html b/docs/GoldPlugin.html index ee01410..6be5277 100644 --- a/docs/GoldPlugin.html +++ b/docs/GoldPlugin.html @@ -14,6 +14,7 @@ <li><a href="#usage">Usage</a> <ul> <li><a href="#example1">Example of link time optimization</a></li> + <li><a href="#lto_autotools">Quickstart for using LTO with autotooled projects</a></li> </ul></li> <li><a href="#licensing">Licensing</a></li> </ol> @@ -136,6 +137,35 @@ $ llvm-gcc -use-gold-plugin a.o b.o -o main # <-- link with LLVMgold plugin </div> <!--=========================================================================--> +<div class="doc_section"><a name="lto_autotools">Quickstart for using LTO with autotooled projects</a></div> +<!--=========================================================================--> +<div class="doc_text"> + <p><tt>gold</tt>, <tt>ar</tt> and <tt>nm</tt> all support plugins now, so everything should be + in place for an easy to use LTO build of autotooled projects:</p> + <ul> + <li>Follow the instructions <a href="#build">on how to build libLLVMgold.so</a>.</li> + <li>Install the newly built binutils to <tt>$PREFIX</tt></li> + <li>Copy <tt>Release/lib/libLLVMgold.so</tt> to + <tt>$PREFIX/libexec/gcc/x86_64-unknown-linux-gnu/4.2.1/</tt> and + <tt>$PREFIX/lib/bfd-plugins/</tt></li> + <li>Set environment variables (<tt>$PREFIX</tt> is where you installed llvm-gcc and + binutils): + <pre class="doc_code"> +export CC="$PREFIX/bin/llvm-gcc -use-gold-plugin" +export CXX="$PREFIX/bin/llvm-g++ -use-gold-plugin" +export AR="$PREFIX/bin/ar --plugin libLLVMgold.so" +export NM="$PREFIX/bin/nm --plugin libLLVMgold.so" +export RANLIB=/bin/true #ranlib is not needed, and doesn't support .bc files in .a +export CFLAGS="-O4" + </pre> + </li> + <li>Configure & build the project as usual: <tt>./configure && make && make check</tt> </li> + </ul> + <p> The environment variable settings may work for non-autotooled projects + too, but you may need to set the <tt>LD</tt> environment variable as well.</p> +</div> + +<!--=========================================================================--> <div class="doc_section"><a name="licensing">Licensing</a></div> <!--=========================================================================--> <div class="doc_text"> diff --git a/include/llvm/CodeGen/JITCodeEmitter.h b/include/llvm/CodeGen/JITCodeEmitter.h index bf6b76e..81a7c60 100644 --- a/include/llvm/CodeGen/JITCodeEmitter.h +++ b/include/llvm/CodeGen/JITCodeEmitter.h @@ -89,7 +89,7 @@ public: /// emitByte - This callback is invoked when a byte needs to be written to the /// output stream. /// - void emitByte(uint8_t B) { + void emitByte(unsigned char B) { if (CurBufferPtr != BufferEnd) *CurBufferPtr++ = B; } @@ -99,10 +99,10 @@ public: /// void emitWordLE(unsigned W) { if (4 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 0); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 24); + *CurBufferPtr++ = (unsigned char)(W >> 0); + *CurBufferPtr++ = (unsigned char)(W >> 8); + *CurBufferPtr++ = (unsigned char)(W >> 16); + *CurBufferPtr++ = (unsigned char)(W >> 24); } else { CurBufferPtr = BufferEnd; } @@ -113,10 +113,10 @@ public: /// void emitWordBE(unsigned W) { if (4 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 0); + *CurBufferPtr++ = (unsigned char)(W >> 24); + *CurBufferPtr++ = (unsigned char)(W >> 16); + *CurBufferPtr++ = (unsigned char)(W >> 8); + *CurBufferPtr++ = (unsigned char)(W >> 0); } else { CurBufferPtr = BufferEnd; } @@ -127,14 +127,14 @@ public: /// void emitDWordLE(uint64_t W) { if (8 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 0); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 32); - *CurBufferPtr++ = (uint8_t)(W >> 40); - *CurBufferPtr++ = (uint8_t)(W >> 48); - *CurBufferPtr++ = (uint8_t)(W >> 56); + *CurBufferPtr++ = (unsigned char)(W >> 0); + *CurBufferPtr++ = (unsigned char)(W >> 8); + *CurBufferPtr++ = (unsigned char)(W >> 16); + *CurBufferPtr++ = (unsigned char)(W >> 24); + *CurBufferPtr++ = (unsigned char)(W >> 32); + *CurBufferPtr++ = (unsigned char)(W >> 40); + *CurBufferPtr++ = (unsigned char)(W >> 48); + *CurBufferPtr++ = (unsigned char)(W >> 56); } else { CurBufferPtr = BufferEnd; } @@ -145,14 +145,14 @@ public: /// void emitDWordBE(uint64_t W) { if (8 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 56); - *CurBufferPtr++ = (uint8_t)(W >> 48); - *CurBufferPtr++ = (uint8_t)(W >> 40); - *CurBufferPtr++ = (uint8_t)(W >> 32); - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 0); + *CurBufferPtr++ = (unsigned char)(W >> 56); + *CurBufferPtr++ = (unsigned char)(W >> 48); + *CurBufferPtr++ = (unsigned char)(W >> 40); + *CurBufferPtr++ = (unsigned char)(W >> 32); + *CurBufferPtr++ = (unsigned char)(W >> 24); + *CurBufferPtr++ = (unsigned char)(W >> 16); + *CurBufferPtr++ = (unsigned char)(W >> 8); + *CurBufferPtr++ = (unsigned char)(W >> 0); } else { CurBufferPtr = BufferEnd; } @@ -166,8 +166,8 @@ public: if(Alignment <= (uintptr_t)(BufferEnd-CurBufferPtr)) { // Move the current buffer ptr up to the specified alignment. CurBufferPtr = - (uint8_t*)(((uintptr_t)CurBufferPtr+Alignment-1) & - ~(uintptr_t)(Alignment-1)); + (unsigned char*)(((uintptr_t)CurBufferPtr+Alignment-1) & + ~(uintptr_t)(Alignment-1)); } else { CurBufferPtr = BufferEnd; } @@ -178,7 +178,7 @@ public: /// written to the output stream. void emitULEB128Bytes(unsigned Value) { do { - uint8_t Byte = Value & 0x7f; + unsigned char Byte = Value & 0x7f; Value >>= 7; if (Value) Byte |= 0x80; emitByte(Byte); @@ -187,12 +187,12 @@ public: /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be /// written to the output stream. - void emitSLEB128Bytes(int32_t Value) { - int32_t Sign = Value >> (8 * sizeof(Value) - 1); + void emitSLEB128Bytes(int Value) { + int Sign = Value >> (8 * sizeof(Value) - 1); bool IsMore; do { - uint8_t Byte = Value & 0x7f; + unsigned char Byte = Value & 0x7f; Value >>= 7; IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; if (IsMore) Byte |= 0x80; @@ -205,14 +205,14 @@ public: void emitString(const std::string &String) { for (unsigned i = 0, N = static_cast<unsigned>(String.size()); i < N; ++i) { - uint8_t C = String[i]; + unsigned char C = String[i]; emitByte(C); } emitByte(0); } /// emitInt32 - Emit a int32 directive. - void emitInt32(int32_t Value) { + void emitInt32(int Value) { if (4 <= BufferEnd-CurBufferPtr) { *((uint32_t*)CurBufferPtr) = Value; CurBufferPtr += 4; diff --git a/include/llvm/CodeGen/MachineCodeEmitter.h b/include/llvm/CodeGen/MachineCodeEmitter.h index aaa41a4..226c4c2 100644 --- a/include/llvm/CodeGen/MachineCodeEmitter.h +++ b/include/llvm/CodeGen/MachineCodeEmitter.h @@ -50,14 +50,14 @@ class MachineCodeEmitter { protected: /// BufferBegin/BufferEnd - Pointers to the start and end of the memory /// allocated for this code buffer. - uint8_t *BufferBegin, *BufferEnd; + unsigned char *BufferBegin, *BufferEnd; /// CurBufferPtr - Pointer to the next byte of memory to fill when emitting /// code. This is guranteed to be in the range [BufferBegin,BufferEnd]. If /// this pointer is at BufferEnd, it will never move due to code emission, and /// all code emission requests will be ignored (this is the buffer overflow /// condition). - uint8_t *CurBufferPtr; + unsigned char *CurBufferPtr; public: virtual ~MachineCodeEmitter() {} @@ -96,7 +96,7 @@ public: /// emitByte - This callback is invoked when a byte needs to be written to the /// output stream. /// - void emitByte(uint8_t B) { + void emitByte(unsigned char B) { if (CurBufferPtr != BufferEnd) *CurBufferPtr++ = B; } @@ -106,10 +106,10 @@ public: /// void emitWordLE(unsigned W) { if (4 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 0); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 24); + *CurBufferPtr++ = (unsigned char)(W >> 0); + *CurBufferPtr++ = (unsigned char)(W >> 8); + *CurBufferPtr++ = (unsigned char)(W >> 16); + *CurBufferPtr++ = (unsigned char)(W >> 24); } else { CurBufferPtr = BufferEnd; } @@ -120,10 +120,10 @@ public: /// void emitWordBE(unsigned W) { if (4 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 0); + *CurBufferPtr++ = (unsigned char)(W >> 24); + *CurBufferPtr++ = (unsigned char)(W >> 16); + *CurBufferPtr++ = (unsigned char)(W >> 8); + *CurBufferPtr++ = (unsigned char)(W >> 0); } else { CurBufferPtr = BufferEnd; } @@ -134,14 +134,14 @@ public: /// void emitDWordLE(uint64_t W) { if (8 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 0); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 32); - *CurBufferPtr++ = (uint8_t)(W >> 40); - *CurBufferPtr++ = (uint8_t)(W >> 48); - *CurBufferPtr++ = (uint8_t)(W >> 56); + *CurBufferPtr++ = (unsigned char)(W >> 0); + *CurBufferPtr++ = (unsigned char)(W >> 8); + *CurBufferPtr++ = (unsigned char)(W >> 16); + *CurBufferPtr++ = (unsigned char)(W >> 24); + *CurBufferPtr++ = (unsigned char)(W >> 32); + *CurBufferPtr++ = (unsigned char)(W >> 40); + *CurBufferPtr++ = (unsigned char)(W >> 48); + *CurBufferPtr++ = (unsigned char)(W >> 56); } else { CurBufferPtr = BufferEnd; } @@ -152,14 +152,14 @@ public: /// void emitDWordBE(uint64_t W) { if (8 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 56); - *CurBufferPtr++ = (uint8_t)(W >> 48); - *CurBufferPtr++ = (uint8_t)(W >> 40); - *CurBufferPtr++ = (uint8_t)(W >> 32); - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 0); + *CurBufferPtr++ = (unsigned char)(W >> 56); + *CurBufferPtr++ = (unsigned char)(W >> 48); + *CurBufferPtr++ = (unsigned char)(W >> 40); + *CurBufferPtr++ = (unsigned char)(W >> 32); + *CurBufferPtr++ = (unsigned char)(W >> 24); + *CurBufferPtr++ = (unsigned char)(W >> 16); + *CurBufferPtr++ = (unsigned char)(W >> 8); + *CurBufferPtr++ = (unsigned char)(W >> 0); } else { CurBufferPtr = BufferEnd; } @@ -173,8 +173,8 @@ public: if(Alignment <= (uintptr_t)(BufferEnd-CurBufferPtr)) { // Move the current buffer ptr up to the specified alignment. CurBufferPtr = - (uint8_t*)(((uintptr_t)CurBufferPtr+Alignment-1) & - ~(uintptr_t)(Alignment-1)); + (unsigned char*)(((uintptr_t)CurBufferPtr+Alignment-1) & + ~(uintptr_t)(Alignment-1)); } else { CurBufferPtr = BufferEnd; } @@ -185,7 +185,7 @@ public: /// written to the output stream. void emitULEB128Bytes(unsigned Value) { do { - uint8_t Byte = Value & 0x7f; + unsigned char Byte = Value & 0x7f; Value >>= 7; if (Value) Byte |= 0x80; emitByte(Byte); @@ -194,12 +194,12 @@ public: /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be /// written to the output stream. - void emitSLEB128Bytes(int32_t Value) { - int32_t Sign = Value >> (8 * sizeof(Value) - 1); + void emitSLEB128Bytes(int Value) { + int Sign = Value >> (8 * sizeof(Value) - 1); bool IsMore; do { - uint8_t Byte = Value & 0x7f; + unsigned char Byte = Value & 0x7f; Value >>= 7; IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; if (IsMore) Byte |= 0x80; @@ -212,14 +212,14 @@ public: void emitString(const std::string &String) { for (unsigned i = 0, N = static_cast<unsigned>(String.size()); i < N; ++i) { - uint8_t C = String[i]; + unsigned char C = String[i]; emitByte(C); } emitByte(0); } /// emitInt32 - Emit a int32 directive. - void emitInt32(int32_t Value) { + void emitInt32(int Value) { if (4 <= BufferEnd-CurBufferPtr) { *((uint32_t*)CurBufferPtr) = Value; CurBufferPtr += 4; diff --git a/include/llvm/ExecutionEngine/JITMemoryManager.h b/include/llvm/ExecutionEngine/JITMemoryManager.h index 688a162..581300e 100644 --- a/include/llvm/ExecutionEngine/JITMemoryManager.h +++ b/include/llvm/ExecutionEngine/JITMemoryManager.h @@ -60,7 +60,7 @@ public: /// getGOTBase - If this is managing a Global Offset Table, this method should /// return a pointer to its base. - virtual uint8_t *getGOTBase() const = 0; + virtual unsigned char *getGOTBase() const = 0; /// SetDlsymTable - If the JIT must be able to relocate stubs after they have /// been emitted, potentially because they are being copied to a process @@ -89,8 +89,8 @@ public: /// emit the function, so it doesn't pass in the size. Instead, this method /// is required to pass back a "valid size". The JIT will be careful to not /// write more than the returned ActualSize bytes of memory. - virtual uint8_t *startFunctionBody(const Function *F, - uintptr_t &ActualSize) = 0; + virtual unsigned char *startFunctionBody(const Function *F, + uintptr_t &ActualSize) = 0; /// allocateStub - This method is called by the JIT to allocate space for a /// function stub (used to handle limited branch displacements) while it is @@ -100,8 +100,9 @@ public: /// thunk for it. The stub should be "close" to the current function body, /// but should not be included in the 'actualsize' returned by /// startFunctionBody. - virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, - unsigned Alignment) = 0; + virtual unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize, + unsigned Alignment) =0; + /// endFunctionBody - This method is called when the JIT is done codegen'ing /// the specified function. At this point we know the size of the JIT @@ -109,11 +110,11 @@ public: /// the startFunctionBody method) and FunctionEnd which is a pointer to the /// actual end of the function. This method should mark the space allocated /// and remember where it is in case the client wants to deallocate it. - virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) = 0; + virtual void endFunctionBody(const Function *F, unsigned char *FunctionStart, + unsigned char *FunctionEnd) = 0; /// allocateSpace - Allocate a memory block of the given size. - virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) = 0; + virtual unsigned char *allocateSpace(intptr_t Size, unsigned Alignment) = 0; /// deallocateMemForFunction - Free JIT memory for the specified function. /// This is never called when the JIT is currently emitting a function. @@ -121,13 +122,14 @@ public: /// startExceptionTable - When we finished JITing the function, if exception /// handling is set, we emit the exception table. - virtual uint8_t* startExceptionTable(const Function* F, - uintptr_t &ActualSize) = 0; + virtual unsigned char* startExceptionTable(const Function* F, + uintptr_t &ActualSize) = 0; /// endExceptionTable - This method is called when the JIT is done emitting /// the exception table. - virtual void endExceptionTable(const Function *F, uint8_t *TableStart, - uint8_t *TableEnd, uint8_t* FrameRegister) = 0; + virtual void endExceptionTable(const Function *F, unsigned char *TableStart, + unsigned char *TableEnd, + unsigned char* FrameRegister) = 0; }; } // end namespace llvm. diff --git a/include/llvm/Support/StandardPasses.h b/include/llvm/Support/StandardPasses.h new file mode 100644 index 0000000..024c019 --- /dev/null +++ b/include/llvm/Support/StandardPasses.h @@ -0,0 +1,250 @@ +//===-- llvm/Support/StandardPasses.h - Standard pass lists -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines utility functions for creating a "standard" set of +// optimization passes, so that compilers and tools which use optimization +// passes use the same set of standard passes. +// +// These are implemented as inline functions so that we do not have to worry +// about link issues. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_STANDARDPASSES_H +#define LLVM_SUPPORT_STANDARDPASSES_H + +#include "llvm/PassManager.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/IPO.h" + +namespace llvm { + /// createStandardFunctionPasses - Add the standard list of function passes to + /// the provided pass manager. + /// + /// \arg OptimizationLevel - The optimization level, corresponding to -O0, + /// -O1, etc. + static inline void createStandardFunctionPasses(FunctionPassManager *PM, + unsigned OptimizationLevel); + + /// createStandardModulePasses - Add the standard list of module passes to the + /// provided pass manager. + /// + /// \arg OptimizationLevel - The optimization level, corresponding to -O0, + /// -O1, etc. + /// \arg OptimizeSize - Whether the transformations should optimize for size. + /// \arg UnitAtATime - Allow passes which may make global module changes. + /// \arg UnrollLoops - Allow loop unrolling. + /// \arg SimplifyLibCalls - Allow library calls to be simplified. + /// \arg HaveExceptions - Whether the module may have code using exceptions. + /// \arg InliningPass - The inlining pass to use, if any, or null. This will + /// always be added, even at -O0.a + static inline void createStandardModulePasses(PassManager *PM, + unsigned OptimizationLevel, + bool OptimizeSize, + bool UnitAtATime, + bool UnrollLoops, + bool SimplifyLibCalls, + bool HaveExceptions, + Pass *InliningPass); + + /// createStandardLTOPasses - Add the standard list of module passes suitable + /// for link time optimization. + /// + /// Internalize - Run the internalize pass. + /// RunInliner - Use a function inlining pass. + /// RunSecondGlobalOpt - Run the global optimizer pass twice. + /// VerifyEach - Run the verifier after each pass. + // + // FIXME: RunSecondGlobalOpt should go away once we resolve which of LTO or + // llvm-ld is better. + static inline void createStandardLTOPasses(PassManager *PM, + bool Internalize, + bool RunInliner, + bool RunSecondGlobalOpt, + bool VerifyEach); + + // Implementations + + static inline void createStandardFunctionPasses(FunctionPassManager *PM, + unsigned OptimizationLevel) { + if (OptimizationLevel > 0) { + PM->add(createCFGSimplificationPass()); + if (OptimizationLevel == 1) + PM->add(createPromoteMemoryToRegisterPass()); + else + PM->add(createScalarReplAggregatesPass()); + PM->add(createInstructionCombiningPass()); + } + } + + static inline void createStandardModulePasses(PassManager *PM, + unsigned OptimizationLevel, + bool OptimizeSize, + bool UnitAtATime, + bool UnrollLoops, + bool SimplifyLibCalls, + bool HaveExceptions, + Pass *InliningPass) { + if (OptimizationLevel == 0) { + if (InliningPass) + PM->add(InliningPass); + } else { + if (UnitAtATime) + PM->add(createRaiseAllocationsPass()); // call %malloc -> malloc inst + PM->add(createCFGSimplificationPass()); // Clean up disgusting code + // Kill useless allocas + PM->add(createPromoteMemoryToRegisterPass()); + if (UnitAtATime) { + PM->add(createGlobalOptimizerPass()); // Optimize out global vars + PM->add(createGlobalDCEPass()); // Remove unused fns and globs + // IP Constant Propagation + PM->add(createIPConstantPropagationPass()); + PM->add(createDeadArgEliminationPass()); // Dead argument elimination + } + PM->add(createInstructionCombiningPass()); // Clean up after IPCP & DAE + PM->add(createCFGSimplificationPass()); // Clean up after IPCP & DAE + if (UnitAtATime) { + if (HaveExceptions) + PM->add(createPruneEHPass()); // Remove dead EH info + PM->add(createFunctionAttrsPass()); // Set readonly/readnone attrs + } + if (InliningPass) + PM->add(InliningPass); + if (OptimizationLevel > 2) + PM->add(createArgumentPromotionPass()); // Scalarize uninlined fn args + if (SimplifyLibCalls) + PM->add(createSimplifyLibCallsPass()); // Library Call Optimizations + PM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl. + PM->add(createJumpThreadingPass()); // Thread jumps. + PM->add(createCFGSimplificationPass()); // Merge & remove BBs + PM->add(createScalarReplAggregatesPass()); // Break up aggregate allocas + PM->add(createInstructionCombiningPass()); // Combine silly seq's + PM->add(createCondPropagationPass()); // Propagate conditionals + PM->add(createTailCallEliminationPass()); // Eliminate tail calls + PM->add(createCFGSimplificationPass()); // Merge & remove BBs + PM->add(createReassociatePass()); // Reassociate expressions + PM->add(createLoopRotatePass()); // Rotate Loop + PM->add(createLICMPass()); // Hoist loop invariants + PM->add(createLoopUnswitchPass(OptimizeSize)); + PM->add(createLoopIndexSplitPass()); // Split loop index + PM->add(createInstructionCombiningPass()); + PM->add(createIndVarSimplifyPass()); // Canonicalize indvars + PM->add(createLoopDeletionPass()); // Delete dead loops + if (UnrollLoops) + PM->add(createLoopUnrollPass()); // Unroll small loops + PM->add(createInstructionCombiningPass()); // Clean up after the unroller + PM->add(createGVNPass()); // Remove redundancies + PM->add(createMemCpyOptPass()); // Remove memcpy / form memset + PM->add(createSCCPPass()); // Constant prop with SCCP + + // Run instcombine after redundancy elimination to exploit opportunities + // opened up by them. + PM->add(createInstructionCombiningPass()); + PM->add(createCondPropagationPass()); // Propagate conditionals + PM->add(createDeadStoreEliminationPass()); // Delete dead stores + PM->add(createAggressiveDCEPass()); // Delete dead instructions + PM->add(createCFGSimplificationPass()); // Merge & remove BBs + + if (UnitAtATime) { + PM->add(createStripDeadPrototypesPass()); // Get rid of dead prototypes + PM->add(createDeadTypeEliminationPass()); // Eliminate dead types + } + + if (OptimizationLevel > 1 && UnitAtATime) + PM->add(createConstantMergePass()); // Merge dup global constants + } + } + + static inline void addOnePass(PassManager *PM, Pass *P, bool AndVerify) { + PM->add(P); + + if (AndVerify) + PM->add(createVerifierPass()); + } + + static inline void createStandardLTOPasses(PassManager *PM, + bool Internalize, + bool RunInliner, + bool RunSecondGlobalOpt, + bool VerifyEach) { + // Now that composite has been compiled, scan through the module, looking + // for a main function. If main is defined, mark all other functions + // internal. + if (Internalize) + addOnePass(PM, createInternalizePass(true), VerifyEach); + + // Propagate constants at call sites into the functions they call. This + // opens opportunities for globalopt (and inlining) by substituting function + // pointers passed as arguments to direct uses of functions. + addOnePass(PM, createIPSCCPPass(), VerifyEach); + + // Now that we internalized some globals, see if we can hack on them! + addOnePass(PM, createGlobalOptimizerPass(), VerifyEach); + + // Linking modules together can lead to duplicated global constants, only + // keep one copy of each constant... + addOnePass(PM, createConstantMergePass(), VerifyEach); + + // Remove unused arguments from functions... + addOnePass(PM, createDeadArgEliminationPass(), VerifyEach); + + // Reduce the code after globalopt and ipsccp. Both can open up significant + // simplification opportunities, and both can propagate functions through + // function pointers. When this happens, we often have to resolve varargs + // calls, etc, so let instcombine do this. + addOnePass(PM, createInstructionCombiningPass(), VerifyEach); + + // Inline small functions + if (RunInliner) + addOnePass(PM, createFunctionInliningPass(), VerifyEach); + + addOnePass(PM, createPruneEHPass(), VerifyEach); // Remove dead EH info. + // Optimize globals again. + if (RunSecondGlobalOpt) + addOnePass(PM, createGlobalOptimizerPass(), VerifyEach); + addOnePass(PM, createGlobalDCEPass(), VerifyEach); // Remove dead functions. + + // If we didn't decide to inline a function, check to see if we can + // transform it to pass arguments by value instead of by reference. + addOnePass(PM, createArgumentPromotionPass(), VerifyEach); + + // The IPO passes may leave cruft around. Clean up after them. + addOnePass(PM, createInstructionCombiningPass(), VerifyEach); + addOnePass(PM, createJumpThreadingPass(), VerifyEach); + // Break up allocas + addOnePass(PM, createScalarReplAggregatesPass(), VerifyEach); + + // Run a few AA driven optimizations here and now, to cleanup the code. + addOnePass(PM, createFunctionAttrsPass(), VerifyEach); // Add nocapture. + addOnePass(PM, createGlobalsModRefPass(), VerifyEach); // IP alias analysis. + + addOnePass(PM, createLICMPass(), VerifyEach); // Hoist loop invariants. + addOnePass(PM, createGVNPass(), VerifyEach); // Remove redundancies. + addOnePass(PM, createMemCpyOptPass(), VerifyEach); // Remove dead memcpys. + // Nuke dead stores. + addOnePass(PM, createDeadStoreEliminationPass(), VerifyEach); + + // Cleanup and simplify the code after the scalar optimizations. + addOnePass(PM, createInstructionCombiningPass(), VerifyEach); + + addOnePass(PM, createJumpThreadingPass(), VerifyEach); + // Cleanup jump threading. + addOnePass(PM, createPromoteMemoryToRegisterPass(), VerifyEach); + + // Delete basic blocks, which optimization passes may have killed... + addOnePass(PM, createCFGSimplificationPass(), VerifyEach); + + // Now that we have optimized the program, discard unreachable functions. + addOnePass(PM, createGlobalDCEPass(), VerifyEach); + } +} + +#endif diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index ca4b31c..ff917a7 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -3,6 +3,7 @@ add_llvm_library(LLVMCodeGen CodePlacementOpt.cpp DeadMachineInstructionElim.cpp DwarfEHPrepare.cpp + ELFCodeEmitter.cpp ELFWriter.cpp GCMetadata.cpp GCMetadataPrinter.cpp @@ -16,6 +17,7 @@ add_llvm_library(LLVMCodeGen LiveStackAnalysis.cpp LiveVariables.cpp LowerSubregs.cpp + MachOCodeEmitter.cpp MachOWriter.cpp MachineBasicBlock.cpp MachineDominators.cpp diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp new file mode 100644 index 0000000..0a0245f --- /dev/null +++ b/lib/CodeGen/ELFCodeEmitter.cpp @@ -0,0 +1,94 @@ +//===-- lib/CodeGen/ELFCodeEmitter.cpp ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ELFCodeEmitter.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/OutputBuffer.h" + +//===----------------------------------------------------------------------===// +// ELFCodeEmitter Implementation +//===----------------------------------------------------------------------===// + +namespace llvm { + +/// startFunction - This callback is invoked when a new machine function is +/// about to be emitted. +void ELFCodeEmitter::startFunction(MachineFunction &F) { + // Align the output buffer to the appropriate alignment. + unsigned Align = 16; // FIXME: GENERICIZE!! + // Get the ELF Section that this function belongs in. + ES = &EW.getSection(".text", ELFWriter::ELFSection::SHT_PROGBITS, + ELFWriter::ELFSection::SHF_EXECINSTR | + ELFWriter::ELFSection::SHF_ALLOC); + OutBuffer = &ES->SectionData; + cerr << "FIXME: This code needs to be updated for changes in the " + << "CodeEmitter interfaces. In particular, this should set " + << "BufferBegin/BufferEnd/CurBufferPtr, not deal with OutBuffer!"; + abort(); + + // Upgrade the section alignment if required. + if (ES->Align < Align) ES->Align = Align; + + // Add padding zeros to the end of the buffer to make sure that the + // function will start on the correct byte alignment within the section. + OutputBuffer OB(*OutBuffer, + TM.getTargetData()->getPointerSizeInBits() == 64, + TM.getTargetData()->isLittleEndian()); + OB.align(Align); + FnStart = OutBuffer->size(); +} + +/// finishFunction - This callback is invoked after the function is completely +/// finished. +bool ELFCodeEmitter::finishFunction(MachineFunction &F) { + // We now know the size of the function, add a symbol to represent it. + ELFWriter::ELFSym FnSym(F.getFunction()); + + // Figure out the binding (linkage) of the symbol. + switch (F.getFunction()->getLinkage()) { + default: + // appending linkage is illegal for functions. + assert(0 && "Unknown linkage type!"); + case GlobalValue::ExternalLinkage: + FnSym.SetBind(ELFWriter::ELFSym::STB_GLOBAL); + break; + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + FnSym.SetBind(ELFWriter::ELFSym::STB_WEAK); + break; + case GlobalValue::PrivateLinkage: + assert (0 && "PrivateLinkage should not be in the symbol table."); + case GlobalValue::InternalLinkage: + FnSym.SetBind(ELFWriter::ELFSym::STB_LOCAL); + break; + } + + ES->Size = OutBuffer->size(); + + FnSym.SetType(ELFWriter::ELFSym::STT_FUNC); + FnSym.SectionIdx = ES->SectionIdx; + FnSym.Value = FnStart; // Value = Offset from start of Section. + FnSym.Size = OutBuffer->size()-FnStart; + + // Finally, add it to the symtab. + EW.SymbolTable.push_back(FnSym); + return false; +} + +} // end namespace llvm diff --git a/lib/CodeGen/ELFCodeEmitter.h b/lib/CodeGen/ELFCodeEmitter.h new file mode 100644 index 0000000..11ebcc8 --- /dev/null +++ b/lib/CodeGen/ELFCodeEmitter.h @@ -0,0 +1,87 @@ +//===-- lib/CodeGen/ELFCodeEmitter.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef ELFCODEEMITTER_H +#define ELFCODEEMITTER_H + +#include "ELFWriter.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include <vector> + +namespace llvm { + + /// ELFCodeEmitter - This class is used by the ELFWriter to + /// emit the code for functions to the ELF file. + class ELFCodeEmitter : public MachineCodeEmitter { + ELFWriter &EW; + TargetMachine &TM; + ELFWriter::ELFSection *ES; // Section to write to. + std::vector<unsigned char> *OutBuffer; + size_t FnStart; + public: + explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM), OutBuffer(0) {} + + void startFunction(MachineFunction &F); + bool finishFunction(MachineFunction &F); + + void addRelocation(const MachineRelocation &MR) { + assert(0 && "relo not handled yet!"); + } + + virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { + } + + virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const { + assert(0 && "CP not implementated yet!"); + return 0; + } + virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const { + assert(0 && "JT not implementated yet!"); + return 0; + } + + virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { + assert(0 && "JT not implementated yet!"); + return 0; + } + + virtual uintptr_t getLabelAddress(uint64_t Label) const { + assert(0 && "Label address not implementated yet!"); + abort(); + return 0; + } + + virtual void emitLabel(uint64_t LabelID) { + assert(0 && "emit Label not implementated yet!"); + abort(); + } + + virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { } + + /// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE! + void startGVStub(const GlobalValue* F, unsigned StubSize, + unsigned Alignment = 1) { + assert(0 && "JIT specific function called!"); + abort(); + } + void startGVStub(const GlobalValue* F, void *Buffer, unsigned StubSize) { + assert(0 && "JIT specific function called!"); + abort(); + } + void *finishGVStub(const GlobalValue *F) { + assert(0 && "JIT specific function called!"); + abort(); + return 0; + } +}; // end class ELFCodeEmitter + +} // end namespace llvm + +#endif + diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp index 7cc1162..be8edce 100644 --- a/lib/CodeGen/ELFWriter.cpp +++ b/lib/CodeGen/ELFWriter.cpp @@ -32,6 +32,7 @@ //===----------------------------------------------------------------------===// #include "ELFWriter.h" +#include "ELFCodeEmitter.h" #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/DerivedTypes.h" @@ -61,149 +62,10 @@ MachineCodeEmitter *llvm::AddELFWriter(PassManagerBase &PM, } //===----------------------------------------------------------------------===// -// ELFCodeEmitter Implementation -//===----------------------------------------------------------------------===// - -namespace llvm { - /// ELFCodeEmitter - This class is used by the ELFWriter to emit the code for - /// functions to the ELF file. - class ELFCodeEmitter : public MachineCodeEmitter { - ELFWriter &EW; - TargetMachine &TM; - ELFWriter::ELFSection *ES; // Section to write to. - std::vector<unsigned char> *OutBuffer; - size_t FnStart; - public: - explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM), OutBuffer(0) {} - - void startFunction(MachineFunction &F); - bool finishFunction(MachineFunction &F); - - void addRelocation(const MachineRelocation &MR) { - assert(0 && "relo not handled yet!"); - } - - virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { - } - - virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const { - assert(0 && "CP not implementated yet!"); - return 0; - } - virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const { - assert(0 && "JT not implementated yet!"); - return 0; - } - - virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { - assert(0 && "JT not implementated yet!"); - return 0; - } - - virtual uintptr_t getLabelAddress(uint64_t Label) const { - assert(0 && "Label address not implementated yet!"); - abort(); - return 0; - } - - virtual void emitLabel(uint64_t LabelID) { - assert(0 && "emit Label not implementated yet!"); - abort(); - } - - - virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { } - - - /// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE! - void startGVStub(const GlobalValue* F, unsigned StubSize, - unsigned Alignment = 1) { - assert(0 && "JIT specific function called!"); - abort(); - } - void startGVStub(const GlobalValue* F, void *Buffer, unsigned StubSize) { - assert(0 && "JIT specific function called!"); - abort(); - } - void *finishGVStub(const GlobalValue *F) { - assert(0 && "JIT specific function called!"); - abort(); - return 0; - } - }; -} - -/// startFunction - This callback is invoked when a new machine function is -/// about to be emitted. -void ELFCodeEmitter::startFunction(MachineFunction &F) { - // Align the output buffer to the appropriate alignment. - unsigned Align = 16; // FIXME: GENERICIZE!! - // Get the ELF Section that this function belongs in. - ES = &EW.getSection(".text", ELFWriter::ELFSection::SHT_PROGBITS, - ELFWriter::ELFSection::SHF_EXECINSTR | - ELFWriter::ELFSection::SHF_ALLOC); - OutBuffer = &ES->SectionData; - cerr << "FIXME: This code needs to be updated for changes in the " - << "CodeEmitter interfaces. In particular, this should set " - << "BufferBegin/BufferEnd/CurBufferPtr, not deal with OutBuffer!"; - abort(); - - // Upgrade the section alignment if required. - if (ES->Align < Align) ES->Align = Align; - - // Add padding zeros to the end of the buffer to make sure that the - // function will start on the correct byte alignment within the section. - OutputBuffer OB(*OutBuffer, - TM.getTargetData()->getPointerSizeInBits() == 64, - TM.getTargetData()->isLittleEndian()); - OB.align(Align); - FnStart = OutBuffer->size(); -} - -/// finishFunction - This callback is invoked after the function is completely -/// finished. -bool ELFCodeEmitter::finishFunction(MachineFunction &F) { - // We now know the size of the function, add a symbol to represent it. - ELFWriter::ELFSym FnSym(F.getFunction()); - - // Figure out the binding (linkage) of the symbol. - switch (F.getFunction()->getLinkage()) { - default: - // appending linkage is illegal for functions. - assert(0 && "Unknown linkage type!"); - case GlobalValue::ExternalLinkage: - FnSym.SetBind(ELFWriter::ELFSym::STB_GLOBAL); - break; - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - FnSym.SetBind(ELFWriter::ELFSym::STB_WEAK); - break; - case GlobalValue::PrivateLinkage: - assert (0 && "PrivateLinkage should not be in the symbol table."); - case GlobalValue::InternalLinkage: - FnSym.SetBind(ELFWriter::ELFSym::STB_LOCAL); - break; - } - - ES->Size = OutBuffer->size(); - - FnSym.SetType(ELFWriter::ELFSym::STT_FUNC); - FnSym.SectionIdx = ES->SectionIdx; - FnSym.Value = FnStart; // Value = Offset from start of Section. - FnSym.Size = OutBuffer->size()-FnStart; - - // Finally, add it to the symtab. - EW.SymbolTable.push_back(FnSym); - return false; -} - -//===----------------------------------------------------------------------===// // ELFWriter Implementation //===----------------------------------------------------------------------===// -ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm) +ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm) : MachineFunctionPass(&ID), O(o), TM(tm) { e_flags = 0; // e_flags defaults to 0, no flags. diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp index d3b0820..89131a0 100644 --- a/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -551,7 +551,7 @@ namespace { // When outputting a function stub in the context of some other function, we // save BufferBegin/BufferEnd/CurBufferPtr here. - uint8_t *SavedBufferBegin, *SavedBufferEnd, *SavedCurBufferPtr; + unsigned char *SavedBufferBegin, *SavedBufferEnd, *SavedCurBufferPtr; /// Relocations - These are the relocations that the function needs, as /// emitted. @@ -1056,11 +1056,11 @@ bool JITEmitter::finishFunction(MachineFunction &F) { // FnStart is the start of the text, not the start of the constant pool and // other per-function data. - uint8_t *FnStart = - (uint8_t *)TheJIT->getPointerToGlobalIfAvailable(F.getFunction()); + unsigned char *FnStart = + (unsigned char *)TheJIT->getPointerToGlobalIfAvailable(F.getFunction()); // FnEnd is the end of the function's machine code. - uint8_t *FnEnd = CurBufferPtr; + unsigned char *FnEnd = CurBufferPtr; if (!Relocations.empty()) { CurFn = F.getFunction(); @@ -1183,7 +1183,7 @@ bool JITEmitter::finishFunction(MachineFunction &F) { } else { DOUT << "JIT: Binary code:\n"; DOUT << std::hex; - uint8_t* q = FnStart; + unsigned char* q = FnStart; for (int i = 0; q < FnEnd; q += 4, ++i) { if (i == 4) i = 0; @@ -1221,7 +1221,7 @@ bool JITEmitter::finishFunction(MachineFunction &F) { BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(), ActualSize); BufferEnd = BufferBegin+ActualSize; - uint8_t* FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd); + unsigned char* FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd); MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr, FrameRegister); BufferBegin = SavedBufferBegin; @@ -1416,7 +1416,7 @@ void JITEmitter::startGVStub(const GlobalValue* GV, void *Buffer, SavedBufferEnd = BufferEnd; SavedCurBufferPtr = CurBufferPtr; - BufferBegin = CurBufferPtr = (uint8_t *)Buffer; + BufferBegin = CurBufferPtr = (unsigned char *)Buffer; BufferEnd = BufferBegin+StubSize+1; } diff --git a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp index 70ccdcc..2819b6d 100644 --- a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp +++ b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp @@ -257,9 +257,9 @@ namespace { // When emitting code into a memory block, this is the block. MemoryRangeHeader *CurBlock; - uint8_t *CurStubPtr, *StubBase; - uint8_t *GOTBase; // Target Specific reserved memory - void *DlsymTable; // Stub external symbol information + unsigned char *CurStubPtr, *StubBase; + unsigned char *GOTBase; // Target Specific reserved memory + void *DlsymTable; // Stub external symbol information // Centralize memory block allocation. sys::MemoryBlock getNewMemoryBlock(unsigned size); @@ -273,12 +273,12 @@ namespace { void AllocateGOT(); void SetDlsymTable(void *); - uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, - unsigned Alignment); + unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize, + unsigned Alignment); /// startFunctionBody - When a function starts, allocate a block of free /// executable memory, returning a pointer to it and its actual size. - uint8_t *startFunctionBody(const Function *F, uintptr_t &ActualSize) { + unsigned char *startFunctionBody(const Function *F, uintptr_t &ActualSize) { FreeRangeHeader* candidateBlock = FreeMemoryList; FreeRangeHeader* head = FreeMemoryList; @@ -301,18 +301,18 @@ namespace { // Allocate the entire memory block. FreeMemoryList = candidateBlock->AllocateBlock(); ActualSize = CurBlock->BlockSize-sizeof(MemoryRangeHeader); - return (uint8_t *)(CurBlock+1); + return (unsigned char *)(CurBlock+1); } /// endFunctionBody - The function F is now allocated, and takes the memory /// in the range [FunctionStart,FunctionEnd). - void endFunctionBody(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) { + void endFunctionBody(const Function *F, unsigned char *FunctionStart, + unsigned char *FunctionEnd) { assert(FunctionEnd > FunctionStart); - assert(FunctionStart == (uint8_t *)(CurBlock+1) && + assert(FunctionStart == (unsigned char *)(CurBlock+1) && "Mismatched function start/end!"); - uintptr_t BlockSize = FunctionEnd - (uint8_t *)CurBlock; + uintptr_t BlockSize = FunctionEnd - (unsigned char *)CurBlock; FunctionBlocks[F] = CurBlock; // Release the memory at the end of this block that isn't needed. @@ -320,17 +320,17 @@ namespace { } /// allocateSpace - Allocate a memory block of the given size. - uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { + unsigned char *allocateSpace(intptr_t Size, unsigned Alignment) { CurBlock = FreeMemoryList; FreeMemoryList = FreeMemoryList->AllocateBlock(); - uint8_t *result = (uint8_t *)CurBlock+1; + unsigned char *result = (unsigned char *)CurBlock+1; if (Alignment == 0) Alignment = 1; - result = (uint8_t*)(((intptr_t)result+Alignment-1) & + result = (unsigned char*)(((intptr_t)result+Alignment-1) & ~(intptr_t)(Alignment-1)); - uintptr_t BlockSize = result + Size - (uint8_t *)CurBlock; + uintptr_t BlockSize = result + Size - (unsigned char *)CurBlock; FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize); return result; @@ -338,26 +338,28 @@ namespace { /// startExceptionTable - Use startFunctionBody to allocate memory for the /// function's exception table. - uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize) { + unsigned char* startExceptionTable(const Function* F, + uintptr_t &ActualSize) { return startFunctionBody(F, ActualSize); } /// endExceptionTable - The exception table of F is now allocated, /// and takes the memory in the range [TableStart,TableEnd). - void endExceptionTable(const Function *F, uint8_t *TableStart, - uint8_t *TableEnd, uint8_t* FrameRegister) { + void endExceptionTable(const Function *F, unsigned char *TableStart, + unsigned char *TableEnd, + unsigned char* FrameRegister) { assert(TableEnd > TableStart); - assert(TableStart == (uint8_t *)(CurBlock+1) && + assert(TableStart == (unsigned char *)(CurBlock+1) && "Mismatched table start/end!"); - uintptr_t BlockSize = TableEnd - (uint8_t *)CurBlock; + uintptr_t BlockSize = TableEnd - (unsigned char *)CurBlock; TableBlocks[F] = CurBlock; // Release the memory at the end of this block that isn't needed. FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize); } - uint8_t *getGOTBase() const { + unsigned char *getGOTBase() const { return GOTBase; } @@ -431,7 +433,7 @@ DefaultJITMemoryManager::DefaultJITMemoryManager() { sys::MemoryBlock MemBlock = getNewMemoryBlock(16 << 20); #endif - uint8_t *MemBase = static_cast<uint8_t*>(MemBlock.base()); + unsigned char *MemBase = static_cast<unsigned char*>(MemBlock.base()); // Allocate stubs backwards from the base, allocate functions forward // from the base. @@ -490,7 +492,7 @@ DefaultJITMemoryManager::DefaultJITMemoryManager() { void DefaultJITMemoryManager::AllocateGOT() { assert(GOTBase == 0 && "Cannot allocate the got multiple times"); - GOTBase = new uint8_t[sizeof(void*) * 8192]; + GOTBase = new unsigned char[sizeof(void*) * 8192]; HasGOT = true; } @@ -506,12 +508,12 @@ DefaultJITMemoryManager::~DefaultJITMemoryManager() { Blocks.clear(); } -uint8_t *DefaultJITMemoryManager::allocateStub(const GlobalValue* F, +unsigned char *DefaultJITMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize, unsigned Alignment) { CurStubPtr -= StubSize; - CurStubPtr = (uint8_t*)(((intptr_t)CurStubPtr) & - ~(intptr_t)(Alignment-1)); + CurStubPtr = (unsigned char*)(((intptr_t)CurStubPtr) & + ~(intptr_t)(Alignment-1)); if (CurStubPtr < StubBase) { // FIXME: allocate a new block fprintf(stderr, "JIT ran out of memory for function stubs!\n"); diff --git a/lib/Target/Alpha/AlphaISelDAGToDAG.cpp b/lib/Target/Alpha/AlphaISelDAGToDAG.cpp index affcd3e..e3f631a 100644 --- a/lib/Target/Alpha/AlphaISelDAGToDAG.cpp +++ b/lib/Target/Alpha/AlphaISelDAGToDAG.cpp @@ -185,8 +185,20 @@ namespace { #include "AlphaGenDAGISel.inc" private: - SDValue getGlobalBaseReg(); - SDValue getGlobalRetAddr(); + /// getTargetMachine - Return a reference to the TargetMachine, casted + /// to the target-specific type. + const AlphaTargetMachine &getTargetMachine() { + return static_cast<const AlphaTargetMachine &>(TM); + } + + /// getInstrInfo - Return a reference to the TargetInstrInfo, casted + /// to the target-specific type. + const AlphaInstrInfo *getInstrInfo() { + return getTargetMachine().getInstrInfo(); + } + + SDNode *getGlobalBaseReg(); + SDNode *getGlobalRetAddr(); void SelectCALL(SDValue Op); }; @@ -195,34 +207,18 @@ private: /// getGlobalBaseReg - Output the instructions required to put the /// GOT address into a register. /// -SDValue AlphaDAGToDAGISel::getGlobalBaseReg() { - unsigned GP = 0; - for(MachineRegisterInfo::livein_iterator ii = RegInfo->livein_begin(), - ee = RegInfo->livein_end(); ii != ee; ++ii) - if (ii->first == Alpha::R29) { - GP = ii->second; - break; - } - assert(GP && "GOT PTR not in liveins"); - // FIXME is there anywhere sensible to get a DebugLoc here? - return CurDAG->getCopyFromReg(CurDAG->getEntryNode(), - DebugLoc::getUnknownLoc(), GP, MVT::i64); +SDNode *AlphaDAGToDAGISel::getGlobalBaseReg() { + MachineFunction *MF = BB->getParent(); + unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF); + return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); } -/// getRASaveReg - Grab the return address +/// getGlobalRetAddr - Grab the return address. /// -SDValue AlphaDAGToDAGISel::getGlobalRetAddr() { - unsigned RA = 0; - for(MachineRegisterInfo::livein_iterator ii = RegInfo->livein_begin(), - ee = RegInfo->livein_end(); ii != ee; ++ii) - if (ii->first == Alpha::R26) { - RA = ii->second; - break; - } - assert(RA && "RA PTR not in liveins"); - // FIXME is there anywhere sensible to get a DebugLoc here? - return CurDAG->getCopyFromReg(CurDAG->getEntryNode(), - DebugLoc::getUnknownLoc(), RA, MVT::i64); +SDNode *AlphaDAGToDAGISel::getGlobalRetAddr() { + MachineFunction *MF = BB->getParent(); + unsigned GlobalRetAddr = getInstrInfo()->getGlobalRetAddr(MF); + return CurDAG->getRegister(GlobalRetAddr, TLI.getPointerTy()).getNode(); } /// InstructionSelect - This callback is invoked by @@ -256,16 +252,10 @@ SDNode *AlphaDAGToDAGISel::Select(SDValue Op) { CurDAG->getTargetFrameIndex(FI, MVT::i32), getI64Imm(0)); } - case ISD::GLOBAL_OFFSET_TABLE: { - SDValue Result = getGlobalBaseReg(); - ReplaceUses(Op, Result); - return NULL; - } - case AlphaISD::GlobalRetAddr: { - SDValue Result = getGlobalRetAddr(); - ReplaceUses(Op, Result); - return NULL; - } + case ISD::GLOBAL_OFFSET_TABLE: + return getGlobalBaseReg(); + case AlphaISD::GlobalRetAddr: + return getGlobalRetAddr(); case AlphaISD::DivCall: { SDValue Chain = CurDAG->getEntryNode(); @@ -315,7 +305,7 @@ SDNode *AlphaDAGToDAGISel::Select(SDValue Op) { ConstantInt *C = ConstantInt::get(Type::Int64Ty, uval); SDValue CPI = CurDAG->getTargetConstantPool(C, MVT::i64); SDNode *Tmp = CurDAG->getTargetNode(Alpha::LDAHr, dl, MVT::i64, CPI, - getGlobalBaseReg()); + SDValue(getGlobalBaseReg(), 0)); return CurDAG->SelectNodeTo(N, Alpha::LDQr, MVT::i64, MVT::Other, CPI, SDValue(Tmp, 0), CurDAG->getEntryNode()); } @@ -503,7 +493,7 @@ void AlphaDAGToDAGISel::SelectCALL(SDValue Op) { // Finally, once everything is in registers to pass to the call, emit the // call itself. if (Addr.getOpcode() == AlphaISD::GPRelLo) { - SDValue GOT = getGlobalBaseReg(); + SDValue GOT = SDValue(getGlobalBaseReg(), 0); Chain = CurDAG->getCopyToReg(Chain, dl, Alpha::R29, GOT, InFlag); InFlag = Chain.getValue(1); Chain = SDValue(CurDAG->getTargetNode(Alpha::BSR, dl, MVT::Other, diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp index 1001112..7ed8ef6 100644 --- a/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/lib/Target/Alpha/AlphaISelLowering.cpp @@ -223,9 +223,6 @@ static SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, SDValue Root = Op.getOperand(0); DebugLoc dl = Op.getDebugLoc(); - AddLiveIn(MF, Alpha::R29, &Alpha::GPRCRegClass); //GP - AddLiveIn(MF, Alpha::R26, &Alpha::GPRCRegClass); //RA - unsigned args_int[] = { Alpha::R16, Alpha::R17, Alpha::R18, Alpha::R19, Alpha::R20, Alpha::R21}; unsigned args_float[] = { diff --git a/lib/Target/Alpha/AlphaInstrInfo.cpp b/lib/Target/Alpha/AlphaInstrInfo.cpp index a54d97d..229f9d4 100644 --- a/lib/Target/Alpha/AlphaInstrInfo.cpp +++ b/lib/Target/Alpha/AlphaInstrInfo.cpp @@ -13,7 +13,9 @@ #include "Alpha.h" #include "AlphaInstrInfo.h" +#include "AlphaMachineFunctionInfo.h" #include "AlphaGenInstrInfo.inc" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -448,3 +450,54 @@ ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { return false; } +/// getGlobalBaseReg - Return a virtual register initialized with the +/// the global base register value. Output instructions required to +/// initialize the register in the function entry block, if necessary. +/// +unsigned AlphaInstrInfo::getGlobalBaseReg(MachineFunction *MF) const { + AlphaMachineFunctionInfo *AlphaFI = MF->getInfo<AlphaMachineFunctionInfo>(); + unsigned GlobalBaseReg = AlphaFI->getGlobalBaseReg(); + if (GlobalBaseReg != 0) + return GlobalBaseReg; + + // Insert the set of GlobalBaseReg into the first MBB of the function + MachineBasicBlock &FirstMBB = MF->front(); + MachineBasicBlock::iterator MBBI = FirstMBB.begin(); + MachineRegisterInfo &RegInfo = MF->getRegInfo(); + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + + GlobalBaseReg = RegInfo.createVirtualRegister(&Alpha::GPRCRegClass); + bool Ok = TII->copyRegToReg(FirstMBB, MBBI, GlobalBaseReg, Alpha::R29, + &Alpha::GPRCRegClass, &Alpha::GPRCRegClass); + assert(Ok && "Couldn't assign to global base register!"); + RegInfo.addLiveIn(Alpha::R29); + + AlphaFI->setGlobalBaseReg(GlobalBaseReg); + return GlobalBaseReg; +} + +/// getGlobalRetAddr - Return a virtual register initialized with the +/// the global base register value. Output instructions required to +/// initialize the register in the function entry block, if necessary. +/// +unsigned AlphaInstrInfo::getGlobalRetAddr(MachineFunction *MF) const { + AlphaMachineFunctionInfo *AlphaFI = MF->getInfo<AlphaMachineFunctionInfo>(); + unsigned GlobalRetAddr = AlphaFI->getGlobalRetAddr(); + if (GlobalRetAddr != 0) + return GlobalRetAddr; + + // Insert the set of GlobalRetAddr into the first MBB of the function + MachineBasicBlock &FirstMBB = MF->front(); + MachineBasicBlock::iterator MBBI = FirstMBB.begin(); + MachineRegisterInfo &RegInfo = MF->getRegInfo(); + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + + GlobalRetAddr = RegInfo.createVirtualRegister(&Alpha::GPRCRegClass); + bool Ok = TII->copyRegToReg(FirstMBB, MBBI, GlobalRetAddr, Alpha::R26, + &Alpha::GPRCRegClass, &Alpha::GPRCRegClass); + assert(Ok && "Couldn't assign to global return address register!"); + RegInfo.addLiveIn(Alpha::R26); + + AlphaFI->setGlobalRetAddr(GlobalRetAddr); + return GlobalRetAddr; +} diff --git a/lib/Target/Alpha/AlphaInstrInfo.h b/lib/Target/Alpha/AlphaInstrInfo.h index 182aa32..ea09885 100644 --- a/lib/Target/Alpha/AlphaInstrInfo.h +++ b/lib/Target/Alpha/AlphaInstrInfo.h @@ -90,6 +90,18 @@ public: MachineBasicBlock::iterator MI) const; bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const; bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const; + + /// getGlobalBaseReg - Return a virtual register initialized with the + /// the global base register value. Output instructions required to + /// initialize the register in the function entry block, if necessary. + /// + unsigned getGlobalBaseReg(MachineFunction *MF) const; + + /// getGlobalRetAddr - Return a virtual register initialized with the + /// the global return address register value. Output instructions required to + /// initialize the register in the function entry block, if necessary. + /// + unsigned getGlobalRetAddr(MachineFunction *MF) const; }; } diff --git a/lib/Target/Alpha/AlphaMachineFunctionInfo.h b/lib/Target/Alpha/AlphaMachineFunctionInfo.h new file mode 100644 index 0000000..47de5df --- /dev/null +++ b/lib/Target/Alpha/AlphaMachineFunctionInfo.h @@ -0,0 +1,48 @@ +//====- AlphaMachineFuctionInfo.h - Alpha machine function info -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares Alpha-specific per-machine-function information. +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHAMACHINEFUNCTIONINFO_H +#define ALPHAMACHINEFUNCTIONINFO_H + +#include "llvm/CodeGen/MachineFunction.h" + +namespace llvm { + +/// AlphaMachineFunctionInfo - This class is derived from MachineFunction +/// private Alpha target-specific information for each MachineFunction. +class AlphaMachineFunctionInfo : public MachineFunctionInfo { + /// GlobalBaseReg - keeps track of the virtual register initialized for + /// use as the global base register. This is used for PIC in some PIC + /// relocation models. + unsigned GlobalBaseReg; + + /// GlobalRetAddr = keeps track of the virtual register initialized for + /// the return address value. + unsigned GlobalRetAddr; + +public: + AlphaMachineFunctionInfo() : GlobalBaseReg(0), GlobalRetAddr(0) {} + + AlphaMachineFunctionInfo(MachineFunction &MF) : GlobalBaseReg(0), + GlobalRetAddr(0) {} + + unsigned getGlobalBaseReg() const { return GlobalBaseReg; } + void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; } + + unsigned getGlobalRetAddr() const { return GlobalRetAddr; } + void setGlobalRetAddr(unsigned Reg) { GlobalRetAddr = Reg; } +}; + +} // End llvm namespace + +#endif diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index f05ac70..53de1bb 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -70,7 +70,19 @@ private: // Include the pieces autogenerated from the target description. #include "MipsGenDAGISel.inc" - SDValue getGlobalBaseReg(); + /// getTargetMachine - Return a reference to the TargetMachine, casted + /// to the target-specific type. + const MipsTargetMachine &getTargetMachine() { + return static_cast<const MipsTargetMachine &>(TM); + } + + /// getInstrInfo - Return a reference to the TargetInstrInfo, casted + /// to the target-specific type. + const MipsInstrInfo *getInstrInfo() { + return getTargetMachine().getInstrInfo(); + } + + SDNode *getGlobalBaseReg(); SDNode *Select(SDValue N); // Complex Pattern. @@ -116,19 +128,10 @@ InstructionSelect() /// getGlobalBaseReg - Output the instructions required to put the /// GOT address into a register. -SDValue MipsDAGToDAGISel::getGlobalBaseReg() { - MachineFunction* MF = BB->getParent(); - unsigned GP = 0; - for(MachineRegisterInfo::livein_iterator ii = MF->getRegInfo().livein_begin(), - ee = MF->getRegInfo().livein_end(); ii != ee; ++ii) - if (ii->first == Mips::GP) { - GP = ii->second; - break; - } - assert(GP && "GOT PTR not in liveins"); - // FIXME is there a sensible place to get debug info for this? - return CurDAG->getCopyFromReg(CurDAG->getEntryNode(), - DebugLoc::getUnknownLoc(), GP, MVT::i32); +SDNode *MipsDAGToDAGISel::getGlobalBaseReg() { + MachineFunction *MF = BB->getParent(); + unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF); + return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); } /// ComplexPattern used on MipsInstrInfo @@ -321,11 +324,8 @@ Select(SDValue N) } // Get target GOT address. - case ISD::GLOBAL_OFFSET_TABLE: { - SDValue Result = getGlobalBaseReg(); - ReplaceUses(N, Result); - return NULL; - } + case ISD::GLOBAL_OFFSET_TABLE: + return getGlobalBaseReg(); /// Handle direct and indirect calls when using PIC. On PIC, when /// GOT is smaller than about 64k (small code) the GA target is diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 9281940..4517cfc 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -941,9 +941,6 @@ LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) unsigned StackReg = MF.getTarget().getRegisterInfo()->getFrameRegister(MF); - // GP must be live into PIC and non-PIC call target. - AddLiveIn(MF, Mips::GP, Mips::CPURegsRegisterClass); - // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs); diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index 6225fa9..92af973 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -13,8 +13,10 @@ #include "MipsInstrInfo.h" #include "MipsTargetMachine.h" +#include "MipsMachineFunction.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "MipsGenInstrInfo.inc" using namespace llvm; @@ -621,3 +623,30 @@ ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const Cond[0].setImm(GetOppositeBranchCondition((Mips::CondCode)Cond[0].getImm())); return false; } + +/// getGlobalBaseReg - Return a virtual register initialized with the +/// the global base register value. Output instructions required to +/// initialize the register in the function entry block, if necessary. +/// +unsigned MipsInstrInfo::getGlobalBaseReg(MachineFunction *MF) const { + MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>(); + unsigned GlobalBaseReg = MipsFI->getGlobalBaseReg(); + if (GlobalBaseReg != 0) + return GlobalBaseReg; + + // Insert the set of GlobalBaseReg into the first MBB of the function + MachineBasicBlock &FirstMBB = MF->front(); + MachineBasicBlock::iterator MBBI = FirstMBB.begin(); + MachineRegisterInfo &RegInfo = MF->getRegInfo(); + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + + GlobalBaseReg = RegInfo.createVirtualRegister(Mips::CPURegsRegisterClass); + bool Ok = TII->copyRegToReg(FirstMBB, MBBI, GlobalBaseReg, Mips::GP, + Mips::CPURegsRegisterClass, + Mips::CPURegsRegisterClass); + assert(Ok && "Couldn't assign to global base register!"); + RegInfo.addLiveIn(Mips::GP); + + MipsFI->setGlobalBaseReg(GlobalBaseReg); + return GlobalBaseReg; +} diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h index 334244e..6655c67 100644 --- a/lib/Target/Mips/MipsInstrInfo.h +++ b/lib/Target/Mips/MipsInstrInfo.h @@ -216,6 +216,12 @@ public: /// Insert nop instruction when hazard condition is found virtual void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const; + + /// getGlobalBaseReg - Return a virtual register initialized with the + /// the global base register value. Output instructions required to + /// initialize the register in the function entry block, if necessary. + /// + unsigned getGlobalBaseReg(MachineFunction *MF) const; }; } diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h index b95394e..ac3cdfd 100644 --- a/lib/Target/Mips/MipsMachineFunction.h +++ b/lib/Target/Mips/MipsMachineFunction.h @@ -75,11 +75,16 @@ private: /// holds the virtual register into which the sret argument is passed. unsigned SRetReturnReg; + /// GlobalBaseReg - keeps track of the virtual register initialized for + /// use as the global base register. This is used for PIC in some PIC + /// relocation models. + unsigned GlobalBaseReg; + public: MipsFunctionInfo(MachineFunction& MF) : FPStackOffset(0), RAStackOffset(0), CPUTopSavedRegOff(0), FPUTopSavedRegOff(0), GPHolder(-1,-1), HasLoadArgs(false), - HasStoreVarArgs(false), SRetReturnReg(0) + HasStoreVarArgs(false), SRetReturnReg(0), GlobalBaseReg(0) {} int getFPStackOffset() const { return FPStackOffset; } @@ -124,6 +129,9 @@ public: unsigned getSRetReturnReg() const { return SRetReturnReg; } void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } + + unsigned getGlobalBaseReg() const { return GlobalBaseReg; } + void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; } }; } // end of namespace llvm diff --git a/lib/Target/PIC16/PIC16.h b/lib/Target/PIC16/PIC16.h index 40bed2f..cf0f9db 100644 --- a/lib/Target/PIC16/PIC16.h +++ b/lib/Target/PIC16/PIC16.h @@ -300,9 +300,11 @@ namespace PIC16CC { case PIC16CC::LT: return "lt"; case PIC16CC::ULT: return "lt"; case PIC16CC::LE: return "le"; + case PIC16CC::ULE: return "le"; case PIC16CC::GT: return "gt"; case PIC16CC::UGT: return "gt"; case PIC16CC::GE: return "ge"; + case PIC16CC::UGE: return "ge"; } } diff --git a/lib/Target/PIC16/PIC16AsmPrinter.cpp b/lib/Target/PIC16/PIC16AsmPrinter.cpp index ef3bc4b..b42ee45 100644 --- a/lib/Target/PIC16/PIC16AsmPrinter.cpp +++ b/lib/Target/PIC16/PIC16AsmPrinter.cpp @@ -47,6 +47,7 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) { const Function *F = MF.getFunction(); CurrentFnName = Mang->getValueName(F); + DbgInfo.EmitFileDirective(F); // Emit the function variables. EmitFunctionFrame(MF); @@ -181,17 +182,11 @@ void PIC16AsmPrinter::printLibcallDecls(void) { bool PIC16AsmPrinter::doInitialization (Module &M) { bool Result = AsmPrinter::doInitialization(M); - DbgInfo.EmitFileDirective(M); // FIXME:: This is temporary solution to generate the include file. // The processor should be passed to llc as in input and the header file // should be generated accordingly. O << "\n\t#include P16F1937.INC\n"; - MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>(); - assert(MMI); - DwarfWriter *DW = getAnalysisIfAvailable<DwarfWriter>(); - assert(DW && "Dwarf Writer is not available"); - DW->BeginModule(&M, MMI, O, this, TAI); // Set the section names for all globals. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); @@ -199,13 +194,14 @@ bool PIC16AsmPrinter::doInitialization (Module &M) { I->setSection(TAI->SectionForGlobal(I)->getName()); } + DbgInfo.EmitFileDirective(M); EmitFunctionDecls(M); EmitUndefinedVars(M); EmitDefinedVars(M); EmitIData(M); EmitUData(M); EmitRomData(M); - DbgInfo.PopulateFunctsDI(M); + DbgInfo.PopulateFunctsDI(M); return Result; } @@ -285,7 +281,7 @@ void PIC16AsmPrinter::EmitRomData (Module &M) bool PIC16AsmPrinter::doFinalization(Module &M) { printLibcallDecls(); DbgInfo.EmitVarDebugInfo(M); - O << "\n\t" << ".EOF"; + DbgInfo.EmitEOF(); O << "\n\t" << "END\n"; bool Result = AsmPrinter::doFinalization(M); return Result; diff --git a/lib/Target/PIC16/PIC16DebugInfo.cpp b/lib/Target/PIC16/PIC16DebugInfo.cpp index 4d43811..faf4590 100644 --- a/lib/Target/PIC16/PIC16DebugInfo.cpp +++ b/lib/Target/PIC16/PIC16DebugInfo.cpp @@ -264,7 +264,29 @@ void PIC16DbgInfo::EmitFileDirective(Module &M) { if (CU) { DICompileUnit DIUnit(CU); std::string Dir, FN; - O << "\n\t.file\t\"" << DIUnit.getDirectory(Dir) <<"/" - << DIUnit.getFilename(FN) << "\"" ; + std::string File = DIUnit.getDirectory(Dir) + "/" + DIUnit.getFilename(FN); + O << "\n\t.file\t\"" << File << "\"\n" ; + CurFile = File; } } + +void PIC16DbgInfo::EmitFileDirective(const Function *F) { + std::string FunctName = F->getName(); + DISubprogram *SP = getFunctDI(FunctName); + if (SP) { + std::string Dir, FN; + DICompileUnit CU = SP->getCompileUnit(); + std::string File = CU.getDirectory(Dir) + "/" + CU.getFilename(FN); + if ( File != CurFile) { + EmitEOF(); + O << "\n\t.file\t\"" << File << "\"\n" ; + CurFile = File; + } + } +} + +void PIC16DbgInfo::EmitEOF() { + if (CurFile != "") + O << "\n\t.EOF"; +} + diff --git a/lib/Target/PIC16/PIC16DebugInfo.h b/lib/Target/PIC16/PIC16DebugInfo.h index 96b23da..be39393 100644 --- a/lib/Target/PIC16/PIC16DebugInfo.h +++ b/lib/Target/PIC16/PIC16DebugInfo.h @@ -94,8 +94,11 @@ namespace llvm { std::map <std::string, DISubprogram *> FunctNameMap; raw_ostream &O; const TargetAsmInfo *TAI; + std::string CurFile; public: - PIC16DbgInfo(raw_ostream &o, const TargetAsmInfo *T) : O(o), TAI(T) {} + PIC16DbgInfo(raw_ostream &o, const TargetAsmInfo *T) : O(o), TAI(T) { + CurFile = ""; + } ~PIC16DbgInfo(); void PopulateDebugInfo(DIType Ty, unsigned short &TypeNo, bool &HasAux, int Aux[], std::string &TypeName); @@ -109,6 +112,8 @@ namespace llvm { inline void EmitSymbol(std::string Name, int Class); void EmitVarDebugInfo(Module &M); void EmitFileDirective(Module &M); + void EmitFileDirective(const Function *F); + void EmitEOF(); }; } // end namespace llvm; #endif diff --git a/lib/Target/PIC16/PIC16ISelLowering.cpp b/lib/Target/PIC16/PIC16ISelLowering.cpp index 92fdcb2..0f83fd2 100644 --- a/lib/Target/PIC16/PIC16ISelLowering.cpp +++ b/lib/Target/PIC16/PIC16ISelLowering.cpp @@ -354,16 +354,29 @@ SDValue PIC16TargetLowering::ExpandFrameIndex(SDNode *N, SelectionDAG &DAG) { FrameIndexSDNode *FR = dyn_cast<FrameIndexSDNode>(SDValue(N,0)); // FIXME there isn't really debug info here DebugLoc dl = FR->getDebugLoc(); - int Index = FR->getIndex(); + // FIXME: Not used. + // int Index = FR->getIndex(); // Expand FrameIndex like GlobalAddress and ExternalSymbol // Also use Offset field for lo and hi parts. The default // offset is zero. + + /* SDValue Offset = DAG.getConstant(0, MVT::i8); SDValue FI = DAG.getTargetFrameIndex(Index, MVT::i8); SDValue Lo = DAG.getNode(PIC16ISD::Lo, dl, MVT::i8, FI, Offset); SDValue Hi = DAG.getNode(PIC16ISD::Hi, dl, MVT::i8, FI, Offset); return DAG.getNode(ISD::BUILD_PAIR, dl, N->getValueType(0), Lo, Hi); + */ + + SDValue ES; + int FrameOffset; + SDValue FI = SDValue(N,0); + LegalizeFrameIndex(FI, DAG, ES, FrameOffset); + SDValue Offset = DAG.getConstant(FrameOffset, MVT::i8); + SDValue Lo = DAG.getNode(PIC16ISD::Lo, dl, MVT::i8, ES, Offset); + SDValue Hi = DAG.getNode(PIC16ISD::Hi, dl, MVT::i8, ES, Offset); + return DAG.getNode(ISD::BUILD_PAIR, dl, N->getValueType(0), Lo, Hi); } @@ -626,12 +639,22 @@ void PIC16TargetLowering::LegalizeAddress(SDValue Ptr, SelectionDAG &DAG, // Expansion of FrameIndex has Lo/Hi parts if (isDirectAddress(Ptr)) { SDValue TFI = Ptr.getOperand(0).getOperand(0); + int FrameOffset; if (TFI.getOpcode() == ISD::TargetFrameIndex) { - int FrameOffset; LegalizeFrameIndex(TFI, DAG, Lo, FrameOffset); Hi = DAG.getConstant(1, MVT::i8); Offset += FrameOffset; return; + } else if (TFI.getOpcode() == ISD::TargetExternalSymbol) { + // FrameIndex has already been expanded. + // Now just make use of its expansion + Lo = TFI; + Hi = DAG.getConstant(1, MVT::i8); + SDValue FOffset = Ptr.getOperand(0).getOperand(1); + assert (FOffset.getOpcode() == ISD::Constant && + "Invalid operand of PIC16ISD::Lo"); + Offset += dyn_cast<ConstantSDNode>(FOffset)->getZExtValue(); + return; } } @@ -721,7 +744,8 @@ SDValue PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) { for (iter=MemBytes; iter<ExtdBytes; ++iter) { PICLoads.push_back(SRA); } - } else if (ISD::isZEXTLoad(N)) { + } else if (ISD::isZEXTLoad(N) || ISD::isEXTLoad(N)) { + //} else if (ISD::isZEXTLoad(N)) { // ZeroExtendedLoad -- For all ExtdBytes use constant 0 SDValue ConstZero = DAG.getConstant(0, MVT::i8); for (iter=MemBytes; iter<ExtdBytes; ++iter) { @@ -1557,8 +1581,8 @@ static PIC16CC::CondCodes IntCCToPIC16CC(ISD::CondCode CC) { case ISD::SETLT: return PIC16CC::LT; case ISD::SETLE: return PIC16CC::LE; case ISD::SETULT: return PIC16CC::ULT; - case ISD::SETULE: return PIC16CC::LE; - case ISD::SETUGE: return PIC16CC::GE; + case ISD::SETULE: return PIC16CC::ULE; + case ISD::SETUGE: return PIC16CC::UGE; case ISD::SETUGT: return PIC16CC::UGT; } } diff --git a/lib/Target/PIC16/PIC16InstrInfo.cpp b/lib/Target/PIC16/PIC16InstrInfo.cpp index 2a769e8..8418423 100644 --- a/lib/Target/PIC16/PIC16InstrInfo.cpp +++ b/lib/Target/PIC16/PIC16InstrInfo.cpp @@ -184,3 +184,31 @@ bool PIC16InstrInfo::isMoveInstr(const MachineInstr &MI, return false; } +/// InsertBranch - Insert a branch into the end of the specified +/// MachineBasicBlock. This operands to this method are the same as those +/// returned by AnalyzeBranch. This is invoked in cases where AnalyzeBranch +/// returns success and when an unconditional branch (TBB is non-null, FBB is +/// null, Cond is empty) needs to be inserted. It returns the number of +/// instructions inserted. +unsigned PIC16InstrInfo:: +InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl<MachineOperand> &Cond) const { + // Shouldn't be a fall through. + assert(TBB && "InsertBranch must not be told to insert a fallthrough"); + + if (FBB == 0) { // One way branch. + if (Cond.empty()) { + // Unconditional branch? + DebugLoc dl = DebugLoc::getUnknownLoc(); + BuildMI(&MBB, dl, get(PIC16::br_uncond)).addMBB(TBB); + } + return 1; + } + + // FIXME: If the there are some conditions specified then conditional branch + // should be generated. + // For the time being no instruction is being generated therefore + // returning NULL. + return 0; +} diff --git a/lib/Target/PIC16/PIC16InstrInfo.h b/lib/Target/PIC16/PIC16InstrInfo.h index 0b67679..85c0984 100644 --- a/lib/Target/PIC16/PIC16InstrInfo.h +++ b/lib/Target/PIC16/PIC16InstrInfo.h @@ -64,6 +64,11 @@ public: unsigned &SrcReg, unsigned &DstReg, unsigned &SrcSubIdx, unsigned &DstSubIdx) const; + virtual + unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl<MachineOperand> &Cond) const; + }; } // namespace llvm diff --git a/lib/Target/PIC16/PIC16InstrInfo.td b/lib/Target/PIC16/PIC16InstrInfo.td index c572188..7557716 100644 --- a/lib/Target/PIC16/PIC16InstrInfo.td +++ b/lib/Target/PIC16/PIC16InstrInfo.td @@ -189,22 +189,22 @@ def movlw : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src), // Move a Lo(TGA) to W. def movlw_lo_1 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2), - "movlw LOW(${src}) + ${src2}", + "movlw LOW(${src} + ${src2})", [(set GPR:$dst, (PIC16Lo tglobaladdr:$src, imm:$src2 ))]>; // Move a Lo(TES) to W. def movlw_lo_2 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2), - "movlw LOW(${src}) + ${src2}", + "movlw LOW(${src} + ${src2})", [(set GPR:$dst, (PIC16Lo texternalsym:$src, imm:$src2 ))]>; // Move a Hi(TGA) to W. def movlw_hi_1 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2), - "movlw HIGH(${src}) + ${src2}", + "movlw HIGH(${src} + ${src2})", [(set GPR:$dst, (PIC16Hi tglobaladdr:$src, imm:$src2))]>; // Move a Hi(TES) to W. def movlw_hi_2 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2), - "movlw HIGH(${src}) + ${src2}", + "movlw HIGH(${src} + ${src2})", [(set GPR:$dst, (PIC16Hi texternalsym:$src, imm:$src2))]>; } diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index bd1fea7..b003efd 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -113,10 +113,6 @@ namespace { /// SelectionDAG operations. /// class VISIBILITY_HIDDEN X86DAGToDAGISel : public SelectionDAGISel { - /// TM - Keep a reference to X86TargetMachine. - /// - X86TargetMachine &TM; - /// X86Lowering - This object fully describes how to lower LLVM code to an /// X86-specific SelectionDAG. X86TargetLowering &X86Lowering; @@ -136,8 +132,8 @@ namespace { public: explicit X86DAGToDAGISel(X86TargetMachine &tm, CodeGenOpt::Level OptLevel) : SelectionDAGISel(tm, OptLevel), - TM(tm), X86Lowering(*TM.getTargetLowering()), - Subtarget(&TM.getSubtarget<X86Subtarget>()), + X86Lowering(*tm.getTargetLowering()), + Subtarget(&tm.getSubtarget<X86Subtarget>()), OptForSize(false) {} virtual const char *getPassName() const { @@ -243,6 +239,18 @@ namespace { /// SDNode *getGlobalBaseReg(); + /// getTargetMachine - Return a reference to the TargetMachine, casted + /// to the target-specific type. + const X86TargetMachine &getTargetMachine() { + return static_cast<const X86TargetMachine &>(TM); + } + + /// getInstrInfo - Return a reference to the TargetInstrInfo, casted + /// to the target-specific type. + const X86InstrInfo *getInstrInfo() { + return getTargetMachine().getInstrInfo(); + } + #ifndef NDEBUG unsigned Indent; #endif @@ -674,6 +682,8 @@ bool X86DAGToDAGISel::MatchLoad(SDValue N, X86ISelAddressMode &AM) { } bool X86DAGToDAGISel::MatchWrapper(SDValue N, X86ISelAddressMode &AM) { + bool SymbolicAddressesAreRIPRel = + getTargetMachine().symbolicAddressesAreRIPRel(); bool is64Bit = Subtarget->is64Bit(); DOUT << "Wrapper: 64bit " << is64Bit; DOUT << " AM "; DEBUG(AM.dump()); DOUT << "\n"; @@ -684,7 +694,7 @@ bool X86DAGToDAGISel::MatchWrapper(SDValue N, X86ISelAddressMode &AM) { // Base and index reg must be 0 in order to use rip as base. bool canUsePICRel = !AM.Base.Reg.getNode() && !AM.IndexReg.getNode(); - if (is64Bit && !canUsePICRel && TM.symbolicAddressesAreRIPRel()) + if (is64Bit && !canUsePICRel && SymbolicAddressesAreRIPRel) return true; if (AM.hasSymbolicDisplacement()) @@ -698,7 +708,7 @@ bool X86DAGToDAGISel::MatchWrapper(SDValue N, X86ISelAddressMode &AM) { uint64_t Offset = G->getOffset(); if (!is64Bit || isInt32(AM.Disp + Offset)) { GlobalValue *GV = G->getGlobal(); - bool isRIPRel = TM.symbolicAddressesAreRIPRel(); + bool isRIPRel = SymbolicAddressesAreRIPRel; if (N0.getOpcode() == llvm::ISD::TargetGlobalTLSAddress) { TLSModel::Model model = getTLSModel (GV, TM.getRelocationModel()); @@ -716,16 +726,16 @@ bool X86DAGToDAGISel::MatchWrapper(SDValue N, X86ISelAddressMode &AM) { AM.CP = CP->getConstVal(); AM.Align = CP->getAlignment(); AM.Disp += Offset; - AM.isRIPRel = TM.symbolicAddressesAreRIPRel(); + AM.isRIPRel = SymbolicAddressesAreRIPRel; return false; } } else if (ExternalSymbolSDNode *S =dyn_cast<ExternalSymbolSDNode>(N0)) { AM.ES = S->getSymbol(); - AM.isRIPRel = TM.symbolicAddressesAreRIPRel(); + AM.isRIPRel = SymbolicAddressesAreRIPRel; return false; } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) { AM.JT = J->getIndex(); - AM.isRIPRel = TM.symbolicAddressesAreRIPRel(); + AM.isRIPRel = SymbolicAddressesAreRIPRel; return false; } @@ -1300,7 +1310,7 @@ bool X86DAGToDAGISel::TryFoldLoad(SDValue P, SDValue N, /// SDNode *X86DAGToDAGISel::getGlobalBaseReg() { MachineFunction *MF = CurBB->getParent(); - unsigned GlobalBaseReg = TM.getInstrInfo()->getGlobalBaseReg(MF); + unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF); return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); } diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 882ee3a..1f507c3 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -15,7 +15,6 @@ #include "X86.h" #include "X86InstrBuilder.h" #include "X86ISelLowering.h" -#include "X86MachineFunctionInfo.h" #include "X86TargetMachine.h" #include "llvm/CallingConv.h" #include "llvm/Constants.h" @@ -25,14 +24,12 @@ #include "llvm/Intrinsics.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/VectorExtras.h" -#include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" -#include "llvm/CodeGen/SelectionDAG.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Target/TargetOptions.h" diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index ca7aa7b..af61eae 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -465,17 +465,6 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType, // Compute the final addrec to expand into code. SCEVHandle AR = IU->getReplacementExpr(*UI); - // FIXME: It is an extremely bad idea to indvar substitute anything more - // complex than affine induction variables. Doing so will put expensive - // polynomial evaluations inside of the loop, and the str reduction pass - // currently can only reduce affine polynomials. For now just disable - // indvar subst on anything more complex than an affine addrec, unless - // it can be expanded to a trivial value. - if (!Stride->isLoopInvariant(L) && - !isa<SCEVConstant>(AR) && - L->contains(User->getParent())) - continue; - Value *NewVal = 0; if (AR->isLoopInvariant(L)) { BasicBlock::iterator I = Rewriter.getInsertionPoint(); @@ -487,6 +476,15 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType, Rewriter.setInsertionPoint(I); ++NumReplaced; } else { + // FIXME: It is an extremely bad idea to indvar substitute anything more + // complex than affine induction variables. Doing so will put expensive + // polynomial evaluations inside of the loop, and the str reduction pass + // currently can only reduce affine polynomials. For now just disable + // indvar subst on anything more complex than an affine addrec, unless + // it can be expanded to a trivial value. + if (!Stride->isLoopInvariant(L)) + continue; + const Type *IVTy = Offset->getType(); const Type *UseTy = Op->getType(); @@ -520,7 +518,7 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType, // induction variable, still in the canonical induction variable's // type, so that all expanded arithmetic is done in the same type. SCEVHandle NewAR = SE->getAddRecExpr(SE->getIntegerSCEV(0, LargestType), - PromotedStride, L); + PromotedStride, L); // Add the PromotedOffset as a separate step, because it may not be // loop-invariant. NewAR = SE->getAddExpr(NewAR, PromotedOffset); diff --git a/test/Transforms/IndVarSimplify/variable-stride-ivs.ll b/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll index 759ba8e..759ba8e 100644 --- a/test/Transforms/IndVarSimplify/variable-stride-ivs.ll +++ b/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll diff --git a/test/Transforms/IndVarSimplify/variable-stride-ivs-1.ll b/test/Transforms/IndVarSimplify/variable-stride-ivs-1.ll new file mode 100644 index 0000000..075e899 --- /dev/null +++ b/test/Transforms/IndVarSimplify/variable-stride-ivs-1.ll @@ -0,0 +1,43 @@ +; RUN: llvm-as < %s | opt -indvars +; PR4315 + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target triple = "x86_64-undermydesk-freebsd8.0" + %struct.mbuf = type <{ %struct.mbuf*, i8*, i32, i8, i8, i8, i8 }> + +define i32 @crash(%struct.mbuf* %m) nounwind { +entry: + br label %for.cond + +for.cond: ; preds = %if.end, %entry + %i.0 = phi i32 [ 0, %entry ], [ %inc, %if.end ] ; <i32> [#uses=3] + %chksum.0 = phi i8 [ 0, %entry ], [ %conv3, %if.end ] ; <i8> [#uses=3] + %cmp = icmp slt i32 %i.0, 1 ; <i1> [#uses=1] + br i1 %cmp, label %for.body, label %do.body + +for.body: ; preds = %for.cond + br i1 undef, label %if.end, label %do.body + +if.end: ; preds = %for.body + %i.02 = trunc i32 %i.0 to i8 ; <i8> [#uses=1] + %conv3 = add i8 %chksum.0, %i.02 ; <i8> [#uses=1] + %inc = add i32 %i.0, 1 ; <i32> [#uses=1] + br label %for.cond + +do.body: ; preds = %do.cond, %for.body, %for.cond + %chksum.2 = phi i8 [ undef, %do.cond ], [ %chksum.0, %for.body ], [ %chksum.0, %for.cond ] ; <i8> [#uses=1] + br i1 undef, label %do.cond, label %bb.nph + +bb.nph: ; preds = %do.body + br label %while.body + +while.body: ; preds = %while.body, %bb.nph + %chksum.13 = phi i8 [ undef, %while.body ], [ %chksum.2, %bb.nph ] ; <i8> [#uses=0] + br i1 undef, label %do.cond, label %while.body + +do.cond: ; preds = %while.body, %do.body + br i1 false, label %do.end, label %do.body + +do.end: ; preds = %do.cond + ret i32 0 +} diff --git a/tools/llvm-config/CMakeLists.txt b/tools/llvm-config/CMakeLists.txt index 29287ab..2cfd6bb 100644 --- a/tools/llvm-config/CMakeLists.txt +++ b/tools/llvm-config/CMakeLists.txt @@ -87,7 +87,6 @@ add_custom_command(OUTPUT ${FINAL_LIBDEPS} DEPENDS ${LIBDEPS} COMMENT "Checking for cyclic dependencies between LLVM libraries.") -string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE) set(C_FLGS "${CMAKE_C_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${LLVM_DEFINITIONS}") set(CXX_FLGS "${CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${LLVM_DEFINITIONS}") set(CPP_FLGS "${CMAKE_CPP_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${LLVM_DEFINITIONS}") diff --git a/tools/llvm-ld/Optimize.cpp b/tools/llvm-ld/Optimize.cpp index f788f06..a4ca951 100644 --- a/tools/llvm-ld/Optimize.cpp +++ b/tools/llvm-ld/Optimize.cpp @@ -17,6 +17,7 @@ #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/StandardPasses.h" #include "llvm/System/DynamicLibrary.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" @@ -91,71 +92,9 @@ void Optimize(Module* M) { // Add an appropriate TargetData instance for this module... addPass(Passes, new TargetData(M)); - if (!DisableOptimizations) { - // Now that composite has been compiled, scan through the module, looking - // for a main function. If main is defined, mark all other functions - // internal. - if (!DisableInternalize) - addPass(Passes, createInternalizePass(true)); - - // Propagate constants at call sites into the functions they call. This - // opens opportunities for globalopt (and inlining) by substituting function - // pointers passed as arguments to direct uses of functions. - addPass(Passes, createIPSCCPPass()); - - // Now that we internalized some globals, see if we can hack on them! - addPass(Passes, createGlobalOptimizerPass()); - - // Linking modules together can lead to duplicated global constants, only - // keep one copy of each constant... - addPass(Passes, createConstantMergePass()); - - // Remove unused arguments from functions... - addPass(Passes, createDeadArgEliminationPass()); - - // Reduce the code after globalopt and ipsccp. Both can open up significant - // simplification opportunities, and both can propagate functions through - // function pointers. When this happens, we often have to resolve varargs - // calls, etc, so let instcombine do this. - addPass(Passes, createInstructionCombiningPass()); - - if (!DisableInline) - addPass(Passes, createFunctionInliningPass()); // Inline small functions - - addPass(Passes, createPruneEHPass()); // Remove dead EH info - addPass(Passes, createGlobalOptimizerPass()); // Optimize globals again. - addPass(Passes, createGlobalDCEPass()); // Remove dead functions - - // If we didn't decide to inline a function, check to see if we can - // transform it to pass arguments by value instead of by reference. - addPass(Passes, createArgumentPromotionPass()); - - // The IPO passes may leave cruft around. Clean up after them. - addPass(Passes, createInstructionCombiningPass()); - addPass(Passes, createJumpThreadingPass()); // Thread jumps. - addPass(Passes, createScalarReplAggregatesPass()); // Break up allocas - - // Run a few AA driven optimizations here and now, to cleanup the code. - addPass(Passes, createFunctionAttrsPass()); // Add nocapture - addPass(Passes, createGlobalsModRefPass()); // IP alias analysis - - addPass(Passes, createLICMPass()); // Hoist loop invariants - addPass(Passes, createGVNPass()); // Remove redundancies - addPass(Passes, createMemCpyOptPass()); // Remove dead memcpy's - addPass(Passes, createDeadStoreEliminationPass()); // Nuke dead stores - - // Cleanup and simplify the code after the scalar optimizations. - addPass(Passes, createInstructionCombiningPass()); - - addPass(Passes, createJumpThreadingPass()); // Thread jumps. - addPass(Passes, createPromoteMemoryToRegisterPass()); // Cleanup jumpthread. - - // Delete basic blocks, which optimization passes may have killed... - addPass(Passes, createCFGSimplificationPass()); - - // Now that we have optimized the program, discard unreachable functions... - addPass(Passes, createGlobalDCEPass()); - } + if (!DisableOptimizations) + createStandardLTOPasses(&Passes, !DisableInternalize, !DisableInline, + /*RunSecondGlobalOpt=*/true, VerifyEach); // If the -s or -S command line options were specified, strip the symbols out // of the resulting program to make it smaller. -s and -S are GNU ld options diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index d3a3f7f..03a11b6 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -24,9 +24,10 @@ #include "llvm/ModuleProvider.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/SystemUtils.h" #include "llvm/Support/Mangler.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/StandardPasses.h" +#include "llvm/Support/SystemUtils.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Signals.h" #include "llvm/Analysis/Passes.h" @@ -389,59 +390,9 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out, // Add an appropriate TargetData instance for this module... passes.add(new TargetData(*_target->getTargetData())); - // Propagate constants at call sites into the functions they call. This - // opens opportunities for globalopt (and inlining) by substituting function - // pointers passed as arguments to direct uses of functions. - passes.add(createIPSCCPPass()); - - // Now that we internalized some globals, see if we can hack on them! - passes.add(createGlobalOptimizerPass()); - - // Linking modules together can lead to duplicated global constants, only - // keep one copy of each constant... - passes.add(createConstantMergePass()); - - // Remove unused arguments from functions... - passes.add(createDeadArgEliminationPass()); - - // Reduce the code after globalopt and ipsccp. Both can open up significant - // simplification opportunities, and both can propagate functions through - // function pointers. When this happens, we often have to resolve varargs - // calls, etc, so let instcombine do this. - passes.add(createInstructionCombiningPass()); - if (!DisableInline) - passes.add(createFunctionInliningPass()); // Inline small functions - passes.add(createPruneEHPass()); // Remove dead EH info - passes.add(createGlobalDCEPass()); // Remove dead functions - - // If we didn't decide to inline a function, check to see if we can - // transform it to pass arguments by value instead of by reference. - passes.add(createArgumentPromotionPass()); - - // The IPO passes may leave cruft around. Clean up after them. - passes.add(createInstructionCombiningPass()); - passes.add(createJumpThreadingPass()); // Thread jumps. - passes.add(createScalarReplAggregatesPass()); // Break up allocas - - // Run a few AA driven optimizations here and now, to cleanup the code. - passes.add(createFunctionAttrsPass()); // Add nocapture - passes.add(createGlobalsModRefPass()); // IP alias analysis - passes.add(createLICMPass()); // Hoist loop invariants - passes.add(createGVNPass()); // Remove common subexprs - passes.add(createMemCpyOptPass()); // Remove dead memcpy's - passes.add(createDeadStoreEliminationPass()); // Nuke dead stores - - // Cleanup and simplify the code after the scalar optimizations. - passes.add(createInstructionCombiningPass()); - passes.add(createJumpThreadingPass()); // Thread jumps. - passes.add(createPromoteMemoryToRegisterPass()); // Cleanup after threading. - - - // Delete basic blocks, which optimization passes may have killed... - passes.add(createCFGSimplificationPass()); - - // Now that we have optimized the program, discard unreachable functions... - passes.add(createGlobalDCEPass()); + createStandardLTOPasses(&passes, /*Internalize=*/ false, !DisableInline, + /*RunSecondGlobalOpt=*/ false, + /*VerifyEach=*/ false); // Make sure everything is still good. passes.add(createVerifierPass()); diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index 680353a..0c36e21 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -28,6 +28,7 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PluginLoader.h" +#include "llvm/Support/StandardPasses.h" #include "llvm/Support/Streams.h" #include "llvm/Support/SystemUtils.h" #include "llvm/Support/raw_ostream.h" @@ -266,79 +267,16 @@ inline void addPass(PassManager &PM, Pass *P) { /// OptLevel - Optimization Level void AddOptimizationPasses(PassManager &MPM, FunctionPassManager &FPM, unsigned OptLevel) { - - if (OptLevel == 0) - return; - - FPM.add(createCFGSimplificationPass()); - if (OptLevel == 1) - FPM.add(createPromoteMemoryToRegisterPass()); - else - FPM.add(createScalarReplAggregatesPass()); - FPM.add(createInstructionCombiningPass()); - - if (UnitAtATime) - MPM.add(createRaiseAllocationsPass()); // call %malloc -> malloc inst - MPM.add(createCFGSimplificationPass()); // Clean up disgusting code - MPM.add(createPromoteMemoryToRegisterPass()); // Kill useless allocas - if (UnitAtATime) { - MPM.add(createGlobalOptimizerPass()); // OptLevel out global vars - MPM.add(createGlobalDCEPass()); // Remove unused fns and globs - MPM.add(createIPConstantPropagationPass()); // IP Constant Propagation - MPM.add(createDeadArgEliminationPass()); // Dead argument elimination - } - MPM.add(createInstructionCombiningPass()); // Clean up after IPCP & DAE - MPM.add(createCFGSimplificationPass()); // Clean up after IPCP & DAE - if (UnitAtATime) { - MPM.add(createPruneEHPass()); // Remove dead EH info - MPM.add(createFunctionAttrsPass()); // Deduce function attrs - } - if (OptLevel > 1) - MPM.add(createFunctionInliningPass()); // Inline small functions - if (OptLevel > 2) - MPM.add(createArgumentPromotionPass()); // Scalarize uninlined fn args - if (!DisableSimplifyLibCalls) - MPM.add(createSimplifyLibCallsPass()); // Library Call Optimizations - MPM.add(createInstructionCombiningPass()); // Cleanup for scalarrepl. - MPM.add(createJumpThreadingPass()); // Thread jumps. - MPM.add(createCFGSimplificationPass()); // Merge & remove BBs - MPM.add(createScalarReplAggregatesPass()); // Break up aggregate allocas - MPM.add(createInstructionCombiningPass()); // Combine silly seq's - MPM.add(createCondPropagationPass()); // Propagate conditionals - MPM.add(createTailCallEliminationPass()); // Eliminate tail calls - MPM.add(createCFGSimplificationPass()); // Merge & remove BBs - MPM.add(createReassociatePass()); // Reassociate expressions - MPM.add(createLoopRotatePass()); // Rotate Loop - MPM.add(createLICMPass()); // Hoist loop invariants - MPM.add(createLoopUnswitchPass()); - MPM.add(createLoopIndexSplitPass()); // Split loop index - MPM.add(createInstructionCombiningPass()); - MPM.add(createIndVarSimplifyPass()); // Canonicalize indvars - MPM.add(createLoopDeletionPass()); // Delete dead loops - if (OptLevel > 1) - MPM.add(createLoopUnrollPass()); // Unroll small loops - MPM.add(createInstructionCombiningPass()); // Clean up after the unroller - MPM.add(createGVNPass()); // Remove redundancies - MPM.add(createMemCpyOptPass()); // Remove memcpy / form memset - MPM.add(createSCCPPass()); // Constant prop with SCCP - - // Run instcombine after redundancy elimination to exploit opportunities - // opened up by them. - MPM.add(createInstructionCombiningPass()); - MPM.add(createCondPropagationPass()); // Propagate conditionals - MPM.add(createDeadStoreEliminationPass()); // Delete dead stores - MPM.add(createAggressiveDCEPass()); // Delete dead instructions - MPM.add(createCFGSimplificationPass()); // Merge & remove BBs - - if (UnitAtATime) { - MPM.add(createStripDeadPrototypesPass()); // Get rid of dead prototypes - MPM.add(createDeadTypeEliminationPass()); // Eliminate dead types - } - - if (OptLevel > 1 && UnitAtATime) - MPM.add(createConstantMergePass()); // Merge dup global constants - - return; + createStandardFunctionPasses(&FPM, OptLevel); + + llvm::Pass *InliningPass = OptLevel > 1 ? createFunctionInliningPass() : 0; + createStandardModulePasses(&MPM, OptLevel, + /*OptimizeSize=*/ false, + UnitAtATime, + /*UnrollLoops=*/ OptLevel > 1, + !DisableSimplifyLibCalls, + /*HaveExceptions=*/ true, + InliningPass); } void AddStandardCompilePasses(PassManager &PM) { @@ -352,59 +290,16 @@ void AddStandardCompilePasses(PassManager &PM) { if (DisableOptimizations) return; - addPass(PM, createRaiseAllocationsPass()); // call %malloc -> malloc inst - addPass(PM, createCFGSimplificationPass()); // Clean up disgusting code - addPass(PM, createPromoteMemoryToRegisterPass());// Kill useless allocas - addPass(PM, createGlobalOptimizerPass()); // Optimize out global vars - addPass(PM, createGlobalDCEPass()); // Remove unused fns and globs - addPass(PM, createIPConstantPropagationPass());// IP Constant Propagation - addPass(PM, createDeadArgEliminationPass()); // Dead argument elimination - addPass(PM, createInstructionCombiningPass()); // Clean up after IPCP & DAE - addPass(PM, createCFGSimplificationPass()); // Clean up after IPCP & DAE - - addPass(PM, createPruneEHPass()); // Remove dead EH info - addPass(PM, createFunctionAttrsPass()); // Deduce function attrs - - if (!DisableInline) - addPass(PM, createFunctionInliningPass()); // Inline small functions - addPass(PM, createArgumentPromotionPass()); // Scalarize uninlined fn args - - addPass(PM, createSimplifyLibCallsPass()); // Library Call Optimizations - addPass(PM, createInstructionCombiningPass()); // Cleanup for scalarrepl. - addPass(PM, createJumpThreadingPass()); // Thread jumps. - addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs - addPass(PM, createScalarReplAggregatesPass()); // Break up aggregate allocas - addPass(PM, createInstructionCombiningPass()); // Combine silly seq's - addPass(PM, createCondPropagationPass()); // Propagate conditionals - - addPass(PM, createTailCallEliminationPass()); // Eliminate tail calls - addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs - addPass(PM, createReassociatePass()); // Reassociate expressions - addPass(PM, createLoopRotatePass()); - addPass(PM, createLICMPass()); // Hoist loop invariants - addPass(PM, createLoopUnswitchPass()); // Unswitch loops. - addPass(PM, createLoopIndexSplitPass()); // Index split loops. - // FIXME : Removing instcombine causes nestedloop regression. - addPass(PM, createInstructionCombiningPass()); - addPass(PM, createIndVarSimplifyPass()); // Canonicalize indvars - addPass(PM, createLoopDeletionPass()); // Delete dead loops - addPass(PM, createLoopUnrollPass()); // Unroll small loops - addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller - addPass(PM, createGVNPass()); // Remove redundancies - addPass(PM, createMemCpyOptPass()); // Remove memcpy / form memset - addPass(PM, createSCCPPass()); // Constant prop with SCCP - - // Run instcombine after redundancy elimination to exploit opportunities - // opened up by them. - addPass(PM, createInstructionCombiningPass()); - addPass(PM, createCondPropagationPass()); // Propagate conditionals - - addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores - addPass(PM, createAggressiveDCEPass()); // Delete dead instructions - addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs - addPass(PM, createStripDeadPrototypesPass()); // Get rid of dead prototypes - addPass(PM, createDeadTypeEliminationPass()); // Eliminate dead types - addPass(PM, createConstantMergePass()); // Merge dup global constants + llvm::Pass *InliningPass = !DisableInline ? createFunctionInliningPass() : 0; + + // -std-compile-opts adds the same module passes as -O3. + createStandardModulePasses(&PM, 3, + /*OptimizeSize=*/ false, + /*UnitAtATime=*/ true, + /*UnrollLoops=*/ true, + /*SimplifyLibCalls=*/ true, + /*HaveExceptions=*/ true, + InliningPass); } } // anonymous namespace |