summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
diff options
context:
space:
mode:
authorBjorn Pettersson <bjorn.a.pettersson@ericsson.com>2019-02-11 19:23:30 +0000
committerBjorn Pettersson <bjorn.a.pettersson@ericsson.com>2019-02-11 19:23:30 +0000
commit4892f06e06cc5c987dfb77bfe13a91e1b1b00524 (patch)
treebfffbe5b52f185aa448d75592b3512b11427babc /llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
parent605b21739d4b339d745d982c359e073a9b92a1ca (diff)
downloadbcm5719-llvm-4892f06e06cc5c987dfb77bfe13a91e1b1b00524.tar.gz
bcm5719-llvm-4892f06e06cc5c987dfb77bfe13a91e1b1b00524.zip
[SelectionDAGBuilder] Add restrictions to EmitFuncArgumentDbgValue
Summary: This patch fixes PR40587. When a dbg.value instrinsic is emitted to the DAG by using EmitFuncArgumentDbgValue the resulting DBG_VALUE is hoisted to the beginning of the entry block. I think the idea is to be able to locate a formal argument already from the start of the function. However, EmitFuncArgumentDbgValue only checked that the value that was used to describe a variable was originating from a function parameter, not that the variable itself actually was an argument to the function. So when for example assigning a local variable "local" the value from an argument "a", the assocated DBG_VALUE instruction would be hoisted to the beginning of the function, even if the scope for "local" started somewhere else (or if "local" was mapped to other values earlier in the function). This patch adds some logic to EmitFuncArgumentDbgValue to check that the variable being described actually is an argument to the function. And that the dbg.value being lowered already is in the entry block. Otherwise we bail out, and the dbg.value will be handled as an ordinary dbg.value (not as a "FuncArgumentDbgValue"). A tricky situation is when both the variable and the value is related to function arguments, but not neccessarily the same argument. We make sure that we do not describe the same argument more than once as a "FuncArgumentDbgValue". This solution works as long as opt has injected a "first" dbg.value that corresponds to the formal argument at the function entry. Reviewers: jmorse, aprantl Subscribers: jyknight, hiraditya, fedor.sergeev, dstenb, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D57702 llvm-svn: 353735
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp71
1 files changed, 71 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index e3c6ddefc3c..a5b43bc0a8e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1156,6 +1156,12 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
"Expected inlined-at fields to agree");
SDDbgValue *SDV;
if (Val.getNode()) {
+ // FIXME: I doubt that it is correct to resolve a dangling DbgValue as a
+ // FuncArgumentDbgValue (it would be hoisted to the function entry, and if
+ // we couldn't resolve it directly when examining the DbgValue intrinsic
+ // in the first place we should not be more successful here). Unless we
+ // have some test case that prove this to be correct we should avoid
+ // calling EmitFuncArgumentDbgValue here.
if (!EmitFuncArgumentDbgValue(V, Variable, Expr, dl, false, Val)) {
LLVM_DEBUG(dbgs() << "Resolve dangling debug info [order="
<< DbgSDNodeOrder << "] for:\n " << *DI << "\n");
@@ -5003,6 +5009,71 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
if (!Arg)
return false;
+ if (!IsDbgDeclare) {
+ // ArgDbgValues are hoisted to the beginning of the entry block. So we
+ // should only emit as ArgDbgValue if the dbg.value intrinsic is found in
+ // the entry block.
+ bool IsInEntryBlock = FuncInfo.MBB == &FuncInfo.MF->front();
+ if (!IsInEntryBlock)
+ return false;
+
+ // ArgDbgValues are hoisted to the beginning of the entry block. So we
+ // should only emit as ArgDbgValue if the dbg.value intrinsic describes a
+ // variable that also is a param.
+ //
+ // Although, if we are at the top of the entry block already, we can still
+ // emit using ArgDbgValue. This might catch some situations when the
+ // dbg.value refers to an argument that isn't used in the entry block, so
+ // any CopyToReg node would be optimized out and the only way to express
+ // this DBG_VALUE is by using the physical reg (or FI) as done in this
+ // method. ArgDbgValues are hoisted to the beginning of the entry block. So
+ // we should only emit as ArgDbgValue if the Variable is an argument to the
+ // current function, and the dbg.value intrinsic is found in the entry
+ // block.
+ bool VariableIsFunctionInputArg = Variable->isParameter() &&
+ !DL->getInlinedAt();
+ bool IsInPrologue = SDNodeOrder == LowestSDNodeOrder;
+ if (!IsInPrologue && !VariableIsFunctionInputArg)
+ return false;
+
+ // Here we assume that a function argument on IR level only can be used to
+ // describe one input parameter on source level. If we for example have
+ // source code like this
+ //
+ // struct A { long x, y; };
+ // void foo(struct A a, long b) {
+ // ...
+ // b = a.x;
+ // ...
+ // }
+ //
+ // and IR like this
+ //
+ // define void @foo(i32 %a1, i32 %a2, i32 %b) {
+ // entry:
+ // call void @llvm.dbg.value(metadata i32 %a1, "a", DW_OP_LLVM_fragment
+ // call void @llvm.dbg.value(metadata i32 %a2, "a", DW_OP_LLVM_fragment
+ // call void @llvm.dbg.value(metadata i32 %b, "b",
+ // ...
+ // call void @llvm.dbg.value(metadata i32 %a1, "b"
+ // ...
+ //
+ // then the last dbg.value is describing a parameter "b" using a value that
+ // is an argument. But since we already has used %a1 to describe a parameter
+ // we should not handle that last dbg.value here (that would result in an
+ // incorrect hoisting of the DBG_VALUE to the function entry).
+ // Notice that we allow one dbg.value per IR level argument, to accomodate
+ // for the situation with fragments above.
+ if (VariableIsFunctionInputArg) {
+ unsigned ArgNo = Arg->getArgNo();
+ if (ArgNo >= FuncInfo.DescribedArgs.size())
+ FuncInfo.DescribedArgs.resize(ArgNo + 1, false);
+ else if (!IsInPrologue && FuncInfo.DescribedArgs.test(ArgNo))
+ return false;
+ FuncInfo.DescribedArgs.set(ArgNo);
+ }
+ }
+
MachineFunction &MF = DAG.getMachineFunction();
const TargetInstrInfo *TII = DAG.getSubtarget().getInstrInfo();
OpenPOWER on IntegriCloud