1# RUN: llc %s -o - -run-pass=machine-cse -mtriple=x86_64-- | FileCheck %s 2# RUN: llc %s -o - -passes=machine-cse -mtriple=x86_64-- | FileCheck %s 3# 4# This test examines machine-cse's behaviour when dealing with copy propagation, 5# the code for which is lifted from test/CodeGen/X86/machine-cse.ll. There are 6# two (MIR) function that have SHL/LEA instructions CSE'd in the bb.1.bb1 block. 7# They both depend on the COPY of a vreg to %100 in the entry block. 8# 9# In the first (@t) there's only one use of %100, and that gets CSE'd away. The 10# corresponding COPY is deleted, and all DBG_VALUEs that refer to it must be 11# updated. 12# 13# In the second (@u) there are two uses of %100, one of which isn't deleted. The 14# DBG_VALUE users of %100 don't need to be updated -- test that they're not. 15--- | 16 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 17 target triple = "x86_64-unknown-unknown" 18 19 %struct.s2 = type { i32, ptr, ptr, [256 x ptr], [8 x i32], i64, ptr, i32, i64, i64, i32, ptr, ptr, [49 x i64] } 20 %struct.s1 = type { %ptr, %ptr } 21 %ptr = type { ptr } 22 %struct.s3 = type { ptr, ptr, i32, i32, i32 } 23 24 ; Function Attrs: nounwind readnone speculatable 25 declare void @llvm.dbg.value(metadata, metadata, metadata) #0 26 27 define fastcc ptr @t(i32 %base, i1 %arg) !dbg !3 { 28 entry: 29 %0 = zext i32 %base to i64 30 %1 = getelementptr inbounds %struct.s2, ptr null, i64 %0 31 br i1 %arg, label %bb1, label %bb2 32 33 bb1: ; preds = %entry 34 %2 = getelementptr inbounds %struct.s2, ptr null, i64 %0, i32 0 35 call void @llvm.dbg.value(metadata ptr %2, metadata !4, metadata !DIExpression()), !dbg !7 36 call void @bar(ptr %2) 37 unreachable 38 39 bb2: ; preds = %entry 40 %3 = ptrtoint ptr %1 to i64 41 call void @baz(i64 %3) 42 unreachable 43 } 44 45 ; This is a stub replicating bb structure of @t 46 define fastcc ptr @u(i32 %base, i1 %arg) !dbg !33 { 47 entry: 48 br i1 %arg, label %bb1, label %bb2 49 50 bb1: ; preds = %entry 51 unreachable 52 53 bb2: ; preds = %entry 54 unreachable 55 } 56 57 58 declare void @bar(ptr) 59 60 declare void @baz(i64) 61 62 declare ptr @foo(ptr) 63 64 ; Function Attrs: nounwind 65 declare void @llvm.stackprotector(ptr, ptr) #1 66 67 attributes #0 = { nounwind readnone speculatable } 68 attributes #1 = { nounwind } 69 70 !llvm.module.flags = !{!0} 71 !llvm.dbg.cu = !{!1} 72 73 !0 = !{i32 2, !"Debug Info Version", i32 3} 74 !1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "beards", isOptimized: true, runtimeVersion: 4, emissionKind: FullDebug) 75 !2 = !DIFile(filename: "bees.cpp", directory: "") 76 !3 = distinct !DISubprogram(name: "nope", scope: !1, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !8) 77 !33 = distinct !DISubprogram(name: "alsonope", scope: !1, file: !2, line: 1, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !8) 78 !4 = !DILocalVariable(name: "bees", scope: !3, type: !5) 79 !5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64) 80 !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) 81 !7 = !DILocation(line: 0, scope: !3) 82 !8 = !{!4} 83 84 85 ; CHECK: ![[METAVAR:[0-9]+]] = !DILocalVariable(name: "bees", 86 87... 88--- 89name: t 90# CHECK-LABEL: name: t 91tracksRegLiveness: true 92liveins: 93 - { reg: '$edi', virtual-reg: '%2' } 94frameInfo: 95 hasCalls: true 96body: | 97 bb.0.entry: 98 successors: %bb.1(0x40000000), %bb.2(0x40000000) 99 liveins: $edi 100 101 ; Capture vreg num for subreg move for later checks; test that the COPY 102 ; of that vreg is optimized out. 103 ; CHECK-LABEL: bb.0.entry: 104 ; CHECK: %[[BASEVREG:[0-9]+]]:gr64 = SUBREG_TO_REG 105 ; CHECK-NOT: COPY %[[BASEVREG]]:gr64 106 107 %2:gr32 = COPY $edi 108 %3:gr32 = MOV32rr %2 109 %0:gr64 = SUBREG_TO_REG 0, killed %3, %subreg.sub_32bit 110 %4:gr64_nosp = SHL64ri %0, 9, implicit-def dead $eflags 111 %1:gr64 = LEA64r %4, 4, %4, 0, $noreg 112 %5:gr32 = MOV32r0 implicit-def dead $eflags 113 %6:gr8 = COPY %5.sub_8bit 114 %100:gr64 = COPY %0:gr64 115 TEST8rr %6, %6, implicit-def $eflags 116 JCC_1 %bb.2, 5, implicit $eflags 117 JMP_1 %bb.1 118 119 bb.1.bb1: 120 successors: 121 122 ; Check for CSE happening and DBG_VALUE updating. 123 ; CHECK-LABEL: bb.1.bb1: 124 ; CHECK-NOT: SHL64ri 125 ; CHECK-NOT: LEA64r 126 ; CHECK: DBG_VALUE %[[BASEVREG]], $noreg, ![[METAVAR]], 127 ; CHECK-NEXT: ADJCALLSTACKDOWN64 128 129 %7:gr64_nosp = SHL64ri %100, 9, implicit-def dead $eflags 130 %8:gr64 = LEA64r %7, 4, %7, 0, $noreg 131 DBG_VALUE %100, $noreg, !4, !DIExpression(), debug-location !7 132 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 133 $rdi = COPY %8 134 CALL64pcrel32 @bar, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp 135 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 136 137 bb.2.bb2: 138 ; As the COPY to %100 dies, the DBG_VALUE below should be updated too. 139 ; CHECK-LABEL: bb.2.bb2: 140 ; CHECK: ADJCALLSTACKDOWN64 141 ; CHECK-NEXT: $rdi = COPY 142 ; CHECK-NEXT: DBG_VALUE %[[BASEVREG]], $noreg, ![[METAVAR]], 143 ; CHECK-NEXT: CALL64pcrel32 144 145 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 146 $rdi = COPY %1 147 DBG_VALUE %100, $noreg, !4, !DIExpression(), debug-location !7 148 CALL64pcrel32 @baz, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp 149 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 150 151... 152--- 153name: u 154# CHECK-LABEL: name: u 155tracksRegLiveness: true 156liveins: 157 - { reg: '$edi', virtual-reg: '%2' } 158frameInfo: 159 hasCalls: true 160body: | 161 bb.0.entry: 162 successors: %bb.1(0x40000000), %bb.2(0x40000000) 163 liveins: $edi 164 165 ; In this function, the COPY to %100 should not be optimized out, and as a 166 ; result the DBG_VALUEs should not be rewritten. 167 ; CHECK-LABEL: bb.0.entry: 168 ; CHECK: %[[BASEVREG:[0-9]+]]:gr64 = SUBREG_TO_REG 169 ; CHECK: %[[COPIEDVREG:[0-9]+]]:gr64 = COPY %[[BASEVREG]] 170 171 %2:gr32 = COPY $edi 172 %3:gr32 = MOV32rr %2 173 %0:gr64 = SUBREG_TO_REG 0, killed %3, %subreg.sub_32bit 174 %4:gr64_nosp = SHL64ri %0, 9, implicit-def dead $eflags 175 %1:gr64 = LEA64r %4, 4, %4, 0, $noreg 176 %5:gr32 = MOV32r0 implicit-def dead $eflags 177 %6:gr8 = COPY %5.sub_8bit 178 %100:gr64 = COPY %0:gr64 179 TEST8rr %6, %6, implicit-def $eflags 180 JCC_1 %bb.2, 5, implicit $eflags 181 JMP_1 %bb.1 182 183 bb.1.bb1: 184 successors: 185 186 ; CSE should happen, DBG_VALUE updating should not. 187 ; CHECK-LABEL: bb.1.bb1: 188 ; CHECK-NOT: SHL64ri 189 ; CHECK-NOT: LEA64r 190 ; CHECK: DBG_VALUE %[[COPIEDVREG]], $noreg, ![[METAVAR]], 191 ; CHECK-NEXT: ADJCALLSTACKDOWN64 192 193 194 195 %7:gr64_nosp = SHL64ri %100, 9, implicit-def dead $eflags 196 %8:gr64 = LEA64r %7, 4, %7, 0, $noreg 197 DBG_VALUE %100, $noreg, !4, !DIExpression(), debug-location !7 198 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 199 $rdi = COPY %8 200 CALL64pcrel32 @bar, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp 201 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 202 203 bb.2.bb2: 204 205 ; Test that the copy-read of %100 below is preserved, and the DBG_VALUE 206 ; operand is too. 207 ; CHECK-LABEL: bb.2.bb2: 208 ; CHECK: ADJCALLSTACKDOWN64 209 ; CHECK-NEXT: $rdi = COPY %[[COPIEDVREG]] 210 ; CHECK-NEXT: DBG_VALUE %[[COPIEDVREG]], $noreg, ![[METAVAR]], 211 ; CHECK-NEXT: CALL64pcrel32 212 213 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 214 $rdi = COPY %100 215 DBG_VALUE %100, $noreg, !4, !DIExpression(), debug-location !7 216 CALL64pcrel32 @baz, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp 217 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 218 219... 220