1 //===- StripGCRelocates.cpp - Remove gc.relocates inserted by RewriteStatePoints===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This is a little utility pass that removes the gc.relocates inserted by 11 // RewriteStatepointsForGC. Note that the generated IR is incorrect, 12 // but this is useful as a single pass in itself, for analysis of IR, without 13 // the GC.relocates. The statepoint and gc.result instrinsics would still be 14 // present. 15 //===----------------------------------------------------------------------===// 16 17 #include "llvm/IR/Function.h" 18 #include "llvm/IR/InstIterator.h" 19 #include "llvm/IR/Instructions.h" 20 #include "llvm/IR/Statepoint.h" 21 #include "llvm/IR/Type.h" 22 #include "llvm/Pass.h" 23 #include "llvm/Support/raw_ostream.h" 24 #include "llvm/Transforms/Scalar.h" 25 26 using namespace llvm; 27 28 namespace { 29 struct StripGCRelocates : public FunctionPass { 30 static char ID; // Pass identification, replacement for typeid 31 StripGCRelocates() : FunctionPass(ID) { 32 initializeStripGCRelocatesPass(*PassRegistry::getPassRegistry()); 33 } 34 35 void getAnalysisUsage(AnalysisUsage &Info) const override {} 36 37 bool runOnFunction(Function &F) override; 38 39 }; 40 char StripGCRelocates::ID = 0; 41 } 42 43 bool StripGCRelocates::runOnFunction(Function &F) { 44 // Nothing to do for declarations. 45 if (F.isDeclaration()) 46 return false; 47 SmallVector<GCRelocateInst *, 20> GCRelocates; 48 // TODO: We currently do not handle gc.relocates that are in landing pads, 49 // i.e. not bound to a single statepoint token. 50 for (Instruction &I : instructions(F)) { 51 if (auto *GCR = dyn_cast<GCRelocateInst>(&I)) 52 if (isStatepoint(GCR->getOperand(0))) 53 GCRelocates.push_back(GCR); 54 } 55 // All gc.relocates are bound to a single statepoint token. The order of 56 // visiting gc.relocates for deletion does not matter. 57 for (GCRelocateInst *GCRel : GCRelocates) { 58 Value *OrigPtr = GCRel->getDerivedPtr(); 59 Value *ReplaceGCRel = OrigPtr; 60 61 // All gc_relocates are i8 addrspace(1)* typed, we need a bitcast from i8 62 // addrspace(1)* to the type of the OrigPtr, if the are not the same. 63 if (GCRel->getType() != OrigPtr->getType()) 64 ReplaceGCRel = new BitCastInst(OrigPtr, GCRel->getType(), "cast", GCRel); 65 66 // Replace all uses of gc.relocate and delete the gc.relocate 67 // There maybe unncessary bitcasts back to the OrigPtr type, an instcombine 68 // pass would clear this up. 69 GCRel->replaceAllUsesWith(ReplaceGCRel); 70 GCRel->eraseFromParent(); 71 } 72 return !GCRelocates.empty(); 73 } 74 75 INITIALIZE_PASS(StripGCRelocates, "strip-gc-relocates", 76 "Strip gc.relocates inserted through RewriteStatepointsForGC", 77 true, false) 78 FunctionPass *llvm::createStripGCRelocatesPass() { 79 return new StripGCRelocates(); 80 } 81