| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 |
| ; RUN: llc -mtriple=aarch64-apple-ios -verify-machineinstrs -global-isel -aarch64-enable-sink-fold=true -aarch64-postlegalizer-consecutive-memops=0 < %s | FileCheck %s --check-prefix=CHECK-NO-SPLIT |
| ; RUN: llc -mtriple=aarch64-apple-ios -verify-machineinstrs -global-isel -aarch64-enable-sink-fold=true < %s | FileCheck %s --check-prefix=CHECK-SPLIT |
| |
| define void @basic_split(ptr %p) { |
| ; CHECK-NO-SPLIT-LABEL: basic_split: |
| ; CHECK-NO-SPLIT: ; %bb.0: |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8000] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8008] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8016] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8024] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8032] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8040] |
| ; CHECK-NO-SPLIT-NEXT: ret |
| ; |
| ; CHECK-SPLIT-LABEL: basic_split: |
| ; CHECK-SPLIT: ; %bb.0: |
| ; CHECK-SPLIT-NEXT: mov w8, #8000 ; =0x1f40 |
| ; CHECK-SPLIT-NEXT: add x8, x0, x8 |
| ; CHECK-SPLIT-NEXT: stp xzr, xzr, [x8] |
| ; CHECK-SPLIT-NEXT: stp xzr, xzr, [x8, #16] |
| ; CHECK-SPLIT-NEXT: stp xzr, xzr, [x8, #32] |
| ; CHECK-SPLIT-NEXT: ret |
| %bigoffset = getelementptr i64, ptr %p, i64 1000 |
| store i64 0, ptr %bigoffset |
| %addr2 = getelementptr i64, ptr %p, i64 1001 |
| store i64 0, ptr %addr2 |
| %addr3 = getelementptr i64, ptr %p, i64 1002 |
| store i64 0, ptr %addr3 |
| %addr4 = getelementptr i64, ptr %p, i64 1003 |
| store i64 0, ptr %addr4 |
| %addr5 = getelementptr i64, ptr %p, i64 1004 |
| store i64 0, ptr %addr5 |
| %addr6 = getelementptr i64, ptr %p, i64 1005 |
| store i64 0, ptr %addr6 |
| ret void |
| } |
| |
| define void @basic_multi_use_ptr(ptr %p, ptr %p2) { |
| ; CHECK-NO-SPLIT-LABEL: basic_multi_use_ptr: |
| ; CHECK-NO-SPLIT: ; %bb.0: |
| ; CHECK-NO-SPLIT-NEXT: mov w8, #8008 ; =0x1f48 |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8000] |
| ; CHECK-NO-SPLIT-NEXT: add x8, x0, x8 |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8008] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8016] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8024] |
| ; CHECK-NO-SPLIT-NEXT: str x8, [x1] |
| ; CHECK-NO-SPLIT-NEXT: ret |
| ; |
| ; CHECK-SPLIT-LABEL: basic_multi_use_ptr: |
| ; CHECK-SPLIT: ; %bb.0: |
| ; CHECK-SPLIT-NEXT: mov w8, #8008 ; =0x1f48 |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8000] |
| ; CHECK-SPLIT-NEXT: add x8, x0, x8 |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8008] |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8016] |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8024] |
| ; CHECK-SPLIT-NEXT: str x8, [x1] |
| ; CHECK-SPLIT-NEXT: ret |
| %bigoffset = getelementptr i64, ptr %p, i64 1000 |
| store i64 0, ptr %bigoffset |
| %addr2 = getelementptr i64, ptr %p, i64 1001 |
| store i64 0, ptr %addr2 |
| %addr3 = getelementptr i64, ptr %p, i64 1002 |
| store i64 0, ptr %addr3 |
| %addr4 = getelementptr i64, ptr %p, i64 1003 |
| store i64 0, ptr %addr4 |
| ; multiuse of %addr2 |
| store ptr %addr2, ptr %p2 |
| ret void |
| } |
| |
| define void @not_consecutive(ptr %p) { |
| ; CHECK-NO-SPLIT-LABEL: not_consecutive: |
| ; CHECK-NO-SPLIT: ; %bb.0: |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8000] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8008] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8024] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8032] |
| ; CHECK-NO-SPLIT-NEXT: ret |
| ; |
| ; CHECK-SPLIT-LABEL: not_consecutive: |
| ; CHECK-SPLIT: ; %bb.0: |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8000] |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8008] |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8024] |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8032] |
| ; CHECK-SPLIT-NEXT: ret |
| %bigoffset = getelementptr i64, ptr %p, i64 1000 |
| store i64 0, ptr %bigoffset |
| %addr2 = getelementptr i64, ptr %p, i64 1001 |
| store i64 0, ptr %addr2 |
| %addr3 = getelementptr i64, ptr %p, i64 1003 |
| store i64 0, ptr %addr3 |
| %addr4 = getelementptr i64, ptr %p, i64 1004 |
| store i64 0, ptr %addr4 |
| ret void |
| } |
| |
| define void @early_store_is_invalid_but_split_rest(ptr %p) { |
| ; CHECK-NO-SPLIT-LABEL: early_store_is_invalid_but_split_rest: |
| ; CHECK-NO-SPLIT: ; %bb.0: |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8000] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8080] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8016] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8024] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8032] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8040] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8048] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8056] |
| ; CHECK-NO-SPLIT-NEXT: ret |
| ; |
| ; CHECK-SPLIT-LABEL: early_store_is_invalid_but_split_rest: |
| ; CHECK-SPLIT: ; %bb.0: |
| ; CHECK-SPLIT-NEXT: mov w8, #8016 ; =0x1f50 |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8000] |
| ; CHECK-SPLIT-NEXT: add x8, x0, x8 |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8080] |
| ; CHECK-SPLIT-NEXT: stp xzr, xzr, [x8] |
| ; CHECK-SPLIT-NEXT: stp xzr, xzr, [x8, #16] |
| ; CHECK-SPLIT-NEXT: stp xzr, xzr, [x8, #32] |
| ; CHECK-SPLIT-NEXT: ret |
| %bigoffset = getelementptr i64, ptr %p, i64 1000 |
| store i64 0, ptr %bigoffset |
| %addr2 = getelementptr i64, ptr %p, i64 1010 |
| store i64 0, ptr %addr2 |
| %addr3 = getelementptr i64, ptr %p, i64 1002 |
| store i64 0, ptr %addr3 |
| %addr4 = getelementptr i64, ptr %p, i64 1003 |
| store i64 0, ptr %addr4 |
| %addr5 = getelementptr i64, ptr %p, i64 1004 |
| store i64 0, ptr %addr5 |
| %addr6 = getelementptr i64, ptr %p, i64 1005 |
| store i64 0, ptr %addr6 |
| %addr7 = getelementptr i64, ptr %p, i64 1006 |
| store i64 0, ptr %addr7 |
| %addr8 = getelementptr i64, ptr %p, i64 1007 |
| store i64 0, ptr %addr8 |
| ret void |
| } |
| |
| define void @vector(ptr %p) { |
| ; CHECK-NO-SPLIT-LABEL: vector: |
| ; CHECK-NO-SPLIT: ; %bb.0: |
| ; CHECK-NO-SPLIT-NEXT: movi.2d v0, #0000000000000000 |
| ; CHECK-NO-SPLIT-NEXT: str q0, [x0, #16000] |
| ; CHECK-NO-SPLIT-NEXT: str q0, [x0, #16016] |
| ; CHECK-NO-SPLIT-NEXT: str q0, [x0, #16032] |
| ; CHECK-NO-SPLIT-NEXT: str q0, [x0, #16048] |
| ; CHECK-NO-SPLIT-NEXT: str q0, [x0, #16064] |
| ; CHECK-NO-SPLIT-NEXT: str q0, [x0, #16080] |
| ; CHECK-NO-SPLIT-NEXT: str q0, [x0, #16096] |
| ; CHECK-NO-SPLIT-NEXT: str q0, [x0, #16112] |
| ; CHECK-NO-SPLIT-NEXT: ret |
| ; |
| ; CHECK-SPLIT-LABEL: vector: |
| ; CHECK-SPLIT: ; %bb.0: |
| ; CHECK-SPLIT-NEXT: movi.2d v0, #0000000000000000 |
| ; CHECK-SPLIT-NEXT: mov w8, #16000 ; =0x3e80 |
| ; CHECK-SPLIT-NEXT: add x8, x0, x8 |
| ; CHECK-SPLIT-NEXT: stp q0, q0, [x8] |
| ; CHECK-SPLIT-NEXT: stp q0, q0, [x8, #32] |
| ; CHECK-SPLIT-NEXT: stp q0, q0, [x8, #64] |
| ; CHECK-SPLIT-NEXT: stp q0, q0, [x8, #96] |
| ; CHECK-SPLIT-NEXT: ret |
| %bigoffset = getelementptr <2 x i64>, ptr %p, i64 1000 |
| store <2 x i64> <i64 0, i64 0>, ptr %bigoffset |
| %addr2 = getelementptr <2 x i64>, ptr %p, i64 1001 |
| store <2 x i64> <i64 0, i64 0>, ptr %addr2 |
| %addr3 = getelementptr <2 x i64>, ptr %p, i64 1002 |
| store <2 x i64> <i64 0, i64 0>, ptr %addr3 |
| %addr4 = getelementptr <2 x i64>, ptr %p, i64 1003 |
| store <2 x i64> <i64 0, i64 0>, ptr %addr4 |
| %addr5 = getelementptr <2 x i64>, ptr %p, i64 1004 |
| store <2 x i64> <i64 0, i64 0>, ptr %addr5 |
| %addr6 = getelementptr <2 x i64>, ptr %p, i64 1005 |
| store <2 x i64> <i64 0, i64 0>, ptr %addr6 |
| %addr7 = getelementptr <2 x i64>, ptr %p, i64 1006 |
| store <2 x i64> <i64 0, i64 0>, ptr %addr7 |
| %addr8 = getelementptr <2 x i64>, ptr %p, i64 1007 |
| store <2 x i64> <i64 0, i64 0>, ptr %addr8 |
| ret void |
| } |
| |
| define void @can_already_form_stp(ptr %p) { |
| ; CHECK-NO-SPLIT-LABEL: can_already_form_stp: |
| ; CHECK-NO-SPLIT: ; %bb.0: |
| ; CHECK-NO-SPLIT-NEXT: stp xzr, xzr, [x0, #80] |
| ; CHECK-NO-SPLIT-NEXT: stp xzr, xzr, [x0, #96] |
| ; CHECK-NO-SPLIT-NEXT: stp xzr, xzr, [x0, #112] |
| ; CHECK-NO-SPLIT-NEXT: ret |
| ; |
| ; CHECK-SPLIT-LABEL: can_already_form_stp: |
| ; CHECK-SPLIT: ; %bb.0: |
| ; CHECK-SPLIT-NEXT: stp xzr, xzr, [x0, #80] |
| ; CHECK-SPLIT-NEXT: stp xzr, xzr, [x0, #96] |
| ; CHECK-SPLIT-NEXT: stp xzr, xzr, [x0, #112] |
| ; CHECK-SPLIT-NEXT: ret |
| %bigoffset = getelementptr i64, ptr %p, i64 10 |
| store i64 0, ptr %bigoffset |
| %addr2 = getelementptr i64, ptr %p, i64 11 |
| store i64 0, ptr %addr2 |
| %addr3 = getelementptr i64, ptr %p, i64 12 |
| store i64 0, ptr %addr3 |
| %addr4 = getelementptr i64, ptr %p, i64 13 |
| store i64 0, ptr %addr4 |
| %addr5 = getelementptr i64, ptr %p, i64 14 |
| store i64 0, ptr %addr5 |
| %addr6 = getelementptr i64, ptr %p, i64 15 |
| store i64 0, ptr %addr6 |
| ret void |
| } |
| |
| define void @use_of_load_in_between(ptr %p, ptr %ldptr, ptr %ldptr2) { |
| ; CHECK-NO-SPLIT-LABEL: use_of_load_in_between: |
| ; CHECK-NO-SPLIT: ; %bb.0: |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8000] |
| ; CHECK-NO-SPLIT-NEXT: ldr x8, [x1] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8016] |
| ; CHECK-NO-SPLIT-NEXT: str x8, [x0, #8008] |
| ; CHECK-NO-SPLIT-NEXT: ldr x8, [x2] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8032] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8040] |
| ; CHECK-NO-SPLIT-NEXT: str x8, [x0, #8024] |
| ; CHECK-NO-SPLIT-NEXT: ret |
| ; |
| ; CHECK-SPLIT-LABEL: use_of_load_in_between: |
| ; CHECK-SPLIT: ; %bb.0: |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8000] |
| ; CHECK-SPLIT-NEXT: ldr x8, [x1] |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8016] |
| ; CHECK-SPLIT-NEXT: str x8, [x0, #8008] |
| ; CHECK-SPLIT-NEXT: ldr x8, [x2] |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8032] |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8040] |
| ; CHECK-SPLIT-NEXT: str x8, [x0, #8024] |
| ; CHECK-SPLIT-NEXT: ret |
| %bigoffset = getelementptr i64, ptr %p, i64 1000 |
| store i64 0, ptr %bigoffset |
| %addr2 = getelementptr i64, ptr %p, i64 1001 |
| %ld = load i64, ptr %ldptr |
| store i64 %ld, ptr %addr2 |
| %addr3 = getelementptr i64, ptr %p, i64 1002 |
| store i64 0, ptr %addr3 |
| %addr4 = getelementptr i64, ptr %p, i64 1003 |
| %ld2 = load i64, ptr %ldptr2 |
| store i64 %ld2, ptr %addr4 |
| %addr5 = getelementptr i64, ptr %p, i64 1004 |
| store i64 0, ptr %addr5 |
| %addr6 = getelementptr i64, ptr %p, i64 1005 |
| store i64 0, ptr %addr6 |
| ret void |
| } |
| |
| define void @offset_legal_for_add_imm(ptr %p) { |
| ; CHECK-NO-SPLIT-LABEL: offset_legal_for_add_imm: |
| ; CHECK-NO-SPLIT: ; %bb.0: |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #3200] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #3208] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #3216] |
| ; CHECK-NO-SPLIT-NEXT: ret |
| ; |
| ; CHECK-SPLIT-LABEL: offset_legal_for_add_imm: |
| ; CHECK-SPLIT: ; %bb.0: |
| ; CHECK-SPLIT-NEXT: add x8, x0, #3200 |
| ; CHECK-SPLIT-NEXT: stp xzr, xzr, [x8] |
| ; CHECK-SPLIT-NEXT: str xzr, [x8, #16] |
| ; CHECK-SPLIT-NEXT: ret |
| %bigoffset = getelementptr i64, ptr %p, i64 400 |
| store i64 0, ptr %bigoffset |
| %addr2 = getelementptr i64, ptr %p, i64 401 |
| store i64 0, ptr %addr2 |
| %addr3 = getelementptr i64, ptr %p, i64 402 |
| store i64 0, ptr %addr3 |
| ret void |
| } |
| |
| define void @offset_illegal_for_add_imm(ptr %p) { |
| ; CHECK-NO-SPLIT-LABEL: offset_illegal_for_add_imm: |
| ; CHECK-NO-SPLIT: ; %bb.0: |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8000] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8008] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8016] |
| ; CHECK-NO-SPLIT-NEXT: ret |
| ; |
| ; CHECK-SPLIT-LABEL: offset_illegal_for_add_imm: |
| ; CHECK-SPLIT: ; %bb.0: |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8000] |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8008] |
| ; CHECK-SPLIT-NEXT: str xzr, [x0, #8016] |
| ; CHECK-SPLIT-NEXT: ret |
| %bigoffset = getelementptr i64, ptr %p, i64 1000 |
| store i64 0, ptr %bigoffset |
| %addr2 = getelementptr i64, ptr %p, i64 1001 |
| store i64 0, ptr %addr2 |
| %addr3 = getelementptr i64, ptr %p, i64 1002 |
| store i64 0, ptr %addr3 |
| ret void |
| } |
| |
| define void @offset_legal_for_add_imm_4_stores(ptr %p) { |
| ; CHECK-NO-SPLIT-LABEL: offset_legal_for_add_imm_4_stores: |
| ; CHECK-NO-SPLIT: ; %bb.0: |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #3200] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #3208] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #3216] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #3224] |
| ; CHECK-NO-SPLIT-NEXT: ret |
| ; |
| ; CHECK-SPLIT-LABEL: offset_legal_for_add_imm_4_stores: |
| ; CHECK-SPLIT: ; %bb.0: |
| ; CHECK-SPLIT-NEXT: add x8, x0, #3200 |
| ; CHECK-SPLIT-NEXT: stp xzr, xzr, [x8] |
| ; CHECK-SPLIT-NEXT: stp xzr, xzr, [x8, #16] |
| ; CHECK-SPLIT-NEXT: ret |
| %bigoffset = getelementptr i64, ptr %p, i64 400 |
| store i64 0, ptr %bigoffset |
| %addr2 = getelementptr i64, ptr %p, i64 401 |
| store i64 0, ptr %addr2 |
| %addr3 = getelementptr i64, ptr %p, i64 402 |
| store i64 0, ptr %addr3 |
| %addr4 = getelementptr i64, ptr %p, i64 403 |
| store i64 0, ptr %addr4 |
| ret void |
| } |
| |
| define void @offset_illegal_for_add_imm_4_stores(ptr %p) { |
| ; CHECK-NO-SPLIT-LABEL: offset_illegal_for_add_imm_4_stores: |
| ; CHECK-NO-SPLIT: ; %bb.0: |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8000] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8008] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8016] |
| ; CHECK-NO-SPLIT-NEXT: str xzr, [x0, #8024] |
| ; CHECK-NO-SPLIT-NEXT: ret |
| ; |
| ; CHECK-SPLIT-LABEL: offset_illegal_for_add_imm_4_stores: |
| ; CHECK-SPLIT: ; %bb.0: |
| ; CHECK-SPLIT-NEXT: mov w8, #8000 ; =0x1f40 |
| ; CHECK-SPLIT-NEXT: add x8, x0, x8 |
| ; CHECK-SPLIT-NEXT: stp xzr, xzr, [x8] |
| ; CHECK-SPLIT-NEXT: stp xzr, xzr, [x8, #16] |
| ; CHECK-SPLIT-NEXT: ret |
| %bigoffset = getelementptr i64, ptr %p, i64 1000 |
| store i64 0, ptr %bigoffset |
| %addr2 = getelementptr i64, ptr %p, i64 1001 |
| store i64 0, ptr %addr2 |
| %addr3 = getelementptr i64, ptr %p, i64 1002 |
| store i64 0, ptr %addr3 |
| %addr4 = getelementptr i64, ptr %p, i64 1003 |
| store i64 0, ptr %addr4 |
| ret void |
| } |