1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
# RUN: llc %s -o - -mtriple=x86_64-unknown-unknown \
# RUN: -experimental-debug-variable-locations \
# RUN: -run-pass=phi-node-elimination,simple-register-coalescing \
# RUN: | FileCheck %s --check-prefix=DOESCOALESCE
# RUN: llc %s -o - -mtriple=x86_64-unknown-unknown \
# RUN: -experimental-debug-variable-locations \
# RUN: -run-pass=phi-node-elimination,simple-register-coalescing,livedebugvars,greedy,virtregrewriter \
# RUN: | FileCheck %s --check-prefix=CHECK
#
# Test that a PHI with a debug instruction number attached survives register
# coalescing, when its vreg gets coalesced. This test comes in two parts, first
# that coalescing actually happens, second that a DBG_PHI is still produced
# afterwards.
#
# Original C code, the PHI is of the value of 'bar' after the control flow.
# Compiled at -O0, applied -mem2reg, llc -O0, then manually added the PHI
# instruction label. Additional variable locations removed.
#
# void ext(long);
# long getlong(void);
# int foo(long bar, long baz) {
# ext(bar);
# bar += 12;
# ext(bar);
#
# if (getlong())
# bar += 1;
#
# bar += baz;
# ext(bar);
# return bar;
# }
#
--- |
; ModuleID = 'promoted.ll'
source_filename = "test.c"
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"
define dso_local i32 @foo(i64 %bar, i64 %baz) !dbg !7 {
entry:
call void @llvm.dbg.value(metadata i64 %bar, metadata !12, metadata !DIExpression()), !dbg !13
call void @llvm.dbg.value(metadata i64 %baz, metadata !14, metadata !DIExpression()), !dbg !13
call void @ext(i64 %bar), !dbg !13
%add = add nsw i64 %bar, 12, !dbg !13
call void @llvm.dbg.value(metadata i64 %add, metadata !12, metadata !DIExpression()), !dbg !13
call void @ext(i64 %add), !dbg !13
%call = call i64 @getlong(), !dbg !13
%tobool = icmp ne i64 %call, 0, !dbg !13
br i1 %tobool, label %if.then, label %if.end, !dbg !13
if.then: ; preds = %entry
%add1 = add nsw i64 %add, 1, !dbg !13
call void @llvm.dbg.value(metadata i64 %add1, metadata !12, metadata !DIExpression()), !dbg !13
br label %if.end, !dbg !13
if.end: ; preds = %if.then, %entry
%bar.addr.0 = phi i64 [ %add1, %if.then ], [ %add, %entry ], !dbg !13
call void @llvm.dbg.value(metadata i64 %bar.addr.0, metadata !12, metadata !DIExpression()), !dbg !13
%add2 = add nsw i64 %bar.addr.0, %baz, !dbg !13
call void @llvm.dbg.value(metadata i64 %add2, metadata !12, metadata !DIExpression()), !dbg !13
call void @ext(i64 %add2), !dbg !13
%conv = trunc i64 %add2 to i32, !dbg !13
ret i32 %conv, !dbg !13
}
; Function Attrs: nounwind readnone speculatable willreturn
declare void @llvm.dbg.declare(metadata, metadata, metadata)
declare dso_local void @ext(i64)
declare dso_local i64 @getlong()
; Function Attrs: nounwind readnone speculatable willreturn
declare void @llvm.dbg.value(metadata, metadata, metadata)
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4, !5}
!llvm.ident = !{!6}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
!1 = !DIFile(filename: "test.c", directory: "/tmp/out.c")
!2 = !{}
!3 = !{i32 7, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"wchar_size", i32 4}
!6 = !{!""}
!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
!8 = !DISubroutineType(types: !9)
!9 = !{!10, !11, !11}
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!11 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed)
!12 = !DILocalVariable(name: "bar", arg: 1, scope: !7, file: !1, line: 3, type: !11)
!13 = !DILocation(line: 0, scope: !7)
!14 = !DILocalVariable(name: "baz", arg: 2, scope: !7, file: !1, line: 3, type: !11)
!15 = distinct !DILexicalBlock(scope: !7, file: !1, line: 8, column: 7)
...
---
name: foo
alignment: 16
tracksRegLiveness: true
liveins:
- { reg: '$rdi', virtual-reg: '%3' }
- { reg: '$rsi', virtual-reg: '%5' }
frameInfo:
maxAlignment: 1
hasCalls: true
machineFunctionInfo: {}
body: |
bb.0.entry:
liveins: $rdi, $rsi
%5:gr64 = COPY $rsi
%3:gr64 = COPY $rdi
%4:gr64 = COPY killed %3
%6:gr64 = COPY killed %5
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
$rdi = COPY %4, debug-location !13
CALL64pcrel32 @ext, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, debug-location !13
ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
%9:gr64 = ADD64ri32 %4, 12, implicit-def $eflags, debug-location !13
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
$rdi = COPY %9, debug-location !13
CALL64pcrel32 @ext, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, debug-location !13
ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
CALL64pcrel32 @getlong, csr_64, implicit $rsp, implicit $ssp, implicit-def $rax, debug-location !13
ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
%8:gr64 = COPY $rax, debug-location !13
CMP64ri8 %8, 0, implicit-def $eflags, debug-location !13
JCC_1 %bb.2, 4, implicit $eflags, debug-location !13
; DOESCOALESCE-LABEL: bb.1.if.then:
; CHECK-LABEL: bb.1.if.then:
bb.1.if.then:
%10:gr64 = ADD64ri32 %9, 1, implicit-def $eflags, debug-location !13
; Verify that the vreg is different immediately after register coalescing.
; DOESCOALESCE-NOT: %10:gr64 ADD64ri32
; DOESCOALESCE: %{{[0-9]+}}:gr64 = ADD64ri32
; Verify that all these registers land in rbx.
; CHECK: renamable $rbx = ADD64ri32 killed renamable $rbx
; DOESCOALESCE-LABEL: bb.2.if.end:
; CHECK-LABEL: bb.2.if.end:
bb.2.if.end:
%2:gr64 = PHI %9, %bb.0, %10, %bb.1, debug-instr-number 1, debug-location !13
; CHECK: DBG_PHI $rbx, 1
DBG_INSTR_REF 1, 0, !12, !DIExpression(), debug-location !13
%14:gr64 = ADD64rr killed %2, %6, implicit-def $eflags, debug-location !13
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
$rdi = COPY %14, debug-location !13
CALL64pcrel32 @ext, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, debug-location !13
ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp, debug-location !13
%13:gr32 = COPY %14.sub_32bit, debug-location !13
$eax = COPY %13, debug-location !13
RET64 implicit $eax, debug-location !13
...
|