23
23
#include " llvm/IR/Function.h"
24
24
#include " llvm/IR/Instruction.h"
25
25
#include " llvm/IR/IntrinsicInst.h"
26
+ #include " llvm/IR/Intrinsics.h"
26
27
#include " llvm/IR/Module.h"
27
28
#include " llvm/IR/PassManager.h"
28
29
#include " llvm/IR/PrintPasses.h"
@@ -1102,6 +1103,8 @@ class AssignmentTrackingLowering {
1102
1103
using UntaggedStoreAssignmentMap =
1103
1104
DenseMap<const Instruction *,
1104
1105
SmallVector<std::pair<VariableID, at::AssignmentInfo>>>;
1106
+ using UnknownStoreAssignmentMap =
1107
+ DenseMap<const Instruction *, SmallVector<VariableID>>;
1105
1108
1106
1109
private:
1107
1110
// / The highest numbered VariableID for partially promoted variables plus 1,
@@ -1112,6 +1115,9 @@ class AssignmentTrackingLowering {
1112
1115
// / Map untagged stores to the variable fragments they assign to. Used by
1113
1116
// / processUntaggedInstruction.
1114
1117
UntaggedStoreAssignmentMap UntaggedStoreVars;
1118
+ // / Map untagged unknown stores (e.g. strided/masked store intrinsics)
1119
+ // / to the variables they may assign to. Used by processUntaggedInstruction.
1120
+ UnknownStoreAssignmentMap UnknownStoreVars;
1115
1121
1116
1122
// Machinery to defer inserting dbg.values.
1117
1123
using InstInsertMap = MapVector<VarLocInsertPt, SmallVector<VarLocInfo>>;
@@ -1354,6 +1360,8 @@ class AssignmentTrackingLowering {
1354
1360
// / Update \p LiveSet after encountering an instruciton without a DIAssignID
1355
1361
// / attachment, \p I.
1356
1362
void processUntaggedInstruction (Instruction &I, BlockInfo *LiveSet);
1363
+ void processUnknownStoreToVariable (Instruction &I, VariableID &Var,
1364
+ BlockInfo *LiveSet);
1357
1365
void processDbgAssign (AssignRecord Assign, BlockInfo *LiveSet);
1358
1366
void processDbgVariableRecord (DbgVariableRecord &DVR, BlockInfo *LiveSet);
1359
1367
void processDbgValue (
@@ -1603,6 +1611,45 @@ void AssignmentTrackingLowering::processNonDbgInstruction(
1603
1611
processUntaggedInstruction (I, LiveSet);
1604
1612
}
1605
1613
1614
+ void AssignmentTrackingLowering::processUnknownStoreToVariable (
1615
+ Instruction &I, VariableID &Var, BlockInfo *LiveSet) {
1616
+ // We may have assigned to some unknown fragment of the variable, so
1617
+ // treat the memory assignment as unknown for now.
1618
+ addMemDef (LiveSet, Var, Assignment::makeNoneOrPhi ());
1619
+ // If we weren't already using a memory location, we don't need to do
1620
+ // anything more.
1621
+ if (getLocKind (LiveSet, Var) != LocKind::Mem)
1622
+ return ;
1623
+ // If there is a live debug value for this variable, fall back to using
1624
+ // that.
1625
+ Assignment DbgAV = LiveSet->getAssignment (BlockInfo::Debug, Var);
1626
+ if (DbgAV.Status != Assignment::NoneOrPhi && DbgAV.Source ) {
1627
+ LLVM_DEBUG (dbgs () << " Switching to fallback debug value: " ;
1628
+ DbgAV.dump (dbgs ()); dbgs () << " \n " );
1629
+ setLocKind (LiveSet, Var, LocKind::Val);
1630
+ emitDbgValue (LocKind::Val, DbgAV.Source , &I);
1631
+ return ;
1632
+ }
1633
+ // Otherwise, find a suitable insert point, before the next instruction or
1634
+ // DbgRecord after I.
1635
+ auto InsertBefore = getNextNode (&I);
1636
+ assert (InsertBefore && " Shouldn't be inserting after a terminator" );
1637
+
1638
+ // Get DILocation for this assignment.
1639
+ DebugVariable V = FnVarLocs->getVariable (Var);
1640
+ DILocation *InlinedAt = const_cast <DILocation *>(V.getInlinedAt ());
1641
+ const DILocation *DILoc = DILocation::get (
1642
+ Fn.getContext (), 0 , 0 , V.getVariable ()->getScope (), InlinedAt);
1643
+
1644
+ VarLocInfo VarLoc;
1645
+ VarLoc.VariableID = static_cast <VariableID>(Var);
1646
+ VarLoc.Expr = DIExpression::get (I.getContext (), {});
1647
+ VarLoc.Values = RawLocationWrapper (
1648
+ ValueAsMetadata::get (PoisonValue::get (Type::getInt1Ty (I.getContext ()))));
1649
+ VarLoc.DL = DILoc;
1650
+ InsertBeforeMap[InsertBefore].push_back (VarLoc);
1651
+ }
1652
+
1606
1653
void AssignmentTrackingLowering::processUntaggedInstruction (
1607
1654
Instruction &I, AssignmentTrackingLowering::BlockInfo *LiveSet) {
1608
1655
// Interpret stack stores that are not tagged as an assignment in memory for
@@ -1618,8 +1665,21 @@ void AssignmentTrackingLowering::processUntaggedInstruction(
1618
1665
// "early", for example.
1619
1666
assert (!I.hasMetadata (LLVMContext::MD_DIAssignID));
1620
1667
auto It = UntaggedStoreVars.find (&I);
1621
- if (It == UntaggedStoreVars.end ())
1668
+ if (It == UntaggedStoreVars.end ()) {
1669
+ // It is possible that we have an untagged unknown store, i.e. one that
1670
+ // cannot be represented as a simple (base, offset, size) - in this case we
1671
+ // should undef the memory location of the variable, as if we had a tagged
1672
+ // store that did not match the current assignment.
1673
+ // FIXME: It should be possible to support these stores, but it would
1674
+ // require more extensive changes to our representation of assignments.
1675
+ if (auto UnhandledStoreIt = UnknownStoreVars.find (&I);
1676
+ UnhandledStoreIt != UnknownStoreVars.end ()) {
1677
+ LLVM_DEBUG (dbgs () << " Processing untagged unknown store " << I << " \n " );
1678
+ for (auto &Var : UnhandledStoreIt->second )
1679
+ processUnknownStoreToVariable (I, Var, LiveSet);
1680
+ }
1622
1681
return ; // No variables associated with the store destination.
1682
+ }
1623
1683
1624
1684
LLVM_DEBUG (dbgs () << " processUntaggedInstruction on UNTAGGED INST " << I
1625
1685
<< " \n " );
@@ -2122,6 +2182,26 @@ getUntaggedStoreAssignmentInfo(const Instruction &I, const DataLayout &Layout) {
2122
2182
return std::nullopt;
2123
2183
}
2124
2184
2185
+ AllocaInst *getUnknownStore (const Instruction &I, const DataLayout &Layout) {
2186
+ auto *II = dyn_cast<IntrinsicInst>(&I);
2187
+ if (!II)
2188
+ return nullptr ;
2189
+ Intrinsic::ID ID = II->getIntrinsicID ();
2190
+ if (ID != Intrinsic::experimental_vp_strided_store &&
2191
+ ID != Intrinsic::masked_store && ID != Intrinsic::vp_scatter &&
2192
+ ID != Intrinsic::masked_scatter && ID != Intrinsic::vp_store &&
2193
+ ID != Intrinsic::masked_compressstore)
2194
+ return nullptr ;
2195
+ Value *MemOp = II->getArgOperand (1 );
2196
+ // We don't actually use the constant offset for now, but we may in future,
2197
+ // and the non-accumulating versions do not support a vector of pointers.
2198
+ APInt Offset (Layout.getIndexTypeSizeInBits (MemOp->getType ()), 0 );
2199
+ Value *Base = MemOp->stripAndAccumulateConstantOffsets (Layout, Offset, true );
2200
+ // For Base pointers that are not an alloca instruction we don't need to do
2201
+ // anything, and simply return nullptr.
2202
+ return dyn_cast<AllocaInst>(Base);
2203
+ }
2204
+
2125
2205
DbgDeclareInst *DynCastToDbgDeclare (DbgVariableIntrinsic *DVI) {
2126
2206
return dyn_cast<DbgDeclareInst>(DVI);
2127
2207
}
@@ -2144,14 +2224,16 @@ DbgVariableRecord *DynCastToDbgDeclare(DbgVariableRecord *DVR) {
2144
2224
// / subsequent variables are either stack homed or fully promoted.
2145
2225
// /
2146
2226
// / Finally, populate UntaggedStoreVars with a mapping of untagged stores to
2147
- // / the stored-to variable fragments.
2227
+ // / the stored-to variable fragments, and UnknownStoreVars with a mapping
2228
+ // / of untagged unknown stores to the stored-to variable aggregates.
2148
2229
// /
2149
2230
// / These tasks are bundled together to reduce the number of times we need
2150
2231
// / to iterate over the function as they can be achieved together in one pass.
2151
2232
static AssignmentTrackingLowering::OverlapMap buildOverlapMapAndRecordDeclares (
2152
2233
Function &Fn, FunctionVarLocsBuilder *FnVarLocs,
2153
2234
const DenseSet<DebugAggregate> &VarsWithStackSlot,
2154
2235
AssignmentTrackingLowering::UntaggedStoreAssignmentMap &UntaggedStoreVars,
2236
+ AssignmentTrackingLowering::UnknownStoreAssignmentMap &UnknownStoreVars,
2155
2237
unsigned &TrackedVariablesVectorSize) {
2156
2238
DenseSet<DebugVariable> Seen;
2157
2239
// Map of Variable: [Fragments].
@@ -2160,7 +2242,8 @@ static AssignmentTrackingLowering::OverlapMap buildOverlapMapAndRecordDeclares(
2160
2242
// - dbg.declare -> add single location variable record
2161
2243
// - dbg.* -> Add fragments to FragmentMap
2162
2244
// - untagged store -> Add fragments to FragmentMap and update
2163
- // UntaggedStoreVars.
2245
+ // UntaggedStoreVars, or add to UnknownStoreVars if
2246
+ // we can't determine the fragment overlap.
2164
2247
// We need to add fragments for untagged stores too so that we can correctly
2165
2248
// clobber overlapped fragment locations later.
2166
2249
SmallVector<DbgDeclareInst *> InstDeclares;
@@ -2223,6 +2306,25 @@ static AssignmentTrackingLowering::OverlapMap buildOverlapMapAndRecordDeclares(
2223
2306
HandleDbgAssignForStore (DAI);
2224
2307
for (DbgVariableRecord *DVR : at::getDVRAssignmentMarkers (Info->Base ))
2225
2308
HandleDbgAssignForStore (DVR);
2309
+ } else if (auto *AI = getUnknownStore (I, Fn.getDataLayout ())) {
2310
+ // Find markers linked to this alloca.
2311
+ auto HandleDbgAssignForUnknownStore = [&](auto *Assign) {
2312
+ // Because we can't currently represent the fragment info for this
2313
+ // store, we treat it as an unusable store to the whole variable.
2314
+ DebugVariable DV =
2315
+ DebugVariable (Assign->getVariable (), std::nullopt,
2316
+ Assign->getDebugLoc ().getInlinedAt ());
2317
+ DebugAggregate DA = {DV.getVariable (), DV.getInlinedAt ()};
2318
+ if (!VarsWithStackSlot.contains (DA))
2319
+ return ;
2320
+
2321
+ // Cache this info for later.
2322
+ UnknownStoreVars[&I].push_back (FnVarLocs->insertVariable (DV));
2323
+ };
2324
+ for (DbgAssignIntrinsic *DAI : at::getAssignmentMarkers (AI))
2325
+ HandleDbgAssignForUnknownStore (DAI);
2326
+ for (DbgVariableRecord *DVR : at::getDVRAssignmentMarkers (AI))
2327
+ HandleDbgAssignForUnknownStore (DVR);
2226
2328
}
2227
2329
}
2228
2330
}
@@ -2297,7 +2399,7 @@ bool AssignmentTrackingLowering::run(FunctionVarLocsBuilder *FnVarLocsBuilder) {
2297
2399
// neither does LiveDebugVariables) because that is difficult to do and
2298
2400
// appears to be rare occurance.
2299
2401
VarContains = buildOverlapMapAndRecordDeclares (
2300
- Fn, FnVarLocs, *VarsWithStackSlot, UntaggedStoreVars,
2402
+ Fn, FnVarLocs, *VarsWithStackSlot, UntaggedStoreVars, UnknownStoreVars,
2301
2403
TrackedVariablesVectorSize);
2302
2404
2303
2405
// Prepare for traversal.
0 commit comments