LLVM API Documentation

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

SparcV9TargetMachine.cpp

Go to the documentation of this file.
00001 //===-- SparcV9TargetMachine.cpp - SparcV9 Target Machine Implementation --===//
00002 // 
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file was developed by the LLVM research group and is distributed under
00006 // the University of Illinois Open Source License. See LICENSE.TXT for details.
00007 // 
00008 //===----------------------------------------------------------------------===//
00009 // 
00010 // Primary interface to machine description for the UltraSPARC.  Primarily just
00011 // initializes machine-dependent parameters in class TargetMachine, and creates
00012 // machine-dependent subclasses for classes such as TargetInstrInfo.
00013 // 
00014 //===----------------------------------------------------------------------===//
00015 
00016 #include "llvm/Function.h"
00017 #include "llvm/PassManager.h"
00018 #include "llvm/Assembly/PrintModulePass.h"
00019 #include "llvm/CodeGen/InstrScheduling.h"
00020 #include "llvm/CodeGen/IntrinsicLowering.h"
00021 #include "llvm/CodeGen/MachineFunction.h"
00022 #include "llvm/CodeGen/Passes.h"
00023 #include "llvm/Target/TargetOptions.h"
00024 #include "llvm/Target/TargetMachineRegistry.h"
00025 #include "llvm/Transforms/Scalar.h"
00026 #include "MappingInfo.h" 
00027 #include "MachineFunctionInfo.h"
00028 #include "MachineCodeForInstruction.h"
00029 #include "SparcV9Internals.h"
00030 #include "SparcV9TargetMachine.h"
00031 #include "SparcV9BurgISel.h"
00032 #include "llvm/Support/CommandLine.h"
00033 using namespace llvm;
00034 
00035 static const unsigned ImplicitRegUseList[] = { 0 }; /* not used yet */
00036 // Build the MachineInstruction Description Array...
00037 const TargetInstrDescriptor llvm::SparcV9MachineInstrDesc[] = {
00038 #define I(ENUM, OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE, \
00039           NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS)             \
00040   { OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE,             \
00041           NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS, 0,          \
00042           ImplicitRegUseList, ImplicitRegUseList },
00043 #include "SparcV9Instr.def"
00044 };
00045 
00046 //---------------------------------------------------------------------------
00047 // Command line options to control choice of code generation passes.
00048 //---------------------------------------------------------------------------
00049 
00050 namespace llvm {
00051   bool EmitMappingInfo = false;
00052 }
00053 
00054 namespace {
00055   cl::opt<bool> DisableSched("disable-sched",
00056                              cl::desc("Disable local scheduling pass"));
00057 
00058   cl::opt<bool> DisablePeephole("disable-peephole",
00059                                 cl::desc("Disable peephole optimization pass"));
00060 
00061   cl::opt<bool, true> EmitMappingInfoOpt("enable-maps",
00062                  cl::location(EmitMappingInfo),
00063                  cl::init(false),
00064                  cl::desc("Emit LLVM-to-MachineCode mapping info to assembly"));
00065 
00066   cl::opt<bool> EnableModSched("enable-modsched", 
00067    cl::desc("Enable modulo scheduling pass instead of local scheduling"), cl::Hidden);
00068 
00069   // Register the target.
00070   RegisterTarget<SparcV9TargetMachine> X("sparcv9", "  SPARC V9");
00071 }
00072 
00073 unsigned SparcV9TargetMachine::getJITMatchQuality() {
00074 #if defined(__sparcv9)
00075   return 10;
00076 #else
00077   return 0;
00078 #endif
00079 }
00080 
00081 unsigned SparcV9TargetMachine::getModuleMatchQuality(const Module &M) {
00082   if (M.getEndianness()  == Module::BigEndian &&
00083       M.getPointerSize() == Module::Pointer64)
00084     return 10;                                   // Direct match
00085   else if (M.getEndianness() != Module::AnyEndianness ||
00086            M.getPointerSize() != Module::AnyPointerSize)
00087     return 0;                                    // Match for some other target
00088 
00089   return getJITMatchQuality()/2;
00090 }
00091 
00092 //===---------------------------------------------------------------------===//
00093 // Code generation/destruction passes
00094 //===---------------------------------------------------------------------===//
00095 
00096 namespace {
00097   class ConstructMachineFunction : public FunctionPass {
00098     TargetMachine &Target;
00099   public:
00100     ConstructMachineFunction(TargetMachine &T) : Target(T) {}
00101     
00102     const char *getPassName() const {
00103       return "ConstructMachineFunction";
00104     }
00105     
00106     bool runOnFunction(Function &F) {
00107       MachineFunction::construct(&F, Target).getInfo<SparcV9FunctionInfo>()->CalculateArgSize();
00108       return false;
00109     }
00110   };
00111 
00112   struct DestroyMachineFunction : public FunctionPass {
00113     const char *getPassName() const { return "DestroyMachineFunction"; }
00114     
00115     static void freeMachineCode(Instruction &I) {
00116       MachineCodeForInstruction::destroy(&I);
00117     }
00118     
00119     bool runOnFunction(Function &F) {
00120       for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
00121         for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E; ++I)
00122           MachineCodeForInstruction::get(I).dropAllReferences();
00123       
00124       for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
00125         for_each(FI->begin(), FI->end(), freeMachineCode);
00126       
00127       MachineFunction::destruct(&F);
00128       return false;
00129     }
00130   };
00131   
00132   FunctionPass *createMachineCodeConstructionPass(TargetMachine &Target) {
00133     return new ConstructMachineFunction(Target);
00134   }
00135 }
00136 
00137 FunctionPass *llvm::createSparcV9MachineCodeDestructionPass() {
00138   return new DestroyMachineFunction();
00139 }
00140 
00141 
00142 SparcV9TargetMachine::SparcV9TargetMachine(const Module &M,
00143                                            IntrinsicLowering *il)
00144   : TargetMachine("UltraSparcV9-Native", il, false),
00145     schedInfo(*this),
00146     regInfo(*this),
00147     frameInfo(*this),
00148     jitInfo(*this) {
00149 }
00150 
00151 /// addPassesToEmitAssembly - This method controls the entire code generation
00152 /// process for the ultra sparc.
00153 ///
00154 bool
00155 SparcV9TargetMachine::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out)
00156 {
00157   // FIXME: Implement efficient support for garbage collection intrinsics.
00158   PM.add(createLowerGCPass());
00159 
00160   // Replace malloc and free instructions with library calls.
00161   PM.add(createLowerAllocationsPass());
00162   
00163   // FIXME: implement the switch instruction in the instruction selector.
00164   PM.add(createLowerSwitchPass());
00165 
00166   // FIXME: implement the invoke/unwind instructions!
00167   PM.add(createLowerInvokePass());
00168   
00169   // decompose multi-dimensional array references into single-dim refs
00170   PM.add(createDecomposeMultiDimRefsPass());
00171 
00172   // Lower LLVM code to the form expected by the SPARCv9 instruction selector.
00173   PM.add(createPreSelectionPass(*this));
00174   PM.add(createLowerSelectPass());
00175 
00176   // Run basic LLVM dataflow optimizations, to clean up after pre-selection.
00177   PM.add(createReassociatePass());
00178   PM.add(createLICMPass());
00179   PM.add(createGCSEPass());
00180 
00181   // If the user's trying to read the generated code, they'll need to see the
00182   // transformed input.
00183   if (PrintMachineCode)
00184     PM.add(new PrintModulePass());
00185 
00186   // Construct and initialize the MachineFunction object for this fn.
00187   PM.add(createMachineCodeConstructionPass(*this));
00188 
00189   // Insert empty stackslots in the stack frame of each function
00190   // so %fp+offset-8 and %fp+offset-16 are empty slots now!
00191   PM.add(createStackSlotsPass(*this));
00192   
00193   PM.add(createSparcV9BurgInstSelector(*this));
00194 
00195   if(PrintMachineCode)
00196     PM.add(createMachineFunctionPrinterPass(&std::cerr, "Before modulo scheduling:\n"));
00197 
00198   //Use ModuloScheduling if enabled, otherwise use local scheduling if not disabled.
00199   if(EnableModSched)
00200     PM.add(createModuloSchedulingPass(*this));
00201   else {
00202     if (!DisableSched)
00203       PM.add(createInstructionSchedulingWithSSAPass(*this));
00204   }
00205   
00206   if (PrintMachineCode)
00207     PM.add(createMachineFunctionPrinterPass(&std::cerr, "Before reg alloc:\n"));
00208 
00209   PM.add(getRegisterAllocator(*this));
00210 
00211   if (PrintMachineCode)
00212     PM.add(createMachineFunctionPrinterPass(&std::cerr, "After reg alloc:\n"));
00213 
00214   PM.add(createPrologEpilogInsertionPass());
00215 
00216   if (!DisablePeephole)
00217     PM.add(createPeepholeOptsPass(*this));
00218 
00219   if (PrintMachineCode)
00220     PM.add(createMachineFunctionPrinterPass(&std::cerr, "Final code:\n"));
00221 
00222   if (EmitMappingInfo) {
00223     PM.add(createInternalGlobalMapperPass());
00224     PM.add(getMappingInfoAsmPrinterPass(Out));
00225   }
00226 
00227   // Output assembly language to the .s file.  Assembly emission is split into
00228   // two parts: Function output and Global value output.  This is because
00229   // function output is pipelined with all of the rest of code generation stuff,
00230   // allowing machine code representations for functions to be free'd after the
00231   // function has been emitted.
00232   PM.add(createAsmPrinterPass(Out, *this));
00233 
00234   // Free machine-code IR which is no longer needed:
00235   PM.add(createSparcV9MachineCodeDestructionPass());
00236 
00237   // Emit bytecode to the assembly file into its special section next
00238   if (EmitMappingInfo)
00239     PM.add(createBytecodeAsmPrinterPass(Out));
00240   
00241   return false;
00242 }
00243 
00244 /// addPassesToJITCompile - This method controls the JIT method of code
00245 /// generation for the UltraSparcV9.
00246 ///
00247 void SparcV9JITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
00248   // FIXME: Implement efficient support for garbage collection intrinsics.
00249   PM.add(createLowerGCPass());
00250 
00251   // Replace malloc and free instructions with library calls.
00252   PM.add(createLowerAllocationsPass());
00253   
00254   // FIXME: implement the switch instruction in the instruction selector.
00255   PM.add(createLowerSwitchPass());
00256 
00257   // FIXME: implement the invoke/unwind instructions!
00258   PM.add(createLowerInvokePass());
00259   
00260   // decompose multi-dimensional array references into single-dim refs
00261   PM.add(createDecomposeMultiDimRefsPass());
00262 
00263   // Lower LLVM code to the form expected by the SPARCv9 instruction selector.
00264   PM.add(createPreSelectionPass(TM));
00265   PM.add(createLowerSelectPass());
00266 
00267   // Run basic LLVM dataflow optimizations, to clean up after pre-selection.
00268   PM.add(createReassociatePass());
00269   // FIXME: these passes crash the FunctionPassManager when being added...
00270   //PM.add(createLICMPass());
00271   //PM.add(createGCSEPass());
00272 
00273   // If the user's trying to read the generated code, they'll need to see the
00274   // transformed input.
00275   if (PrintMachineCode)
00276     PM.add(new PrintFunctionPass());
00277 
00278   // Construct and initialize the MachineFunction object for this fn.
00279   PM.add(createMachineCodeConstructionPass(TM));
00280 
00281   PM.add(createSparcV9BurgInstSelector(TM));
00282 
00283   if (PrintMachineCode)
00284     PM.add(createMachineFunctionPrinterPass(&std::cerr, "Before reg alloc:\n"));
00285 
00286   PM.add(getRegisterAllocator(TM));
00287 
00288   if (PrintMachineCode)
00289     PM.add(createMachineFunctionPrinterPass(&std::cerr, "After reg alloc:\n"));
00290 
00291   PM.add(createPrologEpilogInsertionPass());
00292 
00293   if (!DisablePeephole)
00294     PM.add(createPeepholeOptsPass(TM));
00295 
00296   if (PrintMachineCode)
00297     PM.add(createMachineFunctionPrinterPass(&std::cerr, "Final code:\n"));
00298 }
00299