[llvm-branch-commits] [llvm] 0f56ce0 - [DebugInfo][InstrRef] Avoid a crash from mixed variable location modes
Tom Stellard via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Apr 18 17:10:04 PDT 2022
Author: Jeremy Morse
Date: 2022-04-18T17:07:38-07:00
New Revision: 0f56ce0fb2079c8f1fdcb7f7199d7313f81a863d
URL: https://github.com/llvm/llvm-project/commit/0f56ce0fb2079c8f1fdcb7f7199d7313f81a863d
DIFF: https://github.com/llvm/llvm-project/commit/0f56ce0fb2079c8f1fdcb7f7199d7313f81a863d.diff
LOG: [DebugInfo][InstrRef] Avoid a crash from mixed variable location modes
Variable locations now come in two modes, instruction referencing and
DBG_VALUE. At -O0 we pick DBG_VALUE to allow fast construction of variable
information. Unfortunately, SelectionDAG edits the optimisation level in
the presence of opt-bisect-limit, meaning different passes have different
views of what variable location mode we should use. That causes assertions
when they're mixed.
This patch plumbs through a boolean in SelectionDAG from start to
instruction emission, so that we don't rely on the current optimisation
level for correctness.
Differential Revision: https://reviews.llvm.org/D123033
(cherry picked from commit fb6596f1ecab652b5b90cf2e395d64112504c1f8)
Added:
llvm/test/DebugInfo/X86/instr-ref-opt-bisect.ll
Modified:
llvm/include/llvm/CodeGen/FastISel.h
llvm/include/llvm/CodeGen/SelectionDAG.h
llvm/include/llvm/CodeGen/SelectionDAGISel.h
llvm/lib/CodeGen/MachineFunction.cpp
llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h
llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp
llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/FastISel.h b/llvm/include/llvm/CodeGen/FastISel.h
index 775698a66adae..6de8ac4273f73 100644
--- a/llvm/include/llvm/CodeGen/FastISel.h
+++ b/llvm/include/llvm/CodeGen/FastISel.h
@@ -212,6 +212,7 @@ class FastISel {
const TargetRegisterInfo &TRI;
const TargetLibraryInfo *LibInfo;
bool SkipTargetIndependentISel;
+ bool UseInstrRefDebugInfo = false;
/// The position of the last instruction for materializing constants
/// for use in the current block. It resets to EmitStartPt when it makes sense
@@ -318,6 +319,12 @@ class FastISel {
/// Reset InsertPt to the given old insert position.
void leaveLocalValueArea(SavePoint Old);
+ /// Signal whether instruction referencing variable locations are desired for
+ /// this function's debug-info.
+ void useInstrRefDebugInfo(bool Flag) {
+ UseInstrRefDebugInfo = Flag;
+ }
+
protected:
explicit FastISel(FunctionLoweringInfo &FuncInfo,
const TargetLibraryInfo *LibInfo,
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index e31719bcff0b9..4f348c9feaa5f 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -278,6 +278,9 @@ class SelectionDAG {
uint16_t NextPersistentId = 0;
+ /// Are instruction referencing variable locations desired for this function?
+ bool UseInstrRefDebugInfo = false;
+
public:
/// Clients of various APIs that cause global effects on
/// the DAG can optionally implement this interface. This allows the clients
@@ -1702,6 +1705,16 @@ class SelectionDAG {
/// function mirrors \c llvm::salvageDebugInfo.
void salvageDebugInfo(SDNode &N);
+ /// Signal whether instruction referencing variable locations are desired for
+ /// this function's debug-info.
+ void useInstrRefDebugInfo(bool Flag) {
+ UseInstrRefDebugInfo = Flag;
+ }
+
+ bool getUseInstrRefDebugInfo() const {
+ return UseInstrRefDebugInfo;
+ }
+
void dump() const;
/// In most cases this function returns the ABI alignment for a given type,
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/llvm/include/llvm/CodeGen/SelectionDAGISel.h
index 9cea197724cc6..fc3fdf3e4583d 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGISel.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGISel.h
@@ -53,6 +53,7 @@ class SelectionDAGISel : public MachineFunctionPass {
const TargetLowering *TLI;
bool FastISelFailed;
SmallPtrSet<const Instruction *, 4> ElidedArgCopyInstrs;
+ bool UseInstrRefDebugInfo = false;
/// Current optimization remark emitter.
/// Used to report things like combines and FastISel failures.
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index fd5ea5cad072c..02f58ca5eef05 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -1181,9 +1181,6 @@ void MachineFunction::finalizeDebugInstrRefs() {
MI.getOperand(1).ChangeToRegister(0, false);
};
- if (!useDebugInstrRef())
- return;
-
for (auto &MBB : *this) {
for (auto &MI : MBB) {
if (!MI.isDebugRef() || !MI.getOperand(0).isReg())
diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
index d8ef79fe9a7bc..87a1ebe4c1db7 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -1265,7 +1265,7 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) {
// If using instruction referencing, mutate this into a DBG_INSTR_REF,
// to be later patched up by finalizeDebugInstrRefs. Tack a deref onto
// the expression, we don't have an "indirect" flag in DBG_INSTR_REF.
- if (FuncInfo.MF->useDebugInstrRef() && Op->isReg()) {
+ if (UseInstrRefDebugInfo && Op->isReg()) {
Builder->setDesc(TII.get(TargetOpcode::DBG_INSTR_REF));
Builder->getOperand(1).ChangeToImmediate(0);
auto *NewExpr =
@@ -1324,7 +1324,7 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) {
// If using instruction referencing, mutate this into a DBG_INSTR_REF,
// to be later patched up by finalizeDebugInstrRefs.
- if (FuncInfo.MF->useDebugInstrRef()) {
+ if (UseInstrRefDebugInfo) {
Builder->setDesc(TII.get(TargetOpcode::DBG_INSTR_REF));
Builder->getOperand(1).ChangeToImmediate(0);
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
index 331e0325aea30..e3e05c868102c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
@@ -1341,11 +1341,12 @@ EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned,
/// InstrEmitter - Construct an InstrEmitter and set it to start inserting
/// at the given position in the given block.
InstrEmitter::InstrEmitter(const TargetMachine &TM, MachineBasicBlock *mbb,
- MachineBasicBlock::iterator insertpos)
+ MachineBasicBlock::iterator insertpos,
+ bool UseInstrRefDebugInfo)
: MF(mbb->getParent()), MRI(&MF->getRegInfo()),
TII(MF->getSubtarget().getInstrInfo()),
TRI(MF->getSubtarget().getRegisterInfo()),
TLI(MF->getSubtarget().getTargetLowering()), MBB(mbb),
InsertPos(insertpos) {
- EmitDebugInstrRefs = MF->useDebugInstrRef();
+ EmitDebugInstrRefs = UseInstrRefDebugInfo;
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h
index ac8a70156522a..ced8f064b9be7 100644
--- a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h
+++ b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h
@@ -154,7 +154,8 @@ class LLVM_LIBRARY_VISIBILITY InstrEmitter {
/// InstrEmitter - Construct an InstrEmitter and set it to start inserting
/// at the given position in the given block.
InstrEmitter(const TargetMachine &TM, MachineBasicBlock *mbb,
- MachineBasicBlock::iterator insertpos);
+ MachineBasicBlock::iterator insertpos,
+ bool UseInstrRefDebugInfo);
private:
void EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned,
diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp
index 1b89864116cb9..1a6be0cc2091a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp
@@ -758,7 +758,8 @@ void ScheduleDAGLinearize::Schedule() {
MachineBasicBlock*
ScheduleDAGLinearize::EmitSchedule(MachineBasicBlock::iterator &InsertPos) {
- InstrEmitter Emitter(DAG->getTarget(), BB, InsertPos);
+ InstrEmitter Emitter(DAG->getTarget(), BB, InsertPos,
+ DAG->getUseInstrRefDebugInfo());
DenseMap<SDValue, Register> VRBaseMap;
LLVM_DEBUG({ dbgs() << "\n*** Final schedule ***\n"; });
diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
index 55f6f288f3e3a..92897aca7f6b0 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
@@ -843,7 +843,8 @@ EmitPhysRegCopy(SUnit *SU, DenseMap<SUnit*, Register> &VRBaseMap,
/// not necessarily refer to returned BB. The emitter may split blocks.
MachineBasicBlock *ScheduleDAGSDNodes::
EmitSchedule(MachineBasicBlock::iterator &InsertPos) {
- InstrEmitter Emitter(DAG->getTarget(), BB, InsertPos);
+ InstrEmitter Emitter(DAG->getTarget(), BB, InsertPos,
+ DAG->getUseInstrRefDebugInfo());
DenseMap<SDValue, Register> VRBaseMap;
DenseMap<SUnit*, Register> CopyVRBaseMap;
SmallVector<std::pair<unsigned, MachineInstr*>, 32> Orders;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 3c786904620a1..b83a60129c786 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -425,6 +425,11 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {
const Function &Fn = mf.getFunction();
MF = &mf;
+ // Decide what flavour of variable location debug-info will be used, before
+ // we change the optimisation level.
+ UseInstrRefDebugInfo = mf.useDebugInstrRef();
+ CurDAG->useInstrRefDebugInfo(UseInstrRefDebugInfo);
+
// Reset the target options before resetting the optimization
// level below.
// FIXME: This is a horrible hack and should be processed via
@@ -654,7 +659,8 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {
// For debug-info, in instruction referencing mode, we need to perform some
// post-isel maintenence.
- MF->finalizeDebugInstrRefs();
+ if (UseInstrRefDebugInfo)
+ MF->finalizeDebugInstrRefs();
// Determine if there are any calls in this machine function.
MachineFrameInfo &MFI = MF->getFrameInfo();
@@ -1380,6 +1386,8 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
if (TM.Options.EnableFastISel) {
LLVM_DEBUG(dbgs() << "Enabling fast-isel\n");
FastIS = TLI->createFastISel(*FuncInfo, LibInfo);
+ if (FastIS)
+ FastIS->useInstrRefDebugInfo(UseInstrRefDebugInfo);
}
ReversePostOrderTraversal<const Function*> RPOT(&Fn);
diff --git a/llvm/test/DebugInfo/X86/instr-ref-opt-bisect.ll b/llvm/test/DebugInfo/X86/instr-ref-opt-bisect.ll
new file mode 100644
index 0000000000000..3afa9e611c121
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/instr-ref-opt-bisect.ll
@@ -0,0 +1,117 @@
+; RUN: llc %s -o - -stop-after=livedebugvalues -opt-bisect-limit=0 \
+; RUN: | FileCheck %s
+; RUN: llc %s -o - -stop-after=livedebugvalues -opt-bisect-limit=10 \
+; RUN: | FileCheck %s
+; RUN: llc %s -o - -stop-after=livedebugvalues -opt-bisect-limit=20 \
+; RUN: | FileCheck %s
+; RUN: llc %s -o - -stop-after=livedebugvalues -opt-bisect-limit=30 \
+; RUN: | FileCheck %s
+; RUN: llc %s -o - -stop-after=livedebugvalues -opt-bisect-limit=40 \
+; RUN: | FileCheck %s
+; RUN: llc %s -o - -stop-after=livedebugvalues -opt-bisect-limit=100 \
+; RUN: | FileCheck %s
+;; Test fast-isel for good measure too,
+; RUN: llc %s -o - -stop-after=livedebugvalues -fast-isel=true \
+; RUN: | FileCheck %s
+; RUN: llc %s -o - -stop-after=livedebugvalues -fast-isel=true \
+; RUN: -opt-bisect-limit=0 | FileCheck %s
+; RUN: llc %s -o - -stop-after=livedebugvalues -fast-isel=true \
+; RUN: -opt-bisect-limit=10 | FileCheck %s
+; RUN: llc %s -o - -stop-after=livedebugvalues -fast-isel=true \
+; RUN: -opt-bisect-limit=100 | FileCheck %s
+
+; The function below should be optimised with the "default" optimisation level.
+; However, opt-bisect-limit causes SelectionDAG to change the target settings
+; for the duration of SelectionDAG. This can lead to variable locations created
+; in one mode, but the rest of the debug-info analyses expecting the other.
+; Test that opt-bisect-limit can be used without any assertions firing, and
+; that instruction referencing instructions are seen each time.
+;
+; The selection of bisect positions above are not picked meaningfully, the
+; pass order and positioning will change over time. The most important part
+; is that the bisect limit sits between SelectionDAG and debug-info passes at
+; some point.
+
+; CHECK: DBG_INSTR_REF
+; CHECK: DBG_PHI
+
+; ModuleID = '/tmp/test.cpp'
+source_filename = "/tmp/test.cpp"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%class.Class = type { i8 }
+
+; Function Attrs: mustprogress uwtable
+define dso_local void @_Z4FuncP5Class(%class.Class* noundef %c) local_unnamed_addr !dbg !7 {
+entry:
+ call void @llvm.dbg.value(metadata %class.Class* %c, metadata !15, metadata !DIExpression()), !dbg !16
+ %tobool.not = icmp eq %class.Class* %c, null, !dbg !17
+ br i1 %tobool.not, label %land.lhs.true, label %if.end, !dbg !19
+
+land.lhs.true: ; preds = %entry
+ %call = call noundef zeroext i1 @_Z4Condv(), !dbg !20
+ call void @llvm.assume(i1 %call), !dbg !21
+ %call1 = call noalias noundef nonnull dereferenceable(1) i8* @_Znwm(i64 noundef 1), !dbg !22, !heapallocsite !12
+ %0 = bitcast i8* %call1 to %class.Class*, !dbg !22
+ call void @llvm.dbg.value(metadata %class.Class* %0, metadata !15, metadata !DIExpression()), !dbg !16
+ br label %if.end, !dbg !23
+
+if.end: ; preds = %land.lhs.true, %entry
+ %c.addr.0 = phi %class.Class* [ %c, %entry ], [ %0, %land.lhs.true ]
+ call void @llvm.dbg.value(metadata %class.Class* %c.addr.0, metadata !15, metadata !DIExpression()), !dbg !16
+ call void @_Z11DoSomethingR5Class(%class.Class* noundef nonnull align 1 dereferenceable(1) %c.addr.0), !dbg !24
+ ret void, !dbg !25
+}
+
+declare !dbg !26 dso_local noundef zeroext i1 @_Z4Condv() local_unnamed_addr
+
+; Function Attrs: nobuiltin allocsize(0)
+declare dso_local noundef nonnull i8* @_Znwm(i64 noundef) local_unnamed_addr
+
+declare !dbg !30 dso_local void @_Z11DoSomethingR5Class(%class.Class* noundef nonnull align 1 dereferenceable(1)) local_unnamed_addr
+
+; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+; Function Attrs: inaccessiblememonly nocallback nofree nosync nounwind willreturn
+declare void @llvm.assume(i1 noundef)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "/tmp/test.cpp", directory: ".")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"uwtable", i32 2}
+!6 = !{!"clang"}
+!7 = distinct !DISubprogram(name: "Func", linkageName: "_Z4FuncP5Class", scope: !8, file: !8, line: 6, type: !9, scopeLine: 6, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14)
+!8 = !DIFile(filename: "/tmp/test.cpp", directory: "")
+!9 = !DISubroutineType(types: !10)
+!10 = !{null, !11}
+!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
+!12 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "Class", file: !8, line: 3, size: 8, flags: DIFlagTypePassByValue, elements: !13, identifier: "_ZTS5Class")
+!13 = !{}
+!14 = !{!15}
+!15 = !DILocalVariable(name: "c", arg: 1, scope: !7, file: !8, line: 6, type: !11)
+!16 = !DILocation(line: 0, scope: !7)
+!17 = !DILocation(line: 7, column: 10, scope: !18)
+!18 = distinct !DILexicalBlock(scope: !7, file: !8, line: 7, column: 9)
+!19 = !DILocation(line: 7, column: 12, scope: !18)
+!20 = !DILocation(line: 7, column: 15, scope: !18)
+!21 = !DILocation(line: 7, column: 9, scope: !7)
+!22 = !DILocation(line: 8, column: 13, scope: !18)
+!23 = !DILocation(line: 8, column: 9, scope: !18)
+!24 = !DILocation(line: 10, column: 5, scope: !7)
+!25 = !DILocation(line: 11, column: 1, scope: !7)
+!26 = !DISubprogram(name: "Cond", linkageName: "_Z4Condv", scope: !8, file: !8, line: 5, type: !27, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !13)
+!27 = !DISubroutineType(types: !28)
+!28 = !{!29}
+!29 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean)
+!30 = !DISubprogram(name: "DoSomething", linkageName: "_Z11DoSomethingR5Class", scope: !8, file: !8, line: 4, type: !31, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !13)
+!31 = !DISubroutineType(types: !32)
+!32 = !{null, !33}
+!33 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !12, size: 64)
More information about the llvm-branch-commits
mailing list