aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/InlineFunction.cpp
diff options
context:
space:
mode:
authorOCHyams <orlando.hyams@sony.com>2022-11-18 11:49:43 +0000
committerOCHyams <orlando.hyams@sony.com>2022-11-18 11:55:05 +0000
commite3cd498ff7748f967be1bdcc0a994e40ce82268f (patch)
treeead137f181964596c4d85a97f4fb7e8d34575b8a /llvm/lib/Transforms/Utils/InlineFunction.cpp
parent63f79fe2eb89a891f96a3893df6aaf5153848b54 (diff)
downloadllvm-e3cd498ff7748f967be1bdcc0a994e40ce82268f.zip
llvm-e3cd498ff7748f967be1bdcc0a994e40ce82268f.tar.gz
llvm-e3cd498ff7748f967be1bdcc0a994e40ce82268f.tar.bz2
[Assignment Tracking][21/*] Account for assignment tracking in inliner
The Assignment Tracking debug-info feature is outlined in this RFC: https://discourse.llvm.org/t/ rfc-assignment-tracking-a-better-way-of-specifying-variable-locations-in-ir The inliner requires two additions: fixupAssignments - Update inlined instructions' DIAssignID metadata so that inlined DIAssignID attachments are unique to the inlined instance. trackInlinedStores - Treat inlined stores to caller-local variables (i.e. callee stores to argument pointers that point to the caller's allocas) as assignments. Track them using trackAssignments, which is the same method as is used by the AssignmentTrackingPass. This means that we're able to detect stale memory locations due to DSE after inlining. Because the stores are only tracked _after_ inlining, any DSE or movement of stores _before_ inlining will not be accounted for. This is an accepted limitation mentioned in the RFC. One change is also required: Update CloneBlock to preserve debug use-before-defs. Otherwise the assignments will be dropped due to having the intrinsic operands replaced with empty metadata (see use-before-def.ll in this patch and this related discourse post. Reviewed By: jmorse Differential Revision: https://reviews.llvm.org/D133318
Diffstat (limited to 'llvm/lib/Transforms/Utils/InlineFunction.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/InlineFunction.cpp97
1 files changed, 97 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index dfb7da9..5c9511c 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -1767,6 +1767,94 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI,
}
}
+#undef DEBUG_TYPE
+#define DEBUG_TYPE "assignment-tracking"
+/// Find Alloca and linked DbgAssignIntrinsic for locals escaped by \p CB.
+static at::StorageToVarsMap collectEscapedLocals(const DataLayout &DL,
+ const CallBase &CB) {
+ at::StorageToVarsMap EscapedLocals;
+ SmallPtrSet<const Value *, 4> SeenBases;
+
+ LLVM_DEBUG(
+ errs() << "# Finding caller local variables escaped by callee\n");
+ for (const Value *Arg : CB.args()) {
+ LLVM_DEBUG(errs() << "INSPECT: " << *Arg << "\n");
+ if (!Arg->getType()->isPointerTy()) {
+ LLVM_DEBUG(errs() << " | SKIP: Not a pointer\n");
+ continue;
+ }
+
+ const Instruction *I = dyn_cast<Instruction>(Arg);
+ if (!I) {
+ LLVM_DEBUG(errs() << " | SKIP: Not result of instruction\n");
+ continue;
+ }
+
+ // Walk back to the base storage.
+ assert(Arg->getType()->isPtrOrPtrVectorTy());
+ APInt TmpOffset(DL.getIndexTypeSizeInBits(Arg->getType()), 0, false);
+ const AllocaInst *Base = dyn_cast<AllocaInst>(
+ Arg->stripAndAccumulateConstantOffsets(DL, TmpOffset, true));
+ if (!Base) {
+ LLVM_DEBUG(errs() << " | SKIP: Couldn't walk back to base storage\n");
+ continue;
+ }
+
+ assert(Base);
+ LLVM_DEBUG(errs() << " | BASE: " << *Base << "\n");
+ // We only need to process each base address once - skip any duplicates.
+ if (!SeenBases.insert(Base).second)
+ continue;
+
+ // Find all local variables associated with the backing storage.
+ for (auto *DAI : at::getAssignmentMarkers(Base)) {
+ // Skip variables from inlined functions - they are not local variables.
+ if (DAI->getDebugLoc().getInlinedAt())
+ continue;
+ LLVM_DEBUG(errs() << " > DEF : " << *DAI << "\n");
+ EscapedLocals[Base].insert(at::VarRecord(DAI));
+ }
+ }
+ return EscapedLocals;
+}
+
+static void trackInlinedStores(Function::iterator Start, Function::iterator End,
+ const CallBase &CB) {
+ LLVM_DEBUG(errs() << "trackInlinedStores into "
+ << Start->getParent()->getName() << " from "
+ << CB.getCalledFunction()->getName() << "\n");
+ std::unique_ptr<DataLayout> DL = std::make_unique<DataLayout>(CB.getModule());
+ at::trackAssignments(Start, End, collectEscapedLocals(*DL, CB), *DL);
+}
+
+/// Update inlined instructions' DIAssignID metadata. We need to do this
+/// otherwise a function inlined more than once into the same function
+/// will cause DIAssignID to be shared by many instructions.
+static void fixupAssignments(Function::iterator Start, Function::iterator End) {
+ // Map {Old, New} metadata. Not used directly - use GetNewID.
+ DenseMap<DIAssignID *, DIAssignID *> Map;
+ auto GetNewID = [&Map](Metadata *Old) {
+ DIAssignID *OldID = cast<DIAssignID>(Old);
+ if (DIAssignID *NewID = Map.lookup(OldID))
+ return NewID;
+ DIAssignID *NewID = DIAssignID::getDistinct(OldID->getContext());
+ Map[OldID] = NewID;
+ return NewID;
+ };
+ // Loop over all the inlined instructions. If we find a DIAssignID
+ // attachment or use, replace it with a new version.
+ for (auto BBI = Start; BBI != End; ++BBI) {
+ for (Instruction &I : *BBI) {
+ if (auto *ID = I.getMetadata(LLVMContext::MD_DIAssignID))
+ I.setMetadata(LLVMContext::MD_DIAssignID, GetNewID(ID));
+ else if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(&I))
+ DAI->setAssignId(GetNewID(DAI->getAssignID()));
+ }
+ }
+}
+#undef DEBUG_TYPE
+#define DEBUG_TYPE "inline-function"
+
/// Update the block frequencies of the caller after a callee has been inlined.
///
/// Each block cloned into the caller has its block frequency scaled by the
@@ -2252,6 +2340,15 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
fixupLineNumbers(Caller, FirstNewBlock, &CB,
CalledFunc->getSubprogram() != nullptr);
+ if (getEnableAssignmentTracking()) {
+ // Interpret inlined stores to caller-local variables as assignments.
+ trackInlinedStores(FirstNewBlock, Caller->end(), CB);
+
+ // Update DIAssignID metadata attachments and uses so that they are
+ // unique to this inlined instance.
+ fixupAssignments(FirstNewBlock, Caller->end());
+ }
+
// Now clone the inlined noalias scope metadata.
SAMetadataCloner.clone();
SAMetadataCloner.remap(FirstNewBlock, Caller->end());