[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / CodeGen / AArch64 / GlobalISel / combiner-load-store-indexing.ll
blob8f0b3b2dcf6a51164ad5afd9a845be1ea817a55f
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
2 ; RUN: llc -debugify-and-strip-all-safe -mtriple=arm64-apple-ios -global-isel -global-isel-abort=1 -verify-machineinstrs -stop-after=aarch64-prelegalizer-combiner -force-legal-indexing %s -o - | FileCheck %s
4 define i8* @test_simple_load_pre(i8* %ptr) {
5 ; CHECK-LABEL: name: test_simple_load_pre
6 ; CHECK: [[BASE:%.*]]:_(p0) = COPY $x0
7 ; CHECK: [[OFFSET:%.*]]:_(s64) = G_CONSTANT i64 42
8 ; CHECK-NOT: G_PTR_ADD
9 ; CHECK: {{%.*}}:_(s8), [[NEXT:%.*]]:_(p0) = G_INDEXED_LOAD [[BASE]], [[OFFSET]](s64), 1
10 ; CHECK: $x0 = COPY [[NEXT]](p0)
12   %next = getelementptr i8, i8* %ptr, i32 42
13   load volatile i8, i8* %next
14   ret i8* %next
17 define i8* @test_unused_load_pre(i8* %ptr) {
18 ; CHECK-LABEL: name: test_unused_load_pre
19 ; CHECK-NOT: G_INDEXED_LOAD
21   %next = getelementptr i8, i8* %ptr, i32 42
22   load volatile i8, i8* %next
23   ret i8* null
26 define void @test_load_multiple_dominated(i8* %ptr, i1 %tst, i1 %tst2) {
27 ; CHECK-LABEL: name: test_load_multiple_dominated
28 ; CHECK: [[BASE:%.*]]:_(p0) = COPY $x0
29 ; CHECK: [[OFFSET:%.*]]:_(s64) = G_CONSTANT i64 42
30 ; CHECK-NOT: G_PTR_ADD
31 ; CHECK: {{%.*}}:_(s8), [[NEXT:%.*]]:_(p0) = G_INDEXED_LOAD [[BASE]], [[OFFSET]](s64), 1
32 ; CHECK: $x0 = COPY [[NEXT]](p0)
33   %next = getelementptr i8, i8* %ptr, i32 42
34   br i1 %tst, label %do_load, label %end
36 do_load:
37   load volatile i8, i8* %next
38   br i1 %tst2, label %bb1, label %bb2
40 bb1:
41   store volatile i8* %next, i8** undef
42   ret void
44 bb2:
45   call void @bar(i8* %next)
46   ret void
48 end:
49   ret void
52 define i8* @test_simple_store_pre(i8* %ptr) {
53 ; CHECK-LABEL: name: test_simple_store_pre
54 ; CHECK: [[BASE:%.*]]:_(p0) = COPY $x0
55 ; CHECK: [[VAL:%.*]]:_(s8) = G_CONSTANT i8 0
56 ; CHECK: [[OFFSET:%.*]]:_(s64) = G_CONSTANT i64 42
57 ; CHECK-NOT: G_PTR_ADD
58 ; CHECK: [[NEXT:%.*]]:_(p0) = G_INDEXED_STORE [[VAL]](s8), [[BASE]], [[OFFSET]](s64), 1
59 ; CHECK: $x0 = COPY [[NEXT]](p0)
61   %next = getelementptr i8, i8* %ptr, i32 42
62   store volatile i8 0, i8* %next
63   ret i8* %next
66 ; The potentially pre-indexed address is used as the value stored. Converting
67 ; would produce the value too late but only by one instruction.
68 define i64** @test_store_pre_val_loop(i64** %ptr) {
69 ; CHECK-LABEL: name: test_store_pre_val_loop
70 ; CHECK: G_PTR_ADD
71 ; CHECK: G_STORE %
73   %next = getelementptr i64*, i64** %ptr, i32 42
74   %next.p0 = bitcast i64** %next to i64*
75   store volatile i64* %next.p0, i64** %next
76   ret i64** %next
79 ; Potentially pre-indexed address is used between GEP computing it and load.
80 define i8* @test_load_pre_before(i8* %ptr) {
81 ; CHECK-LABEL: name: test_load_pre_before
82 ; CHECK: G_PTR_ADD
83 ; CHECK: BL @bar
84 ; CHECK: G_LOAD %
86   %next = getelementptr i8, i8* %ptr, i32 42
87   call void @bar(i8* %next)
88   load volatile i8, i8* %next
89   ret i8* %next
92 ; Materializing the base into a writable register (from sp/fp) would be just as
93 ; bad as the original GEP.
94 define i8* @test_alloca_load_pre() {
95 ; CHECK-LABEL: name: test_alloca_load_pre
96 ; CHECK: G_PTR_ADD
97 ; CHECK: G_LOAD %
99   %ptr = alloca i8, i32 128
100   %next = getelementptr i8, i8* %ptr, i32 42
101   load volatile i8, i8* %next
102   ret i8* %next
105 ; Load does not dominate use of its address. No indexing.
106 define i8* @test_pre_nodom(i8* %in, i1 %tst) {
107 ; CHECK-LABEL: name: test_pre_nodom
108 ; CHECK: G_PTR_ADD
109 ; CHECK: G_LOAD %
111   %next = getelementptr i8, i8* %in, i32 16
112   br i1 %tst, label %do_indexed, label %use_addr
114 do_indexed:
115   %val = load i8, i8* %next
116   store i8 %val, i8* @var
117   store i8* %next, i8** @varp8
118   br label %use_addr
120 use_addr:
121   ret i8* %next
124 define i8* @test_simple_load_post(i8* %ptr) {
125 ; CHECK-LABEL: name: test_simple_load_post
126 ; CHECK: [[BASE:%.*]]:_(p0) = COPY $x0
127 ; CHECK: [[OFFSET:%.*]]:_(s64) = G_CONSTANT i64 42
128 ; CHECK-NOT: G_PTR_ADD
129 ; CHECK: {{%.*}}:_(s8), [[NEXT:%.*]]:_(p0) = G_INDEXED_LOAD [[BASE]], [[OFFSET]](s64), 0
130 ; CHECK: $x0 = COPY [[NEXT]](p0)
132   %next = getelementptr i8, i8* %ptr, i32 42
133   load volatile i8, i8* %ptr
134   ret i8* %next
137 define i8* @test_simple_load_post_gep_after(i8* %ptr) {
138 ; CHECK-LABEL: name: test_simple_load_post_gep_after
139 ; CHECK: [[BASE:%.*]]:_(p0) = COPY $x0
140 ; CHECK: BL @get_offset
141 ; CHECK: [[OFFSET:%.*]]:_(s64) = COPY $x0
142 ; CHECK: {{%.*}}:_(s8), [[ADDR:%.*]]:_(p0) = G_INDEXED_LOAD [[BASE]], [[OFFSET]](s64), 0
143 ; CHECK: $x0 = COPY [[ADDR]](p0)
145   %offset = call i64 @get_offset()
146   load volatile i8, i8* %ptr
147   %next = getelementptr i8, i8* %ptr, i64 %offset
148   ret i8* %next
151 define i8* @test_load_post_keep_looking(i8* %ptr) {
152 ; CHECK: name: test_load_post_keep_looking
153 ; CHECK: G_INDEXED_LOAD
155   %offset = call i64 @get_offset()
156   load volatile i8, i8* %ptr
157   %intval = ptrtoint i8* %ptr to i8
158   store i8 %intval, i8* @var
160   %next = getelementptr i8, i8* %ptr, i64 %offset
161   ret i8* %next
164 ; Base is frame index. Using indexing would need copy anyway.
165 define i8* @test_load_post_alloca() {
166 ; CHECK-LABEL: name: test_load_post_alloca
167 ; CHECK: G_PTR_ADD
168 ; CHECK: G_LOAD %
170   %ptr = alloca i8, i32 128
171   %next = getelementptr i8, i8* %ptr, i32 42
172   load volatile i8, i8* %ptr
173   ret i8* %next
176 ; Offset computation does not dominate the load we might be indexing.
177 define i8* @test_load_post_gep_offset_after(i8* %ptr) {
178 ; CHECK-LABEL: name: test_load_post_gep_offset_after
179 ; CHECK: G_LOAD %
180 ; CHECK: BL @get_offset
181 ; CHECK: G_PTR_ADD
183   load volatile i8, i8* %ptr
184   %offset = call i64 @get_offset()
185   %next = getelementptr i8, i8* %ptr, i64 %offset
186   ret i8* %next
189 declare void @bar(i8*)
190 declare i64 @get_offset()
191 @var = global i8 0
192 @varp8 = global i8* null