Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(571)

Unified Diff: lib/Transforms/NaCl/RewriteLLVMIntrinsics.cpp

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/Transforms/NaCl/RewriteAtomics.cpp ('k') | lib/Transforms/NaCl/RewritePNaClLibraryCalls.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/Transforms/NaCl/RewriteLLVMIntrinsics.cpp
diff --git a/lib/Transforms/NaCl/RewriteLLVMIntrinsics.cpp b/lib/Transforms/NaCl/RewriteLLVMIntrinsics.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a11dd0f5b096917d1a6278180e780daa23a7adf8
--- /dev/null
+++ b/lib/Transforms/NaCl/RewriteLLVMIntrinsics.cpp
@@ -0,0 +1,148 @@
+//===- RewriteLLVMIntrinsics.cpp - Rewrite LLVM intrinsics to other values ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass replaces calls to LLVM intrinsics that are *not* part of the
+// PNaCl stable bitcode ABI into simpler values.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/IR/Constants.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 {
+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:
+ 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;
+
+ 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)
+
+bool RewriteLLVMIntrinsics::runOnModule(Module &M) {
+ // 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);
+
+ // Remove all @llvm.prefetch intrinsics.
+ ToNothing PrefetchRewriter(M, Intrinsic::prefetch);
+
+ return visitUses(FltRoundsRewriter) | visitUses(PrefetchRewriter);
+}
+
+bool RewriteLLVMIntrinsics::visitUses(IntrinsicRewriter &Rewriter) {
+ Function *F = Rewriter.function();
+ SmallVector<CallInst *, 64> Calls;
+ for (User *U : F->users()) {
+ if (CallInst *Call = dyn_cast<CallInst>(U)) {
+ Calls.push_back(Call);
+ } else {
+ // 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: " << *U;
+ report_fatal_error(OS.str());
+ }
+ }
+
+ for (auto Call : Calls) {
+ Rewriter.rewriteCall(Call);
+ Call->eraseFromParent();
+ }
+
+ F->eraseFromParent();
+ return !Calls.empty();
+}
+
+ModulePass *llvm::createRewriteLLVMIntrinsicsPass() {
+ return new RewriteLLVMIntrinsics();
+}
« no previous file with comments | « lib/Transforms/NaCl/RewriteAtomics.cpp ('k') | lib/Transforms/NaCl/RewritePNaClLibraryCalls.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698