1# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py 2# RUN: llc -o - -mtriple=x86_64-- -run-pass=greedy %s | FileCheck %s 3# Tests for stack folding ADCX and ADOX. The ADOX tests were manually constructed by modifying ADCX tests to use OF instead of CF. 4--- | 5 ; Function Attrs: nounwind 6 define i8 @stack_fold_adcx32(i8 %a0, i32 %a1, i32 %a2, i8* %a3) #0 { 7 %1 = tail call i64 asm sideeffect "nop", "=x,~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() 8 %2 = call { i8, i32 } @llvm.x86.addcarry.32(i8 %a0, i32 %a1, i32 %a2) 9 %3 = extractvalue { i8, i32 } %2, 1 10 %4 = bitcast i8* %a3 to i32* 11 store i32 %3, i32* %4, align 1 12 %5 = extractvalue { i8, i32 } %2, 0 13 ret i8 %5 14 } 15 16 ; Function Attrs: nounwind 17 define i8 @stack_fold_adcx64(i8 %a0, i64 %a1, i64 %a2, i8* %a3) #0 { 18 %1 = tail call i64 asm sideeffect "nop", "=x,~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() 19 %2 = call { i8, i64 } @llvm.x86.addcarry.64(i8 %a0, i64 %a1, i64 %a2) 20 %3 = extractvalue { i8, i64 } %2, 1 21 %4 = bitcast i8* %a3 to i64* 22 store i64 %3, i64* %4, align 1 23 %5 = extractvalue { i8, i64 } %2, 0 24 ret i8 %5 25 } 26 27 define i8 @stack_fold_adox32(i8 %a0, i32 %a1, i32 %a2, i8* %a3) #0 { 28 %1 = tail call i64 asm sideeffect "nop", "=x,~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() 29 %2 = call { i8, i32 } @llvm.x86.addcarry.32(i8 %a0, i32 %a1, i32 %a2) 30 %3 = extractvalue { i8, i32 } %2, 1 31 %4 = bitcast i8* %a3 to i32* 32 store i32 %3, i32* %4, align 1 33 %5 = extractvalue { i8, i32 } %2, 0 34 ret i8 %5 35 } 36 37 ; Function Attrs: nounwind 38 define i8 @stack_fold_adox64(i8 %a0, i64 %a1, i64 %a2, i8* %a3) #0 { 39 %1 = tail call i64 asm sideeffect "nop", "=x,~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() 40 %2 = call { i8, i64 } @llvm.x86.addcarry.64(i8 %a0, i64 %a1, i64 %a2) 41 %3 = extractvalue { i8, i64 } %2, 1 42 %4 = bitcast i8* %a3 to i64* 43 store i64 %3, i64* %4, align 1 44 %5 = extractvalue { i8, i64 } %2, 0 45 ret i8 %5 46 } 47 48 ; Function Attrs: nounwind readnone 49 declare { i8, i32 } @llvm.x86.addcarry.32(i8, i32, i32) #1 50 51 ; Function Attrs: nounwind readnone 52 declare { i8, i64 } @llvm.x86.addcarry.64(i8, i64, i64) #1 53 54 ; Function Attrs: nounwind 55 declare void @llvm.stackprotector(i8*, i8**) #2 56 57 attributes #0 = { nounwind "target-features"="+adx" } 58 attributes #1 = { nounwind readnone "target-features"="+adx" } 59 attributes #2 = { nounwind } 60 61... 62--- 63name: stack_fold_adcx32 64alignment: 4 65tracksRegLiveness: true 66registers: 67 - { id: 0, class: gr32 } 68 - { id: 1, class: gr32 } 69 - { id: 2, class: gr32 } 70 - { id: 3, class: gr64 } 71 - { id: 4, class: fr64 } 72 - { id: 5, class: gr8 } 73 - { id: 6, class: gr8 } 74 - { id: 7, class: gr32 } 75 - { id: 8, class: gr8 } 76liveins: 77 - { reg: '$edi', virtual-reg: '%0' } 78 - { reg: '$esi', virtual-reg: '%1' } 79 - { reg: '$edx', virtual-reg: '%2' } 80 - { reg: '$rcx', virtual-reg: '%3' } 81body: | 82 bb.0 (%ir-block.0): 83 liveins: $edi, $esi, $edx, $rcx 84 85 ; CHECK-LABEL: name: stack_fold_adcx32 86 ; CHECK: liveins: $edi, $esi, $edx, $rcx 87 ; CHECK: MOV64mr %stack.0, 1, $noreg, 0, $noreg, $rcx :: (store 8 into %stack.0) 88 ; CHECK: MOV32mr %stack.1, 1, $noreg, 0, $noreg, $edx :: (store 4 into %stack.1) 89 ; CHECK: MOV32mr %stack.2, 1, $noreg, 0, $noreg, $esi :: (store 4 into %stack.2) 90 ; CHECK: MOV32mr %stack.3, 1, $noreg, 0, $noreg, $edi :: (store 4 into %stack.3) 91 ; CHECK: INLINEASM &nop, 1, 3145738, def dead %4, 12, implicit-def dead early-clobber $rax, 12, implicit-def dead early-clobber $rbx, 12, implicit-def dead early-clobber $rcx, 12, implicit-def dead early-clobber $rdx, 12, implicit-def dead early-clobber $rsi, 12, implicit-def dead early-clobber $rdi, 12, implicit-def dead early-clobber $rbp, 12, implicit-def dead early-clobber $r8, 12, implicit-def dead early-clobber $r9, 12, implicit-def dead early-clobber $r10, 12, implicit-def dead early-clobber $r11, 12, implicit-def dead early-clobber $r12, 12, implicit-def dead early-clobber $r13, 12, implicit-def dead early-clobber $r14, 12, implicit-def dead early-clobber $r15 92 ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %stack.3, 1, $noreg, 0, $noreg :: (load 4 from %stack.3) 93 ; CHECK: dead [[MOV32rm]].sub_8bit:gr32 = ADD8ri [[MOV32rm]].sub_8bit, -1, implicit-def $eflags 94 ; CHECK: [[MOV32rm1:%[0-9]+]]:gr32 = MOV32rm %stack.2, 1, $noreg, 0, $noreg :: (load 4 from %stack.2) 95 ; CHECK: [[ADCX32rm:%[0-9]+]]:gr32 = ADCX32rm [[ADCX32rm]], %stack.1, 1, $noreg, 0, $noreg, implicit-def $eflags, implicit killed $eflags :: (load 4 from %stack.1) 96 ; CHECK: [[SETBr:%[0-9]+]]:gr8 = SETBr implicit killed $eflags 97 ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load 8 from %stack.0) 98 ; CHECK: MOV32mr [[MOV64rm]], 1, $noreg, 0, $noreg, [[ADCX32rm]] :: (store 4 into %ir.4, align 1) 99 ; CHECK: $al = COPY [[SETBr]] 100 ; CHECK: RET 0, $al 101 %3:gr64 = COPY $rcx 102 %2:gr32 = COPY $edx 103 %7:gr32 = COPY $esi 104 %0:gr32 = COPY $edi 105 INLINEASM &nop, 1, 3145738, def dead %4, 12, implicit-def dead early-clobber $rax, 12, implicit-def dead early-clobber $rbx, 12, implicit-def dead early-clobber $rcx, 12, implicit-def dead early-clobber $rdx, 12, implicit-def dead early-clobber $rsi, 12, implicit-def dead early-clobber $rdi, 12, implicit-def dead early-clobber $rbp, 12, implicit-def dead early-clobber $r8, 12, implicit-def dead early-clobber $r9, 12, implicit-def dead early-clobber $r10, 12, implicit-def dead early-clobber $r11, 12, implicit-def dead early-clobber $r12, 12, implicit-def dead early-clobber $r13, 12, implicit-def dead early-clobber $r14, 12, implicit-def dead early-clobber $r15 106 dead %0.sub_8bit:gr32 = ADD8ri %0.sub_8bit, -1, implicit-def $eflags 107 %7:gr32 = ADCX32rr %7, %2, implicit-def $eflags, implicit killed $eflags 108 %8:gr8 = SETBr implicit killed $eflags 109 MOV32mr %3, 1, $noreg, 0, $noreg, %7 :: (store 4 into %ir.4, align 1) 110 $al = COPY %8 111 RET 0, killed $al 112 113... 114--- 115name: stack_fold_adcx64 116alignment: 4 117tracksRegLiveness: true 118registers: 119 - { id: 0, class: gr32 } 120 - { id: 1, class: gr64 } 121 - { id: 2, class: gr64 } 122 - { id: 3, class: gr64 } 123 - { id: 4, class: fr64 } 124 - { id: 5, class: gr8 } 125 - { id: 6, class: gr8 } 126 - { id: 7, class: gr64 } 127 - { id: 8, class: gr8 } 128liveins: 129 - { reg: '$edi', virtual-reg: '%0' } 130 - { reg: '$rsi', virtual-reg: '%1' } 131 - { reg: '$rdx', virtual-reg: '%2' } 132 - { reg: '$rcx', virtual-reg: '%3' } 133body: | 134 bb.0 (%ir-block.0): 135 liveins: $edi, $rsi, $rdx, $rcx 136 137 ; CHECK-LABEL: name: stack_fold_adcx64 138 ; CHECK: liveins: $edi, $rsi, $rdx, $rcx 139 ; CHECK: MOV64mr %stack.0, 1, $noreg, 0, $noreg, $rcx :: (store 8 into %stack.0) 140 ; CHECK: MOV64mr %stack.1, 1, $noreg, 0, $noreg, $rdx :: (store 8 into %stack.1) 141 ; CHECK: MOV64mr %stack.2, 1, $noreg, 0, $noreg, $rsi :: (store 8 into %stack.2) 142 ; CHECK: MOV32mr %stack.3, 1, $noreg, 0, $noreg, $edi :: (store 4 into %stack.3) 143 ; CHECK: INLINEASM &nop, 1, 3145738, def dead %4, 12, implicit-def dead early-clobber $rax, 12, implicit-def dead early-clobber $rbx, 12, implicit-def dead early-clobber $rcx, 12, implicit-def dead early-clobber $rdx, 12, implicit-def dead early-clobber $rsi, 12, implicit-def dead early-clobber $rdi, 12, implicit-def dead early-clobber $rbp, 12, implicit-def dead early-clobber $r8, 12, implicit-def dead early-clobber $r9, 12, implicit-def dead early-clobber $r10, 12, implicit-def dead early-clobber $r11, 12, implicit-def dead early-clobber $r12, 12, implicit-def dead early-clobber $r13, 12, implicit-def dead early-clobber $r14, 12, implicit-def dead early-clobber $r15 144 ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %stack.3, 1, $noreg, 0, $noreg :: (load 4 from %stack.3) 145 ; CHECK: dead [[MOV32rm]].sub_8bit:gr32 = ADD8ri [[MOV32rm]].sub_8bit, -1, implicit-def $eflags 146 ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm %stack.2, 1, $noreg, 0, $noreg :: (load 8 from %stack.2) 147 ; CHECK: [[ADCX64rm:%[0-9]+]]:gr64 = ADCX64rm [[ADCX64rm]], %stack.1, 1, $noreg, 0, $noreg, implicit-def $eflags, implicit killed $eflags :: (load 8 from %stack.1) 148 ; CHECK: [[SETBr:%[0-9]+]]:gr8 = SETBr implicit killed $eflags 149 ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load 8 from %stack.0) 150 ; CHECK: MOV64mr [[MOV64rm]], 1, $noreg, 0, $noreg, [[ADCX64rm]] :: (store 8 into %ir.4, align 1) 151 ; CHECK: $al = COPY [[SETBr]] 152 ; CHECK: RET 0, $al 153 %3:gr64 = COPY $rcx 154 %2:gr64 = COPY $rdx 155 %7:gr64 = COPY $rsi 156 %0:gr32 = COPY $edi 157 INLINEASM &nop, 1, 3145738, def dead %4, 12, implicit-def dead early-clobber $rax, 12, implicit-def dead early-clobber $rbx, 12, implicit-def dead early-clobber $rcx, 12, implicit-def dead early-clobber $rdx, 12, implicit-def dead early-clobber $rsi, 12, implicit-def dead early-clobber $rdi, 12, implicit-def dead early-clobber $rbp, 12, implicit-def dead early-clobber $r8, 12, implicit-def dead early-clobber $r9, 12, implicit-def dead early-clobber $r10, 12, implicit-def dead early-clobber $r11, 12, implicit-def dead early-clobber $r12, 12, implicit-def dead early-clobber $r13, 12, implicit-def dead early-clobber $r14, 12, implicit-def dead early-clobber $r15 158 dead %0.sub_8bit:gr32 = ADD8ri %0.sub_8bit, -1, implicit-def $eflags 159 %7:gr64 = ADCX64rr %7, %2, implicit-def $eflags, implicit killed $eflags 160 %8:gr8 = SETBr implicit killed $eflags 161 MOV64mr %3, 1, $noreg, 0, $noreg, %7 :: (store 8 into %ir.4, align 1) 162 $al = COPY %8 163 RET 0, killed $al 164 165... 166--- 167name: stack_fold_adox32 168alignment: 4 169tracksRegLiveness: true 170registers: 171 - { id: 0, class: gr32 } 172 - { id: 1, class: gr32 } 173 - { id: 2, class: gr32 } 174 - { id: 3, class: gr64 } 175 - { id: 4, class: fr64 } 176 - { id: 5, class: gr8 } 177 - { id: 6, class: gr8 } 178 - { id: 7, class: gr32 } 179 - { id: 8, class: gr8 } 180liveins: 181 - { reg: '$edi', virtual-reg: '%0' } 182 - { reg: '$esi', virtual-reg: '%1' } 183 - { reg: '$edx', virtual-reg: '%2' } 184 - { reg: '$rcx', virtual-reg: '%3' } 185body: | 186 bb.0 (%ir-block.0): 187 liveins: $edi, $esi, $edx, $rcx 188 189 ; CHECK-LABEL: name: stack_fold_adox32 190 ; CHECK: liveins: $edi, $esi, $edx, $rcx 191 ; CHECK: MOV64mr %stack.0, 1, $noreg, 0, $noreg, $rcx :: (store 8 into %stack.0) 192 ; CHECK: MOV32mr %stack.1, 1, $noreg, 0, $noreg, $edx :: (store 4 into %stack.1) 193 ; CHECK: MOV32mr %stack.2, 1, $noreg, 0, $noreg, $esi :: (store 4 into %stack.2) 194 ; CHECK: MOV32mr %stack.3, 1, $noreg, 0, $noreg, $edi :: (store 4 into %stack.3) 195 ; CHECK: INLINEASM &nop, 1, 3145738, def dead %4, 12, implicit-def dead early-clobber $rax, 12, implicit-def dead early-clobber $rbx, 12, implicit-def dead early-clobber $rcx, 12, implicit-def dead early-clobber $rdx, 12, implicit-def dead early-clobber $rsi, 12, implicit-def dead early-clobber $rdi, 12, implicit-def dead early-clobber $rbp, 12, implicit-def dead early-clobber $r8, 12, implicit-def dead early-clobber $r9, 12, implicit-def dead early-clobber $r10, 12, implicit-def dead early-clobber $r11, 12, implicit-def dead early-clobber $r12, 12, implicit-def dead early-clobber $r13, 12, implicit-def dead early-clobber $r14, 12, implicit-def dead early-clobber $r15 196 ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %stack.3, 1, $noreg, 0, $noreg :: (load 4 from %stack.3) 197 ; CHECK: dead [[MOV32rm]].sub_8bit:gr32 = ADD8ri [[MOV32rm]].sub_8bit, 127, implicit-def $eflags 198 ; CHECK: [[MOV32rm1:%[0-9]+]]:gr32 = MOV32rm %stack.2, 1, $noreg, 0, $noreg :: (load 4 from %stack.2) 199 ; CHECK: [[ADOX32rm:%[0-9]+]]:gr32 = ADOX32rm [[ADOX32rm]], %stack.1, 1, $noreg, 0, $noreg, implicit-def $eflags, implicit killed $eflags :: (load 4 from %stack.1) 200 ; CHECK: [[SETOr:%[0-9]+]]:gr8 = SETOr implicit killed $eflags 201 ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load 8 from %stack.0) 202 ; CHECK: MOV32mr [[MOV64rm]], 1, $noreg, 0, $noreg, [[ADOX32rm]] :: (store 4 into %ir.4, align 1) 203 ; CHECK: $al = COPY [[SETOr]] 204 ; CHECK: RET 0, $al 205 %3:gr64 = COPY $rcx 206 %2:gr32 = COPY $edx 207 %7:gr32 = COPY $esi 208 %0:gr32 = COPY $edi 209 INLINEASM &nop, 1, 3145738, def dead %4, 12, implicit-def dead early-clobber $rax, 12, implicit-def dead early-clobber $rbx, 12, implicit-def dead early-clobber $rcx, 12, implicit-def dead early-clobber $rdx, 12, implicit-def dead early-clobber $rsi, 12, implicit-def dead early-clobber $rdi, 12, implicit-def dead early-clobber $rbp, 12, implicit-def dead early-clobber $r8, 12, implicit-def dead early-clobber $r9, 12, implicit-def dead early-clobber $r10, 12, implicit-def dead early-clobber $r11, 12, implicit-def dead early-clobber $r12, 12, implicit-def dead early-clobber $r13, 12, implicit-def dead early-clobber $r14, 12, implicit-def dead early-clobber $r15 210 dead %0.sub_8bit:gr32 = ADD8ri %0.sub_8bit, 127, implicit-def $eflags 211 %7:gr32 = ADOX32rr %7, %2, implicit-def $eflags, implicit killed $eflags 212 %8:gr8 = SETOr implicit killed $eflags 213 MOV32mr %3, 1, $noreg, 0, $noreg, %7 :: (store 4 into %ir.4, align 1) 214 $al = COPY %8 215 RET 0, killed $al 216 217... 218--- 219name: stack_fold_adox64 220alignment: 4 221tracksRegLiveness: true 222registers: 223 - { id: 0, class: gr32 } 224 - { id: 1, class: gr64 } 225 - { id: 2, class: gr64 } 226 - { id: 3, class: gr64 } 227 - { id: 4, class: fr64 } 228 - { id: 5, class: gr8 } 229 - { id: 6, class: gr8 } 230 - { id: 7, class: gr64 } 231 - { id: 8, class: gr8 } 232liveins: 233 - { reg: '$edi', virtual-reg: '%0' } 234 - { reg: '$rsi', virtual-reg: '%1' } 235 - { reg: '$rdx', virtual-reg: '%2' } 236 - { reg: '$rcx', virtual-reg: '%3' } 237body: | 238 bb.0 (%ir-block.0): 239 liveins: $edi, $rsi, $rdx, $rcx 240 241 ; CHECK-LABEL: name: stack_fold_adox64 242 ; CHECK: liveins: $edi, $rsi, $rdx, $rcx 243 ; CHECK: MOV64mr %stack.0, 1, $noreg, 0, $noreg, $rcx :: (store 8 into %stack.0) 244 ; CHECK: MOV64mr %stack.1, 1, $noreg, 0, $noreg, $rdx :: (store 8 into %stack.1) 245 ; CHECK: MOV64mr %stack.2, 1, $noreg, 0, $noreg, $rsi :: (store 8 into %stack.2) 246 ; CHECK: MOV32mr %stack.3, 1, $noreg, 0, $noreg, $edi :: (store 4 into %stack.3) 247 ; CHECK: INLINEASM &nop, 1, 3145738, def dead %4, 12, implicit-def dead early-clobber $rax, 12, implicit-def dead early-clobber $rbx, 12, implicit-def dead early-clobber $rcx, 12, implicit-def dead early-clobber $rdx, 12, implicit-def dead early-clobber $rsi, 12, implicit-def dead early-clobber $rdi, 12, implicit-def dead early-clobber $rbp, 12, implicit-def dead early-clobber $r8, 12, implicit-def dead early-clobber $r9, 12, implicit-def dead early-clobber $r10, 12, implicit-def dead early-clobber $r11, 12, implicit-def dead early-clobber $r12, 12, implicit-def dead early-clobber $r13, 12, implicit-def dead early-clobber $r14, 12, implicit-def dead early-clobber $r15 248 ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %stack.3, 1, $noreg, 0, $noreg :: (load 4 from %stack.3) 249 ; CHECK: dead [[MOV32rm]].sub_8bit:gr32 = ADD8ri [[MOV32rm]].sub_8bit, 127, implicit-def $eflags 250 ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm %stack.2, 1, $noreg, 0, $noreg :: (load 8 from %stack.2) 251 ; CHECK: [[ADOX64rm:%[0-9]+]]:gr64 = ADOX64rm [[ADOX64rm]], %stack.1, 1, $noreg, 0, $noreg, implicit-def $eflags, implicit killed $eflags :: (load 8 from %stack.1) 252 ; CHECK: [[SETOr:%[0-9]+]]:gr8 = SETOr implicit killed $eflags 253 ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load 8 from %stack.0) 254 ; CHECK: MOV64mr [[MOV64rm]], 1, $noreg, 0, $noreg, [[ADOX64rm]] :: (store 8 into %ir.4, align 1) 255 ; CHECK: $al = COPY [[SETOr]] 256 ; CHECK: RET 0, $al 257 %3:gr64 = COPY $rcx 258 %2:gr64 = COPY $rdx 259 %7:gr64 = COPY $rsi 260 %0:gr32 = COPY $edi 261 INLINEASM &nop, 1, 3145738, def dead %4, 12, implicit-def dead early-clobber $rax, 12, implicit-def dead early-clobber $rbx, 12, implicit-def dead early-clobber $rcx, 12, implicit-def dead early-clobber $rdx, 12, implicit-def dead early-clobber $rsi, 12, implicit-def dead early-clobber $rdi, 12, implicit-def dead early-clobber $rbp, 12, implicit-def dead early-clobber $r8, 12, implicit-def dead early-clobber $r9, 12, implicit-def dead early-clobber $r10, 12, implicit-def dead early-clobber $r11, 12, implicit-def dead early-clobber $r12, 12, implicit-def dead early-clobber $r13, 12, implicit-def dead early-clobber $r14, 12, implicit-def dead early-clobber $r15 262 dead %0.sub_8bit:gr32 = ADD8ri %0.sub_8bit, 127, implicit-def $eflags 263 %7:gr64 = ADOX64rr %7, %2, implicit-def $eflags, implicit killed $eflags 264 %8:gr8 = SETOr implicit killed $eflags 265 MOV64mr %3, 1, $noreg, 0, $noreg, %7 :: (store 8 into %ir.4, align 1) 266 $al = COPY %8 267 RET 0, killed $al 268 269... 270