Skip to content

Commit 0871722

Browse files
committed
[DebugInfo][RemoveDIs] Handle non-instr debug-info in GlobalISel (#75228)
The RemoveDIs project is aiming to eliminate debug intrinsics like dbg.value and dbg.declare from LLVM, and replace them with DPValue objects attached to instructions. ISel is one of the "terminals" where that information needs to be converted into MIR format: this patch implements support for that in GlobalISel. We aim for the output of LLVM to be identical with/without RemoveDIs debug-info. This patch should be NFC, as we're handling the same data about variables stored in a different format -- it now appears in a DPValue object rather than as an intrinsic. To that end, I've refactored the handling of dbg.values into a dedicated function, and call it whenever a dbg.value or a DPValue is encountered. dbg.declare is handled in a similar way. Testing: adding the --try-experimental-debuginfo-iterators switch to llc causes it to try and convert to the "new" debug-info format if it's built in (LLVM_EXPERIMENTAL_DEBUGINFO_ITERATORS=On), and it'll be covered by our buildbot. One test has a few extra wildcard-regexes added: this is because there's some extra data printed about attached debug-info, which is safe to ignore.
1 parent 9edd1c4 commit 0871722

File tree

8 files changed

+170
-106
lines changed

8 files changed

+170
-106
lines changed

llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,27 @@ class IRTranslator : public MachineFunctionPass {
204204
/// \return true if the materialization succeeded.
205205
bool translate(const Constant &C, Register Reg);
206206

207+
/// Examine any debug-info attached to the instruction (in the form of
208+
/// DPValues) and translate it.
209+
void translateDbgInfo(const Instruction &Inst,
210+
MachineIRBuilder &MIRBuilder);
211+
212+
/// Translate a debug-info record of a dbg.value into a DBG_* instruction.
213+
/// Pass in all the contents of the record, rather than relying on how it's
214+
/// stored.
215+
void translateDbgValueRecord(Value *V, bool HasArgList,
216+
const DILocalVariable *Variable,
217+
const DIExpression *Expression, const DebugLoc &DL,
218+
MachineIRBuilder &MIRBuilder);
219+
220+
/// Translate a debug-info record of a dbg.declare into an indirect DBG_*
221+
/// instruction. Pass in all the contents of the record, rather than relying
222+
/// on how it's stored.
223+
void translateDbgDeclareRecord(Value *Address, bool HasArgList,
224+
const DILocalVariable *Variable,
225+
const DIExpression *Expression, const DebugLoc &DL,
226+
MachineIRBuilder &MIRBuilder);
227+
207228
// Translate U as a copy of V.
208229
bool translateCopy(const User &U, const Value &V,
209230
MachineIRBuilder &MIRBuilder);
@@ -250,14 +271,14 @@ class IRTranslator : public MachineFunctionPass {
250271
/// possible.
251272
std::optional<MCRegister> getArgPhysReg(Argument &Arg);
252273

253-
/// If DebugInst targets an Argument and its expression is an EntryValue,
254-
/// lower it as an entry in the MF debug table.
255-
bool translateIfEntryValueArgument(const DbgDeclareInst &DebugInst);
256-
257-
/// If DebugInst targets an Argument and its expression is an EntryValue,
258-
/// lower as a DBG_VALUE targeting the corresponding livein register for that
259-
/// Argument.
260-
bool translateIfEntryValueArgument(const DbgValueInst &DebugInst,
274+
/// If debug-info targets an Argument and its expression is an EntryValue,
275+
/// lower it as either an entry in the MF debug table (dbg.declare), or a
276+
/// DBG_VALUE targeting the corresponding livein register for that Argument
277+
/// (dbg.value).
278+
bool translateIfEntryValueArgument(bool isDeclare, Value *Arg,
279+
const DILocalVariable *Var,
280+
const DIExpression *Expr,
281+
const DebugLoc &DL,
261282
MachineIRBuilder &MIRBuilder);
262283

263284
bool translateInlineAsm(const CallBase &CB, MachineIRBuilder &MIRBuilder);

llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp

Lines changed: 122 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ class DILocationVerifier : public GISelChangeObserver {
162162
// they could have originated from constants, and we don't want a jumpy
163163
// debug experience.
164164
assert((CurrInst->getDebugLoc() == MI.getDebugLoc() ||
165-
(MI.getParent()->isEntryBlock() && !MI.getDebugLoc())) &&
165+
(MI.getParent()->isEntryBlock() && !MI.getDebugLoc()) ||
166+
(MI.isDebugInstr())) &&
166167
"Line info was not transferred to all instructions");
167168
}
168169
};
@@ -2006,47 +2007,35 @@ std::optional<MCRegister> IRTranslator::getArgPhysReg(Argument &Arg) {
20062007
return VRegDef->getOperand(1).getReg().asMCReg();
20072008
}
20082009

2009-
bool IRTranslator::translateIfEntryValueArgument(const DbgValueInst &DebugInst,
2010+
bool IRTranslator::translateIfEntryValueArgument(bool isDeclare, Value *Val,
2011+
const DILocalVariable *Var,
2012+
const DIExpression *Expr,
2013+
const DebugLoc &DL,
20102014
MachineIRBuilder &MIRBuilder) {
2011-
auto *Arg = dyn_cast<Argument>(DebugInst.getValue());
2015+
auto *Arg = dyn_cast<Argument>(Val);
20122016
if (!Arg)
20132017
return false;
20142018

2015-
const DIExpression *Expr = DebugInst.getExpression();
20162019
if (!Expr->isEntryValue())
20172020
return false;
20182021

20192022
std::optional<MCRegister> PhysReg = getArgPhysReg(*Arg);
20202023
if (!PhysReg) {
2021-
LLVM_DEBUG(dbgs() << "Dropping dbg.value: expression is entry_value but "
2022-
"couldn't find a physical register\n"
2023-
<< DebugInst << "\n");
2024+
LLVM_DEBUG(dbgs() << "Dropping dbg." << (isDeclare ? "declare" : "value")
2025+
<< ": expression is entry_value but "
2026+
<< "couldn't find a physical register\n");
2027+
LLVM_DEBUG(dbgs() << *Var << "\n");
20242028
return true;
20252029
}
20262030

2027-
MIRBuilder.buildDirectDbgValue(*PhysReg, DebugInst.getVariable(),
2028-
DebugInst.getExpression());
2029-
return true;
2030-
}
2031-
2032-
bool IRTranslator::translateIfEntryValueArgument(
2033-
const DbgDeclareInst &DebugInst) {
2034-
auto *Arg = dyn_cast<Argument>(DebugInst.getAddress());
2035-
if (!Arg)
2036-
return false;
2037-
2038-
const DIExpression *Expr = DebugInst.getExpression();
2039-
if (!Expr->isEntryValue())
2040-
return false;
2041-
2042-
std::optional<MCRegister> PhysReg = getArgPhysReg(*Arg);
2043-
if (!PhysReg)
2044-
return false;
2031+
if (isDeclare) {
2032+
// Append an op deref to account for the fact that this is a dbg_declare.
2033+
Expr = DIExpression::append(Expr, dwarf::DW_OP_deref);
2034+
MF->setVariableDbgInfo(Var, Expr, *PhysReg, DL);
2035+
} else {
2036+
MIRBuilder.buildDirectDbgValue(*PhysReg, Var, Expr);
2037+
}
20452038

2046-
// Append an op deref to account for the fact that this is a dbg_declare.
2047-
Expr = DIExpression::append(Expr, dwarf::DW_OP_deref);
2048-
MF->setVariableDbgInfo(DebugInst.getVariable(), Expr, *PhysReg,
2049-
DebugInst.getDebugLoc());
20502039
return true;
20512040
}
20522041

@@ -2100,32 +2089,8 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
21002089
case Intrinsic::dbg_declare: {
21012090
const DbgDeclareInst &DI = cast<DbgDeclareInst>(CI);
21022091
assert(DI.getVariable() && "Missing variable");
2103-
2104-
const Value *Address = DI.getAddress();
2105-
if (!Address || isa<UndefValue>(Address)) {
2106-
LLVM_DEBUG(dbgs() << "Dropping debug info for " << DI << "\n");
2107-
return true;
2108-
}
2109-
2110-
assert(DI.getVariable()->isValidLocationForIntrinsic(
2111-
MIRBuilder.getDebugLoc()) &&
2112-
"Expected inlined-at fields to agree");
2113-
auto AI = dyn_cast<AllocaInst>(Address);
2114-
if (AI && AI->isStaticAlloca()) {
2115-
// Static allocas are tracked at the MF level, no need for DBG_VALUE
2116-
// instructions (in fact, they get ignored if they *do* exist).
2117-
MF->setVariableDbgInfo(DI.getVariable(), DI.getExpression(),
2118-
getOrCreateFrameIndex(*AI), DI.getDebugLoc());
2119-
return true;
2120-
}
2121-
2122-
if (translateIfEntryValueArgument(DI))
2123-
return true;
2124-
2125-
// A dbg.declare describes the address of a source variable, so lower it
2126-
// into an indirect DBG_VALUE.
2127-
MIRBuilder.buildIndirectDbgValue(getOrCreateVReg(*Address),
2128-
DI.getVariable(), DI.getExpression());
2092+
translateDbgDeclareRecord(DI.getAddress(), DI.hasArgList(), DI.getVariable(),
2093+
DI.getExpression(), DI.getDebugLoc(), MIRBuilder);
21292094
return true;
21302095
}
21312096
case Intrinsic::dbg_label: {
@@ -2158,41 +2123,8 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
21582123
case Intrinsic::dbg_value: {
21592124
// This form of DBG_VALUE is target-independent.
21602125
const DbgValueInst &DI = cast<DbgValueInst>(CI);
2161-
const Value *V = DI.getValue();
2162-
assert(DI.getVariable()->isValidLocationForIntrinsic(
2163-
MIRBuilder.getDebugLoc()) &&
2164-
"Expected inlined-at fields to agree");
2165-
if (!V || DI.hasArgList()) {
2166-
// DI cannot produce a valid DBG_VALUE, so produce an undef DBG_VALUE to
2167-
// terminate any prior location.
2168-
MIRBuilder.buildIndirectDbgValue(0, DI.getVariable(), DI.getExpression());
2169-
return true;
2170-
}
2171-
if (const auto *CI = dyn_cast<Constant>(V)) {
2172-
MIRBuilder.buildConstDbgValue(*CI, DI.getVariable(), DI.getExpression());
2173-
return true;
2174-
}
2175-
if (auto *AI = dyn_cast<AllocaInst>(V);
2176-
AI && AI->isStaticAlloca() && DI.getExpression()->startsWithDeref()) {
2177-
// If the value is an alloca and the expression starts with a
2178-
// dereference, track a stack slot instead of a register, as registers
2179-
// may be clobbered.
2180-
auto ExprOperands = DI.getExpression()->getElements();
2181-
auto *ExprDerefRemoved =
2182-
DIExpression::get(AI->getContext(), ExprOperands.drop_front());
2183-
MIRBuilder.buildFIDbgValue(getOrCreateFrameIndex(*AI), DI.getVariable(),
2184-
ExprDerefRemoved);
2185-
return true;
2186-
}
2187-
if (translateIfEntryValueArgument(DI, MIRBuilder))
2188-
return true;
2189-
for (Register Reg : getOrCreateVRegs(*V)) {
2190-
// FIXME: This does not handle register-indirect values at offset 0. The
2191-
// direct/indirect thing shouldn't really be handled by something as
2192-
// implicit as reg+noreg vs reg+imm in the first place, but it seems
2193-
// pretty baked in right now.
2194-
MIRBuilder.buildDirectDbgValue(Reg, DI.getVariable(), DI.getExpression());
2195-
}
2126+
translateDbgValueRecord(DI.getValue(), DI.hasArgList(), DI.getVariable(),
2127+
DI.getExpression(), DI.getDebugLoc(), MIRBuilder);
21962128
return true;
21972129
}
21982130
case Intrinsic::uadd_with_overflow:
@@ -3250,6 +3182,102 @@ void IRTranslator::finishPendingPhis() {
32503182
}
32513183
}
32523184

3185+
void IRTranslator::translateDbgValueRecord(Value *V, bool HasArgList,
3186+
const DILocalVariable *Variable,
3187+
const DIExpression *Expression,
3188+
const DebugLoc &DL,
3189+
MachineIRBuilder &MIRBuilder) {
3190+
assert(Variable->isValidLocationForIntrinsic(DL) &&
3191+
"Expected inlined-at fields to agree");
3192+
// Act as if we're handling a debug intrinsic.
3193+
MIRBuilder.setDebugLoc(DL);
3194+
3195+
if (!V || HasArgList) {
3196+
// DI cannot produce a valid DBG_VALUE, so produce an undef DBG_VALUE to
3197+
// terminate any prior location.
3198+
MIRBuilder.buildIndirectDbgValue(0, Variable, Expression);
3199+
return;
3200+
}
3201+
3202+
if (const auto *CI = dyn_cast<Constant>(V)) {
3203+
MIRBuilder.buildConstDbgValue(*CI, Variable, Expression);
3204+
return;
3205+
}
3206+
3207+
if (auto *AI = dyn_cast<AllocaInst>(V);
3208+
AI && AI->isStaticAlloca() && Expression->startsWithDeref()) {
3209+
// If the value is an alloca and the expression starts with a
3210+
// dereference, track a stack slot instead of a register, as registers
3211+
// may be clobbered.
3212+
auto ExprOperands = Expression->getElements();
3213+
auto *ExprDerefRemoved =
3214+
DIExpression::get(AI->getContext(), ExprOperands.drop_front());
3215+
MIRBuilder.buildFIDbgValue(getOrCreateFrameIndex(*AI), Variable,
3216+
ExprDerefRemoved);
3217+
return;
3218+
}
3219+
if (translateIfEntryValueArgument(false, V, Variable, Expression, DL,
3220+
MIRBuilder))
3221+
return;
3222+
for (Register Reg : getOrCreateVRegs(*V)) {
3223+
// FIXME: This does not handle register-indirect values at offset 0. The
3224+
// direct/indirect thing shouldn't really be handled by something as
3225+
// implicit as reg+noreg vs reg+imm in the first place, but it seems
3226+
// pretty baked in right now.
3227+
MIRBuilder.buildDirectDbgValue(Reg, Variable, Expression);
3228+
}
3229+
return;
3230+
}
3231+
3232+
void IRTranslator::translateDbgDeclareRecord(Value *Address, bool HasArgList,
3233+
const DILocalVariable *Variable,
3234+
const DIExpression *Expression,
3235+
const DebugLoc &DL,
3236+
MachineIRBuilder &MIRBuilder) {
3237+
if (!Address || isa<UndefValue>(Address)) {
3238+
LLVM_DEBUG(dbgs() << "Dropping debug info for " << *Variable << "\n");
3239+
return;
3240+
}
3241+
3242+
assert(Variable->isValidLocationForIntrinsic(DL) &&
3243+
"Expected inlined-at fields to agree");
3244+
auto AI = dyn_cast<AllocaInst>(Address);
3245+
if (AI && AI->isStaticAlloca()) {
3246+
// Static allocas are tracked at the MF level, no need for DBG_VALUE
3247+
// instructions (in fact, they get ignored if they *do* exist).
3248+
MF->setVariableDbgInfo(Variable, Expression,
3249+
getOrCreateFrameIndex(*AI), DL);
3250+
return;
3251+
}
3252+
3253+
if (translateIfEntryValueArgument(true, Address, Variable,
3254+
Expression, DL,
3255+
MIRBuilder))
3256+
return;
3257+
3258+
// A dbg.declare describes the address of a source variable, so lower it
3259+
// into an indirect DBG_VALUE.
3260+
MIRBuilder.setDebugLoc(DL);
3261+
MIRBuilder.buildIndirectDbgValue(getOrCreateVReg(*Address),
3262+
Variable, Expression);
3263+
return;
3264+
}
3265+
3266+
void IRTranslator::translateDbgInfo(const Instruction &Inst,
3267+
MachineIRBuilder &MIRBuilder) {
3268+
for (DPValue &DPV : Inst.getDbgValueRange()) {
3269+
const DILocalVariable *Variable = DPV.getVariable();
3270+
const DIExpression *Expression = DPV.getExpression();
3271+
Value *V = DPV.getVariableLocationOp(0);
3272+
if (DPV.isDbgDeclare())
3273+
translateDbgDeclareRecord(V, DPV.hasArgList(), Variable,
3274+
Expression, DPV.getDebugLoc(), MIRBuilder);
3275+
else
3276+
translateDbgValueRecord(V, DPV.hasArgList(), Variable,
3277+
Expression, DPV.getDebugLoc(), MIRBuilder);
3278+
}
3279+
}
3280+
32533281
bool IRTranslator::translate(const Instruction &Inst) {
32543282
CurBuilder->setDebugLoc(Inst.getDebugLoc());
32553283
CurBuilder->setPCSections(Inst.getMetadata(LLVMContext::MD_pcsections));
@@ -3760,6 +3788,10 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) {
37603788
#ifndef NDEBUG
37613789
Verifier.setCurrentInst(&Inst);
37623790
#endif // ifndef NDEBUG
3791+
3792+
// Translate any debug-info attached to the instruction.
3793+
translateDbgInfo(Inst, *CurBuilder.get());
3794+
37633795
if (translate(Inst))
37643796
continue;
37653797

llvm/test/CodeGen/AArch64/GlobalISel/combine-shift-of-shifted-dbg-value-fallback.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
22
; RUN: llc < %s -global-isel -mtriple=arm64-linux-gnu -global-isel-abort=1 | FileCheck %s
3+
; RUN: llc < %s -global-isel -mtriple=arm64-linux-gnu -global-isel-abort=1 --try-experimental-debuginfo-iterators | FileCheck %s
34
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
45
target triple = "arm64-apple-ios9.0.0"
56

llvm/test/CodeGen/AArch64/GlobalISel/debug-cpp.ll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
; RUN: llc -global-isel -mtriple=aarch64 %s -stop-after=irtranslator -o - | FileCheck %s
22
; RUN: llc -mtriple=aarch64 -global-isel --global-isel-abort=0 -o /dev/null
3+
; RUN: llc -global-isel -mtriple=aarch64 %s -stop-after=irtranslator -o - --try-experimental-debuginfo-iterators | FileCheck %s
4+
; RUN: llc -mtriple=aarch64 -global-isel --global-isel-abort=0 -o /dev/null --try-experimental-debuginfo-iterators
35

46
; struct NTCopy {
57
; NTCopy();

llvm/test/CodeGen/AArch64/GlobalISel/debug-insts.ll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
; RUN: llc -global-isel -mtriple=aarch64 %s -stop-after=irtranslator -o - | FileCheck %s
33
; RUN: llc -mtriple=aarch64 -global-isel --global-isel-abort=0 %s -o /dev/null
44
; RUN: llc -mtriple=aarch64 -global-isel --global-isel-abort=0 %s -o /dev/null -debug
5+
;
6+
; RUN: llc -global-isel -mtriple=aarch64 %s -stop-after=irtranslator -o - --try-experimental-debuginfo-iterators | FileCheck %s
7+
; RUN: llc -mtriple=aarch64 -global-isel --global-isel-abort=0 %s -o /dev/null --try-experimental-debuginfo-iterators
8+
; RUN: llc -mtriple=aarch64 -global-isel --global-isel-abort=0 %s -o /dev/null -debug --try-experimental-debuginfo-iterators
59

610
; CHECK-LABEL: name: debug_declare
711
; CHECK: stack:

llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-dilocation.ll

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
; RUN: llc -O0 -mtriple=aarch64-apple-ios -global-isel -debug-only=irtranslator \
22
; RUN: -stop-after=irtranslator %s -o - 2>&1 | FileCheck %s
3+
; RUN: llc -O0 -mtriple=aarch64-apple-ios -global-isel -debug-only=irtranslator \
4+
; RUN: -stop-after=irtranslator %s -o - 2>&1 --try-experimental-debuginfo-iterators | FileCheck %s
35

46
; REQUIRES: asserts
57

6-
; CHECK: Checking DILocation from %retval = alloca i32, align 4 was copied to G_FRAME_INDEX
7-
; CHECK: Checking DILocation from %rv = alloca i32, align 4 was copied to G_FRAME_INDEX
8-
; CHECK: Checking DILocation from store i32 0, ptr %retval, align 4 was copied to G_CONSTANT
9-
; CHECK: Checking DILocation from store i32 0, ptr %retval, align 4 was copied to G_STORE
10-
; CHECK: Checking DILocation from store i32 0, ptr %rv, align 4, !dbg !12 was copied to G_STORE debug-location !12; t.cpp:2:5
11-
; CHECK: Checking DILocation from %0 = load i32, ptr %rv, align 4, !dbg !13 was copied to G_LOAD debug-location !13; t.cpp:3:8
12-
; CHECK: Checking DILocation from ret i32 %0, !dbg !14 was copied to COPY debug-location !14; t.cpp:3:1
13-
; CHECK: Checking DILocation from ret i32 %0, !dbg !14 was copied to RET_ReallyLR implicit $w0, debug-location !14; t.cpp:3:1
8+
; CHECK: Checking DILocation from %retval = alloca i32, align 4{{.*}} was copied to G_FRAME_INDEX
9+
; CHECK: Checking DILocation from %rv = alloca i32, align 4{{.*}} was copied to G_FRAME_INDEX
10+
; CHECK: Checking DILocation from store i32 0, ptr %retval, align 4{{.*}} was copied to G_CONSTANT
11+
; CHECK: Checking DILocation from store i32 0, ptr %retval, align 4{{.*}} was copied to G_STORE
12+
; CHECK: Checking DILocation from store i32 0, ptr %rv, align 4, !dbg !12{{.*}} was copied to G_STORE debug-location !12; t.cpp:2:5
13+
; CHECK: Checking DILocation from %0 = load i32, ptr %rv, align 4, !dbg !13{{.*}} was copied to G_LOAD debug-location !13; t.cpp:3:8
14+
; CHECK: Checking DILocation from ret i32 %0, !dbg !14{{.*}} was copied to COPY debug-location !14; t.cpp:3:1
15+
; CHECK: Checking DILocation from ret i32 %0, !dbg !14{{.*}} was copied to RET_ReallyLR implicit $w0, debug-location !14; t.cpp:3:1
1416

1517
source_filename = "t.cpp"
1618
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"

llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-extract-used-by-dbg.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
; RUN: llc -O0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s
2+
; RUN: llc -O0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 --try-experimental-debuginfo-iterators | FileCheck %s
23

34
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
45
target triple = "aarch64-unknown-fuchsia"

llvm/test/CodeGen/X86/GlobalISel/x86-calllowering-dbg-trunc.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
; RUN: llc -mtriple=i386-linux-gnu -global-isel -verify-machineinstrs < %s -o - | FileCheck %s --check-prefix=ALL
2+
; RUN: llc -mtriple=i386-linux-gnu -global-isel -verify-machineinstrs < %s -o - --try-experimental-debuginfo-iterators | FileCheck %s --check-prefix=ALL
23

34
; This file is the output of clang -g -O2
45
; int test_dbg_trunc(unsigned long long a) { return a; }

0 commit comments

Comments
 (0)