223 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 32; RUN: llc -mtriple=arm64-apple-ios -global-isel -global-isel-abort=1 -verify-machineinstrs -stop-after=aarch64-postlegalizer-combiner -force-legal-indexing %s -o - | FileCheck %s3; RUN: llc -debugify-and-strip-all-safe -mtriple=arm64-apple-ios -global-isel -global-isel-abort=1 -verify-machineinstrs -stop-after=aarch64-postlegalizer-combiner -force-legal-indexing %s -o - | FileCheck %s4 5define ptr @test_simple_load_pre(ptr %ptr) {6 7 ; CHECK-LABEL: name: test_simple_load_pre8 ; CHECK: bb.1 (%ir-block.0):9 ; CHECK-NEXT: liveins: $x010 ; CHECK-NEXT: {{ $}}11 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x012 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4213 ; CHECK-NEXT: [[INDEXED_LOAD:%[0-9]+]]:_(s8), [[INDEXED_LOAD1:%[0-9]+]]:_(p0) = G_INDEXED_LOAD [[COPY]], [[C]](s64), 1 :: (volatile load (s8) from %ir.next)14 ; CHECK-NEXT: $x0 = COPY [[INDEXED_LOAD1]](p0)15 ; CHECK-NEXT: RET_ReallyLR implicit $x016 %next = getelementptr i8, ptr %ptr, i32 4217 load volatile i8, ptr %next18 ret ptr %next19}20 21define ptr @test_unused_load_pre(ptr %ptr) {22 23 ; CHECK-LABEL: name: test_unused_load_pre24 ; CHECK: bb.1 (%ir-block.0):25 ; CHECK-NEXT: liveins: $x026 ; CHECK-NEXT: {{ $}}27 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x028 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4229 ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C]](s64)30 ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s8) = G_LOAD [[PTR_ADD]](p0) :: (volatile load (s8) from %ir.next)31 ; CHECK-NEXT: [[C1:%[0-9]+]]:_(p0) = G_CONSTANT i64 032 ; CHECK-NEXT: $x0 = COPY [[C1]](p0)33 ; CHECK-NEXT: RET_ReallyLR implicit $x034 %next = getelementptr i8, ptr %ptr, i32 4235 load volatile i8, ptr %next36 ret ptr null37}38 39define ptr @test_simple_store_pre(ptr %ptr) {40 41 ; CHECK-LABEL: name: test_simple_store_pre42 ; CHECK: bb.1 (%ir-block.0):43 ; CHECK-NEXT: liveins: $x044 ; CHECK-NEXT: {{ $}}45 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x046 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4247 ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s8) = G_CONSTANT i8 048 ; CHECK-NEXT: [[INDEXED_STORE:%[0-9]+]]:_(p0) = G_INDEXED_STORE [[C1]](s8), [[COPY]], [[C]](s64), 1 :: (volatile store (s8) into %ir.next)49 ; CHECK-NEXT: $x0 = COPY [[INDEXED_STORE]](p0)50 ; CHECK-NEXT: RET_ReallyLR implicit $x051 %next = getelementptr i8, ptr %ptr, i32 4252 store volatile i8 0, ptr %next53 ret ptr %next54}55 56; The potentially pre-indexed address is used as the value stored. Converting57; would produce the value too late but only by one instruction.58define ptr @test_store_pre_val_loop(ptr %ptr) {59 60 ; CHECK-LABEL: name: test_store_pre_val_loop61 ; CHECK: bb.1 (%ir-block.0):62 ; CHECK-NEXT: liveins: $x063 ; CHECK-NEXT: {{ $}}64 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x065 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 33666 ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C]](s64)67 ; CHECK-NEXT: G_STORE [[PTR_ADD]](p0), [[PTR_ADD]](p0) :: (volatile store (p0) into %ir.next)68 ; CHECK-NEXT: $x0 = COPY [[PTR_ADD]](p0)69 ; CHECK-NEXT: RET_ReallyLR implicit $x070 %next = getelementptr ptr, ptr %ptr, i32 4271 store volatile ptr %next, ptr %next72 ret ptr %next73}74 75; Potentially pre-indexed address is used between GEP computing it and load.76define ptr @test_load_pre_before(ptr %ptr) {77 78 ; CHECK-LABEL: name: test_load_pre_before79 ; CHECK: bb.1 (%ir-block.0):80 ; CHECK-NEXT: liveins: $x081 ; CHECK-NEXT: {{ $}}82 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x083 ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp84 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4285 ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C]](s64)86 ; CHECK-NEXT: $x0 = COPY [[PTR_ADD]](p0)87 ; CHECK-NEXT: BL @bar, csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x088 ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp89 ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s8) = G_LOAD [[PTR_ADD]](p0) :: (volatile load (s8) from %ir.next)90 ; CHECK-NEXT: $x0 = COPY [[PTR_ADD]](p0)91 ; CHECK-NEXT: RET_ReallyLR implicit $x092 %next = getelementptr i8, ptr %ptr, i32 4293 call void @bar(ptr %next)94 load volatile i8, ptr %next95 ret ptr %next96}97 98; Materializing the base into a writable register (from sp/fp) would be just as99; bad as the original GEP.100define ptr @test_alloca_load_pre() {101 102 ; CHECK-LABEL: name: test_alloca_load_pre103 ; CHECK: bb.1 (%ir-block.0):104 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 42105 ; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.ptr106 ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[FRAME_INDEX]], [[C]](s64)107 ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s8) = G_LOAD [[PTR_ADD]](p0) :: (volatile load (s8) from %ir.next)108 ; CHECK-NEXT: $x0 = COPY [[PTR_ADD]](p0)109 ; CHECK-NEXT: RET_ReallyLR implicit $x0110 %ptr = alloca i8, i32 128111 %next = getelementptr i8, ptr %ptr, i32 42112 load volatile i8, ptr %next113 ret ptr %next114}115 116define ptr @test_simple_load_post(ptr %ptr) {117 118 ; CHECK-LABEL: name: test_simple_load_post119 ; CHECK: bb.1 (%ir-block.0):120 ; CHECK-NEXT: liveins: $x0121 ; CHECK-NEXT: {{ $}}122 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0123 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 42124 ; CHECK-NEXT: [[INDEXED_LOAD:%[0-9]+]]:_(s8), [[INDEXED_LOAD1:%[0-9]+]]:_(p0) = G_INDEXED_LOAD [[COPY]], [[C]](s64), 0 :: (volatile load (s8) from %ir.ptr)125 ; CHECK-NEXT: $x0 = COPY [[INDEXED_LOAD1]](p0)126 ; CHECK-NEXT: RET_ReallyLR implicit $x0127 %next = getelementptr i8, ptr %ptr, i32 42128 load volatile i8, ptr %ptr129 ret ptr %next130}131 132define ptr @test_simple_load_post_gep_after(ptr %ptr) {133 134 ; CHECK-LABEL: name: test_simple_load_post_gep_after135 ; CHECK: bb.1 (%ir-block.0):136 ; CHECK-NEXT: liveins: $x0137 ; CHECK-NEXT: {{ $}}138 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0139 ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp140 ; CHECK-NEXT: BL @get_offset, csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit-def $x0141 ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp142 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x0143 ; CHECK-NEXT: [[INDEXED_LOAD:%[0-9]+]]:_(s8), [[INDEXED_LOAD1:%[0-9]+]]:_(p0) = G_INDEXED_LOAD [[COPY]], [[COPY1]](s64), 0 :: (volatile load (s8) from %ir.ptr)144 ; CHECK-NEXT: $x0 = COPY [[INDEXED_LOAD1]](p0)145 ; CHECK-NEXT: RET_ReallyLR implicit $x0146 %offset = call i64 @get_offset()147 load volatile i8, ptr %ptr148 %next = getelementptr i8, ptr %ptr, i64 %offset149 ret ptr %next150}151 152define ptr @test_load_post_keep_looking(ptr %ptr) {153 154 ; CHECK-LABEL: name: test_load_post_keep_looking155 ; CHECK: bb.1 (%ir-block.0):156 ; CHECK-NEXT: liveins: $x0157 ; CHECK-NEXT: {{ $}}158 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0159 ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp160 ; CHECK-NEXT: BL @get_offset, csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit-def $x0161 ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp162 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x0163 ; CHECK-NEXT: [[INDEXED_LOAD:%[0-9]+]]:_(s8), [[INDEXED_LOAD1:%[0-9]+]]:_(p0) = G_INDEXED_LOAD [[COPY]], [[COPY1]](s64), 0 :: (volatile load (s8) from %ir.ptr)164 ; CHECK-NEXT: [[PTRTOINT:%[0-9]+]]:_(s64) = G_PTRTOINT [[COPY]](p0)165 ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[PTRTOINT]](s64)166 ; CHECK-NEXT: [[ADRP:%[0-9]+]]:gpr64(p0) = ADRP target-flags(aarch64-page) @var167 ; CHECK-NEXT: [[ADD_LOW:%[0-9]+]]:_(p0) = G_ADD_LOW [[ADRP]](p0), target-flags(aarch64-pageoff, aarch64-nc) @var168 ; CHECK-NEXT: G_STORE [[TRUNC]](s8), [[ADD_LOW]](p0) :: (store (s8) into @var)169 ; CHECK-NEXT: $x0 = COPY [[INDEXED_LOAD1]](p0)170 ; CHECK-NEXT: RET_ReallyLR implicit $x0171 %offset = call i64 @get_offset()172 load volatile i8, ptr %ptr173 %intval = ptrtoint ptr %ptr to i8174 store i8 %intval, ptr @var175 176 %next = getelementptr i8, ptr %ptr, i64 %offset177 ret ptr %next178}179 180; Base is frame index. Using indexing would need copy anyway.181define ptr @test_load_post_alloca() {182 183 ; CHECK-LABEL: name: test_load_post_alloca184 ; CHECK: bb.1 (%ir-block.0):185 ; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.ptr186 ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s8) = G_LOAD [[FRAME_INDEX]](p0) :: (volatile load (s8) from %ir.ptr)187 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 42188 ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[FRAME_INDEX]], [[C]](s64)189 ; CHECK-NEXT: $x0 = COPY [[PTR_ADD]](p0)190 ; CHECK-NEXT: RET_ReallyLR implicit $x0191 %ptr = alloca i8, i32 128192 %next = getelementptr i8, ptr %ptr, i32 42193 load volatile i8, ptr %ptr194 ret ptr %next195}196 197; Offset computation does not dominate the load we might be indexing.198define ptr @test_load_post_gep_offset_after(ptr %ptr) {199 200 ; CHECK-LABEL: name: test_load_post_gep_offset_after201 ; CHECK: bb.1 (%ir-block.0):202 ; CHECK-NEXT: liveins: $x0203 ; CHECK-NEXT: {{ $}}204 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0205 ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s8) = G_LOAD [[COPY]](p0) :: (volatile load (s8) from %ir.ptr)206 ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp207 ; CHECK-NEXT: BL @get_offset, csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit-def $x0208 ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp209 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x0210 ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[COPY1]](s64)211 ; CHECK-NEXT: $x0 = COPY [[PTR_ADD]](p0)212 ; CHECK-NEXT: RET_ReallyLR implicit $x0213 load volatile i8, ptr %ptr214 %offset = call i64 @get_offset()215 %next = getelementptr i8, ptr %ptr, i64 %offset216 ret ptr %next217}218 219declare void @bar(ptr)220declare i64 @get_offset()221@var = global i8 0222@varp8 = global ptr null223