10b57cec5SDimitry Andric //===- RewriteStatepointsForGC.cpp - Make GC relocations explicit ---------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Rewrite call/invoke instructions so as to make potential relocations 100b57cec5SDimitry Andric // performed by the garbage collector explicit in the IR. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/RewriteStatepointsForGC.h" 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 170b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 180b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h" 190b57cec5SDimitry Andric #include "llvm/ADT/MapVector.h" 200b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 215f757f3fSDimitry Andric #include "llvm/ADT/Sequence.h" 220b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h" 230b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h" 240b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 250b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 260b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h" 270b57cec5SDimitry Andric #include "llvm/Analysis/DomTreeUpdater.h" 280b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 290b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 300b57cec5SDimitry Andric #include "llvm/IR/Argument.h" 3106c3fb27SDimitry Andric #include "llvm/IR/AttributeMask.h" 320b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 330b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h" 340b57cec5SDimitry Andric #include "llvm/IR/CallingConv.h" 350b57cec5SDimitry Andric #include "llvm/IR/Constant.h" 360b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 370b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 380b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 390b57cec5SDimitry Andric #include "llvm/IR/Dominators.h" 400b57cec5SDimitry Andric #include "llvm/IR/Function.h" 4106c3fb27SDimitry Andric #include "llvm/IR/GCStrategy.h" 420b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h" 430b57cec5SDimitry Andric #include "llvm/IR/InstIterator.h" 440b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h" 450b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 460b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 470b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 480b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h" 490b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h" 500b57cec5SDimitry Andric #include "llvm/IR/MDBuilder.h" 510b57cec5SDimitry Andric #include "llvm/IR/Metadata.h" 520b57cec5SDimitry Andric #include "llvm/IR/Module.h" 530b57cec5SDimitry Andric #include "llvm/IR/Statepoint.h" 540b57cec5SDimitry Andric #include "llvm/IR/Type.h" 550b57cec5SDimitry Andric #include "llvm/IR/User.h" 560b57cec5SDimitry Andric #include "llvm/IR/Value.h" 570b57cec5SDimitry Andric #include "llvm/IR/ValueHandle.h" 580b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 590b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 600b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 610b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 620b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 630b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 640b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 650b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Local.h" 660b57cec5SDimitry Andric #include "llvm/Transforms/Utils/PromoteMemToReg.h" 670b57cec5SDimitry Andric #include <algorithm> 680b57cec5SDimitry Andric #include <cassert> 690b57cec5SDimitry Andric #include <cstddef> 700b57cec5SDimitry Andric #include <cstdint> 710b57cec5SDimitry Andric #include <iterator> 72bdd1243dSDimitry Andric #include <optional> 730b57cec5SDimitry Andric #include <set> 740b57cec5SDimitry Andric #include <string> 750b57cec5SDimitry Andric #include <utility> 760b57cec5SDimitry Andric #include <vector> 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric #define DEBUG_TYPE "rewrite-statepoints-for-gc" 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric using namespace llvm; 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric // Print the liveset found at the insert location 830b57cec5SDimitry Andric static cl::opt<bool> PrintLiveSet("spp-print-liveset", cl::Hidden, 840b57cec5SDimitry Andric cl::init(false)); 850b57cec5SDimitry Andric static cl::opt<bool> PrintLiveSetSize("spp-print-liveset-size", cl::Hidden, 860b57cec5SDimitry Andric cl::init(false)); 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric // Print out the base pointers for debugging 890b57cec5SDimitry Andric static cl::opt<bool> PrintBasePointers("spp-print-base-pointers", cl::Hidden, 900b57cec5SDimitry Andric cl::init(false)); 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric // Cost threshold measuring when it is profitable to rematerialize value instead 930b57cec5SDimitry Andric // of relocating it 940b57cec5SDimitry Andric static cl::opt<unsigned> 950b57cec5SDimitry Andric RematerializationThreshold("spp-rematerialization-threshold", cl::Hidden, 960b57cec5SDimitry Andric cl::init(6)); 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 990b57cec5SDimitry Andric static bool ClobberNonLive = true; 1000b57cec5SDimitry Andric #else 1010b57cec5SDimitry Andric static bool ClobberNonLive = false; 1020b57cec5SDimitry Andric #endif 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric static cl::opt<bool, true> ClobberNonLiveOverride("rs4gc-clobber-non-live", 1050b57cec5SDimitry Andric cl::location(ClobberNonLive), 1060b57cec5SDimitry Andric cl::Hidden); 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric static cl::opt<bool> 1090b57cec5SDimitry Andric AllowStatepointWithNoDeoptInfo("rs4gc-allow-statepoint-with-no-deopt-info", 1100b57cec5SDimitry Andric cl::Hidden, cl::init(true)); 1110b57cec5SDimitry Andric 112bdd1243dSDimitry Andric static cl::opt<bool> RematDerivedAtUses("rs4gc-remat-derived-at-uses", 113bdd1243dSDimitry Andric cl::Hidden, cl::init(true)); 114bdd1243dSDimitry Andric 1150b57cec5SDimitry Andric /// The IR fed into RewriteStatepointsForGC may have had attributes and 1160b57cec5SDimitry Andric /// metadata implying dereferenceability that are no longer valid/correct after 1170b57cec5SDimitry Andric /// RewriteStatepointsForGC has run. This is because semantically, after 1180b57cec5SDimitry Andric /// RewriteStatepointsForGC runs, all calls to gc.statepoint "free" the entire 1190b57cec5SDimitry Andric /// heap. stripNonValidData (conservatively) restores 1200b57cec5SDimitry Andric /// correctness by erasing all attributes in the module that externally imply 1210b57cec5SDimitry Andric /// dereferenceability. Similar reasoning also applies to the noalias 1220b57cec5SDimitry Andric /// attributes and metadata. gc.statepoint can touch the entire heap including 1230b57cec5SDimitry Andric /// noalias objects. 1240b57cec5SDimitry Andric /// Apart from attributes and metadata, we also remove instructions that imply 1250b57cec5SDimitry Andric /// constant physical memory: llvm.invariant.start. 1260b57cec5SDimitry Andric static void stripNonValidData(Module &M); 1270b57cec5SDimitry Andric 12806c3fb27SDimitry Andric // Find the GC strategy for a function, or null if it doesn't have one. 12906c3fb27SDimitry Andric static std::unique_ptr<GCStrategy> findGCStrategy(Function &F); 13006c3fb27SDimitry Andric 1310b57cec5SDimitry Andric static bool shouldRewriteStatepointsIn(Function &F); 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric PreservedAnalyses RewriteStatepointsForGC::run(Module &M, 1340b57cec5SDimitry Andric ModuleAnalysisManager &AM) { 1350b57cec5SDimitry Andric bool Changed = false; 1360b57cec5SDimitry Andric auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 1370b57cec5SDimitry Andric for (Function &F : M) { 1380b57cec5SDimitry Andric // Nothing to do for declarations. 1390b57cec5SDimitry Andric if (F.isDeclaration() || F.empty()) 1400b57cec5SDimitry Andric continue; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric // Policy choice says not to rewrite - the most common reason is that we're 1430b57cec5SDimitry Andric // compiling code without a GCStrategy. 1440b57cec5SDimitry Andric if (!shouldRewriteStatepointsIn(F)) 1450b57cec5SDimitry Andric continue; 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric auto &DT = FAM.getResult<DominatorTreeAnalysis>(F); 1480b57cec5SDimitry Andric auto &TTI = FAM.getResult<TargetIRAnalysis>(F); 1490b57cec5SDimitry Andric auto &TLI = FAM.getResult<TargetLibraryAnalysis>(F); 1500b57cec5SDimitry Andric Changed |= runOnFunction(F, DT, TTI, TLI); 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric if (!Changed) 1530b57cec5SDimitry Andric return PreservedAnalyses::all(); 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric // stripNonValidData asserts that shouldRewriteStatepointsIn 1560b57cec5SDimitry Andric // returns true for at least one function in the module. Since at least 1570b57cec5SDimitry Andric // one function changed, we know that the precondition is satisfied. 1580b57cec5SDimitry Andric stripNonValidData(M); 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric PreservedAnalyses PA; 1610b57cec5SDimitry Andric PA.preserve<TargetIRAnalysis>(); 1620b57cec5SDimitry Andric PA.preserve<TargetLibraryAnalysis>(); 1630b57cec5SDimitry Andric return PA; 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric namespace { 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric struct GCPtrLivenessData { 1690b57cec5SDimitry Andric /// Values defined in this block. 1700b57cec5SDimitry Andric MapVector<BasicBlock *, SetVector<Value *>> KillSet; 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric /// Values used in this block (and thus live); does not included values 1730b57cec5SDimitry Andric /// killed within this block. 1740b57cec5SDimitry Andric MapVector<BasicBlock *, SetVector<Value *>> LiveSet; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric /// Values live into this basic block (i.e. used by any 1770b57cec5SDimitry Andric /// instruction in this basic block or ones reachable from here) 1780b57cec5SDimitry Andric MapVector<BasicBlock *, SetVector<Value *>> LiveIn; 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric /// Values live out of this basic block (i.e. live into 1810b57cec5SDimitry Andric /// any successor block) 1820b57cec5SDimitry Andric MapVector<BasicBlock *, SetVector<Value *>> LiveOut; 1830b57cec5SDimitry Andric }; 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric // The type of the internal cache used inside the findBasePointers family 1860b57cec5SDimitry Andric // of functions. From the callers perspective, this is an opaque type and 1870b57cec5SDimitry Andric // should not be inspected. 1880b57cec5SDimitry Andric // 1890b57cec5SDimitry Andric // In the actual implementation this caches two relations: 1900b57cec5SDimitry Andric // - The base relation itself (i.e. this pointer is based on that one) 1910b57cec5SDimitry Andric // - The base defining value relation (i.e. before base_phi insertion) 1920b57cec5SDimitry Andric // Generally, after the execution of a full findBasePointer call, only the 1930b57cec5SDimitry Andric // base relation will remain. Internally, we add a mixture of the two 1940b57cec5SDimitry Andric // types, then update all the second type to the first type 1950b57cec5SDimitry Andric using DefiningValueMapTy = MapVector<Value *, Value *>; 19681ad6265SDimitry Andric using IsKnownBaseMapTy = MapVector<Value *, bool>; 1971fd87a68SDimitry Andric using PointerToBaseTy = MapVector<Value *, Value *>; 1980b57cec5SDimitry Andric using StatepointLiveSetTy = SetVector<Value *>; 1990b57cec5SDimitry Andric using RematerializedValueMapTy = 2000b57cec5SDimitry Andric MapVector<AssertingVH<Instruction>, AssertingVH<Value>>; 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric struct PartiallyConstructedSafepointRecord { 2030b57cec5SDimitry Andric /// The set of values known to be live across this safepoint 2040b57cec5SDimitry Andric StatepointLiveSetTy LiveSet; 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric /// The *new* gc.statepoint instruction itself. This produces the token 2070b57cec5SDimitry Andric /// that normal path gc.relocates and the gc.result are tied to. 2085ffd83dbSDimitry Andric GCStatepointInst *StatepointToken; 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric /// Instruction to which exceptional gc relocates are attached 2110b57cec5SDimitry Andric /// Makes it easier to iterate through them during relocationViaAlloca. 2120b57cec5SDimitry Andric Instruction *UnwindToken; 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric /// Record live values we are rematerialized instead of relocating. 2150b57cec5SDimitry Andric /// They are not included into 'LiveSet' field. 2160b57cec5SDimitry Andric /// Maps rematerialized copy to it's original value. 2170b57cec5SDimitry Andric RematerializedValueMapTy RematerializedValues; 2180b57cec5SDimitry Andric }; 2190b57cec5SDimitry Andric 22081ad6265SDimitry Andric struct RematerizlizationCandidateRecord { 22181ad6265SDimitry Andric // Chain from derived pointer to base. 22281ad6265SDimitry Andric SmallVector<Instruction *, 3> ChainToBase; 22381ad6265SDimitry Andric // Original base. 22481ad6265SDimitry Andric Value *RootOfChain; 22581ad6265SDimitry Andric // Cost of chain. 22681ad6265SDimitry Andric InstructionCost Cost; 22781ad6265SDimitry Andric }; 22881ad6265SDimitry Andric using RematCandTy = MapVector<Value *, RematerizlizationCandidateRecord>; 22981ad6265SDimitry Andric 2300b57cec5SDimitry Andric } // end anonymous namespace 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric static ArrayRef<Use> GetDeoptBundleOperands(const CallBase *Call) { 233bdd1243dSDimitry Andric std::optional<OperandBundleUse> DeoptBundle = 2340b57cec5SDimitry Andric Call->getOperandBundle(LLVMContext::OB_deopt); 2350b57cec5SDimitry Andric 23681ad6265SDimitry Andric if (!DeoptBundle) { 2370b57cec5SDimitry Andric assert(AllowStatepointWithNoDeoptInfo && 2380b57cec5SDimitry Andric "Found non-leaf call without deopt info!"); 239bdd1243dSDimitry Andric return std::nullopt; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 24281ad6265SDimitry Andric return DeoptBundle->Inputs; 2430b57cec5SDimitry Andric } 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric /// Compute the live-in set for every basic block in the function 2460b57cec5SDimitry Andric static void computeLiveInValues(DominatorTree &DT, Function &F, 24706c3fb27SDimitry Andric GCPtrLivenessData &Data, GCStrategy *GC); 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric /// Given results from the dataflow liveness computation, find the set of live 2500b57cec5SDimitry Andric /// Values at a particular instruction. 2510b57cec5SDimitry Andric static void findLiveSetAtInst(Instruction *inst, GCPtrLivenessData &Data, 25206c3fb27SDimitry Andric StatepointLiveSetTy &out, GCStrategy *GC); 2530b57cec5SDimitry Andric 25406c3fb27SDimitry Andric static bool isGCPointerType(Type *T, GCStrategy *GC) { 25506c3fb27SDimitry Andric assert(GC && "GC Strategy for isGCPointerType cannot be null"); 2560b57cec5SDimitry Andric 25706c3fb27SDimitry Andric if (!isa<PointerType>(T)) 2580b57cec5SDimitry Andric return false; 25906c3fb27SDimitry Andric 26006c3fb27SDimitry Andric // conservative - same as StatepointLowering 26106c3fb27SDimitry Andric return GC->isGCManagedPointer(T).value_or(true); 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric // Return true if this type is one which a) is a gc pointer or contains a GC 2650b57cec5SDimitry Andric // pointer and b) is of a type this code expects to encounter as a live value. 2660b57cec5SDimitry Andric // (The insertion code will assert that a type which matches (a) and not (b) 2670b57cec5SDimitry Andric // is not encountered.) 26806c3fb27SDimitry Andric static bool isHandledGCPointerType(Type *T, GCStrategy *GC) { 2690b57cec5SDimitry Andric // We fully support gc pointers 27006c3fb27SDimitry Andric if (isGCPointerType(T, GC)) 2710b57cec5SDimitry Andric return true; 2720b57cec5SDimitry Andric // We partially support vectors of gc pointers. The code will assert if it 2730b57cec5SDimitry Andric // can't handle something. 2740b57cec5SDimitry Andric if (auto VT = dyn_cast<VectorType>(T)) 27506c3fb27SDimitry Andric if (isGCPointerType(VT->getElementType(), GC)) 2760b57cec5SDimitry Andric return true; 2770b57cec5SDimitry Andric return false; 2780b57cec5SDimitry Andric } 2790b57cec5SDimitry Andric 2800b57cec5SDimitry Andric #ifndef NDEBUG 2810b57cec5SDimitry Andric /// Returns true if this type contains a gc pointer whether we know how to 2820b57cec5SDimitry Andric /// handle that type or not. 28306c3fb27SDimitry Andric static bool containsGCPtrType(Type *Ty, GCStrategy *GC) { 28406c3fb27SDimitry Andric if (isGCPointerType(Ty, GC)) 2850b57cec5SDimitry Andric return true; 2860b57cec5SDimitry Andric if (VectorType *VT = dyn_cast<VectorType>(Ty)) 28706c3fb27SDimitry Andric return isGCPointerType(VT->getScalarType(), GC); 2880b57cec5SDimitry Andric if (ArrayType *AT = dyn_cast<ArrayType>(Ty)) 28906c3fb27SDimitry Andric return containsGCPtrType(AT->getElementType(), GC); 2900b57cec5SDimitry Andric if (StructType *ST = dyn_cast<StructType>(Ty)) 29106c3fb27SDimitry Andric return llvm::any_of(ST->elements(), 29206c3fb27SDimitry Andric [GC](Type *Ty) { return containsGCPtrType(Ty, GC); }); 2930b57cec5SDimitry Andric return false; 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric // Returns true if this is a type which a) is a gc pointer or contains a GC 2970b57cec5SDimitry Andric // pointer and b) is of a type which the code doesn't expect (i.e. first class 2980b57cec5SDimitry Andric // aggregates). Used to trip assertions. 29906c3fb27SDimitry Andric static bool isUnhandledGCPointerType(Type *Ty, GCStrategy *GC) { 30006c3fb27SDimitry Andric return containsGCPtrType(Ty, GC) && !isHandledGCPointerType(Ty, GC); 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric #endif 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric // Return the name of the value suffixed with the provided value, or if the 3050b57cec5SDimitry Andric // value didn't have a name, the default value specified. 3060b57cec5SDimitry Andric static std::string suffixed_name_or(Value *V, StringRef Suffix, 3070b57cec5SDimitry Andric StringRef DefaultName) { 3080b57cec5SDimitry Andric return V->hasName() ? (V->getName() + Suffix).str() : DefaultName.str(); 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric // Conservatively identifies any definitions which might be live at the 3120b57cec5SDimitry Andric // given instruction. The analysis is performed immediately before the 3130b57cec5SDimitry Andric // given instruction. Values defined by that instruction are not considered 3140b57cec5SDimitry Andric // live. Values used by that instruction are considered live. 3150b57cec5SDimitry Andric static void analyzeParsePointLiveness( 3160b57cec5SDimitry Andric DominatorTree &DT, GCPtrLivenessData &OriginalLivenessData, CallBase *Call, 31706c3fb27SDimitry Andric PartiallyConstructedSafepointRecord &Result, GCStrategy *GC) { 3180b57cec5SDimitry Andric StatepointLiveSetTy LiveSet; 31906c3fb27SDimitry Andric findLiveSetAtInst(Call, OriginalLivenessData, LiveSet, GC); 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric if (PrintLiveSet) { 3220b57cec5SDimitry Andric dbgs() << "Live Variables:\n"; 3230b57cec5SDimitry Andric for (Value *V : LiveSet) 3240b57cec5SDimitry Andric dbgs() << " " << V->getName() << " " << *V << "\n"; 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric if (PrintLiveSetSize) { 3275ffd83dbSDimitry Andric dbgs() << "Safepoint For: " << Call->getCalledOperand()->getName() << "\n"; 3280b57cec5SDimitry Andric dbgs() << "Number live values: " << LiveSet.size() << "\n"; 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric Result.LiveSet = LiveSet; 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric 33381ad6265SDimitry Andric /// Returns true if V is a known base. 33481ad6265SDimitry Andric static bool isKnownBase(Value *V, const IsKnownBaseMapTy &KnownBases); 3350b57cec5SDimitry Andric 33681ad6265SDimitry Andric /// Caches the IsKnownBase flag for a value and asserts that it wasn't present 33781ad6265SDimitry Andric /// in the cache before. 33881ad6265SDimitry Andric static void setKnownBase(Value *V, bool IsKnownBase, 33981ad6265SDimitry Andric IsKnownBaseMapTy &KnownBases); 3405ffd83dbSDimitry Andric 34181ad6265SDimitry Andric static Value *findBaseDefiningValue(Value *I, DefiningValueMapTy &Cache, 34281ad6265SDimitry Andric IsKnownBaseMapTy &KnownBases); 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric /// Return a base defining value for the 'Index' element of the given vector 3450b57cec5SDimitry Andric /// instruction 'I'. If Index is null, returns a BDV for the entire vector 3460b57cec5SDimitry Andric /// 'I'. As an optimization, this method will try to determine when the 3470b57cec5SDimitry Andric /// element is known to already be a base pointer. If this can be established, 3480b57cec5SDimitry Andric /// the second value in the returned pair will be true. Note that either a 3490b57cec5SDimitry Andric /// vector or a pointer typed value can be returned. For the former, the 3500b57cec5SDimitry Andric /// vector returned is a BDV (and possibly a base) of the entire vector 'I'. 3510b57cec5SDimitry Andric /// If the later, the return pointer is a BDV (or possibly a base) for the 3520b57cec5SDimitry Andric /// particular element in 'I'. 35381ad6265SDimitry Andric static Value *findBaseDefiningValueOfVector(Value *I, DefiningValueMapTy &Cache, 35481ad6265SDimitry Andric IsKnownBaseMapTy &KnownBases) { 3550b57cec5SDimitry Andric // Each case parallels findBaseDefiningValue below, see that code for 3560b57cec5SDimitry Andric // detailed motivation. 3570b57cec5SDimitry Andric 35881ad6265SDimitry Andric auto Cached = Cache.find(I); 35981ad6265SDimitry Andric if (Cached != Cache.end()) 36081ad6265SDimitry Andric return Cached->second; 3610b57cec5SDimitry Andric 36281ad6265SDimitry Andric if (isa<Argument>(I)) { 36381ad6265SDimitry Andric // An incoming argument to the function is a base pointer 36481ad6265SDimitry Andric Cache[I] = I; 36581ad6265SDimitry Andric setKnownBase(I, /* IsKnownBase */true, KnownBases); 36681ad6265SDimitry Andric return I; 36781ad6265SDimitry Andric } 36881ad6265SDimitry Andric 36981ad6265SDimitry Andric if (isa<Constant>(I)) { 3700b57cec5SDimitry Andric // Base of constant vector consists only of constant null pointers. 3710b57cec5SDimitry Andric // For reasoning see similar case inside 'findBaseDefiningValue' function. 37281ad6265SDimitry Andric auto *CAZ = ConstantAggregateZero::get(I->getType()); 37381ad6265SDimitry Andric Cache[I] = CAZ; 37481ad6265SDimitry Andric setKnownBase(CAZ, /* IsKnownBase */true, KnownBases); 37581ad6265SDimitry Andric return CAZ; 37681ad6265SDimitry Andric } 3770b57cec5SDimitry Andric 37881ad6265SDimitry Andric if (isa<LoadInst>(I)) { 37981ad6265SDimitry Andric Cache[I] = I; 38081ad6265SDimitry Andric setKnownBase(I, /* IsKnownBase */true, KnownBases); 38181ad6265SDimitry Andric return I; 38281ad6265SDimitry Andric } 3830b57cec5SDimitry Andric 38481ad6265SDimitry Andric if (isa<InsertElementInst>(I)) { 3850b57cec5SDimitry Andric // We don't know whether this vector contains entirely base pointers or 3860b57cec5SDimitry Andric // not. To be conservatively correct, we treat it as a BDV and will 3870b57cec5SDimitry Andric // duplicate code as needed to construct a parallel vector of bases. 38881ad6265SDimitry Andric Cache[I] = I; 38981ad6265SDimitry Andric setKnownBase(I, /* IsKnownBase */false, KnownBases); 39081ad6265SDimitry Andric return I; 39181ad6265SDimitry Andric } 3920b57cec5SDimitry Andric 39381ad6265SDimitry Andric if (isa<ShuffleVectorInst>(I)) { 3940b57cec5SDimitry Andric // We don't know whether this vector contains entirely base pointers or 3950b57cec5SDimitry Andric // not. To be conservatively correct, we treat it as a BDV and will 3960b57cec5SDimitry Andric // duplicate code as needed to construct a parallel vector of bases. 3970b57cec5SDimitry Andric // TODO: There a number of local optimizations which could be applied here 3980b57cec5SDimitry Andric // for particular sufflevector patterns. 39981ad6265SDimitry Andric Cache[I] = I; 40081ad6265SDimitry Andric setKnownBase(I, /* IsKnownBase */false, KnownBases); 40181ad6265SDimitry Andric return I; 40281ad6265SDimitry Andric } 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric // The behavior of getelementptr instructions is the same for vector and 4050b57cec5SDimitry Andric // non-vector data types. 40681ad6265SDimitry Andric if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) { 40781ad6265SDimitry Andric auto *BDV = 40881ad6265SDimitry Andric findBaseDefiningValue(GEP->getPointerOperand(), Cache, KnownBases); 40981ad6265SDimitry Andric Cache[GEP] = BDV; 41081ad6265SDimitry Andric return BDV; 41181ad6265SDimitry Andric } 41281ad6265SDimitry Andric 41381ad6265SDimitry Andric // The behavior of freeze instructions is the same for vector and 41481ad6265SDimitry Andric // non-vector data types. 41581ad6265SDimitry Andric if (auto *Freeze = dyn_cast<FreezeInst>(I)) { 41681ad6265SDimitry Andric auto *BDV = findBaseDefiningValue(Freeze->getOperand(0), Cache, KnownBases); 41781ad6265SDimitry Andric Cache[Freeze] = BDV; 41881ad6265SDimitry Andric return BDV; 41981ad6265SDimitry Andric } 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric // If the pointer comes through a bitcast of a vector of pointers to 4220b57cec5SDimitry Andric // a vector of another type of pointer, then look through the bitcast 42381ad6265SDimitry Andric if (auto *BC = dyn_cast<BitCastInst>(I)) { 42481ad6265SDimitry Andric auto *BDV = findBaseDefiningValue(BC->getOperand(0), Cache, KnownBases); 42581ad6265SDimitry Andric Cache[BC] = BDV; 42681ad6265SDimitry Andric return BDV; 42781ad6265SDimitry Andric } 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric // We assume that functions in the source language only return base 4300b57cec5SDimitry Andric // pointers. This should probably be generalized via attributes to support 4310b57cec5SDimitry Andric // both source language and internal functions. 43281ad6265SDimitry Andric if (isa<CallInst>(I) || isa<InvokeInst>(I)) { 43381ad6265SDimitry Andric Cache[I] = I; 43481ad6265SDimitry Andric setKnownBase(I, /* IsKnownBase */true, KnownBases); 43581ad6265SDimitry Andric return I; 43681ad6265SDimitry Andric } 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric // A PHI or Select is a base defining value. The outer findBasePointer 4390b57cec5SDimitry Andric // algorithm is responsible for constructing a base value for this BDV. 4400b57cec5SDimitry Andric assert((isa<SelectInst>(I) || isa<PHINode>(I)) && 4410b57cec5SDimitry Andric "unknown vector instruction - no base found for vector element"); 44281ad6265SDimitry Andric Cache[I] = I; 44381ad6265SDimitry Andric setKnownBase(I, /* IsKnownBase */false, KnownBases); 44481ad6265SDimitry Andric return I; 4450b57cec5SDimitry Andric } 4460b57cec5SDimitry Andric 4470b57cec5SDimitry Andric /// Helper function for findBasePointer - Will return a value which either a) 4480b57cec5SDimitry Andric /// defines the base pointer for the input, b) blocks the simple search 4490b57cec5SDimitry Andric /// (i.e. a PHI or Select of two derived pointers), or c) involves a change 4500b57cec5SDimitry Andric /// from pointer to vector type or back. 45181ad6265SDimitry Andric static Value *findBaseDefiningValue(Value *I, DefiningValueMapTy &Cache, 45281ad6265SDimitry Andric IsKnownBaseMapTy &KnownBases) { 4530b57cec5SDimitry Andric assert(I->getType()->isPtrOrPtrVectorTy() && 4540b57cec5SDimitry Andric "Illegal to ask for the base pointer of a non-pointer type"); 45581ad6265SDimitry Andric auto Cached = Cache.find(I); 45681ad6265SDimitry Andric if (Cached != Cache.end()) 45781ad6265SDimitry Andric return Cached->second; 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric if (I->getType()->isVectorTy()) 46081ad6265SDimitry Andric return findBaseDefiningValueOfVector(I, Cache, KnownBases); 4610b57cec5SDimitry Andric 46281ad6265SDimitry Andric if (isa<Argument>(I)) { 4630b57cec5SDimitry Andric // An incoming argument to the function is a base pointer 4640b57cec5SDimitry Andric // We should have never reached here if this argument isn't an gc value 46581ad6265SDimitry Andric Cache[I] = I; 46681ad6265SDimitry Andric setKnownBase(I, /* IsKnownBase */true, KnownBases); 46781ad6265SDimitry Andric return I; 46881ad6265SDimitry Andric } 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric if (isa<Constant>(I)) { 4710b57cec5SDimitry Andric // We assume that objects with a constant base (e.g. a global) can't move 4720b57cec5SDimitry Andric // and don't need to be reported to the collector because they are always 4730b57cec5SDimitry Andric // live. Besides global references, all kinds of constants (e.g. undef, 4740b57cec5SDimitry Andric // constant expressions, null pointers) can be introduced by the inliner or 4750b57cec5SDimitry Andric // the optimizer, especially on dynamically dead paths. 4760b57cec5SDimitry Andric // Here we treat all of them as having single null base. By doing this we 4770b57cec5SDimitry Andric // trying to avoid problems reporting various conflicts in a form of 4780b57cec5SDimitry Andric // "phi (const1, const2)" or "phi (const, regular gc ptr)". 4790b57cec5SDimitry Andric // See constant.ll file for relevant test cases. 4800b57cec5SDimitry Andric 48181ad6265SDimitry Andric auto *CPN = ConstantPointerNull::get(cast<PointerType>(I->getType())); 48281ad6265SDimitry Andric Cache[I] = CPN; 48381ad6265SDimitry Andric setKnownBase(CPN, /* IsKnownBase */true, KnownBases); 48481ad6265SDimitry Andric return CPN; 4850b57cec5SDimitry Andric } 4860b57cec5SDimitry Andric 487fe6060f1SDimitry Andric // inttoptrs in an integral address space are currently ill-defined. We 488fe6060f1SDimitry Andric // treat them as defining base pointers here for consistency with the 489fe6060f1SDimitry Andric // constant rule above and because we don't really have a better semantic 490fe6060f1SDimitry Andric // to give them. Note that the optimizer is always free to insert undefined 491fe6060f1SDimitry Andric // behavior on dynamically dead paths as well. 49281ad6265SDimitry Andric if (isa<IntToPtrInst>(I)) { 49381ad6265SDimitry Andric Cache[I] = I; 49481ad6265SDimitry Andric setKnownBase(I, /* IsKnownBase */true, KnownBases); 49581ad6265SDimitry Andric return I; 49681ad6265SDimitry Andric } 497fe6060f1SDimitry Andric 4980b57cec5SDimitry Andric if (CastInst *CI = dyn_cast<CastInst>(I)) { 4990b57cec5SDimitry Andric Value *Def = CI->stripPointerCasts(); 5000b57cec5SDimitry Andric // If stripping pointer casts changes the address space there is an 5010b57cec5SDimitry Andric // addrspacecast in between. 5020b57cec5SDimitry Andric assert(cast<PointerType>(Def->getType())->getAddressSpace() == 5030b57cec5SDimitry Andric cast<PointerType>(CI->getType())->getAddressSpace() && 5040b57cec5SDimitry Andric "unsupported addrspacecast"); 5050b57cec5SDimitry Andric // If we find a cast instruction here, it means we've found a cast which is 5060b57cec5SDimitry Andric // not simply a pointer cast (i.e. an inttoptr). We don't know how to 5070b57cec5SDimitry Andric // handle int->ptr conversion. 5080b57cec5SDimitry Andric assert(!isa<CastInst>(Def) && "shouldn't find another cast here"); 50981ad6265SDimitry Andric auto *BDV = findBaseDefiningValue(Def, Cache, KnownBases); 51081ad6265SDimitry Andric Cache[CI] = BDV; 51181ad6265SDimitry Andric return BDV; 5120b57cec5SDimitry Andric } 5130b57cec5SDimitry Andric 51481ad6265SDimitry Andric if (isa<LoadInst>(I)) { 5150b57cec5SDimitry Andric // The value loaded is an gc base itself 51681ad6265SDimitry Andric Cache[I] = I; 51781ad6265SDimitry Andric setKnownBase(I, /* IsKnownBase */true, KnownBases); 51881ad6265SDimitry Andric return I; 51981ad6265SDimitry Andric } 5200b57cec5SDimitry Andric 52181ad6265SDimitry Andric if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I)) { 5220b57cec5SDimitry Andric // The base of this GEP is the base 52381ad6265SDimitry Andric auto *BDV = 52481ad6265SDimitry Andric findBaseDefiningValue(GEP->getPointerOperand(), Cache, KnownBases); 52581ad6265SDimitry Andric Cache[GEP] = BDV; 52681ad6265SDimitry Andric return BDV; 52781ad6265SDimitry Andric } 52881ad6265SDimitry Andric 52981ad6265SDimitry Andric if (auto *Freeze = dyn_cast<FreezeInst>(I)) { 53081ad6265SDimitry Andric auto *BDV = findBaseDefiningValue(Freeze->getOperand(0), Cache, KnownBases); 53181ad6265SDimitry Andric Cache[Freeze] = BDV; 53281ad6265SDimitry Andric return BDV; 53381ad6265SDimitry Andric } 5340b57cec5SDimitry Andric 5350b57cec5SDimitry Andric if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { 5360b57cec5SDimitry Andric switch (II->getIntrinsicID()) { 5370b57cec5SDimitry Andric default: 5380b57cec5SDimitry Andric // fall through to general call handling 5390b57cec5SDimitry Andric break; 5400b57cec5SDimitry Andric case Intrinsic::experimental_gc_statepoint: 5410b57cec5SDimitry Andric llvm_unreachable("statepoints don't produce pointers"); 5420b57cec5SDimitry Andric case Intrinsic::experimental_gc_relocate: 5430b57cec5SDimitry Andric // Rerunning safepoint insertion after safepoints are already 5440b57cec5SDimitry Andric // inserted is not supported. It could probably be made to work, 5450b57cec5SDimitry Andric // but why are you doing this? There's no good reason. 5460b57cec5SDimitry Andric llvm_unreachable("repeat safepoint insertion is not supported"); 5470b57cec5SDimitry Andric case Intrinsic::gcroot: 5480b57cec5SDimitry Andric // Currently, this mechanism hasn't been extended to work with gcroot. 5490b57cec5SDimitry Andric // There's no reason it couldn't be, but I haven't thought about the 5500b57cec5SDimitry Andric // implications much. 5510b57cec5SDimitry Andric llvm_unreachable( 5520b57cec5SDimitry Andric "interaction with the gcroot mechanism is not supported"); 553fe6060f1SDimitry Andric case Intrinsic::experimental_gc_get_pointer_base: 55481ad6265SDimitry Andric auto *BDV = findBaseDefiningValue(II->getOperand(0), Cache, KnownBases); 55581ad6265SDimitry Andric Cache[II] = BDV; 55681ad6265SDimitry Andric return BDV; 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric } 5590b57cec5SDimitry Andric // We assume that functions in the source language only return base 5600b57cec5SDimitry Andric // pointers. This should probably be generalized via attributes to support 5610b57cec5SDimitry Andric // both source language and internal functions. 56281ad6265SDimitry Andric if (isa<CallInst>(I) || isa<InvokeInst>(I)) { 56381ad6265SDimitry Andric Cache[I] = I; 56481ad6265SDimitry Andric setKnownBase(I, /* IsKnownBase */true, KnownBases); 56581ad6265SDimitry Andric return I; 56681ad6265SDimitry Andric } 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric // TODO: I have absolutely no idea how to implement this part yet. It's not 5690b57cec5SDimitry Andric // necessarily hard, I just haven't really looked at it yet. 5700b57cec5SDimitry Andric assert(!isa<LandingPadInst>(I) && "Landing Pad is unimplemented"); 5710b57cec5SDimitry Andric 57281ad6265SDimitry Andric if (isa<AtomicCmpXchgInst>(I)) { 5730b57cec5SDimitry Andric // A CAS is effectively a atomic store and load combined under a 5740b57cec5SDimitry Andric // predicate. From the perspective of base pointers, we just treat it 5750b57cec5SDimitry Andric // like a load. 57681ad6265SDimitry Andric Cache[I] = I; 57781ad6265SDimitry Andric setKnownBase(I, /* IsKnownBase */true, KnownBases); 57881ad6265SDimitry Andric return I; 57981ad6265SDimitry Andric } 5800b57cec5SDimitry Andric 5810b57cec5SDimitry Andric assert(!isa<AtomicRMWInst>(I) && "Xchg handled above, all others are " 5820b57cec5SDimitry Andric "binary ops which don't apply to pointers"); 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric // The aggregate ops. Aggregates can either be in the heap or on the 5850b57cec5SDimitry Andric // stack, but in either case, this is simply a field load. As a result, 5860b57cec5SDimitry Andric // this is a defining definition of the base just like a load is. 58781ad6265SDimitry Andric if (isa<ExtractValueInst>(I)) { 58881ad6265SDimitry Andric Cache[I] = I; 58981ad6265SDimitry Andric setKnownBase(I, /* IsKnownBase */true, KnownBases); 59081ad6265SDimitry Andric return I; 59181ad6265SDimitry Andric } 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric // We should never see an insert vector since that would require we be 5940b57cec5SDimitry Andric // tracing back a struct value not a pointer value. 5950b57cec5SDimitry Andric assert(!isa<InsertValueInst>(I) && 5960b57cec5SDimitry Andric "Base pointer for a struct is meaningless"); 5970b57cec5SDimitry Andric 598fe6060f1SDimitry Andric // This value might have been generated by findBasePointer() called when 599fe6060f1SDimitry Andric // substituting gc.get.pointer.base() intrinsic. 600fe6060f1SDimitry Andric bool IsKnownBase = 601fe6060f1SDimitry Andric isa<Instruction>(I) && cast<Instruction>(I)->getMetadata("is_base_value"); 60281ad6265SDimitry Andric setKnownBase(I, /* IsKnownBase */IsKnownBase, KnownBases); 60381ad6265SDimitry Andric Cache[I] = I; 604fe6060f1SDimitry Andric 6050b57cec5SDimitry Andric // An extractelement produces a base result exactly when it's input does. 6060b57cec5SDimitry Andric // We may need to insert a parallel instruction to extract the appropriate 6070b57cec5SDimitry Andric // element out of the base vector corresponding to the input. Given this, 6080b57cec5SDimitry Andric // it's analogous to the phi and select case even though it's not a merge. 6090b57cec5SDimitry Andric if (isa<ExtractElementInst>(I)) 6100b57cec5SDimitry Andric // Note: There a lot of obvious peephole cases here. This are deliberately 6110b57cec5SDimitry Andric // handled after the main base pointer inference algorithm to make writing 6120b57cec5SDimitry Andric // test cases to exercise that code easier. 61381ad6265SDimitry Andric return I; 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric // The last two cases here don't return a base pointer. Instead, they 6160b57cec5SDimitry Andric // return a value which dynamically selects from among several base 6170b57cec5SDimitry Andric // derived pointers (each with it's own base potentially). It's the job of 6180b57cec5SDimitry Andric // the caller to resolve these. 6190b57cec5SDimitry Andric assert((isa<SelectInst>(I) || isa<PHINode>(I)) && 62081ad6265SDimitry Andric "missing instruction case in findBaseDefiningValue"); 62181ad6265SDimitry Andric return I; 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric /// Returns the base defining value for this value. 62581ad6265SDimitry Andric static Value *findBaseDefiningValueCached(Value *I, DefiningValueMapTy &Cache, 62681ad6265SDimitry Andric IsKnownBaseMapTy &KnownBases) { 62706c3fb27SDimitry Andric if (!Cache.contains(I)) { 62881ad6265SDimitry Andric auto *BDV = findBaseDefiningValue(I, Cache, KnownBases); 62981ad6265SDimitry Andric Cache[I] = BDV; 6300b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "fBDV-cached: " << I->getName() << " -> " 63181ad6265SDimitry Andric << Cache[I]->getName() << ", is known base = " 63281ad6265SDimitry Andric << KnownBases[I] << "\n"); 6330b57cec5SDimitry Andric } 6340b57cec5SDimitry Andric assert(Cache[I] != nullptr); 63506c3fb27SDimitry Andric assert(KnownBases.contains(Cache[I]) && 63681ad6265SDimitry Andric "Cached value must be present in known bases map"); 63781ad6265SDimitry Andric return Cache[I]; 6380b57cec5SDimitry Andric } 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andric /// Return a base pointer for this value if known. Otherwise, return it's 6410b57cec5SDimitry Andric /// base defining value. 64281ad6265SDimitry Andric static Value *findBaseOrBDV(Value *I, DefiningValueMapTy &Cache, 64381ad6265SDimitry Andric IsKnownBaseMapTy &KnownBases) { 64481ad6265SDimitry Andric Value *Def = findBaseDefiningValueCached(I, Cache, KnownBases); 6450b57cec5SDimitry Andric auto Found = Cache.find(Def); 6460b57cec5SDimitry Andric if (Found != Cache.end()) { 6470b57cec5SDimitry Andric // Either a base-of relation, or a self reference. Caller must check. 6480b57cec5SDimitry Andric return Found->second; 6490b57cec5SDimitry Andric } 6500b57cec5SDimitry Andric // Only a BDV available 6510b57cec5SDimitry Andric return Def; 6520b57cec5SDimitry Andric } 6530b57cec5SDimitry Andric 65481ad6265SDimitry Andric #ifndef NDEBUG 6555ffd83dbSDimitry Andric /// This value is a base pointer that is not generated by RS4GC, i.e. it already 6565ffd83dbSDimitry Andric /// exists in the code. 6575ffd83dbSDimitry Andric static bool isOriginalBaseResult(Value *V) { 6585ffd83dbSDimitry Andric // no recursion possible 6595ffd83dbSDimitry Andric return !isa<PHINode>(V) && !isa<SelectInst>(V) && 6605ffd83dbSDimitry Andric !isa<ExtractElementInst>(V) && !isa<InsertElementInst>(V) && 6615ffd83dbSDimitry Andric !isa<ShuffleVectorInst>(V); 6625ffd83dbSDimitry Andric } 66381ad6265SDimitry Andric #endif 6645ffd83dbSDimitry Andric 66581ad6265SDimitry Andric static bool isKnownBase(Value *V, const IsKnownBaseMapTy &KnownBases) { 66681ad6265SDimitry Andric auto It = KnownBases.find(V); 66781ad6265SDimitry Andric assert(It != KnownBases.end() && "Value not present in the map"); 66881ad6265SDimitry Andric return It->second; 6690b57cec5SDimitry Andric } 6700b57cec5SDimitry Andric 67181ad6265SDimitry Andric static void setKnownBase(Value *V, bool IsKnownBase, 67281ad6265SDimitry Andric IsKnownBaseMapTy &KnownBases) { 67381ad6265SDimitry Andric #ifndef NDEBUG 67481ad6265SDimitry Andric auto It = KnownBases.find(V); 67581ad6265SDimitry Andric if (It != KnownBases.end()) 67681ad6265SDimitry Andric assert(It->second == IsKnownBase && "Changing already present value"); 67781ad6265SDimitry Andric #endif 67881ad6265SDimitry Andric KnownBases[V] = IsKnownBase; 6790b57cec5SDimitry Andric } 6800b57cec5SDimitry Andric 6815ffd83dbSDimitry Andric // Returns true if First and Second values are both scalar or both vector. 6825ffd83dbSDimitry Andric static bool areBothVectorOrScalar(Value *First, Value *Second) { 6835ffd83dbSDimitry Andric return isa<VectorType>(First->getType()) == 6845ffd83dbSDimitry Andric isa<VectorType>(Second->getType()); 6855ffd83dbSDimitry Andric } 6865ffd83dbSDimitry Andric 6870b57cec5SDimitry Andric namespace { 6880b57cec5SDimitry Andric 6890b57cec5SDimitry Andric /// Models the state of a single base defining value in the findBasePointer 6900b57cec5SDimitry Andric /// algorithm for determining where a new instruction is needed to propagate 6910b57cec5SDimitry Andric /// the base of this BDV. 6920b57cec5SDimitry Andric class BDVState { 6930b57cec5SDimitry Andric public: 694fe6060f1SDimitry Andric enum StatusTy { 695fe6060f1SDimitry Andric // Starting state of lattice 696fe6060f1SDimitry Andric Unknown, 697fe6060f1SDimitry Andric // Some specific base value -- does *not* mean that instruction 698fe6060f1SDimitry Andric // propagates the base of the object 699fe6060f1SDimitry Andric // ex: gep %arg, 16 -> %arg is the base value 700fe6060f1SDimitry Andric Base, 701fe6060f1SDimitry Andric // Need to insert a node to represent a merge. 702fe6060f1SDimitry Andric Conflict 703fe6060f1SDimitry Andric }; 7040b57cec5SDimitry Andric 705fe6060f1SDimitry Andric BDVState() { 706fe6060f1SDimitry Andric llvm_unreachable("missing state in map"); 707fe6060f1SDimitry Andric } 7080b57cec5SDimitry Andric 709fe6060f1SDimitry Andric explicit BDVState(Value *OriginalValue) 710fe6060f1SDimitry Andric : OriginalValue(OriginalValue) {} 711fe6060f1SDimitry Andric explicit BDVState(Value *OriginalValue, StatusTy Status, Value *BaseValue = nullptr) 712fe6060f1SDimitry Andric : OriginalValue(OriginalValue), Status(Status), BaseValue(BaseValue) { 7130b57cec5SDimitry Andric assert(Status != Base || BaseValue); 7140b57cec5SDimitry Andric } 7150b57cec5SDimitry Andric 716fe6060f1SDimitry Andric StatusTy getStatus() const { return Status; } 717fe6060f1SDimitry Andric Value *getOriginalValue() const { return OriginalValue; } 7180b57cec5SDimitry Andric Value *getBaseValue() const { return BaseValue; } 7190b57cec5SDimitry Andric 7200b57cec5SDimitry Andric bool isBase() const { return getStatus() == Base; } 7210b57cec5SDimitry Andric bool isUnknown() const { return getStatus() == Unknown; } 7220b57cec5SDimitry Andric bool isConflict() const { return getStatus() == Conflict; } 7230b57cec5SDimitry Andric 724fe6060f1SDimitry Andric // Values of type BDVState form a lattice, and this function implements the 725fe6060f1SDimitry Andric // meet 726fe6060f1SDimitry Andric // operation. 727fe6060f1SDimitry Andric void meet(const BDVState &Other) { 728fe6060f1SDimitry Andric auto markConflict = [&]() { 729fe6060f1SDimitry Andric Status = BDVState::Conflict; 730fe6060f1SDimitry Andric BaseValue = nullptr; 731fe6060f1SDimitry Andric }; 732fe6060f1SDimitry Andric // Conflict is a final state. 733fe6060f1SDimitry Andric if (isConflict()) 734fe6060f1SDimitry Andric return; 735fe6060f1SDimitry Andric // if we are not known - just take other state. 736fe6060f1SDimitry Andric if (isUnknown()) { 737fe6060f1SDimitry Andric Status = Other.getStatus(); 738fe6060f1SDimitry Andric BaseValue = Other.getBaseValue(); 739fe6060f1SDimitry Andric return; 740fe6060f1SDimitry Andric } 741fe6060f1SDimitry Andric // We are base. 742fe6060f1SDimitry Andric assert(isBase() && "Unknown state"); 743fe6060f1SDimitry Andric // If other is unknown - just keep our state. 744fe6060f1SDimitry Andric if (Other.isUnknown()) 745fe6060f1SDimitry Andric return; 746fe6060f1SDimitry Andric // If other is conflict - it is a final state. 747fe6060f1SDimitry Andric if (Other.isConflict()) 748fe6060f1SDimitry Andric return markConflict(); 749fe6060f1SDimitry Andric // Other is base as well. 750fe6060f1SDimitry Andric assert(Other.isBase() && "Unknown state"); 751fe6060f1SDimitry Andric // If bases are different - Conflict. 752fe6060f1SDimitry Andric if (getBaseValue() != Other.getBaseValue()) 753fe6060f1SDimitry Andric return markConflict(); 754fe6060f1SDimitry Andric // We are identical, do nothing. 755fe6060f1SDimitry Andric } 756fe6060f1SDimitry Andric 7570b57cec5SDimitry Andric bool operator==(const BDVState &Other) const { 758349cc55cSDimitry Andric return OriginalValue == Other.OriginalValue && BaseValue == Other.BaseValue && 759fe6060f1SDimitry Andric Status == Other.Status; 7600b57cec5SDimitry Andric } 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric bool operator!=(const BDVState &other) const { return !(*this == other); } 7630b57cec5SDimitry Andric 7640b57cec5SDimitry Andric LLVM_DUMP_METHOD 7650b57cec5SDimitry Andric void dump() const { 7660b57cec5SDimitry Andric print(dbgs()); 7670b57cec5SDimitry Andric dbgs() << '\n'; 7680b57cec5SDimitry Andric } 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric void print(raw_ostream &OS) const { 7710b57cec5SDimitry Andric switch (getStatus()) { 7720b57cec5SDimitry Andric case Unknown: 7730b57cec5SDimitry Andric OS << "U"; 7740b57cec5SDimitry Andric break; 7750b57cec5SDimitry Andric case Base: 7760b57cec5SDimitry Andric OS << "B"; 7770b57cec5SDimitry Andric break; 7780b57cec5SDimitry Andric case Conflict: 7790b57cec5SDimitry Andric OS << "C"; 7800b57cec5SDimitry Andric break; 7810b57cec5SDimitry Andric } 782fe6060f1SDimitry Andric OS << " (base " << getBaseValue() << " - " 783fe6060f1SDimitry Andric << (getBaseValue() ? getBaseValue()->getName() : "nullptr") << ")" 784fe6060f1SDimitry Andric << " for " << OriginalValue->getName() << ":"; 7850b57cec5SDimitry Andric } 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric private: 788fe6060f1SDimitry Andric AssertingVH<Value> OriginalValue; // instruction this state corresponds to 789fe6060f1SDimitry Andric StatusTy Status = Unknown; 790fe6060f1SDimitry Andric AssertingVH<Value> BaseValue = nullptr; // Non-null only if Status == Base. 7910b57cec5SDimitry Andric }; 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric } // end anonymous namespace 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric #ifndef NDEBUG 7960b57cec5SDimitry Andric static raw_ostream &operator<<(raw_ostream &OS, const BDVState &State) { 7970b57cec5SDimitry Andric State.print(OS); 7980b57cec5SDimitry Andric return OS; 7990b57cec5SDimitry Andric } 8000b57cec5SDimitry Andric #endif 8010b57cec5SDimitry Andric 8020b57cec5SDimitry Andric /// For a given value or instruction, figure out what base ptr its derived from. 8030b57cec5SDimitry Andric /// For gc objects, this is simply itself. On success, returns a value which is 8040b57cec5SDimitry Andric /// the base pointer. (This is reliable and can be used for relocation.) On 8050b57cec5SDimitry Andric /// failure, returns nullptr. 80681ad6265SDimitry Andric static Value *findBasePointer(Value *I, DefiningValueMapTy &Cache, 80781ad6265SDimitry Andric IsKnownBaseMapTy &KnownBases) { 80881ad6265SDimitry Andric Value *Def = findBaseOrBDV(I, Cache, KnownBases); 8090b57cec5SDimitry Andric 81081ad6265SDimitry Andric if (isKnownBase(Def, KnownBases) && areBothVectorOrScalar(Def, I)) 8110b57cec5SDimitry Andric return Def; 8120b57cec5SDimitry Andric 8130b57cec5SDimitry Andric // Here's the rough algorithm: 8140b57cec5SDimitry Andric // - For every SSA value, construct a mapping to either an actual base 8150b57cec5SDimitry Andric // pointer or a PHI which obscures the base pointer. 8160b57cec5SDimitry Andric // - Construct a mapping from PHI to unknown TOP state. Use an 8170b57cec5SDimitry Andric // optimistic algorithm to propagate base pointer information. Lattice 8180b57cec5SDimitry Andric // looks like: 8190b57cec5SDimitry Andric // UNKNOWN 8200b57cec5SDimitry Andric // b1 b2 b3 b4 8210b57cec5SDimitry Andric // CONFLICT 8220b57cec5SDimitry Andric // When algorithm terminates, all PHIs will either have a single concrete 8230b57cec5SDimitry Andric // base or be in a conflict state. 8240b57cec5SDimitry Andric // - For every conflict, insert a dummy PHI node without arguments. Add 8250b57cec5SDimitry Andric // these to the base[Instruction] = BasePtr mapping. For every 8260b57cec5SDimitry Andric // non-conflict, add the actual base. 8270b57cec5SDimitry Andric // - For every conflict, add arguments for the base[a] of each input 8280b57cec5SDimitry Andric // arguments. 8290b57cec5SDimitry Andric // 8300b57cec5SDimitry Andric // Note: A simpler form of this would be to add the conflict form of all 8310b57cec5SDimitry Andric // PHIs without running the optimistic algorithm. This would be 8320b57cec5SDimitry Andric // analogous to pessimistic data flow and would likely lead to an 8330b57cec5SDimitry Andric // overall worse solution. 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric #ifndef NDEBUG 8360b57cec5SDimitry Andric auto isExpectedBDVType = [](Value *BDV) { 8370b57cec5SDimitry Andric return isa<PHINode>(BDV) || isa<SelectInst>(BDV) || 8380b57cec5SDimitry Andric isa<ExtractElementInst>(BDV) || isa<InsertElementInst>(BDV) || 8390b57cec5SDimitry Andric isa<ShuffleVectorInst>(BDV); 8400b57cec5SDimitry Andric }; 8410b57cec5SDimitry Andric #endif 8420b57cec5SDimitry Andric 8430b57cec5SDimitry Andric // Once populated, will contain a mapping from each potentially non-base BDV 8440b57cec5SDimitry Andric // to a lattice value (described above) which corresponds to that BDV. 8450b57cec5SDimitry Andric // We use the order of insertion (DFS over the def/use graph) to provide a 8460b57cec5SDimitry Andric // stable deterministic ordering for visiting DenseMaps (which are unordered) 8470b57cec5SDimitry Andric // below. This is important for deterministic compilation. 8480b57cec5SDimitry Andric MapVector<Value *, BDVState> States; 8490b57cec5SDimitry Andric 850fe6060f1SDimitry Andric #ifndef NDEBUG 851fe6060f1SDimitry Andric auto VerifyStates = [&]() { 852fe6060f1SDimitry Andric for (auto &Entry : States) { 853fe6060f1SDimitry Andric assert(Entry.first == Entry.second.getOriginalValue()); 854fe6060f1SDimitry Andric } 855fe6060f1SDimitry Andric }; 856fe6060f1SDimitry Andric #endif 857fe6060f1SDimitry Andric 858fe6060f1SDimitry Andric auto visitBDVOperands = [](Value *BDV, std::function<void (Value*)> F) { 859fe6060f1SDimitry Andric if (PHINode *PN = dyn_cast<PHINode>(BDV)) { 860fe6060f1SDimitry Andric for (Value *InVal : PN->incoming_values()) 861fe6060f1SDimitry Andric F(InVal); 862fe6060f1SDimitry Andric } else if (SelectInst *SI = dyn_cast<SelectInst>(BDV)) { 863fe6060f1SDimitry Andric F(SI->getTrueValue()); 864fe6060f1SDimitry Andric F(SI->getFalseValue()); 865fe6060f1SDimitry Andric } else if (auto *EE = dyn_cast<ExtractElementInst>(BDV)) { 866fe6060f1SDimitry Andric F(EE->getVectorOperand()); 867fe6060f1SDimitry Andric } else if (auto *IE = dyn_cast<InsertElementInst>(BDV)) { 868fe6060f1SDimitry Andric F(IE->getOperand(0)); 869fe6060f1SDimitry Andric F(IE->getOperand(1)); 870fe6060f1SDimitry Andric } else if (auto *SV = dyn_cast<ShuffleVectorInst>(BDV)) { 871fe6060f1SDimitry Andric // For a canonical broadcast, ignore the undef argument 872fe6060f1SDimitry Andric // (without this, we insert a parallel base shuffle for every broadcast) 873fe6060f1SDimitry Andric F(SV->getOperand(0)); 874fe6060f1SDimitry Andric if (!SV->isZeroEltSplat()) 875fe6060f1SDimitry Andric F(SV->getOperand(1)); 876fe6060f1SDimitry Andric } else { 877fe6060f1SDimitry Andric llvm_unreachable("unexpected BDV type"); 878fe6060f1SDimitry Andric } 879fe6060f1SDimitry Andric }; 880fe6060f1SDimitry Andric 881fe6060f1SDimitry Andric 8820b57cec5SDimitry Andric // Recursively fill in all base defining values reachable from the initial 8830b57cec5SDimitry Andric // one for which we don't already know a definite base value for 8840b57cec5SDimitry Andric /* scope */ { 8850b57cec5SDimitry Andric SmallVector<Value*, 16> Worklist; 8860b57cec5SDimitry Andric Worklist.push_back(Def); 887fe6060f1SDimitry Andric States.insert({Def, BDVState(Def)}); 8880b57cec5SDimitry Andric while (!Worklist.empty()) { 8890b57cec5SDimitry Andric Value *Current = Worklist.pop_back_val(); 8905ffd83dbSDimitry Andric assert(!isOriginalBaseResult(Current) && "why did it get added?"); 8910b57cec5SDimitry Andric 8920b57cec5SDimitry Andric auto visitIncomingValue = [&](Value *InVal) { 89381ad6265SDimitry Andric Value *Base = findBaseOrBDV(InVal, Cache, KnownBases); 89481ad6265SDimitry Andric if (isKnownBase(Base, KnownBases) && areBothVectorOrScalar(Base, InVal)) 8950b57cec5SDimitry Andric // Known bases won't need new instructions introduced and can be 8965ffd83dbSDimitry Andric // ignored safely. However, this can only be done when InVal and Base 8975ffd83dbSDimitry Andric // are both scalar or both vector. Otherwise, we need to find a 8985ffd83dbSDimitry Andric // correct BDV for InVal, by creating an entry in the lattice 8995ffd83dbSDimitry Andric // (States). 9000b57cec5SDimitry Andric return; 9010b57cec5SDimitry Andric assert(isExpectedBDVType(Base) && "the only non-base values " 9020b57cec5SDimitry Andric "we see should be base defining values"); 903fe6060f1SDimitry Andric if (States.insert(std::make_pair(Base, BDVState(Base))).second) 9040b57cec5SDimitry Andric Worklist.push_back(Base); 9050b57cec5SDimitry Andric }; 906fe6060f1SDimitry Andric 907fe6060f1SDimitry Andric visitBDVOperands(Current, visitIncomingValue); 9080b57cec5SDimitry Andric } 9090b57cec5SDimitry Andric } 9100b57cec5SDimitry Andric 9110b57cec5SDimitry Andric #ifndef NDEBUG 912fe6060f1SDimitry Andric VerifyStates(); 9130b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "States after initialization:\n"); 914349cc55cSDimitry Andric for (const auto &Pair : States) { 9150b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " " << Pair.second << " for " << *Pair.first << "\n"); 9160b57cec5SDimitry Andric } 9170b57cec5SDimitry Andric #endif 9180b57cec5SDimitry Andric 919fe6060f1SDimitry Andric // Iterate forward through the value graph pruning any node from the state 920fe6060f1SDimitry Andric // list where all of the inputs are base pointers. The purpose of this is to 921fe6060f1SDimitry Andric // reuse existing values when the derived pointer we were asked to materialize 922fe6060f1SDimitry Andric // a base pointer for happens to be a base pointer itself. (Or a sub-graph 923fe6060f1SDimitry Andric // feeding it does.) 924fe6060f1SDimitry Andric SmallVector<Value *> ToRemove; 925fe6060f1SDimitry Andric do { 926fe6060f1SDimitry Andric ToRemove.clear(); 927fe6060f1SDimitry Andric for (auto Pair : States) { 928fe6060f1SDimitry Andric Value *BDV = Pair.first; 929fe6060f1SDimitry Andric auto canPruneInput = [&](Value *V) { 93081ad6265SDimitry Andric // If the input of the BDV is the BDV itself we can prune it. This is 93181ad6265SDimitry Andric // only possible if the BDV is a PHI node. 93281ad6265SDimitry Andric if (V->stripPointerCasts() == BDV) 93381ad6265SDimitry Andric return true; 93481ad6265SDimitry Andric Value *VBDV = findBaseOrBDV(V, Cache, KnownBases); 93581ad6265SDimitry Andric if (V->stripPointerCasts() != VBDV) 936fe6060f1SDimitry Andric return false; 937fe6060f1SDimitry Andric // The assumption is that anything not in the state list is 938fe6060f1SDimitry Andric // propagates a base pointer. 93981ad6265SDimitry Andric return States.count(VBDV) == 0; 940fe6060f1SDimitry Andric }; 941fe6060f1SDimitry Andric 942fe6060f1SDimitry Andric bool CanPrune = true; 943fe6060f1SDimitry Andric visitBDVOperands(BDV, [&](Value *Op) { 944fe6060f1SDimitry Andric CanPrune = CanPrune && canPruneInput(Op); 945fe6060f1SDimitry Andric }); 946fe6060f1SDimitry Andric if (CanPrune) 947fe6060f1SDimitry Andric ToRemove.push_back(BDV); 948fe6060f1SDimitry Andric } 949fe6060f1SDimitry Andric for (Value *V : ToRemove) { 950fe6060f1SDimitry Andric States.erase(V); 951fe6060f1SDimitry Andric // Cache the fact V is it's own base for later usage. 952fe6060f1SDimitry Andric Cache[V] = V; 953fe6060f1SDimitry Andric } 954fe6060f1SDimitry Andric } while (!ToRemove.empty()); 955fe6060f1SDimitry Andric 956fe6060f1SDimitry Andric // Did we manage to prove that Def itself must be a base pointer? 957fe6060f1SDimitry Andric if (!States.count(Def)) 958fe6060f1SDimitry Andric return Def; 959fe6060f1SDimitry Andric 9600b57cec5SDimitry Andric // Return a phi state for a base defining value. We'll generate a new 9610b57cec5SDimitry Andric // base state for known bases and expect to find a cached state otherwise. 9625ffd83dbSDimitry Andric auto GetStateForBDV = [&](Value *BaseValue, Value *Input) { 9635ffd83dbSDimitry Andric auto I = States.find(BaseValue); 964fe6060f1SDimitry Andric if (I != States.end()) 9650b57cec5SDimitry Andric return I->second; 966fe6060f1SDimitry Andric assert(areBothVectorOrScalar(BaseValue, Input)); 967fe6060f1SDimitry Andric return BDVState(BaseValue, BDVState::Base, BaseValue); 9680b57cec5SDimitry Andric }; 9690b57cec5SDimitry Andric 9705f757f3fSDimitry Andric // Even though we have identified a concrete base (or a conflict) for all live 9715f757f3fSDimitry Andric // pointers at this point, there are cases where the base is of an 9725f757f3fSDimitry Andric // incompatible type compared to the original instruction. We conservatively 9735f757f3fSDimitry Andric // mark those as conflicts to ensure that corresponding BDVs will be generated 9745f757f3fSDimitry Andric // in the next steps. 9755f757f3fSDimitry Andric 9765f757f3fSDimitry Andric // this is a rather explicit check for all cases where we should mark the 9775f757f3fSDimitry Andric // state as a conflict to force the latter stages of the algorithm to emit 9785f757f3fSDimitry Andric // the BDVs. 9795f757f3fSDimitry Andric // TODO: in many cases the instructions emited for the conflicting states 9805f757f3fSDimitry Andric // will be identical to the I itself (if the I's operate on their BDVs 9817a6dacacSDimitry Andric // themselves). We should exploit this, but can't do it here since it would 9825f757f3fSDimitry Andric // break the invariant about the BDVs not being known to be a base. 9835f757f3fSDimitry Andric // TODO: the code also does not handle constants at all - the algorithm relies 9845f757f3fSDimitry Andric // on all constants having the same BDV and therefore constant-only insns 9855f757f3fSDimitry Andric // will never be in conflict, but this check is ignored here. If the 9865f757f3fSDimitry Andric // constant conflicts will be to BDVs themselves, they will be identical 9875f757f3fSDimitry Andric // instructions and will get optimized away (as in the above TODO) 9885f757f3fSDimitry Andric auto MarkConflict = [&](Instruction *I, Value *BaseValue) { 9895f757f3fSDimitry Andric // II and EE mixes vector & scalar so is always a conflict 9905f757f3fSDimitry Andric if (isa<InsertElementInst>(I) || isa<ExtractElementInst>(I)) 9915f757f3fSDimitry Andric return true; 9925f757f3fSDimitry Andric // Shuffle vector is always a conflict as it creates new vector from 9935f757f3fSDimitry Andric // existing ones. 9945f757f3fSDimitry Andric if (isa<ShuffleVectorInst>(I)) 9955f757f3fSDimitry Andric return true; 9965f757f3fSDimitry Andric // Any instructions where the computed base type differs from the 9975f757f3fSDimitry Andric // instruction type. An example is where an extract instruction is used by a 9985f757f3fSDimitry Andric // select. Here the select's BDV is a vector (because of extract's BDV), 9995f757f3fSDimitry Andric // while the select itself is a scalar type. Note that the IE and EE 10005f757f3fSDimitry Andric // instruction check is not fully subsumed by the vector<->scalar check at 10015f757f3fSDimitry Andric // the end, this is due to the BDV algorithm being ignorant of BDV types at 10025f757f3fSDimitry Andric // this junction. 10035f757f3fSDimitry Andric if (!areBothVectorOrScalar(BaseValue, I)) 10045f757f3fSDimitry Andric return true; 10055f757f3fSDimitry Andric return false; 10065f757f3fSDimitry Andric }; 10075f757f3fSDimitry Andric 10087a6dacacSDimitry Andric bool Progress = true; 10097a6dacacSDimitry Andric while (Progress) { 10107a6dacacSDimitry Andric #ifndef NDEBUG 10117a6dacacSDimitry Andric const size_t OldSize = States.size(); 10127a6dacacSDimitry Andric #endif 10137a6dacacSDimitry Andric Progress = false; 10147a6dacacSDimitry Andric // We're only changing values in this loop, thus safe to keep iterators. 10157a6dacacSDimitry Andric // Since this is computing a fixed point, the order of visit does not 10167a6dacacSDimitry Andric // effect the result. TODO: We could use a worklist here and make this run 10177a6dacacSDimitry Andric // much faster. 10187a6dacacSDimitry Andric for (auto Pair : States) { 10197a6dacacSDimitry Andric Value *BDV = Pair.first; 10207a6dacacSDimitry Andric // Only values that do not have known bases or those that have differing 10217a6dacacSDimitry Andric // type (scalar versus vector) from a possible known base should be in the 10227a6dacacSDimitry Andric // lattice. 10237a6dacacSDimitry Andric assert((!isKnownBase(BDV, KnownBases) || 10247a6dacacSDimitry Andric !areBothVectorOrScalar(BDV, Pair.second.getBaseValue())) && 10257a6dacacSDimitry Andric "why did it get added?"); 10267a6dacacSDimitry Andric 10277a6dacacSDimitry Andric BDVState NewState(BDV); 10287a6dacacSDimitry Andric visitBDVOperands(BDV, [&](Value *Op) { 10297a6dacacSDimitry Andric Value *BDV = findBaseOrBDV(Op, Cache, KnownBases); 10307a6dacacSDimitry Andric auto OpState = GetStateForBDV(BDV, Op); 10317a6dacacSDimitry Andric NewState.meet(OpState); 10327a6dacacSDimitry Andric }); 10337a6dacacSDimitry Andric 10347a6dacacSDimitry Andric // if the instruction has known base, but should in fact be marked as 10357a6dacacSDimitry Andric // conflict because of incompatible in/out types, we mark it as such 10367a6dacacSDimitry Andric // ensuring that it will propagate through the fixpoint iteration 10377a6dacacSDimitry Andric auto I = cast<Instruction>(BDV); 10387a6dacacSDimitry Andric auto BV = NewState.getBaseValue(); 10397a6dacacSDimitry Andric if (BV && MarkConflict(I, BV)) 10407a6dacacSDimitry Andric NewState = BDVState(I, BDVState::Conflict); 10417a6dacacSDimitry Andric 10427a6dacacSDimitry Andric BDVState OldState = Pair.second; 10437a6dacacSDimitry Andric if (OldState != NewState) { 10447a6dacacSDimitry Andric Progress = true; 10457a6dacacSDimitry Andric States[BDV] = NewState; 10467a6dacacSDimitry Andric } 10477a6dacacSDimitry Andric } 10487a6dacacSDimitry Andric 10497a6dacacSDimitry Andric assert(OldSize == States.size() && 10507a6dacacSDimitry Andric "fixed point shouldn't be adding any new nodes to state"); 10517a6dacacSDimitry Andric } 10527a6dacacSDimitry Andric 10537a6dacacSDimitry Andric #ifndef NDEBUG 10547a6dacacSDimitry Andric VerifyStates(); 10557a6dacacSDimitry Andric LLVM_DEBUG(dbgs() << "States after meet iteration:\n"); 10567a6dacacSDimitry Andric for (const auto &Pair : States) { 10577a6dacacSDimitry Andric LLVM_DEBUG(dbgs() << " " << Pair.second << " for " << *Pair.first << "\n"); 10587a6dacacSDimitry Andric } 10597a6dacacSDimitry Andric 10607a6dacacSDimitry Andric // since we do the conflict marking as part of the fixpoint iteration this 10617a6dacacSDimitry Andric // loop only asserts that invariants are met 10620b57cec5SDimitry Andric for (auto Pair : States) { 10630b57cec5SDimitry Andric Instruction *I = cast<Instruction>(Pair.first); 10640b57cec5SDimitry Andric BDVState State = Pair.second; 10655ffd83dbSDimitry Andric auto *BaseValue = State.getBaseValue(); 10665ffd83dbSDimitry Andric // Only values that do not have known bases or those that have differing 10675ffd83dbSDimitry Andric // type (scalar versus vector) from a possible known base should be in the 10685ffd83dbSDimitry Andric // lattice. 106981ad6265SDimitry Andric assert( 107081ad6265SDimitry Andric (!isKnownBase(I, KnownBases) || !areBothVectorOrScalar(I, BaseValue)) && 10715ffd83dbSDimitry Andric "why did it get added?"); 10720b57cec5SDimitry Andric assert(!State.isUnknown() && "Optimistic algorithm didn't complete!"); 10730b57cec5SDimitry Andric } 1074fe6060f1SDimitry Andric #endif 1075fe6060f1SDimitry Andric 10765ffd83dbSDimitry Andric // Insert Phis for all conflicts 10775ffd83dbSDimitry Andric // TODO: adjust naming patterns to avoid this order of iteration dependency 10785ffd83dbSDimitry Andric for (auto Pair : States) { 10795ffd83dbSDimitry Andric Instruction *I = cast<Instruction>(Pair.first); 10805ffd83dbSDimitry Andric BDVState State = Pair.second; 10815ffd83dbSDimitry Andric // Only values that do not have known bases or those that have differing 10825ffd83dbSDimitry Andric // type (scalar versus vector) from a possible known base should be in the 10835ffd83dbSDimitry Andric // lattice. 108481ad6265SDimitry Andric assert((!isKnownBase(I, KnownBases) || 108581ad6265SDimitry Andric !areBothVectorOrScalar(I, State.getBaseValue())) && 10865ffd83dbSDimitry Andric "why did it get added?"); 10875ffd83dbSDimitry Andric assert(!State.isUnknown() && "Optimistic algorithm didn't complete!"); 10880b57cec5SDimitry Andric 10890b57cec5SDimitry Andric // Since we're joining a vector and scalar base, they can never be the 10900b57cec5SDimitry Andric // same. As a result, we should always see insert element having reached 10910b57cec5SDimitry Andric // the conflict state. 10920b57cec5SDimitry Andric assert(!isa<InsertElementInst>(I) || State.isConflict()); 10930b57cec5SDimitry Andric 10940b57cec5SDimitry Andric if (!State.isConflict()) 10950b57cec5SDimitry Andric continue; 10960b57cec5SDimitry Andric 1097fe6060f1SDimitry Andric auto getMangledName = [](Instruction *I) -> std::string { 10980b57cec5SDimitry Andric if (isa<PHINode>(I)) { 1099fe6060f1SDimitry Andric return suffixed_name_or(I, ".base", "base_phi"); 1100fe6060f1SDimitry Andric } else if (isa<SelectInst>(I)) { 1101fe6060f1SDimitry Andric return suffixed_name_or(I, ".base", "base_select"); 1102fe6060f1SDimitry Andric } else if (isa<ExtractElementInst>(I)) { 1103fe6060f1SDimitry Andric return suffixed_name_or(I, ".base", "base_ee"); 1104fe6060f1SDimitry Andric } else if (isa<InsertElementInst>(I)) { 1105fe6060f1SDimitry Andric return suffixed_name_or(I, ".base", "base_ie"); 11060b57cec5SDimitry Andric } else { 1107fe6060f1SDimitry Andric return suffixed_name_or(I, ".base", "base_sv"); 11080b57cec5SDimitry Andric } 11090b57cec5SDimitry Andric }; 1110fe6060f1SDimitry Andric 1111fe6060f1SDimitry Andric Instruction *BaseInst = I->clone(); 1112fe6060f1SDimitry Andric BaseInst->insertBefore(I); 1113fe6060f1SDimitry Andric BaseInst->setName(getMangledName(I)); 11140b57cec5SDimitry Andric // Add metadata marking this as a base value 11150b57cec5SDimitry Andric BaseInst->setMetadata("is_base_value", MDNode::get(I->getContext(), {})); 1116fe6060f1SDimitry Andric States[I] = BDVState(I, BDVState::Conflict, BaseInst); 111781ad6265SDimitry Andric setKnownBase(BaseInst, /* IsKnownBase */true, KnownBases); 11180b57cec5SDimitry Andric } 11190b57cec5SDimitry Andric 1120fe6060f1SDimitry Andric #ifndef NDEBUG 1121fe6060f1SDimitry Andric VerifyStates(); 1122fe6060f1SDimitry Andric #endif 1123fe6060f1SDimitry Andric 11240b57cec5SDimitry Andric // Returns a instruction which produces the base pointer for a given 11250b57cec5SDimitry Andric // instruction. The instruction is assumed to be an input to one of the BDVs 11260b57cec5SDimitry Andric // seen in the inference algorithm above. As such, we must either already 11270b57cec5SDimitry Andric // know it's base defining value is a base, or have inserted a new 11280b57cec5SDimitry Andric // instruction to propagate the base of it's BDV and have entered that newly 11290b57cec5SDimitry Andric // introduced instruction into the state table. In either case, we are 11300b57cec5SDimitry Andric // assured to be able to determine an instruction which produces it's base 11310b57cec5SDimitry Andric // pointer. 11320b57cec5SDimitry Andric auto getBaseForInput = [&](Value *Input, Instruction *InsertPt) { 113381ad6265SDimitry Andric Value *BDV = findBaseOrBDV(Input, Cache, KnownBases); 11340b57cec5SDimitry Andric Value *Base = nullptr; 1135fe6060f1SDimitry Andric if (!States.count(BDV)) { 1136fe6060f1SDimitry Andric assert(areBothVectorOrScalar(BDV, Input)); 11370b57cec5SDimitry Andric Base = BDV; 11380b57cec5SDimitry Andric } else { 11390b57cec5SDimitry Andric // Either conflict or base. 11400b57cec5SDimitry Andric assert(States.count(BDV)); 11410b57cec5SDimitry Andric Base = States[BDV].getBaseValue(); 11420b57cec5SDimitry Andric } 11430b57cec5SDimitry Andric assert(Base && "Can't be null"); 11440b57cec5SDimitry Andric // The cast is needed since base traversal may strip away bitcasts 11450b57cec5SDimitry Andric if (Base->getType() != Input->getType() && InsertPt) 1146*0fca6ea1SDimitry Andric Base = new BitCastInst(Base, Input->getType(), "cast", 1147*0fca6ea1SDimitry Andric InsertPt->getIterator()); 11480b57cec5SDimitry Andric return Base; 11490b57cec5SDimitry Andric }; 11500b57cec5SDimitry Andric 11510b57cec5SDimitry Andric // Fixup all the inputs of the new PHIs. Visit order needs to be 11520b57cec5SDimitry Andric // deterministic and predictable because we're naming newly created 11530b57cec5SDimitry Andric // instructions. 11540b57cec5SDimitry Andric for (auto Pair : States) { 11550b57cec5SDimitry Andric Instruction *BDV = cast<Instruction>(Pair.first); 11560b57cec5SDimitry Andric BDVState State = Pair.second; 11570b57cec5SDimitry Andric 11585ffd83dbSDimitry Andric // Only values that do not have known bases or those that have differing 11595ffd83dbSDimitry Andric // type (scalar versus vector) from a possible known base should be in the 11605ffd83dbSDimitry Andric // lattice. 116181ad6265SDimitry Andric assert((!isKnownBase(BDV, KnownBases) || 11625ffd83dbSDimitry Andric !areBothVectorOrScalar(BDV, State.getBaseValue())) && 11635ffd83dbSDimitry Andric "why did it get added?"); 11640b57cec5SDimitry Andric assert(!State.isUnknown() && "Optimistic algorithm didn't complete!"); 11650b57cec5SDimitry Andric if (!State.isConflict()) 11660b57cec5SDimitry Andric continue; 11670b57cec5SDimitry Andric 11680b57cec5SDimitry Andric if (PHINode *BasePHI = dyn_cast<PHINode>(State.getBaseValue())) { 11690b57cec5SDimitry Andric PHINode *PN = cast<PHINode>(BDV); 1170fe6060f1SDimitry Andric const unsigned NumPHIValues = PN->getNumIncomingValues(); 1171fe6060f1SDimitry Andric 1172fe6060f1SDimitry Andric // The IR verifier requires phi nodes with multiple entries from the 1173fe6060f1SDimitry Andric // same basic block to have the same incoming value for each of those 1174fe6060f1SDimitry Andric // entries. Since we're inserting bitcasts in the loop, make sure we 1175fe6060f1SDimitry Andric // do so at least once per incoming block. 1176fe6060f1SDimitry Andric DenseMap<BasicBlock *, Value*> BlockToValue; 11770b57cec5SDimitry Andric for (unsigned i = 0; i < NumPHIValues; i++) { 11780b57cec5SDimitry Andric Value *InVal = PN->getIncomingValue(i); 11790b57cec5SDimitry Andric BasicBlock *InBB = PN->getIncomingBlock(i); 1180fe6060f1SDimitry Andric if (!BlockToValue.count(InBB)) 1181fe6060f1SDimitry Andric BlockToValue[InBB] = getBaseForInput(InVal, InBB->getTerminator()); 1182fe6060f1SDimitry Andric else { 11830b57cec5SDimitry Andric #ifndef NDEBUG 1184fe6060f1SDimitry Andric Value *OldBase = BlockToValue[InBB]; 11850b57cec5SDimitry Andric Value *Base = getBaseForInput(InVal, nullptr); 118681ad6265SDimitry Andric 118781ad6265SDimitry Andric // We can't use `stripPointerCasts` instead of this function because 118881ad6265SDimitry Andric // `stripPointerCasts` doesn't handle vectors of pointers. 118981ad6265SDimitry Andric auto StripBitCasts = [](Value *V) -> Value * { 119081ad6265SDimitry Andric while (auto *BC = dyn_cast<BitCastInst>(V)) 119181ad6265SDimitry Andric V = BC->getOperand(0); 119281ad6265SDimitry Andric return V; 119381ad6265SDimitry Andric }; 11940b57cec5SDimitry Andric // In essence this assert states: the only way two values 11950b57cec5SDimitry Andric // incoming from the same basic block may be different is by 11960b57cec5SDimitry Andric // being different bitcasts of the same value. A cleanup 11970b57cec5SDimitry Andric // that remains TODO is changing findBaseOrBDV to return an 11980b57cec5SDimitry Andric // llvm::Value of the correct type (and still remain pure). 11990b57cec5SDimitry Andric // This will remove the need to add bitcasts. 120081ad6265SDimitry Andric assert(StripBitCasts(Base) == StripBitCasts(OldBase) && 1201349cc55cSDimitry Andric "findBaseOrBDV should be pure!"); 12020b57cec5SDimitry Andric #endif 12030b57cec5SDimitry Andric } 1204fe6060f1SDimitry Andric Value *Base = BlockToValue[InBB]; 1205fe6060f1SDimitry Andric BasePHI->setIncomingValue(i, Base); 12060b57cec5SDimitry Andric } 12070b57cec5SDimitry Andric } else if (SelectInst *BaseSI = 12080b57cec5SDimitry Andric dyn_cast<SelectInst>(State.getBaseValue())) { 12090b57cec5SDimitry Andric SelectInst *SI = cast<SelectInst>(BDV); 12100b57cec5SDimitry Andric 12110b57cec5SDimitry Andric // Find the instruction which produces the base for each input. 12120b57cec5SDimitry Andric // We may need to insert a bitcast. 12130b57cec5SDimitry Andric BaseSI->setTrueValue(getBaseForInput(SI->getTrueValue(), BaseSI)); 12140b57cec5SDimitry Andric BaseSI->setFalseValue(getBaseForInput(SI->getFalseValue(), BaseSI)); 12150b57cec5SDimitry Andric } else if (auto *BaseEE = 12160b57cec5SDimitry Andric dyn_cast<ExtractElementInst>(State.getBaseValue())) { 12170b57cec5SDimitry Andric Value *InVal = cast<ExtractElementInst>(BDV)->getVectorOperand(); 12180b57cec5SDimitry Andric // Find the instruction which produces the base for each input. We may 12190b57cec5SDimitry Andric // need to insert a bitcast. 12200b57cec5SDimitry Andric BaseEE->setOperand(0, getBaseForInput(InVal, BaseEE)); 12210b57cec5SDimitry Andric } else if (auto *BaseIE = dyn_cast<InsertElementInst>(State.getBaseValue())){ 12220b57cec5SDimitry Andric auto *BdvIE = cast<InsertElementInst>(BDV); 12230b57cec5SDimitry Andric auto UpdateOperand = [&](int OperandIdx) { 12240b57cec5SDimitry Andric Value *InVal = BdvIE->getOperand(OperandIdx); 12250b57cec5SDimitry Andric Value *Base = getBaseForInput(InVal, BaseIE); 12260b57cec5SDimitry Andric BaseIE->setOperand(OperandIdx, Base); 12270b57cec5SDimitry Andric }; 12280b57cec5SDimitry Andric UpdateOperand(0); // vector operand 12290b57cec5SDimitry Andric UpdateOperand(1); // scalar operand 12300b57cec5SDimitry Andric } else { 12310b57cec5SDimitry Andric auto *BaseSV = cast<ShuffleVectorInst>(State.getBaseValue()); 12320b57cec5SDimitry Andric auto *BdvSV = cast<ShuffleVectorInst>(BDV); 12330b57cec5SDimitry Andric auto UpdateOperand = [&](int OperandIdx) { 12340b57cec5SDimitry Andric Value *InVal = BdvSV->getOperand(OperandIdx); 12350b57cec5SDimitry Andric Value *Base = getBaseForInput(InVal, BaseSV); 12360b57cec5SDimitry Andric BaseSV->setOperand(OperandIdx, Base); 12370b57cec5SDimitry Andric }; 12380b57cec5SDimitry Andric UpdateOperand(0); // vector operand 1239fe6060f1SDimitry Andric if (!BdvSV->isZeroEltSplat()) 12400b57cec5SDimitry Andric UpdateOperand(1); // vector operand 1241fe6060f1SDimitry Andric else { 124206c3fb27SDimitry Andric // Never read, so just use poison 1243fe6060f1SDimitry Andric Value *InVal = BdvSV->getOperand(1); 124406c3fb27SDimitry Andric BaseSV->setOperand(1, PoisonValue::get(InVal->getType())); 12450b57cec5SDimitry Andric } 12460b57cec5SDimitry Andric } 1247fe6060f1SDimitry Andric } 1248fe6060f1SDimitry Andric 1249fe6060f1SDimitry Andric #ifndef NDEBUG 1250fe6060f1SDimitry Andric VerifyStates(); 1251fe6060f1SDimitry Andric #endif 12520b57cec5SDimitry Andric 12535f757f3fSDimitry Andric // get the data layout to compare the sizes of base/derived pointer values 12545f757f3fSDimitry Andric [[maybe_unused]] auto &DL = 1255*0fca6ea1SDimitry Andric cast<llvm::Instruction>(Def)->getDataLayout(); 12560b57cec5SDimitry Andric // Cache all of our results so we can cheaply reuse them 12570b57cec5SDimitry Andric // NOTE: This is actually two caches: one of the base defining value 12580b57cec5SDimitry Andric // relation and one of the base pointer relation! FIXME 12590b57cec5SDimitry Andric for (auto Pair : States) { 12600b57cec5SDimitry Andric auto *BDV = Pair.first; 12610b57cec5SDimitry Andric Value *Base = Pair.second.getBaseValue(); 12620b57cec5SDimitry Andric assert(BDV && Base); 12635f757f3fSDimitry Andric // Whenever we have a derived ptr(s), their base 12645f757f3fSDimitry Andric // ptr(s) must be of the same size, not necessarily the same type 12655f757f3fSDimitry Andric assert(DL.getTypeAllocSize(BDV->getType()) == 12665f757f3fSDimitry Andric DL.getTypeAllocSize(Base->getType()) && 12675f757f3fSDimitry Andric "Derived and base values should have same size"); 12685ffd83dbSDimitry Andric // Only values that do not have known bases or those that have differing 12695ffd83dbSDimitry Andric // type (scalar versus vector) from a possible known base should be in the 12705ffd83dbSDimitry Andric // lattice. 127181ad6265SDimitry Andric assert( 127281ad6265SDimitry Andric (!isKnownBase(BDV, KnownBases) || !areBothVectorOrScalar(BDV, Base)) && 12735ffd83dbSDimitry Andric "why did it get added?"); 12740b57cec5SDimitry Andric 12750b57cec5SDimitry Andric LLVM_DEBUG( 12760b57cec5SDimitry Andric dbgs() << "Updating base value cache" 12770b57cec5SDimitry Andric << " for: " << BDV->getName() << " from: " 12780b57cec5SDimitry Andric << (Cache.count(BDV) ? Cache[BDV]->getName().str() : "none") 12790b57cec5SDimitry Andric << " to: " << Base->getName() << "\n"); 12800b57cec5SDimitry Andric 12810b57cec5SDimitry Andric Cache[BDV] = Base; 12820b57cec5SDimitry Andric } 12830b57cec5SDimitry Andric assert(Cache.count(Def)); 12840b57cec5SDimitry Andric return Cache[Def]; 12850b57cec5SDimitry Andric } 12860b57cec5SDimitry Andric 12870b57cec5SDimitry Andric // For a set of live pointers (base and/or derived), identify the base 12880b57cec5SDimitry Andric // pointer of the object which they are derived from. This routine will 12890b57cec5SDimitry Andric // mutate the IR graph as needed to make the 'base' pointer live at the 12900b57cec5SDimitry Andric // definition site of 'derived'. This ensures that any use of 'derived' can 12910b57cec5SDimitry Andric // also use 'base'. This may involve the insertion of a number of 12920b57cec5SDimitry Andric // additional PHI nodes. 12930b57cec5SDimitry Andric // 12940b57cec5SDimitry Andric // preconditions: live is a set of pointer type Values 12950b57cec5SDimitry Andric // 12960b57cec5SDimitry Andric // side effects: may insert PHI nodes into the existing CFG, will preserve 12970b57cec5SDimitry Andric // CFG, will not remove or mutate any existing nodes 12980b57cec5SDimitry Andric // 12990b57cec5SDimitry Andric // post condition: PointerToBase contains one (derived, base) pair for every 13000b57cec5SDimitry Andric // pointer in live. Note that derived can be equal to base if the original 13010b57cec5SDimitry Andric // pointer was a base pointer. 13021fd87a68SDimitry Andric static void findBasePointers(const StatepointLiveSetTy &live, 13031fd87a68SDimitry Andric PointerToBaseTy &PointerToBase, DominatorTree *DT, 130481ad6265SDimitry Andric DefiningValueMapTy &DVCache, 130581ad6265SDimitry Andric IsKnownBaseMapTy &KnownBases) { 13060b57cec5SDimitry Andric for (Value *ptr : live) { 130781ad6265SDimitry Andric Value *base = findBasePointer(ptr, DVCache, KnownBases); 13080b57cec5SDimitry Andric assert(base && "failed to find base pointer"); 13090b57cec5SDimitry Andric PointerToBase[ptr] = base; 13100b57cec5SDimitry Andric assert((!isa<Instruction>(base) || !isa<Instruction>(ptr) || 13110b57cec5SDimitry Andric DT->dominates(cast<Instruction>(base)->getParent(), 13120b57cec5SDimitry Andric cast<Instruction>(ptr)->getParent())) && 13130b57cec5SDimitry Andric "The base we found better dominate the derived pointer"); 13140b57cec5SDimitry Andric } 13150b57cec5SDimitry Andric } 13160b57cec5SDimitry Andric 13170b57cec5SDimitry Andric /// Find the required based pointers (and adjust the live set) for the given 13180b57cec5SDimitry Andric /// parse point. 13190b57cec5SDimitry Andric static void findBasePointers(DominatorTree &DT, DefiningValueMapTy &DVCache, 13200b57cec5SDimitry Andric CallBase *Call, 13211fd87a68SDimitry Andric PartiallyConstructedSafepointRecord &result, 132281ad6265SDimitry Andric PointerToBaseTy &PointerToBase, 132381ad6265SDimitry Andric IsKnownBaseMapTy &KnownBases) { 1324fe6060f1SDimitry Andric StatepointLiveSetTy PotentiallyDerivedPointers = result.LiveSet; 1325fe6060f1SDimitry Andric // We assume that all pointers passed to deopt are base pointers; as an 1326*0fca6ea1SDimitry Andric // optimization, we can use this to avoid separately materializing the base 1327fe6060f1SDimitry Andric // pointer graph. This is only relevant since we're very conservative about 1328fe6060f1SDimitry Andric // generating new conflict nodes during base pointer insertion. If we were 1329fe6060f1SDimitry Andric // smarter there, this would be irrelevant. 1330fe6060f1SDimitry Andric if (auto Opt = Call->getOperandBundle(LLVMContext::OB_deopt)) 1331fe6060f1SDimitry Andric for (Value *V : Opt->Inputs) { 1332fe6060f1SDimitry Andric if (!PotentiallyDerivedPointers.count(V)) 1333fe6060f1SDimitry Andric continue; 1334fe6060f1SDimitry Andric PotentiallyDerivedPointers.remove(V); 1335fe6060f1SDimitry Andric PointerToBase[V] = V; 1336fe6060f1SDimitry Andric } 133781ad6265SDimitry Andric findBasePointers(PotentiallyDerivedPointers, PointerToBase, &DT, DVCache, 133881ad6265SDimitry Andric KnownBases); 13390b57cec5SDimitry Andric } 13400b57cec5SDimitry Andric 13410b57cec5SDimitry Andric /// Given an updated version of the dataflow liveness results, update the 13420b57cec5SDimitry Andric /// liveset and base pointer maps for the call site CS. 13430b57cec5SDimitry Andric static void recomputeLiveInValues(GCPtrLivenessData &RevisedLivenessData, 13440b57cec5SDimitry Andric CallBase *Call, 13451fd87a68SDimitry Andric PartiallyConstructedSafepointRecord &result, 134606c3fb27SDimitry Andric PointerToBaseTy &PointerToBase, 134706c3fb27SDimitry Andric GCStrategy *GC); 13480b57cec5SDimitry Andric 13490b57cec5SDimitry Andric static void recomputeLiveInValues( 13500b57cec5SDimitry Andric Function &F, DominatorTree &DT, ArrayRef<CallBase *> toUpdate, 13511fd87a68SDimitry Andric MutableArrayRef<struct PartiallyConstructedSafepointRecord> records, 135206c3fb27SDimitry Andric PointerToBaseTy &PointerToBase, GCStrategy *GC) { 13530b57cec5SDimitry Andric // TODO-PERF: reuse the original liveness, then simply run the dataflow 13540b57cec5SDimitry Andric // again. The old values are still live and will help it stabilize quickly. 13550b57cec5SDimitry Andric GCPtrLivenessData RevisedLivenessData; 135606c3fb27SDimitry Andric computeLiveInValues(DT, F, RevisedLivenessData, GC); 13570b57cec5SDimitry Andric for (size_t i = 0; i < records.size(); i++) { 13580b57cec5SDimitry Andric struct PartiallyConstructedSafepointRecord &info = records[i]; 135906c3fb27SDimitry Andric recomputeLiveInValues(RevisedLivenessData, toUpdate[i], info, PointerToBase, 136006c3fb27SDimitry Andric GC); 13610b57cec5SDimitry Andric } 13620b57cec5SDimitry Andric } 13630b57cec5SDimitry Andric 1364bdd1243dSDimitry Andric // Utility function which clones all instructions from "ChainToBase" 1365bdd1243dSDimitry Andric // and inserts them before "InsertBefore". Returns rematerialized value 1366bdd1243dSDimitry Andric // which should be used after statepoint. 1367bdd1243dSDimitry Andric static Instruction *rematerializeChain(ArrayRef<Instruction *> ChainToBase, 1368bdd1243dSDimitry Andric Instruction *InsertBefore, 1369bdd1243dSDimitry Andric Value *RootOfChain, 1370bdd1243dSDimitry Andric Value *AlternateLiveBase) { 1371bdd1243dSDimitry Andric Instruction *LastClonedValue = nullptr; 1372bdd1243dSDimitry Andric Instruction *LastValue = nullptr; 1373bdd1243dSDimitry Andric // Walk backwards to visit top-most instructions first. 1374bdd1243dSDimitry Andric for (Instruction *Instr : 1375bdd1243dSDimitry Andric make_range(ChainToBase.rbegin(), ChainToBase.rend())) { 1376bdd1243dSDimitry Andric // Only GEP's and casts are supported as we need to be careful to not 1377bdd1243dSDimitry Andric // introduce any new uses of pointers not in the liveset. 1378bdd1243dSDimitry Andric // Note that it's fine to introduce new uses of pointers which were 1379bdd1243dSDimitry Andric // otherwise not used after this statepoint. 1380bdd1243dSDimitry Andric assert(isa<GetElementPtrInst>(Instr) || isa<CastInst>(Instr)); 1381bdd1243dSDimitry Andric 1382bdd1243dSDimitry Andric Instruction *ClonedValue = Instr->clone(); 1383bdd1243dSDimitry Andric ClonedValue->insertBefore(InsertBefore); 1384bdd1243dSDimitry Andric ClonedValue->setName(Instr->getName() + ".remat"); 1385bdd1243dSDimitry Andric 1386bdd1243dSDimitry Andric // If it is not first instruction in the chain then it uses previously 1387bdd1243dSDimitry Andric // cloned value. We should update it to use cloned value. 1388bdd1243dSDimitry Andric if (LastClonedValue) { 1389bdd1243dSDimitry Andric assert(LastValue); 1390bdd1243dSDimitry Andric ClonedValue->replaceUsesOfWith(LastValue, LastClonedValue); 1391bdd1243dSDimitry Andric #ifndef NDEBUG 1392bdd1243dSDimitry Andric for (auto *OpValue : ClonedValue->operand_values()) { 1393bdd1243dSDimitry Andric // Assert that cloned instruction does not use any instructions from 1394bdd1243dSDimitry Andric // this chain other than LastClonedValue 1395bdd1243dSDimitry Andric assert(!is_contained(ChainToBase, OpValue) && 1396bdd1243dSDimitry Andric "incorrect use in rematerialization chain"); 1397bdd1243dSDimitry Andric // Assert that the cloned instruction does not use the RootOfChain 1398bdd1243dSDimitry Andric // or the AlternateLiveBase. 1399bdd1243dSDimitry Andric assert(OpValue != RootOfChain && OpValue != AlternateLiveBase); 1400bdd1243dSDimitry Andric } 1401bdd1243dSDimitry Andric #endif 1402bdd1243dSDimitry Andric } else { 1403bdd1243dSDimitry Andric // For the first instruction, replace the use of unrelocated base i.e. 1404bdd1243dSDimitry Andric // RootOfChain/OrigRootPhi, with the corresponding PHI present in the 1405bdd1243dSDimitry Andric // live set. They have been proved to be the same PHI nodes. Note 1406bdd1243dSDimitry Andric // that the *only* use of the RootOfChain in the ChainToBase list is 1407bdd1243dSDimitry Andric // the first Value in the list. 1408bdd1243dSDimitry Andric if (RootOfChain != AlternateLiveBase) 1409bdd1243dSDimitry Andric ClonedValue->replaceUsesOfWith(RootOfChain, AlternateLiveBase); 1410bdd1243dSDimitry Andric } 1411bdd1243dSDimitry Andric 1412bdd1243dSDimitry Andric LastClonedValue = ClonedValue; 1413bdd1243dSDimitry Andric LastValue = Instr; 1414bdd1243dSDimitry Andric } 1415bdd1243dSDimitry Andric assert(LastClonedValue); 1416bdd1243dSDimitry Andric return LastClonedValue; 1417bdd1243dSDimitry Andric } 1418bdd1243dSDimitry Andric 14190b57cec5SDimitry Andric // When inserting gc.relocate and gc.result calls, we need to ensure there are 14200b57cec5SDimitry Andric // no uses of the original value / return value between the gc.statepoint and 14210b57cec5SDimitry Andric // the gc.relocate / gc.result call. One case which can arise is a phi node 14220b57cec5SDimitry Andric // starting one of the successor blocks. We also need to be able to insert the 14230b57cec5SDimitry Andric // gc.relocates only on the path which goes through the statepoint. We might 14240b57cec5SDimitry Andric // need to split an edge to make this possible. 14250b57cec5SDimitry Andric static BasicBlock * 14260b57cec5SDimitry Andric normalizeForInvokeSafepoint(BasicBlock *BB, BasicBlock *InvokeParent, 14270b57cec5SDimitry Andric DominatorTree &DT) { 14280b57cec5SDimitry Andric BasicBlock *Ret = BB; 14290b57cec5SDimitry Andric if (!BB->getUniquePredecessor()) 14300b57cec5SDimitry Andric Ret = SplitBlockPredecessors(BB, InvokeParent, "", &DT); 14310b57cec5SDimitry Andric 14320b57cec5SDimitry Andric // Now that 'Ret' has unique predecessor we can safely remove all phi nodes 14330b57cec5SDimitry Andric // from it 14340b57cec5SDimitry Andric FoldSingleEntryPHINodes(Ret); 14350b57cec5SDimitry Andric assert(!isa<PHINode>(Ret->begin()) && 14360b57cec5SDimitry Andric "All PHI nodes should have been removed!"); 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric // At this point, we can safely insert a gc.relocate or gc.result as the first 14390b57cec5SDimitry Andric // instruction in Ret if needed. 14400b57cec5SDimitry Andric return Ret; 14410b57cec5SDimitry Andric } 14420b57cec5SDimitry Andric 1443fe6060f1SDimitry Andric // List of all function attributes which must be stripped when lowering from 1444fe6060f1SDimitry Andric // abstract machine model to physical machine model. Essentially, these are 1445fe6060f1SDimitry Andric // all the effects a safepoint might have which we ignored in the abstract 1446fe6060f1SDimitry Andric // machine model for purposes of optimization. We have to strip these on 1447fe6060f1SDimitry Andric // both function declarations and call sites. 1448fe6060f1SDimitry Andric static constexpr Attribute::AttrKind FnAttrsToStrip[] = 1449bdd1243dSDimitry Andric {Attribute::Memory, Attribute::NoSync, Attribute::NoFree}; 1450fe6060f1SDimitry Andric 14510b57cec5SDimitry Andric // Create new attribute set containing only attributes which can be transferred 14525f757f3fSDimitry Andric // from the original call to the safepoint. 14535f757f3fSDimitry Andric static AttributeList legalizeCallAttributes(CallBase *Call, bool IsMemIntrinsic, 145481ad6265SDimitry Andric AttributeList StatepointAL) { 14555f757f3fSDimitry Andric AttributeList OrigAL = Call->getAttributes(); 145681ad6265SDimitry Andric if (OrigAL.isEmpty()) 145781ad6265SDimitry Andric return StatepointAL; 14580b57cec5SDimitry Andric 14590b57cec5SDimitry Andric // Remove the readonly, readnone, and statepoint function attributes. 14605f757f3fSDimitry Andric LLVMContext &Ctx = Call->getContext(); 146181ad6265SDimitry Andric AttrBuilder FnAttrs(Ctx, OrigAL.getFnAttrs()); 1462fe6060f1SDimitry Andric for (auto Attr : FnAttrsToStrip) 1463fe6060f1SDimitry Andric FnAttrs.removeAttribute(Attr); 1464fe6060f1SDimitry Andric 146581ad6265SDimitry Andric for (Attribute A : OrigAL.getFnAttrs()) { 14660b57cec5SDimitry Andric if (isStatepointDirectiveAttr(A)) 146704eeddc0SDimitry Andric FnAttrs.removeAttribute(A); 14680b57cec5SDimitry Andric } 14690b57cec5SDimitry Andric 14705f757f3fSDimitry Andric StatepointAL = StatepointAL.addFnAttributes(Ctx, FnAttrs); 14715f757f3fSDimitry Andric 14725f757f3fSDimitry Andric // The memory intrinsics do not have a 1:1 correspondence of the original 14735f757f3fSDimitry Andric // call arguments to the produced statepoint. Do not transfer the argument 14745f757f3fSDimitry Andric // attributes to avoid putting them on incorrect arguments. 14755f757f3fSDimitry Andric if (IsMemIntrinsic) 14765f757f3fSDimitry Andric return StatepointAL; 14775f757f3fSDimitry Andric 14785f757f3fSDimitry Andric // Attach the argument attributes from the original call at the corresponding 14795f757f3fSDimitry Andric // arguments in the statepoint. Note that any argument attributes that are 14805f757f3fSDimitry Andric // invalid after lowering are stripped in stripNonValidDataFromBody. 14815f757f3fSDimitry Andric for (unsigned I : llvm::seq(Call->arg_size())) 14825f757f3fSDimitry Andric StatepointAL = StatepointAL.addParamAttributes( 14835f757f3fSDimitry Andric Ctx, GCStatepointInst::CallArgsBeginPos + I, 14845f757f3fSDimitry Andric AttrBuilder(Ctx, OrigAL.getParamAttrs(I))); 14855f757f3fSDimitry Andric 14865f757f3fSDimitry Andric // Return attributes are later attached to the gc.result intrinsic. 14875f757f3fSDimitry Andric return StatepointAL; 14880b57cec5SDimitry Andric } 14890b57cec5SDimitry Andric 14900b57cec5SDimitry Andric /// Helper function to place all gc relocates necessary for the given 14910b57cec5SDimitry Andric /// statepoint. 14920b57cec5SDimitry Andric /// Inputs: 14930b57cec5SDimitry Andric /// liveVariables - list of variables to be relocated. 14940b57cec5SDimitry Andric /// basePtrs - base pointers. 14950b57cec5SDimitry Andric /// statepointToken - statepoint instruction to which relocates should be 14960b57cec5SDimitry Andric /// bound. 14970b57cec5SDimitry Andric /// Builder - Llvm IR builder to be used to construct new calls. 14980b57cec5SDimitry Andric static void CreateGCRelocates(ArrayRef<Value *> LiveVariables, 14990b57cec5SDimitry Andric ArrayRef<Value *> BasePtrs, 15000b57cec5SDimitry Andric Instruction *StatepointToken, 150106c3fb27SDimitry Andric IRBuilder<> &Builder, GCStrategy *GC) { 15020b57cec5SDimitry Andric if (LiveVariables.empty()) 15030b57cec5SDimitry Andric return; 15040b57cec5SDimitry Andric 15050b57cec5SDimitry Andric auto FindIndex = [](ArrayRef<Value *> LiveVec, Value *Val) { 15060b57cec5SDimitry Andric auto ValIt = llvm::find(LiveVec, Val); 15070b57cec5SDimitry Andric assert(ValIt != LiveVec.end() && "Val not found in LiveVec!"); 15080b57cec5SDimitry Andric size_t Index = std::distance(LiveVec.begin(), ValIt); 15090b57cec5SDimitry Andric assert(Index < LiveVec.size() && "Bug in std::find?"); 15100b57cec5SDimitry Andric return Index; 15110b57cec5SDimitry Andric }; 15120b57cec5SDimitry Andric Module *M = StatepointToken->getModule(); 15130b57cec5SDimitry Andric 15140b57cec5SDimitry Andric // All gc_relocate are generated as i8 addrspace(1)* (or a vector type whose 15150b57cec5SDimitry Andric // element type is i8 addrspace(1)*). We originally generated unique 15160b57cec5SDimitry Andric // declarations for each pointer type, but this proved problematic because 15170b57cec5SDimitry Andric // the intrinsic mangling code is incomplete and fragile. Since we're moving 15180b57cec5SDimitry Andric // towards a single unified pointer type anyways, we can just cast everything 15190b57cec5SDimitry Andric // to an i8* of the right address space. A bitcast is added later to convert 15200b57cec5SDimitry Andric // gc_relocate to the actual value's type. 15210b57cec5SDimitry Andric auto getGCRelocateDecl = [&](Type *Ty) { 152206c3fb27SDimitry Andric assert(isHandledGCPointerType(Ty, GC)); 15230b57cec5SDimitry Andric auto AS = Ty->getScalarType()->getPointerAddressSpace(); 15245f757f3fSDimitry Andric Type *NewTy = PointerType::get(M->getContext(), AS); 15250b57cec5SDimitry Andric if (auto *VT = dyn_cast<VectorType>(Ty)) 15265ffd83dbSDimitry Andric NewTy = FixedVectorType::get(NewTy, 15275ffd83dbSDimitry Andric cast<FixedVectorType>(VT)->getNumElements()); 15280b57cec5SDimitry Andric return Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_relocate, 15290b57cec5SDimitry Andric {NewTy}); 15300b57cec5SDimitry Andric }; 15310b57cec5SDimitry Andric 15320b57cec5SDimitry Andric // Lazily populated map from input types to the canonicalized form mentioned 15330b57cec5SDimitry Andric // in the comment above. This should probably be cached somewhere more 15340b57cec5SDimitry Andric // broadly. 15350b57cec5SDimitry Andric DenseMap<Type *, Function *> TypeToDeclMap; 15360b57cec5SDimitry Andric 15370b57cec5SDimitry Andric for (unsigned i = 0; i < LiveVariables.size(); i++) { 15380b57cec5SDimitry Andric // Generate the gc.relocate call and save the result 15395ffd83dbSDimitry Andric Value *BaseIdx = Builder.getInt32(FindIndex(LiveVariables, BasePtrs[i])); 15405ffd83dbSDimitry Andric Value *LiveIdx = Builder.getInt32(i); 15410b57cec5SDimitry Andric 15420b57cec5SDimitry Andric Type *Ty = LiveVariables[i]->getType(); 15430b57cec5SDimitry Andric if (!TypeToDeclMap.count(Ty)) 15440b57cec5SDimitry Andric TypeToDeclMap[Ty] = getGCRelocateDecl(Ty); 15450b57cec5SDimitry Andric Function *GCRelocateDecl = TypeToDeclMap[Ty]; 15460b57cec5SDimitry Andric 15470b57cec5SDimitry Andric // only specify a debug name if we can give a useful one 15480b57cec5SDimitry Andric CallInst *Reloc = Builder.CreateCall( 15490b57cec5SDimitry Andric GCRelocateDecl, {StatepointToken, BaseIdx, LiveIdx}, 15500b57cec5SDimitry Andric suffixed_name_or(LiveVariables[i], ".relocated", "")); 15510b57cec5SDimitry Andric // Trick CodeGen into thinking there are lots of free registers at this 15520b57cec5SDimitry Andric // fake call. 15530b57cec5SDimitry Andric Reloc->setCallingConv(CallingConv::Cold); 15540b57cec5SDimitry Andric } 15550b57cec5SDimitry Andric } 15560b57cec5SDimitry Andric 15570b57cec5SDimitry Andric namespace { 15580b57cec5SDimitry Andric 15590b57cec5SDimitry Andric /// This struct is used to defer RAUWs and `eraseFromParent` s. Using this 15600b57cec5SDimitry Andric /// avoids having to worry about keeping around dangling pointers to Values. 15610b57cec5SDimitry Andric class DeferredReplacement { 15620b57cec5SDimitry Andric AssertingVH<Instruction> Old; 15630b57cec5SDimitry Andric AssertingVH<Instruction> New; 15640b57cec5SDimitry Andric bool IsDeoptimize = false; 15650b57cec5SDimitry Andric 15660b57cec5SDimitry Andric DeferredReplacement() = default; 15670b57cec5SDimitry Andric 15680b57cec5SDimitry Andric public: 15690b57cec5SDimitry Andric static DeferredReplacement createRAUW(Instruction *Old, Instruction *New) { 15700b57cec5SDimitry Andric assert(Old != New && Old && New && 15710b57cec5SDimitry Andric "Cannot RAUW equal values or to / from null!"); 15720b57cec5SDimitry Andric 15730b57cec5SDimitry Andric DeferredReplacement D; 15740b57cec5SDimitry Andric D.Old = Old; 15750b57cec5SDimitry Andric D.New = New; 15760b57cec5SDimitry Andric return D; 15770b57cec5SDimitry Andric } 15780b57cec5SDimitry Andric 15790b57cec5SDimitry Andric static DeferredReplacement createDelete(Instruction *ToErase) { 15800b57cec5SDimitry Andric DeferredReplacement D; 15810b57cec5SDimitry Andric D.Old = ToErase; 15820b57cec5SDimitry Andric return D; 15830b57cec5SDimitry Andric } 15840b57cec5SDimitry Andric 15850b57cec5SDimitry Andric static DeferredReplacement createDeoptimizeReplacement(Instruction *Old) { 15860b57cec5SDimitry Andric #ifndef NDEBUG 15870b57cec5SDimitry Andric auto *F = cast<CallInst>(Old)->getCalledFunction(); 15880b57cec5SDimitry Andric assert(F && F->getIntrinsicID() == Intrinsic::experimental_deoptimize && 15890b57cec5SDimitry Andric "Only way to construct a deoptimize deferred replacement"); 15900b57cec5SDimitry Andric #endif 15910b57cec5SDimitry Andric DeferredReplacement D; 15920b57cec5SDimitry Andric D.Old = Old; 15930b57cec5SDimitry Andric D.IsDeoptimize = true; 15940b57cec5SDimitry Andric return D; 15950b57cec5SDimitry Andric } 15960b57cec5SDimitry Andric 15970b57cec5SDimitry Andric /// Does the task represented by this instance. 15980b57cec5SDimitry Andric void doReplacement() { 15990b57cec5SDimitry Andric Instruction *OldI = Old; 16000b57cec5SDimitry Andric Instruction *NewI = New; 16010b57cec5SDimitry Andric 16020b57cec5SDimitry Andric assert(OldI != NewI && "Disallowed at construction?!"); 16030b57cec5SDimitry Andric assert((!IsDeoptimize || !New) && 16040b57cec5SDimitry Andric "Deoptimize intrinsics are not replaced!"); 16050b57cec5SDimitry Andric 16060b57cec5SDimitry Andric Old = nullptr; 16070b57cec5SDimitry Andric New = nullptr; 16080b57cec5SDimitry Andric 16090b57cec5SDimitry Andric if (NewI) 16100b57cec5SDimitry Andric OldI->replaceAllUsesWith(NewI); 16110b57cec5SDimitry Andric 16120b57cec5SDimitry Andric if (IsDeoptimize) { 16130b57cec5SDimitry Andric // Note: we've inserted instructions, so the call to llvm.deoptimize may 16140b57cec5SDimitry Andric // not necessarily be followed by the matching return. 16150b57cec5SDimitry Andric auto *RI = cast<ReturnInst>(OldI->getParent()->getTerminator()); 1616*0fca6ea1SDimitry Andric new UnreachableInst(RI->getContext(), RI->getIterator()); 16170b57cec5SDimitry Andric RI->eraseFromParent(); 16180b57cec5SDimitry Andric } 16190b57cec5SDimitry Andric 16200b57cec5SDimitry Andric OldI->eraseFromParent(); 16210b57cec5SDimitry Andric } 16220b57cec5SDimitry Andric }; 16230b57cec5SDimitry Andric 16240b57cec5SDimitry Andric } // end anonymous namespace 16250b57cec5SDimitry Andric 16260b57cec5SDimitry Andric static StringRef getDeoptLowering(CallBase *Call) { 16270b57cec5SDimitry Andric const char *DeoptLowering = "deopt-lowering"; 16280b57cec5SDimitry Andric if (Call->hasFnAttr(DeoptLowering)) { 16290b57cec5SDimitry Andric // FIXME: Calls have a *really* confusing interface around attributes 16300b57cec5SDimitry Andric // with values. 16310b57cec5SDimitry Andric const AttributeList &CSAS = Call->getAttributes(); 1632349cc55cSDimitry Andric if (CSAS.hasFnAttr(DeoptLowering)) 1633349cc55cSDimitry Andric return CSAS.getFnAttr(DeoptLowering).getValueAsString(); 16340b57cec5SDimitry Andric Function *F = Call->getCalledFunction(); 16350b57cec5SDimitry Andric assert(F && F->hasFnAttribute(DeoptLowering)); 16360b57cec5SDimitry Andric return F->getFnAttribute(DeoptLowering).getValueAsString(); 16370b57cec5SDimitry Andric } 16380b57cec5SDimitry Andric return "live-through"; 16390b57cec5SDimitry Andric } 16400b57cec5SDimitry Andric 16410b57cec5SDimitry Andric static void 16420b57cec5SDimitry Andric makeStatepointExplicitImpl(CallBase *Call, /* to replace */ 16430b57cec5SDimitry Andric const SmallVectorImpl<Value *> &BasePtrs, 16440b57cec5SDimitry Andric const SmallVectorImpl<Value *> &LiveVariables, 16450b57cec5SDimitry Andric PartiallyConstructedSafepointRecord &Result, 16461fd87a68SDimitry Andric std::vector<DeferredReplacement> &Replacements, 164706c3fb27SDimitry Andric const PointerToBaseTy &PointerToBase, 164806c3fb27SDimitry Andric GCStrategy *GC) { 16490b57cec5SDimitry Andric assert(BasePtrs.size() == LiveVariables.size()); 16500b57cec5SDimitry Andric 16510b57cec5SDimitry Andric // Then go ahead and use the builder do actually do the inserts. We insert 16520b57cec5SDimitry Andric // immediately before the previous instruction under the assumption that all 16530b57cec5SDimitry Andric // arguments will be available here. We can't insert afterwards since we may 16540b57cec5SDimitry Andric // be replacing a terminator. 16550b57cec5SDimitry Andric IRBuilder<> Builder(Call); 16560b57cec5SDimitry Andric 16570b57cec5SDimitry Andric ArrayRef<Value *> GCArgs(LiveVariables); 16580b57cec5SDimitry Andric uint64_t StatepointID = StatepointDirectives::DefaultStatepointID; 16590b57cec5SDimitry Andric uint32_t NumPatchBytes = 0; 16600b57cec5SDimitry Andric uint32_t Flags = uint32_t(StatepointFlags::None); 16610b57cec5SDimitry Andric 1662e8d8bef9SDimitry Andric SmallVector<Value *, 8> CallArgs(Call->args()); 1663bdd1243dSDimitry Andric std::optional<ArrayRef<Use>> DeoptArgs; 16645ffd83dbSDimitry Andric if (auto Bundle = Call->getOperandBundle(LLVMContext::OB_deopt)) 16655ffd83dbSDimitry Andric DeoptArgs = Bundle->Inputs; 1666bdd1243dSDimitry Andric std::optional<ArrayRef<Use>> TransitionArgs; 16675ffd83dbSDimitry Andric if (auto Bundle = Call->getOperandBundle(LLVMContext::OB_gc_transition)) { 16685ffd83dbSDimitry Andric TransitionArgs = Bundle->Inputs; 16695ffd83dbSDimitry Andric // TODO: This flag no longer serves a purpose and can be removed later 16700b57cec5SDimitry Andric Flags |= uint32_t(StatepointFlags::GCTransition); 16710b57cec5SDimitry Andric } 16720b57cec5SDimitry Andric 16730b57cec5SDimitry Andric // Instead of lowering calls to @llvm.experimental.deoptimize as normal calls 16740b57cec5SDimitry Andric // with a return value, we lower then as never returning calls to 16750b57cec5SDimitry Andric // __llvm_deoptimize that are followed by unreachable to get better codegen. 16760b57cec5SDimitry Andric bool IsDeoptimize = false; 16775f757f3fSDimitry Andric bool IsMemIntrinsic = false; 16780b57cec5SDimitry Andric 16790b57cec5SDimitry Andric StatepointDirectives SD = 16800b57cec5SDimitry Andric parseStatepointDirectivesFromAttrs(Call->getAttributes()); 16810b57cec5SDimitry Andric if (SD.NumPatchBytes) 16820b57cec5SDimitry Andric NumPatchBytes = *SD.NumPatchBytes; 16830b57cec5SDimitry Andric if (SD.StatepointID) 16840b57cec5SDimitry Andric StatepointID = *SD.StatepointID; 16850b57cec5SDimitry Andric 16860b57cec5SDimitry Andric // Pass through the requested lowering if any. The default is live-through. 16870b57cec5SDimitry Andric StringRef DeoptLowering = getDeoptLowering(Call); 1688*0fca6ea1SDimitry Andric if (DeoptLowering == "live-in") 16890b57cec5SDimitry Andric Flags |= uint32_t(StatepointFlags::DeoptLiveIn); 16900b57cec5SDimitry Andric else { 1691*0fca6ea1SDimitry Andric assert(DeoptLowering == "live-through" && "Unsupported value!"); 16920b57cec5SDimitry Andric } 16930b57cec5SDimitry Andric 169481ad6265SDimitry Andric FunctionCallee CallTarget(Call->getFunctionType(), Call->getCalledOperand()); 169581ad6265SDimitry Andric if (Function *F = dyn_cast<Function>(CallTarget.getCallee())) { 1696e8d8bef9SDimitry Andric auto IID = F->getIntrinsicID(); 1697e8d8bef9SDimitry Andric if (IID == Intrinsic::experimental_deoptimize) { 16980b57cec5SDimitry Andric // Calls to llvm.experimental.deoptimize are lowered to calls to the 16990b57cec5SDimitry Andric // __llvm_deoptimize symbol. We want to resolve this now, since the 17000b57cec5SDimitry Andric // verifier does not allow taking the address of an intrinsic function. 17010b57cec5SDimitry Andric 17020b57cec5SDimitry Andric SmallVector<Type *, 8> DomainTy; 17030b57cec5SDimitry Andric for (Value *Arg : CallArgs) 17040b57cec5SDimitry Andric DomainTy.push_back(Arg->getType()); 17050b57cec5SDimitry Andric auto *FTy = FunctionType::get(Type::getVoidTy(F->getContext()), DomainTy, 17060b57cec5SDimitry Andric /* isVarArg = */ false); 17070b57cec5SDimitry Andric 17080b57cec5SDimitry Andric // Note: CallTarget can be a bitcast instruction of a symbol if there are 17090b57cec5SDimitry Andric // calls to @llvm.experimental.deoptimize with different argument types in 17100b57cec5SDimitry Andric // the same module. This is fine -- we assume the frontend knew what it 17110b57cec5SDimitry Andric // was doing when generating this kind of IR. 17120b57cec5SDimitry Andric CallTarget = F->getParent() 171381ad6265SDimitry Andric ->getOrInsertFunction("__llvm_deoptimize", FTy); 17140b57cec5SDimitry Andric 17150b57cec5SDimitry Andric IsDeoptimize = true; 1716e8d8bef9SDimitry Andric } else if (IID == Intrinsic::memcpy_element_unordered_atomic || 1717e8d8bef9SDimitry Andric IID == Intrinsic::memmove_element_unordered_atomic) { 17185f757f3fSDimitry Andric IsMemIntrinsic = true; 17195f757f3fSDimitry Andric 1720e8d8bef9SDimitry Andric // Unordered atomic memcpy and memmove intrinsics which are not explicitly 1721e8d8bef9SDimitry Andric // marked as "gc-leaf-function" should be lowered in a GC parseable way. 1722e8d8bef9SDimitry Andric // Specifically, these calls should be lowered to the 1723e8d8bef9SDimitry Andric // __llvm_{memcpy|memmove}_element_unordered_atomic_safepoint symbols. 1724e8d8bef9SDimitry Andric // Similarly to __llvm_deoptimize we want to resolve this now, since the 1725e8d8bef9SDimitry Andric // verifier does not allow taking the address of an intrinsic function. 1726e8d8bef9SDimitry Andric // 1727e8d8bef9SDimitry Andric // Moreover we need to shuffle the arguments for the call in order to 1728e8d8bef9SDimitry Andric // accommodate GC. The underlying source and destination objects might be 1729e8d8bef9SDimitry Andric // relocated during copy operation should the GC occur. To relocate the 1730e8d8bef9SDimitry Andric // derived source and destination pointers the implementation of the 1731e8d8bef9SDimitry Andric // intrinsic should know the corresponding base pointers. 1732e8d8bef9SDimitry Andric // 1733e8d8bef9SDimitry Andric // To make the base pointers available pass them explicitly as arguments: 1734e8d8bef9SDimitry Andric // memcpy(dest_derived, source_derived, ...) => 1735e8d8bef9SDimitry Andric // memcpy(dest_base, dest_offset, source_base, source_offset, ...) 1736e8d8bef9SDimitry Andric auto &Context = Call->getContext(); 1737*0fca6ea1SDimitry Andric auto &DL = Call->getDataLayout(); 1738e8d8bef9SDimitry Andric auto GetBaseAndOffset = [&](Value *Derived) { 1739fcaf7f86SDimitry Andric Value *Base = nullptr; 1740fcaf7f86SDimitry Andric // Optimizations in unreachable code might substitute the real pointer 1741fcaf7f86SDimitry Andric // with undef, poison or null-derived constant. Return null base for 1742fcaf7f86SDimitry Andric // them to be consistent with the handling in the main algorithm in 1743fcaf7f86SDimitry Andric // findBaseDefiningValue. 1744fcaf7f86SDimitry Andric if (isa<Constant>(Derived)) 1745fcaf7f86SDimitry Andric Base = 1746fcaf7f86SDimitry Andric ConstantPointerNull::get(cast<PointerType>(Derived->getType())); 1747fcaf7f86SDimitry Andric else { 17481fd87a68SDimitry Andric assert(PointerToBase.count(Derived)); 1749fcaf7f86SDimitry Andric Base = PointerToBase.find(Derived)->second; 1750fcaf7f86SDimitry Andric } 1751e8d8bef9SDimitry Andric unsigned AddressSpace = Derived->getType()->getPointerAddressSpace(); 1752e8d8bef9SDimitry Andric unsigned IntPtrSize = DL.getPointerSizeInBits(AddressSpace); 1753e8d8bef9SDimitry Andric Value *Base_int = Builder.CreatePtrToInt( 1754e8d8bef9SDimitry Andric Base, Type::getIntNTy(Context, IntPtrSize)); 1755e8d8bef9SDimitry Andric Value *Derived_int = Builder.CreatePtrToInt( 1756e8d8bef9SDimitry Andric Derived, Type::getIntNTy(Context, IntPtrSize)); 1757e8d8bef9SDimitry Andric return std::make_pair(Base, Builder.CreateSub(Derived_int, Base_int)); 1758e8d8bef9SDimitry Andric }; 1759e8d8bef9SDimitry Andric 1760e8d8bef9SDimitry Andric auto *Dest = CallArgs[0]; 1761e8d8bef9SDimitry Andric Value *DestBase, *DestOffset; 1762e8d8bef9SDimitry Andric std::tie(DestBase, DestOffset) = GetBaseAndOffset(Dest); 1763e8d8bef9SDimitry Andric 1764e8d8bef9SDimitry Andric auto *Source = CallArgs[1]; 1765e8d8bef9SDimitry Andric Value *SourceBase, *SourceOffset; 1766e8d8bef9SDimitry Andric std::tie(SourceBase, SourceOffset) = GetBaseAndOffset(Source); 1767e8d8bef9SDimitry Andric 1768e8d8bef9SDimitry Andric auto *LengthInBytes = CallArgs[2]; 1769e8d8bef9SDimitry Andric auto *ElementSizeCI = cast<ConstantInt>(CallArgs[3]); 1770e8d8bef9SDimitry Andric 1771e8d8bef9SDimitry Andric CallArgs.clear(); 1772e8d8bef9SDimitry Andric CallArgs.push_back(DestBase); 1773e8d8bef9SDimitry Andric CallArgs.push_back(DestOffset); 1774e8d8bef9SDimitry Andric CallArgs.push_back(SourceBase); 1775e8d8bef9SDimitry Andric CallArgs.push_back(SourceOffset); 1776e8d8bef9SDimitry Andric CallArgs.push_back(LengthInBytes); 1777e8d8bef9SDimitry Andric 1778e8d8bef9SDimitry Andric SmallVector<Type *, 8> DomainTy; 1779e8d8bef9SDimitry Andric for (Value *Arg : CallArgs) 1780e8d8bef9SDimitry Andric DomainTy.push_back(Arg->getType()); 1781e8d8bef9SDimitry Andric auto *FTy = FunctionType::get(Type::getVoidTy(F->getContext()), DomainTy, 1782e8d8bef9SDimitry Andric /* isVarArg = */ false); 1783e8d8bef9SDimitry Andric 1784e8d8bef9SDimitry Andric auto GetFunctionName = [](Intrinsic::ID IID, ConstantInt *ElementSizeCI) { 1785e8d8bef9SDimitry Andric uint64_t ElementSize = ElementSizeCI->getZExtValue(); 1786e8d8bef9SDimitry Andric if (IID == Intrinsic::memcpy_element_unordered_atomic) { 1787e8d8bef9SDimitry Andric switch (ElementSize) { 1788e8d8bef9SDimitry Andric case 1: 1789e8d8bef9SDimitry Andric return "__llvm_memcpy_element_unordered_atomic_safepoint_1"; 1790e8d8bef9SDimitry Andric case 2: 1791e8d8bef9SDimitry Andric return "__llvm_memcpy_element_unordered_atomic_safepoint_2"; 1792e8d8bef9SDimitry Andric case 4: 1793e8d8bef9SDimitry Andric return "__llvm_memcpy_element_unordered_atomic_safepoint_4"; 1794e8d8bef9SDimitry Andric case 8: 1795e8d8bef9SDimitry Andric return "__llvm_memcpy_element_unordered_atomic_safepoint_8"; 1796e8d8bef9SDimitry Andric case 16: 1797e8d8bef9SDimitry Andric return "__llvm_memcpy_element_unordered_atomic_safepoint_16"; 1798e8d8bef9SDimitry Andric default: 1799e8d8bef9SDimitry Andric llvm_unreachable("unexpected element size!"); 1800e8d8bef9SDimitry Andric } 1801e8d8bef9SDimitry Andric } 1802e8d8bef9SDimitry Andric assert(IID == Intrinsic::memmove_element_unordered_atomic); 1803e8d8bef9SDimitry Andric switch (ElementSize) { 1804e8d8bef9SDimitry Andric case 1: 1805e8d8bef9SDimitry Andric return "__llvm_memmove_element_unordered_atomic_safepoint_1"; 1806e8d8bef9SDimitry Andric case 2: 1807e8d8bef9SDimitry Andric return "__llvm_memmove_element_unordered_atomic_safepoint_2"; 1808e8d8bef9SDimitry Andric case 4: 1809e8d8bef9SDimitry Andric return "__llvm_memmove_element_unordered_atomic_safepoint_4"; 1810e8d8bef9SDimitry Andric case 8: 1811e8d8bef9SDimitry Andric return "__llvm_memmove_element_unordered_atomic_safepoint_8"; 1812e8d8bef9SDimitry Andric case 16: 1813e8d8bef9SDimitry Andric return "__llvm_memmove_element_unordered_atomic_safepoint_16"; 1814e8d8bef9SDimitry Andric default: 1815e8d8bef9SDimitry Andric llvm_unreachable("unexpected element size!"); 1816e8d8bef9SDimitry Andric } 1817e8d8bef9SDimitry Andric }; 1818e8d8bef9SDimitry Andric 1819e8d8bef9SDimitry Andric CallTarget = 1820e8d8bef9SDimitry Andric F->getParent() 182181ad6265SDimitry Andric ->getOrInsertFunction(GetFunctionName(IID, ElementSizeCI), FTy); 18220b57cec5SDimitry Andric } 18230b57cec5SDimitry Andric } 18240b57cec5SDimitry Andric 18250b57cec5SDimitry Andric // Create the statepoint given all the arguments 18265ffd83dbSDimitry Andric GCStatepointInst *Token = nullptr; 18270b57cec5SDimitry Andric if (auto *CI = dyn_cast<CallInst>(Call)) { 18280b57cec5SDimitry Andric CallInst *SPCall = Builder.CreateGCStatepointCall( 18290b57cec5SDimitry Andric StatepointID, NumPatchBytes, CallTarget, Flags, CallArgs, 18300b57cec5SDimitry Andric TransitionArgs, DeoptArgs, GCArgs, "safepoint_token"); 18310b57cec5SDimitry Andric 18320b57cec5SDimitry Andric SPCall->setTailCallKind(CI->getTailCallKind()); 18330b57cec5SDimitry Andric SPCall->setCallingConv(CI->getCallingConv()); 18340b57cec5SDimitry Andric 18355f757f3fSDimitry Andric // Set up function attrs directly on statepoint and return attrs later for 18360b57cec5SDimitry Andric // gc_result intrinsic. 18375f757f3fSDimitry Andric SPCall->setAttributes( 18385f757f3fSDimitry Andric legalizeCallAttributes(CI, IsMemIntrinsic, SPCall->getAttributes())); 18390b57cec5SDimitry Andric 18405ffd83dbSDimitry Andric Token = cast<GCStatepointInst>(SPCall); 18410b57cec5SDimitry Andric 18420b57cec5SDimitry Andric // Put the following gc_result and gc_relocate calls immediately after the 18430b57cec5SDimitry Andric // the old call (which we're about to delete) 18440b57cec5SDimitry Andric assert(CI->getNextNode() && "Not a terminator, must have next!"); 18450b57cec5SDimitry Andric Builder.SetInsertPoint(CI->getNextNode()); 18460b57cec5SDimitry Andric Builder.SetCurrentDebugLocation(CI->getNextNode()->getDebugLoc()); 18470b57cec5SDimitry Andric } else { 18480b57cec5SDimitry Andric auto *II = cast<InvokeInst>(Call); 18490b57cec5SDimitry Andric 18500b57cec5SDimitry Andric // Insert the new invoke into the old block. We'll remove the old one in a 18510b57cec5SDimitry Andric // moment at which point this will become the new terminator for the 18520b57cec5SDimitry Andric // original block. 18530b57cec5SDimitry Andric InvokeInst *SPInvoke = Builder.CreateGCStatepointInvoke( 18540b57cec5SDimitry Andric StatepointID, NumPatchBytes, CallTarget, II->getNormalDest(), 18550b57cec5SDimitry Andric II->getUnwindDest(), Flags, CallArgs, TransitionArgs, DeoptArgs, GCArgs, 18560b57cec5SDimitry Andric "statepoint_token"); 18570b57cec5SDimitry Andric 18580b57cec5SDimitry Andric SPInvoke->setCallingConv(II->getCallingConv()); 18590b57cec5SDimitry Andric 18605f757f3fSDimitry Andric // Set up function attrs directly on statepoint and return attrs later for 18610b57cec5SDimitry Andric // gc_result intrinsic. 18625f757f3fSDimitry Andric SPInvoke->setAttributes( 18635f757f3fSDimitry Andric legalizeCallAttributes(II, IsMemIntrinsic, SPInvoke->getAttributes())); 18640b57cec5SDimitry Andric 18655ffd83dbSDimitry Andric Token = cast<GCStatepointInst>(SPInvoke); 18660b57cec5SDimitry Andric 18670b57cec5SDimitry Andric // Generate gc relocates in exceptional path 18680b57cec5SDimitry Andric BasicBlock *UnwindBlock = II->getUnwindDest(); 18690b57cec5SDimitry Andric assert(!isa<PHINode>(UnwindBlock->begin()) && 18700b57cec5SDimitry Andric UnwindBlock->getUniquePredecessor() && 18710b57cec5SDimitry Andric "can't safely insert in this block!"); 18720b57cec5SDimitry Andric 18735f757f3fSDimitry Andric Builder.SetInsertPoint(UnwindBlock, UnwindBlock->getFirstInsertionPt()); 18740b57cec5SDimitry Andric Builder.SetCurrentDebugLocation(II->getDebugLoc()); 18750b57cec5SDimitry Andric 18760b57cec5SDimitry Andric // Attach exceptional gc relocates to the landingpad. 18770b57cec5SDimitry Andric Instruction *ExceptionalToken = UnwindBlock->getLandingPadInst(); 18780b57cec5SDimitry Andric Result.UnwindToken = ExceptionalToken; 18790b57cec5SDimitry Andric 188006c3fb27SDimitry Andric CreateGCRelocates(LiveVariables, BasePtrs, ExceptionalToken, Builder, GC); 18810b57cec5SDimitry Andric 18820b57cec5SDimitry Andric // Generate gc relocates and returns for normal block 18830b57cec5SDimitry Andric BasicBlock *NormalDest = II->getNormalDest(); 18840b57cec5SDimitry Andric assert(!isa<PHINode>(NormalDest->begin()) && 18850b57cec5SDimitry Andric NormalDest->getUniquePredecessor() && 18860b57cec5SDimitry Andric "can't safely insert in this block!"); 18870b57cec5SDimitry Andric 18885f757f3fSDimitry Andric Builder.SetInsertPoint(NormalDest, NormalDest->getFirstInsertionPt()); 18890b57cec5SDimitry Andric 18900b57cec5SDimitry Andric // gc relocates will be generated later as if it were regular call 18910b57cec5SDimitry Andric // statepoint 18920b57cec5SDimitry Andric } 18930b57cec5SDimitry Andric assert(Token && "Should be set in one of the above branches!"); 18940b57cec5SDimitry Andric 18950b57cec5SDimitry Andric if (IsDeoptimize) { 18960b57cec5SDimitry Andric // If we're wrapping an @llvm.experimental.deoptimize in a statepoint, we 18970b57cec5SDimitry Andric // transform the tail-call like structure to a call to a void function 18980b57cec5SDimitry Andric // followed by unreachable to get better codegen. 18990b57cec5SDimitry Andric Replacements.push_back( 19000b57cec5SDimitry Andric DeferredReplacement::createDeoptimizeReplacement(Call)); 19010b57cec5SDimitry Andric } else { 19020b57cec5SDimitry Andric Token->setName("statepoint_token"); 19030b57cec5SDimitry Andric if (!Call->getType()->isVoidTy() && !Call->use_empty()) { 19040b57cec5SDimitry Andric StringRef Name = Call->hasName() ? Call->getName() : ""; 19050b57cec5SDimitry Andric CallInst *GCResult = Builder.CreateGCResult(Token, Call->getType(), Name); 19060b57cec5SDimitry Andric GCResult->setAttributes( 19070b57cec5SDimitry Andric AttributeList::get(GCResult->getContext(), AttributeList::ReturnIndex, 1908349cc55cSDimitry Andric Call->getAttributes().getRetAttrs())); 19090b57cec5SDimitry Andric 19100b57cec5SDimitry Andric // We cannot RAUW or delete CS.getInstruction() because it could be in the 19110b57cec5SDimitry Andric // live set of some other safepoint, in which case that safepoint's 19120b57cec5SDimitry Andric // PartiallyConstructedSafepointRecord will hold a raw pointer to this 19130b57cec5SDimitry Andric // llvm::Instruction. Instead, we defer the replacement and deletion to 19140b57cec5SDimitry Andric // after the live sets have been made explicit in the IR, and we no longer 19150b57cec5SDimitry Andric // have raw pointers to worry about. 19160b57cec5SDimitry Andric Replacements.emplace_back( 19170b57cec5SDimitry Andric DeferredReplacement::createRAUW(Call, GCResult)); 19180b57cec5SDimitry Andric } else { 19190b57cec5SDimitry Andric Replacements.emplace_back(DeferredReplacement::createDelete(Call)); 19200b57cec5SDimitry Andric } 19210b57cec5SDimitry Andric } 19220b57cec5SDimitry Andric 19230b57cec5SDimitry Andric Result.StatepointToken = Token; 19240b57cec5SDimitry Andric 19250b57cec5SDimitry Andric // Second, create a gc.relocate for every live variable 192606c3fb27SDimitry Andric CreateGCRelocates(LiveVariables, BasePtrs, Token, Builder, GC); 19270b57cec5SDimitry Andric } 19280b57cec5SDimitry Andric 19290b57cec5SDimitry Andric // Replace an existing gc.statepoint with a new one and a set of gc.relocates 19300b57cec5SDimitry Andric // which make the relocations happening at this safepoint explicit. 19310b57cec5SDimitry Andric // 19320b57cec5SDimitry Andric // WARNING: Does not do any fixup to adjust users of the original live 19330b57cec5SDimitry Andric // values. That's the callers responsibility. 19340b57cec5SDimitry Andric static void 19350b57cec5SDimitry Andric makeStatepointExplicit(DominatorTree &DT, CallBase *Call, 19360b57cec5SDimitry Andric PartiallyConstructedSafepointRecord &Result, 19371fd87a68SDimitry Andric std::vector<DeferredReplacement> &Replacements, 193806c3fb27SDimitry Andric const PointerToBaseTy &PointerToBase, GCStrategy *GC) { 19390b57cec5SDimitry Andric const auto &LiveSet = Result.LiveSet; 19400b57cec5SDimitry Andric 19410b57cec5SDimitry Andric // Convert to vector for efficient cross referencing. 19420b57cec5SDimitry Andric SmallVector<Value *, 64> BaseVec, LiveVec; 19430b57cec5SDimitry Andric LiveVec.reserve(LiveSet.size()); 19440b57cec5SDimitry Andric BaseVec.reserve(LiveSet.size()); 19450b57cec5SDimitry Andric for (Value *L : LiveSet) { 19460b57cec5SDimitry Andric LiveVec.push_back(L); 19470b57cec5SDimitry Andric assert(PointerToBase.count(L)); 19480b57cec5SDimitry Andric Value *Base = PointerToBase.find(L)->second; 19490b57cec5SDimitry Andric BaseVec.push_back(Base); 19500b57cec5SDimitry Andric } 19510b57cec5SDimitry Andric assert(LiveVec.size() == BaseVec.size()); 19520b57cec5SDimitry Andric 19530b57cec5SDimitry Andric // Do the actual rewriting and delete the old statepoint 19541fd87a68SDimitry Andric makeStatepointExplicitImpl(Call, BaseVec, LiveVec, Result, Replacements, 195506c3fb27SDimitry Andric PointerToBase, GC); 19560b57cec5SDimitry Andric } 19570b57cec5SDimitry Andric 19580b57cec5SDimitry Andric // Helper function for the relocationViaAlloca. 19590b57cec5SDimitry Andric // 19600b57cec5SDimitry Andric // It receives iterator to the statepoint gc relocates and emits a store to the 19610b57cec5SDimitry Andric // assigned location (via allocaMap) for the each one of them. It adds the 19620b57cec5SDimitry Andric // visited values into the visitedLiveValues set, which we will later use them 1963349cc55cSDimitry Andric // for validation checking. 19640b57cec5SDimitry Andric static void 19650b57cec5SDimitry Andric insertRelocationStores(iterator_range<Value::user_iterator> GCRelocs, 19660b57cec5SDimitry Andric DenseMap<Value *, AllocaInst *> &AllocaMap, 19670b57cec5SDimitry Andric DenseSet<Value *> &VisitedLiveValues) { 19680b57cec5SDimitry Andric for (User *U : GCRelocs) { 19690b57cec5SDimitry Andric GCRelocateInst *Relocate = dyn_cast<GCRelocateInst>(U); 19700b57cec5SDimitry Andric if (!Relocate) 19710b57cec5SDimitry Andric continue; 19720b57cec5SDimitry Andric 19730b57cec5SDimitry Andric Value *OriginalValue = Relocate->getDerivedPtr(); 19740b57cec5SDimitry Andric assert(AllocaMap.count(OriginalValue)); 19750b57cec5SDimitry Andric Value *Alloca = AllocaMap[OriginalValue]; 19760b57cec5SDimitry Andric 1977297eecfbSDimitry Andric // Emit store into the related alloca. 19780b57cec5SDimitry Andric assert(Relocate->getNextNode() && 19790b57cec5SDimitry Andric "Should always have one since it's not a terminator"); 1980*0fca6ea1SDimitry Andric new StoreInst(Relocate, Alloca, std::next(Relocate->getIterator())); 19810b57cec5SDimitry Andric 19820b57cec5SDimitry Andric #ifndef NDEBUG 19830b57cec5SDimitry Andric VisitedLiveValues.insert(OriginalValue); 19840b57cec5SDimitry Andric #endif 19850b57cec5SDimitry Andric } 19860b57cec5SDimitry Andric } 19870b57cec5SDimitry Andric 19880b57cec5SDimitry Andric // Helper function for the "relocationViaAlloca". Similar to the 19890b57cec5SDimitry Andric // "insertRelocationStores" but works for rematerialized values. 19900b57cec5SDimitry Andric static void insertRematerializationStores( 19910b57cec5SDimitry Andric const RematerializedValueMapTy &RematerializedValues, 19920b57cec5SDimitry Andric DenseMap<Value *, AllocaInst *> &AllocaMap, 19930b57cec5SDimitry Andric DenseSet<Value *> &VisitedLiveValues) { 19940b57cec5SDimitry Andric for (auto RematerializedValuePair: RematerializedValues) { 19950b57cec5SDimitry Andric Instruction *RematerializedValue = RematerializedValuePair.first; 19960b57cec5SDimitry Andric Value *OriginalValue = RematerializedValuePair.second; 19970b57cec5SDimitry Andric 19980b57cec5SDimitry Andric assert(AllocaMap.count(OriginalValue) && 19990b57cec5SDimitry Andric "Can not find alloca for rematerialized value"); 20000b57cec5SDimitry Andric Value *Alloca = AllocaMap[OriginalValue]; 20010b57cec5SDimitry Andric 20025ffd83dbSDimitry Andric new StoreInst(RematerializedValue, Alloca, 2003*0fca6ea1SDimitry Andric std::next(RematerializedValue->getIterator())); 20040b57cec5SDimitry Andric 20050b57cec5SDimitry Andric #ifndef NDEBUG 20060b57cec5SDimitry Andric VisitedLiveValues.insert(OriginalValue); 20070b57cec5SDimitry Andric #endif 20080b57cec5SDimitry Andric } 20090b57cec5SDimitry Andric } 20100b57cec5SDimitry Andric 20110b57cec5SDimitry Andric /// Do all the relocation update via allocas and mem2reg 20120b57cec5SDimitry Andric static void relocationViaAlloca( 20130b57cec5SDimitry Andric Function &F, DominatorTree &DT, ArrayRef<Value *> Live, 20140b57cec5SDimitry Andric ArrayRef<PartiallyConstructedSafepointRecord> Records) { 20150b57cec5SDimitry Andric #ifndef NDEBUG 20160b57cec5SDimitry Andric // record initial number of (static) allocas; we'll check we have the same 20170b57cec5SDimitry Andric // number when we get done. 20180b57cec5SDimitry Andric int InitialAllocaNum = 0; 20190b57cec5SDimitry Andric for (Instruction &I : F.getEntryBlock()) 20200b57cec5SDimitry Andric if (isa<AllocaInst>(I)) 20210b57cec5SDimitry Andric InitialAllocaNum++; 20220b57cec5SDimitry Andric #endif 20230b57cec5SDimitry Andric 20240b57cec5SDimitry Andric // TODO-PERF: change data structures, reserve 20250b57cec5SDimitry Andric DenseMap<Value *, AllocaInst *> AllocaMap; 20260b57cec5SDimitry Andric SmallVector<AllocaInst *, 200> PromotableAllocas; 20270b57cec5SDimitry Andric // Used later to chack that we have enough allocas to store all values 20280b57cec5SDimitry Andric std::size_t NumRematerializedValues = 0; 20290b57cec5SDimitry Andric PromotableAllocas.reserve(Live.size()); 20300b57cec5SDimitry Andric 20310b57cec5SDimitry Andric // Emit alloca for "LiveValue" and record it in "allocaMap" and 20320b57cec5SDimitry Andric // "PromotableAllocas" 2033*0fca6ea1SDimitry Andric const DataLayout &DL = F.getDataLayout(); 20340b57cec5SDimitry Andric auto emitAllocaFor = [&](Value *LiveValue) { 2035*0fca6ea1SDimitry Andric AllocaInst *Alloca = 2036*0fca6ea1SDimitry Andric new AllocaInst(LiveValue->getType(), DL.getAllocaAddrSpace(), "", 2037*0fca6ea1SDimitry Andric F.getEntryBlock().getFirstNonPHIIt()); 20380b57cec5SDimitry Andric AllocaMap[LiveValue] = Alloca; 20390b57cec5SDimitry Andric PromotableAllocas.push_back(Alloca); 20400b57cec5SDimitry Andric }; 20410b57cec5SDimitry Andric 20420b57cec5SDimitry Andric // Emit alloca for each live gc pointer 20430b57cec5SDimitry Andric for (Value *V : Live) 20440b57cec5SDimitry Andric emitAllocaFor(V); 20450b57cec5SDimitry Andric 20460b57cec5SDimitry Andric // Emit allocas for rematerialized values 20470b57cec5SDimitry Andric for (const auto &Info : Records) 20480b57cec5SDimitry Andric for (auto RematerializedValuePair : Info.RematerializedValues) { 20490b57cec5SDimitry Andric Value *OriginalValue = RematerializedValuePair.second; 2050cb14a3feSDimitry Andric if (AllocaMap.contains(OriginalValue)) 20510b57cec5SDimitry Andric continue; 20520b57cec5SDimitry Andric 20530b57cec5SDimitry Andric emitAllocaFor(OriginalValue); 20540b57cec5SDimitry Andric ++NumRematerializedValues; 20550b57cec5SDimitry Andric } 20560b57cec5SDimitry Andric 20570b57cec5SDimitry Andric // The next two loops are part of the same conceptual operation. We need to 20580b57cec5SDimitry Andric // insert a store to the alloca after the original def and at each 20590b57cec5SDimitry Andric // redefinition. We need to insert a load before each use. These are split 20600b57cec5SDimitry Andric // into distinct loops for performance reasons. 20610b57cec5SDimitry Andric 20620b57cec5SDimitry Andric // Update gc pointer after each statepoint: either store a relocated value or 20630b57cec5SDimitry Andric // null (if no relocated value was found for this gc pointer and it is not a 20640b57cec5SDimitry Andric // gc_result). This must happen before we update the statepoint with load of 20650b57cec5SDimitry Andric // alloca otherwise we lose the link between statepoint and old def. 20660b57cec5SDimitry Andric for (const auto &Info : Records) { 20670b57cec5SDimitry Andric Value *Statepoint = Info.StatepointToken; 20680b57cec5SDimitry Andric 20690b57cec5SDimitry Andric // This will be used for consistency check 20700b57cec5SDimitry Andric DenseSet<Value *> VisitedLiveValues; 20710b57cec5SDimitry Andric 20720b57cec5SDimitry Andric // Insert stores for normal statepoint gc relocates 20730b57cec5SDimitry Andric insertRelocationStores(Statepoint->users(), AllocaMap, VisitedLiveValues); 20740b57cec5SDimitry Andric 20750b57cec5SDimitry Andric // In case if it was invoke statepoint 20760b57cec5SDimitry Andric // we will insert stores for exceptional path gc relocates. 20770b57cec5SDimitry Andric if (isa<InvokeInst>(Statepoint)) { 20780b57cec5SDimitry Andric insertRelocationStores(Info.UnwindToken->users(), AllocaMap, 20790b57cec5SDimitry Andric VisitedLiveValues); 20800b57cec5SDimitry Andric } 20810b57cec5SDimitry Andric 20820b57cec5SDimitry Andric // Do similar thing with rematerialized values 20830b57cec5SDimitry Andric insertRematerializationStores(Info.RematerializedValues, AllocaMap, 20840b57cec5SDimitry Andric VisitedLiveValues); 20850b57cec5SDimitry Andric 20860b57cec5SDimitry Andric if (ClobberNonLive) { 20870b57cec5SDimitry Andric // As a debugging aid, pretend that an unrelocated pointer becomes null at 20880b57cec5SDimitry Andric // the gc.statepoint. This will turn some subtle GC problems into 20890b57cec5SDimitry Andric // slightly easier to debug SEGVs. Note that on large IR files with 20900b57cec5SDimitry Andric // lots of gc.statepoints this is extremely costly both memory and time 20910b57cec5SDimitry Andric // wise. 20920b57cec5SDimitry Andric SmallVector<AllocaInst *, 64> ToClobber; 20930b57cec5SDimitry Andric for (auto Pair : AllocaMap) { 20940b57cec5SDimitry Andric Value *Def = Pair.first; 20950b57cec5SDimitry Andric AllocaInst *Alloca = Pair.second; 20960b57cec5SDimitry Andric 20970b57cec5SDimitry Andric // This value was relocated 20980b57cec5SDimitry Andric if (VisitedLiveValues.count(Def)) { 20990b57cec5SDimitry Andric continue; 21000b57cec5SDimitry Andric } 21010b57cec5SDimitry Andric ToClobber.push_back(Alloca); 21020b57cec5SDimitry Andric } 21030b57cec5SDimitry Andric 2104*0fca6ea1SDimitry Andric auto InsertClobbersAt = [&](BasicBlock::iterator IP) { 21050b57cec5SDimitry Andric for (auto *AI : ToClobber) { 2106bdd1243dSDimitry Andric auto AT = AI->getAllocatedType(); 2107bdd1243dSDimitry Andric Constant *CPN; 2108bdd1243dSDimitry Andric if (AT->isVectorTy()) 2109bdd1243dSDimitry Andric CPN = ConstantAggregateZero::get(AT); 2110bdd1243dSDimitry Andric else 2111bdd1243dSDimitry Andric CPN = ConstantPointerNull::get(cast<PointerType>(AT)); 21125ffd83dbSDimitry Andric new StoreInst(CPN, AI, IP); 21130b57cec5SDimitry Andric } 21140b57cec5SDimitry Andric }; 21150b57cec5SDimitry Andric 21160b57cec5SDimitry Andric // Insert the clobbering stores. These may get intermixed with the 21170b57cec5SDimitry Andric // gc.results and gc.relocates, but that's fine. 21180b57cec5SDimitry Andric if (auto II = dyn_cast<InvokeInst>(Statepoint)) { 2119*0fca6ea1SDimitry Andric InsertClobbersAt(II->getNormalDest()->getFirstInsertionPt()); 2120*0fca6ea1SDimitry Andric InsertClobbersAt(II->getUnwindDest()->getFirstInsertionPt()); 21210b57cec5SDimitry Andric } else { 2122*0fca6ea1SDimitry Andric InsertClobbersAt( 2123*0fca6ea1SDimitry Andric std::next(cast<Instruction>(Statepoint)->getIterator())); 21240b57cec5SDimitry Andric } 21250b57cec5SDimitry Andric } 21260b57cec5SDimitry Andric } 21270b57cec5SDimitry Andric 21280b57cec5SDimitry Andric // Update use with load allocas and add store for gc_relocated. 21290b57cec5SDimitry Andric for (auto Pair : AllocaMap) { 21300b57cec5SDimitry Andric Value *Def = Pair.first; 21310b57cec5SDimitry Andric AllocaInst *Alloca = Pair.second; 21320b57cec5SDimitry Andric 21330b57cec5SDimitry Andric // We pre-record the uses of allocas so that we dont have to worry about 21340b57cec5SDimitry Andric // later update that changes the user information.. 21350b57cec5SDimitry Andric 21360b57cec5SDimitry Andric SmallVector<Instruction *, 20> Uses; 21370b57cec5SDimitry Andric // PERF: trade a linear scan for repeated reallocation 21380b57cec5SDimitry Andric Uses.reserve(Def->getNumUses()); 21390b57cec5SDimitry Andric for (User *U : Def->users()) { 21400b57cec5SDimitry Andric if (!isa<ConstantExpr>(U)) { 21410b57cec5SDimitry Andric // If the def has a ConstantExpr use, then the def is either a 21420b57cec5SDimitry Andric // ConstantExpr use itself or null. In either case 21430b57cec5SDimitry Andric // (recursively in the first, directly in the second), the oop 21440b57cec5SDimitry Andric // it is ultimately dependent on is null and this particular 21450b57cec5SDimitry Andric // use does not need to be fixed up. 21460b57cec5SDimitry Andric Uses.push_back(cast<Instruction>(U)); 21470b57cec5SDimitry Andric } 21480b57cec5SDimitry Andric } 21490b57cec5SDimitry Andric 21500b57cec5SDimitry Andric llvm::sort(Uses); 2151*0fca6ea1SDimitry Andric auto Last = llvm::unique(Uses); 21520b57cec5SDimitry Andric Uses.erase(Last, Uses.end()); 21530b57cec5SDimitry Andric 21540b57cec5SDimitry Andric for (Instruction *Use : Uses) { 21550b57cec5SDimitry Andric if (isa<PHINode>(Use)) { 21560b57cec5SDimitry Andric PHINode *Phi = cast<PHINode>(Use); 21570b57cec5SDimitry Andric for (unsigned i = 0; i < Phi->getNumIncomingValues(); i++) { 21580b57cec5SDimitry Andric if (Def == Phi->getIncomingValue(i)) { 2159*0fca6ea1SDimitry Andric LoadInst *Load = new LoadInst( 2160*0fca6ea1SDimitry Andric Alloca->getAllocatedType(), Alloca, "", 2161*0fca6ea1SDimitry Andric Phi->getIncomingBlock(i)->getTerminator()->getIterator()); 21620b57cec5SDimitry Andric Phi->setIncomingValue(i, Load); 21630b57cec5SDimitry Andric } 21640b57cec5SDimitry Andric } 21650b57cec5SDimitry Andric } else { 2166*0fca6ea1SDimitry Andric LoadInst *Load = new LoadInst(Alloca->getAllocatedType(), Alloca, "", 2167*0fca6ea1SDimitry Andric Use->getIterator()); 21680b57cec5SDimitry Andric Use->replaceUsesOfWith(Def, Load); 21690b57cec5SDimitry Andric } 21700b57cec5SDimitry Andric } 21710b57cec5SDimitry Andric 21720b57cec5SDimitry Andric // Emit store for the initial gc value. Store must be inserted after load, 21730b57cec5SDimitry Andric // otherwise store will be in alloca's use list and an extra load will be 21740b57cec5SDimitry Andric // inserted before it. 21755ffd83dbSDimitry Andric StoreInst *Store = new StoreInst(Def, Alloca, /*volatile*/ false, 21765ffd83dbSDimitry Andric DL.getABITypeAlign(Def->getType())); 21770b57cec5SDimitry Andric if (Instruction *Inst = dyn_cast<Instruction>(Def)) { 21780b57cec5SDimitry Andric if (InvokeInst *Invoke = dyn_cast<InvokeInst>(Inst)) { 21790b57cec5SDimitry Andric // InvokeInst is a terminator so the store need to be inserted into its 21800b57cec5SDimitry Andric // normal destination block. 21810b57cec5SDimitry Andric BasicBlock *NormalDest = Invoke->getNormalDest(); 21820b57cec5SDimitry Andric Store->insertBefore(NormalDest->getFirstNonPHI()); 21830b57cec5SDimitry Andric } else { 21840b57cec5SDimitry Andric assert(!Inst->isTerminator() && 21850b57cec5SDimitry Andric "The only terminator that can produce a value is " 21860b57cec5SDimitry Andric "InvokeInst which is handled above."); 21870b57cec5SDimitry Andric Store->insertAfter(Inst); 21880b57cec5SDimitry Andric } 21890b57cec5SDimitry Andric } else { 21900b57cec5SDimitry Andric assert(isa<Argument>(Def)); 21910b57cec5SDimitry Andric Store->insertAfter(cast<Instruction>(Alloca)); 21920b57cec5SDimitry Andric } 21930b57cec5SDimitry Andric } 21940b57cec5SDimitry Andric 21950b57cec5SDimitry Andric assert(PromotableAllocas.size() == Live.size() + NumRematerializedValues && 21960b57cec5SDimitry Andric "we must have the same allocas with lives"); 219781ad6265SDimitry Andric (void) NumRematerializedValues; 21980b57cec5SDimitry Andric if (!PromotableAllocas.empty()) { 21990b57cec5SDimitry Andric // Apply mem2reg to promote alloca to SSA 22000b57cec5SDimitry Andric PromoteMemToReg(PromotableAllocas, DT); 22010b57cec5SDimitry Andric } 22020b57cec5SDimitry Andric 22030b57cec5SDimitry Andric #ifndef NDEBUG 22040b57cec5SDimitry Andric for (auto &I : F.getEntryBlock()) 22050b57cec5SDimitry Andric if (isa<AllocaInst>(I)) 22060b57cec5SDimitry Andric InitialAllocaNum--; 22070b57cec5SDimitry Andric assert(InitialAllocaNum == 0 && "We must not introduce any extra allocas"); 22080b57cec5SDimitry Andric #endif 22090b57cec5SDimitry Andric } 22100b57cec5SDimitry Andric 22110b57cec5SDimitry Andric /// Implement a unique function which doesn't require we sort the input 22120b57cec5SDimitry Andric /// vector. Doing so has the effect of changing the output of a couple of 22130b57cec5SDimitry Andric /// tests in ways which make them less useful in testing fused safepoints. 22140b57cec5SDimitry Andric template <typename T> static void unique_unsorted(SmallVectorImpl<T> &Vec) { 22150b57cec5SDimitry Andric SmallSet<T, 8> Seen; 2216e8d8bef9SDimitry Andric erase_if(Vec, [&](const T &V) { return !Seen.insert(V).second; }); 22170b57cec5SDimitry Andric } 22180b57cec5SDimitry Andric 22190b57cec5SDimitry Andric /// Insert holders so that each Value is obviously live through the entire 22200b57cec5SDimitry Andric /// lifetime of the call. 22210b57cec5SDimitry Andric static void insertUseHolderAfter(CallBase *Call, const ArrayRef<Value *> Values, 22220b57cec5SDimitry Andric SmallVectorImpl<CallInst *> &Holders) { 22230b57cec5SDimitry Andric if (Values.empty()) 22240b57cec5SDimitry Andric // No values to hold live, might as well not insert the empty holder 22250b57cec5SDimitry Andric return; 22260b57cec5SDimitry Andric 22270b57cec5SDimitry Andric Module *M = Call->getModule(); 22280b57cec5SDimitry Andric // Use a dummy vararg function to actually hold the values live 22290b57cec5SDimitry Andric FunctionCallee Func = M->getOrInsertFunction( 22300b57cec5SDimitry Andric "__tmp_use", FunctionType::get(Type::getVoidTy(M->getContext()), true)); 22310b57cec5SDimitry Andric if (isa<CallInst>(Call)) { 22320b57cec5SDimitry Andric // For call safepoints insert dummy calls right after safepoint 22330b57cec5SDimitry Andric Holders.push_back( 2234*0fca6ea1SDimitry Andric CallInst::Create(Func, Values, "", std::next(Call->getIterator()))); 22350b57cec5SDimitry Andric return; 22360b57cec5SDimitry Andric } 22370b57cec5SDimitry Andric // For invoke safepooints insert dummy calls both in normal and 22380b57cec5SDimitry Andric // exceptional destination blocks 22390b57cec5SDimitry Andric auto *II = cast<InvokeInst>(Call); 22400b57cec5SDimitry Andric Holders.push_back(CallInst::Create( 2241*0fca6ea1SDimitry Andric Func, Values, "", II->getNormalDest()->getFirstInsertionPt())); 22420b57cec5SDimitry Andric Holders.push_back(CallInst::Create( 2243*0fca6ea1SDimitry Andric Func, Values, "", II->getUnwindDest()->getFirstInsertionPt())); 22440b57cec5SDimitry Andric } 22450b57cec5SDimitry Andric 22460b57cec5SDimitry Andric static void findLiveReferences( 22470b57cec5SDimitry Andric Function &F, DominatorTree &DT, ArrayRef<CallBase *> toUpdate, 224806c3fb27SDimitry Andric MutableArrayRef<struct PartiallyConstructedSafepointRecord> records, 224906c3fb27SDimitry Andric GCStrategy *GC) { 22500b57cec5SDimitry Andric GCPtrLivenessData OriginalLivenessData; 225106c3fb27SDimitry Andric computeLiveInValues(DT, F, OriginalLivenessData, GC); 22520b57cec5SDimitry Andric for (size_t i = 0; i < records.size(); i++) { 22530b57cec5SDimitry Andric struct PartiallyConstructedSafepointRecord &info = records[i]; 225406c3fb27SDimitry Andric analyzeParsePointLiveness(DT, OriginalLivenessData, toUpdate[i], info, GC); 22550b57cec5SDimitry Andric } 22560b57cec5SDimitry Andric } 22570b57cec5SDimitry Andric 22580b57cec5SDimitry Andric // Helper function for the "rematerializeLiveValues". It walks use chain 22590b57cec5SDimitry Andric // starting from the "CurrentValue" until it reaches the root of the chain, i.e. 22600b57cec5SDimitry Andric // the base or a value it cannot process. Only "simple" values are processed 22610b57cec5SDimitry Andric // (currently it is GEP's and casts). The returned root is examined by the 22620b57cec5SDimitry Andric // callers of findRematerializableChainToBasePointer. Fills "ChainToBase" array 22630b57cec5SDimitry Andric // with all visited values. 22640b57cec5SDimitry Andric static Value* findRematerializableChainToBasePointer( 22650b57cec5SDimitry Andric SmallVectorImpl<Instruction*> &ChainToBase, 22660b57cec5SDimitry Andric Value *CurrentValue) { 22670b57cec5SDimitry Andric if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(CurrentValue)) { 22680b57cec5SDimitry Andric ChainToBase.push_back(GEP); 22690b57cec5SDimitry Andric return findRematerializableChainToBasePointer(ChainToBase, 22700b57cec5SDimitry Andric GEP->getPointerOperand()); 22710b57cec5SDimitry Andric } 22720b57cec5SDimitry Andric 22730b57cec5SDimitry Andric if (CastInst *CI = dyn_cast<CastInst>(CurrentValue)) { 2274*0fca6ea1SDimitry Andric if (!CI->isNoopCast(CI->getDataLayout())) 22750b57cec5SDimitry Andric return CI; 22760b57cec5SDimitry Andric 22770b57cec5SDimitry Andric ChainToBase.push_back(CI); 22780b57cec5SDimitry Andric return findRematerializableChainToBasePointer(ChainToBase, 22790b57cec5SDimitry Andric CI->getOperand(0)); 22800b57cec5SDimitry Andric } 22810b57cec5SDimitry Andric 22820b57cec5SDimitry Andric // We have reached the root of the chain, which is either equal to the base or 22830b57cec5SDimitry Andric // is the first unsupported value along the use chain. 22840b57cec5SDimitry Andric return CurrentValue; 22850b57cec5SDimitry Andric } 22860b57cec5SDimitry Andric 22870b57cec5SDimitry Andric // Helper function for the "rematerializeLiveValues". Compute cost of the use 22880b57cec5SDimitry Andric // chain we are going to rematerialize. 2289e8d8bef9SDimitry Andric static InstructionCost 22900b57cec5SDimitry Andric chainToBasePointerCost(SmallVectorImpl<Instruction *> &Chain, 22910b57cec5SDimitry Andric TargetTransformInfo &TTI) { 2292e8d8bef9SDimitry Andric InstructionCost Cost = 0; 22930b57cec5SDimitry Andric 22940b57cec5SDimitry Andric for (Instruction *Instr : Chain) { 22950b57cec5SDimitry Andric if (CastInst *CI = dyn_cast<CastInst>(Instr)) { 2296*0fca6ea1SDimitry Andric assert(CI->isNoopCast(CI->getDataLayout()) && 22970b57cec5SDimitry Andric "non noop cast is found during rematerialization"); 22980b57cec5SDimitry Andric 22990b57cec5SDimitry Andric Type *SrcTy = CI->getOperand(0)->getType(); 23005ffd83dbSDimitry Andric Cost += TTI.getCastInstrCost(CI->getOpcode(), CI->getType(), SrcTy, 2301e8d8bef9SDimitry Andric TTI::getCastContextHint(CI), 2302e8d8bef9SDimitry Andric TargetTransformInfo::TCK_SizeAndLatency, CI); 23030b57cec5SDimitry Andric 23040b57cec5SDimitry Andric } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Instr)) { 23050b57cec5SDimitry Andric // Cost of the address calculation 23060b57cec5SDimitry Andric Type *ValTy = GEP->getSourceElementType(); 23070b57cec5SDimitry Andric Cost += TTI.getAddressComputationCost(ValTy); 23080b57cec5SDimitry Andric 23090b57cec5SDimitry Andric // And cost of the GEP itself 23100b57cec5SDimitry Andric // TODO: Use TTI->getGEPCost here (it exists, but appears to be not 23110b57cec5SDimitry Andric // allowed for the external usage) 23120b57cec5SDimitry Andric if (!GEP->hasAllConstantIndices()) 23130b57cec5SDimitry Andric Cost += 2; 23140b57cec5SDimitry Andric 23150b57cec5SDimitry Andric } else { 23160b57cec5SDimitry Andric llvm_unreachable("unsupported instruction type during rematerialization"); 23170b57cec5SDimitry Andric } 23180b57cec5SDimitry Andric } 23190b57cec5SDimitry Andric 23200b57cec5SDimitry Andric return Cost; 23210b57cec5SDimitry Andric } 23220b57cec5SDimitry Andric 23230b57cec5SDimitry Andric static bool AreEquivalentPhiNodes(PHINode &OrigRootPhi, PHINode &AlternateRootPhi) { 23240b57cec5SDimitry Andric unsigned PhiNum = OrigRootPhi.getNumIncomingValues(); 23250b57cec5SDimitry Andric if (PhiNum != AlternateRootPhi.getNumIncomingValues() || 23260b57cec5SDimitry Andric OrigRootPhi.getParent() != AlternateRootPhi.getParent()) 23270b57cec5SDimitry Andric return false; 23280b57cec5SDimitry Andric // Map of incoming values and their corresponding basic blocks of 23290b57cec5SDimitry Andric // OrigRootPhi. 23300b57cec5SDimitry Andric SmallDenseMap<Value *, BasicBlock *, 8> CurrentIncomingValues; 23310b57cec5SDimitry Andric for (unsigned i = 0; i < PhiNum; i++) 23320b57cec5SDimitry Andric CurrentIncomingValues[OrigRootPhi.getIncomingValue(i)] = 23330b57cec5SDimitry Andric OrigRootPhi.getIncomingBlock(i); 23340b57cec5SDimitry Andric 23350b57cec5SDimitry Andric // Both current and base PHIs should have same incoming values and 23360b57cec5SDimitry Andric // the same basic blocks corresponding to the incoming values. 23370b57cec5SDimitry Andric for (unsigned i = 0; i < PhiNum; i++) { 23380b57cec5SDimitry Andric auto CIVI = 23390b57cec5SDimitry Andric CurrentIncomingValues.find(AlternateRootPhi.getIncomingValue(i)); 23400b57cec5SDimitry Andric if (CIVI == CurrentIncomingValues.end()) 23410b57cec5SDimitry Andric return false; 23420b57cec5SDimitry Andric BasicBlock *CurrentIncomingBB = CIVI->second; 23430b57cec5SDimitry Andric if (CurrentIncomingBB != AlternateRootPhi.getIncomingBlock(i)) 23440b57cec5SDimitry Andric return false; 23450b57cec5SDimitry Andric } 23460b57cec5SDimitry Andric return true; 23470b57cec5SDimitry Andric } 23480b57cec5SDimitry Andric 234981ad6265SDimitry Andric // Find derived pointers that can be recomputed cheap enough and fill 235081ad6265SDimitry Andric // RematerizationCandidates with such candidates. 235181ad6265SDimitry Andric static void 235281ad6265SDimitry Andric findRematerializationCandidates(PointerToBaseTy PointerToBase, 235381ad6265SDimitry Andric RematCandTy &RematerizationCandidates, 23540b57cec5SDimitry Andric TargetTransformInfo &TTI) { 23550b57cec5SDimitry Andric const unsigned int ChainLengthThreshold = 10; 23560b57cec5SDimitry Andric 235781ad6265SDimitry Andric for (auto P2B : PointerToBase) { 235881ad6265SDimitry Andric auto *Derived = P2B.first; 235981ad6265SDimitry Andric auto *Base = P2B.second; 236081ad6265SDimitry Andric // Consider only derived pointers. 236181ad6265SDimitry Andric if (Derived == Base) 236281ad6265SDimitry Andric continue; 23630b57cec5SDimitry Andric 236481ad6265SDimitry Andric // For each live pointer find its defining chain. 23650b57cec5SDimitry Andric SmallVector<Instruction *, 3> ChainToBase; 23660b57cec5SDimitry Andric Value *RootOfChain = 236781ad6265SDimitry Andric findRematerializableChainToBasePointer(ChainToBase, Derived); 23680b57cec5SDimitry Andric 23690b57cec5SDimitry Andric // Nothing to do, or chain is too long 23700b57cec5SDimitry Andric if ( ChainToBase.size() == 0 || 23710b57cec5SDimitry Andric ChainToBase.size() > ChainLengthThreshold) 23720b57cec5SDimitry Andric continue; 23730b57cec5SDimitry Andric 23740b57cec5SDimitry Andric // Handle the scenario where the RootOfChain is not equal to the 23750b57cec5SDimitry Andric // Base Value, but they are essentially the same phi values. 237681ad6265SDimitry Andric if (RootOfChain != PointerToBase[Derived]) { 23770b57cec5SDimitry Andric PHINode *OrigRootPhi = dyn_cast<PHINode>(RootOfChain); 237881ad6265SDimitry Andric PHINode *AlternateRootPhi = dyn_cast<PHINode>(PointerToBase[Derived]); 23790b57cec5SDimitry Andric if (!OrigRootPhi || !AlternateRootPhi) 23800b57cec5SDimitry Andric continue; 23810b57cec5SDimitry Andric // PHI nodes that have the same incoming values, and belonging to the same 23820b57cec5SDimitry Andric // basic blocks are essentially the same SSA value. When the original phi 23830b57cec5SDimitry Andric // has incoming values with different base pointers, the original phi is 23840b57cec5SDimitry Andric // marked as conflict, and an additional `AlternateRootPhi` with the same 23850b57cec5SDimitry Andric // incoming values get generated by the findBasePointer function. We need 23860b57cec5SDimitry Andric // to identify the newly generated AlternateRootPhi (.base version of phi) 23870b57cec5SDimitry Andric // and RootOfChain (the original phi node itself) are the same, so that we 23880b57cec5SDimitry Andric // can rematerialize the gep and casts. This is a workaround for the 23890b57cec5SDimitry Andric // deficiency in the findBasePointer algorithm. 23900b57cec5SDimitry Andric if (!AreEquivalentPhiNodes(*OrigRootPhi, *AlternateRootPhi)) 23910b57cec5SDimitry Andric continue; 23920b57cec5SDimitry Andric } 239381ad6265SDimitry Andric // Compute cost of this chain. 2394e8d8bef9SDimitry Andric InstructionCost Cost = chainToBasePointerCost(ChainToBase, TTI); 23950b57cec5SDimitry Andric // TODO: We can also account for cases when we will be able to remove some 23960b57cec5SDimitry Andric // of the rematerialized values by later optimization passes. I.e if 23970b57cec5SDimitry Andric // we rematerialized several intersecting chains. Or if original values 23980b57cec5SDimitry Andric // don't have any uses besides this statepoint. 23990b57cec5SDimitry Andric 240081ad6265SDimitry Andric // Ok, there is a candidate. 240181ad6265SDimitry Andric RematerizlizationCandidateRecord Record; 240281ad6265SDimitry Andric Record.ChainToBase = ChainToBase; 240381ad6265SDimitry Andric Record.RootOfChain = RootOfChain; 240481ad6265SDimitry Andric Record.Cost = Cost; 240581ad6265SDimitry Andric RematerizationCandidates.insert({ Derived, Record }); 240681ad6265SDimitry Andric } 240781ad6265SDimitry Andric } 240881ad6265SDimitry Andric 2409bdd1243dSDimitry Andric // Try to rematerialize derived pointers immediately before their uses 2410bdd1243dSDimitry Andric // (instead of rematerializing after every statepoint it is live through). 2411bdd1243dSDimitry Andric // This can be beneficial when derived pointer is live across many 2412bdd1243dSDimitry Andric // statepoints, but uses are rare. 2413bdd1243dSDimitry Andric static void rematerializeLiveValuesAtUses( 2414bdd1243dSDimitry Andric RematCandTy &RematerizationCandidates, 2415bdd1243dSDimitry Andric MutableArrayRef<PartiallyConstructedSafepointRecord> Records, 2416bdd1243dSDimitry Andric PointerToBaseTy &PointerToBase) { 2417bdd1243dSDimitry Andric if (!RematDerivedAtUses) 2418bdd1243dSDimitry Andric return; 2419bdd1243dSDimitry Andric 2420bdd1243dSDimitry Andric SmallVector<Instruction *, 32> LiveValuesToBeDeleted; 2421bdd1243dSDimitry Andric 2422bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Rematerialize derived pointers at uses, " 2423bdd1243dSDimitry Andric << "Num statepoints: " << Records.size() << '\n'); 2424bdd1243dSDimitry Andric 2425bdd1243dSDimitry Andric for (auto &It : RematerizationCandidates) { 2426bdd1243dSDimitry Andric Instruction *Cand = cast<Instruction>(It.first); 2427bdd1243dSDimitry Andric auto &Record = It.second; 2428bdd1243dSDimitry Andric 2429bdd1243dSDimitry Andric if (Record.Cost >= RematerializationThreshold) 2430bdd1243dSDimitry Andric continue; 2431bdd1243dSDimitry Andric 2432bdd1243dSDimitry Andric if (Cand->user_empty()) 2433bdd1243dSDimitry Andric continue; 2434bdd1243dSDimitry Andric 2435bdd1243dSDimitry Andric if (Cand->hasOneUse()) 2436bdd1243dSDimitry Andric if (auto *U = dyn_cast<Instruction>(Cand->getUniqueUndroppableUser())) 2437bdd1243dSDimitry Andric if (U->getParent() == Cand->getParent()) 2438bdd1243dSDimitry Andric continue; 2439bdd1243dSDimitry Andric 2440bdd1243dSDimitry Andric // Rematerialization before PHI nodes is not implemented. 2441bdd1243dSDimitry Andric if (llvm::any_of(Cand->users(), 2442bdd1243dSDimitry Andric [](const auto *U) { return isa<PHINode>(U); })) 2443bdd1243dSDimitry Andric continue; 2444bdd1243dSDimitry Andric 2445bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Trying cand " << *Cand << " ... "); 2446bdd1243dSDimitry Andric 2447bdd1243dSDimitry Andric // Count of rematerialization instructions we introduce is equal to number 2448bdd1243dSDimitry Andric // of candidate uses. 2449bdd1243dSDimitry Andric // Count of rematerialization instructions we eliminate is equal to number 2450bdd1243dSDimitry Andric // of statepoints it is live through. 2451bdd1243dSDimitry Andric // Consider transformation profitable if latter is greater than former 2452bdd1243dSDimitry Andric // (in other words, we create less than eliminate). 2453bdd1243dSDimitry Andric unsigned NumLiveStatepoints = llvm::count_if( 2454bdd1243dSDimitry Andric Records, [Cand](const auto &R) { return R.LiveSet.contains(Cand); }); 2455bdd1243dSDimitry Andric unsigned NumUses = Cand->getNumUses(); 2456bdd1243dSDimitry Andric 2457bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Num uses: " << NumUses << " Num live statepoints: " 2458bdd1243dSDimitry Andric << NumLiveStatepoints << " "); 2459bdd1243dSDimitry Andric 2460bdd1243dSDimitry Andric if (NumLiveStatepoints < NumUses) { 2461bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "not profitable\n"); 2462bdd1243dSDimitry Andric continue; 2463bdd1243dSDimitry Andric } 2464bdd1243dSDimitry Andric 2465bdd1243dSDimitry Andric // If rematerialization is 'free', then favor rematerialization at 2466bdd1243dSDimitry Andric // uses as it generally shortens live ranges. 2467bdd1243dSDimitry Andric // TODO: Short (size ==1) chains only? 2468bdd1243dSDimitry Andric if (NumLiveStatepoints == NumUses && Record.Cost > 0) { 2469bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "not profitable\n"); 2470bdd1243dSDimitry Andric continue; 2471bdd1243dSDimitry Andric } 2472bdd1243dSDimitry Andric 2473bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "looks profitable\n"); 2474bdd1243dSDimitry Andric 2475bdd1243dSDimitry Andric // ChainToBase may contain another remat candidate (as a sub chain) which 2476bdd1243dSDimitry Andric // has been rewritten by now. Need to recollect chain to have up to date 2477bdd1243dSDimitry Andric // value. 2478bdd1243dSDimitry Andric // TODO: sort records in findRematerializationCandidates() in 2479bdd1243dSDimitry Andric // decreasing chain size order? 2480bdd1243dSDimitry Andric if (Record.ChainToBase.size() > 1) { 2481bdd1243dSDimitry Andric Record.ChainToBase.clear(); 2482bdd1243dSDimitry Andric findRematerializableChainToBasePointer(Record.ChainToBase, Cand); 2483bdd1243dSDimitry Andric } 2484bdd1243dSDimitry Andric 2485bdd1243dSDimitry Andric // Current rematerialization algorithm is very simple: we rematerialize 2486bdd1243dSDimitry Andric // immediately before EVERY use, even if there are several uses in same 2487bdd1243dSDimitry Andric // block or if use is local to Cand Def. The reason is that this allows 2488bdd1243dSDimitry Andric // us to avoid recomputing liveness without complicated analysis: 2489bdd1243dSDimitry Andric // - If we did not eliminate all uses of original Candidate, we do not 2490bdd1243dSDimitry Andric // know exaclty in what BBs it is still live. 2491bdd1243dSDimitry Andric // - If we rematerialize once per BB, we need to find proper insertion 2492bdd1243dSDimitry Andric // place (first use in block, but after Def) and analyze if there is 2493bdd1243dSDimitry Andric // statepoint between uses in the block. 2494bdd1243dSDimitry Andric while (!Cand->user_empty()) { 2495bdd1243dSDimitry Andric Instruction *UserI = cast<Instruction>(*Cand->user_begin()); 2496bdd1243dSDimitry Andric Instruction *RematChain = rematerializeChain( 2497bdd1243dSDimitry Andric Record.ChainToBase, UserI, Record.RootOfChain, PointerToBase[Cand]); 2498bdd1243dSDimitry Andric UserI->replaceUsesOfWith(Cand, RematChain); 2499bdd1243dSDimitry Andric PointerToBase[RematChain] = PointerToBase[Cand]; 2500bdd1243dSDimitry Andric } 2501bdd1243dSDimitry Andric LiveValuesToBeDeleted.push_back(Cand); 2502bdd1243dSDimitry Andric } 2503bdd1243dSDimitry Andric 2504bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Rematerialized " << LiveValuesToBeDeleted.size() 2505bdd1243dSDimitry Andric << " derived pointers\n"); 2506bdd1243dSDimitry Andric for (auto *Cand : LiveValuesToBeDeleted) { 2507bdd1243dSDimitry Andric assert(Cand->use_empty() && "Unexpected user remain"); 2508bdd1243dSDimitry Andric RematerizationCandidates.erase(Cand); 2509bdd1243dSDimitry Andric for (auto &R : Records) { 2510bdd1243dSDimitry Andric assert(!R.LiveSet.contains(Cand) || 2511bdd1243dSDimitry Andric R.LiveSet.contains(PointerToBase[Cand])); 2512bdd1243dSDimitry Andric R.LiveSet.remove(Cand); 2513bdd1243dSDimitry Andric } 2514bdd1243dSDimitry Andric } 2515bdd1243dSDimitry Andric 2516bdd1243dSDimitry Andric // Recollect not rematerialized chains - we might have rewritten 2517bdd1243dSDimitry Andric // their sub-chains. 2518bdd1243dSDimitry Andric if (!LiveValuesToBeDeleted.empty()) { 2519bdd1243dSDimitry Andric for (auto &P : RematerizationCandidates) { 2520bdd1243dSDimitry Andric auto &R = P.second; 2521bdd1243dSDimitry Andric if (R.ChainToBase.size() > 1) { 2522bdd1243dSDimitry Andric R.ChainToBase.clear(); 2523bdd1243dSDimitry Andric findRematerializableChainToBasePointer(R.ChainToBase, P.first); 2524bdd1243dSDimitry Andric } 2525bdd1243dSDimitry Andric } 2526bdd1243dSDimitry Andric } 2527bdd1243dSDimitry Andric } 2528bdd1243dSDimitry Andric 252981ad6265SDimitry Andric // From the statepoint live set pick values that are cheaper to recompute then 253081ad6265SDimitry Andric // to relocate. Remove this values from the live set, rematerialize them after 253181ad6265SDimitry Andric // statepoint and record them in "Info" structure. Note that similar to 253281ad6265SDimitry Andric // relocated values we don't do any user adjustments here. 253381ad6265SDimitry Andric static void rematerializeLiveValues(CallBase *Call, 253481ad6265SDimitry Andric PartiallyConstructedSafepointRecord &Info, 253581ad6265SDimitry Andric PointerToBaseTy &PointerToBase, 253681ad6265SDimitry Andric RematCandTy &RematerizationCandidates, 253781ad6265SDimitry Andric TargetTransformInfo &TTI) { 253881ad6265SDimitry Andric // Record values we are going to delete from this statepoint live set. 253981ad6265SDimitry Andric // We can not di this in following loop due to iterator invalidation. 254081ad6265SDimitry Andric SmallVector<Value *, 32> LiveValuesToBeDeleted; 254181ad6265SDimitry Andric 254281ad6265SDimitry Andric for (Value *LiveValue : Info.LiveSet) { 254381ad6265SDimitry Andric auto It = RematerizationCandidates.find(LiveValue); 254481ad6265SDimitry Andric if (It == RematerizationCandidates.end()) 254581ad6265SDimitry Andric continue; 254681ad6265SDimitry Andric 254781ad6265SDimitry Andric RematerizlizationCandidateRecord &Record = It->second; 254881ad6265SDimitry Andric 254981ad6265SDimitry Andric InstructionCost Cost = Record.Cost; 25500b57cec5SDimitry Andric // For invokes we need to rematerialize each chain twice - for normal and 25510b57cec5SDimitry Andric // for unwind basic blocks. Model this by multiplying cost by two. 255281ad6265SDimitry Andric if (isa<InvokeInst>(Call)) 25530b57cec5SDimitry Andric Cost *= 2; 255481ad6265SDimitry Andric 255581ad6265SDimitry Andric // If it's too expensive - skip it. 25560b57cec5SDimitry Andric if (Cost >= RematerializationThreshold) 25570b57cec5SDimitry Andric continue; 25580b57cec5SDimitry Andric 25590b57cec5SDimitry Andric // Remove value from the live set 25600b57cec5SDimitry Andric LiveValuesToBeDeleted.push_back(LiveValue); 25610b57cec5SDimitry Andric 256281ad6265SDimitry Andric // Clone instructions and record them inside "Info" structure. 25630b57cec5SDimitry Andric 25640b57cec5SDimitry Andric // Different cases for calls and invokes. For invokes we need to clone 25650b57cec5SDimitry Andric // instructions both on normal and unwind path. 25660b57cec5SDimitry Andric if (isa<CallInst>(Call)) { 25670b57cec5SDimitry Andric Instruction *InsertBefore = Call->getNextNode(); 25680b57cec5SDimitry Andric assert(InsertBefore); 2569bdd1243dSDimitry Andric Instruction *RematerializedValue = 2570bdd1243dSDimitry Andric rematerializeChain(Record.ChainToBase, InsertBefore, 2571bdd1243dSDimitry Andric Record.RootOfChain, PointerToBase[LiveValue]); 25720b57cec5SDimitry Andric Info.RematerializedValues[RematerializedValue] = LiveValue; 25730b57cec5SDimitry Andric } else { 25740b57cec5SDimitry Andric auto *Invoke = cast<InvokeInst>(Call); 25750b57cec5SDimitry Andric 25760b57cec5SDimitry Andric Instruction *NormalInsertBefore = 25770b57cec5SDimitry Andric &*Invoke->getNormalDest()->getFirstInsertionPt(); 25780b57cec5SDimitry Andric Instruction *UnwindInsertBefore = 25790b57cec5SDimitry Andric &*Invoke->getUnwindDest()->getFirstInsertionPt(); 25800b57cec5SDimitry Andric 2581bdd1243dSDimitry Andric Instruction *NormalRematerializedValue = 2582bdd1243dSDimitry Andric rematerializeChain(Record.ChainToBase, NormalInsertBefore, 2583bdd1243dSDimitry Andric Record.RootOfChain, PointerToBase[LiveValue]); 2584bdd1243dSDimitry Andric Instruction *UnwindRematerializedValue = 2585bdd1243dSDimitry Andric rematerializeChain(Record.ChainToBase, UnwindInsertBefore, 2586bdd1243dSDimitry Andric Record.RootOfChain, PointerToBase[LiveValue]); 25870b57cec5SDimitry Andric 25880b57cec5SDimitry Andric Info.RematerializedValues[NormalRematerializedValue] = LiveValue; 25890b57cec5SDimitry Andric Info.RematerializedValues[UnwindRematerializedValue] = LiveValue; 25900b57cec5SDimitry Andric } 25910b57cec5SDimitry Andric } 25920b57cec5SDimitry Andric 2593bdd1243dSDimitry Andric // Remove rematerialized values from the live set. 2594bdd1243dSDimitry Andric for (auto *LiveValue: LiveValuesToBeDeleted) { 25950b57cec5SDimitry Andric Info.LiveSet.remove(LiveValue); 25960b57cec5SDimitry Andric } 25970b57cec5SDimitry Andric } 25980b57cec5SDimitry Andric 2599fe6060f1SDimitry Andric static bool inlineGetBaseAndOffset(Function &F, 2600fe6060f1SDimitry Andric SmallVectorImpl<CallInst *> &Intrinsics, 260181ad6265SDimitry Andric DefiningValueMapTy &DVCache, 260281ad6265SDimitry Andric IsKnownBaseMapTy &KnownBases) { 2603fe6060f1SDimitry Andric auto &Context = F.getContext(); 2604*0fca6ea1SDimitry Andric auto &DL = F.getDataLayout(); 2605fe6060f1SDimitry Andric bool Changed = false; 2606fe6060f1SDimitry Andric 2607fe6060f1SDimitry Andric for (auto *Callsite : Intrinsics) 2608fe6060f1SDimitry Andric switch (Callsite->getIntrinsicID()) { 2609fe6060f1SDimitry Andric case Intrinsic::experimental_gc_get_pointer_base: { 2610fe6060f1SDimitry Andric Changed = true; 261181ad6265SDimitry Andric Value *Base = 261281ad6265SDimitry Andric findBasePointer(Callsite->getOperand(0), DVCache, KnownBases); 2613fe6060f1SDimitry Andric assert(!DVCache.count(Callsite)); 2614297eecfbSDimitry Andric Callsite->replaceAllUsesWith(Base); 2615297eecfbSDimitry Andric if (!Base->hasName()) 2616297eecfbSDimitry Andric Base->takeName(Callsite); 2617fe6060f1SDimitry Andric Callsite->eraseFromParent(); 2618fe6060f1SDimitry Andric break; 2619fe6060f1SDimitry Andric } 2620fe6060f1SDimitry Andric case Intrinsic::experimental_gc_get_pointer_offset: { 2621fe6060f1SDimitry Andric Changed = true; 2622fe6060f1SDimitry Andric Value *Derived = Callsite->getOperand(0); 262381ad6265SDimitry Andric Value *Base = findBasePointer(Derived, DVCache, KnownBases); 2624fe6060f1SDimitry Andric assert(!DVCache.count(Callsite)); 2625fe6060f1SDimitry Andric unsigned AddressSpace = Derived->getType()->getPointerAddressSpace(); 2626fe6060f1SDimitry Andric unsigned IntPtrSize = DL.getPointerSizeInBits(AddressSpace); 2627fe6060f1SDimitry Andric IRBuilder<> Builder(Callsite); 2628fe6060f1SDimitry Andric Value *BaseInt = 2629fe6060f1SDimitry Andric Builder.CreatePtrToInt(Base, Type::getIntNTy(Context, IntPtrSize), 2630fe6060f1SDimitry Andric suffixed_name_or(Base, ".int", "")); 2631fe6060f1SDimitry Andric Value *DerivedInt = 2632fe6060f1SDimitry Andric Builder.CreatePtrToInt(Derived, Type::getIntNTy(Context, IntPtrSize), 2633fe6060f1SDimitry Andric suffixed_name_or(Derived, ".int", "")); 2634fe6060f1SDimitry Andric Value *Offset = Builder.CreateSub(DerivedInt, BaseInt); 2635fe6060f1SDimitry Andric Callsite->replaceAllUsesWith(Offset); 2636fe6060f1SDimitry Andric Offset->takeName(Callsite); 2637fe6060f1SDimitry Andric Callsite->eraseFromParent(); 2638fe6060f1SDimitry Andric break; 2639fe6060f1SDimitry Andric } 2640fe6060f1SDimitry Andric default: 2641fe6060f1SDimitry Andric llvm_unreachable("Unknown intrinsic"); 2642fe6060f1SDimitry Andric } 2643fe6060f1SDimitry Andric 2644fe6060f1SDimitry Andric return Changed; 2645fe6060f1SDimitry Andric } 2646fe6060f1SDimitry Andric 26470b57cec5SDimitry Andric static bool insertParsePoints(Function &F, DominatorTree &DT, 26480b57cec5SDimitry Andric TargetTransformInfo &TTI, 2649fe6060f1SDimitry Andric SmallVectorImpl<CallBase *> &ToUpdate, 265081ad6265SDimitry Andric DefiningValueMapTy &DVCache, 265181ad6265SDimitry Andric IsKnownBaseMapTy &KnownBases) { 265206c3fb27SDimitry Andric std::unique_ptr<GCStrategy> GC = findGCStrategy(F); 265306c3fb27SDimitry Andric 26540b57cec5SDimitry Andric #ifndef NDEBUG 2655349cc55cSDimitry Andric // Validate the input 26560b57cec5SDimitry Andric std::set<CallBase *> Uniqued; 26570b57cec5SDimitry Andric Uniqued.insert(ToUpdate.begin(), ToUpdate.end()); 26580b57cec5SDimitry Andric assert(Uniqued.size() == ToUpdate.size() && "no duplicates please!"); 26590b57cec5SDimitry Andric 26600b57cec5SDimitry Andric for (CallBase *Call : ToUpdate) 26610b57cec5SDimitry Andric assert(Call->getFunction() == &F); 26620b57cec5SDimitry Andric #endif 26630b57cec5SDimitry Andric 26640b57cec5SDimitry Andric // When inserting gc.relocates for invokes, we need to be able to insert at 26650b57cec5SDimitry Andric // the top of the successor blocks. See the comment on 26660b57cec5SDimitry Andric // normalForInvokeSafepoint on exactly what is needed. Note that this step 26670b57cec5SDimitry Andric // may restructure the CFG. 26680b57cec5SDimitry Andric for (CallBase *Call : ToUpdate) { 26690b57cec5SDimitry Andric auto *II = dyn_cast<InvokeInst>(Call); 26700b57cec5SDimitry Andric if (!II) 26710b57cec5SDimitry Andric continue; 26720b57cec5SDimitry Andric normalizeForInvokeSafepoint(II->getNormalDest(), II->getParent(), DT); 26730b57cec5SDimitry Andric normalizeForInvokeSafepoint(II->getUnwindDest(), II->getParent(), DT); 26740b57cec5SDimitry Andric } 26750b57cec5SDimitry Andric 26760b57cec5SDimitry Andric // A list of dummy calls added to the IR to keep various values obviously 26770b57cec5SDimitry Andric // live in the IR. We'll remove all of these when done. 26780b57cec5SDimitry Andric SmallVector<CallInst *, 64> Holders; 26790b57cec5SDimitry Andric 26800b57cec5SDimitry Andric // Insert a dummy call with all of the deopt operands we'll need for the 26810b57cec5SDimitry Andric // actual safepoint insertion as arguments. This ensures reference operands 26820b57cec5SDimitry Andric // in the deopt argument list are considered live through the safepoint (and 26830b57cec5SDimitry Andric // thus makes sure they get relocated.) 26840b57cec5SDimitry Andric for (CallBase *Call : ToUpdate) { 26850b57cec5SDimitry Andric SmallVector<Value *, 64> DeoptValues; 26860b57cec5SDimitry Andric 26870b57cec5SDimitry Andric for (Value *Arg : GetDeoptBundleOperands(Call)) { 268806c3fb27SDimitry Andric assert(!isUnhandledGCPointerType(Arg->getType(), GC.get()) && 26890b57cec5SDimitry Andric "support for FCA unimplemented"); 269006c3fb27SDimitry Andric if (isHandledGCPointerType(Arg->getType(), GC.get())) 26910b57cec5SDimitry Andric DeoptValues.push_back(Arg); 26920b57cec5SDimitry Andric } 26930b57cec5SDimitry Andric 26940b57cec5SDimitry Andric insertUseHolderAfter(Call, DeoptValues, Holders); 26950b57cec5SDimitry Andric } 26960b57cec5SDimitry Andric 26970b57cec5SDimitry Andric SmallVector<PartiallyConstructedSafepointRecord, 64> Records(ToUpdate.size()); 26980b57cec5SDimitry Andric 26990b57cec5SDimitry Andric // A) Identify all gc pointers which are statically live at the given call 27000b57cec5SDimitry Andric // site. 270106c3fb27SDimitry Andric findLiveReferences(F, DT, ToUpdate, Records, GC.get()); 27020b57cec5SDimitry Andric 27031fd87a68SDimitry Andric /// Global mapping from live pointers to a base-defining-value. 27041fd87a68SDimitry Andric PointerToBaseTy PointerToBase; 27051fd87a68SDimitry Andric 27060b57cec5SDimitry Andric // B) Find the base pointers for each live pointer 27070b57cec5SDimitry Andric for (size_t i = 0; i < Records.size(); i++) { 27080b57cec5SDimitry Andric PartiallyConstructedSafepointRecord &info = Records[i]; 270981ad6265SDimitry Andric findBasePointers(DT, DVCache, ToUpdate[i], info, PointerToBase, KnownBases); 27101fd87a68SDimitry Andric } 27111fd87a68SDimitry Andric if (PrintBasePointers) { 27121fd87a68SDimitry Andric errs() << "Base Pairs (w/o Relocation):\n"; 27131fd87a68SDimitry Andric for (auto &Pair : PointerToBase) { 27141fd87a68SDimitry Andric errs() << " derived "; 27151fd87a68SDimitry Andric Pair.first->printAsOperand(errs(), false); 27161fd87a68SDimitry Andric errs() << " base "; 27171fd87a68SDimitry Andric Pair.second->printAsOperand(errs(), false); 27181fd87a68SDimitry Andric errs() << "\n"; 27191fd87a68SDimitry Andric ; 27201fd87a68SDimitry Andric } 27210b57cec5SDimitry Andric } 27220b57cec5SDimitry Andric 27230b57cec5SDimitry Andric // The base phi insertion logic (for any safepoint) may have inserted new 27240b57cec5SDimitry Andric // instructions which are now live at some safepoint. The simplest such 27250b57cec5SDimitry Andric // example is: 27260b57cec5SDimitry Andric // loop: 27270b57cec5SDimitry Andric // phi a <-- will be a new base_phi here 27280b57cec5SDimitry Andric // safepoint 1 <-- that needs to be live here 27290b57cec5SDimitry Andric // gep a + 1 27300b57cec5SDimitry Andric // safepoint 2 27310b57cec5SDimitry Andric // br loop 27320b57cec5SDimitry Andric // We insert some dummy calls after each safepoint to definitely hold live 27330b57cec5SDimitry Andric // the base pointers which were identified for that safepoint. We'll then 27340b57cec5SDimitry Andric // ask liveness for _every_ base inserted to see what is now live. Then we 27350b57cec5SDimitry Andric // remove the dummy calls. 27360b57cec5SDimitry Andric Holders.reserve(Holders.size() + Records.size()); 27370b57cec5SDimitry Andric for (size_t i = 0; i < Records.size(); i++) { 27380b57cec5SDimitry Andric PartiallyConstructedSafepointRecord &Info = Records[i]; 27390b57cec5SDimitry Andric 27400b57cec5SDimitry Andric SmallVector<Value *, 128> Bases; 27411fd87a68SDimitry Andric for (auto *Derived : Info.LiveSet) { 27421fd87a68SDimitry Andric assert(PointerToBase.count(Derived) && "Missed base for derived pointer"); 27431fd87a68SDimitry Andric Bases.push_back(PointerToBase[Derived]); 27441fd87a68SDimitry Andric } 27450b57cec5SDimitry Andric 27460b57cec5SDimitry Andric insertUseHolderAfter(ToUpdate[i], Bases, Holders); 27470b57cec5SDimitry Andric } 27480b57cec5SDimitry Andric 27490b57cec5SDimitry Andric // By selecting base pointers, we've effectively inserted new uses. Thus, we 27500b57cec5SDimitry Andric // need to rerun liveness. We may *also* have inserted new defs, but that's 27510b57cec5SDimitry Andric // not the key issue. 275206c3fb27SDimitry Andric recomputeLiveInValues(F, DT, ToUpdate, Records, PointerToBase, GC.get()); 27530b57cec5SDimitry Andric 27540b57cec5SDimitry Andric if (PrintBasePointers) { 27550b57cec5SDimitry Andric errs() << "Base Pairs: (w/Relocation)\n"; 27561fd87a68SDimitry Andric for (auto Pair : PointerToBase) { 27570b57cec5SDimitry Andric errs() << " derived "; 27580b57cec5SDimitry Andric Pair.first->printAsOperand(errs(), false); 27590b57cec5SDimitry Andric errs() << " base "; 27600b57cec5SDimitry Andric Pair.second->printAsOperand(errs(), false); 27610b57cec5SDimitry Andric errs() << "\n"; 27620b57cec5SDimitry Andric } 27630b57cec5SDimitry Andric } 27640b57cec5SDimitry Andric 27650b57cec5SDimitry Andric // It is possible that non-constant live variables have a constant base. For 27660b57cec5SDimitry Andric // example, a GEP with a variable offset from a global. In this case we can 27670b57cec5SDimitry Andric // remove it from the liveset. We already don't add constants to the liveset 27680b57cec5SDimitry Andric // because we assume they won't move at runtime and the GC doesn't need to be 27690b57cec5SDimitry Andric // informed about them. The same reasoning applies if the base is constant. 27700b57cec5SDimitry Andric // Note that the relocation placement code relies on this filtering for 27710b57cec5SDimitry Andric // correctness as it expects the base to be in the liveset, which isn't true 27720b57cec5SDimitry Andric // if the base is constant. 27731fd87a68SDimitry Andric for (auto &Info : Records) { 27741fd87a68SDimitry Andric Info.LiveSet.remove_if([&](Value *LiveV) { 27751fd87a68SDimitry Andric assert(PointerToBase.count(LiveV) && "Missed base for derived pointer"); 27761fd87a68SDimitry Andric return isa<Constant>(PointerToBase[LiveV]); 27771fd87a68SDimitry Andric }); 27781fd87a68SDimitry Andric } 27790b57cec5SDimitry Andric 27800b57cec5SDimitry Andric for (CallInst *CI : Holders) 27810b57cec5SDimitry Andric CI->eraseFromParent(); 27820b57cec5SDimitry Andric 27830b57cec5SDimitry Andric Holders.clear(); 27840b57cec5SDimitry Andric 278581ad6265SDimitry Andric // Compute the cost of possible re-materialization of derived pointers. 278681ad6265SDimitry Andric RematCandTy RematerizationCandidates; 278781ad6265SDimitry Andric findRematerializationCandidates(PointerToBase, RematerizationCandidates, TTI); 278881ad6265SDimitry Andric 27890b57cec5SDimitry Andric // In order to reduce live set of statepoint we might choose to rematerialize 27900b57cec5SDimitry Andric // some values instead of relocating them. This is purely an optimization and 27910b57cec5SDimitry Andric // does not influence correctness. 2792bdd1243dSDimitry Andric // First try rematerialization at uses, then after statepoints. 2793bdd1243dSDimitry Andric rematerializeLiveValuesAtUses(RematerizationCandidates, Records, 2794bdd1243dSDimitry Andric PointerToBase); 27950b57cec5SDimitry Andric for (size_t i = 0; i < Records.size(); i++) 279681ad6265SDimitry Andric rematerializeLiveValues(ToUpdate[i], Records[i], PointerToBase, 279781ad6265SDimitry Andric RematerizationCandidates, TTI); 27980b57cec5SDimitry Andric 27990b57cec5SDimitry Andric // We need this to safely RAUW and delete call or invoke return values that 28000b57cec5SDimitry Andric // may themselves be live over a statepoint. For details, please see usage in 28010b57cec5SDimitry Andric // makeStatepointExplicitImpl. 28020b57cec5SDimitry Andric std::vector<DeferredReplacement> Replacements; 28030b57cec5SDimitry Andric 28040b57cec5SDimitry Andric // Now run through and replace the existing statepoints with new ones with 28050b57cec5SDimitry Andric // the live variables listed. We do not yet update uses of the values being 28060b57cec5SDimitry Andric // relocated. We have references to live variables that need to 28070b57cec5SDimitry Andric // survive to the last iteration of this loop. (By construction, the 28080b57cec5SDimitry Andric // previous statepoint can not be a live variable, thus we can and remove 28090b57cec5SDimitry Andric // the old statepoint calls as we go.) 28100b57cec5SDimitry Andric for (size_t i = 0; i < Records.size(); i++) 28111fd87a68SDimitry Andric makeStatepointExplicit(DT, ToUpdate[i], Records[i], Replacements, 281206c3fb27SDimitry Andric PointerToBase, GC.get()); 28130b57cec5SDimitry Andric 28140b57cec5SDimitry Andric ToUpdate.clear(); // prevent accident use of invalid calls. 28150b57cec5SDimitry Andric 28160b57cec5SDimitry Andric for (auto &PR : Replacements) 28170b57cec5SDimitry Andric PR.doReplacement(); 28180b57cec5SDimitry Andric 28190b57cec5SDimitry Andric Replacements.clear(); 28200b57cec5SDimitry Andric 28210b57cec5SDimitry Andric for (auto &Info : Records) { 28220b57cec5SDimitry Andric // These live sets may contain state Value pointers, since we replaced calls 28230b57cec5SDimitry Andric // with operand bundles with calls wrapped in gc.statepoint, and some of 28240b57cec5SDimitry Andric // those calls may have been def'ing live gc pointers. Clear these out to 28250b57cec5SDimitry Andric // avoid accidentally using them. 28260b57cec5SDimitry Andric // 28270b57cec5SDimitry Andric // TODO: We should create a separate data structure that does not contain 28280b57cec5SDimitry Andric // these live sets, and migrate to using that data structure from this point 28290b57cec5SDimitry Andric // onward. 28300b57cec5SDimitry Andric Info.LiveSet.clear(); 28310b57cec5SDimitry Andric } 28321fd87a68SDimitry Andric PointerToBase.clear(); 28330b57cec5SDimitry Andric 28340b57cec5SDimitry Andric // Do all the fixups of the original live variables to their relocated selves 28350b57cec5SDimitry Andric SmallVector<Value *, 128> Live; 283606c3fb27SDimitry Andric for (const PartiallyConstructedSafepointRecord &Info : Records) { 28370b57cec5SDimitry Andric // We can't simply save the live set from the original insertion. One of 28380b57cec5SDimitry Andric // the live values might be the result of a call which needs a safepoint. 28390b57cec5SDimitry Andric // That Value* no longer exists and we need to use the new gc_result. 28400b57cec5SDimitry Andric // Thankfully, the live set is embedded in the statepoint (and updated), so 28410b57cec5SDimitry Andric // we just grab that. 2842e8d8bef9SDimitry Andric llvm::append_range(Live, Info.StatepointToken->gc_args()); 28430b57cec5SDimitry Andric #ifndef NDEBUG 2844349cc55cSDimitry Andric // Do some basic validation checking on our liveness results before 2845349cc55cSDimitry Andric // performing relocation. Relocation can and will turn mistakes in liveness 2846349cc55cSDimitry Andric // results into non-sensical code which is must harder to debug. 28470b57cec5SDimitry Andric // TODO: It would be nice to test consistency as well 28480b57cec5SDimitry Andric assert(DT.isReachableFromEntry(Info.StatepointToken->getParent()) && 28490b57cec5SDimitry Andric "statepoint must be reachable or liveness is meaningless"); 28505ffd83dbSDimitry Andric for (Value *V : Info.StatepointToken->gc_args()) { 28510b57cec5SDimitry Andric if (!isa<Instruction>(V)) 28520b57cec5SDimitry Andric // Non-instruction values trivial dominate all possible uses 28530b57cec5SDimitry Andric continue; 28540b57cec5SDimitry Andric auto *LiveInst = cast<Instruction>(V); 28550b57cec5SDimitry Andric assert(DT.isReachableFromEntry(LiveInst->getParent()) && 28560b57cec5SDimitry Andric "unreachable values should never be live"); 28570b57cec5SDimitry Andric assert(DT.dominates(LiveInst, Info.StatepointToken) && 28580b57cec5SDimitry Andric "basic SSA liveness expectation violated by liveness analysis"); 28590b57cec5SDimitry Andric } 28600b57cec5SDimitry Andric #endif 28610b57cec5SDimitry Andric } 28620b57cec5SDimitry Andric unique_unsorted(Live); 28630b57cec5SDimitry Andric 28640b57cec5SDimitry Andric #ifndef NDEBUG 2865349cc55cSDimitry Andric // Validation check 28660b57cec5SDimitry Andric for (auto *Ptr : Live) 286706c3fb27SDimitry Andric assert(isHandledGCPointerType(Ptr->getType(), GC.get()) && 28680b57cec5SDimitry Andric "must be a gc pointer type"); 28690b57cec5SDimitry Andric #endif 28700b57cec5SDimitry Andric 28710b57cec5SDimitry Andric relocationViaAlloca(F, DT, Live, Records); 28720b57cec5SDimitry Andric return !Records.empty(); 28730b57cec5SDimitry Andric } 28740b57cec5SDimitry Andric 28750eae32dcSDimitry Andric // List of all parameter and return attributes which must be stripped when 28760eae32dcSDimitry Andric // lowering from the abstract machine model. Note that we list attributes 28770eae32dcSDimitry Andric // here which aren't valid as return attributes, that is okay. 287804eeddc0SDimitry Andric static AttributeMask getParamAndReturnAttributesToRemove() { 287904eeddc0SDimitry Andric AttributeMask R; 288004eeddc0SDimitry Andric R.addAttribute(Attribute::Dereferenceable); 288104eeddc0SDimitry Andric R.addAttribute(Attribute::DereferenceableOrNull); 28820eae32dcSDimitry Andric R.addAttribute(Attribute::ReadNone); 28830eae32dcSDimitry Andric R.addAttribute(Attribute::ReadOnly); 28840eae32dcSDimitry Andric R.addAttribute(Attribute::WriteOnly); 28850eae32dcSDimitry Andric R.addAttribute(Attribute::NoAlias); 28860eae32dcSDimitry Andric R.addAttribute(Attribute::NoFree); 28870eae32dcSDimitry Andric return R; 28880b57cec5SDimitry Andric } 28890b57cec5SDimitry Andric 28900b57cec5SDimitry Andric static void stripNonValidAttributesFromPrototype(Function &F) { 28910b57cec5SDimitry Andric LLVMContext &Ctx = F.getContext(); 28920b57cec5SDimitry Andric 2893fe6060f1SDimitry Andric // Intrinsics are very delicate. Lowering sometimes depends the presence 2894fe6060f1SDimitry Andric // of certain attributes for correctness, but we may have also inferred 2895fe6060f1SDimitry Andric // additional ones in the abstract machine model which need stripped. This 2896fe6060f1SDimitry Andric // assumes that the attributes defined in Intrinsic.td are conservatively 2897fe6060f1SDimitry Andric // correct for both physical and abstract model. 2898fe6060f1SDimitry Andric if (Intrinsic::ID id = F.getIntrinsicID()) { 2899fe6060f1SDimitry Andric F.setAttributes(Intrinsic::getAttributes(Ctx, id)); 2900fe6060f1SDimitry Andric return; 2901fe6060f1SDimitry Andric } 2902fe6060f1SDimitry Andric 290304eeddc0SDimitry Andric AttributeMask R = getParamAndReturnAttributesToRemove(); 29040b57cec5SDimitry Andric for (Argument &A : F.args()) 29050b57cec5SDimitry Andric if (isa<PointerType>(A.getType())) 29060eae32dcSDimitry Andric F.removeParamAttrs(A.getArgNo(), R); 29070b57cec5SDimitry Andric 29080b57cec5SDimitry Andric if (isa<PointerType>(F.getReturnType())) 29090eae32dcSDimitry Andric F.removeRetAttrs(R); 2910fe6060f1SDimitry Andric 2911fe6060f1SDimitry Andric for (auto Attr : FnAttrsToStrip) 2912fe6060f1SDimitry Andric F.removeFnAttr(Attr); 29130b57cec5SDimitry Andric } 29140b57cec5SDimitry Andric 29150b57cec5SDimitry Andric /// Certain metadata on instructions are invalid after running RS4GC. 29160b57cec5SDimitry Andric /// Optimizations that run after RS4GC can incorrectly use this metadata to 29170b57cec5SDimitry Andric /// optimize functions. We drop such metadata on the instruction. 29180b57cec5SDimitry Andric static void stripInvalidMetadataFromInstruction(Instruction &I) { 29190b57cec5SDimitry Andric if (!isa<LoadInst>(I) && !isa<StoreInst>(I)) 29200b57cec5SDimitry Andric return; 29210b57cec5SDimitry Andric // These are the attributes that are still valid on loads and stores after 29220b57cec5SDimitry Andric // RS4GC. 29230b57cec5SDimitry Andric // The metadata implying dereferenceability and noalias are (conservatively) 29240b57cec5SDimitry Andric // dropped. This is because semantically, after RewriteStatepointsForGC runs, 29250b57cec5SDimitry Andric // all calls to gc.statepoint "free" the entire heap. Also, gc.statepoint can 29260b57cec5SDimitry Andric // touch the entire heap including noalias objects. Note: The reasoning is 29270b57cec5SDimitry Andric // same as stripping the dereferenceability and noalias attributes that are 29280b57cec5SDimitry Andric // analogous to the metadata counterparts. 29290b57cec5SDimitry Andric // We also drop the invariant.load metadata on the load because that metadata 29300b57cec5SDimitry Andric // implies the address operand to the load points to memory that is never 29310b57cec5SDimitry Andric // changed once it became dereferenceable. This is no longer true after RS4GC. 29320b57cec5SDimitry Andric // Similar reasoning applies to invariant.group metadata, which applies to 29330b57cec5SDimitry Andric // loads within a group. 29340b57cec5SDimitry Andric unsigned ValidMetadataAfterRS4GC[] = {LLVMContext::MD_tbaa, 29350b57cec5SDimitry Andric LLVMContext::MD_range, 29360b57cec5SDimitry Andric LLVMContext::MD_alias_scope, 29370b57cec5SDimitry Andric LLVMContext::MD_nontemporal, 29380b57cec5SDimitry Andric LLVMContext::MD_nonnull, 29390b57cec5SDimitry Andric LLVMContext::MD_align, 29400b57cec5SDimitry Andric LLVMContext::MD_type}; 29410b57cec5SDimitry Andric 29420b57cec5SDimitry Andric // Drops all metadata on the instruction other than ValidMetadataAfterRS4GC. 29430b57cec5SDimitry Andric I.dropUnknownNonDebugMetadata(ValidMetadataAfterRS4GC); 29440b57cec5SDimitry Andric } 29450b57cec5SDimitry Andric 29460b57cec5SDimitry Andric static void stripNonValidDataFromBody(Function &F) { 29470b57cec5SDimitry Andric if (F.empty()) 29480b57cec5SDimitry Andric return; 29490b57cec5SDimitry Andric 29500b57cec5SDimitry Andric LLVMContext &Ctx = F.getContext(); 29510b57cec5SDimitry Andric MDBuilder Builder(Ctx); 29520b57cec5SDimitry Andric 29530b57cec5SDimitry Andric // Set of invariantstart instructions that we need to remove. 29540b57cec5SDimitry Andric // Use this to avoid invalidating the instruction iterator. 29550b57cec5SDimitry Andric SmallVector<IntrinsicInst*, 12> InvariantStartInstructions; 29560b57cec5SDimitry Andric 29570b57cec5SDimitry Andric for (Instruction &I : instructions(F)) { 29580b57cec5SDimitry Andric // invariant.start on memory location implies that the referenced memory 29590b57cec5SDimitry Andric // location is constant and unchanging. This is no longer true after 29600b57cec5SDimitry Andric // RewriteStatepointsForGC runs because there can be calls to gc.statepoint 29610b57cec5SDimitry Andric // which frees the entire heap and the presence of invariant.start allows 29620b57cec5SDimitry Andric // the optimizer to sink the load of a memory location past a statepoint, 29630b57cec5SDimitry Andric // which is incorrect. 29640b57cec5SDimitry Andric if (auto *II = dyn_cast<IntrinsicInst>(&I)) 29650b57cec5SDimitry Andric if (II->getIntrinsicID() == Intrinsic::invariant_start) { 29660b57cec5SDimitry Andric InvariantStartInstructions.push_back(II); 29670b57cec5SDimitry Andric continue; 29680b57cec5SDimitry Andric } 29690b57cec5SDimitry Andric 29700b57cec5SDimitry Andric if (MDNode *Tag = I.getMetadata(LLVMContext::MD_tbaa)) { 29710b57cec5SDimitry Andric MDNode *MutableTBAA = Builder.createMutableTBAAAccessTag(Tag); 29720b57cec5SDimitry Andric I.setMetadata(LLVMContext::MD_tbaa, MutableTBAA); 29730b57cec5SDimitry Andric } 29740b57cec5SDimitry Andric 29750b57cec5SDimitry Andric stripInvalidMetadataFromInstruction(I); 29760b57cec5SDimitry Andric 297704eeddc0SDimitry Andric AttributeMask R = getParamAndReturnAttributesToRemove(); 29780b57cec5SDimitry Andric if (auto *Call = dyn_cast<CallBase>(&I)) { 29790b57cec5SDimitry Andric for (int i = 0, e = Call->arg_size(); i != e; i++) 29800b57cec5SDimitry Andric if (isa<PointerType>(Call->getArgOperand(i)->getType())) 29810eae32dcSDimitry Andric Call->removeParamAttrs(i, R); 29820b57cec5SDimitry Andric if (isa<PointerType>(Call->getType())) 29830eae32dcSDimitry Andric Call->removeRetAttrs(R); 29840b57cec5SDimitry Andric } 29850b57cec5SDimitry Andric } 29860b57cec5SDimitry Andric 298706c3fb27SDimitry Andric // Delete the invariant.start instructions and RAUW poison. 29880b57cec5SDimitry Andric for (auto *II : InvariantStartInstructions) { 298906c3fb27SDimitry Andric II->replaceAllUsesWith(PoisonValue::get(II->getType())); 29900b57cec5SDimitry Andric II->eraseFromParent(); 29910b57cec5SDimitry Andric } 29920b57cec5SDimitry Andric } 29930b57cec5SDimitry Andric 299406c3fb27SDimitry Andric /// Looks up the GC strategy for a given function, returning null if the 299506c3fb27SDimitry Andric /// function doesn't have a GC tag. The strategy is stored in the cache. 299606c3fb27SDimitry Andric static std::unique_ptr<GCStrategy> findGCStrategy(Function &F) { 299706c3fb27SDimitry Andric if (!F.hasGC()) 299806c3fb27SDimitry Andric return nullptr; 299906c3fb27SDimitry Andric 300006c3fb27SDimitry Andric return getGCStrategy(F.getGC()); 300106c3fb27SDimitry Andric } 300206c3fb27SDimitry Andric 30030b57cec5SDimitry Andric /// Returns true if this function should be rewritten by this pass. The main 30040b57cec5SDimitry Andric /// point of this function is as an extension point for custom logic. 30050b57cec5SDimitry Andric static bool shouldRewriteStatepointsIn(Function &F) { 300606c3fb27SDimitry Andric if (!F.hasGC()) 30070b57cec5SDimitry Andric return false; 300806c3fb27SDimitry Andric 300906c3fb27SDimitry Andric std::unique_ptr<GCStrategy> Strategy = findGCStrategy(F); 301006c3fb27SDimitry Andric 301106c3fb27SDimitry Andric assert(Strategy && "GC strategy is required by function, but was not found"); 301206c3fb27SDimitry Andric 301306c3fb27SDimitry Andric return Strategy->useRS4GC(); 30140b57cec5SDimitry Andric } 30150b57cec5SDimitry Andric 30160b57cec5SDimitry Andric static void stripNonValidData(Module &M) { 30170b57cec5SDimitry Andric #ifndef NDEBUG 30180b57cec5SDimitry Andric assert(llvm::any_of(M, shouldRewriteStatepointsIn) && "precondition!"); 30190b57cec5SDimitry Andric #endif 30200b57cec5SDimitry Andric 30210b57cec5SDimitry Andric for (Function &F : M) 30220b57cec5SDimitry Andric stripNonValidAttributesFromPrototype(F); 30230b57cec5SDimitry Andric 30240b57cec5SDimitry Andric for (Function &F : M) 30250b57cec5SDimitry Andric stripNonValidDataFromBody(F); 30260b57cec5SDimitry Andric } 30270b57cec5SDimitry Andric 30280b57cec5SDimitry Andric bool RewriteStatepointsForGC::runOnFunction(Function &F, DominatorTree &DT, 30290b57cec5SDimitry Andric TargetTransformInfo &TTI, 30300b57cec5SDimitry Andric const TargetLibraryInfo &TLI) { 30310b57cec5SDimitry Andric assert(!F.isDeclaration() && !F.empty() && 30320b57cec5SDimitry Andric "need function body to rewrite statepoints in"); 30330b57cec5SDimitry Andric assert(shouldRewriteStatepointsIn(F) && "mismatch in rewrite decision"); 30340b57cec5SDimitry Andric 30350b57cec5SDimitry Andric auto NeedsRewrite = [&TLI](Instruction &I) { 3036e8d8bef9SDimitry Andric if (const auto *Call = dyn_cast<CallBase>(&I)) { 3037e8d8bef9SDimitry Andric if (isa<GCStatepointInst>(Call)) 3038e8d8bef9SDimitry Andric return false; 3039e8d8bef9SDimitry Andric if (callsGCLeafFunction(Call, TLI)) 3040e8d8bef9SDimitry Andric return false; 3041e8d8bef9SDimitry Andric 3042e8d8bef9SDimitry Andric // Normally it's up to the frontend to make sure that non-leaf calls also 3043e8d8bef9SDimitry Andric // have proper deopt state if it is required. We make an exception for 3044e8d8bef9SDimitry Andric // element atomic memcpy/memmove intrinsics here. Unlike other intrinsics 3045e8d8bef9SDimitry Andric // these are non-leaf by default. They might be generated by the optimizer 3046e8d8bef9SDimitry Andric // which doesn't know how to produce a proper deopt state. So if we see a 3047e8d8bef9SDimitry Andric // non-leaf memcpy/memmove without deopt state just treat it as a leaf 3048e8d8bef9SDimitry Andric // copy and don't produce a statepoint. 3049*0fca6ea1SDimitry Andric if (!AllowStatepointWithNoDeoptInfo && !Call->hasDeoptState()) { 3050e8d8bef9SDimitry Andric assert((isa<AtomicMemCpyInst>(Call) || isa<AtomicMemMoveInst>(Call)) && 3051e8d8bef9SDimitry Andric "Don't expect any other calls here!"); 3052e8d8bef9SDimitry Andric return false; 3053e8d8bef9SDimitry Andric } 3054e8d8bef9SDimitry Andric return true; 3055e8d8bef9SDimitry Andric } 30560b57cec5SDimitry Andric return false; 30570b57cec5SDimitry Andric }; 30580b57cec5SDimitry Andric 30590b57cec5SDimitry Andric // Delete any unreachable statepoints so that we don't have unrewritten 30600b57cec5SDimitry Andric // statepoints surviving this pass. This makes testing easier and the 30610b57cec5SDimitry Andric // resulting IR less confusing to human readers. 30620b57cec5SDimitry Andric DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy); 30638bcb0991SDimitry Andric bool MadeChange = removeUnreachableBlocks(F, &DTU); 30640b57cec5SDimitry Andric // Flush the Dominator Tree. 30650b57cec5SDimitry Andric DTU.getDomTree(); 30660b57cec5SDimitry Andric 30670b57cec5SDimitry Andric // Gather all the statepoints which need rewritten. Be careful to only 30680b57cec5SDimitry Andric // consider those in reachable code since we need to ask dominance queries 30690b57cec5SDimitry Andric // when rewriting. We'll delete the unreachable ones in a moment. 30700b57cec5SDimitry Andric SmallVector<CallBase *, 64> ParsePointNeeded; 3071fe6060f1SDimitry Andric SmallVector<CallInst *, 64> Intrinsics; 30720b57cec5SDimitry Andric for (Instruction &I : instructions(F)) { 30730b57cec5SDimitry Andric // TODO: only the ones with the flag set! 30740b57cec5SDimitry Andric if (NeedsRewrite(I)) { 30750b57cec5SDimitry Andric // NOTE removeUnreachableBlocks() is stronger than 30760b57cec5SDimitry Andric // DominatorTree::isReachableFromEntry(). In other words 30770b57cec5SDimitry Andric // removeUnreachableBlocks can remove some blocks for which 30780b57cec5SDimitry Andric // isReachableFromEntry() returns true. 30790b57cec5SDimitry Andric assert(DT.isReachableFromEntry(I.getParent()) && 30800b57cec5SDimitry Andric "no unreachable blocks expected"); 30810b57cec5SDimitry Andric ParsePointNeeded.push_back(cast<CallBase>(&I)); 30820b57cec5SDimitry Andric } 3083fe6060f1SDimitry Andric if (auto *CI = dyn_cast<CallInst>(&I)) 3084fe6060f1SDimitry Andric if (CI->getIntrinsicID() == Intrinsic::experimental_gc_get_pointer_base || 3085fe6060f1SDimitry Andric CI->getIntrinsicID() == Intrinsic::experimental_gc_get_pointer_offset) 3086fe6060f1SDimitry Andric Intrinsics.emplace_back(CI); 30870b57cec5SDimitry Andric } 30880b57cec5SDimitry Andric 30890b57cec5SDimitry Andric // Return early if no work to do. 3090fe6060f1SDimitry Andric if (ParsePointNeeded.empty() && Intrinsics.empty()) 30910b57cec5SDimitry Andric return MadeChange; 30920b57cec5SDimitry Andric 30930b57cec5SDimitry Andric // As a prepass, go ahead and aggressively destroy single entry phi nodes. 30940b57cec5SDimitry Andric // These are created by LCSSA. They have the effect of increasing the size 30950b57cec5SDimitry Andric // of liveness sets for no good reason. It may be harder to do this post 30960b57cec5SDimitry Andric // insertion since relocations and base phis can confuse things. 30970b57cec5SDimitry Andric for (BasicBlock &BB : F) 3098e8d8bef9SDimitry Andric if (BB.getUniquePredecessor()) 3099e8d8bef9SDimitry Andric MadeChange |= FoldSingleEntryPHINodes(&BB); 31000b57cec5SDimitry Andric 31010b57cec5SDimitry Andric // Before we start introducing relocations, we want to tweak the IR a bit to 31020b57cec5SDimitry Andric // avoid unfortunate code generation effects. The main example is that we 31030b57cec5SDimitry Andric // want to try to make sure the comparison feeding a branch is after any 31040b57cec5SDimitry Andric // safepoints. Otherwise, we end up with a comparison of pre-relocation 31050b57cec5SDimitry Andric // values feeding a branch after relocation. This is semantically correct, 31060b57cec5SDimitry Andric // but results in extra register pressure since both the pre-relocation and 31070b57cec5SDimitry Andric // post-relocation copies must be available in registers. For code without 31080b57cec5SDimitry Andric // relocations this is handled elsewhere, but teaching the scheduler to 31090b57cec5SDimitry Andric // reverse the transform we're about to do would be slightly complex. 31100b57cec5SDimitry Andric // Note: This may extend the live range of the inputs to the icmp and thus 31110b57cec5SDimitry Andric // increase the liveset of any statepoint we move over. This is profitable 31120b57cec5SDimitry Andric // as long as all statepoints are in rare blocks. If we had in-register 31130b57cec5SDimitry Andric // lowering for live values this would be a much safer transform. 31140b57cec5SDimitry Andric auto getConditionInst = [](Instruction *TI) -> Instruction * { 31150b57cec5SDimitry Andric if (auto *BI = dyn_cast<BranchInst>(TI)) 31160b57cec5SDimitry Andric if (BI->isConditional()) 31170b57cec5SDimitry Andric return dyn_cast<Instruction>(BI->getCondition()); 31180b57cec5SDimitry Andric // TODO: Extend this to handle switches 31190b57cec5SDimitry Andric return nullptr; 31200b57cec5SDimitry Andric }; 31210b57cec5SDimitry Andric for (BasicBlock &BB : F) { 31220b57cec5SDimitry Andric Instruction *TI = BB.getTerminator(); 31230b57cec5SDimitry Andric if (auto *Cond = getConditionInst(TI)) 31240b57cec5SDimitry Andric // TODO: Handle more than just ICmps here. We should be able to move 31250b57cec5SDimitry Andric // most instructions without side effects or memory access. 31260b57cec5SDimitry Andric if (isa<ICmpInst>(Cond) && Cond->hasOneUse()) { 31270b57cec5SDimitry Andric MadeChange = true; 31280b57cec5SDimitry Andric Cond->moveBefore(TI); 31290b57cec5SDimitry Andric } 31300b57cec5SDimitry Andric } 31310b57cec5SDimitry Andric 31320b57cec5SDimitry Andric // Nasty workaround - The base computation code in the main algorithm doesn't 31330b57cec5SDimitry Andric // consider the fact that a GEP can be used to convert a scalar to a vector. 31340b57cec5SDimitry Andric // The right fix for this is to integrate GEPs into the base rewriting 31350b57cec5SDimitry Andric // algorithm properly, this is just a short term workaround to prevent 31360b57cec5SDimitry Andric // crashes by canonicalizing such GEPs into fully vector GEPs. 31370b57cec5SDimitry Andric for (Instruction &I : instructions(F)) { 31380b57cec5SDimitry Andric if (!isa<GetElementPtrInst>(I)) 31390b57cec5SDimitry Andric continue; 31400b57cec5SDimitry Andric 31410b57cec5SDimitry Andric unsigned VF = 0; 31420b57cec5SDimitry Andric for (unsigned i = 0; i < I.getNumOperands(); i++) 31435ffd83dbSDimitry Andric if (auto *OpndVTy = dyn_cast<VectorType>(I.getOperand(i)->getType())) { 31440b57cec5SDimitry Andric assert(VF == 0 || 31455ffd83dbSDimitry Andric VF == cast<FixedVectorType>(OpndVTy)->getNumElements()); 31465ffd83dbSDimitry Andric VF = cast<FixedVectorType>(OpndVTy)->getNumElements(); 31470b57cec5SDimitry Andric } 31480b57cec5SDimitry Andric 31490b57cec5SDimitry Andric // It's the vector to scalar traversal through the pointer operand which 31500b57cec5SDimitry Andric // confuses base pointer rewriting, so limit ourselves to that case. 31510b57cec5SDimitry Andric if (!I.getOperand(0)->getType()->isVectorTy() && VF != 0) { 31520b57cec5SDimitry Andric IRBuilder<> B(&I); 31530b57cec5SDimitry Andric auto *Splat = B.CreateVectorSplat(VF, I.getOperand(0)); 31540b57cec5SDimitry Andric I.setOperand(0, Splat); 31550b57cec5SDimitry Andric MadeChange = true; 31560b57cec5SDimitry Andric } 31570b57cec5SDimitry Andric } 31580b57cec5SDimitry Andric 3159fe6060f1SDimitry Andric // Cache the 'defining value' relation used in the computation and 3160fe6060f1SDimitry Andric // insertion of base phis and selects. This ensures that we don't insert 3161fe6060f1SDimitry Andric // large numbers of duplicate base_phis. Use one cache for both 3162fe6060f1SDimitry Andric // inlineGetBaseAndOffset() and insertParsePoints(). 3163fe6060f1SDimitry Andric DefiningValueMapTy DVCache; 3164fe6060f1SDimitry Andric 316581ad6265SDimitry Andric // Mapping between a base values and a flag indicating whether it's a known 316681ad6265SDimitry Andric // base or not. 316781ad6265SDimitry Andric IsKnownBaseMapTy KnownBases; 316881ad6265SDimitry Andric 3169fe6060f1SDimitry Andric if (!Intrinsics.empty()) 3170fe6060f1SDimitry Andric // Inline @gc.get.pointer.base() and @gc.get.pointer.offset() before finding 3171fe6060f1SDimitry Andric // live references. 317281ad6265SDimitry Andric MadeChange |= inlineGetBaseAndOffset(F, Intrinsics, DVCache, KnownBases); 3173fe6060f1SDimitry Andric 3174fe6060f1SDimitry Andric if (!ParsePointNeeded.empty()) 317581ad6265SDimitry Andric MadeChange |= 317681ad6265SDimitry Andric insertParsePoints(F, DT, TTI, ParsePointNeeded, DVCache, KnownBases); 3177fe6060f1SDimitry Andric 31780b57cec5SDimitry Andric return MadeChange; 31790b57cec5SDimitry Andric } 31800b57cec5SDimitry Andric 31810b57cec5SDimitry Andric // liveness computation via standard dataflow 31820b57cec5SDimitry Andric // ------------------------------------------------------------------- 31830b57cec5SDimitry Andric 31840b57cec5SDimitry Andric // TODO: Consider using bitvectors for liveness, the set of potentially 31850b57cec5SDimitry Andric // interesting values should be small and easy to pre-compute. 31860b57cec5SDimitry Andric 31870b57cec5SDimitry Andric /// Compute the live-in set for the location rbegin starting from 31880b57cec5SDimitry Andric /// the live-out set of the basic block 31890b57cec5SDimitry Andric static void computeLiveInValues(BasicBlock::reverse_iterator Begin, 31900b57cec5SDimitry Andric BasicBlock::reverse_iterator End, 319106c3fb27SDimitry Andric SetVector<Value *> &LiveTmp, GCStrategy *GC) { 31920b57cec5SDimitry Andric for (auto &I : make_range(Begin, End)) { 31930b57cec5SDimitry Andric // KILL/Def - Remove this definition from LiveIn 31940b57cec5SDimitry Andric LiveTmp.remove(&I); 31950b57cec5SDimitry Andric 31960b57cec5SDimitry Andric // Don't consider *uses* in PHI nodes, we handle their contribution to 31970b57cec5SDimitry Andric // predecessor blocks when we seed the LiveOut sets 31980b57cec5SDimitry Andric if (isa<PHINode>(I)) 31990b57cec5SDimitry Andric continue; 32000b57cec5SDimitry Andric 32010b57cec5SDimitry Andric // USE - Add to the LiveIn set for this instruction 32020b57cec5SDimitry Andric for (Value *V : I.operands()) { 320306c3fb27SDimitry Andric assert(!isUnhandledGCPointerType(V->getType(), GC) && 32040b57cec5SDimitry Andric "support for FCA unimplemented"); 320506c3fb27SDimitry Andric if (isHandledGCPointerType(V->getType(), GC) && !isa<Constant>(V)) { 32060b57cec5SDimitry Andric // The choice to exclude all things constant here is slightly subtle. 32070b57cec5SDimitry Andric // There are two independent reasons: 32080b57cec5SDimitry Andric // - We assume that things which are constant (from LLVM's definition) 32090b57cec5SDimitry Andric // do not move at runtime. For example, the address of a global 32100b57cec5SDimitry Andric // variable is fixed, even though it's contents may not be. 32110b57cec5SDimitry Andric // - Second, we can't disallow arbitrary inttoptr constants even 32120b57cec5SDimitry Andric // if the language frontend does. Optimization passes are free to 32130b57cec5SDimitry Andric // locally exploit facts without respect to global reachability. This 32140b57cec5SDimitry Andric // can create sections of code which are dynamically unreachable and 32150b57cec5SDimitry Andric // contain just about anything. (see constants.ll in tests) 32160b57cec5SDimitry Andric LiveTmp.insert(V); 32170b57cec5SDimitry Andric } 32180b57cec5SDimitry Andric } 32190b57cec5SDimitry Andric } 32200b57cec5SDimitry Andric } 32210b57cec5SDimitry Andric 322206c3fb27SDimitry Andric static void computeLiveOutSeed(BasicBlock *BB, SetVector<Value *> &LiveTmp, 322306c3fb27SDimitry Andric GCStrategy *GC) { 32240b57cec5SDimitry Andric for (BasicBlock *Succ : successors(BB)) { 32250b57cec5SDimitry Andric for (auto &I : *Succ) { 32260b57cec5SDimitry Andric PHINode *PN = dyn_cast<PHINode>(&I); 32270b57cec5SDimitry Andric if (!PN) 32280b57cec5SDimitry Andric break; 32290b57cec5SDimitry Andric 32300b57cec5SDimitry Andric Value *V = PN->getIncomingValueForBlock(BB); 323106c3fb27SDimitry Andric assert(!isUnhandledGCPointerType(V->getType(), GC) && 32320b57cec5SDimitry Andric "support for FCA unimplemented"); 323306c3fb27SDimitry Andric if (isHandledGCPointerType(V->getType(), GC) && !isa<Constant>(V)) 32340b57cec5SDimitry Andric LiveTmp.insert(V); 32350b57cec5SDimitry Andric } 32360b57cec5SDimitry Andric } 32370b57cec5SDimitry Andric } 32380b57cec5SDimitry Andric 323906c3fb27SDimitry Andric static SetVector<Value *> computeKillSet(BasicBlock *BB, GCStrategy *GC) { 32400b57cec5SDimitry Andric SetVector<Value *> KillSet; 32410b57cec5SDimitry Andric for (Instruction &I : *BB) 324206c3fb27SDimitry Andric if (isHandledGCPointerType(I.getType(), GC)) 32430b57cec5SDimitry Andric KillSet.insert(&I); 32440b57cec5SDimitry Andric return KillSet; 32450b57cec5SDimitry Andric } 32460b57cec5SDimitry Andric 32470b57cec5SDimitry Andric #ifndef NDEBUG 32480b57cec5SDimitry Andric /// Check that the items in 'Live' dominate 'TI'. This is used as a basic 3249349cc55cSDimitry Andric /// validation check for the liveness computation. 32500b57cec5SDimitry Andric static void checkBasicSSA(DominatorTree &DT, SetVector<Value *> &Live, 32510b57cec5SDimitry Andric Instruction *TI, bool TermOkay = false) { 32520b57cec5SDimitry Andric for (Value *V : Live) { 32530b57cec5SDimitry Andric if (auto *I = dyn_cast<Instruction>(V)) { 32540b57cec5SDimitry Andric // The terminator can be a member of the LiveOut set. LLVM's definition 32550b57cec5SDimitry Andric // of instruction dominance states that V does not dominate itself. As 32560b57cec5SDimitry Andric // such, we need to special case this to allow it. 32570b57cec5SDimitry Andric if (TermOkay && TI == I) 32580b57cec5SDimitry Andric continue; 32590b57cec5SDimitry Andric assert(DT.dominates(I, TI) && 32600b57cec5SDimitry Andric "basic SSA liveness expectation violated by liveness analysis"); 32610b57cec5SDimitry Andric } 32620b57cec5SDimitry Andric } 32630b57cec5SDimitry Andric } 32640b57cec5SDimitry Andric 32650b57cec5SDimitry Andric /// Check that all the liveness sets used during the computation of liveness 32660b57cec5SDimitry Andric /// obey basic SSA properties. This is useful for finding cases where we miss 32670b57cec5SDimitry Andric /// a def. 32680b57cec5SDimitry Andric static void checkBasicSSA(DominatorTree &DT, GCPtrLivenessData &Data, 32690b57cec5SDimitry Andric BasicBlock &BB) { 32700b57cec5SDimitry Andric checkBasicSSA(DT, Data.LiveSet[&BB], BB.getTerminator()); 32710b57cec5SDimitry Andric checkBasicSSA(DT, Data.LiveOut[&BB], BB.getTerminator(), true); 32720b57cec5SDimitry Andric checkBasicSSA(DT, Data.LiveIn[&BB], BB.getTerminator()); 32730b57cec5SDimitry Andric } 32740b57cec5SDimitry Andric #endif 32750b57cec5SDimitry Andric 32760b57cec5SDimitry Andric static void computeLiveInValues(DominatorTree &DT, Function &F, 327706c3fb27SDimitry Andric GCPtrLivenessData &Data, GCStrategy *GC) { 32780b57cec5SDimitry Andric SmallSetVector<BasicBlock *, 32> Worklist; 32790b57cec5SDimitry Andric 32800b57cec5SDimitry Andric // Seed the liveness for each individual block 32810b57cec5SDimitry Andric for (BasicBlock &BB : F) { 328206c3fb27SDimitry Andric Data.KillSet[&BB] = computeKillSet(&BB, GC); 32830b57cec5SDimitry Andric Data.LiveSet[&BB].clear(); 328406c3fb27SDimitry Andric computeLiveInValues(BB.rbegin(), BB.rend(), Data.LiveSet[&BB], GC); 32850b57cec5SDimitry Andric 32860b57cec5SDimitry Andric #ifndef NDEBUG 32870b57cec5SDimitry Andric for (Value *Kill : Data.KillSet[&BB]) 32880b57cec5SDimitry Andric assert(!Data.LiveSet[&BB].count(Kill) && "live set contains kill"); 32890b57cec5SDimitry Andric #endif 32900b57cec5SDimitry Andric 32910b57cec5SDimitry Andric Data.LiveOut[&BB] = SetVector<Value *>(); 329206c3fb27SDimitry Andric computeLiveOutSeed(&BB, Data.LiveOut[&BB], GC); 32930b57cec5SDimitry Andric Data.LiveIn[&BB] = Data.LiveSet[&BB]; 32940b57cec5SDimitry Andric Data.LiveIn[&BB].set_union(Data.LiveOut[&BB]); 32950b57cec5SDimitry Andric Data.LiveIn[&BB].set_subtract(Data.KillSet[&BB]); 32960b57cec5SDimitry Andric if (!Data.LiveIn[&BB].empty()) 32970b57cec5SDimitry Andric Worklist.insert(pred_begin(&BB), pred_end(&BB)); 32980b57cec5SDimitry Andric } 32990b57cec5SDimitry Andric 33000b57cec5SDimitry Andric // Propagate that liveness until stable 33010b57cec5SDimitry Andric while (!Worklist.empty()) { 33020b57cec5SDimitry Andric BasicBlock *BB = Worklist.pop_back_val(); 33030b57cec5SDimitry Andric 33040b57cec5SDimitry Andric // Compute our new liveout set, then exit early if it hasn't changed despite 33050b57cec5SDimitry Andric // the contribution of our successor. 33060b57cec5SDimitry Andric SetVector<Value *> LiveOut = Data.LiveOut[BB]; 33070b57cec5SDimitry Andric const auto OldLiveOutSize = LiveOut.size(); 33080b57cec5SDimitry Andric for (BasicBlock *Succ : successors(BB)) { 33090b57cec5SDimitry Andric assert(Data.LiveIn.count(Succ)); 33100b57cec5SDimitry Andric LiveOut.set_union(Data.LiveIn[Succ]); 33110b57cec5SDimitry Andric } 33120b57cec5SDimitry Andric // assert OutLiveOut is a subset of LiveOut 33130b57cec5SDimitry Andric if (OldLiveOutSize == LiveOut.size()) { 33140b57cec5SDimitry Andric // If the sets are the same size, then we didn't actually add anything 33150b57cec5SDimitry Andric // when unioning our successors LiveIn. Thus, the LiveIn of this block 33160b57cec5SDimitry Andric // hasn't changed. 33170b57cec5SDimitry Andric continue; 33180b57cec5SDimitry Andric } 33190b57cec5SDimitry Andric Data.LiveOut[BB] = LiveOut; 33200b57cec5SDimitry Andric 33210b57cec5SDimitry Andric // Apply the effects of this basic block 33220b57cec5SDimitry Andric SetVector<Value *> LiveTmp = LiveOut; 33230b57cec5SDimitry Andric LiveTmp.set_union(Data.LiveSet[BB]); 33240b57cec5SDimitry Andric LiveTmp.set_subtract(Data.KillSet[BB]); 33250b57cec5SDimitry Andric 33260b57cec5SDimitry Andric assert(Data.LiveIn.count(BB)); 33270b57cec5SDimitry Andric const SetVector<Value *> &OldLiveIn = Data.LiveIn[BB]; 33280b57cec5SDimitry Andric // assert: OldLiveIn is a subset of LiveTmp 33290b57cec5SDimitry Andric if (OldLiveIn.size() != LiveTmp.size()) { 33300b57cec5SDimitry Andric Data.LiveIn[BB] = LiveTmp; 33310b57cec5SDimitry Andric Worklist.insert(pred_begin(BB), pred_end(BB)); 33320b57cec5SDimitry Andric } 33330b57cec5SDimitry Andric } // while (!Worklist.empty()) 33340b57cec5SDimitry Andric 33350b57cec5SDimitry Andric #ifndef NDEBUG 3336349cc55cSDimitry Andric // Verify our output against SSA properties. This helps catch any 33370b57cec5SDimitry Andric // missing kills during the above iteration. 33380b57cec5SDimitry Andric for (BasicBlock &BB : F) 33390b57cec5SDimitry Andric checkBasicSSA(DT, Data, BB); 33400b57cec5SDimitry Andric #endif 33410b57cec5SDimitry Andric } 33420b57cec5SDimitry Andric 33430b57cec5SDimitry Andric static void findLiveSetAtInst(Instruction *Inst, GCPtrLivenessData &Data, 334406c3fb27SDimitry Andric StatepointLiveSetTy &Out, GCStrategy *GC) { 33450b57cec5SDimitry Andric BasicBlock *BB = Inst->getParent(); 33460b57cec5SDimitry Andric 33470b57cec5SDimitry Andric // Note: The copy is intentional and required 33480b57cec5SDimitry Andric assert(Data.LiveOut.count(BB)); 33490b57cec5SDimitry Andric SetVector<Value *> LiveOut = Data.LiveOut[BB]; 33500b57cec5SDimitry Andric 33510b57cec5SDimitry Andric // We want to handle the statepoint itself oddly. It's 33520b57cec5SDimitry Andric // call result is not live (normal), nor are it's arguments 33530b57cec5SDimitry Andric // (unless they're used again later). This adjustment is 33540b57cec5SDimitry Andric // specifically what we need to relocate 335506c3fb27SDimitry Andric computeLiveInValues(BB->rbegin(), ++Inst->getIterator().getReverse(), LiveOut, 335606c3fb27SDimitry Andric GC); 33570b57cec5SDimitry Andric LiveOut.remove(Inst); 33580b57cec5SDimitry Andric Out.insert(LiveOut.begin(), LiveOut.end()); 33590b57cec5SDimitry Andric } 33600b57cec5SDimitry Andric 33610b57cec5SDimitry Andric static void recomputeLiveInValues(GCPtrLivenessData &RevisedLivenessData, 33620b57cec5SDimitry Andric CallBase *Call, 33631fd87a68SDimitry Andric PartiallyConstructedSafepointRecord &Info, 336406c3fb27SDimitry Andric PointerToBaseTy &PointerToBase, 336506c3fb27SDimitry Andric GCStrategy *GC) { 33660b57cec5SDimitry Andric StatepointLiveSetTy Updated; 336706c3fb27SDimitry Andric findLiveSetAtInst(Call, RevisedLivenessData, Updated, GC); 33680b57cec5SDimitry Andric 33690b57cec5SDimitry Andric // We may have base pointers which are now live that weren't before. We need 33700b57cec5SDimitry Andric // to update the PointerToBase structure to reflect this. 3371bdd1243dSDimitry Andric for (auto *V : Updated) 33721fd87a68SDimitry Andric PointerToBase.insert({ V, V }); 33730b57cec5SDimitry Andric 33740b57cec5SDimitry Andric Info.LiveSet = Updated; 33750b57cec5SDimitry Andric } 3376