Skip to content

Commit 5372658

Browse files
committed
[DebugInfo][AArch64] Recognise target specific instruction as mov instr
This fix is for the problem from https://bugs.llvm.org/show_bug.cgi?id=38714. Specifically, Simple Register Coalescing creates following conversion : undef %0.sub_32:gpr64 = ORRWrs $wzr, %3:gpr32common, 0, debug-location !24; It copies 32-bit value from gpr32 into gpr64. But Live DEBUG_VALUE analysis is not able to create debug location record for that instruction. So the problem is in that debug info for argc variable is incorrect. The fix is to write custom isCopyInstrImpl() which would recognize the ORRWrs instr. llvm-svn: 361417
1 parent dfeb797 commit 5372658

File tree

3 files changed

+271
-0
lines changed

3 files changed

+271
-0
lines changed

llvm/lib/Target/AArch64/AArch64InstrInfo.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -5512,5 +5512,30 @@ bool AArch64InstrInfo::shouldOutlineFromFunctionByDefault(
55125512
return MF.getFunction().hasMinSize();
55135513
}
55145514

5515+
bool AArch64InstrInfo::isCopyInstrImpl(
5516+
const MachineInstr &MI, const MachineOperand *&Source,
5517+
const MachineOperand *&Destination) const {
5518+
5519+
// AArch64::ORRWrs and AArch64::ORRXrs with WZR/XZR reg
5520+
// and zero immediate operands used as an alias for mov instruction.
5521+
if (MI.getOpcode() == AArch64::ORRWrs &&
5522+
MI.getOperand(1).getReg() == AArch64::WZR &&
5523+
MI.getOperand(3).getImm() == 0x0) {
5524+
Destination = &MI.getOperand(0);
5525+
Source = &MI.getOperand(2);
5526+
return true;
5527+
}
5528+
5529+
if (MI.getOpcode() == AArch64::ORRXrs &&
5530+
MI.getOperand(1).getReg() == AArch64::XZR &&
5531+
MI.getOperand(3).getImm() == 0x0) {
5532+
Destination = &MI.getOperand(0);
5533+
Source = &MI.getOperand(2);
5534+
return true;
5535+
}
5536+
5537+
return false;
5538+
}
5539+
55155540
#define GET_INSTRINFO_HELPERS
55165541
#include "AArch64GenInstrInfo.inc"

llvm/lib/Target/AArch64/AArch64InstrInfo.h

+7
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,13 @@ class AArch64InstrInfo final : public AArch64GenInstrInfo {
267267
#define GET_INSTRINFO_HELPER_DECLS
268268
#include "AArch64GenInstrInfo.inc"
269269

270+
protected:
271+
/// If the specific machine instruction is a instruction that moves/copies
272+
/// value from one register to another register return true along with
273+
/// @Source machine operand and @Destination machine operand.
274+
bool isCopyInstrImpl(const MachineInstr &MI, const MachineOperand *&Source,
275+
const MachineOperand *&Destination) const override;
276+
270277
private:
271278
/// Sets the offsets on outlined instructions in \p MBB which use SP
272279
/// so that they will be valid post-outlining.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
2+
# RUN: llc -mtriple=aarch64-none-linux-gnu -verify-machineinstrs -run-pass=livedebugvalues %s -o - | FileCheck %s
3+
4+
#
5+
# This test is for the problem from https://bugs.llvm.org/show_bug.cgi?id=38714.
6+
#
7+
# Specifically, Simple Register Coalescing creates following conversion :
8+
#
9+
# undef %0.sub_32:gpr64 = ORRWrs $wzr, %3:gpr32common, 0, debug-location !24;
10+
#
11+
# It copies 32-bit value from gpr32 into gpr64. But later Live DEBUG_VALUE analysis
12+
# is not able to create debug location record for that instruction. The fix is
13+
# to write custom isCopyInstrImpl() which would recognize the ORRWrs instr as
14+
# move instruction.
15+
#
16+
# The LLVM-IR below was produced by clang on the following C++ code:
17+
#
18+
# int printf(const char* restrict format, ...);
19+
#
20+
#
21+
# int main( int argc, char **argv )
22+
# {
23+
# for(int i = 1; i < argc; ++i) {
24+
# printf("Argument %d: %s\n", i, argv[i]);
25+
# }
26+
# return 0;
27+
# }
28+
#
29+
30+
# CHECK-LABEL: main
31+
# CHECK: DBG_VALUE $w0, $noreg
32+
# CHECK: renamable $[[REG1:w[0-9]+]] = ORRWrs $wzr, killed renamable $w0, 0
33+
# CHECK: DBG_VALUE $[[REG1]], $noreg
34+
35+
36+
--- |
37+
; ModuleID = '<stdin>'
38+
source_filename = "test.c"
39+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
40+
target triple = "aarch64-unknown-linux"
41+
42+
@.str = private unnamed_addr constant [17 x i8] c"Argument %d: %s\0A\00", align 1
43+
44+
; Function Attrs: nounwind
45+
define dso_local i32 @main(i32 %argc, i8** nocapture readonly %argv) local_unnamed_addr #0 !dbg !7 {
46+
entry:
47+
call void @llvm.dbg.value(metadata i32 %argc, metadata !15, metadata !DIExpression()), !dbg !19
48+
call void @llvm.dbg.value(metadata i8** %argv, metadata !16, metadata !DIExpression()), !dbg !19
49+
call void @llvm.dbg.value(metadata i32 1, metadata !17, metadata !DIExpression()), !dbg !20
50+
%cmp5 = icmp sgt i32 %argc, 1, !dbg !21
51+
br i1 %cmp5, label %for.body.preheader, label %for.cond.cleanup, !dbg !23
52+
53+
for.body.preheader: ; preds = %entry
54+
%wide.trip.count = zext i32 %argc to i64, !dbg !24
55+
br label %for.body, !dbg !25
56+
57+
for.cond.cleanup: ; preds = %for.body, %entry
58+
ret i32 0, !dbg !27
59+
60+
for.body: ; preds = %for.body, %for.body.preheader
61+
%indvars.iv = phi i64 [ 1, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
62+
call void @llvm.dbg.value(metadata i64 %indvars.iv, metadata !17, metadata !DIExpression()), !dbg !20
63+
%scevgep = getelementptr i8*, i8** %argv, i64 %indvars.iv, !dbg !25
64+
%0 = load i8*, i8** %scevgep, align 8, !dbg !25, !tbaa !28
65+
%tmp = trunc i64 %indvars.iv to i32
66+
%call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str, i64 0, i64 0), i32 %tmp, i8* %0), !dbg !32
67+
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !33
68+
call void @llvm.dbg.value(metadata i32 undef, metadata !17, metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !20
69+
%exitcond = icmp eq i64 %wide.trip.count, %indvars.iv.next, !dbg !21
70+
br i1 %exitcond, label %for.cond.cleanup, label %for.body, !dbg !23, !llvm.loop !34
71+
}
72+
73+
; Function Attrs: nounwind
74+
declare dso_local i32 @printf(i8* nocapture readonly, ...) local_unnamed_addr #1
75+
76+
; Function Attrs: nounwind readnone speculatable
77+
declare void @llvm.dbg.value(metadata, metadata, metadata) #2
78+
79+
; Function Attrs: nounwind
80+
declare void @llvm.stackprotector(i8*, i8**) #3
81+
82+
attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+neon" "unsafe-fp-math"="false" "use-soft-float"="false" }
83+
attributes #1 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+neon" "unsafe-fp-math"="false" "use-soft-float"="false" }
84+
attributes #2 = { nounwind readnone speculatable }
85+
attributes #3 = { nounwind }
86+
87+
!llvm.dbg.cu = !{!0}
88+
!llvm.module.flags = !{!3, !4, !5}
89+
!llvm.ident = !{!6}
90+
91+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 9.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
92+
!1 = !DIFile(filename: "test.c", directory: "test")
93+
!2 = !{}
94+
!3 = !{i32 2, !"Dwarf Version", i32 4}
95+
!4 = !{i32 2, !"Debug Info Version", i32 3}
96+
!5 = !{i32 1, !"wchar_size", i32 4}
97+
!6 = !{!"clang version 9.0.0 "}
98+
!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 6, type: !8, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14)
99+
!8 = !DISubroutineType(types: !9)
100+
!9 = !{!10, !10, !11}
101+
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
102+
!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
103+
!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64)
104+
!13 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_unsigned_char)
105+
!14 = !{!15, !16, !17}
106+
!15 = !DILocalVariable(name: "argc", arg: 1, scope: !7, file: !1, line: 6, type: !10)
107+
!16 = !DILocalVariable(name: "argv", arg: 2, scope: !7, file: !1, line: 6, type: !11)
108+
!17 = !DILocalVariable(name: "i", scope: !18, file: !1, line: 8, type: !10)
109+
!18 = distinct !DILexicalBlock(scope: !7, file: !1, line: 8, column: 3)
110+
!19 = !DILocation(line: 0, scope: !7)
111+
!20 = !DILocation(line: 0, scope: !18)
112+
!21 = !DILocation(line: 8, column: 20, scope: !22)
113+
!22 = distinct !DILexicalBlock(scope: !18, file: !1, line: 8, column: 3)
114+
!23 = !DILocation(line: 8, column: 3, scope: !18)
115+
!24 = !DILocation(line: 0, scope: !22)
116+
!25 = !DILocation(line: 9, column: 36, scope: !26)
117+
!26 = distinct !DILexicalBlock(scope: !22, file: !1, line: 8, column: 33)
118+
!27 = !DILocation(line: 11, column: 3, scope: !7)
119+
!28 = !{!29, !29, i64 0}
120+
!29 = !{!"any pointer", !30, i64 0}
121+
!30 = !{!"omnipotent char", !31, i64 0}
122+
!31 = !{!"Simple C/C++ TBAA"}
123+
!32 = !DILocation(line: 9, column: 5, scope: !26)
124+
!33 = !DILocation(line: 8, column: 28, scope: !22)
125+
!34 = distinct !{!34, !23, !35}
126+
!35 = !DILocation(line: 10, column: 3, scope: !18)
127+
128+
...
129+
---
130+
name: main
131+
alignment: 2
132+
exposesReturnsTwice: false
133+
legalized: false
134+
regBankSelected: false
135+
selected: false
136+
failedISel: false
137+
tracksRegLiveness: true
138+
hasWinCFI: false
139+
registers: []
140+
liveins:
141+
- { reg: '$w0', virtual-reg: '' }
142+
- { reg: '$x1', virtual-reg: '' }
143+
frameInfo:
144+
isFrameAddressTaken: false
145+
isReturnAddressTaken: false
146+
hasStackMap: false
147+
hasPatchPoint: false
148+
stackSize: 48
149+
offsetAdjustment: 0
150+
maxAlignment: 8
151+
adjustsStack: true
152+
hasCalls: true
153+
stackProtector: ''
154+
maxCallFrameSize: 0
155+
cvBytesOfCalleeSavedRegisters: 0
156+
hasOpaqueSPAdjustment: false
157+
hasVAStart: false
158+
hasMustTailInVarArgFunc: false
159+
localFrameSize: 0
160+
savePoint: ''
161+
restorePoint: ''
162+
fixedStack: []
163+
stack:
164+
- { id: 0, name: '', type: spill-slot, offset: -8, size: 8, alignment: 8,
165+
stack-id: 0, callee-saved-register: '$lr', callee-saved-restored: true,
166+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
167+
- { id: 1, name: '', type: spill-slot, offset: -16, size: 8, alignment: 8,
168+
stack-id: 0, callee-saved-register: '$fp', callee-saved-restored: true,
169+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
170+
- { id: 2, name: '', type: spill-slot, offset: -24, size: 8, alignment: 8,
171+
stack-id: 0, callee-saved-register: '$x19', callee-saved-restored: true,
172+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
173+
- { id: 3, name: '', type: spill-slot, offset: -32, size: 8, alignment: 8,
174+
stack-id: 0, callee-saved-register: '$x20', callee-saved-restored: true,
175+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
176+
- { id: 4, name: '', type: spill-slot, offset: -40, size: 8, alignment: 8,
177+
stack-id: 0, callee-saved-register: '$x21', callee-saved-restored: true,
178+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
179+
- { id: 5, name: '', type: spill-slot, offset: -48, size: 8, alignment: 8,
180+
stack-id: 0, callee-saved-register: '$x22', callee-saved-restored: true,
181+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
182+
constants: []
183+
machineFunctionInfo: {}
184+
body: |
185+
bb.0.entry:
186+
successors: %bb.1(0x40000000), %bb.3(0x40000000)
187+
liveins: $w0, $x1, $x21, $x22, $x19, $x20, $lr
188+
189+
DBG_VALUE $w0, $noreg, !15, !DIExpression(), debug-location !19
190+
DBG_VALUE $w0, $noreg, !15, !DIExpression(), debug-location !19
191+
DBG_VALUE $x1, $noreg, !16, !DIExpression(), debug-location !19
192+
early-clobber $sp = frame-setup STPXpre killed $x22, killed $x21, $sp, -6 :: (store 8 into %stack.5), (store 8 into %stack.4)
193+
frame-setup STPXi killed $x20, killed $x19, $sp, 2 :: (store 8 into %stack.3), (store 8 into %stack.2)
194+
frame-setup STPXi $fp, killed $lr, $sp, 4 :: (store 8 into %stack.1), (store 8 into %stack.0)
195+
$fp = frame-setup ADDXri $sp, 32, 0
196+
frame-setup CFI_INSTRUCTION def_cfa $w29, 16
197+
frame-setup CFI_INSTRUCTION offset $w30, -8, debug-location !23
198+
frame-setup CFI_INSTRUCTION offset $w29, -16, debug-location !23
199+
frame-setup CFI_INSTRUCTION offset $w19, -24, debug-location !23
200+
frame-setup CFI_INSTRUCTION offset $w20, -32, debug-location !23
201+
frame-setup CFI_INSTRUCTION offset $w21, -40, debug-location !23
202+
frame-setup CFI_INSTRUCTION offset $w22, -48, debug-location !23
203+
DBG_VALUE 1, $noreg, !17, !DIExpression(), debug-location !20
204+
dead $wzr = SUBSWri renamable $w0, 2, 0, implicit-def $nzcv, debug-location !23
205+
Bcc 11, %bb.3, implicit $nzcv, debug-location !23
206+
207+
bb.1.for.body.preheader:
208+
successors: %bb.2(0x80000000)
209+
liveins: $w0, $x1
210+
211+
$x21 = ADRP target-flags(aarch64-page) @.str
212+
$x19 = ORRXrs $xzr, killed $x1, 0
213+
DBG_VALUE $x19, $noreg, !16, !DIExpression(), debug-location !19
214+
renamable $w22 = ORRWrs $wzr, killed renamable $w0, 0, implicit-def $x22, debug-location !24
215+
$w20 = MOVZWi 1, 0, implicit-def $x20
216+
renamable $x21 = ADDXri killed $x21, target-flags(aarch64-pageoff, aarch64-nc) @.str, 0
217+
218+
bb.2.for.body:
219+
successors: %bb.3(0x04000000), %bb.2(0x7c000000)
220+
liveins: $x19, $x20, $x21, $x22
221+
222+
DBG_VALUE $x20, $noreg, !17, !DIExpression(), debug-location !20
223+
renamable $x2 = LDRXroX renamable $x19, renamable $x20, 0, 1, debug-location !25 :: (load 8 from %ir.scevgep, !tbaa !28)
224+
$x0 = ORRXrs $xzr, $x21, 0, debug-location !32
225+
$w1 = ORRWrs $wzr, $w20, 0, debug-location !32
226+
BL @printf, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $x0, implicit killed $w1, implicit killed $x2, implicit-def $sp, implicit-def dead $w0, debug-location !32
227+
renamable $x20 = nuw nsw ADDXri killed renamable $x20, 1, 0, debug-location !33
228+
DBG_VALUE $noreg, $noreg, !17, !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value), debug-location !20
229+
$xzr = SUBSXrs renamable $x22, renamable $x20, 0, implicit-def $nzcv, implicit-def $nzcv, debug-location !23
230+
Bcc 1, %bb.2, implicit killed $nzcv, debug-location !23
231+
232+
bb.3.for.cond.cleanup:
233+
$fp, $lr = frame-destroy LDPXi $sp, 4, debug-location !27 :: (load 8 from %stack.1), (load 8 from %stack.0)
234+
$x20, $x19 = frame-destroy LDPXi $sp, 2, debug-location !27 :: (load 8 from %stack.3), (load 8 from %stack.2)
235+
$w0 = ORRWrs $wzr, $wzr, 0, debug-location !27
236+
early-clobber $sp, $x22, $x21 = frame-destroy LDPXpost $sp, 6, debug-location !27 :: (load 8 from %stack.5), (load 8 from %stack.4)
237+
RET undef $lr, implicit killed $w0, debug-location !27
238+
239+
...

0 commit comments

Comments
 (0)