[llvm] r313400 - [DebugInfo] Insert DW_OP_deref when spilling indirect DBG_VALUEs
Reid Kleckner via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 19 09:41:40 PDT 2017
I re-landed this in r313640 with a new test case that looks like this:
#define FORCE_SPILL()
\
__asm volatile(""
\
:
\
:
\
: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8",
\
"r9", "r10", "r11", "r12", "r13", "r14", "r15")
int g(int);
int f() {
int x = g(0);
FORCE_SPILL();
int y = g(0);
g(y);
g(y);
g(y);
return x + y;
}
I forgot to zero out a BitVector before reusing it, so I would end up
claiming that both x and y were spilled in this example. Only x is spilled
and y is allocated to a callee-saved register.
The assertion came up in brotli because we ended up trying to claim that
the address of a variable was based on a non-pointer sized vector register,
which of course doesn't make sense.
On Mon, Sep 18, 2017 at 4:11 PM, Hans Wennborg <hans at chromium.org> wrote:
> I've reverted in r313589 since this caused asserts in the Chromium
> build (see http://crbug.com/766261).
>
> On Fri, Sep 15, 2017 at 2:54 PM, Reid Kleckner via llvm-commits
> <llvm-commits at lists.llvm.org> wrote:
> > Author: rnk
> > Date: Fri Sep 15 14:54:38 2017
> > New Revision: 313400
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=313400&view=rev
> > Log:
> > [DebugInfo] Insert DW_OP_deref when spilling indirect DBG_VALUEs
> >
> > Summary:
> > This comes up in optimized debug info for C++ programs that pass and
> > return objects indirectly by address. In these programs,
> > llvm.dbg.declare survives optimization, which causes us to emit indirect
> > DBG_VALUE instructions. The fast register allocator knows to insert
> > DW_OP_deref when spilling indirect DBG_VALUE instructions, but the
> > LiveDebugVariables did not until this change.
> >
> > This fixes part of PR34513. I need to look into why this doesn't work at
> > -O0 and I'll send follow up patches to handle that.
> >
> > Reviewers: aprantl, dblaikie, probinson
> >
> > Subscribers: qcolombet, hiraditya, llvm-commits
> >
> > Differential Revision: https://reviews.llvm.org/D37911
> >
> > Added:
> > llvm/trunk/test/DebugInfo/X86/spill-indirect-nrvo.ll
> > llvm/trunk/test/DebugInfo/X86/spill-nontrivial-param.ll
> > Modified:
> > llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp
> > llvm/trunk/test/DebugInfo/X86/bbjoin.ll
> >
> > Modified: llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> CodeGen/LiveDebugVariables.cpp?rev=313400&r1=313399&r2=313400&view=diff
> > ============================================================
> ==================
> > --- llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp (original)
> > +++ llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp Fri Sep 15 14:54:38
> 2017
> > @@ -108,8 +108,8 @@ class LDVImpl;
> > /// held by the same virtual register. The equivalence class is the
> transitive
> > /// closure of that relation.
> > class UserValue {
> > - const MDNode *Variable; ///< The debug info variable we are part of.
> > - const MDNode *Expression; ///< Any complex address expression.
> > + const DILocalVariable *Variable; ///< The debug info variable we are
> part of.
> > + const DIExpression *Expression; ///< Any complex address expression.
> > bool IsIndirect; ///< true if this is a
> register-indirect+offset value.
> > DebugLoc dl; ///< The debug location for the variable.
> This is
> > ///< used by dwarf writer to find lexical
> scope.
> > @@ -132,8 +132,9 @@ class UserValue {
> > void coalesceLocation(unsigned LocNo);
> >
> > /// insertDebugValue - Insert a DBG_VALUE into MBB at Idx for LocNo.
> > - void insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx,
> unsigned LocNo,
> > - LiveIntervals &LIS, const TargetInstrInfo &TII);
> > + void insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx,
> > + unsigned LocNo, bool Spilled, LiveIntervals
> &LIS,
> > + const TargetInstrInfo &TII);
> >
> > /// splitLocation - Replace OldLocNo ranges with NewRegs ranges where
> NewRegs
> > /// is live. Returns true if any changes were made.
> > @@ -142,8 +143,8 @@ class UserValue {
> >
> > public:
> > /// UserValue - Create a new UserValue.
> > - UserValue(const MDNode *var, const MDNode *expr, bool i, DebugLoc L,
> > - LocMap::Allocator &alloc)
> > + UserValue(const DILocalVariable *var, const DIExpression *expr, bool
> i,
> > + DebugLoc L, LocMap::Allocator &alloc)
> > : Variable(var), Expression(expr), IsIndirect(i),
> dl(std::move(L)),
> > leader(this), locInts(alloc) {}
> >
> > @@ -159,8 +160,8 @@ public:
> > UserValue *getNext() const { return next; }
> >
> > /// match - Does this UserValue match the parameters?
> > - bool match(const MDNode *Var, const MDNode *Expr, const DILocation
> *IA,
> > - bool indirect) const {
> > + bool match(const DILocalVariable *Var, const DIExpression *Expr,
> > + const DILocation *IA, bool indirect) const {
> > return Var == Variable && Expr == Expression && dl->getInlinedAt()
> == IA &&
> > indirect == IsIndirect;
> > }
> > @@ -262,12 +263,14 @@ public:
> > LiveIntervals &LIS);
> >
> > /// rewriteLocations - Rewrite virtual register locations according
> to the
> > - /// provided virtual register map.
> > - void rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI);
> > + /// provided virtual register map. Record which locations were
> spilled.
> > + void rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI,
> > + BitVector &SpilledLocations);
> >
> > /// emitDebugValues - Recreate DBG_VALUE instruction from data
> structures.
> > - void emitDebugValues(VirtRegMap *VRM,
> > - LiveIntervals &LIS, const TargetInstrInfo &TRI);
> > + void emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
> > + const TargetInstrInfo &TRI,
> > + const BitVector &SpilledLocations);
> >
> > /// getDebugLoc - Return DebugLoc of this UserValue.
> > DebugLoc getDebugLoc() { return dl;}
> > @@ -297,11 +300,11 @@ class LDVImpl {
> > VRMap virtRegToEqClass;
> >
> > /// Map user variable to eq class leader.
> > - using UVMap = DenseMap<const MDNode *, UserValue *>;
> > + using UVMap = DenseMap<const DILocalVariable *, UserValue *>;
> > UVMap userVarMap;
> >
> > /// getUserValue - Find or create a UserValue.
> > - UserValue *getUserValue(const MDNode *Var, const MDNode *Expr,
> > + UserValue *getUserValue(const DILocalVariable *Var, const
> DIExpression *Expr,
> > bool IsIndirect, const DebugLoc &DL);
> >
> > /// lookupVirtReg - Find the EC leader for VirtReg or null.
> > @@ -454,8 +457,9 @@ void UserValue::mapVirtRegs(LDVImpl *LDV
> > LDV->mapVirtReg(locations[i].getReg(), this);
> > }
> >
> > -UserValue *LDVImpl::getUserValue(const MDNode *Var, const MDNode *Expr,
> > - bool IsIndirect, const DebugLoc &DL) {
> > +UserValue *LDVImpl::getUserValue(const DILocalVariable *Var,
> > + const DIExpression *Expr, bool
> IsIndirect,
> > + const DebugLoc &DL) {
> > UserValue *&Leader = userVarMap[Var];
> > if (Leader) {
> > UserValue *UV = Leader->getLeader();
> > @@ -494,11 +498,11 @@ bool LDVImpl::handleDebugValue(MachineIn
> > }
> >
> > // Get or create the UserValue for (variable,offset).
> > - bool IsIndirect = MI.isIndirectDebugValue();
> > + bool IsIndirect = MI.getOperand(1).isImm();
> > if (IsIndirect)
> > assert(MI.getOperand(1).getImm() == 0 && "DBG_VALUE with nonzero
> offset");
> > - const MDNode *Var = MI.getDebugVariable();
> > - const MDNode *Expr = MI.getDebugExpression();
> > + const DILocalVariable *Var = MI.getDebugVariable();
> > + const DIExpression *Expr = MI.getDebugExpression();
> > //here.
> > UserValue *UV = getUserValue(Var, Expr, IsIndirect, MI.getDebugLoc());
> > UV->addDef(Idx, MI.getOperand(0));
> > @@ -971,8 +975,10 @@ splitRegister(unsigned OldReg, ArrayRef<
> > static_cast<LDVImpl*>(pImpl)->splitRegister(OldReg, NewRegs);
> > }
> >
> > -void
> > -UserValue::rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo
> &TRI) {
> > +void UserValue::rewriteLocations(VirtRegMap &VRM, const
> TargetRegisterInfo &TRI,
> > + BitVector &SpilledLocations) {
> > + SpilledLocations.resize(locations.size());
> > +
> > // Iterate over locations in reverse makes it easier to handle
> coalescing.
> > for (unsigned i = locations.size(); i ; --i) {
> > unsigned LocNo = i-1;
> > @@ -991,6 +997,7 @@ UserValue::rewriteLocations(VirtRegMap &
> > } else if (VRM.getStackSlot(VirtReg) != VirtRegMap::NO_STACK_SLOT) {
> > // FIXME: Translate SubIdx to a stackslot offset.
> > Loc = MachineOperand::CreateFI(VRM.getStackSlot(VirtReg));
> > + SpilledLocations.set(LocNo);
> > } else {
> > Loc.setReg(0);
> > Loc.setSubReg(0);
> > @@ -1024,7 +1031,7 @@ findInsertLocation(MachineBasicBlock *MB
> > }
> >
> > void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx,
> > - unsigned LocNo,
> > + unsigned LocNo, bool Spilled,
> > LiveIntervals &LIS,
> > const TargetInstrInfo &TII) {
> > MachineBasicBlock::iterator I = findInsertLocation(MBB, Idx, LIS);
> > @@ -1034,25 +1041,35 @@ void UserValue::insertDebugValue(Machine
> > assert(cast<DILocalVariable>(Variable)
> > ->isValidLocationForIntrinsic(getDebugLoc()) &&
> > "Expected inlined-at fields to agree");
> > - if (Loc.isReg())
> > - BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_VALUE),
> > - IsIndirect, Loc.getReg(), Variable, Expression);
> > +
> > + // If the location was spilled, the new DBG_VALUE will be indirect.
> If the
> > + // original DBG_VALUE was indirect, we need to add DW_OP_deref to
> indicate
> > + // that the original virtual register was a pointer.
> > + bool NewIndirect = IsIndirect || Spilled;
> > + const DIExpression *Expr = Expression;
> > + if (Spilled && IsIndirect)
> > + Expr = DIExpression::prepend(Expr, DIExpression::WithDeref);
> > +
> > + MachineInstrBuilder MIB =
> > + BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_VALUE))
> > + .add(Loc);
> > + if (NewIndirect)
> > + MIB.addImm(0U);
> > else
> > - BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_VALUE))
> > - .add(Loc)
> > - .addImm(0U)
> > - .addMetadata(Variable)
> > - .addMetadata(Expression);
> > + MIB.addReg(0U, RegState::Debug);
> > + MIB.addMetadata(Variable).addMetadata(Expr);
> > }
> >
> > void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
> > - const TargetInstrInfo &TII) {
> > + const TargetInstrInfo &TII,
> > + const BitVector &SpilledLocations) {
> > MachineFunction::iterator MFEnd = VRM->getMachineFunction().end();
> >
> > for (LocMap::const_iterator I = locInts.begin(); I.valid();) {
> > SlotIndex Start = I.start();
> > SlotIndex Stop = I.stop();
> > unsigned LocNo = I.value();
> > + bool Spilled = LocNo != ~0U ? SpilledLocations.test(LocNo) : false;
> >
> > // If the interval start was trimmed to the lexical scope insert the
> > // DBG_VALUE at the previous index (otherwise it appears after the
> > @@ -1065,7 +1082,7 @@ void UserValue::emitDebugValues(VirtRegM
> > SlotIndex MBBEnd = LIS.getMBBEndIdx(&*MBB);
> >
> > DEBUG(dbgs() << " BB#" << MBB->getNumber() << '-' << MBBEnd);
> > - insertDebugValue(&*MBB, Start, LocNo, LIS, TII);
> > + insertDebugValue(&*MBB, Start, LocNo, Spilled, LIS, TII);
> > // This interval may span multiple basic blocks.
> > // Insert a DBG_VALUE into each one.
> > while(Stop > MBBEnd) {
> > @@ -1075,7 +1092,7 @@ void UserValue::emitDebugValues(VirtRegM
> > break;
> > MBBEnd = LIS.getMBBEndIdx(&*MBB);
> > DEBUG(dbgs() << " BB#" << MBB->getNumber() << '-' << MBBEnd);
> > - insertDebugValue(&*MBB, Start, LocNo, LIS, TII);
> > + insertDebugValue(&*MBB, Start, LocNo, Spilled, LIS, TII);
> > }
> > DEBUG(dbgs() << '\n');
> > if (MBB == MFEnd)
> > @@ -1090,10 +1107,11 @@ void LDVImpl::emitDebugValues(VirtRegMap
> > if (!MF)
> > return;
> > const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
> > + BitVector SpilledLocations;
> > for (unsigned i = 0, e = userValues.size(); i != e; ++i) {
> > DEBUG(userValues[i]->print(dbgs(), TRI));
> > - userValues[i]->rewriteLocations(*VRM, *TRI);
> > - userValues[i]->emitDebugValues(VRM, *LIS, *TII);
> > + userValues[i]->rewriteLocations(*VRM, *TRI, SpilledLocations);
> > + userValues[i]->emitDebugValues(VRM, *LIS, *TII, SpilledLocations);
> > }
> > EmitDone = true;
> > }
> >
> > Modified: llvm/trunk/test/DebugInfo/X86/bbjoin.ll
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> DebugInfo/X86/bbjoin.ll?rev=313400&r1=313399&r2=313400&view=diff
> > ============================================================
> ==================
> > --- llvm/trunk/test/DebugInfo/X86/bbjoin.ll (original)
> > +++ llvm/trunk/test/DebugInfo/X86/bbjoin.ll Fri Sep 15 14:54:38 2017
> > @@ -11,12 +11,12 @@
> > ; }
> > ; CHECK: ![[X:.*]] = !DILocalVariable(name: "x",
> > ; CHECK: bb.0.entry:
> > -; CHECK: DBG_VALUE 23, 0, ![[X]],
> > +; CHECK: DBG_VALUE 23, debug-use _, ![[X]],
> > ; CHECK: DBG_VALUE %rsp, 0, ![[X]], !DIExpression(DW_OP_plus_uconst,
> 4, DW_OP_deref),
> > ; CHECK: bb.1.if.then:
> > -; CHECK: DBG_VALUE 43, 0, ![[X]],
> > +; CHECK: DBG_VALUE 43, debug-use _, ![[X]],
> > ; CHECK: bb.2.if.end:
> > -; CHECK-NOT: DBG_VALUE 23, 0, ![[X]],
> > +; CHECK-NOT: DBG_VALUE 23, debug-use _, ![[X]],
> > ; CHECK: RETQ %eax
> >
> > target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
> >
> > Added: llvm/trunk/test/DebugInfo/X86/spill-indirect-nrvo.ll
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> DebugInfo/X86/spill-indirect-nrvo.ll?rev=313400&view=auto
> > ============================================================
> ==================
> > --- llvm/trunk/test/DebugInfo/X86/spill-indirect-nrvo.ll (added)
> > +++ llvm/trunk/test/DebugInfo/X86/spill-indirect-nrvo.ll Fri Sep 15
> 14:54:38 2017
> > @@ -0,0 +1,103 @@
> > +; RUN: llc < %s | FileCheck %s
> > +; RUN: llc -O0 < %s | FileCheck %s
> > +
> > +; Make sure we insert DW_OP_deref when spilling indirect DBG_VALUE
> instructions.
> > +
> > +; C++ source:
> > +; #define FORCE_SPILL() \
> > +; __asm volatile("" : : : \
> > +; "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp",
> "r8", \
> > +; "r9", "r10", "r11", "r12", "r13", "r14", "r15")
> > +; struct string {
> > +; string();
> > +; string(int i);
> > +; ~string();
> > +; int i = 0;
> > +; };
> > +; string get_string() {
> > +; string result = 3;
> > +; FORCE_SPILL();
> > +; return result;
> > +; }
> > +
> > +; CHECK-LABEL: _Z10get_stringv:
> > +; CHECK: #DEBUG_VALUE: get_string:result <- [%RDI+0]
> > +; CHECK: movq %rdi, [[OFFS:[0-9]+]](%rsp) # 8-byte Spill
> > +; CHECK: #DEBUG_VALUE: get_string:result <- [DW_OP_plus_uconst
> [[OFFS]], DW_OP_deref] [%RSP+0]
> > +; CHECK: callq _ZN6stringC1Ei
> > +; CHECK: #APP
> > +; CHECK: #NO_APP
> > +
> > +; ModuleID = 't.cpp'
> > +source_filename = "t.cpp"
> > +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
> > +target triple = "x86_64--linux"
> > +
> > +%struct.string = type { i32 }
> > +
> > +; Function Attrs: uwtable
> > +define void @_Z10get_stringv(%struct.string* noalias sret %agg.result)
> #0 !dbg !7 {
> > +entry:
> > + %nrvo = alloca i1, align 1
> > + store i1 false, i1* %nrvo, align 1, !dbg !24
> > + call void @llvm.dbg.declare(metadata %struct.string* %agg.result,
> metadata !23, metadata !DIExpression()), !dbg !25
> > + call void @_ZN6stringC1Ei(%struct.string* %agg.result, i32 3), !dbg
> !26
> > + call void asm sideeffect "", "~{rax},~{rbx},~{rcx},~{rdx},~
> {rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{
> r13},~{r14},~{r15},~{dirflag},~{fpsr},~{flags}"() #3, !dbg !27, !srcloc
> !28
> > + store i1 true, i1* %nrvo, align 1, !dbg !29
> > + %nrvo.val = load i1, i1* %nrvo, align 1, !dbg !30
> > + br i1 %nrvo.val, label %nrvo.skipdtor, label %nrvo.unused, !dbg !30
> > +
> > +nrvo.unused: ; preds = %entry
> > + call void @_ZN6stringD1Ev(%struct.string* %agg.result), !dbg !30
> > + br label %nrvo.skipdtor, !dbg !30
> > +
> > +nrvo.skipdtor: ; preds =
> %nrvo.unused, %entry
> > + ret void, !dbg !30
> > +}
> > +
> > +; Function Attrs: nounwind readnone speculatable
> > +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
> > +
> > +declare void @_ZN6stringC1Ei(%struct.string*, i32) unnamed_addr
> > +
> > +declare void @_ZN6stringD1Ev(%struct.string*) unnamed_addr
> > +
> > +attributes #0 = { uwtable }
> > +attributes #1 = { nounwind readnone speculatable }
> > +attributes #3 = { nounwind }
> > +
> > +!llvm.dbg.cu = !{!0}
> > +!llvm.module.flags = !{!3, !4, !5}
> > +!llvm.ident = !{!6}
> > +
> > +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1,
> producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0,
> emissionKind: FullDebug, enums: !2)
> > +!1 = !DIFile(filename: "t.cpp", directory: "C:\5Csrc\5Cllvm-project\
> 5Cbuild")
> > +!2 = !{}
> > +!3 = !{i32 2, !"Dwarf Version", i32 4}
> > +!4 = !{i32 2, !"Debug Info Version", i32 3}
> > +!5 = !{i32 1, !"wchar_size", i32 4}
> > +!6 = !{!"clang version 6.0.0 "}
> > +!7 = distinct !DISubprogram(name: "get_string", linkageName:
> "_Z10get_stringv", scope: !1, file: !1, line: 13, type: !8, isLocal: false,
> isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized:
> true, unit: !0, variables: !22)
> > +!8 = !DISubroutineType(types: !9)
> > +!9 = !{!10}
> > +!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name:
> "string", file: !1, line: 7, size: 32, elements: !11, identifier:
> "_ZTS6string")
> > +!11 = !{!12, !14, !18, !21}
> > +!12 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !10, file:
> !1, line: 11, baseType: !13, size: 32)
> > +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
> > +!14 = !DISubprogram(name: "string", scope: !10, file: !1, line: 8,
> type: !15, isLocal: false, isDefinition: false, scopeLine: 8, flags:
> DIFlagPrototyped, isOptimized: true)
> > +!15 = !DISubroutineType(types: !16)
> > +!16 = !{null, !17}
> > +!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64,
> flags: DIFlagArtificial | DIFlagObjectPointer)
> > +!18 = !DISubprogram(name: "string", scope: !10, file: !1, line: 9,
> type: !19, isLocal: false, isDefinition: false, scopeLine: 9, flags:
> DIFlagPrototyped, isOptimized: true)
> > +!19 = !DISubroutineType(types: !20)
> > +!20 = !{null, !17, !13}
> > +!21 = !DISubprogram(name: "~string", scope: !10, file: !1, line: 10,
> type: !15, isLocal: false, isDefinition: false, scopeLine: 10, flags:
> DIFlagPrototyped, isOptimized: true)
> > +!22 = !{!23}
> > +!23 = !DILocalVariable(name: "result", scope: !7, file: !1, line: 14,
> type: !10)
> > +!24 = !DILocation(line: 14, column: 3, scope: !7)
> > +!25 = !DILocation(line: 14, column: 10, scope: !7)
> > +!26 = !DILocation(line: 14, column: 19, scope: !7)
> > +!27 = !DILocation(line: 15, column: 3, scope: !7)
> > +!28 = !{i32 -2147471175}
> > +!29 = !DILocation(line: 16, column: 3, scope: !7)
> > +!30 = !DILocation(line: 17, column: 1, scope: !7)
> >
> > Added: llvm/trunk/test/DebugInfo/X86/spill-nontrivial-param.ll
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> DebugInfo/X86/spill-nontrivial-param.ll?rev=313400&view=auto
> > ============================================================
> ==================
> > --- llvm/trunk/test/DebugInfo/X86/spill-nontrivial-param.ll (added)
> > +++ llvm/trunk/test/DebugInfo/X86/spill-nontrivial-param.ll Fri Sep 15
> 14:54:38 2017
> > @@ -0,0 +1,89 @@
> > +; RUN: llc < %s | FileCheck %s
> > +
> > +; Make sure we insert DW_OP_deref when spilling indirect DBG_VALUE
> instructions.
> > +; In this example, 'nt' is passed by address because it is not trivially
> > +; copyable. When we spill the physical argument register at the
> barrier, we need
> > +; to insert DW_OP_deref.
> > +
> > +; #define FORCE_SPILL() \
> > +; __asm volatile("" : : : \
> > +; "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp",
> "r8", \
> > +; "r9", "r10", "r11", "r12", "r13", "r14", "r15")
> > +; struct NonTrivial {
> > +; NonTrivial();
> > +; ~NonTrivial();
> > +; int i;
> > +; };
> > +; int foo(NonTrivial nt) {
> > +; FORCE_SPILL();
> > +; return nt.i;
> > +; }
> > +
> > +; CHECK-LABEL: _Z3foo10NonTrivial:
> > +; CHECK: #DEBUG_VALUE: foo:nt <- [%RDI+0]
> > +; CHECK: movq %rdi, -8(%rsp) # 8-byte Spill
> > +; CHECK: #DEBUG_VALUE: foo:nt <- [DW_OP_constu 8, DW_OP_minus,
> DW_OP_deref] [%RSP+0]
> > +; CHECK: #APP
> > +; CHECK: #NO_APP
> > +; CHECK: movq -8(%rsp), %rax # 8-byte Reload
> > +; CHECK: movl (%rax), %eax
> > +
> > +; ModuleID = 't.cpp'
> > +source_filename = "t.cpp"
> > +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
> > +target triple = "x86_64--linux"
> > +
> > +%struct.NonTrivial = type { i32 }
> > +
> > +; Function Attrs: nounwind uwtable
> > +define i32 @_Z3foo10NonTrivial(%struct.NonTrivial* nocapture readonly
> %nt) local_unnamed_addr #0 !dbg !7 {
> > +entry:
> > + tail call void @llvm.dbg.declare(metadata %struct.NonTrivial* %nt,
> metadata !20, metadata !DIExpression()), !dbg !21
> > + tail call void asm sideeffect "", "~{rax},~{rbx},~{rcx},~{rdx},~
> {rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{
> r13},~{r14},~{r15},~{dirflag},~{fpsr},~{flags}"() #2, !dbg !22, !srcloc
> !23
> > + %i = getelementptr inbounds %struct.NonTrivial, %struct.NonTrivial*
> %nt, i64 0, i32 0, !dbg !24
> > + %0 = load i32, i32* %i, align 4, !dbg !24, !tbaa !25
> > + ret i32 %0, !dbg !30
> > +}
> > +
> > +; Function Attrs: nounwind readnone speculatable
> > +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
> > +
> > +attributes #0 = { nounwind uwtable }
> > +attributes #1 = { nounwind readnone speculatable }
> > +attributes #2 = { nounwind }
> > +
> > +!llvm.dbg.cu = !{!0}
> > +!llvm.module.flags = !{!3, !4, !5}
> > +!llvm.ident = !{!6}
> > +
> > +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1,
> producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0,
> emissionKind: FullDebug, enums: !2)
> > +!1 = !DIFile(filename: "t.cpp", directory: "C:\5Csrc\5Cllvm-project\
> 5Cbuild")
> > +!2 = !{}
> > +!3 = !{i32 2, !"Dwarf Version", i32 4}
> > +!4 = !{i32 2, !"Debug Info Version", i32 3}
> > +!5 = !{i32 1, !"wchar_size", i32 4}
> > +!6 = !{!"clang version 6.0.0 "}
> > +!7 = distinct !DISubprogram(name: "foo", linkageName:
> "_Z3foo10NonTrivial", scope: !1, file: !1, line: 10, type: !8, isLocal:
> false, isDefinition: true, scopeLine: 10, flags: DIFlagPrototyped,
> isOptimized: true, unit: !0, variables: !19)
> > +!8 = !DISubroutineType(types: !9)
> > +!9 = !{!10, !11}
> > +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
> > +!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name:
> "NonTrivial", file: !1, line: 5, size: 32, elements: !12, identifier:
> "_ZTS10NonTrivial")
> > +!12 = !{!13, !14, !18}
> > +!13 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !11, file:
> !1, line: 8, baseType: !10, size: 32)
> > +!14 = !DISubprogram(name: "NonTrivial", scope: !11, file: !1, line: 6,
> type: !15, isLocal: false, isDefinition: false, scopeLine: 6, flags:
> DIFlagPrototyped, isOptimized: true)
> > +!15 = !DISubroutineType(types: !16)
> > +!16 = !{null, !17}
> > +!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64,
> flags: DIFlagArtificial | DIFlagObjectPointer)
> > +!18 = !DISubprogram(name: "~NonTrivial", scope: !11, file: !1, line: 7,
> type: !15, isLocal: false, isDefinition: false, scopeLine: 7, flags:
> DIFlagPrototyped, isOptimized: true)
> > +!19 = !{!20}
> > +!20 = !DILocalVariable(name: "nt", arg: 1, scope: !7, file: !1, line:
> 10, type: !11)
> > +!21 = !DILocation(line: 10, column: 20, scope: !7)
> > +!22 = !DILocation(line: 11, column: 3, scope: !7)
> > +!23 = !{i32 -2147471481}
> > +!24 = !DILocation(line: 12, column: 13, scope: !7)
> > +!25 = !{!26, !27, i64 0}
> > +!26 = !{!"_ZTS10NonTrivial", !27, i64 0}
> > +!27 = !{!"int", !28, i64 0}
> > +!28 = !{!"omnipotent char", !29, i64 0}
> > +!29 = !{!"Simple C++ TBAA"}
> > +!30 = !DILocation(line: 12, column: 3, scope: !7)
> >
> >
> > _______________________________________________
> > llvm-commits mailing list
> > llvm-commits at lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170919/2c1f0ba3/attachment-0001.html>
More information about the llvm-commits
mailing list