Import LLVM, at r72805, which fixes PR4315 and PR4316.
Normally I'm not updating sources this often, but I want to get rid of this breakage, because right now I can't offer a proper source snapshot yet.
This commit is contained in:
parent
33a8e4360f
commit
68eb509bdc
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
@ -135,6 +136,35 @@ $ llvm-gcc -use-gold-plugin a.o b.o -o main # <-- link with LLVMgold plugin
|
|||
example</a> gold does not currently eliminate foo4.</p>
|
||||
</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>
|
||||
<!--=========================================================================-->
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -32,6 +32,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ELFWriter.h"
|
||||
#include "ELFCodeEmitter.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/PassManager.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
|
@ -60,150 +61,11 @@ MachineCodeEmitter *llvm::AddELFWriter(PassManagerBase &PM,
|
|||
return &EW->getMachineCodeEmitter();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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))]>;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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}")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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) {
|
||||
createStandardFunctionPasses(&FPM, 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;
|
||||
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
|
||||
llvm::Pass *InliningPass = !DisableInline ? createFunctionInliningPass() : 0;
|
||||
|
||||
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
|
||||
// -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
|
||||
|
|
Loading…
Reference in New Issue