• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc < %s -mtriple=x86_64-linux | FileCheck %s -check-prefix=CHECK -check-prefix=ENABLED
2; RUN: llc --disable-x86-lea-opt < %s -mtriple=x86_64-linux | FileCheck %s -check-prefix=CHECK -check-prefix=DISABLED
3
4%struct.anon1 = type { i32, i32, i32 }
5%struct.anon2 = type { i32, [32 x i32], i32 }
6
7@arr1 = external global [65 x %struct.anon1], align 16
8@arr2 = external global [65 x %struct.anon2], align 16
9
10define void @test1(i64 %x) nounwind {
11entry:
12  %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0
13  %tmp = load i32, i32* %a, align 4
14  %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1
15  %tmp1 = load i32, i32* %b, align 4
16  %sub = sub i32 %tmp, %tmp1
17  %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2
18  %tmp2 = load i32, i32* %c, align 4
19  %add = add nsw i32 %sub, %tmp2
20  switch i32 %add, label %sw.epilog [
21    i32 1, label %sw.bb.1
22    i32 2, label %sw.bb.2
23  ]
24
25sw.bb.1:                                          ; preds = %entry
26  store i32 111, i32* %b, align 4
27  store i32 222, i32* %c, align 4
28  br label %sw.epilog
29
30sw.bb.2:                                          ; preds = %entry
31  store i32 333, i32* %b, align 4
32  store i32 444, i32* %c, align 4
33  br label %sw.epilog
34
35sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
36  ret void
37; CHECK-LABEL: test1:
38; CHECK:	shlq $2, [[REG1:%[a-z]+]]
39; CHECK:	movl arr1([[REG1]],[[REG1]],2), {{.*}}
40; CHECK:	leaq arr1+4([[REG1]],[[REG1]],2), [[REG2:%[a-z]+]]
41; CHECK:	subl arr1+4([[REG1]],[[REG1]],2), {{.*}}
42; DISABLED:	leaq arr1+8([[REG1]],[[REG1]],2), [[REG3:%[a-z]+]]
43; CHECK:	addl arr1+8([[REG1]],[[REG1]],2), {{.*}}
44; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
45; ENABLED:	movl ${{[1-4]+}}, 4([[REG2]])
46; DISABLED:	movl ${{[1-4]+}}, ([[REG3]])
47; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
48; ENABLED:	movl ${{[1-4]+}}, 4([[REG2]])
49; DISABLED:	movl ${{[1-4]+}}, ([[REG3]])
50}
51
52define void @test2(i64 %x) nounwind optsize {
53entry:
54  %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0
55  %tmp = load i32, i32* %a, align 4
56  %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1
57  %tmp1 = load i32, i32* %b, align 4
58  %sub = sub i32 %tmp, %tmp1
59  %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2
60  %tmp2 = load i32, i32* %c, align 4
61  %add = add nsw i32 %sub, %tmp2
62  switch i32 %add, label %sw.epilog [
63    i32 1, label %sw.bb.1
64    i32 2, label %sw.bb.2
65  ]
66
67sw.bb.1:                                          ; preds = %entry
68  store i32 111, i32* %b, align 4
69  store i32 222, i32* %c, align 4
70  br label %sw.epilog
71
72sw.bb.2:                                          ; preds = %entry
73  store i32 333, i32* %b, align 4
74  store i32 444, i32* %c, align 4
75  br label %sw.epilog
76
77sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
78  ret void
79; CHECK-LABEL: test2:
80; CHECK:	shlq $2, [[REG1:%[a-z]+]]
81; DISABLED:	movl arr1([[REG1]],[[REG1]],2), {{.*}}
82; CHECK:	leaq arr1+4([[REG1]],[[REG1]],2), [[REG2:%[a-z]+]]
83; ENABLED:	movl -4([[REG2]]), {{.*}}
84; ENABLED:	subl ([[REG2]]), {{.*}}
85; ENABLED:	addl 4([[REG2]]), {{.*}}
86; DISABLED:	subl arr1+4([[REG1]],[[REG1]],2), {{.*}}
87; DISABLED:	leaq arr1+8([[REG1]],[[REG1]],2), [[REG3:%[a-z]+]]
88; DISABLED:	addl arr1+8([[REG1]],[[REG1]],2), {{.*}}
89; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
90; ENABLED:	movl ${{[1-4]+}}, 4([[REG2]])
91; DISABLED:	movl ${{[1-4]+}}, ([[REG3]])
92; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
93; ENABLED:	movl ${{[1-4]+}}, 4([[REG2]])
94; DISABLED:	movl ${{[1-4]+}}, ([[REG3]])
95}
96
97; Check that LEA optimization pass takes into account a resultant address
98; displacement when choosing a LEA instruction for replacing a redundant
99; address recalculation.
100
101define void @test3(i64 %x) nounwind optsize {
102entry:
103  %a = getelementptr inbounds [65 x %struct.anon2], [65 x %struct.anon2]* @arr2, i64 0, i64 %x, i32 2
104  %tmp = load i32, i32* %a, align 4
105  %b = getelementptr inbounds [65 x %struct.anon2], [65 x %struct.anon2]* @arr2, i64 0, i64 %x, i32 0
106  %tmp1 = load i32, i32* %b, align 4
107  %add = add nsw i32 %tmp, %tmp1
108  switch i32 %add, label %sw.epilog [
109    i32 1, label %sw.bb.1
110    i32 2, label %sw.bb.2
111  ]
112
113sw.bb.1:                                          ; preds = %entry
114  store i32 111, i32* %a, align 4
115  store i32 222, i32* %b, align 4
116  br label %sw.epilog
117
118sw.bb.2:                                          ; preds = %entry
119  store i32 333, i32* %a, align 4
120  ; Make sure the REG3's definition LEA won't be removed as redundant.
121  %cvt = ptrtoint i32* %b to i32
122  store i32 %cvt, i32* %b, align 4
123  br label %sw.epilog
124
125sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
126  ret void
127; CHECK-LABEL: test3:
128; CHECK:	imulq {{.*}}, [[REG1:%[a-z]+]]
129; CHECK:	leaq arr2+132([[REG1]]), [[REG2:%[a-z]+]]
130; CHECK:	leaq arr2([[REG1]]), [[REG3:%[a-z]+]]
131
132; REG3's definition is closer to movl than REG2's, but the pass still chooses
133; REG2 because it provides the resultant address displacement fitting 1 byte.
134
135; ENABLED:	movl ([[REG2]]), {{.*}}
136; ENABLED:	addl ([[REG3]]), {{.*}}
137; DISABLED:	movl arr2+132([[REG1]]), {{.*}}
138; DISABLED:	addl arr2([[REG1]]), {{.*}}
139; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
140; CHECK:	movl ${{[1-4]+}}, ([[REG3]])
141; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
142; CHECK:	movl {{.*}}, ([[REG3]])
143}
144
145define void @test4(i64 %x) nounwind minsize {
146entry:
147  %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0
148  %tmp = load i32, i32* %a, align 4
149  %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1
150  %tmp1 = load i32, i32* %b, align 4
151  %sub = sub i32 %tmp, %tmp1
152  %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2
153  %tmp2 = load i32, i32* %c, align 4
154  %add = add nsw i32 %sub, %tmp2
155  switch i32 %add, label %sw.epilog [
156    i32 1, label %sw.bb.1
157    i32 2, label %sw.bb.2
158  ]
159
160sw.bb.1:                                          ; preds = %entry
161  store i32 111, i32* %b, align 4
162  store i32 222, i32* %c, align 4
163  br label %sw.epilog
164
165sw.bb.2:                                          ; preds = %entry
166  store i32 333, i32* %b, align 4
167  store i32 444, i32* %c, align 4
168  br label %sw.epilog
169
170sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
171  ret void
172; CHECK-LABEL: test4:
173; CHECK:	imulq {{.*}}, [[REG1:%[a-z]+]]
174; DISABLED:	movl arr1([[REG1]]), {{.*}}
175; CHECK:	leaq arr1+4([[REG1]]), [[REG2:%[a-z]+]]
176; ENABLED:	movl -4([[REG2]]), {{.*}}
177; ENABLED:	subl ([[REG2]]), {{.*}}
178; ENABLED:	addl 4([[REG2]]), {{.*}}
179; DISABLED:	subl arr1+4([[REG1]]), {{.*}}
180; DISABLED:	leaq arr1+8([[REG1]]), [[REG3:%[a-z]+]]
181; DISABLED:	addl arr1+8([[REG1]]), {{.*}}
182; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
183; ENABLED:	movl ${{[1-4]+}}, 4([[REG2]])
184; DISABLED:	movl ${{[1-4]+}}, ([[REG3]])
185; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
186; ENABLED:	movl ${{[1-4]+}}, 4([[REG2]])
187; DISABLED:	movl ${{[1-4]+}}, ([[REG3]])
188}
189