Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 1 | From 7e36390f24f6ceaea7bc2ba4adcd55d06cf73439 Mon Sep 17 00:00:00 2001 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 2 | From: Yabin Hu <yabin.hwu@gmail.com> |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 3 | Date: Thu, 29 Nov 2012 16:08:29 +0800 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 4 | Subject: [PATCH] Add llvm.codegen intrinsic. |
| 5 | |
| 6 | The llvm.codegen intrinsic generates code for embedded LLVM-IR |
| 7 | strings. Each call to the intrinsic is replaced by a pointer to |
| 8 | the newly generated target code. The code generation target can be |
| 9 | different to the one of the parent module. |
| 10 | --- |
| 11 | docs/LangRef.html | 36 +++ |
| 12 | include/llvm/CodeGen/Passes.h | 3 + |
| 13 | include/llvm/InitializePasses.h | 1 + |
| 14 | include/llvm/Intrinsics.td | 4 + |
| 15 | lib/CodeGen/CMakeLists.txt | 1 + |
| 16 | lib/CodeGen/CodeGen.cpp | 1 + |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 17 | lib/CodeGen/CodeGenIntrinsic.cpp | 227 ++++++++++++++++++++ |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 18 | lib/CodeGen/Passes.cpp | 3 + |
Tobias Grosser | 1b593a1 | 2012-07-01 13:47:50 | [diff] [blame] | 19 | lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 2 + |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 20 | lib/Target/LLVMBuild.txt | 2 +- |
| 21 | lib/VMCore/Verifier.cpp | 10 + |
| 22 | .../CodeGen/X86/EmbeddedCG/embedded-codegen-ptx.ll | 28 +++ |
| 23 | test/CodeGen/X86/EmbeddedCG/lit.local.cfg | 5 + |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 24 | 13 files changed, 322 insertions(+), 1 deletions(-) |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 25 | create mode 100644 lib/CodeGen/CodeGenIntrinsic.cpp |
| 26 | create mode 100644 test/CodeGen/X86/EmbeddedCG/embedded-codegen-ptx.ll |
| 27 | create mode 100644 test/CodeGen/X86/EmbeddedCG/lit.local.cfg |
| 28 | |
| 29 | diff --git a/docs/LangRef.html b/docs/LangRef.html |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 30 | index cfc1c7d..eae069e 100644 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 31 | --- a/docs/LangRef.html |
| 32 | +++ b/docs/LangRef.html |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 33 | @@ -243,6 +243,7 @@ |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 34 | <li><a href="#int_prefetch">'<tt>llvm.prefetch</tt>' Intrinsic</a></li> |
| 35 | <li><a href="#int_pcmarker">'<tt>llvm.pcmarker</tt>' Intrinsic</a></li> |
| 36 | <li><a href="#int_readcyclecounter">'<tt>llvm.readcyclecounter</tt>' Intrinsic</a></li> |
| 37 | + <li><a href="#int_codegen_intrinsic">'<tt>llvm.codegen</tt>' Intrinsic</a></li> |
| 38 | </ol> |
| 39 | </li> |
| 40 | <li><a href="#int_libc">Standard C Library Intrinsics</a> |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 41 | @@ -7249,6 +7250,41 @@ LLVM</a>.</p> |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 42 | |
| 43 | </div> |
| 44 | |
| 45 | +<!-- _______________________________________________________________________ --> |
| 46 | +<h4> |
| 47 | + <a name="int_codegen_intrinsic">'<tt>llvm.codegen</tt>' Intrinsic</a> |
| 48 | +</h4> |
| 49 | + |
| 50 | +<div> |
| 51 | + |
| 52 | +<h5>Syntax:</h5> |
| 53 | +<pre> |
| 54 | + declare i8* @llvm.codegen(i8* <IRString>, i8* <MCPU>, i8* < |
| 55 | + Features>) |
| 56 | +</pre> |
| 57 | + |
| 58 | +<h5>Overview:</h5> |
| 59 | +<p>The '<tt>llvm.codegen</tt>' intrinsic uses the LLVM back ends to generate |
| 60 | + code for embedded LLVM-IR strings. The code generation target can be |
| 61 | + different to the one of the parent module.</p> |
| 62 | + |
| 63 | +<h5>Arguments:</h5> |
| 64 | +<p><tt>IRString</tt> is a string containing LLVM-IR.</p> |
| 65 | +<p><tt>MCPU</tt> is the name of the target CPU.</p> |
| 66 | +<p><tt>Features</tt> is the string representation of the additional target |
| 67 | + features.</p> |
| 68 | + |
| 69 | +<h5>Semantics:</h5> |
| 70 | +<p>The '<tt>llvm.codegen</tt>' intrinsic transforms a string containing LLVM IR |
| 71 | + to target assembly code. Calls to the intrinsic are replaced by a pointer to |
| 72 | + the newly generated target code. In case LLVM can not generate code (e.g. the |
| 73 | + target is not available), the call to the intrinsic is replaced by a i8 NULL |
| 74 | + pointer.Users of this intrinsic should make sure the target triple is |
| 75 | + properly set in the <IRString>. Inputs to both <MCPU> and |
| 76 | + <Features> parameters can be null pointers.</p> |
| 77 | + |
| 78 | +</div> |
| 79 | + |
| 80 | </div> |
| 81 | |
| 82 | <!-- ======================================================================= --> |
| 83 | diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 84 | index 44c9676..57b3aa2 100644 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 85 | --- a/include/llvm/CodeGen/Passes.h |
| 86 | +++ b/include/llvm/CodeGen/Passes.h |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 87 | @@ -432,6 +432,9 @@ namespace llvm { |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 88 | /// branch folding). |
| 89 | extern char &GCMachineCodeAnalysisID; |
| 90 | |
| 91 | + /// CodeGenIntrinsic Pass - Create target code for embedded LLVM-IR strings. |
| 92 | + FunctionPass *createCodeGenIntrinsicPass(); |
| 93 | + |
| 94 | /// Deleter Pass - Releases GC metadata. |
| 95 | /// |
| 96 | FunctionPass *createGCInfoDeleter(); |
| 97 | diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 98 | index e06b892..fe8655e 100644 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 99 | --- a/include/llvm/InitializePasses.h |
| 100 | +++ b/include/llvm/InitializePasses.h |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 101 | @@ -93,6 +93,7 @@ void initializeCorrelatedValuePropagationPass(PassRegistry&); |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 102 | void initializeDAEPass(PassRegistry&); |
| 103 | void initializeDAHPass(PassRegistry&); |
| 104 | void initializeDCEPass(PassRegistry&); |
| 105 | +void initializeCodeGenIntrinsicPass(PassRegistry&); |
| 106 | void initializeDSEPass(PassRegistry&); |
| 107 | void initializeDeadInstEliminationPass(PassRegistry&); |
| 108 | void initializeDeadMachineInstructionElimPass(PassRegistry&); |
| 109 | diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 110 | index d3a548c..a60d2bb 100644 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 111 | --- a/include/llvm/Intrinsics.td |
| 112 | +++ b/include/llvm/Intrinsics.td |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 113 | @@ -238,6 +238,10 @@ def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>; |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 114 | // guard to the correct place on the stack frame. |
| 115 | def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>; |
| 116 | |
| 117 | +//===----------------- Code Generation for Embedded LLVM-IR ---------------===// |
| 118 | +def int_codegen : Intrinsic<[llvm_ptr_ty], |
| 119 | + [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty]>; |
| 120 | + |
| 121 | //===------------------- Standard C Library Intrinsics --------------------===// |
| 122 | // |
| 123 | |
| 124 | diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 125 | index 7a20ff6..8e1ab9a 100644 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 126 | --- a/lib/CodeGen/CMakeLists.txt |
| 127 | +++ b/lib/CodeGen/CMakeLists.txt |
| 128 | @@ -6,6 +6,7 @@ add_llvm_library(LLVMCodeGen |
| 129 | CalcSpillWeights.cpp |
| 130 | CallingConvLower.cpp |
| 131 | CodeGen.cpp |
| 132 | + CodeGenIntrinsic.cpp |
| 133 | CodePlacementOpt.cpp |
| 134 | CriticalAntiDepBreaker.cpp |
| 135 | DeadMachineInstructionElim.cpp |
| 136 | diff --git a/lib/CodeGen/CodeGen.cpp b/lib/CodeGen/CodeGen.cpp |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 137 | index a53f6f8..702ee18 100644 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 138 | --- a/lib/CodeGen/CodeGen.cpp |
| 139 | +++ b/lib/CodeGen/CodeGen.cpp |
| 140 | @@ -21,6 +21,7 @@ using namespace llvm; |
| 141 | void llvm::initializeCodeGen(PassRegistry &Registry) { |
| 142 | initializeBranchFolderPassPass(Registry); |
| 143 | initializeCalculateSpillWeightsPass(Registry); |
| 144 | + initializeCodeGenIntrinsicPass(Registry); |
| 145 | initializeCodePlacementOptPass(Registry); |
| 146 | initializeDeadMachineInstructionElimPass(Registry); |
Tobias Grosser | 9e97ae1 | 2012-08-02 08:16:40 | [diff] [blame] | 147 | initializeEarlyIfConverterPass(Registry); |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 148 | diff --git a/lib/CodeGen/CodeGenIntrinsic.cpp b/lib/CodeGen/CodeGenIntrinsic.cpp |
| 149 | new file mode 100644 |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 150 | index 0000000..cf8aa54 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 151 | --- /dev/null |
| 152 | +++ b/lib/CodeGen/CodeGenIntrinsic.cpp |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 153 | @@ -0,0 +1,227 @@ |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 154 | +//===-- CodeGenIntrinsic.cpp - CodeGen Intrinsic --------------------------===// |
| 155 | +// |
| 156 | +// The LLVM Compiler Infrastructure |
| 157 | +// |
| 158 | +// This file is distributed under the University of Illinois Open Source |
| 159 | +// License. See LICENSE.TXT for details. |
| 160 | +// |
| 161 | +//===----------------------------------------------------------------------===// |
| 162 | +// |
| 163 | +// This file implements the llvm.codegen intrinsic. |
| 164 | +// |
| 165 | +//===----------------------------------------------------------------------===// |
| 166 | + |
| 167 | +#include "llvm/CodeGen/Passes.h" |
| 168 | +#include "llvm/CallingConv.h" |
Chandler Carruth | c55b598 | 2012-06-29 12:39:49 | [diff] [blame] | 169 | +#include "llvm/IRBuilder.h" |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 170 | +#include "llvm/IntrinsicInst.h" |
| 171 | +#include "llvm/LLVMContext.h" |
| 172 | +#include "llvm/Module.h" |
| 173 | +#include "llvm/PassManager.h" |
Chandler Carruth | e243b03 | 2014-01-07 12:59:58 | [diff] [blame] | 174 | +#include "llvm/AsmParser/Parser.h" |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 175 | +#include "llvm/Target/TargetMachine.h" |
| 176 | +#include "llvm/Target/TargetRegisterInfo.h" |
| 177 | +#include "llvm/Support/Debug.h" |
| 178 | +#include "llvm/Support/ErrorHandling.h" |
| 179 | +#include "llvm/Support/FormattedStream.h" |
| 180 | +#include "llvm/Support/Host.h" |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 181 | +#include "llvm/Support/raw_ostream.h" |
| 182 | +#include "llvm/Support/SourceMgr.h" |
| 183 | +#include "llvm/Support/TargetRegistry.h" |
| 184 | +#include "llvm/ADT/Triple.h" |
| 185 | + |
| 186 | +using namespace llvm; |
| 187 | + |
| 188 | +namespace { |
| 189 | + /// ASMGenerator generates target-specific assembly code from LLVM IR. |
| 190 | + class ASMGenerator { |
| 191 | + public: |
| 192 | + ASMGenerator() {} |
| 193 | + |
| 194 | + /// generate - Generates a target code string from a LLVM IR Value. |
| 195 | + bool generate(Value *IRStr, Value *MCPUStr, Value *FeaturesStr, |
| 196 | + std::string &ASM); |
| 197 | + |
| 198 | + private: |
| 199 | + bool getStringFromConstantExpr(Value *ConstData, std::string &Out) const; |
| 200 | + }; |
| 201 | + |
| 202 | + /// CodeGenIntrinsic - This pass replaces each call to the llvm.codegen |
| 203 | + /// intrinsic with a string generated by ASMGenerator. |
| 204 | + class CodeGenIntrinsic : public FunctionPass { |
| 205 | + public: |
| 206 | + static char ID; |
| 207 | + |
| 208 | + CodeGenIntrinsic(); |
| 209 | + const char *getPassName() const; |
| 210 | + virtual bool runOnFunction(Function &F); |
| 211 | + }; |
| 212 | +} |
| 213 | + |
| 214 | +// ----------------------------------------------------------------------------- |
| 215 | +static bool getTargetMachineFromModule(Module *M, const StringRef &TripleStr, |
| 216 | + const StringRef &MCPU, |
| 217 | + const StringRef &Features, |
| 218 | + TargetMachine *&TM) { |
| 219 | + std::string ErrMsg; |
| 220 | + const Target *TheTarget = TargetRegistry::lookupTarget(TripleStr, ErrMsg); |
| 221 | + if (!TheTarget) { |
| 222 | + errs() << ErrMsg << "\n"; |
| 223 | + return false; |
| 224 | + } |
| 225 | + |
| 226 | + TargetOptions Options; |
| 227 | + TM = TheTarget->createTargetMachine(TripleStr, MCPU, Features, Options); |
| 228 | + assert(TM && "Could not allocate target machine!"); |
| 229 | + return true; |
| 230 | +} |
| 231 | + |
| 232 | +static bool createASMAsString(Module *New, const StringRef &Triple, |
| 233 | + const StringRef &MCPU, const StringRef &Features, |
| 234 | + std::string &ASM) { |
| 235 | + TargetMachine *Target; |
| 236 | + if (!getTargetMachineFromModule(New, Triple, MCPU, Features, Target)) { |
| 237 | + return false; |
| 238 | + } |
| 239 | + |
| 240 | + // Build up all of the passes that we want to do to the module. |
| 241 | + PassManager PM; |
| 242 | + |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 243 | + // Get the data layout of the new module. If it is empty, return false. |
| 244 | + const std::string &ModuleDataLayout = New->getDataLayout(); |
| 245 | + if (ModuleDataLayout.empty()) |
| 246 | + return false; |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 247 | + |
| 248 | + { |
| 249 | + raw_string_ostream NameROS(ASM); |
| 250 | + formatted_raw_ostream FOS(NameROS); |
| 251 | + |
| 252 | + // Ask the target to add backend passes as necessary. |
| 253 | + int UseVerifier = true; |
| 254 | + if (Target->addPassesToEmitFile(PM, FOS, TargetMachine::CGFT_AssemblyFile, |
| 255 | + UseVerifier)) { |
| 256 | + errs() << "CodeGen Intrinsic: target does not support generation of this " |
| 257 | + << "file type!\n"; |
| 258 | + |
| 259 | + return false; |
| 260 | + } |
| 261 | + |
| 262 | + PM.run(*New); |
| 263 | + FOS.flush(); |
| 264 | + } |
| 265 | + |
| 266 | + delete Target; |
| 267 | + return true; |
| 268 | +} |
| 269 | + |
| 270 | +bool ASMGenerator::getStringFromConstantExpr(Value *ConstData, |
| 271 | + std::string &Out) const { |
| 272 | + bool Result = false; |
| 273 | + if (ConstantExpr *U = dyn_cast<ConstantExpr>(ConstData)) { |
| 274 | + Value *R = U->getOperand(0); |
| 275 | + if (GlobalVariable *GV = dyn_cast<GlobalVariable>(R)) { |
| 276 | + Constant *C = GV->getInitializer(); |
| 277 | + if (ConstantDataArray *CA = dyn_cast<ConstantDataArray>(C)) { |
| 278 | + Out = CA->getAsString(); |
| 279 | + Result = true; |
| 280 | + } |
| 281 | + } |
| 282 | + } |
| 283 | + return Result; |
| 284 | +} |
| 285 | + |
| 286 | +bool ASMGenerator::generate(Value *IRStr, Value *MCPUStr, Value *FeaturesStr, |
| 287 | + std::string &ASM) { |
| 288 | + std::string Kernel; |
| 289 | + if (!getStringFromConstantExpr(IRStr, Kernel)) |
| 290 | + return false; |
| 291 | + |
| 292 | + std::string MCPU; |
| 293 | + if (!getStringFromConstantExpr(MCPUStr, MCPU)) |
| 294 | + MCPU = ""; |
| 295 | + |
| 296 | + std::string Features; |
| 297 | + if (!getStringFromConstantExpr(FeaturesStr, Features)) |
| 298 | + Features = ""; |
| 299 | + |
| 300 | + SMDiagnostic ErrorMessage; |
| 301 | + LLVMContext Context; |
| 302 | + std::auto_ptr<Module> TempModule( |
| 303 | + ParseAssemblyString(Kernel.c_str(), 0, ErrorMessage, Context)); |
| 304 | + |
| 305 | + Triple TheTriple(TempModule->getTargetTriple()); |
| 306 | + const std::string TripleStr = TheTriple.getTriple(); |
| 307 | + if(TripleStr.empty()) { |
| 308 | + errs() << "error: Target triple isn't set correctly for the new module.\n"; |
| 309 | + return false; |
| 310 | + } |
| 311 | + |
| 312 | + return createASMAsString(TempModule.get(), TripleStr.data(), MCPU.data(), |
| 313 | + Features.data(), ASM); |
| 314 | +} |
| 315 | + |
| 316 | +// ----------------------------------------------------------------------------- |
| 317 | +INITIALIZE_PASS(CodeGenIntrinsic, "codegen-intrinsic", "CodeGen Intrinsic", |
| 318 | + false, false) |
| 319 | + |
| 320 | +FunctionPass *llvm::createCodeGenIntrinsicPass() { |
| 321 | + return new CodeGenIntrinsic(); |
| 322 | +} |
| 323 | + |
| 324 | +char CodeGenIntrinsic::ID = 0; |
| 325 | + |
| 326 | +CodeGenIntrinsic::CodeGenIntrinsic() |
| 327 | + : FunctionPass(ID) { |
| 328 | +} |
| 329 | + |
| 330 | +const char *CodeGenIntrinsic::getPassName() const { |
| 331 | + return "Lowering CodeGen Intrinsic."; |
| 332 | +} |
| 333 | + |
| 334 | +bool CodeGenIntrinsic::runOnFunction(Function &F) { |
| 335 | + bool MadeChange = false; |
| 336 | + Module *M = F.getParent(); |
| 337 | + if (Function *CG = M->getFunction("llvm.codegen")) { |
| 338 | + for (Function::use_iterator I = CG->use_begin(), E = CG->use_end(); |
| 339 | + I != E; ++I) { |
| 340 | + if (CallInst *CI = dyn_cast<CallInst>(*I)) { |
| 341 | + if (&F != CI->getParent()->getParent()) |
| 342 | + continue; |
| 343 | + |
| 344 | + std::string ASM; |
| 345 | + ASMGenerator *Generator = new ASMGenerator(); |
| 346 | + IRBuilder<> Builder(CI->getParent(), CI); |
| 347 | + Value *St; |
| 348 | + if (!Generator->generate(CI->getArgOperand(0), CI->getArgOperand(1), |
| 349 | + CI->getArgOperand(2), ASM)) { |
| 350 | + Type *Ty= CG->getReturnType(); |
| 351 | + St = Constant::getNullValue(Ty); |
| 352 | + } else { |
| 353 | + // FIXME: Is this actually dangerous as WritingAnLLVMPass.html claims? |
| 354 | + // Seems that, short of multithreaded LLVM, it should be safe; |
| 355 | + // all that is necessary is that a simple Module::iterator loop |
| 356 | + // not be invalidated. Appending to the GlobalVariable list is |
| 357 | + // safe in that sense. |
| 358 | + // |
| 359 | + // All the output passes emit globals last. The ExecutionEngine |
| 360 | + // explicitly supports adding globals to the module after |
| 361 | + // initialization. |
| 362 | + // |
| 363 | + // Still, if it isn't deemed acceptable, then this |
| 364 | + // transformation needs to be a ModulePass (which means it |
| 365 | + // cannot be in the 'llc' pipeline (which uses a |
| 366 | + // FunctionPassManager (which segfaults (not asserts) if |
| 367 | + // provided a ModulePass))). |
| 368 | + St = Builder.CreateGlobalStringPtr(ASM, "ASM"); |
| 369 | + } |
| 370 | + CI->replaceAllUsesWith(St); |
| 371 | + CI->eraseFromParent(); |
| 372 | + // We should erase the unused globals from current module. But we |
| 373 | + // can't do this within a FunctionPass. |
| 374 | + MadeChange = true; |
| 375 | + } |
| 376 | + } |
| 377 | + } |
| 378 | + |
| 379 | + return MadeChange; |
| 380 | +} |
| 381 | diff --git a/lib/CodeGen/Passes.cpp b/lib/CodeGen/Passes.cpp |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 382 | index 526d994..1de0c63 100644 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 383 | --- a/lib/CodeGen/Passes.cpp |
| 384 | +++ b/lib/CodeGen/Passes.cpp |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 385 | @@ -369,6 +369,9 @@ void TargetPassConfig::addIRPasses() { |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 386 | |
Tobias Grosser | b266c98 | 2012-07-03 08:18:31 | [diff] [blame] | 387 | addPass(createGCLoweringPass()); |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 388 | |
| 389 | + // Generate target code for embedded LLVM-IR strings. |
Tobias Grosser | b266c98 | 2012-07-03 08:18:31 | [diff] [blame] | 390 | + addPass(createCodeGenIntrinsicPass()); |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 391 | + |
| 392 | // Make sure that no unreachable blocks are instruction selected. |
Tobias Grosser | b266c98 | 2012-07-03 08:18:31 | [diff] [blame] | 393 | addPass(createUnreachableBlockEliminationPass()); |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 394 | } |
| 395 | diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 396 | index 56e774c..97006c0 100644 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 397 | --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp |
| 398 | +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 399 | @@ -5169,6 +5169,8 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { |
Tobias Grosser | 1b593a1 | 2012-07-01 13:47:50 | [diff] [blame] | 400 | case Intrinsic::donothing: |
| 401 | // ignore |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 402 | return 0; |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 403 | + case Intrinsic::codegen: |
| 404 | + llvm_unreachable("failed to lower codegen intrinsic!"); |
| 405 | } |
| 406 | } |
| 407 | |
| 408 | diff --git a/lib/Target/LLVMBuild.txt b/lib/Target/LLVMBuild.txt |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 409 | index eb6c779..a54f57c 100644 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 410 | --- a/lib/Target/LLVMBuild.txt |
| 411 | +++ b/lib/Target/LLVMBuild.txt |
| 412 | @@ -45,7 +45,7 @@ parent = Libraries |
| 413 | type = Library |
| 414 | name = Target |
| 415 | parent = Libraries |
| 416 | -required_libraries = Core MC Support |
| 417 | +required_libraries = Core MC Support AsmParser |
| 418 | |
| 419 | ; This is a special group whose required libraries are extended (by llvm-build) |
| 420 | ; with every built target, which makes it easy for tools to include every |
| 421 | diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 422 | index 3782957..896772a 100644 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 423 | --- a/lib/VMCore/Verifier.cpp |
| 424 | +++ b/lib/VMCore/Verifier.cpp |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 425 | @@ -1952,6 +1952,16 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 426 | Assert1(isa<ConstantInt>(CI.getArgOperand(1)), |
| 427 | "llvm.invariant.end parameter #2 must be a constant integer", &CI); |
| 428 | break; |
| 429 | + case Intrinsic::codegen: |
| 430 | + Assert1(isa<ConstantExpr>(CI.getArgOperand(0)), |
| 431 | + "llvm.codegen parameter #1 must be a constant expression", &CI); |
| 432 | + Assert1(isa<ConstantExpr>(CI.getArgOperand(1)) || |
| 433 | + isa<ConstantPointerNull>(CI.getArgOperand(1)), |
| 434 | + "llvm.codegen parameter #2 must be a constant expression", &CI); |
| 435 | + Assert1(isa<ConstantExpr>(CI.getArgOperand(2)) || |
| 436 | + isa<ConstantPointerNull>(CI.getArgOperand(2)), |
| 437 | + "llvm.codegen parameter #3 must be a constant expression", &CI); |
| 438 | + break; |
| 439 | } |
| 440 | } |
| 441 | |
| 442 | diff --git a/test/CodeGen/X86/EmbeddedCG/embedded-codegen-ptx.ll b/test/CodeGen/X86/EmbeddedCG/embedded-codegen-ptx.ll |
| 443 | new file mode 100644 |
Tobias Grosser | 822b254 | 2012-07-03 08:18:34 | [diff] [blame] | 444 | index 0000000..73d34e1 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 445 | --- /dev/null |
| 446 | +++ b/test/CodeGen/X86/EmbeddedCG/embedded-codegen-ptx.ll |
| 447 | @@ -0,0 +1,28 @@ |
| 448 | +; RUN: llc < %s -march=x86 | FileCheck %s |
| 449 | + |
| 450 | +; ModuleID = 'embedded-codegen-ptx.ll' |
| 451 | +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" |
| 452 | +target triple = "i386-pc-linux-gnu" |
| 453 | + |
Tobias Grosser | 822b254 | 2012-07-03 08:18:34 | [diff] [blame] | 454 | +@llvm_kernel = private unnamed_addr constant [1940 x i8] c"target triple = \22nvptx-unknown-unknown\22\0A\0Adefine internal ptx_kernel void @gpu_codegen.ptx_subfn(i8* %ptx.Array) {\0Aptx.setup:\0A %0 = bitcast i8* %ptx.Array to [128 x [128 x i32]]*\0A %1 = call i32 @llvm.ptx.read.nctaid.x()\0A %2 = zext i32 %1 to i64\0A %3 = call i32 @llvm.ptx.read.nctaid.y()\0A %4 = zext i32 %3 to i64\0A %5 = call i32 @llvm.ptx.read.ntid.x()\0A %6 = zext i32 %5 to i64\0A %7 = call i32 @llvm.ptx.read.ntid.y()\0A %8 = zext i32 %7 to i64\0A %9 = call i32 @llvm.ptx.read.ctaid.x()\0A %10 = zext i32 %9 to i64\0A %11 = call i32 @llvm.ptx.read.ctaid.y()\0A %12 = zext i32 %11 to i64\0A %13 = call i32 @llvm.ptx.read.tid.x()\0A %14 = zext i32 %13 to i64\0A %15 = call i32 @llvm.ptx.read.tid.y()\0A %16 = zext i32 %15 to i64\0A br label %ptx.loop_body\0A\0Aptx.exit: ; preds = %polly.stmt.for.body3\0A ret void\0A\0Aptx.loop_body: ; preds = %ptx.setup\0A %p_gpu_index_i = mul i64 %12, %2\0A %17 = add i64 %p_gpu_index_i, %10\0A %p_gpu_index_j = mul i64 %16, %6\0A %18 = add i64 %p_gpu_index_j, %14\0A br label %polly.stmt.for.body3\0A\0Apolly.stmt.for.body3: ; preds = %ptx.loop_body\0A %19 = trunc i64 %17 to i32\0A %p_mul = shl nsw i32 %19, 7\0A %20 = trunc i64 %18 to i32\0A %p_add = add nsw i32 %p_mul, %20\0A %21 = trunc i64 %17 to i32\0A %22 = trunc i64 %18 to i32\0A %p_arrayidx4 = getelementptr inbounds [128 x [128 x i32]]* %0, i32 0, i32 %21, i32 %22\0A store i32 %p_add, i32* %p_arrayidx4\0A br label %ptx.exit\0A}\0A\0Adeclare i32 @llvm.ptx.read.nctaid.x() nounwind readnone\0A\0Adeclare i32 @llvm.ptx.read.nctaid.y() nounwind readnone\0A\0Adeclare i32 @llvm.ptx.read.ctaid.x() nounwind readnone\0A\0Adeclare i32 @llvm.ptx.read.ctaid.y() nounwind readnone\0A\0Adeclare i32 @llvm.ptx.read.ntid.x() nounwind readnone\0A\0Adeclare i32 @llvm.ptx.read.ntid.y() nounwind readnone\0A\0Adeclare i32 @llvm.ptx.read.tid.x() nounwind readnone\0A\0Adeclare i32 @llvm.ptx.read.tid.y() nounwind readnone\0A\00" |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 455 | + |
| 456 | +@.str = private unnamed_addr constant [3 x i8] c"%s\00", align 1 |
| 457 | + |
| 458 | +define i32 @gpu_codegen() nounwind { |
| 459 | +entry: |
Tobias Grosser | 822b254 | 2012-07-03 08:18:34 | [diff] [blame] | 460 | + %0 = call i8* @llvm.codegen(i8* getelementptr inbounds ([1940 x i8]* @llvm_kernel, i32 0, i32 0), i8* null, i8* null) |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 461 | + %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([3 x i8]* @.str, i32 0, i32 0), i8* %0) |
| 462 | + ret i32 0 |
| 463 | +} |
| 464 | + |
| 465 | +define i32 @main() nounwind { |
| 466 | +entry: |
| 467 | + %call = call i32 @gpu_codegen() |
| 468 | + ret i32 0 |
| 469 | +} |
| 470 | + |
| 471 | +declare i8* @llvm.codegen(i8*, i8*, i8*) nounwind |
| 472 | + |
| 473 | +declare i32 @printf(i8*, ...) nounwind |
| 474 | + |
Tobias Grosser | 822b254 | 2012-07-03 08:18:34 | [diff] [blame] | 475 | +; CHECK: gpu_codegen_2E_ptx_subfn |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 476 | diff --git a/test/CodeGen/X86/EmbeddedCG/lit.local.cfg b/test/CodeGen/X86/EmbeddedCG/lit.local.cfg |
| 477 | new file mode 100644 |
Tobias Grosser | 822b254 | 2012-07-03 08:18:34 | [diff] [blame] | 478 | index 0000000..7180c84 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 479 | --- /dev/null |
| 480 | +++ b/test/CodeGen/X86/EmbeddedCG/lit.local.cfg |
| 481 | @@ -0,0 +1,5 @@ |
| 482 | +config.suffixes = ['.ll', '.c', '.cpp'] |
| 483 | + |
| 484 | +targets = set(config.root.targets_to_build.split()) |
Tobias Grosser | 822b254 | 2012-07-03 08:18:34 | [diff] [blame] | 485 | +if not 'NVPTX' in targets: |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 486 | + config.unsupported = True |
| 487 | -- |
Tobias Grosser | 5087d0a | 2012-11-29 17:34:50 | [diff] [blame] | 488 | 1.7.6.5 |
Tobias Grosser | 8d7c4db | 2012-05-30 13:53:57 | [diff] [blame] | 489 | |