xref: /llvm-project/llvm/test/Transforms/InstCombine/memcpy-addrspace.ll (revision 434a8a08a2f26bb30cb30c3f9f6794cf7a190844)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4@test.data = private unnamed_addr addrspace(2) constant [8 x i32] [i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7], align 4
5
6define void @test_load(ptr addrspace(1) %out, i64 %x) {
7; CHECK-LABEL: @test_load(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i32], ptr addrspace(2) @test.data, i64 0, i64 [[X:%.*]]
10; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr addrspace(2) [[ARRAYIDX]], align 4
11; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]]
12; CHECK-NEXT:    store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4
13; CHECK-NEXT:    ret void
14;
15entry:
16  %data = alloca [8 x i32], align 4
17  call void @llvm.memcpy.p0.p2.i64(ptr align 4 %data, ptr addrspace(2) align 4 @test.data, i64 32, i1 false)
18  %arrayidx = getelementptr inbounds [8 x i32], ptr %data, i64 0, i64 %x
19  %0 = load i32, ptr %arrayidx, align 4
20  %arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %x
21  store i32 %0, ptr addrspace(1) %arrayidx1, align 4
22  ret void
23}
24
25; Same as previous test, but with gep nusw nuw instead of inbounds.
26define void @test_load_gep_nusw_nuw(ptr addrspace(1) %out, i64 %x) {
27; CHECK-LABEL: @test_load_gep_nusw_nuw(
28; CHECK-NEXT:  entry:
29; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr nusw nuw [8 x i32], ptr addrspace(2) @test.data, i64 0, i64 [[X:%.*]]
30; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr addrspace(2) [[ARRAYIDX]], align 4
31; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr nusw nuw i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]]
32; CHECK-NEXT:    store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4
33; CHECK-NEXT:    ret void
34;
35entry:
36  %data = alloca [8 x i32], align 4
37  call void @llvm.memcpy.p0.p2.i64(ptr align 4 %data, ptr addrspace(2) align 4 @test.data, i64 32, i1 false)
38  %arrayidx = getelementptr nusw nuw [8 x i32], ptr %data, i64 0, i64 %x
39  %0 = load i32, ptr %arrayidx, align 4
40  %arrayidx1 = getelementptr nusw nuw i32, ptr addrspace(1) %out, i64 %x
41  store i32 %0, ptr addrspace(1) %arrayidx1, align 4
42  ret void
43}
44
45define void @test_load_bitcast_chain(ptr addrspace(1) %out, i64 %x) {
46; CHECK-LABEL: @test_load_bitcast_chain(
47; CHECK-NEXT:  entry:
48; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr addrspace(2) @test.data, i64 [[X:%.*]]
49; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr addrspace(2) [[ARRAYIDX]], align 4
50; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]]
51; CHECK-NEXT:    store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4
52; CHECK-NEXT:    ret void
53;
54entry:
55  %data = alloca [8 x i32], align 4
56  call void @llvm.memcpy.p0.p2.i64(ptr align 4 %data, ptr addrspace(2) align 4 @test.data, i64 32, i1 false)
57  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %x
58  %0 = load i32, ptr %arrayidx, align 4
59  %arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %x
60  store i32 %0, ptr addrspace(1) %arrayidx1, align 4
61  ret void
62}
63
64define void @test_call(ptr addrspace(1) %out, i64 %x) {
65; CHECK-LABEL: @test_call(
66; CHECK-NEXT:  entry:
67; CHECK-NEXT:    [[DATA:%.*]] = alloca [8 x i32], align 4
68; CHECK-NEXT:    call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 4 dereferenceable(32) [[DATA]], ptr addrspace(2) noundef align 4 dereferenceable(32) @test.data, i64 32, i1 false)
69; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i32], ptr [[DATA]], i64 0, i64 [[X:%.*]]
70; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @foo(ptr nonnull [[ARRAYIDX]])
71; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]]
72; CHECK-NEXT:    store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4
73; CHECK-NEXT:    ret void
74;
75entry:
76  %data = alloca [8 x i32], align 4
77  call void @llvm.memcpy.p0.p2.i64(ptr align 4 %data, ptr addrspace(2) align 4 @test.data, i64 32, i1 false)
78  %arrayidx = getelementptr inbounds [8 x i32], ptr %data, i64 0, i64 %x
79  %0 = call i32 @foo(ptr %arrayidx)
80  %arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %x
81  store i32 %0, ptr addrspace(1) %arrayidx1, align 4
82  ret void
83}
84
85define void @test_call_no_null_opt(ptr addrspace(1) %out, i64 %x) #0 {
86; CHECK-LABEL: @test_call_no_null_opt(
87; CHECK-NEXT:  entry:
88; CHECK-NEXT:    [[DATA:%.*]] = alloca [8 x i32], align 4
89; CHECK-NEXT:    call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 4 dereferenceable(32) [[DATA]], ptr addrspace(2) noundef align 4 dereferenceable(32) @test.data, i64 32, i1 false)
90; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i32], ptr [[DATA]], i64 0, i64 [[X:%.*]]
91; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @foo(ptr [[ARRAYIDX]])
92; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]]
93; CHECK-NEXT:    store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4
94; CHECK-NEXT:    ret void
95;
96entry:
97  %data = alloca [8 x i32], align 4
98  call void @llvm.memcpy.p0.p2.i64(ptr align 4 %data, ptr addrspace(2) align 4 @test.data, i64 32, i1 false)
99  %arrayidx = getelementptr inbounds [8 x i32], ptr %data, i64 0, i64 %x
100  %0 = call i32 @foo(ptr %arrayidx)
101  %arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %x
102  store i32 %0, ptr addrspace(1) %arrayidx1, align 4
103  ret void
104}
105
106define void @test_load_and_call(ptr addrspace(1) %out, i64 %x, i64 %y) {
107; CHECK-LABEL: @test_load_and_call(
108; CHECK-NEXT:  entry:
109; CHECK-NEXT:    [[DATA:%.*]] = alloca [8 x i32], align 4
110; CHECK-NEXT:    call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 4 dereferenceable(32) [[DATA]], ptr addrspace(2) noundef align 4 dereferenceable(32) @test.data, i64 32, i1 false)
111; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i32], ptr [[DATA]], i64 0, i64 [[X:%.*]]
112; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
113; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]]
114; CHECK-NEXT:    store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4
115; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @foo(ptr nonnull [[ARRAYIDX]])
116; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT]], i64 [[Y:%.*]]
117; CHECK-NEXT:    store i32 [[TMP1]], ptr addrspace(1) [[ARRAYIDX2]], align 4
118; CHECK-NEXT:    ret void
119;
120entry:
121  %data = alloca [8 x i32], align 4
122  call void @llvm.memcpy.p0.p2.i64(ptr align 4 %data, ptr addrspace(2) align 4 @test.data, i64 32, i1 false)
123  %arrayidx = getelementptr inbounds [8 x i32], ptr %data, i64 0, i64 %x
124  %0 = load i32, ptr %arrayidx, align 4
125  %arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %x
126  store i32 %0, ptr addrspace(1) %arrayidx1, align 4
127  %1 = call i32 @foo(ptr %arrayidx)
128  %arrayidx2 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %y
129  store i32 %1, ptr addrspace(1) %arrayidx2, align 4
130  ret void
131}
132
133define void @test_load_and_call_no_null_opt(ptr addrspace(1) %out, i64 %x, i64 %y) #0 {
134; CHECK-LABEL: @test_load_and_call_no_null_opt(
135; CHECK-NEXT:  entry:
136; CHECK-NEXT:    [[DATA:%.*]] = alloca [8 x i32], align 4
137; CHECK-NEXT:    call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 4 dereferenceable(32) [[DATA]], ptr addrspace(2) noundef align 4 dereferenceable(32) @test.data, i64 32, i1 false)
138; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i32], ptr [[DATA]], i64 0, i64 [[X:%.*]]
139; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
140; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]]
141; CHECK-NEXT:    store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4
142; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @foo(ptr [[ARRAYIDX]])
143; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT]], i64 [[Y:%.*]]
144; CHECK-NEXT:    store i32 [[TMP1]], ptr addrspace(1) [[ARRAYIDX2]], align 4
145; CHECK-NEXT:    ret void
146;
147entry:
148  %data = alloca [8 x i32], align 4
149  call void @llvm.memcpy.p0.p2.i64(ptr align 4 %data, ptr addrspace(2) align 4 @test.data, i64 32, i1 false)
150  %arrayidx = getelementptr inbounds [8 x i32], ptr %data, i64 0, i64 %x
151  %0 = load i32, ptr %arrayidx, align 4
152  %arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %x
153  store i32 %0, ptr addrspace(1) %arrayidx1, align 4
154  %1 = call i32 @foo(ptr %arrayidx)
155  %arrayidx2 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %y
156  store i32 %1, ptr addrspace(1) %arrayidx2, align 4
157  ret void
158}
159
160declare void @llvm.memcpy.p0.p2.i64(ptr nocapture writeonly, ptr addrspace(2) nocapture readonly, i64, i1)
161declare i32 @foo(ptr %x)
162
163attributes #0 = { null_pointer_is_valid }
164