Skip to content

Commit c6b245f

Browse files
[SelectionDAG] Reland debuginfo salvage for load/ext combines (llvm#194700)
This relands fe5d5b7, which salvages debug info when folding load and zext/sext patterns in SelectionDAG. Salvage debuginfo when combining load and z|s ext instrs. SelectionDAG uses the DAGCombiner to fold a load followed by a sext to a load and sext instruction. For example, in x86 we will see that ``` %1 = load i32, ptr @GloBaRR #dbg_value(i32 %1, !43, !DIExpression(), !52) %2 = sext i32 %1 to i64, !dbg !53 ``` is converted to: ``` %0:gr64_nosp = MOVSX64rm32 $rip, 1, $noreg, @GloBaRR, $noreg, debug-instr-number 1, debug-location !51 DBG_VALUE $noreg, $noreg, !"Idx", !DIExpression(), debug-location !52 ``` The `DBG_VALUE` needs to be transferred correctly to the new combined instruction, and it needs to be appended with a `DIExpression` which contains a `DW_OP_LLVM_convert` expression, which correctly casts the value in the virtual register to the correct size. This patch fixes the above described problem. The patch also accounts for multiple DW_OP_LLVM_arg's in a DIExpression which had caused it to break tests on the sanitizer-x86_64-linux bot but has now been fixed, with an added testcase called selectionDAG-load-zext-multiple-args.ll which was reduced from the broken test itself. fe5d5b7 exposed a crash in tryToFoldExtOfLoad(), which is described in llvm#193475 Fix that by replacing the folded node before deleting or rewriting the old nodes, and by transferring debug values before entering the replacement path. Add an X86 regression test for the extload combine crash.
1 parent 330a8f9 commit c6b245f

5 files changed

Lines changed: 296 additions & 3 deletions

File tree

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include "llvm/IR/Attributes.h"
5353
#include "llvm/IR/Constant.h"
5454
#include "llvm/IR/DataLayout.h"
55+
#include "llvm/IR/DebugInfoMetadata.h"
5556
#include "llvm/IR/DerivedTypes.h"
5657
#include "llvm/IR/Function.h"
5758
#include "llvm/IR/Metadata.h"
@@ -79,6 +80,7 @@
7980
#include <variant>
8081

8182
#include "MatchContext.h"
83+
#include "SDNodeDbgValue.h"
8284

8385
using namespace llvm;
8486
using namespace llvm::SDPatternMatch;
@@ -14987,6 +14989,7 @@ static SDValue tryToFoldExtOfLoad(SelectionDAG &DAG, DAGCombiner &Combiner,
1498714989
ISD::LoadExtType ExtLoadType,
1498814990
ISD::NodeType ExtOpc,
1498914991
bool NonNegZExt = false) {
14992+
1499014993
bool Frozen = N0.getOpcode() == ISD::FREEZE;
1499114994
SDValue Freeze = Frozen ? N0 : SDValue();
1499214995
auto *Load = dyn_cast<LoadSDNode>(Frozen ? N0.getOperand(0) : N0);
@@ -15030,8 +15033,80 @@ static SDValue tryToFoldExtOfLoad(SelectionDAG &DAG, DAGCombiner &Combiner,
1503015033
return {};
1503115034

1503215035
SDLoc DL(Load);
15033-
// If the load value is used only by N, replace it via CombineTo N.
15034-
bool NoReplaceTrunc = N0.hasOneUse();
15036+
15037+
auto SalvageDbgValue = [&](SDDbgValue *Dbg, SDValue Old, SDValue New,
15038+
unsigned OldBits, unsigned NewBits,
15039+
bool IsSigned) {
15040+
SmallVector<SDDbgOperand> Locs = Dbg->copyLocationOps();
15041+
bool Changed = false;
15042+
15043+
bool IsVariadic = Dbg->isVariadic();
15044+
SmallVector<unsigned, 2> AffectedArgs;
15045+
15046+
for (unsigned I = 0, E = Locs.size(); I != E; ++I) {
15047+
SDDbgOperand &Op = Locs[I];
15048+
if (Op.getKind() != SDDbgOperand::SDNODE)
15049+
continue;
15050+
15051+
if (Op.getSDNode() == Old.getNode() && Op.getResNo() == Old.getResNo()) {
15052+
Op = SDDbgOperand::fromNode(New.getNode(), New.getResNo());
15053+
Changed = true;
15054+
15055+
if (IsVariadic)
15056+
AffectedArgs.push_back(I);
15057+
}
15058+
}
15059+
15060+
if (!Changed)
15061+
return;
15062+
15063+
const DIExpression *OldExpr = Dbg->getExpression();
15064+
const DIExpression *NewExpr = nullptr;
15065+
15066+
if (!IsVariadic) {
15067+
// Do not introduce DW_OP_LLVM_arg into ordinary single-location
15068+
// DBG_VALUEs.
15069+
NewExpr = DIExpression::appendExt(OldExpr, NewBits, OldBits, IsSigned);
15070+
} else {
15071+
auto ExtOps = DIExpression::getExtOps(NewBits, OldBits, IsSigned);
15072+
15073+
NewExpr = DIExpression::convertToVariadicExpression(OldExpr);
15074+
15075+
for (unsigned ArgNo : AffectedArgs)
15076+
NewExpr = DIExpression::appendOpsToArg(NewExpr, ExtOps, ArgNo,
15077+
/*StackValue=*/false);
15078+
}
15079+
15080+
SDDbgValue *NewDV = DAG.getDbgValueList(
15081+
Dbg->getVariable(), const_cast<DIExpression *>(NewExpr), Locs,
15082+
Dbg->getAdditionalDependencies(), Dbg->isIndirect(), Dbg->getDebugLoc(),
15083+
Dbg->getOrder(), Dbg->isVariadic());
15084+
15085+
Dbg->setIsInvalidated();
15086+
Dbg->setIsEmitted();
15087+
DAG.AddDbgValue(NewDV, /*isParameter=*/false);
15088+
};
15089+
15090+
// Because we are replacing a load and a s|z ext with a load-s|z ext
15091+
// instruction, the dbg_value attached to the load will be of a smaller bit
15092+
// width, and we have to add a DW_OP_LLVM_convert expression to get the
15093+
// correct size.
15094+
auto SalvageToOldLoadSize = [&](SDValue Old, SDValue New, bool IsSigned) {
15095+
SmallVector<SDDbgValue *, 4> DbgVals(
15096+
DAG.GetDbgValues(Old.getNode()).begin(),
15097+
DAG.GetDbgValues(Old.getNode()).end());
15098+
15099+
unsigned VarBitsOld = Old.getValueSizeInBits();
15100+
unsigned VarBitsNew = New.getValueSizeInBits();
15101+
15102+
for (SDDbgValue *Dbg : DbgVals) {
15103+
if (Dbg->isInvalidated())
15104+
continue;
15105+
15106+
SalvageDbgValue(Dbg, Old, New, VarBitsOld, VarBitsNew, IsSigned);
15107+
}
15108+
};
15109+
1503515110
SDValue ExtLoad =
1503615111
DAG.getExtLoad(ExtLoadType, DL, VT, Load->getChain(), Load->getBasePtr(),
1503715112
Load->getValueType(0), Load->getMemOperand());
@@ -15044,11 +15119,23 @@ static SDValue tryToFoldExtOfLoad(SelectionDAG &DAG, DAGCombiner &Combiner,
1504415119
DAG.getValueType(Load->getValueType(0).getScalarType()));
1504515120
}
1504615121
Combiner.ExtendSetCCUses(SetCCs, N0, Res, ExtOpc);
15047-
Combiner.CombineTo(N, Res);
15122+
// If the load value is used only by N, replace it via CombineTo N.
15123+
bool NoReplaceTrunc = N0.hasOneUse();
15124+
if (N->getHasDebugValue()) {
15125+
SDValue OldExtValue(N, 0);
15126+
DAG.transferDbgValues(OldExtValue, ExtLoad);
15127+
}
1504815128
if (NoReplaceTrunc) {
15129+
bool IsSigned = N->getOpcode() == ISD::SIGN_EXTEND;
15130+
if (Load->getHasDebugValue()) {
15131+
SDValue OldLoadVal(Load, 0);
15132+
SalvageToOldLoadSize(OldLoadVal, ExtLoad, IsSigned);
15133+
}
1504915134
DAG.ReplaceAllUsesOfValueWith(SDValue(Load, 1), ExtLoad.getValue(1));
15135+
Combiner.CombineTo(N, Res);
1505015136
Combiner.recursivelyDeleteUnusedNodes(N0.getNode());
1505115137
} else {
15138+
Combiner.CombineTo(N, Res);
1505215139
SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, Load->getValueType(0), Res);
1505315140
if (Frozen) {
1505415141
Combiner.CombineTo(Freeze.getNode(), Trunc);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
; This test checks that after SelectionDAG runs, DAGCombiner can combine a
2+
; load and a zext instruction without crashing in tryToFoldExtOfLoad(),
3+
; even when the folded load result is still used along the truncate
4+
; replacement path.
5+
6+
; RUN: llc -O3 -mtriple=x86_64-unknown-linux-gnu -filetype=null < %s
7+
8+
@ak = external global i16
9+
@s = external global i16
10+
11+
define i32 @main() {
12+
entry:
13+
%0 = load i16, ptr @ak, align 2
14+
%1 = load volatile i16, ptr @s, align 2
15+
%2 = load i16, ptr @ak, align 2
16+
%3 = xor i16 %2, -1
17+
%conv4211404 = zext i16 %3 to i64
18+
%xor422 = xor i64 1, %conv4211404
19+
%conv3591399 = zext i16 %0 to i64
20+
%or424 = or i64 %xor422, %conv3591399
21+
%conv333 = sext i16 %0 to i32
22+
%conv434 = zext i16 %2 to i32
23+
%4 = trunc i64 %or424 to i32
24+
%or436 = or i32 %conv434, %4
25+
%conv453 = xor i32 %conv333, %or436
26+
ret i32 %conv453
27+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
; This test checks that after SelectionDAG runs, it preserves the debug info that is lost due to the DAGCombiner combining a load and a sext instruction, where the #dbg_value is pointing to the result of the load.
2+
; However, in this case, the load has multiple uses.
3+
4+
; RUN: llc %s -mtriple=x86_64-unkown-linux -start-before=x86-isel -stop-after=x86-isel -o - | FileCheck %s --check-prefix=MIR
5+
; RUN: llc -O2 %s -start-before=x86-isel -mtriple=x86_64-unkown-linux --filetype=obj -o %t.o
6+
; RUN: llvm-dwarfdump %t.o --name Idx | FileCheck %s --check-prefix=DUMP
7+
; RUN: llvm-dwarfdump %t.o --name Idx2 | FileCheck %s --check-prefix=DUMP2
8+
9+
; MIR: ![[IDX:[0-9]+]] = !DILocalVariable(name: "Idx"
10+
; MIR: ![[IDX2:[0-9]+]] = !DILocalVariable(name: "Idx2"
11+
; MIR: name: _Z8useValuei
12+
; MIR: name: main
13+
; MIR: debugValueSubstitutions
14+
; MIR-NEXT: - { srcinst: [[INSTR_NUM2:[0-9]+]], srcop: 0, dstinst: [[INSTR_NUM:[0-9]+]], dstop: 0, subreg: 6 }
15+
; MIR-LABEL: bb.0 (%ir-block.0)
16+
; MIR: %{{[0-9a-f]+}}{{.*}} = MOVSX64rm32 ${{.*}}, 1, $noreg, @GlobArr, $noreg, debug-instr-number [[INSTR_NUM]]
17+
; MIR-NEXT: {{.*}} = COPY %0.sub_32bit
18+
; MIR-NEXT DBG_INSTR_REF ![[IDX]], !DIExpression(DW_OP_LLVM_arg, 0), dbg-instr-ref([[INSTR_NUM2]], 0)
19+
; MIR-NEXT DBG_INSTR_REF ![[IDX2]], !DIExpression(DW_OP_LLVM_arg, 0), dbg-instr-ref([[INSTR_NUM]], 0)
20+
21+
; DUMP: DW_AT_location (indexed ({{[0-9a-f]+}}x{{[0-9a-f]+}}) loclist = 0x{{[0-9a-f]+}}:
22+
; DUMP-NEXT: [0x{{[0-9a-f]+}}, 0x{{[0-9a-f]+}}): DW_OP_reg3 RBX)
23+
24+
; DUMP2: DW_AT_location (indexed ({{[0-9a-f]+}}x{{[0-9a-f]+}}) loclist = 0x{{[0-9a-f]+}}:
25+
; DUMP2-NEXT: [0x{{[0-9a-f]+}}, 0x{{[0-9a-f]+}}): DW_OP_reg3 RBX)
26+
27+
28+
29+
@GlobArr = dso_local local_unnamed_addr global [5 x i32] [i32 1, i32 1, i32 2, i32 3, i32 5], align 16, !dbg !0
30+
@__const.main.Data = private unnamed_addr constant [7 x i32] [i32 10, i32 20, i32 30, i32 40, i32 50, i32 60, i32 70], align 16
31+
define dso_local void @_Z8useValuei(i32 noundef %0) local_unnamed_addr #0 !dbg !22 {
32+
ret void, !dbg !28
33+
}
34+
define dso_local noundef i32 @main() local_unnamed_addr #1 !dbg !29 {
35+
%1 = load i32, ptr @GlobArr
36+
#dbg_value(i32 %1, !43, !DIExpression(), !52)
37+
%2 = sext i32 %1 to i64
38+
#dbg_value(i64 %2, !57, !DIExpression(), !52)
39+
tail call void @_Z8useValuei(i32 noundef %1), !dbg !56
40+
%3 = getelementptr inbounds i32, ptr @__const.main.Data, i64 %2
41+
%4 = load i32, ptr %3
42+
tail call void @_Z8useValuei(i32 noundef %4), !dbg !56
43+
ret i32 0
44+
}
45+
!llvm.dbg.cu = !{!2}
46+
!llvm.module.flags = !{!10, !11, !16}
47+
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
48+
!1 = distinct !DIGlobalVariable(type: !6, isDefinition: true)
49+
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, emissionKind: FullDebug, nameTableKind: None)
50+
!3 = !DIFile(filename: "/tmp/test.cpp", directory: "/Users/srastogi/Development/llvm-project/build_ninja", checksumkind: CSK_MD5, checksum: "0fe735937e606b4db3e3b2e9253eff90")
51+
!6 = !DICompositeType(tag: DW_TAG_array_type, elements: !8)
52+
!7 = !DIBasicType()
53+
!8 = !{}
54+
!10 = !{i32 7, !"Dwarf Version", i32 5}
55+
!11 = !{i32 2, !"Debug Info Version", i32 3}
56+
!16 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
57+
!22 = distinct !DISubprogram(type: !23, unit: !2, keyInstructions: true)
58+
!23 = !DISubroutineType(types: !24)
59+
!24 = !{}
60+
!28 = !DILocation(scope: !22, atomRank: 1)
61+
!29 = distinct !DISubprogram(type: !30, unit: !2, keyInstructions: true)
62+
!30 = !DISubroutineType(types: !31)
63+
!31 = !{}
64+
!38 = distinct !DILexicalBlock(scope: !29, line: 5, column: 3)
65+
!43 = !DILocalVariable(name: "Idx", scope: !44, type: !7)
66+
!44 = distinct !DILexicalBlock(scope: !38, line: 5, column: 3)
67+
!46 = distinct !DILexicalBlock(scope: !44, line: 5, column: 27)
68+
!52 = !DILocation(scope: !44)
69+
!56 = !DILocation(scope: !46)
70+
!57 = !DILocalVariable(name: "Idx2", scope: !44, type: !7)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
; This test checks that after SelectionDAG runs, it preserves the debug info that is lost due to the DAGCombiner combining a load and a sext instruction, where the #dbg_value is pointing to the result of the load.
2+
; RUN: llc %s -mtriple=x86_64-unkown-linux -start-before=x86-isel -stop-after=x86-isel -o - | FileCheck %s --check-prefix=MIR
3+
; RUN: llc -O2 %s -start-before=x86-isel -mtriple=x86_64-unkown-linux --filetype=obj -o %t.o
4+
; RUN: llvm-dwarfdump %t.o --name Idx | FileCheck %s --check-prefix=DUMP
5+
; RUN: llvm-dwarfdump %t.o --name Idx2 | FileCheck %s --check-prefix=DUMP2
6+
7+
; MIR: ![[IDX:[0-9]+]] = !DILocalVariable(name: "Idx"
8+
; MIR: ![[IDX2:[0-9]+]] = !DILocalVariable(name: "Idx2"
9+
; MIR-LABEL: bb.0
10+
; MIR: %{{[0-9a-f]+}}{{.*}} = MOVSX64rm32 ${{.*}}, 1, $noreg, @GlobArr, $noreg, debug-instr-number [[INSTR_NUM:[0-9]+]]
11+
; MIR-NEXT: DBG_INSTR_REF ![[IDX]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_convert, 64, DW_ATE_signed, DW_OP_LLVM_convert, 32, DW_ATE_signed, DW_OP_stack_value), dbg-instr-ref([[INSTR_NUM]], 0)
12+
; MIR-NEXT: DBG_INSTR_REF ![[IDX2]], !DIExpression(DW_OP_LLVM_arg, 0), dbg-instr-ref([[INSTR_NUM]], 0)
13+
14+
; DUMP: DW_AT_location (indexed ({{[0-9a-f]+}}x{{[0-9a-f]+}}) loclist = 0x{{[0-9a-f]+}}:
15+
; DUMP-NEXT: [0x{{[0-9a-f]+}}, 0x{{[0-9a-f]+}}): DW_OP_breg0 RAX+0, DW_OP_convert (0x{{[0-9a-f]+}}) "DW_ATE_signed_64", DW_OP_convert (0x{{[0-9a-f]+}}) "DW_ATE_signed_32", DW_OP_stack_value)
16+
17+
; DUMP2: DW_AT_location (indexed ({{[0-9a-f]+}}x{{[0-9a-f]+}}) loclist = 0x{{[0-9a-f]+}}:
18+
; DUMP2-NEXT: [0x{{[0-9a-f]+}}, 0x{{[0-9a-f]+}}): DW_OP_reg0 RAX)
19+
20+
21+
@GlobArr = dso_local local_unnamed_addr global [5 x i32] [i32 1, i32 1, i32 2, i32 3, i32 5], align 16, !dbg !0
22+
@__const.main.Data = private unnamed_addr constant [7 x i32] [i32 10, i32 20, i32 30, i32 40, i32 50, i32 60, i32 70], align 16
23+
define dso_local void @_Z8useValuei(i32 noundef %0) local_unnamed_addr #0 !dbg !22 {
24+
ret void, !dbg !28
25+
}
26+
define dso_local noundef i32 @main() local_unnamed_addr #1 !dbg !29 {
27+
%1 = load i32, ptr @GlobArr
28+
#dbg_value(i32 %1, !43, !DIExpression(), !52)
29+
%2 = sext i32 %1 to i64
30+
#dbg_value(i64 %2, !57, !DIExpression(), !52)
31+
%3 = getelementptr inbounds i32, ptr @__const.main.Data, i64 %2
32+
%4 = load i32, ptr %3
33+
tail call void @_Z8useValuei(i32 noundef %4), !dbg !56
34+
ret i32 0
35+
}
36+
!llvm.dbg.cu = !{!2}
37+
!llvm.module.flags = !{!10, !11, !16}
38+
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
39+
!1 = distinct !DIGlobalVariable(type: !6, isDefinition: true)
40+
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, emissionKind: FullDebug, nameTableKind: None)
41+
!3 = !DIFile(filename: "/tmp/test.cpp", directory: "/Users/srastogi/Development/llvm-project/build_ninja", checksumkind: CSK_MD5, checksum: "0fe735937e606b4db3e3b2e9253eff90")
42+
!6 = !DICompositeType(tag: DW_TAG_array_type, elements: !8)
43+
!7 = !DIBasicType()
44+
!8 = !{}
45+
!10 = !{i32 7, !"Dwarf Version", i32 5}
46+
!11 = !{i32 2, !"Debug Info Version", i32 3}
47+
!16 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
48+
!22 = distinct !DISubprogram(type: !23, unit: !2, keyInstructions: true)
49+
!23 = !DISubroutineType(types: !24)
50+
!24 = !{}
51+
!28 = !DILocation(scope: !22, atomRank: 1)
52+
!29 = distinct !DISubprogram(type: !30, unit: !2, keyInstructions: true)
53+
!30 = !DISubroutineType(types: !31)
54+
!31 = !{}
55+
!38 = distinct !DILexicalBlock(scope: !29, line: 5, column: 3)
56+
!43 = !DILocalVariable(name: "Idx", scope: !44, type: !7)
57+
!44 = distinct !DILexicalBlock(scope: !38, line: 5, column: 3)
58+
!46 = distinct !DILexicalBlock(scope: !44, line: 5, column: 27)
59+
!52 = !DILocation(scope: !44)
60+
!56 = !DILocation(scope: !46)
61+
!57 = !DILocalVariable(name: "Idx2", scope: !44, type: !7)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
; This test checks that after SelectionDAG runs, it preserves the debug info that is lost due to the DAGCombiner combining a load and a zext instruction, where the #dbg_value is pointing to the result of the load. However, this test also ensures that the DIExpression, which has multiple DW_OP_LLVM_arg's is handled correctly when the debug info is preserved in selectioDAG.
2+
; RUN: llc %s -mtriple=x86_64-unkown-linux-gnu -start-before=x86-isel -stop-after=x86-isel -o - | FileCheck %s --check-prefix=MIR
3+
; RUN: llc -O2 %s -start-before=x86-isel -mtriple=x86_64-unkown-linux --filetype=obj -o %t.o
4+
5+
; MIR: ![[V:[0-9]+]] = !DILocalVariable(name: "v"
6+
; MIR-LABEL: bb.0
7+
; MIR: %{{[0-9a-f]+}}{{.*}} = MOVZX32rm8 {{.*}}, 1, $noreg, 0, $noreg, debug-instr-number [[INSTR_NUM:[0-9]+]]
8+
; MIR-NEXT: DBG_INSTR_REF ![[V]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_constu, 45, DW_OP_eq, DW_OP_LLVM_arg, 1, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_constu, 114, DW_OP_eq, DW_OP_or, DW_OP_stack_value), dbg-instr-ref([[INSTR_NUM]], 0), dbg-instr-ref([[INSTR_NUM]], 0)
9+
10+
@.str = private unnamed_addr constant [105 x i8] c"/Users/srastogi/Development/llvm-project-2/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cpp\00"
11+
@.str.1 = private unnamed_addr constant [45 x i8] c"((IsOneOf(*data_.current, '-', 'r'))) != (0)\00"
12+
define hidden noundef zeroext i1 @_ZN11__sanitizer19MemoryMappingLayout4NextEPNS_19MemoryMappedSegmentE(ptr noundef nonnull readonly align 8 captures(none) dereferenceable(32) %this, ptr noundef readonly captures(none) %segment) unnamed_addr #0 align 2 !dbg !64 {
13+
%current = getelementptr inbounds nuw i8, ptr %this, i64 24
14+
%3 = load ptr, ptr %current, !dbg !95
15+
%4 = load i8, ptr %3
16+
#dbg_value(!DIArgList(i8 %4, i8 %4), !71, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 45, DW_OP_eq, DW_OP_LLVM_arg, 1, DW_OP_constu, 114, DW_OP_eq, DW_OP_or, DW_OP_stack_value), !98)
17+
%5 = zext i8 %4 to i32
18+
switch i32 %5, label %if.then [
19+
i32 114, label %if.end
20+
i32 45, label %if.end
21+
]
22+
if.then: ; preds = %entry
23+
tail call void @_ZN11__sanitizer11CheckFailedEPKciS1_yy(ptr noundef nonnull @.str, i32 noundef 45, ptr noundef nonnull @.str.1, i64 noundef 0, i64 noundef 0) #5
24+
unreachable
25+
if.end: ; preds = %entry, %entry
26+
ret i1 true
27+
}
28+
declare void @_ZN11__sanitizer11CheckFailedEPKciS1_yy(ptr noundef, i32 noundef, ptr noundef, i64 noundef, i64 noundef) local_unnamed_addr #2
29+
!llvm.dbg.cu = !{!15}
30+
!llvm.module.flags = !{!55, !58}
31+
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
32+
!1 = distinct !DIGlobalVariable()
33+
!2 = !DIFile(filename: "san.pp.cpp", directory: "/Users/srastogi/Development/Delta", checksumkind: CSK_MD5, checksum: "386698ddde6c66899ec76581efaeabe2")
34+
!15 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !16, emissionKind: FullDebug, nameTableKind: None)
35+
!16 = !DIFile(filename: "/Users/srastogi/Development/Delta/san.pp.cpp", directory: "/Users/srastogi/Development/Delta", checksumkind: CSK_MD5, checksum: "386698ddde6c66899ec76581efaeabe2")
36+
!19 = !DIDerivedType(tag: DW_TAG_typedef,baseType: !21)
37+
!21 = !DIBasicType()
38+
!22 = !DIDerivedType(tag: DW_TAG_typedef, baseType: !23)
39+
!23 = !DIBasicType()
40+
!46 = !DISubroutineType(types: !47)
41+
!47 = !{}
42+
!55 = !{i32 2, !"Debug Info Version", i32 3}
43+
!58 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
44+
!64 = distinct !DISubprogram( type: !46, unit: !15, keyInstructions: true)
45+
!71 = !DILocalVariable(name: "v", scope: !72, type: !19)
46+
!72 = distinct !DILexicalBlock(scope: !64, line: 187, column: 6)
47+
!95 = !DILocation( scope: !72)
48+
!98 = !DILocation(scope: !72)

0 commit comments

Comments
 (0)