llvm-6502/lib/Target/X86/X86TargetMachine.cpp
Nate Begeman f15485a8d0 SelectionDAGISel can now natively handle Switch instructions, in the same
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
2006-03-27 01:32:24 +00:00

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;
}