mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-21 18:29:46 +00:00
manner that the LowerSwitch LLVM to LLVM pass does: emitting a binary search tree of basic blocks. The new approach has several advantages: it is faster, it generates significantly smaller code in many cases, and it paves the way for implementing dense switch tables as a jump table by handling switches directly in the instruction selector. This functionality is currently only enabled on x86, but should be safe for every target. In anticipation of making it the default, the cfg is now properly updated in the x86, ppc, and sparc select lowering code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27156 91177308-0d34-0410-b5e6-96231b3b80d8
211 lines
7.4 KiB
C++
211 lines
7.4 KiB
C++
//===-- X86TargetMachine.cpp - Define TargetMachine for the X86 -----------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file was developed by the LLVM research group and is distributed under
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the X86 specific subclass of TargetMachine.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "X86TargetMachine.h"
|
|
#include "X86.h"
|
|
#include "llvm/Module.h"
|
|
#include "llvm/PassManager.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/Passes.h"
|
|
#include "llvm/Target/TargetOptions.h"
|
|
#include "llvm/Target/TargetMachineRegistry.h"
|
|
#include "llvm/Transforms/Scalar.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/ADT/Statistic.h"
|
|
#include <iostream>
|
|
using namespace llvm;
|
|
|
|
/// X86TargetMachineModule - Note that this is used on hosts that cannot link
|
|
/// in a library unless there are references into the library. In particular,
|
|
/// it seems that it is not possible to get things to work on Win32 without
|
|
/// this. Though it is unused, do not remove it.
|
|
extern "C" int X86TargetMachineModule;
|
|
int X86TargetMachineModule = 0;
|
|
|
|
namespace {
|
|
cl::opt<bool> DisableOutput("disable-x86-llc-output", cl::Hidden,
|
|
cl::desc("Disable the X86 asm printer, for use "
|
|
"when profiling the code generator."));
|
|
cl::opt<bool> DisableLowerSwitch("disable-lower-switch", cl::Hidden,
|
|
cl::desc("Disable the LowerSwitch pass"));
|
|
// Register the target.
|
|
RegisterTarget<X86TargetMachine> X("x86", " IA-32 (Pentium and above)");
|
|
}
|
|
|
|
unsigned X86TargetMachine::getJITMatchQuality() {
|
|
#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
|
|
return 10;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
unsigned X86TargetMachine::getModuleMatchQuality(const Module &M) {
|
|
// We strongly match "i[3-9]86-*".
|
|
std::string TT = M.getTargetTriple();
|
|
if (TT.size() >= 5 && TT[0] == 'i' && TT[2] == '8' && TT[3] == '6' &&
|
|
TT[4] == '-' && TT[1] - '3' < 6)
|
|
return 20;
|
|
|
|
if (M.getEndianness() == Module::LittleEndian &&
|
|
M.getPointerSize() == Module::Pointer32)
|
|
return 10; // Weak match
|
|
else if (M.getEndianness() != Module::AnyEndianness ||
|
|
M.getPointerSize() != Module::AnyPointerSize)
|
|
return 0; // Match for some other target
|
|
|
|
return getJITMatchQuality()/2;
|
|
}
|
|
|
|
/// X86TargetMachine ctor - Create an ILP32 architecture model
|
|
///
|
|
X86TargetMachine::X86TargetMachine(const Module &M, const std::string &FS)
|
|
: TargetMachine("X86", true, 4, 4, 4, 4, 4),
|
|
Subtarget(M, FS),
|
|
FrameInfo(TargetFrameInfo::StackGrowsDown,
|
|
Subtarget.getStackAlignment(), -4),
|
|
JITInfo(*this), TLInfo(*this) {
|
|
if (getRelocationModel() == Reloc::Default)
|
|
if (Subtarget.isTargetDarwin())
|
|
setRelocationModel(Reloc::DynamicNoPIC);
|
|
else
|
|
setRelocationModel(Reloc::PIC);
|
|
}
|
|
|
|
|
|
// addPassesToEmitFile - We currently use all of the same passes as the JIT
|
|
// does to emit statically compiled machine code.
|
|
bool X86TargetMachine::addPassesToEmitFile(PassManager &PM, std::ostream &Out,
|
|
CodeGenFileType FileType,
|
|
bool Fast) {
|
|
if (FileType != TargetMachine::AssemblyFile &&
|
|
FileType != TargetMachine::ObjectFile) return true;
|
|
|
|
// Run loop strength reduction before anything else.
|
|
PM.add(createLoopStrengthReducePass(&TLInfo));
|
|
|
|
// FIXME: Implement efficient support for garbage collection intrinsics.
|
|
PM.add(createLowerGCPass());
|
|
|
|
// FIXME: Implement the invoke/unwind instructions!
|
|
PM.add(createLowerInvokePass());
|
|
|
|
// FIXME: Implement the switch instruction in the instruction selector!
|
|
if (!DisableLowerSwitch)
|
|
PM.add(createLowerSwitchPass());
|
|
|
|
// Make sure that no unreachable blocks are instruction selected.
|
|
PM.add(createUnreachableBlockEliminationPass());
|
|
|
|
// Install an instruction selector.
|
|
PM.add(createX86ISelDag(*this));
|
|
|
|
// Print the instruction selected machine code...
|
|
if (PrintMachineCode)
|
|
PM.add(createMachineFunctionPrinterPass(&std::cerr));
|
|
|
|
// Perform register allocation to convert to a concrete x86 representation
|
|
PM.add(createRegisterAllocator());
|
|
|
|
if (PrintMachineCode)
|
|
PM.add(createMachineFunctionPrinterPass(&std::cerr));
|
|
|
|
PM.add(createX86FloatingPointStackifierPass());
|
|
|
|
if (PrintMachineCode)
|
|
PM.add(createMachineFunctionPrinterPass(&std::cerr));
|
|
|
|
// Insert prolog/epilog code. Eliminate abstract frame index references...
|
|
PM.add(createPrologEpilogCodeInserter());
|
|
|
|
if (PrintMachineCode) // Print the register-allocated code
|
|
PM.add(createX86CodePrinterPass(std::cerr, *this));
|
|
|
|
if (!DisableOutput)
|
|
switch (FileType) {
|
|
default:
|
|
assert(0 && "Unexpected filetype here!");
|
|
case TargetMachine::AssemblyFile:
|
|
PM.add(createX86CodePrinterPass(Out, *this));
|
|
break;
|
|
case TargetMachine::ObjectFile:
|
|
// FIXME: We only support emission of ELF files for now, this should check
|
|
// the target triple and decide on the format to write (e.g. COFF on
|
|
// win32).
|
|
addX86ELFObjectWriterPass(PM, Out, *this);
|
|
break;
|
|
}
|
|
|
|
// Delete machine code for this function
|
|
PM.add(createMachineCodeDeleter());
|
|
|
|
return false; // success!
|
|
}
|
|
|
|
/// addPassesToJITCompile - Add passes to the specified pass manager to
|
|
/// implement a fast dynamic compiler for this target. Return true if this is
|
|
/// not supported for this target.
|
|
///
|
|
void X86JITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
|
|
// The JIT should use static relocation model.
|
|
TM.setRelocationModel(Reloc::Static);
|
|
|
|
// Run loop strength reduction before anything else.
|
|
PM.add(createLoopStrengthReducePass(TM.getTargetLowering()));
|
|
|
|
// FIXME: Implement efficient support for garbage collection intrinsics.
|
|
PM.add(createLowerGCPass());
|
|
|
|
// FIXME: Implement the invoke/unwind instructions!
|
|
PM.add(createLowerInvokePass());
|
|
|
|
// FIXME: Implement the switch instruction in the instruction selector!
|
|
if (!DisableLowerSwitch)
|
|
PM.add(createLowerSwitchPass());
|
|
|
|
// Make sure that no unreachable blocks are instruction selected.
|
|
PM.add(createUnreachableBlockEliminationPass());
|
|
|
|
// Install an instruction selector.
|
|
PM.add(createX86ISelDag(TM));
|
|
|
|
// Print the instruction selected machine code...
|
|
if (PrintMachineCode)
|
|
PM.add(createMachineFunctionPrinterPass(&std::cerr));
|
|
|
|
// Perform register allocation to convert to a concrete x86 representation
|
|
PM.add(createRegisterAllocator());
|
|
|
|
if (PrintMachineCode)
|
|
PM.add(createMachineFunctionPrinterPass(&std::cerr));
|
|
|
|
PM.add(createX86FloatingPointStackifierPass());
|
|
|
|
if (PrintMachineCode)
|
|
PM.add(createMachineFunctionPrinterPass(&std::cerr));
|
|
|
|
// Insert prolog/epilog code. Eliminate abstract frame index references...
|
|
PM.add(createPrologEpilogCodeInserter());
|
|
|
|
if (PrintMachineCode) // Print the register-allocated code
|
|
PM.add(createX86CodePrinterPass(std::cerr, TM));
|
|
}
|
|
|
|
bool X86TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
|
|
MachineCodeEmitter &MCE) {
|
|
PM.add(createX86CodeEmitterPass(MCE));
|
|
// Delete machine code for this function
|
|
PM.add(createMachineCodeDeleter());
|
|
return false;
|
|
}
|