Skip to content

Commit dadf074

Browse files
Artem Gindinsonigcbot
authored andcommitted
Re-apply "Only emit DI stack value at the end of SIMD32 exprs"
This is a re-commit of d08d9ce. Compared to the original change, a nullptr dereference issue has been addressed, and the test file has been renamed for unification purposes. Since our emitter splits SIMD32 programs into SIMD16 subprograms, we should adapt the debug info by only emitting `DW_OP_stack_value` at the end of the source variable's DI Block, i.e. after the merge point that follows the upper SIMD16 register. The approach is to note the information about the split in an `IGC::DbgVariable` instance when generating the upper register variable. Potentially, we could also consider checking for the presence of `DW_OP_skip` when evaluating the DI expression, however it would seem less future-proof in case of future use cases for skips. The change is accompanied by minor in-place refactoring where appropriate.
1 parent 970f0d1 commit dadf074

File tree

5 files changed

+163
-30
lines changed

5 files changed

+163
-30
lines changed

IGC/DebugInfo/DwarfCompileUnit.cpp

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2257,7 +2257,7 @@ IGC::DIE *CompileUnit::constructVariableDIE(DbgVariable &DV,
22572257

22582258
// Check if variable is described by a DBG_VALUE instruction.
22592259
const Instruction *pDbgInst = DV.getDbgInst();
2260-
if (!pDbgInst || !DV.isLocationInlined) {
2260+
if (!pDbgInst || !DV.currentLocationIsInlined()) {
22612261
DV.setDIE(VariableDie);
22622262
LLVM_DEBUG(dbgs() << " done. No dbg.inst assotiated\n");
22632263
return VariableDie;
@@ -2603,8 +2603,7 @@ bool CompileUnit::buildFpBasedLoc(const DbgVariable &var, IGC::DIEBlock *Block,
26032603
}
26042604

26052605
bool CompileUnit::buildSlicedLoc(
2606-
const DbgVariable &var, IGC::DIEBlock *Block,
2607-
const VISAVariableLocation &loc,
2606+
DbgVariable &var, IGC::DIEBlock *Block, const VISAVariableLocation &loc,
26082607
const std::vector<DbgDecoder::LiveIntervalsVISA> *vars) {
26092608
LLVM_DEBUG(dbgs() << " sliced variable, pushing lane \n");
26102609
// DW_OP_push_simd_lane
@@ -2628,7 +2627,7 @@ bool CompileUnit::buildSlicedLoc(
26282627
unsigned int offsetNotTaken = Block->ComputeSizeOnTheFly(Asm);
26292628

26302629
// Emit first register
2631-
if (!buildValidVar(var, Block, loc, vars, true))
2630+
if (!buildValidVar(var, Block, loc, vars, DbgRegisterType::FirstHalf))
26322631
return false;
26332632

26342633
// Emit second half register
@@ -2645,16 +2644,16 @@ bool CompileUnit::buildSlicedLoc(
26452644
// register in buildValidVar(), which always processes the 1st register only.
26462645
VISAVariableLocation second_loc(loc);
26472646
second_loc.SetRegister(loc.GetSecondReg());
2648-
if (!buildValidVar(var, Block, second_loc, vars, false))
2647+
if (!buildValidVar(var, Block, second_loc, vars, DbgRegisterType::SecondHalf))
26492648
return false;
26502649

26512650
return true;
26522651
}
26532652

26542653
bool CompileUnit::buildValidVar(
2655-
const DbgVariable &var, IGC::DIEBlock *Block,
2656-
const VISAVariableLocation &loc,
2657-
const std::vector<DbgDecoder::LiveIntervalsVISA> *vars, bool firstHalf) {
2654+
DbgVariable &var, IGC::DIEBlock *Block, const VISAVariableLocation &loc,
2655+
const std::vector<DbgDecoder::LiveIntervalsVISA> *vars,
2656+
DbgRegisterType regType) {
26582657
const DbgDecoder::VarInfo *VarInfo = nullptr;
26592658
const auto *VISAMod = loc.GetVISAModule();
26602659

@@ -2671,11 +2670,26 @@ bool CompileUnit::buildValidVar(
26712670
LLVM_DEBUG(dbgs() << " warning: could not get vISA Variable info\n");
26722671
}
26732672

2674-
if (VarInfo || (vars && vars->size() >= (firstHalf ? 1u : 2u))) {
2675-
const auto &lrToUse =
2676-
vars ? vars->at(firstHalf ? 0 : 1) : VarInfo->lrs.front();
2673+
const bool isSecondHalf = regType == DbgRegisterType::SecondHalf;
2674+
const unsigned NumVarsExpected = isSecondHalf ? 2 : 1;
2675+
// TODO: If neither condition is fulfilled, should we do an early
2676+
// 'return false' as in "invalid variable"? In that case, we could improve
2677+
// the logic in the following way:
2678+
//
2679+
// DbgDecoder::LiveIntervalsVISA *lrToUse = nullptr;
2680+
// if (vars && vars->size() >= NumVarsExpected)
2681+
// lrToUse = vars->at(LRIndex);
2682+
// else if (VarInfo)
2683+
// lrToUse = VarInfo->lrs.front();
2684+
// if (!lrToUse)
2685+
// return false;
2686+
// /* remaining code from the if block */
2687+
if (VarInfo || (vars && vars->size() >= NumVarsExpected)) {
2688+
const unsigned LRIndex = isSecondHalf ? 1 : 0;
2689+
const auto &lrToUse = vars ? vars->at(LRIndex) : VarInfo->lrs.front();
26772690
LLVM_DEBUG(dbgs() << " emitting variable location at LR: <";
26782691
lrToUse.print(dbgs()); dbgs() << ">\n");
2692+
var.setLocationRegisterType(regType);
26792693
emitLocation = true;
26802694
if (lrToUse.isGRF()) {
26812695
if (loc.IsVectorized() == false) {
@@ -2702,7 +2716,7 @@ bool CompileUnit::buildValidVar(
27022716
SimdOffset < MaxUI16);
27032717
if (loc.IsRegister())
27042718
addSimdLane(Block, var, loc, &lrToUse, (uint16_t)(SimdOffset),
2705-
false, !firstHalf);
2719+
false, isSecondHalf);
27062720
}
27072721
}
27082722
} else if (lrToUse.isSpill()) {
@@ -2738,7 +2752,7 @@ bool CompileUnit::buildValidVar(
27382752
static_cast<int32_t>(VectorOffset));
27392753
addBE_FP(Block);
27402754
addSimdLane(Block, var, loc, &lrToUse, 0, false,
2741-
!firstHalf); // Emit SIMD lane for spill (unpacked)
2755+
isSecondHalf); // Emit SIMD lane for spill (unpacked)
27422756
}
27432757
}
27442758
} else {
@@ -2751,7 +2765,7 @@ bool CompileUnit::buildValidVar(
27512765
}
27522766

27532767
IGC::DIEBlock *CompileUnit::buildGeneral(
2754-
const DbgVariable &var, const VISAVariableLocation &loc,
2768+
DbgVariable &var, const VISAVariableLocation &loc,
27552769
const std::vector<DbgDecoder::LiveIntervalsVISA> *vars,
27562770
IGC::DIE *VariableDie) {
27572771
IGC::DIEBlock *Block = new (DIEValueAllocator) IGC::DIEBlock();
@@ -2788,7 +2802,7 @@ IGC::DIEBlock *CompileUnit::buildGeneral(
27882802
if (loc.HasLocationSecondReg()) {
27892803
buildSlicedLoc(var, Block, loc, vars);
27902804
} else {
2791-
buildValidVar(var, Block, loc, vars, true);
2805+
buildValidVar(var, Block, loc, vars, DbgRegisterType::Regular);
27922806
}
27932807
}
27942808

IGC/DebugInfo/DwarfCompileUnit.hpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ class CompileUnit {
524524
// buildSLM - Build expression for location described as offset in SLM memory.
525525
DIEBlock *buildSLM(const DbgVariable &, const VISAVariableLocation &,
526526
IGC::DIE *);
527-
DIEBlock *buildGeneral(const DbgVariable &, const VISAVariableLocation &,
527+
DIEBlock *buildGeneral(DbgVariable &, const VISAVariableLocation &,
528528
const std::vector<DbgDecoder::LiveIntervalsVISA> *,
529529
IGC::DIE *);
530530

@@ -533,12 +533,13 @@ class CompileUnit {
533533
const VISAVariableLocation &);
534534
bool buildFpBasedLoc(const DbgVariable &, IGC::DIEBlock *,
535535
const VISAVariableLocation &);
536-
bool buildSlicedLoc(const DbgVariable &, IGC::DIEBlock *,
536+
bool buildSlicedLoc(DbgVariable &, IGC::DIEBlock *,
537537
const VISAVariableLocation &,
538538
const std::vector<DbgDecoder::LiveIntervalsVISA> *);
539-
bool buildValidVar(const DbgVariable &, IGC::DIEBlock *,
539+
bool buildValidVar(DbgVariable &, IGC::DIEBlock *,
540540
const VISAVariableLocation &,
541-
const std::vector<DbgDecoder::LiveIntervalsVISA> *, bool);
541+
const std::vector<DbgDecoder::LiveIntervalsVISA> *,
542+
DbgRegisterType);
542543

543544
// Variables, used in buildGeneral-algorithm:
544545
bool emitLocation = false;

IGC/DebugInfo/DwarfDebug.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -211,14 +211,19 @@ void DbgVariable::emitExpression(CompileUnit *CU, IGC::DIEBlock *Block) const {
211211
}
212212
I->appendToVector(Elements);
213213
}
214-
bool isStackValueNeeded = false;
215-
if (currentLocationIsSimpleIndirectValue()) {
216-
// drop OP_deref and don't emit DW_OP_stack_value.
214+
const bool isSimpleIndirect = currentLocationIsSimpleIndirectValue();
215+
if (isSimpleIndirect)
216+
// drop OP_deref
217217
Elements.erase(Elements.begin());
218-
} else if (!currentLocationIsMemoryAddress() &&
219-
!currentLocationIsImplicit() && !currentLocationIsVector()) {
220-
isStackValueNeeded = true;
218+
bool shouldResetStackValue = currentLocationIsImplicit();
219+
if (shouldResetStackValue && !Elements.empty() &&
220+
*Elements.rbegin() == dwarf::DW_OP_stack_value) {
221+
Elements.pop_back();
221222
}
223+
const bool isFirstHalf = this->RegType == DbgRegisterType::FirstHalf;
224+
bool isStackValueNeeded = !isSimpleIndirect &&
225+
!currentLocationIsMemoryAddress() &&
226+
!currentLocationIsVector() && !isFirstHalf;
222227

223228
for (auto elem : Elements) {
224229
auto BF = DIEInteger::BestForm(false, elem);
@@ -1648,7 +1653,7 @@ void DwarfDebug::collectVariableInfo(
16481653
(pInst->getMetadata("StorageOffset") ||
16491654
Loc.HasSurface() || Loc.IsSLM()))) {
16501655
RegVar->setDbgInst(pInst);
1651-
RegVar->isLocationInlined = true;
1656+
RegVar->setLocationInlined(true);
16521657
break;
16531658
}
16541659
}

IGC/DebugInfo/DwarfDebug.hpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,15 @@ class DotDebugLocEntry {
123123
void setSymbol(llvm::MCSymbol *S) { Symbol = S; }
124124
};
125125

126+
//===----------------------------------------------------------------------===//
127+
/// \brief This enum is used to describe whether a register represents one of
128+
/// the SIMD32 register halves.
129+
enum class DbgRegisterType : uint8_t {
130+
Regular = 0, // Represents all SIMD channels for a source variable, no slice
131+
FirstHalf = 1, // SIMD32 sliced - lower channels
132+
SecondHalf = 2 // SIMD32 sliced - upper channels
133+
};
134+
126135
//===----------------------------------------------------------------------===//
127136
/// \brief This class is used to track local variable information.
128137
class DbgVariable {
@@ -143,6 +152,12 @@ class DbgVariable {
143152
// DBG_VALUE instruction of the variable
144153
const llvm::DbgVariableIntrinsic *m_pDbgInst = nullptr;
145154

155+
// isLocationInlined is true when we expect location to be inlined in
156+
// DW_AT_location.
157+
bool isLocationInlined = false;
158+
159+
DbgRegisterType RegType = DbgRegisterType::Regular;
160+
146161
public:
147162
// AbsVar may be NULL.
148163
DbgVariable(const llvm::DILocalVariable *V,
@@ -196,6 +211,16 @@ class DbgVariable {
196211
bool currentLocationIsSimpleIndirectValue() const;
197212
bool currentLocationIsVector() const;
198213

214+
bool currentLocationIsInlined() const { return isLocationInlined; }
215+
void setLocationInlined(bool isInlined = true) {
216+
isLocationInlined = isInlined;
217+
}
218+
219+
DbgRegisterType getLocationRegisterType() const { return RegType; }
220+
void setLocationRegisterType(DbgRegisterType RegType) {
221+
this->RegType = RegType;
222+
}
223+
199224
void emitExpression(CompileUnit *CU, IGC::DIEBlock *Block) const;
200225

201226
// Translate tag to proper Dwarf tag.
@@ -223,10 +248,6 @@ class DbgVariable {
223248
return false;
224249
}
225250

226-
// isLocationInlined is true when we expect location to be inlined in
227-
// DW_AT_location.
228-
bool isLocationInlined = false;
229-
230251
bool isBlockByrefVariable() const;
231252

232253
llvm::DIType *getType() const;
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
//========================== begin_copyright_notice ============================
2+
//
3+
// Copyright (C) 2024 Intel Corporation
4+
//
5+
// SPDX-License-Identifier: MIT
6+
//
7+
//=========================== end_copyright_notice =============================
8+
9+
// UNSUPPORTED: sys32
10+
// REQUIRES: oneapi-readelf, dg2-supported
11+
12+
// RUN: ocloc compile -file %s -options "-g -igc_opts 'PrintToConsole=1 PrintAfter=EmitPass'" -device dg2 2>&1 | FileCheck %s --check-prefix=CHECK-LLVM
13+
// RUN: ocloc compile -file %s -options "-g -igc_opts 'ElfDumpEnable=1 DumpUseShorterName=0 DebugDumpNamePrefix=%t_dg2_'" -device dg2
14+
// RUN: oneapi-readelf --debug-dump %t_dg2_OCL_simd32_entry_0001.elf | FileCheck %s --check-prefix=CHECK-DWARF
15+
16+
// CHECK-LLVM-LABEL: define spir_kernel void @test
17+
// CHECK-LLVM-SAME: ({{.*}} %in,{{.*}} %out,{{.*}} i16 %localIdX{{.*}})
18+
__attribute__((intel_reqd_sub_group_size(32)))
19+
kernel void test(global int* in, global int* out) {
20+
// COM: The routine instructions for local ID extraction are largely skipped in the checks below
21+
// CHECK-LLVM: %[[LOCAL_ID_X:.+]] = zext i16 %localIdX to i32, !dbg !{{[0-9]+}}
22+
// CHECK-LLVM: %[[LOCAL_ID_TMP_0:.+]] = add i32 %{{.+}}, %localIdX4, !dbg !{{[0-9]+}}
23+
// CHECK-LLVM: %[[LOCAL_ID_TMP_1:.+]] = add i32 %[[LOCAL_ID_TMP_0]], %{{.*}}, !dbg !{{[0-9]+}}
24+
// COM: 'gid' is implicitly marked as a stack value before the emitter
25+
// CHECK-LLVM: call void @llvm.dbg.value(metadata i32 %[[LOCAL_ID_TMP_1]], metadata ![[GID_DI_VAR_MD:[0-9]+]]
26+
// CHECK-LLVM-SAME: metadata !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 64, DW_ATE_unsigned, DW_OP_stack_value))
27+
size_t gid = get_global_id(0);
28+
// CHECK-LLVM: %[[IN_LOAD:.+]] = call i32 @llvm.genx.GenISA.ldraw.indexed.i32{{.*}}({{.*}}), !dbg !{{.*}}
29+
// CHECK-LLVM: %[[MUL:.+]] = mul nsw i32 %[[IN_LOAD]], 42, !dbg !{{.*}}
30+
// COM: 'mul' is to be marked as a stack value during the emitter phase
31+
// CHECK-LLVM: call void @llvm.dbg.value(metadata i32 %[[MUL]], metadata ![[MUL_DI_VAR_MD:[0-9]+]], metadata !DIExpression())
32+
int mul = in[gid] * 42;
33+
out[gid] = mul;
34+
}
35+
// CHECK-LLVM-DAG: !{{[0-9]+}} = !{!"sub_group_size", i32 32}
36+
//
37+
// CHECK-LLVM-DAG: ![[GID_DI_VAR_MD]] = !DILocalVariable(name: "gid", {{.+}}, type: ![[SIZE_T_DI_TY_MD:[0-9]+]])
38+
// CHECK-LLVM-DAG: ![[SIZE_T_DI_TY_MD]] = !DIDerivedType(tag: DW_TAG_typedef, name: "size_t", file: !{{[0-9]+}}, baseType: !{{[0-9]+}})
39+
// CHECK-LLVM-DAG: ![[MUL_DI_VAR_MD]] = !DILocalVariable(name: "mul", {{.+}}, type: ![[INT_DI_TY_MD:[0-9]+]])
40+
// CHECK-LLVM-DAG: ![[INT_DI_TY_MD]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
41+
42+
// CHECK-DWARF: Contents of the .debug_info section:
43+
// COM: Briefly check global layout
44+
// CHECK-DWARF: Abbrev Number: 1 (DW_TAG_compile_unit)
45+
// CHECK-DWARF: DW_AT_name{{ *}}: simd32-sliced-stack-value.cl
46+
// CHECK-DWARF: DW_AT_INTEL_simd_width{{ *}}: 32
47+
// CHECK-DWARF: Abbrev Number: 2 (DW_TAG_subprogram)
48+
// CHECK-DWARF: DW_AT_name{{ *}}: test
49+
// CHECK-DWARF: DW_AT_INTEL_simd_width{{ *}}: 32
50+
// CHECK-DWARF: Abbrev Number: 3 (DW_TAG_formal_parameter)
51+
// CHECK-DWARF: DW_AT_name{{ *}}: in
52+
// CHECK-DWARF: Abbrev Number: 3 (DW_TAG_formal_parameter)
53+
// CHECK-DWARF: DW_AT_name{{ *}}: out
54+
// COM: Relevant variable checks/type captures
55+
// CHECK-DWARF: Abbrev Number: 4 (DW_TAG_variable)
56+
// CHECK-DWARF: DW_AT_name{{ *}}: gid
57+
// CHECK-DWARF: DW_AT_type{{ *}}: <0x[[SIZE_T_TY:[0-9a-f]+]]>
58+
// CHECK-DWARF: DW_AT_location{{ *}}: [[GID_LOC:0]] (location list)
59+
// CHECK-DWARF: Abbrev Number: 4 (DW_TAG_variable)
60+
// CHECK-DWARF: DW_AT_name{{ *}}: mul
61+
// CHECK-DWARF: DW_AT_type{{ *}}: <0x[[INT_TY:[0-9a-f]+]]>
62+
// CHECK-DWARF: DW_AT_location{{ *}}: 0x[[MUL_LOC:[0-9a-f]+]] (location list)
63+
// COM: Type checks
64+
// CHECK-DWARF: <[[INT_TY]]>: Abbrev Number: 6 (DW_TAG_base_type)
65+
// CHECK-DWARF-NEXT: DW_AT_name{{ *}}: int
66+
// CHECK-DWARF-NEXT: DW_AT_encoding{{ *}}: 5{{ *}} (signed)
67+
// CHECK-DWARF: <[[SIZE_T_TY]]>: Abbrev Number: 7 (DW_TAG_typedef)
68+
// CHECK-DWARF-NEXT: DW_AT_type
69+
// CHECK-DWARF-NEXT: DW_AT_name{{ *}}: size_t
70+
//
71+
// CHECK-DWARF: Contents of the .debug_loc section:
72+
// COM: Check SIMD 32 location expressions. We only expect DW_OP_stack_value at the end of each
73+
// expression, never before a DW_OP_skip.
74+
// CHECK-DWARF-NOT: DW_OP_stack_value; DW_OP_skip
75+
// COM: 'gid' source variable (implicit stack value)
76+
// CHECK-DWARF: {{0+}}[[GID_LOC]] {{[0-9a-f]+}} {{[0-9a-f]+}}
77+
// CHECK-DWARF-SAME: (DW_OP_INTEL_push_simd_lane; DW_OP_lit16; DW_OP_ge; DW_OP_bra: [[GID_BR:[0-9]+]];
78+
// CHECK-DWARF-SAME: DW_OP_INTEL_push_simd_lane; DW_OP_lit3; DW_OP_shr; DW_OP_plus_uconst: {{[0-9]+}};
79+
// CHECK-DWARF-SAME: DW_OP_INTEL_push_simd_lane; [[GID_MAIN_EXPR:DW_OP_lit7; DW_OP_and; DW_OP_const1u: 32; DW_OP_mul; DW_OP_INTEL_regval_bits: 32; DW_OP_const4u: 4294967295; DW_OP_and]];
80+
// CHECK-DWARF-SAME: DW_OP_skip: [[GID_BR]];
81+
// CHECK-DWARF-SAME: DW_OP_INTEL_push_simd_lane; DW_OP_lit16; DW_OP_minus; DW_OP_lit3; DW_OP_shr; DW_OP_plus_uconst: {{[0-9]+}};
82+
// CHECK-DWARF-SAME: DW_OP_INTEL_push_simd_lane; [[GID_MAIN_EXPR]]; DW_OP_stack_value)
83+
// CHECK-DWARF-NEXT: <End of list>
84+
// COM: 'mul' source variable (explicitly marked as stack value)
85+
// CHECK-DWARF: {{0+}}[[MUL_LOC]] {{[0-9a-f]+}} {{[0-9a-f]+}}
86+
// CHECK-DWARF-SAME: (DW_OP_INTEL_push_simd_lane; DW_OP_lit16; DW_OP_ge; DW_OP_bra: [[MUL_BR:[0-9]+]];
87+
// CHECK-DWARF-SAME: DW_OP_INTEL_push_simd_lane; DW_OP_lit3; DW_OP_shr; DW_OP_plus_uconst: {{[0-9]+}};
88+
// CHECK-DWARF-SAME: DW_OP_INTEL_push_simd_lane; [[MUL_MAIN_EXPR:DW_OP_lit7; DW_OP_and; DW_OP_const1u: 32; DW_OP_mul; DW_OP_INTEL_regval_bits: 32]];
89+
// CHECK-DWARF-SAME: DW_OP_skip: [[MUL_BR]];
90+
// CHECK-DWARF-SAME: DW_OP_INTEL_push_simd_lane; DW_OP_lit16; DW_OP_minus; DW_OP_lit3; DW_OP_shr; DW_OP_plus_uconst: {{[0-9]+}};
91+
// CHECK-DWARF-SAME: DW_OP_INTEL_push_simd_lane; [[MUL_MAIN_EXPR]]; DW_OP_stack_value)
92+
// CHECK-DWARF-NEXT: <End of list>

0 commit comments

Comments
 (0)