Use getIntrinsicID instead of looking up intrinsic prototypes. Also

fixes a bug with indirect calls. (Test case will be included with
ocaml collector patch.)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45316 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Gordon Henriksen 2007-12-22 17:27:01 +00:00
parent 860b25a611
commit a6c9925087

View File

@ -35,10 +35,6 @@ namespace {
/// directed by the Collector. It also performs automatic root initialization /// directed by the Collector. It also performs automatic root initialization
/// and custom intrinsic lowering. /// and custom intrinsic lowering.
class VISIBILITY_HIDDEN LowerIntrinsics : public FunctionPass { class VISIBILITY_HIDDEN LowerIntrinsics : public FunctionPass {
/// GCRootInt, GCReadInt, GCWriteInt - The function prototypes for the
/// llvm.gc* intrinsics.
Function *GCRootInt, *GCReadInt, *GCWriteInt;
static bool NeedsDefaultLoweringPass(const Collector &C); static bool NeedsDefaultLoweringPass(const Collector &C);
static bool NeedsCustomLoweringPass(const Collector &C); static bool NeedsCustomLoweringPass(const Collector &C);
static bool CouldBecomeSafePoint(Instruction *I); static bool CouldBecomeSafePoint(Instruction *I);
@ -138,8 +134,7 @@ FunctionPass *llvm::createGCLoweringPass() {
char LowerIntrinsics::ID = 0; char LowerIntrinsics::ID = 0;
LowerIntrinsics::LowerIntrinsics() LowerIntrinsics::LowerIntrinsics()
: FunctionPass((intptr_t)&ID), : FunctionPass((intptr_t)&ID) {}
GCRootInt(0), GCReadInt(0), GCWriteInt(0) {}
const char *LowerIntrinsics::getPassName() const { const char *LowerIntrinsics::getPassName() const {
return "Lower Garbage Collection Instructions"; return "Lower Garbage Collection Instructions";
@ -152,10 +147,6 @@ void LowerIntrinsics::getAnalysisUsage(AnalysisUsage &AU) const {
/// doInitialization - If this module uses the GC intrinsics, find them now. /// doInitialization - If this module uses the GC intrinsics, find them now.
bool LowerIntrinsics::doInitialization(Module &M) { bool LowerIntrinsics::doInitialization(Module &M) {
GCReadInt = M.getFunction("llvm.gcread");
GCWriteInt = M.getFunction("llvm.gcwrite");
GCRootInt = M.getFunction("llvm.gcroot");
// FIXME: This is rather antisocial in the context of a JIT since it performs // FIXME: This is rather antisocial in the context of a JIT since it performs
// work against the entire module. But this cannot be done at // work against the entire module. But this cannot be done at
// runFunction time (initializeCustomLowering likely needs to change // runFunction time (initializeCustomLowering likely needs to change
@ -277,25 +268,35 @@ bool LowerIntrinsics::PerformDefaultLowering(Function &F, Collector &Coll) {
bool MadeChange = false; bool MadeChange = false;
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) { for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) {
if (CallInst *CI = dyn_cast<CallInst>(II++)) { if (IntrinsicInst *CI = dyn_cast<IntrinsicInst>(II++)) {
Function *F = CI->getCalledFunction(); Function *F = CI->getCalledFunction();
if (F == GCWriteInt && LowerWr) { switch (F->getIntrinsicID()) {
// Replace a write barrier with a simple store. case Intrinsic::gcwrite:
Value *St = new StoreInst(CI->getOperand(1), CI->getOperand(3), CI); if (LowerWr) {
CI->replaceAllUsesWith(St); // Replace a write barrier with a simple store.
CI->eraseFromParent(); Value *St = new StoreInst(CI->getOperand(1), CI->getOperand(3), CI);
} else if (F == GCReadInt && LowerRd) { CI->replaceAllUsesWith(St);
// Replace a read barrier with a simple load. CI->eraseFromParent();
Value *Ld = new LoadInst(CI->getOperand(2), "", CI); }
Ld->takeName(CI); break;
CI->replaceAllUsesWith(Ld); case Intrinsic::gcread:
CI->eraseFromParent(); if (LowerRd) {
} else if (F == GCRootInt && InitRoots) { // Replace a read barrier with a simple load.
// Initialize the GC root, but do not delete the intrinsic. The Value *Ld = new LoadInst(CI->getOperand(2), "", CI);
// backend needs the intrinsic to flag the stack slot. Ld->takeName(CI);
Roots.push_back(cast<AllocaInst>( CI->replaceAllUsesWith(Ld);
IntrinsicInst::StripPointerCasts(CI->getOperand(1)))); CI->eraseFromParent();
} else { }
break;
case Intrinsic::gcroot:
if (InitRoots) {
// Initialize the GC root, but do not delete the intrinsic. The
// backend needs the intrinsic to flag the stack slot.
Roots.push_back(cast<AllocaInst>(
IntrinsicInst::StripPointerCasts(CI->getOperand(1))));
}
break;
default:
continue; continue;
} }