• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; This file checks support for address mode optimization.
2
3; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 \
4; RUN:   -allow-externally-defined-symbols | FileCheck %s
5; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 -mattr=sse4.1 \
6; RUN:   -allow-externally-defined-symbols | FileCheck --check-prefix=SSE41 %s
7
8define internal float @load_arg_plus_200000(float* %arg) {
9entry:
10  %arg.int = ptrtoint float* %arg to i32
11  %addr.int = add i32 %arg.int, 200000
12  %addr.ptr = inttoptr i32 %addr.int to float*
13  %addr.load = load float, float* %addr.ptr, align 4
14  ret float %addr.load
15; CHECK-LABEL: load_arg_plus_200000
16; CHECK: movss xmm0,DWORD PTR [eax+0x30d40]
17}
18
19define internal float @load_200000_plus_arg(float* %arg) {
20entry:
21  %arg.int = ptrtoint float* %arg to i32
22  %addr.int = add i32 200000, %arg.int
23  %addr.ptr = inttoptr i32 %addr.int to float*
24  %addr.load = load float, float* %addr.ptr, align 4
25  ret float %addr.load
26; CHECK-LABEL: load_200000_plus_arg
27; CHECK: movss xmm0,DWORD PTR [eax+0x30d40]
28}
29
30define internal float @load_arg_minus_200000(float* %arg) {
31entry:
32  %arg.int = ptrtoint float* %arg to i32
33  %addr.int = sub i32 %arg.int, 200000
34  %addr.ptr = inttoptr i32 %addr.int to float*
35  %addr.load = load float, float* %addr.ptr, align 4
36  ret float %addr.load
37; CHECK-LABEL: load_arg_minus_200000
38; CHECK: movss xmm0,DWORD PTR [eax-0x30d40]
39}
40
41define internal float @load_200000_minus_arg(float* %arg) {
42entry:
43  %arg.int = ptrtoint float* %arg to i32
44  %addr.int = sub i32 200000, %arg.int
45  %addr.ptr = inttoptr i32 %addr.int to float*
46  %addr.load = load float, float* %addr.ptr, align 4
47  ret float %addr.load
48; CHECK-LABEL: load_200000_minus_arg
49; CHECK: movss xmm0,DWORD PTR [e{{..}}]
50}
51
52define internal <8 x i16> @load_mul_v8i16_mem(<8 x i16> %arg0, i32 %arg1_iptr) {
53entry:
54  %addr_sub = sub i32 %arg1_iptr, 200000
55  %addr_ptr = inttoptr i32 %addr_sub to <8 x i16>*
56  %arg1 = load <8 x i16>, <8 x i16>* %addr_ptr, align 2
57  %res_vec = mul <8 x i16> %arg0, %arg1
58  ret <8 x i16> %res_vec
59; Address mode optimization is generally unsafe for SSE vector instructions.
60; CHECK-LABEL: load_mul_v8i16_mem
61; CHECK-NOT: pmullw xmm{{.*}},XMMWORD PTR [e{{..}}-0x30d40]
62}
63
64define internal <4 x i32> @load_mul_v4i32_mem(<4 x i32> %arg0, i32 %arg1_iptr) {
65entry:
66  %addr_sub = sub i32 %arg1_iptr, 200000
67  %addr_ptr = inttoptr i32 %addr_sub to <4 x i32>*
68  %arg1 = load <4 x i32>, <4 x i32>* %addr_ptr, align 4
69  %res = mul <4 x i32> %arg0, %arg1
70  ret <4 x i32> %res
71; Address mode optimization is generally unsafe for SSE vector instructions.
72; CHECK-LABEL: load_mul_v4i32_mem
73; CHECK-NOT: pmuludq xmm{{.*}},XMMWORD PTR [e{{..}}-0x30d40]
74; CHECK: pmuludq
75;
76; SSE41-LABEL: load_mul_v4i32_mem
77; SSE41-NOT: pmulld xmm{{.*}},XMMWORD PTR [e{{..}}-0x30d40]
78}
79
80define internal float @address_mode_opt_chaining(float* %arg) {
81entry:
82  %arg.int = ptrtoint float* %arg to i32
83  %addr1.int = add i32 12, %arg.int
84  %addr2.int = sub i32 %addr1.int, 4
85  %addr2.ptr = inttoptr i32 %addr2.int to float*
86  %addr2.load = load float, float* %addr2.ptr, align 4
87  ret float %addr2.load
88; CHECK-LABEL: address_mode_opt_chaining
89; CHECK: movss xmm0,DWORD PTR [eax+0x8]
90}
91
92define internal float @address_mode_opt_chaining_overflow(float* %arg) {
93entry:
94  %arg.int = ptrtoint float* %arg to i32
95  %addr1.int = add i32 2147483640, %arg.int
96  %addr2.int = add i32 %addr1.int, 2147483643
97  %addr2.ptr = inttoptr i32 %addr2.int to float*
98  %addr2.load = load float, float* %addr2.ptr, align 4
99  ret float %addr2.load
100; CHECK-LABEL: address_mode_opt_chaining_overflow
101; CHECK: 0x7ffffff8
102; CHECK: movss xmm0,DWORD PTR [{{.*}}+0x7ffffffb]
103}
104
105define internal float @address_mode_opt_chaining_overflow_sub(float* %arg) {
106entry:
107  %arg.int = ptrtoint float* %arg to i32
108  %addr1.int = sub i32 %arg.int, 2147483640
109  %addr2.int = sub i32 %addr1.int, 2147483643
110  %addr2.ptr = inttoptr i32 %addr2.int to float*
111  %addr2.load = load float, float* %addr2.ptr, align 4
112  ret float %addr2.load
113; CHECK-LABEL: address_mode_opt_chaining_overflow_sub
114; CHECK: 0x7ffffff8
115; CHECK: movss xmm0,DWORD PTR [{{.*}}-0x7ffffffb]
116}
117
118define internal float @address_mode_opt_chaining_no_overflow(float* %arg) {
119entry:
120  %arg.int = ptrtoint float* %arg to i32
121  %addr1.int = sub i32 %arg.int, 2147483640
122  %addr2.int = add i32 %addr1.int, 2147483643
123  %addr2.ptr = inttoptr i32 %addr2.int to float*
124  %addr2.load = load float, float* %addr2.ptr, align 4
125  ret float %addr2.load
126; CHECK-LABEL: address_mode_opt_chaining_no_overflow
127; CHECK: movss xmm0,DWORD PTR [{{.*}}+0x3]
128}
129
130define internal float @address_mode_opt_add_pos_min_int(float* %arg) {
131entry:
132  %arg.int = ptrtoint float* %arg to i32
133  %addr1.int = add i32 %arg.int, 2147483648
134  %addr1.ptr = inttoptr i32 %addr1.int to float*
135  %addr1.load = load float, float* %addr1.ptr, align 4
136  ret float %addr1.load
137; CHECK-LABEL: address_mode_opt_add_pos_min_int
138; CHECK: movss xmm0,DWORD PTR [{{.*}}-0x80000000]
139}
140
141define internal float @address_mode_opt_sub_min_int(float* %arg) {
142entry:
143  %arg.int = ptrtoint float* %arg to i32
144  %addr1.int = sub i32 %arg.int, 2147483648
145  %addr1.ptr = inttoptr i32 %addr1.int to float*
146  %addr1.load = load float, float* %addr1.ptr, align 4
147  ret float %addr1.load
148; CHECK-LABEL: address_mode_opt_sub_min_int
149; CHECK: movss xmm0,DWORD PTR [{{.*}}-0x80000000]
150}
151
152define internal float @load_1_or__2_shl_arg(float* %arg) {
153entry:
154  %arg.int = ptrtoint float* %arg to i32
155  %shl1 = shl i32 %arg.int, 2
156  %addr.int = or i32 1, %shl1
157  %addr.ptr = inttoptr i32 %addr.int to float*
158  %addr.load = load float, float* %addr.ptr, align 4
159  ret float %addr.load
160; CHECK-LABEL: load_1_or__2_shl_arg
161; CHECK-NOT: or
162; CHECK: movss xmm{{[0-9]+}},DWORD PTR [{{e..}}*4+0x1]
163}
164
165define internal float @or_add_boundary_check_1(float* %arg) {
166entry:
167  %arg.int = ptrtoint float* %arg to i32
168  %shl1 = shl i32 %arg.int, 2
169  %addr.int = or i32 5, %shl1
170  %addr.ptr = inttoptr i32 %addr.int to float*
171  %addr.load = load float, float* %addr.ptr, align 4
172  ret float %addr.load
173; CHECK-LABEL: or_add_boundary_check_1
174; CHECK: or
175; CHECK-NOT: movss xmm{{[0-9]+}},DWORD PTR [{{e..}}*4+0x5]
176}
177
178define internal float @or_add_boundary_check_2(float* %arg) {
179entry:
180  %arg.int = ptrtoint float* %arg to i32
181  %shl1 = shl i32 %arg.int, 2
182  %addr.int = or i32 -1, %shl1
183  %addr.ptr = inttoptr i32 %addr.int to float*
184  %addr.load = load float, float* %addr.ptr, align 4
185  ret float %addr.load
186; CHECK-LABEL: or_add_boundary_check_2
187; CHECK: or
188; CHECK-NOT: movss xmm{{[0-9]+}},DWORD PTR [{{e..}}*4+0xFFFF]
189}
190
191define internal void @invert_icmp(i32* %arg1, i32* %arg2) {
192entry:
193  %addr.other = load i32, i32* %arg2, align 1
194  br label %next
195next:
196  %addr.load = load i32, i32* %arg1, align 1
197  %cond = icmp slt i32 %addr.load, %addr.other
198  br i1 %cond, label %if.then, label %if.else
199if.then:
200  ret void
201if.else:
202  ret void
203; CHECK-LABEL: invert_icmp
204; CHECK: cmp {{e..}},DWORD PTR [{{e..}}]
205; CHECK: jle
206}