1# RUN: llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o - %s | FileCheck %s 2# This test ensures that the MIR parser parses the machine memory operands 3# correctly. 4 5--- | 6 7 define i32 @test(i32* %a) { 8 entry: 9 %b = load i32, i32* %a 10 store i32 42, i32* %a 11 ret i32 %b 12 } 13 14 define void @test2(i32* %"a value") { 15 entry2: 16 %b = load i32, i32* %"a value" 17 %c = add i32 %b, 1 18 store i32 %c, i32* %"a value" 19 ret void 20 } 21 22 define void @test3(i32*) { 23 entry3: 24 %1 = alloca i32 25 %b = load i32, i32* %0 26 %c = add i32 %b, 1 27 store i32 %c, i32* %1 28 ret void 29 } 30 31 define i32 @volatile_inc(i32* %x) { 32 entry: 33 %0 = load volatile i32, i32* %x 34 %1 = add i32 %0, 1 35 store volatile i32 %1, i32* %x 36 ret i32 %1 37 } 38 39 define void @non_temporal_store(i32* %a, i32 %b) { 40 entry: 41 store i32 %b, i32* %a, align 16, !nontemporal !0 42 ret void 43 } 44 45 !0 = !{i32 1} 46 47 define i32 @invariant_load(i32* %x) { 48 entry: 49 %v = load i32, i32* %x, !invariant.load !1 50 ret i32 %v 51 } 52 53 !1 = !{} 54 55 define void @memory_offset(<8 x float>* %vec) { 56 entry: 57 %v = load <8 x float>, <8 x float>* %vec 58 %v2 = insertelement <8 x float> %v, float 0.0, i32 4 59 store <8 x float> %v2, <8 x float>* %vec 60 ret void 61 } 62 63 define void @memory_alignment(<8 x float>* %vec) { 64 entry: 65 %v = load <8 x float>, <8 x float>* %vec 66 %v2 = insertelement <8 x float> %v, float 0.0, i32 4 67 store <8 x float> %v2, <8 x float>* %vec 68 ret void 69 } 70 71 define double @constant_pool_psv(double %a) { 72 entry: 73 %b = fadd double %a, 3.250000e+00 74 ret double %b 75 } 76 77 declare x86_fp80 @cosl(x86_fp80) #0 78 79 define x86_fp80 @stack_psv(x86_fp80 %x) { 80 entry: 81 %y = call x86_fp80 @cosl(x86_fp80 %x) #0 82 ret x86_fp80 %y 83 } 84 85 attributes #0 = { readonly } 86 87 @G = external global i32 88 89 define i32 @got_psv() { 90 entry: 91 %a = load i32, i32* @G 92 %b = add i32 %a, 1 93 ret i32 %b 94 } 95 96 @0 = external global i32 97 98 define i32 @global_value() { 99 entry: 100 %a = load i32, i32* @G 101 %b = add i32 %a, 1 102 %c = load i32, i32* @0 103 %d = add i32 %b, %c 104 ret i32 %d 105 } 106 107 define i32 @jumptable_psv(i32 %in) { 108 entry: 109 switch i32 %in, label %def [ 110 i32 0, label %lbl1 111 i32 1, label %lbl2 112 i32 2, label %lbl3 113 i32 3, label %lbl4 114 ] 115 def: 116 ret i32 0 117 lbl1: 118 ret i32 1 119 lbl2: 120 ret i32 2 121 lbl3: 122 ret i32 4 123 lbl4: 124 ret i32 8 125 } 126 127 %struct.XXH_state64_t = type { i32, i32, i64, i64, i64 } 128 129 @a = common global i32 0, align 4 130 131 define i32 @tbaa_metadata() { 132 entry: 133 %0 = load i32, i32* @a, align 4, !tbaa !2 134 %1 = inttoptr i32 %0 to %struct.XXH_state64_t* 135 %total_len2 = bitcast %struct.XXH_state64_t* %1 to i32* 136 %2 = load i32, i32* %total_len2, align 4, !tbaa !6 137 ret i32 %2 138 } 139 140 !2 = !{!3, !3, i64 0} 141 !3 = !{!"int", !4, i64 0} 142 !4 = !{!"omnipotent char", !5, i64 0} 143 !5 = !{!"Simple C/C++ TBAA"} 144 !6 = !{!7, !3, i64 0} 145 !7 = !{!"XXH_state64_t", !3, i64 0, !3, i64 4, !8, i64 8, !8, i64 16, !8, i64 24} 146 !8 = !{!"long long", !4, i64 0} 147 148 define void @aa_scope(float* nocapture %a, float* nocapture readonly %c) #1 { 149 entry: 150 %0 = load float, float* %c, align 4, !alias.scope !9 151 %arrayidx.i = getelementptr inbounds float, float* %a, i64 5 152 store float %0, float* %arrayidx.i, align 4, !noalias !9 153 %1 = load float, float* %c, align 4 154 %arrayidx = getelementptr inbounds float, float* %a, i64 7 155 store float %1, float* %arrayidx, align 4 156 ret void 157 } 158 159 attributes #1 = { nounwind uwtable } 160 161 !9 = distinct !{!9, !10, !"some scope"} 162 !10 = distinct !{!10, !"some domain"} 163 164 define zeroext i1 @range_metadata(i8* %x) { 165 entry: 166 %0 = load i8, i8* %x, align 1, !range !11 167 %tobool = trunc i8 %0 to i1 168 ret i1 %tobool 169 } 170 171 !11 = !{i8 0, i8 2} 172 173 %st = type { i32, i32 } 174 175 @values = common global [50 x %st] zeroinitializer, align 16 176 177 define void @gep_value(i64 %d) { 178 entry: 179 %conv = trunc i64 %d to i32 180 store i32 %conv, i32* getelementptr inbounds ([50 x %st], [50 x %st]* @values, i64 0, i64 0, i32 0), align 16 181 ret void 182 } 183 184 define i8* @undef_value() { 185 entry: 186 %0 = load i8*, i8** undef, align 8 187 ret i8* %0 188 } 189 190 define void @dummy0() { ret void } 191 define void @dummy1() { ret void } 192... 193--- 194name: test 195tracksRegLiveness: true 196liveins: 197 - { reg: '%rdi' } 198body: | 199 bb.0.entry: 200 liveins: %rdi 201 ; CHECK: %eax = MOV32rm %rdi, 1, _, 0, _ :: (load 4 from %ir.a) 202 ; CHECK-NEXT: MOV32mi killed %rdi, 1, _, 0, _, 42 :: (store 4 into %ir.a) 203 %eax = MOV32rm %rdi, 1, _, 0, _ :: (load 4 from %ir.a) 204 MOV32mi killed %rdi, 1, _, 0, _, 42 :: (store 4 into %ir.a) 205 RETQ %eax 206... 207--- 208name: test2 209tracksRegLiveness: true 210liveins: 211 - { reg: '%rdi' } 212body: | 213 bb.0.entry2: 214 liveins: %rdi 215 ; CHECK: INC32m killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (store 4 into %ir."a value"), (load 4 from %ir."a value") 216 INC32m killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (store 4 into %ir."a value"), (load 4 from %ir."a value") 217 RETQ 218... 219--- 220name: test3 221tracksRegLiveness: true 222liveins: 223 - { reg: '%rdi' } 224frameInfo: 225 maxAlignment: 4 226stack: 227 - { id: 0, offset: -12, size: 4, alignment: 4 } 228body: | 229 bb.0.entry3: 230 liveins: %rdi 231 ; Verify that the unnamed local values can be serialized. 232 ; CHECK-LABEL: name: test3 233 ; CHECK: %eax = MOV32rm killed %rdi, 1, _, 0, _ :: (load 4 from %ir.0) 234 ; CHECK: MOV32mr %rsp, 1, _, -4, _, killed %eax :: (store 4 into %ir.1) 235 %eax = MOV32rm killed %rdi, 1, _, 0, _ :: (load 4 from %ir.0) 236 %eax = INC32r killed %eax, implicit-def dead %eflags 237 MOV32mr %rsp, 1, _, -4, _, killed %eax :: (store 4 into %ir.1) 238 RETQ 239... 240--- 241name: volatile_inc 242tracksRegLiveness: true 243liveins: 244 - { reg: '%rdi' } 245body: | 246 bb.0.entry: 247 liveins: %rdi 248 ; CHECK: name: volatile_inc 249 ; CHECK: %eax = MOV32rm %rdi, 1, _, 0, _ :: (volatile load 4 from %ir.x) 250 ; CHECK: MOV32mr killed %rdi, 1, _, 0, _, %eax :: (volatile store 4 into %ir.x) 251 %eax = MOV32rm %rdi, 1, _, 0, _ :: (volatile load 4 from %ir.x) 252 %eax = INC32r killed %eax, implicit-def dead %eflags 253 MOV32mr killed %rdi, 1, _, 0, _, %eax :: (volatile store 4 into %ir.x) 254 RETQ %eax 255... 256--- 257name: non_temporal_store 258tracksRegLiveness: true 259liveins: 260 - { reg: '%rdi' } 261 - { reg: '%esi' } 262body: | 263 bb.0.entry: 264 liveins: %esi, %rdi 265 ; CHECK: name: non_temporal_store 266 ; CHECK: MOVNTImr killed %rdi, 1, _, 0, _, killed %esi :: (non-temporal store 4 into %ir.a) 267 MOVNTImr killed %rdi, 1, _, 0, _, killed %esi :: (non-temporal store 4 into %ir.a) 268 RETQ 269... 270--- 271name: invariant_load 272tracksRegLiveness: true 273liveins: 274 - { reg: '%rdi' } 275body: | 276 bb.0.entry: 277 liveins: %rdi 278 ; CHECK: name: invariant_load 279 ; CHECK: %eax = MOV32rm killed %rdi, 1, _, 0, _ :: (invariant load 4 from %ir.x) 280 %eax = MOV32rm killed %rdi, 1, _, 0, _ :: (invariant load 4 from %ir.x) 281 RETQ %eax 282... 283--- 284name: memory_offset 285tracksRegLiveness: true 286liveins: 287 - { reg: '%rdi' } 288body: | 289 bb.0.entry: 290 liveins: %rdi 291 ; CHECK: name: memory_offset 292 ; CHECK: %xmm0 = MOVAPSrm %rdi, 1, _, 0, _ :: (load 16 from %ir.vec) 293 ; CHECK-NEXT: %xmm1 = MOVAPSrm %rdi, 1, _, 16, _ :: (load 16 from %ir.vec + 16) 294 ; CHECK: MOVAPSmr %rdi, 1, _, 0, _, killed %xmm0 :: (store 16 into %ir.vec) 295 ; CHECK-NEXT: MOVAPSmr killed %rdi, 1, _, 16, _, killed %xmm1 :: (store 16 into %ir.vec + 16) 296 %xmm0 = MOVAPSrm %rdi, 1, _, 0, _ :: (load 16 from %ir.vec) 297 %xmm1 = MOVAPSrm %rdi, 1, _, 16, _ :: (load 16 from %ir.vec + 16) 298 %xmm2 = FsFLD0SS 299 %xmm1 = MOVSSrr killed %xmm1, killed %xmm2 300 MOVAPSmr %rdi, 1, _, 0, _, killed %xmm0 :: (store 16 into %ir.vec) 301 MOVAPSmr killed %rdi, 1, _, 16, _, killed %xmm1 :: (store 16 into %ir.vec + 16) 302 RETQ 303... 304--- 305name: memory_alignment 306tracksRegLiveness: true 307liveins: 308 - { reg: '%rdi' } 309body: | 310 bb.0.entry: 311 liveins: %rdi 312 ; CHECK: name: memory_alignment 313 ; CHECK: %xmm0 = MOVAPSrm %rdi, 1, _, 0, _ :: (load 16 from %ir.vec, align 32) 314 ; CHECK-NEXT: %xmm1 = MOVAPSrm %rdi, 1, _, 16, _ :: (load 16 from %ir.vec + 16, align 32) 315 ; CHECK: MOVAPSmr %rdi, 1, _, 0, _, killed %xmm0 :: (store 16 into %ir.vec, align 32) 316 ; CHECK-NEXT: MOVAPSmr killed %rdi, 1, _, 16, _, killed %xmm1 :: (store 16 into %ir.vec + 16, align 32) 317 %xmm0 = MOVAPSrm %rdi, 1, _, 0, _ :: (load 16 from %ir.vec, align 32) 318 %xmm1 = MOVAPSrm %rdi, 1, _, 16, _ :: (load 16 from %ir.vec + 16, align 32) 319 %xmm2 = FsFLD0SS 320 %xmm1 = MOVSSrr killed %xmm1, killed %xmm2 321 MOVAPSmr %rdi, 1, _, 0, _, killed %xmm0 :: (store 16 into %ir.vec, align 32) 322 MOVAPSmr killed %rdi, 1, _, 16, _, killed %xmm1 :: (store 16 into %ir.vec + 16, align 32) 323 RETQ 324... 325--- 326name: constant_pool_psv 327tracksRegLiveness: true 328liveins: 329 - { reg: '%xmm0' } 330constants: 331 - id: 0 332 value: 'double 3.250000e+00' 333body: | 334 bb.0.entry: 335 liveins: %xmm0 336 ; CHECK: name: constant_pool_psv 337 ; CHECK: %xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _ :: (load 8 from constant-pool) 338 ; CHECK-NEXT: %xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _ :: (load 8 from constant-pool + 8) 339 %xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _ :: (load 8 from constant-pool) 340 %xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _ :: (load 8 from constant-pool + 8) 341 RETQ %xmm0 342... 343--- 344name: stack_psv 345tracksRegLiveness: true 346frameInfo: 347 stackSize: 24 348 maxAlignment: 16 349 adjustsStack: true 350 hasCalls: true 351 maxCallFrameSize: 16 352fixedStack: 353 - { id: 0, offset: 0, size: 10, alignment: 16, isImmutable: true, isAliased: false } 354body: | 355 bb.0.entry: 356 %rsp = frame-setup SUB64ri8 %rsp, 24, implicit-def dead %eflags 357 CFI_INSTRUCTION .cfi_def_cfa_offset 32 358 LD_F80m %rsp, 1, _, 32, _, implicit-def dead %fpsw 359 ; CHECK: name: stack_psv 360 ; CHECK: ST_FP80m %rsp, 1, _, 0, _, implicit-def dead %fpsw :: (store 10 into stack, align 16) 361 ST_FP80m %rsp, 1, _, 0, _, implicit-def dead %fpsw :: (store 10 into stack, align 16) 362 CALL64pcrel32 $cosl, csr_64, implicit %rsp, implicit-def %rsp, implicit-def %fp0 363 %rsp = ADD64ri8 %rsp, 24, implicit-def dead %eflags 364 RETQ 365... 366--- 367name: got_psv 368tracksRegLiveness: true 369body: | 370 bb.0.entry: 371 ; CHECK: name: got_psv 372 ; CHECK: %rax = MOV64rm %rip, 1, _, @G, _ :: (load 8 from got) 373 %rax = MOV64rm %rip, 1, _, @G, _ :: (load 8 from got) 374 %eax = MOV32rm killed %rax, 1, _, 0, _ 375 %eax = INC32r killed %eax, implicit-def dead %eflags 376 RETQ %eax 377... 378--- 379name: global_value 380tracksRegLiveness: true 381body: | 382 bb.0.entry: 383 %rax = MOV64rm %rip, 1, _, @G, _ 384 ; CHECK-LABEL: name: global_value 385 ; CHECK: %eax = MOV32rm killed %rax, 1, _, 0, _, implicit-def %rax :: (load 4 from @G) 386 ; CHECK: %ecx = MOV32rm killed %rcx, 1, _, 0, _, implicit-def %rcx :: (load 4 from @0) 387 %eax = MOV32rm killed %rax, 1, _, 0, _, implicit-def %rax :: (load 4 from @G) 388 %rcx = MOV64rm %rip, 1, _, @0, _ 389 %ecx = MOV32rm killed %rcx, 1, _, 0, _, implicit-def %rcx :: (load 4 from @0) 390 %eax = LEA64_32r killed %rax, 1, killed %rcx, 1, _ 391 RETQ %eax 392... 393--- 394name: jumptable_psv 395tracksRegLiveness: true 396liveins: 397 - { reg: '%edi' } 398jumpTable: 399 kind: label-difference32 400 entries: 401 - id: 0 402 blocks: [ '%bb.3.lbl1', '%bb.4.lbl2', '%bb.5.lbl3', '%bb.6.lbl4' ] 403body: | 404 bb.0.entry: 405 successors: %bb.2.def, %bb.1.entry 406 liveins: %edi 407 408 %eax = MOV32rr %edi, implicit-def %rax 409 CMP32ri8 killed %edi, 3, implicit-def %eflags 410 JA_1 %bb.2.def, implicit killed %eflags 411 412 bb.1.entry: 413 successors: %bb.3.lbl1, %bb.4.lbl2, %bb.5.lbl3, %bb.6.lbl4 414 liveins: %rax 415 416 %rcx = LEA64r %rip, 1, _, %jump-table.0, _ 417 ; CHECK: name: jumptable_psv 418 ; CHECK: %rax = MOVSX64rm32 %rcx, 4, killed %rax, 0, _ :: (load 4 from jump-table, align 8) 419 %rax = MOVSX64rm32 %rcx, 4, killed %rax, 0, _ :: (load 4 from jump-table, align 8) 420 %rax = ADD64rr killed %rax, killed %rcx, implicit-def dead %eflags 421 JMP64r killed %rax 422 423 bb.2.def: 424 %eax = MOV32r0 implicit-def dead %eflags 425 RETQ %eax 426 427 bb.3.lbl1: 428 %eax = MOV32ri 1 429 RETQ %eax 430 431 bb.4.lbl2: 432 %eax = MOV32ri 2 433 RETQ %eax 434 435 bb.5.lbl3: 436 %eax = MOV32ri 4 437 RETQ %eax 438 439 bb.6.lbl4: 440 %eax = MOV32ri 8 441 RETQ %eax 442... 443--- 444name: tbaa_metadata 445tracksRegLiveness: true 446body: | 447 bb.0.entry: 448 %rax = MOV64rm %rip, 1, _, @a, _ :: (load 8 from got) 449 ; CHECK-LABEL: name: tbaa_metadata 450 ; CHECK: %eax = MOV32rm killed %rax, 1, _, 0, _, implicit-def %rax :: (load 4 from @a, !tbaa !2) 451 ; CHECK-NEXT: %eax = MOV32rm killed %rax, 1, _, 0, _ :: (load 4 from %ir.total_len2, !tbaa !6) 452 %eax = MOV32rm killed %rax, 1, _, 0, _, implicit-def %rax :: (load 4 from @a, !tbaa !2) 453 %eax = MOV32rm killed %rax, 1, _, 0, _ :: (load 4 from %ir.total_len2, !tbaa !6) 454 RETQ %eax 455... 456--- 457name: aa_scope 458tracksRegLiveness: true 459liveins: 460 - { reg: '%rdi' } 461 - { reg: '%rsi' } 462body: | 463 bb.0.entry: 464 liveins: %rdi, %rsi 465 ; CHECK-LABEL: name: aa_scope 466 ; CHECK: %xmm0 = MOVSSrm %rsi, 1, _, 0, _ :: (load 4 from %ir.c, !alias.scope !9) 467 %xmm0 = MOVSSrm %rsi, 1, _, 0, _ :: (load 4 from %ir.c, !alias.scope !9) 468 ; CHECK-NEXT: MOVSSmr %rdi, 1, _, 20, _, killed %xmm0 :: (store 4 into %ir.arrayidx.i, !noalias !9) 469 MOVSSmr %rdi, 1, _, 20, _, killed %xmm0 :: (store 4 into %ir.arrayidx.i, !noalias !9) 470 %xmm0 = MOVSSrm killed %rsi, 1, _, 0, _ :: (load 4 from %ir.c) 471 MOVSSmr killed %rdi, 1, _, 28, _, killed %xmm0 :: (store 4 into %ir.arrayidx) 472 RETQ 473... 474--- 475name: range_metadata 476tracksRegLiveness: true 477liveins: 478 - { reg: '%rdi' } 479body: | 480 bb.0.entry: 481 liveins: %rdi 482 ; CHECK-LABEL: name: range_metadata 483 ; CHECK: %al = MOV8rm killed %rdi, 1, _, 0, _ :: (load 1 from %ir.x, !range !11) 484 %al = MOV8rm killed %rdi, 1, _, 0, _ :: (load 1 from %ir.x, !range !11) 485 RETQ %al 486... 487--- 488name: gep_value 489tracksRegLiveness: true 490liveins: 491 - { reg: '%rdi' } 492body: | 493 bb.0.entry: 494 liveins: %rdi 495 496 %rax = MOV64rm %rip, 1, _, @values, _ :: (load 8 from got) 497 ; CHECK-LABEL: gep_value 498 ; CHECK: MOV32mr killed %rax, 1, _, 0, _, %edi, implicit killed %rdi :: (store 4 into `i32* getelementptr inbounds ([50 x %st], [50 x %st]* @values, i64 0, i64 0, i32 0)`, align 16) 499 MOV32mr killed %rax, 1, _, 0, _, %edi, implicit killed %rdi :: (store 4 into `i32* getelementptr inbounds ([50 x %st], [50 x %st]* @values, i64 0, i64 0, i32 0)`, align 16) 500 RETQ 501... 502--- 503name: undef_value 504tracksRegLiveness: true 505body: | 506 bb.0.entry: 507 ; CHECK-LABEL: name: undef_value 508 ; CHECK: %rax = MOV64rm undef %rax, 1, _, 0, _ :: (load 8 from `i8** undef`) 509 %rax = MOV64rm undef %rax, 1, _, 0, _ :: (load 8 from `i8** undef`) 510 RETQ %rax 511... 512--- 513# Test memory operand without associated value. 514# CHECK-LABEL: name: dummy0 515# CHECK: %rax = MOV64rm undef %rax, 1, _, 0, _ :: (load 8) 516name: dummy0 517tracksRegLiveness: true 518body: | 519 bb.0: 520 %rax = MOV64rm undef %rax, 1, _, 0, _ :: (load 8) 521 RETQ %rax 522... 523--- 524# Test parsing of stack references in machine memory operands. 525# CHECK-LABEL: name: dummy1 526# CHECK: %rax = MOV64rm %rsp, 1, _, 0, _ :: (load 8 from %stack.0) 527name: dummy1 528tracksRegLiveness: true 529stack: 530 - { id: 0, size: 4, alignment: 4 } 531body: | 532 bb.0: 533 %rax = MOV64rm %rsp, 1, _, 0, _ :: (load 8 from %stack.0) 534 RETQ %rax 535 536... 537