summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorPete Cooper <peter_cooper@apple.com>2018-12-18 22:20:03 +0000
committerPete Cooper <peter_cooper@apple.com>2018-12-18 22:20:03 +0000
commitf86db5ce9e90495e417eaf8c4f8847ee272a03ab (patch)
tree24def6662eb8d25eeb6e89edb412c5bc7716065d /llvm/lib/CodeGen
parentef57943e3fbabc6976dd7a949362d643b6e087ef (diff)
downloadbcm5719-llvm-f86db5ce9e90495e417eaf8c4f8847ee272a03ab.tar.gz
bcm5719-llvm-f86db5ce9e90495e417eaf8c4f8847ee272a03ab.zip
Rewrite objc intrinsics to runtime methods in PreISelIntrinsicLowering instead of SDAG.
SelectionDAG currently changes these intrinsics to function calls, but that won't work for other ISel's. Also we want to eventually support nonlazybind and weak linkage coming from the front-end which we can't do in SelectionDAG. llvm-svn: 349552
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp114
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp50
2 files changed, 112 insertions, 52 deletions
diff --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
index 8f88ef78828..cd15f6b7fcb 100644
--- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
+++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
@@ -7,13 +7,15 @@
//
//===----------------------------------------------------------------------===//
//
-// This pass implements IR lowering for the llvm.load.relative intrinsic.
+// This pass implements IR lowering for the llvm.load.relative and llvm.objc.*
+// intrinsics.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/PreISelIntrinsicLowering.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/Function.h"
+#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
@@ -55,11 +57,119 @@ static bool lowerLoadRelative(Function &F) {
return Changed;
}
+static bool lowerObjCCall(Function &F, const char *NewFn) {
+ if (F.use_empty())
+ return false;
+
+ // If we haven't already looked up this function, check to see if the
+ // program already contains a function with this name.
+ Module *M = F.getParent();
+ Constant* FCache = M->getOrInsertFunction(NewFn, F.getFunctionType());
+
+ for (auto I = F.use_begin(), E = F.use_end(); I != E;) {
+ auto *CI = dyn_cast<CallInst>(I->getUser());
+ assert(CI->getCalledFunction() && "Cannot lower an indirect call!");
+ ++I;
+
+ IRBuilder<> Builder(CI->getParent(), CI->getIterator());
+ SmallVector<Value *, 8> Args(CI->arg_begin(), CI->arg_end());
+ CallInst *NewCI = Builder.CreateCall(FCache, Args);
+ NewCI->setName(CI->getName());
+ NewCI->setTailCallKind(CI->getTailCallKind());
+ if (!CI->use_empty())
+ CI->replaceAllUsesWith(NewCI);
+ CI->eraseFromParent();
+ }
+
+ return true;
+}
+
static bool lowerIntrinsics(Module &M) {
bool Changed = false;
for (Function &F : M) {
- if (F.getName().startswith("llvm.load.relative."))
+ if (F.getName().startswith("llvm.load.relative.")) {
Changed |= lowerLoadRelative(F);
+ continue;
+ }
+ switch (F.getIntrinsicID()) {
+ default:
+ break;
+ case Intrinsic::objc_autorelease:
+ Changed |= lowerObjCCall(F, "objc_autorelease");
+ break;
+ case Intrinsic::objc_autoreleasePoolPop:
+ Changed |= lowerObjCCall(F, "objc_autoreleasePoolPop");
+ break;
+ case Intrinsic::objc_autoreleasePoolPush:
+ Changed |= lowerObjCCall(F, "objc_autoreleasePoolPush");
+ break;
+ case Intrinsic::objc_autoreleaseReturnValue:
+ Changed |= lowerObjCCall(F, "objc_autoreleaseReturnValue");
+ break;
+ case Intrinsic::objc_copyWeak:
+ Changed |= lowerObjCCall(F, "objc_copyWeak");
+ break;
+ case Intrinsic::objc_destroyWeak:
+ Changed |= lowerObjCCall(F, "objc_destroyWeak");
+ break;
+ case Intrinsic::objc_initWeak:
+ Changed |= lowerObjCCall(F, "objc_initWeak");
+ break;
+ case Intrinsic::objc_loadWeak:
+ Changed |= lowerObjCCall(F, "objc_loadWeak");
+ break;
+ case Intrinsic::objc_loadWeakRetained:
+ Changed |= lowerObjCCall(F, "objc_loadWeakRetained");
+ break;
+ case Intrinsic::objc_moveWeak:
+ Changed |= lowerObjCCall(F, "objc_moveWeak");
+ break;
+ case Intrinsic::objc_release:
+ Changed |= lowerObjCCall(F, "objc_release");
+ break;
+ case Intrinsic::objc_retain:
+ Changed |= lowerObjCCall(F, "objc_retain");
+ break;
+ case Intrinsic::objc_retainAutorelease:
+ Changed |= lowerObjCCall(F, "objc_retainAutorelease");
+ break;
+ case Intrinsic::objc_retainAutoreleaseReturnValue:
+ Changed |= lowerObjCCall(F, "objc_retainAutoreleaseReturnValue");
+ break;
+ case Intrinsic::objc_retainAutoreleasedReturnValue:
+ Changed |= lowerObjCCall(F, "objc_retainAutoreleasedReturnValue");
+ break;
+ case Intrinsic::objc_retainBlock:
+ Changed |= lowerObjCCall(F, "objc_retainBlock");
+ break;
+ case Intrinsic::objc_storeStrong:
+ Changed |= lowerObjCCall(F, "objc_storeStrong");
+ break;
+ case Intrinsic::objc_storeWeak:
+ Changed |= lowerObjCCall(F, "objc_storeWeak");
+ break;
+ case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue:
+ Changed |= lowerObjCCall(F, "objc_unsafeClaimAutoreleasedReturnValue");
+ break;
+ case Intrinsic::objc_retainedObject:
+ Changed |= lowerObjCCall(F, "objc_retainedObject");
+ break;
+ case Intrinsic::objc_unretainedObject:
+ Changed |= lowerObjCCall(F, "objc_unretainedObject");
+ break;
+ case Intrinsic::objc_unretainedPointer:
+ Changed |= lowerObjCCall(F, "objc_unretainedPointer");
+ break;
+ case Intrinsic::objc_retain_autorelease:
+ Changed |= lowerObjCCall(F, "objc_retain_autorelease");
+ break;
+ case Intrinsic::objc_sync_enter:
+ Changed |= lowerObjCCall(F, "objc_sync_enter");
+ break;
+ case Intrinsic::objc_sync_exit:
+ Changed |= lowerObjCCall(F, "objc_sync_exit");
+ break;
+ }
}
return Changed;
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index cf06c1f0b4b..c42d2491243 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -6363,56 +6363,6 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
// MachineFunction in SelectionDAGISel::PrepareEHLandingPad. We can safely
// delete it now.
return nullptr;
- case Intrinsic::objc_autorelease:
- return "objc_autorelease";
- case Intrinsic::objc_autoreleasePoolPop:
- return "objc_autoreleasePoolPop";
- case Intrinsic::objc_autoreleasePoolPush:
- return "objc_autoreleasePoolPush";
- case Intrinsic::objc_autoreleaseReturnValue:
- return "objc_autoreleaseReturnValue";
- case Intrinsic::objc_copyWeak:
- return "objc_copyWeak";
- case Intrinsic::objc_destroyWeak:
- return "objc_destroyWeak";
- case Intrinsic::objc_initWeak:
- return "objc_initWeak";
- case Intrinsic::objc_loadWeak:
- return "objc_loadWeak";
- case Intrinsic::objc_loadWeakRetained:
- return "objc_loadWeakRetained";
- case Intrinsic::objc_moveWeak:
- return "objc_moveWeak";
- case Intrinsic::objc_release:
- return "objc_release";
- case Intrinsic::objc_retain:
- return "objc_retain";
- case Intrinsic::objc_retainAutorelease:
- return "objc_retainAutorelease";
- case Intrinsic::objc_retainAutoreleaseReturnValue:
- return "objc_retainAutoreleaseReturnValue";
- case Intrinsic::objc_retainAutoreleasedReturnValue:
- return "objc_retainAutoreleasedReturnValue";
- case Intrinsic::objc_retainBlock:
- return "objc_retainBlock";
- case Intrinsic::objc_storeStrong:
- return "objc_storeStrong";
- case Intrinsic::objc_storeWeak:
- return "objc_storeWeak";
- case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue:
- return "objc_unsafeClaimAutoreleasedReturnValue";
- case Intrinsic::objc_retainedObject:
- return "objc_retainedObject";
- case Intrinsic::objc_unretainedObject:
- return "objc_unretainedObject";
- case Intrinsic::objc_unretainedPointer:
- return "objc_unretainedPointer";
- case Intrinsic::objc_retain_autorelease:
- return "objc_retain_autorelease";
- case Intrinsic::objc_sync_enter:
- return "objc_sync_enter";
- case Intrinsic::objc_sync_exit:
- return "objc_sync_exit";
}
}
OpenPOWER on IntegriCloud