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