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