diff options
author | JF Bastien <jfb@chromium.org> | 2013-07-20 19:35:41 -0700 |
---|---|---|
committer | JF Bastien <jfb@chromium.org> | 2013-07-20 19:35:41 -0700 |
commit | 1856bd7d7cb47f7ae32b7c848a8df5c28281e424 (patch) | |
tree | 5183147b68bd8c70e2975f794f1cf8e9d6a1dc74 /lib | |
parent | 58dfde724a201838b40f1314590ec4a1a7f2a601 (diff) |
Remove prefetch
Following our discussion in the related bug, prefetch will not be part of our initial stable ABI.
BUG= https://code.google.com/p/nativeclient/issues/detail?id=3531
TEST= cd ./pnacl/build/llvm_x86_64; ninja check
R=jvoung@chromium.org
Review URL: https://codereview.chromium.org/19771015
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Analysis/NaCl/PNaClABIVerifyModule.cpp | 1 | ||||
-rw-r--r-- | lib/Transforms/NaCl/RewriteLLVMIntrinsics.cpp | 123 |
2 files changed, 98 insertions, 26 deletions
diff --git a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp index a418246bae..2793d2ec96 100644 --- a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp +++ b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp @@ -316,7 +316,6 @@ bool AllowedIntrinsics::isAllowed(const Function *Func) { case Intrinsic::dbg_value: return PNaClABIAllowDevIntrinsics || PNaClABIAllowDebugMetadata; case Intrinsic::nacl_target_arch: // Used by translator self-build. - case Intrinsic::prefetch: // TODO(jfb): Use our own data-prefetch intrinsic instead. return PNaClABIAllowDevIntrinsics; } } diff --git a/lib/Transforms/NaCl/RewriteLLVMIntrinsics.cpp b/lib/Transforms/NaCl/RewriteLLVMIntrinsics.cpp index 17cd2347cc..9b3d3cea51 100644 --- a/lib/Transforms/NaCl/RewriteLLVMIntrinsics.cpp +++ b/lib/Transforms/NaCl/RewriteLLVMIntrinsics.cpp @@ -12,57 +12,130 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/Twine.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" #include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/NaCl.h" +#include <string> using namespace llvm; namespace { - class RewriteLLVMIntrinsics : public ModulePass { +class RewriteLLVMIntrinsics : public ModulePass { +public: + static char ID; + RewriteLLVMIntrinsics() : ModulePass(ID) { + // This is a module pass because this makes it easier to access uses + // of global intrinsic functions. + initializeRewriteLLVMIntrinsicsPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnModule(Module &M); + + /// Rewrite an intrinsic to something different. + class IntrinsicRewriter { public: - static char ID; - RewriteLLVMIntrinsics() : ModulePass(ID) { - // This is a module pass because this makes it easier to access uses - // of global intrinsic functions. - initializeRewriteLLVMIntrinsicsPass(*PassRegistry::getPassRegistry()); - } + Function *function() const { return F; } + /// Called once per \p Call of the Intrinsic Function. + void rewriteCall(CallInst *Call) { doRewriteCall(Call); } + + protected: + IntrinsicRewriter(Module &M, Intrinsic::ID IntrinsicID) + : F(Intrinsic::getDeclaration(&M, IntrinsicID)) {} + virtual ~IntrinsicRewriter() {} + /// This pure virtual method must be defined by implementors, and + /// will be called by rewriteCall. + virtual void doRewriteCall(CallInst *Call) = 0; - virtual bool runOnModule(Module &M); + Function *F; + + private: + IntrinsicRewriter() LLVM_DELETED_FUNCTION; + IntrinsicRewriter(const IntrinsicRewriter &) LLVM_DELETED_FUNCTION; + IntrinsicRewriter &operator=( + const IntrinsicRewriter &) LLVM_DELETED_FUNCTION; }; + +private: + /// Visit all uses of a Function, rewrite it using the \p Rewriter, + /// and then delete the Call. Later delete the Function from the + /// Module. Returns true if the Module was changed. + bool visitUses(IntrinsicRewriter &Rewriter); +}; + +/// Rewrite a Call to nothing. +class ToNothing : public RewriteLLVMIntrinsics::IntrinsicRewriter { +public: + ToNothing(Module &M, Intrinsic::ID IntrinsicID) + : IntrinsicRewriter(M, IntrinsicID) {} + virtual ~ToNothing() {} + +protected: + virtual void doRewriteCall(CallInst *Call) { + // Nothing to do: the visit does the deletion. + } +}; + +/// Rewrite a Call to a ConstantInt of the same type. +class ToConstantInt : public RewriteLLVMIntrinsics::IntrinsicRewriter { +public: + ToConstantInt(Module &M, Intrinsic::ID IntrinsicID, uint64_t Value) + : IntrinsicRewriter(M, IntrinsicID), Value(Value), + RetType(function()->getFunctionType()->getReturnType()) {} + virtual ~ToConstantInt() {} + +protected: + virtual void doRewriteCall(CallInst *Call) { + Constant *C = ConstantInt::get(RetType, Value); + Call->replaceAllUsesWith(C); + } + +private: + uint64_t Value; + Type *RetType; +}; } char RewriteLLVMIntrinsics::ID = 0; INITIALIZE_PASS(RewriteLLVMIntrinsics, "rewrite-llvm-intrinsic-calls", - "Rewrite LLVM intrinsic calls to simpler expressions", - false, false) + "Rewrite LLVM intrinsic calls to simpler expressions", false, + false) bool RewriteLLVMIntrinsics::runOnModule(Module &M) { - bool Changed = false; + // Replace all uses of the @llvm.flt.rounds intrinsic with the constant + // "1" (round-to-nearest). Until we add a second intrinsic like + // @llvm.set.flt.round it is impossible to have a rounding mode that is + // not the initial rounding mode (round-to-nearest). We can remove + // this rewrite after adding a set() intrinsic. + ToConstantInt FltRoundsRewriter(M, Intrinsic::flt_rounds, 1); - // Iterate over all uses of the llvm.flt.rounds, and replace it with - // the constant "1" (round-to-nearest). Until we add a second intrinsic - // like llvm.set.flt.round it is impossible to have a rounding mode - // that is not the initial rounding mode (round-to-nearest). - // We can remove this rewrite after adding a set() intrinsic. - Function *FltRounds = Intrinsic::getDeclaration(&M, Intrinsic::flt_rounds); - Type *RetType = FltRounds->getFunctionType()->getReturnType(); - for (Value::use_iterator UI = FltRounds->use_begin(), - UE = FltRounds->use_end(); UI != UE;) { + // Remove all @llvm.prefetch intrinsics. + ToNothing PrefetchRewriter(M, Intrinsic::prefetch); + + return visitUses(FltRoundsRewriter) | visitUses(PrefetchRewriter); +} + +bool RewriteLLVMIntrinsics::visitUses(IntrinsicRewriter &Rewriter) { + bool Changed = false; + Function *F = Rewriter.function(); + for (Value::use_iterator UI = F->use_begin(), UE = F->use_end(); UI != UE;) { Value *Use = *UI++; if (CallInst *Call = dyn_cast<CallInst>(Use)) { - Constant *C = ConstantInt::get(RetType, 1); - Call->replaceAllUsesWith(C); + Rewriter.rewriteCall(Call); Call->eraseFromParent(); Changed = true; } else { - report_fatal_error("Taking the address of llvm.flt.rounds is invalid"); + // Intrinsics we care about currently don't need to handle this case. + std::string S; + raw_string_ostream OS(S); + OS << "Taking the address of this intrinsic is invalid: " << *Use; + report_fatal_error(OS.str()); } } - FltRounds->eraseFromParent(); - + F->eraseFromParent(); return Changed; } |