[llvm-commits] [llvm] r128327 - in /llvm/trunk: include/llvm/CodeGen/MachineBasicBlock.h lib/CodeGen/AsmPrinter/DwarfDebug.cpp lib/CodeGen/AsmPrinter/DwarfDebug.h test/CodeGen/X86/dbg-merge-loc-entry.ll

Alexey Samsonov samsonov at google.com
Mon Dec 2 08:00:07 PST 2013


Hi David,

Let me outline some ideas I got after reading this code as a
sanity-check-request - I have too little knowledge of DBG_VALUE machine
instructions, working with machine functions, etc.

On Fri, Nov 1, 2013 at 1:46 AM, David Blaikie <dblaikie at gmail.com> wrote:

> To document some of my own state on this issue (I'm happy to take this
> into another thread or bug to discuss if people think there's a better
> context for such discussion)...
>
> In DwarfDebug::beginFunction there is a bunch of code (that could probably
> be refactored into some named functions to make it more documented) but
> here's the basic idea:
>
> For all MBB
>   For all MI
>     if it's a debug value
>       record the location in the 'history' for this variable
>       mark the register as in-use by a certain variable (what happens if
> we end up with two variables in the same register? I don't think this code
> can handle that)
>

I agree - there are real-life cases when several variables refer to the
same register - e.g. in ASan mode addresses of all local variables are
defined as offsets from $rsp via DBG_VALUE instruction.
So, instead of [Register]->[Debug variable] mapping we need to have
[Register] -> [Vector of debug variables] here.

The code in this branch also inserts a range-terminator instruction between
a pair DBG_VALUE instrs for the same variable if instructions in this pair
are from different basic blocks (I assume, this is done for the same
purpose as inserting range-terminators in the second loop, and it can hurt
us as well).


>      else
>       if this instruction clobbers any register
>        * if this instruction is in the same MBB as the current defining
> debug value for the variable*
>           record this instruction in the history (it will act as a debug
> loc range terminator) of the variable
>
> For all the variables
>   If the end of the history is debug value (not a non-debug instruction
> which would terminate the range)
>     If that debug value is in a different basic block than the final basic
> block in the function
>       add the last instruction in the debug values basic block to the
> history to terminate the range
>
>
We terminate ranges too early - some registers may not in fact be clobbered
between two different basic blocks. However, looks like we *have* all the
information we need - DBG_VALUE instructions and
register-clobbering instructions - in DwarfDebug::beginFunction(), and
should just properly compute location ranges. It is nontrivial, though, and
I think the main purpose range-terminator instructions were added is
to deal with confusion when MBB has more than one predecessor. We need to
somehow implement "phi-nodes" for variable locations...
Suppose we have:

MBB1:
  dbg_loc("x") = %rax
  jmp MBB3
MBB2:
  dbg_loc("x") = %rdx
  jmp MBB3
MBB3:
  // where is "x" now?

currently we add dbg_loc("x") = undef at the end of MBB1 and MBB2 for
safety, but in general we should do a proper analysis.
Now this looks like a problem, which could be solved by graph traversal :)
Basically, we may take first instruction and all the DBG_VALUE instructions
as starting points, and scan all the instructions in the order of execution
(following jumps), inserting range-terminators if we see a register
clobbering instruction or if we enter a new MBB and incoming variable
locations are different.

Does it all make sense?


Hopefully that makes some sense. The bolded text is one of the problematic
> places - but I don't believe it's correct to simply not do that check (some
> things do actually get clobbered across basic blocks). It might be as
> simple as also checking (both at the bolded step, and in the "for all
> variables" loop) if the register in question is something that won't get
> clobbered across basic blocks.
>
> Lang - this still seems rather special-cased. I assume we do some inter-BB
> register allocation above -O0, so how should we be doing this to get
> accurate live ranges for our debug variables? Just assuming all registers
> (except the base pointer?) get clobbered at the end of a basic block seems
> a bit 'rough' at best, but perhaps I'm wrong.
>
> - David
>
> On Tue, Oct 29, 2013 at 3:33 PM, David Blaikie <dblaikie at gmail.com> wrote:
>
>> +Alexey who's encountering this in ASan
>>
>>
>> On Fri, Oct 25, 2013 at 1:28 PM, David Blaikie <dblaikie at gmail.com>wrote:
>>
>>> Bump because... argh. (I've also reformatted the samples to remove all
>>> the extra newlines, hopefully).
>>>
>>> Lang - you want to chat about this some time? Eric & I really aren't
>>> sure who else to chat to about this.
>>>
>>>  Eric - this patch seems to be related to the issue I was discussing
>>>> at/with you yesterday. Specifically the "or when the basic block ends" part
>>>> is problematic for cases I'm looking at:
>>>>
>>>
>>>
>>>>
>>>>    1. struct foo {
>>>>    2. foo() : i(3) {}
>>>>    3. foo(const foo& f) : i(f.i) { }
>>>>    4. int i;
>>>>    5. };
>>>>    6.
>>>>    7. int func(foo f) {
>>>>    8. if (!f.i)
>>>>    9. return f.i + 1;
>>>>    10. return f.i + 2;
>>>>    11. }
>>>>    12.
>>>>    13. int main() {
>>>>    14. foo l;
>>>>    15. func(l);
>>>>    16. }
>>>>
>>>>
>>>> I get the following assembly for 'func':
>>>>
>>>>
>>>>    1.  .globl _Z4func3foo
>>>>    2.  .align 16, 0x90
>>>>    3.  .type _Z4func3foo, at function
>>>>    4. _Z4func3foo: # @_Z4func3foo
>>>>    5.  .cfi_startproc
>>>>    6. .Lfunc_begin0:
>>>>    7.  .loc 1 7 0 # test.cpp:7:0
>>>>    8. # BB#0: # %entry
>>>>    9.  pushq %rbp
>>>>    10. .Ltmp2:
>>>>    11.  .cfi_def_cfa_offset 16
>>>>    12. .Ltmp3:
>>>>    13.  .cfi_offset %rbp, -16
>>>>    14.  movq %rsp, %rbp
>>>>    15. .Ltmp4:
>>>>    16.  .cfi_def_cfa_register %rbp
>>>>    17.  #DEBUG_VALUE: func:f <- RDI
>>>>    18.  .loc 1 8 0 prologue_end # test.cpp:8:0
>>>>    19. .Ltmp5:
>>>>    20.  cmpl $0, (%rdi)
>>>>    21.  movq %rdi, -16(%rbp) # 8-byte Spill
>>>>    22. .Ltmp6: *no
>>>>    23.  #DEBUG_VALUE: func:f <- [RBP+-16]
>>>>    24.  jne .LBB0_2
>>>>    25. .Ltmp7:
>>>>    26. # BB#1: # %if.then
>>>>    27.  .loc 1 9 0 # test.cpp:9:0
>>>>    28.  movq -16(%rbp), %rax # 8-byte Reload
>>>>    29.  movl (%rax), %ecx
>>>>    30.  addl $1, %ecx
>>>>    31.  movl %ecx, -4(%rbp)
>>>>    32.  jmp .LBB0_3
>>>>    33. .Ltmp8:
>>>>    34. .LBB0_2: # %if.end
>>>>    35.  .loc 1 10 0 # test.cpp:10:0
>>>>    36.  movq -16(%rbp), %rax # 8-byte Reload
>>>>    37.  movl (%rax), %ecx
>>>>    38.  addl $2, %ecx
>>>>    39.  movl %ecx, -4(%rbp)
>>>>    40. .LBB0_3: # %return
>>>>    41.  .loc 1 11 0 # test.cpp:11:0
>>>>    42.  movl -4(%rbp), %eax
>>>>    43.  popq %rbp
>>>>    44.  ret
>>>>
>>>>
>>>
>>>>  And the debug_loc for 'func:f' is:
>>>>
>>>>
>>>>    1. .Ldebug_loc0:
>>>>    2.  .quad .Lfunc_begin0
>>>>    3.  .quad .Ltmp6
>>>>    4. .Lset0 = .Ltmp53-.Ltmp52 # Loc expr size
>>>>    5.  .short .Lset0
>>>>    6. .Ltmp52:
>>>>    7.  .byte 117 # DW_OP_breg5
>>>>    8.  .byte 0
>>>>    9. .Ltmp53:
>>>>    10.  .quad .Ltmp6
>>>>    11.  .quad .Ltmp7
>>>>    12. .Lset1 = .Ltmp55-.Ltmp54 # Loc expr size
>>>>    13.  .short .Lset1
>>>>    14. .Ltmp54:
>>>>    15.  .byte 118 # DW_OP_breg6
>>>>    16.  .byte 112
>>>>    17.  .byte 6
>>>>    18. .Ltmp55:
>>>>
>>>>
>>>> The important point being that the second range for the variable (for
>>>> -16(%rbp)) ends at the end of the first basic block. Thus for the range
>>>> tmp7-func_end we have no location information for this variable.
>>>>
>>>> This bug appears to manifest on any non-trivial-pass-by-value parameter
>>>> and any trivial pass-by-value parameter than ends up lowered to LLVM
>>>> "byval" (if it's split into multiple reg parameters then we must
>>>> reconstitute it inside the function and then we track the debug info for
>>>> that reconstituted value - probably an alloca so everything is good at -O0
>>>> at least).
>>>>
>>>> Should we be special casing indirect dbg_values and letting them past
>>>> the edge of basic blocks?
>>>> Or only ones relative to the base pointer?
>>>> Or do we need to have dbg_value MI intrinsics inserted at the beginning
>>>> of every subsequent basic block to properly communicate where variables are?
>>>> Or something else entirely.
>>>>
>>>> The code is now ready to deal with variables that are sometimes in a
>>>>> register
>>>>> and sometimes on the stack. We just need to teach emitDebugLoc to say
>>>>> 'stack
>>>>> slot'.
>>>>>
>>>>
>>>> Not sure if this /\ point is relevant, irrelevant, or something that's
>>>> been addressed since this commit. My best guess is that this comment is
>>>> just about how we describe stack slots in a location list - in that we
>>>> could describe them more compactly than reg+offset (by using fbreg instead
>>>> of breg) and we aren't. That seems like an easy special case of "is the
>>>> register the frame register, then use fbreg".
>>>>
>>>>
>>>>>
>>>>> Modified:
>>>>>     llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h
>>>>>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
>>>>>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h
>>>>>     llvm/trunk/test/CodeGen/X86/dbg-merge-loc-entry.ll
>>>>>
>>>>> Modified: llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h
>>>>> URL:
>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h?rev=128327&r1=128326&r2=128327&view=diff
>>>>>
>>>>> ==============================================================================
>>>>> --- llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h (original)
>>>>> +++ llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h Fri Mar 25
>>>>> 21:19:36 2011
>>>>> @@ -309,6 +309,10 @@
>>>>>    /// instruction in the basic block, or end()
>>>>>    iterator getLastNonDebugInstr();
>>>>>
>>>>> +  const_iterator getLastNonDebugInstr() const {
>>>>> +    return
>>>>> const_cast<MachineBasicBlock*>(this)->getLastNonDebugInstr();
>>>>> +  }
>>>>> +
>>>>>    /// SplitCriticalEdge - Split the critical edge from this block to
>>>>> the
>>>>>    /// given successor block, and return the newly created block, or
>>>>> null
>>>>>    /// if splitting is not possible.
>>>>>
>>>>> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
>>>>> URL:
>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=128327&r1=128326&r2=128327&view=diff
>>>>>
>>>>> ==============================================================================
>>>>> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
>>>>> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Fri Mar 25
>>>>> 21:19:36 2011
>>>>> @@ -2408,38 +2408,21 @@
>>>>>    /// collection info from MMI table.
>>>>>    collectVariableInfoFromMMITable(MF, Processed);
>>>>>
>>>>> -  SmallVector<const MachineInstr *, 8> DbgValues;
>>>>> -  // Collect variable information from DBG_VALUE machine instructions;
>>>>> -  for (MachineFunction::const_iterator I = Asm->MF->begin(), E =
>>>>> Asm->MF->end();
>>>>> -       I != E; ++I)
>>>>> -    for (MachineBasicBlock::const_iterator II = I->begin(), IE =
>>>>> I->end();
>>>>> -         II != IE; ++II) {
>>>>> -      const MachineInstr *MInsn = II;
>>>>> -      if (!MInsn->isDebugValue())
>>>>> -        continue;
>>>>> -      DbgValues.push_back(MInsn);
>>>>> -    }
>>>>> -
>>>>> -  // This is a collection of DBG_VALUE instructions describing same
>>>>> variable.
>>>>> -  SmallVector<const MachineInstr *, 4> MultipleValues;
>>>>> -  for(SmallVector<const MachineInstr *, 8>::iterator I =
>>>>> DbgValues.begin(),
>>>>> -        E = DbgValues.end(); I != E; ++I) {
>>>>> -    const MachineInstr *MInsn = *I;
>>>>> -    MultipleValues.clear();
>>>>> -    if (isDbgValueInDefinedReg(MInsn))
>>>>> -      MultipleValues.push_back(MInsn);
>>>>> -    DIVariable DV(MInsn->getOperand(MInsn->getNumOperands() -
>>>>> 1).getMetadata());
>>>>> -    if (Processed.count(DV) != 0)
>>>>> +  for (SmallVectorImpl<const MDNode*>::const_iterator
>>>>> +         UVI = UserVariables.begin(), UVE = UserVariables.end(); UVI
>>>>> != UVE;
>>>>> +         ++UVI) {
>>>>> +    const MDNode *Var = *UVI;
>>>>> +    if (Processed.count(Var))
>>>>>        continue;
>>>>>
>>>>> -    for (SmallVector<const MachineInstr *, 8>::iterator MI = I+1,
>>>>> -           ME = DbgValues.end(); MI != ME; ++MI) {
>>>>> -      const MDNode *Var =
>>>>> -        (*MI)->getOperand((*MI)->getNumOperands()-1).getMetadata();
>>>>> -      if (Var == DV)
>>>>> -        MultipleValues.push_back(*MI);
>>>>> -    }
>>>>> +    // History contains relevant DBG_VALUE instructions for Var and
>>>>> instructions
>>>>> +    // clobbering it.
>>>>> +    SmallVectorImpl<const MachineInstr*> &History = DbgValues[Var];
>>>>> +    if (History.empty())
>>>>> +      continue;
>>>>> +    const MachineInstr *MInsn = History.front();
>>>>>
>>>>> +    DIVariable DV(Var);
>>>>>      DbgScope *Scope = NULL;
>>>>>      if (DV.getTag() == dwarf::DW_TAG_arg_variable &&
>>>>>          DISubprogram(DV.getContext()).describes(MF->getFunction()))
>>>>> @@ -2451,6 +2434,7 @@
>>>>>        continue;
>>>>>
>>>>>      Processed.insert(DV);
>>>>> +    assert(MInsn->isDebugValue() && "History must begin with debug
>>>>> value");
>>>>>      DbgVariable *RegVar = new DbgVariable(DV);
>>>>>      if (!addCurrentFnArgument(MF, RegVar, Scope))
>>>>>        Scope->addVariable(RegVar);
>>>>> @@ -2458,21 +2442,21 @@
>>>>>        DbgVariableToDbgInstMap[AbsVar] = MInsn;
>>>>>        VarToAbstractVarMap[RegVar] = AbsVar;
>>>>>      }
>>>>> -    if (MultipleValues.size() <= 1 && !RegClobberInsn.count(MInsn)) {
>>>>> +
>>>>> +    // Simple ranges that are fully coalesced.
>>>>> +    if (History.size() <= 1 || (History.size() == 2 &&
>>>>> +
>>>>>  MInsn->isIdenticalTo(History.back()))) {
>>>>>        DbgVariableToDbgInstMap[RegVar] = MInsn;
>>>>>        continue;
>>>>>      }
>>>>>
>>>>>      // handle multiple DBG_VALUE instructions describing one variable.
>>>>> -    if (DotDebugLocEntries.empty())
>>>>> -      RegVar->setDotDebugLocOffset(0);
>>>>> -    else
>>>>> -      RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
>>>>> +    RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
>>>>>
>>>>> -    for (SmallVector<const MachineInstr *, 4>::iterator
>>>>> -           MVI = MultipleValues.begin(), MVE = MultipleValues.end();
>>>>> -         MVI != MVE; ++MVI) {
>>>>> -      const MachineInstr *Begin = *MVI;
>>>>> +    for (SmallVectorImpl<const MachineInstr*>::const_iterator
>>>>> +           HI = History.begin(), HE = History.end(); HI != HE; ++HI) {
>>>>> +      const MachineInstr *Begin = *HI;
>>>>> +      assert(Begin->isDebugValue() && "Invalid History entry");
>>>>>        MachineLocation MLoc;
>>>>>        if (Begin->getNumOperands() == 3) {
>>>>>          if (Begin->getOperand(0).isReg() &&
>>>>> Begin->getOperand(1).isImm())
>>>>> @@ -2480,6 +2464,7 @@
>>>>>        } else
>>>>>          MLoc = Asm->getDebugValueLocation(Begin);
>>>>>
>>>>> +      // FIXME: emitDebugLoc only understands registers.
>>>>>        if (!MLoc.getReg())
>>>>>          continue;
>>>>>
>>>>> @@ -2487,17 +2472,23 @@
>>>>>        const MCSymbol *FLabel = getLabelBeforeInsn(Begin);
>>>>>        const MCSymbol *SLabel = 0;
>>>>>
>>>>> -      if (const MachineInstr *ClobberMI =
>>>>> RegClobberInsn.lookup(Begin))
>>>>> -        // The register range starting at Begin may be clobbered.
>>>>> -        SLabel = getLabelAfterInsn(ClobberMI);
>>>>> -      else if (MVI + 1 == MVE)
>>>>> -        // If Begin is the last instruction then its value is valid
>>>>> +      if (HI + 1 == HE)
>>>>> +        // If Begin is the last instruction in History then its value
>>>>> is valid
>>>>>          // until the end of the funtion.
>>>>>          SLabel = FunctionEndSym;
>>>>> -      else
>>>>> -        // The value is valid until the next DBG_VALUE.
>>>>> -        SLabel = getLabelBeforeInsn(MVI[1]);
>>>>> +      else {
>>>>> +        const MachineInstr *End = HI[1];
>>>>> +        if (End->isDebugValue())
>>>>> +          SLabel = getLabelBeforeInsn(End);
>>>>> +        else {
>>>>> +          // End is a normal instruction clobbering the range.
>>>>> +          SLabel = getLabelAfterInsn(End);
>>>>> +          assert(SLabel && "Forgot label after clobber instruction");
>>>>> +          ++HI;
>>>>> +        }
>>>>> +      }
>>>>>
>>>>> +      // The value is valid until the next DBG_VALUE or clobber.
>>>>>        DotDebugLocEntries.push_back(DotDebugLocEntry(FLabel, SLabel,
>>>>> MLoc));
>>>>>      }
>>>>>      DotDebugLocEntries.push_back(DotDebugLocEntry());
>>>>> @@ -2519,21 +2510,14 @@
>>>>>
>>>>>  /// getLabelBeforeInsn - Return Label preceding the instruction.
>>>>>  const MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr
>>>>> *MI) {
>>>>> -  DenseMap<const MachineInstr *, MCSymbol *>::iterator I =
>>>>> -    LabelsBeforeInsn.find(MI);
>>>>> -  if (I == LabelsBeforeInsn.end())
>>>>> -    // FunctionBeginSym always preceeds all the instruction in
>>>>> current function.
>>>>> -    return FunctionBeginSym;
>>>>> -  return I->second;
>>>>> +  MCSymbol *Label = LabelsBeforeInsn.lookup(MI);
>>>>> +  assert(Label && "Didn't insert label before instruction");
>>>>> +  return Label;
>>>>>  }
>>>>>
>>>>>  /// getLabelAfterInsn - Return Label immediately following the
>>>>> instruction.
>>>>>  const MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI)
>>>>> {
>>>>> -  DenseMap<const MachineInstr *, MCSymbol *>::iterator I =
>>>>> -    LabelsAfterInsn.find(MI);
>>>>> -  if (I == LabelsAfterInsn.end())
>>>>> -    return NULL;
>>>>> -  return I->second;
>>>>> +  return LabelsAfterInsn.lookup(MI);
>>>>>  }
>>>>>
>>>>>  /// beginInstruction - Process beginning of an instruction.
>>>>> @@ -2552,14 +2536,22 @@
>>>>>    }
>>>>>
>>>>>    // Insert labels where requested.
>>>>> -  if (!InsnNeedsLabel.count(MI))
>>>>> +  DenseMap<const MachineInstr*, MCSymbol*>::iterator I =
>>>>> +    LabelsBeforeInsn.find(MI);
>>>>> +
>>>>> +  // No label needed.
>>>>> +  if (I == LabelsBeforeInsn.end())
>>>>> +    return;
>>>>> +
>>>>> +  // Label already assigned.
>>>>> +  if (I->second)
>>>>>      return;
>>>>>
>>>>>    if (!PrevLabel) {
>>>>>      PrevLabel = MMI->getContext().CreateTempSymbol();
>>>>>      Asm->OutStreamer.EmitLabel(PrevLabel);
>>>>>    }
>>>>> -  LabelsBeforeInsn[MI] = PrevLabel;
>>>>> +  I->second = PrevLabel;
>>>>>  }
>>>>>
>>>>>  /// endInstruction - Process end of an instruction.
>>>>> @@ -2569,7 +2561,15 @@
>>>>>    if (!MI->isDebugValue())
>>>>>      PrevLabel = 0;
>>>>>
>>>>> -  if (!InsnsNeedsLabelAfter.count(MI))
>>>>> +  DenseMap<const MachineInstr*, MCSymbol*>::iterator I =
>>>>> +    LabelsAfterInsn.find(MI);
>>>>> +
>>>>> +  // No label needed.
>>>>> +  if (I == LabelsAfterInsn.end())
>>>>> +    return;
>>>>> +
>>>>> +  // Label already assigned.
>>>>> +  if (I->second)
>>>>>      return;
>>>>>
>>>>>    // We need a label after this instruction.
>>>>> @@ -2577,7 +2577,7 @@
>>>>>      PrevLabel = MMI->getContext().CreateTempSymbol();
>>>>>      Asm->OutStreamer.EmitLabel(PrevLabel);
>>>>>    }
>>>>> -  LabelsAfterInsn[MI] = PrevLabel;
>>>>> +  I->second = PrevLabel;
>>>>>  }
>>>>>
>>>>>  /// getOrCreateDbgScope - Create DbgScope for the scope.
>>>>> @@ -2837,8 +2837,8 @@
>>>>>             RE = Ranges.end(); RI != RE; ++RI) {
>>>>>        assert(RI->first && "DbgRange does not have first
>>>>> instruction!");
>>>>>        assert(RI->second && "DbgRange does not have second
>>>>> instruction!");
>>>>> -      InsnNeedsLabel.insert(RI->first);
>>>>> -      InsnsNeedsLabelAfter.insert(RI->second);
>>>>> +      requestLabelBeforeInsn(RI->first);
>>>>> +      requestLabelAfterInsn(RI->second);
>>>>>      }
>>>>>    }
>>>>>  }
>>>>> @@ -2916,46 +2916,78 @@
>>>>>
>>>>>    recordSourceLine(Line, Col, TheScope);
>>>>>
>>>>> +  assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't
>>>>> cleaned");
>>>>> +
>>>>>    /// ProcessedArgs - Collection of arguments already processed.
>>>>>    SmallPtrSet<const MDNode *, 8> ProcessedArgs;
>>>>>
>>>>> -  /// LastDbgValue - Refer back to the last DBG_VALUE instruction to
>>>>> mention MD.
>>>>> -  DenseMap<const MDNode*, const MachineInstr*> LastDbgValue;
>>>>> -
>>>>>    const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo();
>>>>>
>>>>>    /// LiveUserVar - Map physreg numbers to the MDNode they contain.
>>>>>    std::vector<const MDNode*> LiveUserVar(TRI->getNumRegs());
>>>>>
>>>>>    for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
>>>>> -       I != E; ++I)
>>>>> +       I != E; ++I) {
>>>>> +    bool AtBlockEntry = true;
>>>>>      for (MachineBasicBlock::const_iterator II = I->begin(), IE =
>>>>> I->end();
>>>>>           II != IE; ++II) {
>>>>>        const MachineInstr *MI = II;
>>>>> -      DebugLoc DL = MI->getDebugLoc();
>>>>> +
>>>>>        if (MI->isDebugValue()) {
>>>>>          assert (MI->getNumOperands() > 1 && "Invalid machine
>>>>> instruction!");
>>>>>
>>>>> -        // Keep track of variables in registers.
>>>>> +        // Keep track of user variables.
>>>>>          const MDNode *Var =
>>>>>            MI->getOperand(MI->getNumOperands() - 1).getMetadata();
>>>>> -        LastDbgValue[Var] = MI;
>>>>> +
>>>>> +        // Variable is in a register, we need to check for clobbers.
>>>>>          if (isDbgValueInDefinedReg(MI))
>>>>>            LiveUserVar[MI->getOperand(0).getReg()] = Var;
>>>>>
>>>>> -        DIVariable DV(Var);
>>>>> -        if (!DV.Verify()) continue;
>>>>> -        // If DBG_VALUE is for a local variable then it needs a label.
>>>>> -        if (DV.getTag() != dwarf::DW_TAG_arg_variable)
>>>>> -          InsnNeedsLabel.insert(MI);
>>>>> -        // DBG_VALUE for inlined functions argument needs a label.
>>>>> -        else if (!DISubprogram(getDISubprogram(DV.getContext())).
>>>>> -                 describes(MF->getFunction()))
>>>>> -          InsnNeedsLabel.insert(MI);
>>>>> -        // DBG_VALUE indicating argument location change needs a
>>>>> label.
>>>>> -        else if (!ProcessedArgs.insert(DV))
>>>>> -          InsnNeedsLabel.insert(MI);
>>>>> +        // Check the history of this variable.
>>>>> +        SmallVectorImpl<const MachineInstr*> &History =
>>>>> DbgValues[Var];
>>>>> +        if (History.empty()) {
>>>>> +          UserVariables.push_back(Var);
>>>>> +          // The first mention of a function argument gets the
>>>>> FunctionBeginSym
>>>>> +          // label, so arguments are visible when breaking at
>>>>> function entry.
>>>>> +          DIVariable DV(Var);
>>>>> +          if (DV.Verify() && DV.getTag() ==
>>>>> dwarf::DW_TAG_arg_variable &&
>>>>> +              DISubprogram(getDISubprogram(DV.getContext()))
>>>>> +                .describes(MF->getFunction()))
>>>>> +            LabelsBeforeInsn[MI] = FunctionBeginSym;
>>>>> +        } else {
>>>>> +          // We have seen this variable before. Try to coalesce
>>>>> DBG_VALUEs.
>>>>> +          const MachineInstr *Prev = History.back();
>>>>> +          if (Prev->isDebugValue()) {
>>>>> +            // Coalesce identical entries at the end of History.
>>>>> +            if (History.size() >= 2 &&
>>>>> +                Prev->isIdenticalTo(History[History.size() - 2]))
>>>>> +              History.pop_back();
>>>>> +
>>>>> +            // Terminate old register assignments that don't reach MI;
>>>>> +            MachineFunction::const_iterator PrevMBB =
>>>>> Prev->getParent();
>>>>> +            if (PrevMBB != I && (!AtBlockEntry || llvm::next(PrevMBB)
>>>>> != I) &&
>>>>> +                isDbgValueInDefinedReg(Prev)) {
>>>>> +              // Previous register assignment needs to terminate at
>>>>> the end of
>>>>> +              // its basic block.
>>>>> +              MachineBasicBlock::const_iterator LastMI =
>>>>> +                PrevMBB->getLastNonDebugInstr();
>>>>> +              if (LastMI == PrevMBB->end())
>>>>> +                // Drop DBG_VALUE for empty range.
>>>>> +                History.pop_back();
>>>>> +              else {
>>>>> +                // Terminate after LastMI.
>>>>> +                History.push_back(LastMI);
>>>>> +              }
>>>>> +            }
>>>>> +          }
>>>>> +        }
>>>>> +        History.push_back(MI);
>>>>>        } else {
>>>>> +        // Not a DBG_VALUE instruction.
>>>>> +        if (!MI->isLabel())
>>>>> +          AtBlockEntry = false;
>>>>> +
>>>>>          // Check if the instruction clobbers any registers with debug
>>>>> vars.
>>>>>          for (MachineInstr::const_mop_iterator MOI =
>>>>> MI->operands_begin(),
>>>>>                 MOE = MI->operands_end(); MOI != MOE; ++MOI) {
>>>>> @@ -2970,19 +3002,57 @@
>>>>>              LiveUserVar[Reg] = 0;
>>>>>
>>>>>              // Was MD last defined by a DBG_VALUE referring to Reg?
>>>>> -            const MachineInstr *Last = LastDbgValue.lookup(Var);
>>>>> -            if (!Last || Last->getParent() != MI->getParent())
>>>>> +            DbgValueHistoryMap::iterator HistI = DbgValues.find(Var);
>>>>> +            if (HistI == DbgValues.end())
>>>>>                continue;
>>>>> -            if (!isDbgValueInDefinedReg(Last) ||
>>>>> -                Last->getOperand(0).getReg() != Reg)
>>>>> +            SmallVectorImpl<const MachineInstr*> &History =
>>>>> HistI->second;
>>>>> +            if (History.empty())
>>>>>                continue;
>>>>> -            // MD is clobbered. Make sure the next instruction gets a
>>>>> label.
>>>>> -            InsnsNeedsLabelAfter.insert(MI);
>>>>> -            RegClobberInsn[Last] = MI;
>>>>> +            const MachineInstr *Prev = History.back();
>>>>> +            // Sanity-check: Register assignments are terminated at
>>>>> the end of
>>>>> +            // their block.
>>>>> +            if (!Prev->isDebugValue() || Prev->getParent() !=
>>>>> MI->getParent())
>>>>> +              continue;
>>>>> +            // Is the variable still in Reg?
>>>>> +            if (!isDbgValueInDefinedReg(Prev) ||
>>>>> +                Prev->getOperand(0).getReg() != Reg)
>>>>> +              continue;
>>>>> +            // Var is clobbered. Make sure the next instruction gets
>>>>> a label.
>>>>> +            History.push_back(MI);
>>>>>            }
>>>>>          }
>>>>>        }
>>>>>      }
>>>>> +  }
>>>>> +
>>>>> +  for (DbgValueHistoryMap::iterator I = DbgValues.begin(), E =
>>>>> DbgValues.end();
>>>>> +       I != E; ++I) {
>>>>> +    SmallVectorImpl<const MachineInstr*> &History = I->second;
>>>>> +    if (History.empty())
>>>>> +      continue;
>>>>> +
>>>>> +    // Make sure the final register assignments are terminated.
>>>>> +    const MachineInstr *Prev = History.back();
>>>>> +    if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) {
>>>>> +      const MachineBasicBlock *PrevMBB = Prev->getParent();
>>>>> +      MachineBasicBlock::const_iterator LastMI =
>>>>> PrevMBB->getLastNonDebugInstr();
>>>>> +      if (LastMI == PrevMBB->end())
>>>>> +        // Drop DBG_VALUE for empty range.
>>>>> +        History.pop_back();
>>>>> +      else {
>>>>> +        // Terminate after LastMI.
>>>>> +        History.push_back(LastMI);
>>>>> +      }
>>>>> +    }
>>>>> +    // Request labels for the full history.
>>>>> +    for (unsigned i = 0, e = History.size(); i != e; ++i) {
>>>>> +      const MachineInstr *MI = History[i];
>>>>> +      if (MI->isDebugValue())
>>>>> +        requestLabelBeforeInsn(MI);
>>>>> +      else
>>>>> +        requestLabelAfterInsn(MI);
>>>>> +    }
>>>>> +  }
>>>>>
>>>>>    PrevInstLoc = DebugLoc();
>>>>>    PrevLabel = FunctionBeginSym;
>>>>> @@ -3043,13 +3113,12 @@
>>>>>    // Clear debug info
>>>>>    CurrentFnDbgScope = NULL;
>>>>>    CurrentFnArguments.clear();
>>>>> -  InsnNeedsLabel.clear();
>>>>>    DbgVariableToFrameIndexMap.clear();
>>>>>    VarToAbstractVarMap.clear();
>>>>>    DbgVariableToDbgInstMap.clear();
>>>>>    DeleteContainerSeconds(DbgScopeMap);
>>>>> -  InsnsNeedsLabelAfter.clear();
>>>>> -  RegClobberInsn.clear();
>>>>> +  UserVariables.clear();
>>>>> +  DbgValues.clear();
>>>>>    ConcreteScopes.clear();
>>>>>    DeleteContainerSeconds(AbstractScopes);
>>>>>    AbstractScopesList.clear();
>>>>>
>>>>> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h
>>>>> URL:
>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=128327&r1=128326&r2=128327&view=diff
>>>>>
>>>>> ==============================================================================
>>>>> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h (original)
>>>>> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Fri Mar 25 21:19:36
>>>>> 2011
>>>>> @@ -218,19 +218,16 @@
>>>>>    /// instruction.
>>>>>    DenseMap<const MachineInstr *, MCSymbol *> LabelsAfterInsn;
>>>>>
>>>>> -  /// insnNeedsLabel - Collection of instructions that need a label
>>>>> to mark
>>>>> -  /// a debuggging information entity.
>>>>> -  SmallPtrSet<const MachineInstr *, 8> InsnNeedsLabel;
>>>>> -
>>>>> -  /// InsnsNeedsLabelAfter - Collection of instructions that need a
>>>>> label after
>>>>> -  /// the instruction because they end a scope of clobber a register.
>>>>> -  SmallPtrSet<const MachineInstr *, 8> InsnsNeedsLabelAfter;
>>>>> -
>>>>> -  /// RegClobberInsn - For each DBG_VALUE instruction referring to a
>>>>> register
>>>>> -  /// that is clobbered before the variable gets a new DBG_VALUE, map
>>>>> the
>>>>> -  /// instruction that clobbered the register. This instruction will
>>>>> also be in
>>>>> -  /// InsnsNeedsLabelAfter.
>>>>> -  DenseMap<const MachineInstr *, const MachineInstr *> RegClobberInsn;
>>>>> +  /// UserVariables - Every user variable mentioned by a DBG_VALUE
>>>>> instruction
>>>>> +  /// in order of appearance.
>>>>> +  SmallVector<const MDNode*, 8> UserVariables;
>>>>> +
>>>>> +  /// DbgValues - For each user variable, keep a list of DBG_VALUE
>>>>> +  /// instructions in order. The list can also contain normal
>>>>> instructions that
>>>>> +  /// clobber the previous DBG_VALUE.
>>>>> +  typedef DenseMap<const MDNode*, SmallVector<const MachineInstr*, 4>
>>>>> >
>>>>> +    DbgValueHistoryMap;
>>>>> +  DbgValueHistoryMap DbgValues;
>>>>>
>>>>>    SmallVector<const MCSymbol *, 8> DebugRangeSymbols;
>>>>>
>>>>> @@ -570,6 +567,23 @@
>>>>>    /// side table maintained by MMI.
>>>>>    void collectVariableInfoFromMMITable(const MachineFunction * MF,
>>>>>                                         SmallPtrSet<const MDNode *,
>>>>> 16> &P);
>>>>> +
>>>>> +  /// requestLabelBeforeInsn - Ensure that a label will be emitted
>>>>> before MI.
>>>>> +  void requestLabelBeforeInsn(const MachineInstr *MI) {
>>>>> +    LabelsBeforeInsn.insert(std::make_pair(MI, (MCSymbol*)0));
>>>>> +  }
>>>>> +
>>>>> +  /// getLabelBeforeInsn - Return Label preceding the instruction.
>>>>> +  const MCSymbol *getLabelBeforeInsn(const MachineInstr *MI);
>>>>> +
>>>>> +  /// requestLabelAfterInsn - Ensure that a label will be emitted
>>>>> after MI.
>>>>> +  void requestLabelAfterInsn(const MachineInstr *MI) {
>>>>> +    LabelsAfterInsn.insert(std::make_pair(MI, (MCSymbol*)0));
>>>>> +  }
>>>>> +
>>>>> +  /// getLabelAfterInsn - Return Label immediately following the
>>>>> instruction.
>>>>> +  const MCSymbol *getLabelAfterInsn(const MachineInstr *MI);
>>>>> +
>>>>>  public:
>>>>>
>>>>>  //===--------------------------------------------------------------------===//
>>>>>    // Main entry points.
>>>>> @@ -593,12 +607,6 @@
>>>>>    ///
>>>>>    void endFunction(const MachineFunction *MF);
>>>>>
>>>>> -  /// getLabelBeforeInsn - Return Label preceding the instruction.
>>>>> -  const MCSymbol *getLabelBeforeInsn(const MachineInstr *MI);
>>>>> -
>>>>> -  /// getLabelAfterInsn - Return Label immediately following the
>>>>> instruction.
>>>>> -  const MCSymbol *getLabelAfterInsn(const MachineInstr *MI);
>>>>> -
>>>>>    /// beginInstruction - Process beginning of an instruction.
>>>>>    void beginInstruction(const MachineInstr *MI);
>>>>>
>>>>>
>>>>> Modified: llvm/trunk/test/CodeGen/X86/dbg-merge-loc-entry.ll
>>>>> URL:
>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/dbg-merge-loc-entry.ll?rev=128327&r1=128326&r2=128327&view=diff
>>>>>
>>>>> ==============================================================================
>>>>> --- llvm/trunk/test/CodeGen/X86/dbg-merge-loc-entry.ll (original)
>>>>> +++ llvm/trunk/test/CodeGen/X86/dbg-merge-loc-entry.ll Fri Mar 25
>>>>> 21:19:36 2011
>>>>> @@ -4,7 +4,7 @@
>>>>>
>>>>>  ;CHECK: Ldebug_loc0:
>>>>>  ;CHECK-NEXT:   .quad   Lfunc_begin0
>>>>> -;CHECK-NEXT:   .quad   Lfunc_end0
>>>>> +;CHECK-NEXT:   .quad   L
>>>>>  ;CHECK-NEXT:   .short  1                       ## Loc expr size
>>>>>  ;CHECK-NEXT:   .byte   85                      ## DW_OP_reg5
>>>>>  ;CHECK-NEXT:   .quad   0
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> llvm-commits mailing list
>>>>> llvm-commits at cs.uiuc.edu
>>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>>>>
>>>>
>>>>
>>>
>>
>


-- 
Alexey Samsonov, MSK
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20131202/abaa51da/attachment.html>


More information about the llvm-commits mailing list