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
run(Module & M,ModuleAnalysisManager & AM)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
GetDeoptBundleOperands(const CallBase * Call)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
isGCPointerType(Type * T,GCStrategy * GC)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.)
isHandledGCPointerType(Type * T,GCStrategy * GC)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.
containsGCPtrType(Type * Ty,GCStrategy * GC)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.
isUnhandledGCPointerType(Type * Ty,GCStrategy * GC)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.
suffixed_name_or(Value * V,StringRef Suffix,StringRef DefaultName)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.
analyzeParsePointLiveness(DominatorTree & DT,GCPtrLivenessData & OriginalLivenessData,CallBase * Call,PartiallyConstructedSafepointRecord & Result,GCStrategy * GC)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'.
findBaseDefiningValueOfVector(Value * I,DefiningValueMapTy & Cache,IsKnownBaseMapTy & KnownBases)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.
findBaseDefiningValue(Value * I,DefiningValueMapTy & Cache,IsKnownBaseMapTy & KnownBases)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.
findBaseDefiningValueCached(Value * I,DefiningValueMapTy & Cache,IsKnownBaseMapTy & KnownBases)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.
findBaseOrBDV(Value * I,DefiningValueMapTy & Cache,IsKnownBaseMapTy & KnownBases)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.
isOriginalBaseResult(Value * V)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
isKnownBase(Value * V,const IsKnownBaseMapTy & KnownBases)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
setKnownBase(Value * V,bool IsKnownBase,IsKnownBaseMapTy & KnownBases)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.
areBothVectorOrScalar(Value * First,Value * Second)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
BDVState()705fe6060f1SDimitry Andric BDVState() {
706fe6060f1SDimitry Andric llvm_unreachable("missing state in map");
707fe6060f1SDimitry Andric }
7080b57cec5SDimitry Andric
BDVState(Value * OriginalValue)709fe6060f1SDimitry Andric explicit BDVState(Value *OriginalValue)
710fe6060f1SDimitry Andric : OriginalValue(OriginalValue) {}
BDVState(Value * OriginalValue,StatusTy Status,Value * BaseValue=nullptr)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
getStatus() const716fe6060f1SDimitry Andric StatusTy getStatus() const { return Status; }
getOriginalValue() const717fe6060f1SDimitry Andric Value *getOriginalValue() const { return OriginalValue; }
getBaseValue() const7180b57cec5SDimitry Andric Value *getBaseValue() const { return BaseValue; }
7190b57cec5SDimitry Andric
isBase() const7200b57cec5SDimitry Andric bool isBase() const { return getStatus() == Base; }
isUnknown() const7210b57cec5SDimitry Andric bool isUnknown() const { return getStatus() == Unknown; }
isConflict() const7220b57cec5SDimitry 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.
meet(const BDVState & Other)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
operator ==(const BDVState & Other) const7570b57cec5SDimitry 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
operator !=(const BDVState & other) const7620b57cec5SDimitry Andric bool operator!=(const BDVState &other) const { return !(*this == other); }
7630b57cec5SDimitry Andric
7640b57cec5SDimitry Andric LLVM_DUMP_METHOD
dump() const7650b57cec5SDimitry Andric void dump() const {
7660b57cec5SDimitry Andric print(dbgs());
7670b57cec5SDimitry Andric dbgs() << '\n';
7680b57cec5SDimitry Andric }
7690b57cec5SDimitry Andric
print(raw_ostream & OS) const7700b57cec5SDimitry 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
operator <<(raw_ostream & OS,const BDVState & State)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.
findBasePointer(Value * I,DefiningValueMapTy & Cache,IsKnownBaseMapTy & KnownBases)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.
findBasePointers(const StatepointLiveSetTy & live,PointerToBaseTy & PointerToBase,DominatorTree * DT,DefiningValueMapTy & DVCache,IsKnownBaseMapTy & KnownBases)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.
findBasePointers(DominatorTree & DT,DefiningValueMapTy & DVCache,CallBase * Call,PartiallyConstructedSafepointRecord & result,PointerToBaseTy & PointerToBase,IsKnownBaseMapTy & KnownBases)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
recomputeLiveInValues(Function & F,DominatorTree & DT,ArrayRef<CallBase * > toUpdate,MutableArrayRef<struct PartiallyConstructedSafepointRecord> records,PointerToBaseTy & PointerToBase,GCStrategy * GC)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.
rematerializeChain(ArrayRef<Instruction * > ChainToBase,Instruction * InsertBefore,Value * RootOfChain,Value * AlternateLiveBase)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 *
normalizeForInvokeSafepoint(BasicBlock * BB,BasicBlock * InvokeParent,DominatorTree & DT)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.
legalizeCallAttributes(CallBase * Call,bool IsMemIntrinsic,AttributeList StatepointAL)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.
CreateGCRelocates(ArrayRef<Value * > LiveVariables,ArrayRef<Value * > BasePtrs,Instruction * StatepointToken,IRBuilder<> & Builder,GCStrategy * GC)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:
createRAUW(Instruction * Old,Instruction * New)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
createDelete(Instruction * ToErase)15790b57cec5SDimitry Andric static DeferredReplacement createDelete(Instruction *ToErase) {
15800b57cec5SDimitry Andric DeferredReplacement D;
15810b57cec5SDimitry Andric D.Old = ToErase;
15820b57cec5SDimitry Andric return D;
15830b57cec5SDimitry Andric }
15840b57cec5SDimitry Andric
createDeoptimizeReplacement(Instruction * Old)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.
doReplacement()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
getDeoptLowering(CallBase * Call)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
makeStatepointExplicitImpl(CallBase * Call,const SmallVectorImpl<Value * > & BasePtrs,const SmallVectorImpl<Value * > & LiveVariables,PartiallyConstructedSafepointRecord & Result,std::vector<DeferredReplacement> & Replacements,const PointerToBaseTy & PointerToBase,GCStrategy * GC)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
makeStatepointExplicit(DominatorTree & DT,CallBase * Call,PartiallyConstructedSafepointRecord & Result,std::vector<DeferredReplacement> & Replacements,const PointerToBaseTy & PointerToBase,GCStrategy * GC)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
insertRelocationStores(iterator_range<Value::user_iterator> GCRelocs,DenseMap<Value *,AllocaInst * > & AllocaMap,DenseSet<Value * > & VisitedLiveValues)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.
insertRematerializationStores(const RematerializedValueMapTy & RematerializedValues,DenseMap<Value *,AllocaInst * > & AllocaMap,DenseSet<Value * > & VisitedLiveValues)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
relocationViaAlloca(Function & F,DominatorTree & DT,ArrayRef<Value * > Live,ArrayRef<PartiallyConstructedSafepointRecord> Records)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.
unique_unsorted(SmallVectorImpl<T> & Vec)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.
insertUseHolderAfter(CallBase * Call,const ArrayRef<Value * > Values,SmallVectorImpl<CallInst * > & Holders)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
findLiveReferences(Function & F,DominatorTree & DT,ArrayRef<CallBase * > toUpdate,MutableArrayRef<struct PartiallyConstructedSafepointRecord> records,GCStrategy * GC)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.
findRematerializableChainToBasePointer(SmallVectorImpl<Instruction * > & ChainToBase,Value * CurrentValue)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
chainToBasePointerCost(SmallVectorImpl<Instruction * > & Chain,TargetTransformInfo & TTI)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
AreEquivalentPhiNodes(PHINode & OrigRootPhi,PHINode & AlternateRootPhi)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
findRematerializationCandidates(PointerToBaseTy PointerToBase,RematCandTy & RematerizationCandidates,TargetTransformInfo & TTI)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.
rematerializeLiveValuesAtUses(RematCandTy & RematerizationCandidates,MutableArrayRef<PartiallyConstructedSafepointRecord> Records,PointerToBaseTy & PointerToBase)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.
rematerializeLiveValues(CallBase * Call,PartiallyConstructedSafepointRecord & Info,PointerToBaseTy & PointerToBase,RematCandTy & RematerizationCandidates,TargetTransformInfo & TTI)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
inlineGetBaseAndOffset(Function & F,SmallVectorImpl<CallInst * > & Intrinsics,DefiningValueMapTy & DVCache,IsKnownBaseMapTy & KnownBases)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
insertParsePoints(Function & F,DominatorTree & DT,TargetTransformInfo & TTI,SmallVectorImpl<CallBase * > & ToUpdate,DefiningValueMapTy & DVCache,IsKnownBaseMapTy & KnownBases)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.
getParamAndReturnAttributesToRemove()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
stripNonValidAttributesFromPrototype(Function & F)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.
stripInvalidMetadataFromInstruction(Instruction & I)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
stripNonValidDataFromBody(Function & F)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.
findGCStrategy(Function & F)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.
shouldRewriteStatepointsIn(Function & F)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
stripNonValidData(Module & M)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
runOnFunction(Function & F,DominatorTree & DT,TargetTransformInfo & TTI,const TargetLibraryInfo & TLI)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
computeLiveInValues(BasicBlock::reverse_iterator Begin,BasicBlock::reverse_iterator End,SetVector<Value * > & LiveTmp,GCStrategy * GC)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
computeLiveOutSeed(BasicBlock * BB,SetVector<Value * > & LiveTmp,GCStrategy * GC)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
computeKillSet(BasicBlock * BB,GCStrategy * GC)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.
checkBasicSSA(DominatorTree & DT,SetVector<Value * > & Live,Instruction * TI,bool TermOkay=false)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.
checkBasicSSA(DominatorTree & DT,GCPtrLivenessData & Data,BasicBlock & BB)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
computeLiveInValues(DominatorTree & DT,Function & F,GCPtrLivenessData & Data,GCStrategy * GC)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
findLiveSetAtInst(Instruction * Inst,GCPtrLivenessData & Data,StatepointLiveSetTy & Out,GCStrategy * GC)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
recomputeLiveInValues(GCPtrLivenessData & RevisedLivenessData,CallBase * Call,PartiallyConstructedSafepointRecord & Info,PointerToBaseTy & PointerToBase,GCStrategy * GC)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