1ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines//===-- GCRootLowering.cpp - Garbage collection infrastructure ------------===// 2ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// 3ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// The LLVM Compiler Infrastructure 4ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// 5ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// This file is distributed under the University of Illinois Open Source 6ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// License. See LICENSE.TXT for details. 7ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// 8ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines//===----------------------------------------------------------------------===// 9ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// 10ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// This file implements the lowering for the gc.root mechanism. 11ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// 12ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines//===----------------------------------------------------------------------===// 13ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 14ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/CodeGen/GCMetadata.h" 15ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/CodeGen/GCStrategy.h" 16ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/CodeGen/MachineFrameInfo.h" 17ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/CodeGen/MachineFunctionPass.h" 18ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/CodeGen/MachineInstrBuilder.h" 19ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/CodeGen/MachineModuleInfo.h" 20ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/CodeGen/Passes.h" 21ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/IR/Dominators.h" 22ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/IR/IntrinsicInst.h" 23ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/IR/Module.h" 24ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/Support/Debug.h" 25ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/Support/ErrorHandling.h" 26ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/Support/raw_ostream.h" 27ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/Target/TargetFrameLowering.h" 28ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/Target/TargetInstrInfo.h" 29ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/Target/TargetMachine.h" 30ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/Target/TargetRegisterInfo.h" 31ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/Target/TargetSubtargetInfo.h" 32ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 33ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesusing namespace llvm; 34ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 35ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesnamespace { 36ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 37ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// LowerIntrinsics - This pass rewrites calls to the llvm.gcread or 38ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// llvm.gcwrite intrinsics, replacing them with simple loads and stores as 39ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// directed by the GCStrategy. It also performs automatic root initialization 40ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// and custom intrinsic lowering. 41ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesclass LowerIntrinsics : public FunctionPass { 42ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool PerformDefaultLowering(Function &F, GCStrategy &Coll); 43ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 44ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinespublic: 45ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines static char ID; 46ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 47ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines LowerIntrinsics(); 48ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines const char *getPassName() const override; 49ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines void getAnalysisUsage(AnalysisUsage &AU) const override; 50ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 51ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool doInitialization(Module &M) override; 52ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool runOnFunction(Function &F) override; 53ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines}; 54ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 55ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// GCMachineCodeAnalysis - This is a target-independent pass over the machine 56ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// function representation to identify safe points for the garbage collector 57ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// in the machine code. It inserts labels at safe points and populates a 58ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// GCMetadata record for each function. 59ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesclass GCMachineCodeAnalysis : public MachineFunctionPass { 60ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines GCFunctionInfo *FI; 61ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines MachineModuleInfo *MMI; 62ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines const TargetInstrInfo *TII; 63ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 64ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines void FindSafePoints(MachineFunction &MF); 65ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines void VisitCallPoint(MachineBasicBlock::iterator MI); 66ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines MCSymbol *InsertLabel(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 67de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const DebugLoc &DL) const; 68ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 69ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines void FindStackOffsets(MachineFunction &MF); 70ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 71ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinespublic: 72ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines static char ID; 73ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 74ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines GCMachineCodeAnalysis(); 75ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines void getAnalysisUsage(AnalysisUsage &AU) const override; 76ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 77ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool runOnMachineFunction(MachineFunction &MF) override; 78ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines}; 79ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 80ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 81ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// ----------------------------------------------------------------------------- 82ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 83ebe69fe11e48d322045d5949c83283927a0d790bStephen HinesINITIALIZE_PASS_BEGIN(LowerIntrinsics, "gc-lowering", "GC Lowering", false, 84ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines false) 85ebe69fe11e48d322045d5949c83283927a0d790bStephen HinesINITIALIZE_PASS_DEPENDENCY(GCModuleInfo) 86ebe69fe11e48d322045d5949c83283927a0d790bStephen HinesINITIALIZE_PASS_END(LowerIntrinsics, "gc-lowering", "GC Lowering", false, false) 87ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 88ebe69fe11e48d322045d5949c83283927a0d790bStephen HinesFunctionPass *llvm::createGCLoweringPass() { return new LowerIntrinsics(); } 89ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 90ebe69fe11e48d322045d5949c83283927a0d790bStephen Hineschar LowerIntrinsics::ID = 0; 91ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 92ebe69fe11e48d322045d5949c83283927a0d790bStephen HinesLowerIntrinsics::LowerIntrinsics() : FunctionPass(ID) { 93ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines initializeLowerIntrinsicsPass(*PassRegistry::getPassRegistry()); 94ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 95ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 96ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesconst char *LowerIntrinsics::getPassName() const { 97ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return "Lower Garbage Collection Instructions"; 98ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 99ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 100ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesvoid LowerIntrinsics::getAnalysisUsage(AnalysisUsage &AU) const { 101ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines FunctionPass::getAnalysisUsage(AU); 102ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines AU.addRequired<GCModuleInfo>(); 103ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines AU.addPreserved<DominatorTreeWrapperPass>(); 104ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 105ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 106ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesstatic bool NeedsDefaultLoweringPass(const GCStrategy &C) { 107ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Default lowering is necessary only if read or write barriers have a default 108ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // action. The default for roots is no action. 109ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return !C.customWriteBarrier() || !C.customReadBarrier() || 110ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines C.initializeRoots(); 111ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 112ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 113ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// doInitialization - If this module uses the GC intrinsics, find them now. 114ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesbool LowerIntrinsics::doInitialization(Module &M) { 115ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>(); 116ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines assert(MI && "LowerIntrinsics didn't require GCModuleInfo!?"); 117ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) 118ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (!I->isDeclaration() && I->hasGC()) 119ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines MI->getFunctionInfo(*I); // Instantiate the GC strategy. 120ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 121ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return false; 122ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 123ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 124ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// CouldBecomeSafePoint - Predicate to conservatively determine whether the 125ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// instruction could introduce a safe point. 126ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesstatic bool CouldBecomeSafePoint(Instruction *I) { 127ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // The natural definition of instructions which could introduce safe points 128ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // are: 129ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // 130ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // - call, invoke (AfterCall, BeforeCall) 131ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // - phis (Loops) 132ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // - invoke, ret, unwind (Exit) 133ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // 134ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // However, instructions as seemingly inoccuous as arithmetic can become 135ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // libcalls upon lowering (e.g., div i64 on a 32-bit platform), so instead 136ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // it is necessary to take a conservative approach. 137ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 138ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (isa<AllocaInst>(I) || isa<GetElementPtrInst>(I) || isa<StoreInst>(I) || 139ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines isa<LoadInst>(I)) 140ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return false; 141ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 142ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // llvm.gcroot is safe because it doesn't do anything at runtime. 143ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (CallInst *CI = dyn_cast<CallInst>(I)) 144ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (Function *F = CI->getCalledFunction()) 1456948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar if (Intrinsic::ID IID = F->getIntrinsicID()) 146ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (IID == Intrinsic::gcroot) 147ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return false; 148ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 149ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return true; 150ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 151ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 152ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesstatic bool InsertRootInitializers(Function &F, AllocaInst **Roots, 153ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines unsigned Count) { 154ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Scroll past alloca instructions. 155ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines BasicBlock::iterator IP = F.getEntryBlock().begin(); 156ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines while (isa<AllocaInst>(IP)) 157ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines ++IP; 158ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 159ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Search for initializers in the initial BB. 160ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines SmallPtrSet<AllocaInst *, 16> InitedRoots; 161f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar for (; !CouldBecomeSafePoint(&*IP); ++IP) 162ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (StoreInst *SI = dyn_cast<StoreInst>(IP)) 163ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (AllocaInst *AI = 164ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines dyn_cast<AllocaInst>(SI->getOperand(1)->stripPointerCasts())) 165ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines InitedRoots.insert(AI); 166ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 167ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Add root initializers. 168ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool MadeChange = false; 169ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 170ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines for (AllocaInst **I = Roots, **E = Roots + Count; I != E; ++I) 171ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (!InitedRoots.count(*I)) { 172ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines StoreInst *SI = new StoreInst( 173de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ConstantPointerNull::get(cast<PointerType>((*I)->getAllocatedType())), 174ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines *I); 175ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines SI->insertAfter(*I); 176ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines MadeChange = true; 177ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 178ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 179ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return MadeChange; 180ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 181ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 182ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// runOnFunction - Replace gcread/gcwrite intrinsics with loads and stores. 183ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// Leave gcroot intrinsics; the code generator needs to see those. 184ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesbool LowerIntrinsics::runOnFunction(Function &F) { 185ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Quick exit for functions that do not use GC. 186ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (!F.hasGC()) 187ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return false; 188ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 189ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines GCFunctionInfo &FI = getAnalysis<GCModuleInfo>().getFunctionInfo(F); 190ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines GCStrategy &S = FI.getStrategy(); 191ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 192ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool MadeChange = false; 193ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 194ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (NeedsDefaultLoweringPass(S)) 195ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines MadeChange |= PerformDefaultLowering(F, S); 196ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 197ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return MadeChange; 198ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 199ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 200ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesbool LowerIntrinsics::PerformDefaultLowering(Function &F, GCStrategy &S) { 201ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool LowerWr = !S.customWriteBarrier(); 202ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool LowerRd = !S.customReadBarrier(); 203ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool InitRoots = S.initializeRoots(); 204ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 205ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines SmallVector<AllocaInst *, 32> Roots; 206ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 207ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines bool MadeChange = false; 208ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { 209ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) { 210ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (IntrinsicInst *CI = dyn_cast<IntrinsicInst>(II++)) { 211ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Function *F = CI->getCalledFunction(); 212ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines switch (F->getIntrinsicID()) { 213ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines case Intrinsic::gcwrite: 214ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (LowerWr) { 215ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Replace a write barrier with a simple store. 216ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *St = 217ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines new StoreInst(CI->getArgOperand(0), CI->getArgOperand(2), CI); 218ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines CI->replaceAllUsesWith(St); 219ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines CI->eraseFromParent(); 220ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 221ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines break; 222ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines case Intrinsic::gcread: 223ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (LowerRd) { 224ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Replace a read barrier with a simple load. 225ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Value *Ld = new LoadInst(CI->getArgOperand(1), "", CI); 226ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Ld->takeName(CI); 227ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines CI->replaceAllUsesWith(Ld); 228ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines CI->eraseFromParent(); 229ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 230ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines break; 231ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines case Intrinsic::gcroot: 232ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (InitRoots) { 233ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Initialize the GC root, but do not delete the intrinsic. The 234ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // backend needs the intrinsic to flag the stack slot. 235ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Roots.push_back( 236ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines cast<AllocaInst>(CI->getArgOperand(0)->stripPointerCasts())); 237ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 238ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines break; 239ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines default: 240ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines continue; 241ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 242ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 243ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines MadeChange = true; 244ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 245ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 246ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 247ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 248ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (Roots.size()) 249ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines MadeChange |= InsertRootInitializers(F, Roots.begin(), Roots.size()); 250ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 251ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return MadeChange; 252ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 253ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 254ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// ----------------------------------------------------------------------------- 255ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 256ebe69fe11e48d322045d5949c83283927a0d790bStephen Hineschar GCMachineCodeAnalysis::ID = 0; 257ebe69fe11e48d322045d5949c83283927a0d790bStephen Hineschar &llvm::GCMachineCodeAnalysisID = GCMachineCodeAnalysis::ID; 258ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 259ebe69fe11e48d322045d5949c83283927a0d790bStephen HinesINITIALIZE_PASS(GCMachineCodeAnalysis, "gc-analysis", 260ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines "Analyze Machine Code For Garbage Collection", false, false) 261ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 262ebe69fe11e48d322045d5949c83283927a0d790bStephen HinesGCMachineCodeAnalysis::GCMachineCodeAnalysis() : MachineFunctionPass(ID) {} 263ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 264ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesvoid GCMachineCodeAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { 265ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines MachineFunctionPass::getAnalysisUsage(AU); 266ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines AU.setPreservesAll(); 267ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines AU.addRequired<MachineModuleInfo>(); 268ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines AU.addRequired<GCModuleInfo>(); 269ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 270ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 271ebe69fe11e48d322045d5949c83283927a0d790bStephen HinesMCSymbol *GCMachineCodeAnalysis::InsertLabel(MachineBasicBlock &MBB, 272ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines MachineBasicBlock::iterator MI, 273de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const DebugLoc &DL) const { 2746948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar MCSymbol *Label = MBB.getParent()->getContext().createTempSymbol(); 275ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines BuildMI(MBB, MI, DL, TII->get(TargetOpcode::GC_LABEL)).addSym(Label); 276ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return Label; 277ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 278ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 279ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesvoid GCMachineCodeAnalysis::VisitCallPoint(MachineBasicBlock::iterator CI) { 280ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Find the return address (next instruction), too, so as to bracket the call 281ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // instruction. 282ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines MachineBasicBlock::iterator RAI = CI; 283ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines ++RAI; 284ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 285ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (FI->getStrategy().needsSafePoint(GC::PreCall)) { 286ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines MCSymbol *Label = InsertLabel(*CI->getParent(), CI, CI->getDebugLoc()); 287ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines FI->addSafePoint(GC::PreCall, Label, CI->getDebugLoc()); 288ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 289ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 290ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (FI->getStrategy().needsSafePoint(GC::PostCall)) { 291ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines MCSymbol *Label = InsertLabel(*CI->getParent(), RAI, CI->getDebugLoc()); 292ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines FI->addSafePoint(GC::PostCall, Label, CI->getDebugLoc()); 293ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 294ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 295ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 296ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesvoid GCMachineCodeAnalysis::FindSafePoints(MachineFunction &MF) { 297ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines for (MachineFunction::iterator BBI = MF.begin(), BBE = MF.end(); BBI != BBE; 298ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines ++BBI) 299ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines for (MachineBasicBlock::iterator MI = BBI->begin(), ME = BBI->end(); 300ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines MI != ME; ++MI) 301ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (MI->isCall()) { 302ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Do not treat tail or sibling call sites as safe points. This is 303ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // legal since any arguments passed to the callee which live in the 304ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // remnants of the callers frame will be owned and updated by the 305ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // callee if required. 306ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (MI->isTerminator()) 307ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines continue; 308ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines VisitCallPoint(MI); 309ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 310ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 311ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 312ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesvoid GCMachineCodeAnalysis::FindStackOffsets(MachineFunction &MF) { 313ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); 314ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines assert(TFI && "TargetRegisterInfo not available!"); 315ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 316ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines for (GCFunctionInfo::roots_iterator RI = FI->roots_begin(); 317ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines RI != FI->roots_end();) { 318ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // If the root references a dead object, no need to keep it. 319ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (MF.getFrameInfo()->isDeadObjectIndex(RI->Num)) { 320ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines RI = FI->removeStackRoot(RI); 321ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } else { 322f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar unsigned FrameReg; // FIXME: surely GCRoot ought to store the 323f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // register that the offset is from? 324f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar RI->StackOffset = TFI->getFrameIndexReference(MF, RI->Num, FrameReg); 325ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines ++RI; 326ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 327ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 328ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 329ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 330ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesbool GCMachineCodeAnalysis::runOnMachineFunction(MachineFunction &MF) { 331ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Quick exit for functions that do not use GC. 332ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (!MF.getFunction()->hasGC()) 333ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return false; 334ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 335ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines FI = &getAnalysis<GCModuleInfo>().getFunctionInfo(*MF.getFunction()); 336ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines MMI = &getAnalysis<MachineModuleInfo>(); 337ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines TII = MF.getSubtarget().getInstrInfo(); 338ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 3390c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar // Find the size of the stack frame. There may be no correct static frame 3400c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar // size, we use UINT64_MAX to represent this. 3410c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar const MachineFrameInfo *MFI = MF.getFrameInfo(); 3420c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); 3430c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar const bool DynamicFrameSize = MFI->hasVarSizedObjects() || 3440c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar RegInfo->needsStackRealignment(MF); 3450c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar FI->setFrameSize(DynamicFrameSize ? UINT64_MAX : MFI->getStackSize()); 346ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 347ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Find all safe points. 3480c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar if (FI->getStrategy().needsSafePoints()) 3490c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar FindSafePoints(MF); 350ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 3510c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar // Find the concrete stack offsets for all roots (stack slots) 352ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines FindStackOffsets(MF); 353ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 354ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return false; 355ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 356