1 ; RUN: llc < %s -mtriple=x86_64-linux -enable-x86-lea-opt | FileCheck %s
3 %struct.anon1 = type { i32, i32, i32 }
4 %struct.anon2 = type { i32, [32 x i32], i32 }
6 @arr1 = external global [65 x %struct.anon1], align 16
7 @arr2 = external global [65 x %struct.anon2], align 16
9 define void @test1(i64 %x) nounwind {
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 [
24 sw.bb.1: ; preds = %entry
25 store i32 111, i32* %b, align 4
26 store i32 222, i32* %c, align 4
29 sw.bb.2: ; preds = %entry
30 store i32 333, i32* %b, align 4
31 store i32 444, i32* %c, align 4
34 sw.epilog: ; preds = %sw.bb.2, %sw.bb.1, %entry
37 ; CHECK: leaq (%rdi,%rdi,2), [[REG1:%[a-z]+]]
38 ; CHECK: movl arr1(,[[REG1]],4), {{.*}}
39 ; CHECK: leaq arr1+4(,[[REG1]],4), [[REG2:%[a-z]+]]
40 ; CHECK: subl arr1+4(,[[REG1]],4), {{.*}}
41 ; CHECK: leaq arr1+8(,[[REG1]],4), [[REG3:%[a-z]+]]
42 ; CHECK: addl arr1+8(,[[REG1]],4), {{.*}}
43 ; CHECK: movl ${{[1-4]+}}, ([[REG2]])
44 ; CHECK: movl ${{[1-4]+}}, ([[REG3]])
45 ; CHECK: movl ${{[1-4]+}}, ([[REG2]])
46 ; CHECK: movl ${{[1-4]+}}, ([[REG3]])
49 define void @test2(i64 %x) nounwind optsize {
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 [
64 sw.bb.1: ; preds = %entry
65 store i32 111, i32* %b, align 4
66 store i32 222, i32* %c, align 4
69 sw.bb.2: ; preds = %entry
70 store i32 333, i32* %b, align 4
71 store i32 444, i32* %c, align 4
74 sw.epilog: ; preds = %sw.bb.2, %sw.bb.1, %entry
77 ; CHECK: leaq (%rdi,%rdi,2), [[REG1:%[a-z]+]]
78 ; CHECK: leaq arr1+4(,[[REG1]],4), [[REG2:%[a-z]+]]
79 ; CHECK: movl -4([[REG2]]), {{.*}}
80 ; CHECK: subl ([[REG2]]), {{.*}}
81 ; CHECK: leaq arr1+8(,[[REG1]],4), [[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]])
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.
93 define void @test3(i64 %x) nounwind optsize {
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
105 sw.bb.1: ; preds = %entry
106 store i32 111, i32* %a, align 4
107 store i32 222, i32* %b, align 4
110 sw.bb.2: ; preds = %entry
111 store i32 333, i32* %a, align 4
112 store i32 444, i32* %b, align 4
115 sw.epilog: ; preds = %sw.bb.2, %sw.bb.1, %entry
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]+]]
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.
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]])