[MIParser] Set RegClassOrRegBank during instruction parsing
[llvm-complete.git] / test / CodeGen / AArch64 / GlobalISel / combiner-load-store-indexing.ll
blobdd26cbdc3f629f22fa46a3371f7f196e837024d7
1 ; RUN: llc -mtriple=arm64-apple-ios -global-isel -global-isel-abort=1 -verify-machineinstrs -stop-after=aarch64-prelegalizer-combiner -force-legal-indexing %s -o - | FileCheck %s
3 define i8* @test_simple_load_pre(i8* %ptr) {
4 ; CHECK-LABEL: name: test_simple_load_pre
5 ; CHECK: [[BASE:%.*]]:_(p0) = COPY $x0
6 ; CHECK: [[OFFSET:%.*]]:_(s64) = G_CONSTANT i64 42
7 ; CHECK-NOT: G_GEP
8 ; CHECK: {{%.*}}:_(s8), [[NEXT:%.*]]:_(p0) = G_INDEXED_LOAD [[BASE]], [[OFFSET]](s64), 1
9 ; CHECK: $x0 = COPY [[NEXT]](p0)
11   %next = getelementptr i8, i8* %ptr, i32 42
12   load volatile i8, i8* %next
13   ret i8* %next
16 define void @test_load_multiple_dominated(i8* %ptr, i1 %tst, i1 %tst2) {
17 ; CHECK-LABEL: name: test_load_multiple_dominated
18 ; CHECK: [[BASE:%.*]]:_(p0) = COPY $x0
19 ; CHECK: [[OFFSET:%.*]]:_(s64) = G_CONSTANT i64 42
20 ; CHECK-NOT: G_GEP
21 ; CHECK: {{%.*}}:_(s8), [[NEXT:%.*]]:_(p0) = G_INDEXED_LOAD [[BASE]], [[OFFSET]](s64), 1
22 ; CHECK: $x0 = COPY [[NEXT]](p0)
23   %next = getelementptr i8, i8* %ptr, i32 42
24   br i1 %tst, label %do_load, label %end
26 do_load:
27   load volatile i8, i8* %next
28   br i1 %tst2, label %bb1, label %bb2
30 bb1:
31   store volatile i8* %next, i8** undef
32   ret void
34 bb2:
35   call void @bar(i8* %next)
36   ret void
38 end:
39   ret void
42 define i8* @test_simple_store_pre(i8* %ptr) {
43 ; CHECK-LABEL: name: test_simple_store_pre
44 ; CHECK: [[BASE:%.*]]:_(p0) = COPY $x0
45 ; CHECK: [[VAL:%.*]]:_(s8) = G_CONSTANT i8 0
46 ; CHECK: [[OFFSET:%.*]]:_(s64) = G_CONSTANT i64 42
47 ; CHECK-NOT: G_GEP
48 ; CHECK: [[NEXT:%.*]]:_(p0) = G_INDEXED_STORE [[VAL]](s8), [[BASE]], [[OFFSET]](s64), 1
49 ; CHECK: $x0 = COPY [[NEXT]](p0)
51   %next = getelementptr i8, i8* %ptr, i32 42
52   store volatile i8 0, i8* %next
53   ret i8* %next
56 ; The potentially pre-indexed address is used as the value stored. Converting
57 ; would produce the value too late but only by one instruction.
58 define i64** @test_store_pre_val_loop(i64** %ptr) {
59 ; CHECK-LABEL: name: test_store_pre_val_loop
60 ; CHECK: G_GEP
61 ; CHECK: G_STORE %
63   %next = getelementptr i64*, i64** %ptr, i32 42
64   %next.p0 = bitcast i64** %next to i64*
65   store volatile i64* %next.p0, i64** %next
66   ret i64** %next
69 ; Potentially pre-indexed address is used between GEP computing it and load.
70 define i8* @test_load_pre_before(i8* %ptr) {
71 ; CHECK-LABEL: name: test_load_pre_before
72 ; CHECK: G_GEP
73 ; CHECK: BL @bar
74 ; CHECK: G_LOAD %
76   %next = getelementptr i8, i8* %ptr, i32 42
77   call void @bar(i8* %next)
78   load volatile i8, i8* %next
79   ret i8* %next
82 ; Materializing the base into a writable register (from sp/fp) would be just as
83 ; bad as the original GEP.
84 define i8* @test_alloca_load_pre() {
85 ; CHECK-LABEL: name: test_alloca_load_pre
86 ; CHECK: G_GEP
87 ; CHECK: G_LOAD %
89   %ptr = alloca i8, i32 128
90   %next = getelementptr i8, i8* %ptr, i32 42
91   load volatile i8, i8* %next
92   ret i8* %next
95 ; Load does not dominate use of its address. No indexing.
96 define i8* @test_pre_nodom(i8* %in, i1 %tst) {
97 ; CHECK-LABEL: name: test_pre_nodom
98 ; CHECK: G_GEP
99 ; CHECK: G_LOAD %
101   %next = getelementptr i8, i8* %in, i32 16
102   br i1 %tst, label %do_indexed, label %use_addr
104 do_indexed:
105   %val = load i8, i8* %next
106   store i8 %val, i8* @var
107   store i8* %next, i8** @varp8
108   br label %use_addr
110 use_addr:
111   ret i8* %next
114 define i8* @test_simple_load_post(i8* %ptr) {
115 ; CHECK-LABEL: name: test_simple_load_post
116 ; CHECK: [[BASE:%.*]]:_(p0) = COPY $x0
117 ; CHECK: [[OFFSET:%.*]]:_(s64) = G_CONSTANT i64 42
118 ; CHECK-NOT: G_GEP
119 ; CHECK: {{%.*}}:_(s8), [[NEXT:%.*]]:_(p0) = G_INDEXED_LOAD [[BASE]], [[OFFSET]](s64), 0
120 ; CHECK: $x0 = COPY [[NEXT]](p0)
122   %next = getelementptr i8, i8* %ptr, i32 42
123   load volatile i8, i8* %ptr
124   ret i8* %next
127 define i8* @test_simple_load_post_gep_after(i8* %ptr) {
128 ; CHECK-LABEL: name: test_simple_load_post_gep_after
129 ; CHECK: [[BASE:%.*]]:_(p0) = COPY $x0
130 ; CHECK: BL @get_offset
131 ; CHECK: [[OFFSET:%.*]]:_(s64) = COPY $x0
132 ; CHECK: {{%.*}}:_(s8), [[ADDR:%.*]]:_(p0) = G_INDEXED_LOAD [[BASE]], [[OFFSET]](s64), 0
133 ; CHECK: $x0 = COPY [[ADDR]](p0)
135   %offset = call i64 @get_offset()
136   load volatile i8, i8* %ptr
137   %next = getelementptr i8, i8* %ptr, i64 %offset
138   ret i8* %next
141 define i8* @test_load_post_keep_looking(i8* %ptr) {
142 ; CHECK: name: test_load_post_keep_looking
143 ; CHECK: G_INDEXED_LOAD
145   %offset = call i64 @get_offset()
146   load volatile i8, i8* %ptr
147   %intval = ptrtoint i8* %ptr to i8
148   store i8 %intval, i8* @var
150   %next = getelementptr i8, i8* %ptr, i64 %offset
151   ret i8* %next
154 ; Base is frame index. Using indexing would need copy anyway.
155 define i8* @test_load_post_alloca() {
156 ; CHECK-LABEL: name: test_load_post_alloca
157 ; CHECK: G_GEP
158 ; CHECK: G_LOAD %
160   %ptr = alloca i8, i32 128
161   %next = getelementptr i8, i8* %ptr, i32 42
162   load volatile i8, i8* %ptr
163   ret i8* %next
166 ; Offset computation does not dominate the load we might be indexing.
167 define i8* @test_load_post_gep_offset_after(i8* %ptr) {
168 ; CHECK-LABEL: name: test_load_post_gep_offset_after
169 ; CHECK: G_LOAD %
170 ; CHECK: BL @get_offset
171 ; CHECK: G_GEP
173   load volatile i8, i8* %ptr
174   %offset = call i64 @get_offset()
175   %next = getelementptr i8, i8* %ptr, i64 %offset
176   ret i8* %next
179 declare void @bar(i8*)
180 declare i64 @get_offset()
181 @var = global i8 0
182 @varp8 = global i8* null