1# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py 2# RUN: llc -o - -mtriple=x86_64-- -run-pass=twoaddressinstruction,simple-register-coalescing %s | FileCheck %s 3# Tests for commuting ADCX and ADOX to avoid copies. The ADOX tests were manually constructed by modifying ADCX tests to use OF instead of CF. 4--- | 5 ; ModuleID = 'test.ll' 6 source_filename = "test.ll" 7 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 8 9 define void @adcx32_commute(i8 %cf, i32 %a, i32 %b, i32* %res) #0 { 10 %ret = call { i8, i32 } @llvm.x86.addcarry.32(i8 %cf, i32 %a, i32 %b) 11 %1 = extractvalue { i8, i32 } %ret, 1 12 %2 = mul i32 %a, %1 13 store i32 %2, i32* %res 14 ret void 15 } 16 17 define void @adcx64_commute(i8 %cf, i64 %a, i64 %b, i64* %res) #0 { 18 %ret = call { i8, i64 } @llvm.x86.addcarry.64(i8 %cf, i64 %a, i64 %b) 19 %1 = extractvalue { i8, i64 } %ret, 1 20 %2 = mul i64 %a, %1 21 store i64 %2, i64* %res 22 ret void 23 } 24 25 define void @adox32_commute(i8 %cf, i32 %a, i32 %b, i32* %res) #0 { 26 %ret = call { i8, i32 } @llvm.x86.addcarry.32(i8 %cf, i32 %a, i32 %b) 27 %1 = extractvalue { i8, i32 } %ret, 1 28 %2 = mul i32 %a, %1 29 store i32 %2, i32* %res 30 ret void 31 } 32 33 define void @adox64_commute(i8 %cf, i64 %a, i64 %b, i64* %res) #0 { 34 %ret = call { i8, i64 } @llvm.x86.addcarry.64(i8 %cf, i64 %a, i64 %b) 35 %1 = extractvalue { i8, i64 } %ret, 1 36 %2 = mul i64 %a, %1 37 store i64 %2, i64* %res 38 ret void 39 } 40 41 ; Function Attrs: nounwind readnone 42 declare { i8, i32 } @llvm.x86.addcarry.32(i8, i32, i32) #1 43 44 ; Function Attrs: nounwind readnone 45 declare { i8, i64 } @llvm.x86.addcarry.64(i8, i64, i64) #1 46 47 ; Function Attrs: nounwind 48 declare void @llvm.stackprotector(i8*, i8**) #2 49 50 attributes #0 = { "target-features"="+adx" } 51 attributes #1 = { nounwind readnone "target-features"="+adx" } 52 attributes #2 = { nounwind } 53 54... 55--- 56name: adcx32_commute 57alignment: 16 58tracksRegLiveness: true 59registers: 60 - { id: 0, class: gr32 } 61 - { id: 1, class: gr32 } 62 - { id: 2, class: gr32 } 63 - { id: 3, class: gr64 } 64 - { id: 4, class: gr8 } 65 - { id: 5, class: gr8 } 66 - { id: 6, class: gr32 } 67 - { id: 7, class: gr32 } 68liveins: 69 - { reg: '$edi', virtual-reg: '%0' } 70 - { reg: '$esi', virtual-reg: '%1' } 71 - { reg: '$edx', virtual-reg: '%2' } 72 - { reg: '$rcx', virtual-reg: '%3' } 73body: | 74 bb.0 (%ir-block.0): 75 liveins: $edi, $esi, $edx, $rcx 76 77 ; CHECK-LABEL: name: adcx32_commute 78 ; CHECK: liveins: $edi, $esi, $edx, $rcx 79 ; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rcx 80 ; CHECK: [[COPY1:%[0-9]+]]:gr32 = COPY $edx 81 ; CHECK: [[COPY2:%[0-9]+]]:gr32 = COPY $esi 82 ; CHECK: [[COPY3:%[0-9]+]]:gr32 = COPY $edi 83 ; CHECK: dead [[COPY3]].sub_8bit:gr32 = ADD8ri [[COPY3]].sub_8bit, -1, implicit-def $eflags 84 ; CHECK: [[ADCX32rr:%[0-9]+]]:gr32 = ADCX32rr [[ADCX32rr]], [[COPY2]], implicit-def dead $eflags, implicit killed $eflags 85 ; CHECK: [[IMUL32rr:%[0-9]+]]:gr32 = IMUL32rr [[IMUL32rr]], [[COPY2]], implicit-def dead $eflags 86 ; CHECK: MOV32mr [[COPY]], 1, $noreg, 0, $noreg, [[IMUL32rr]] :: (store 4 into %ir.res) 87 ; CHECK: RET 0 88 %3:gr64 = COPY killed $rcx 89 %2:gr32 = COPY killed $edx 90 %1:gr32 = COPY killed $esi 91 %0:gr32 = COPY killed $edi 92 %4:gr8 = COPY killed %0.sub_8bit 93 dead %5:gr8 = ADD8ri killed %4, -1, implicit-def $eflags 94 %6:gr32 = ADCX32rr %1, killed %2, implicit-def dead $eflags, implicit killed $eflags 95 %7:gr32 = IMUL32rr killed %1, killed %6, implicit-def dead $eflags 96 MOV32mr killed %3, 1, $noreg, 0, $noreg, killed %7 :: (store 4 into %ir.res) 97 RET 0 98 99... 100--- 101name: adcx64_commute 102alignment: 16 103tracksRegLiveness: true 104registers: 105 - { id: 0, class: gr32 } 106 - { id: 1, class: gr64 } 107 - { id: 2, class: gr64 } 108 - { id: 3, class: gr64 } 109 - { id: 4, class: gr8 } 110 - { id: 5, class: gr8 } 111 - { id: 6, class: gr64 } 112 - { id: 7, class: gr64 } 113liveins: 114 - { reg: '$edi', virtual-reg: '%0' } 115 - { reg: '$rsi', virtual-reg: '%1' } 116 - { reg: '$rdx', virtual-reg: '%2' } 117 - { reg: '$rcx', virtual-reg: '%3' } 118body: | 119 bb.0 (%ir-block.0): 120 liveins: $edi, $rsi, $rdx, $rcx 121 122 ; CHECK-LABEL: name: adcx64_commute 123 ; CHECK: liveins: $edi, $rsi, $rdx, $rcx 124 ; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rcx 125 ; CHECK: [[COPY1:%[0-9]+]]:gr64 = COPY $rdx 126 ; CHECK: [[COPY2:%[0-9]+]]:gr64 = COPY $rsi 127 ; CHECK: [[COPY3:%[0-9]+]]:gr32 = COPY $edi 128 ; CHECK: dead [[COPY3]].sub_8bit:gr32 = ADD8ri [[COPY3]].sub_8bit, -1, implicit-def $eflags 129 ; CHECK: [[ADCX64rr:%[0-9]+]]:gr64 = ADCX64rr [[ADCX64rr]], [[COPY2]], implicit-def dead $eflags, implicit killed $eflags 130 ; CHECK: [[IMUL64rr:%[0-9]+]]:gr64 = IMUL64rr [[IMUL64rr]], [[COPY2]], implicit-def dead $eflags 131 ; CHECK: MOV64mr [[COPY]], 1, $noreg, 0, $noreg, [[IMUL64rr]] :: (store 8 into %ir.res) 132 ; CHECK: RET 0 133 %3:gr64 = COPY killed $rcx 134 %2:gr64 = COPY killed $rdx 135 %1:gr64 = COPY killed $rsi 136 %0:gr32 = COPY killed $edi 137 %4:gr8 = COPY killed %0.sub_8bit 138 dead %5:gr8 = ADD8ri killed %4, -1, implicit-def $eflags 139 %6:gr64 = ADCX64rr %1, killed %2, implicit-def dead $eflags, implicit killed $eflags 140 %7:gr64 = IMUL64rr killed %1, killed %6, implicit-def dead $eflags 141 MOV64mr killed %3, 1, $noreg, 0, $noreg, killed %7 :: (store 8 into %ir.res) 142 RET 0 143 144... 145--- 146name: adox32_commute 147alignment: 16 148tracksRegLiveness: true 149registers: 150 - { id: 0, class: gr32 } 151 - { id: 1, class: gr32 } 152 - { id: 2, class: gr32 } 153 - { id: 3, class: gr64 } 154 - { id: 4, class: gr8 } 155 - { id: 5, class: gr8 } 156 - { id: 6, class: gr32 } 157 - { id: 7, class: gr32 } 158liveins: 159 - { reg: '$edi', virtual-reg: '%0' } 160 - { reg: '$esi', virtual-reg: '%1' } 161 - { reg: '$edx', virtual-reg: '%2' } 162 - { reg: '$rcx', virtual-reg: '%3' } 163body: | 164 bb.0 (%ir-block.0): 165 liveins: $edi, $esi, $edx, $rcx 166 167 ; CHECK-LABEL: name: adox32_commute 168 ; CHECK: liveins: $edi, $esi, $edx, $rcx 169 ; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rcx 170 ; CHECK: [[COPY1:%[0-9]+]]:gr32 = COPY $edx 171 ; CHECK: [[COPY2:%[0-9]+]]:gr32 = COPY $esi 172 ; CHECK: [[COPY3:%[0-9]+]]:gr32 = COPY $edi 173 ; CHECK: dead [[COPY3]].sub_8bit:gr32 = ADD8ri [[COPY3]].sub_8bit, 127, implicit-def $eflags 174 ; CHECK: [[ADOX32rr:%[0-9]+]]:gr32 = ADOX32rr [[ADOX32rr]], [[COPY2]], implicit-def dead $eflags, implicit killed $eflags 175 ; CHECK: [[IMUL32rr:%[0-9]+]]:gr32 = IMUL32rr [[IMUL32rr]], [[COPY2]], implicit-def dead $eflags 176 ; CHECK: MOV32mr [[COPY]], 1, $noreg, 0, $noreg, [[IMUL32rr]] :: (store 4 into %ir.res) 177 ; CHECK: RET 0 178 %3:gr64 = COPY killed $rcx 179 %2:gr32 = COPY killed $edx 180 %1:gr32 = COPY killed $esi 181 %0:gr32 = COPY killed $edi 182 %4:gr8 = COPY killed %0.sub_8bit 183 dead %5:gr8 = ADD8ri killed %4, 127, implicit-def $eflags 184 %6:gr32 = ADOX32rr %1, killed %2, implicit-def dead $eflags, implicit killed $eflags 185 %7:gr32 = IMUL32rr killed %1, killed %6, implicit-def dead $eflags 186 MOV32mr killed %3, 1, $noreg, 0, $noreg, killed %7 :: (store 4 into %ir.res) 187 RET 0 188 189... 190--- 191name: adox64_commute 192alignment: 16 193tracksRegLiveness: true 194registers: 195 - { id: 0, class: gr32 } 196 - { id: 1, class: gr64 } 197 - { id: 2, class: gr64 } 198 - { id: 3, class: gr64 } 199 - { id: 4, class: gr8 } 200 - { id: 5, class: gr8 } 201 - { id: 6, class: gr64 } 202 - { id: 7, class: gr64 } 203liveins: 204 - { reg: '$edi', virtual-reg: '%0' } 205 - { reg: '$rsi', virtual-reg: '%1' } 206 - { reg: '$rdx', virtual-reg: '%2' } 207 - { reg: '$rcx', virtual-reg: '%3' } 208body: | 209 bb.0 (%ir-block.0): 210 liveins: $edi, $rsi, $rdx, $rcx 211 212 ; CHECK-LABEL: name: adox64_commute 213 ; CHECK: liveins: $edi, $rsi, $rdx, $rcx 214 ; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rcx 215 ; CHECK: [[COPY1:%[0-9]+]]:gr64 = COPY $rdx 216 ; CHECK: [[COPY2:%[0-9]+]]:gr64 = COPY $rsi 217 ; CHECK: [[COPY3:%[0-9]+]]:gr32 = COPY $edi 218 ; CHECK: dead [[COPY3]].sub_8bit:gr32 = ADD8ri [[COPY3]].sub_8bit, 127, implicit-def $eflags 219 ; CHECK: [[ADOX64rr:%[0-9]+]]:gr64 = ADOX64rr [[ADOX64rr]], [[COPY2]], implicit-def dead $eflags, implicit killed $eflags 220 ; CHECK: [[IMUL64rr:%[0-9]+]]:gr64 = IMUL64rr [[IMUL64rr]], [[COPY2]], implicit-def dead $eflags 221 ; CHECK: MOV64mr [[COPY]], 1, $noreg, 0, $noreg, [[IMUL64rr]] :: (store 8 into %ir.res) 222 ; CHECK: RET 0 223 %3:gr64 = COPY killed $rcx 224 %2:gr64 = COPY killed $rdx 225 %1:gr64 = COPY killed $rsi 226 %0:gr32 = COPY killed $edi 227 %4:gr8 = COPY killed %0.sub_8bit 228 dead %5:gr8 = ADD8ri killed %4, 127, implicit-def $eflags 229 %6:gr64 = ADOX64rr %1, killed %2, implicit-def dead $eflags, implicit killed $eflags 230 %7:gr64 = IMUL64rr killed %1, killed %6, implicit-def dead $eflags 231 MOV64mr killed %3, 1, $noreg, 0, $noreg, killed %7 :: (store 8 into %ir.res) 232 RET 0 233 234... 235