1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-- -mattr=+slow-3ops-lea | FileCheck %s
3; RUN: llc < %s -mtriple=x86_64-- -mattr=-slow-3ops-lea | FileCheck %s
4
5define i16 @and_i8_zext_shl_add_i16(i16 %t0, i8 %t1) {
6; CHECK-LABEL: and_i8_zext_shl_add_i16:
7; CHECK:       # %bb.0:
8; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
9; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
10; CHECK-NEXT:    andl $8, %esi
11; CHECK-NEXT:    leal (%rdi,%rsi,4), %eax
12; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
13; CHECK-NEXT:    retq
14  %t4 = and i8 %t1, 8
15  %t5 = zext i8 %t4 to i16
16  %sh = shl i16 %t5, 2
17  %t6 = add i16 %sh, %t0
18  ret i16 %t6
19}
20
21define i16 @and_i8_shl_zext_add_i16(i16 %t0, i8 %t1) {
22; CHECK-LABEL: and_i8_shl_zext_add_i16:
23; CHECK:       # %bb.0:
24; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
25; CHECK-NEXT:    andb $8, %sil
26; CHECK-NEXT:    movzbl %sil, %eax
27; CHECK-NEXT:    leal (%rdi,%rax,4), %eax
28; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
29; CHECK-NEXT:    retq
30  %t4 = and i8 %t1, 8
31  %sh = shl i8 %t4, 2
32  %t5 = zext i8 %sh to i16
33  %t6 = add i16 %t5, %t0
34  ret i16 %t6
35}
36
37define i32 @and_i8_zext_shl_add_i32(i32 %t0, i8 %t1) {
38; CHECK-LABEL: and_i8_zext_shl_add_i32:
39; CHECK:       # %bb.0:
40; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
41; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
42; CHECK-NEXT:    andl $8, %esi
43; CHECK-NEXT:    leal (%rdi,%rsi,8), %eax
44; CHECK-NEXT:    retq
45  %t4 = and i8 %t1, 8
46  %t5 = zext i8 %t4 to i32
47  %sh = shl i32 %t5, 3
48  %t6 = add i32 %sh, %t0
49  ret i32 %t6
50}
51
52define i32 @and_i8_shl_zext_add_i32(i32 %t0, i8 %t1) {
53; CHECK-LABEL: and_i8_shl_zext_add_i32:
54; CHECK:       # %bb.0:
55; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
56; CHECK-NEXT:    andb $8, %sil
57; CHECK-NEXT:    movzbl %sil, %eax
58; CHECK-NEXT:    leal (%rdi,%rax,8), %eax
59; CHECK-NEXT:    retq
60  %t4 = and i8 %t1, 8
61  %sh = shl i8 %t4, 3
62  %t5 = zext i8 %sh to i32
63  %t6 = add i32 %t5, %t0
64  ret i32 %t6
65}
66
67define i32 @and_i16_zext_shl_add_i32(i32 %t0, i16 %t1) {
68; CHECK-LABEL: and_i16_zext_shl_add_i32:
69; CHECK:       # %bb.0:
70; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
71; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
72; CHECK-NEXT:    andl $8, %esi
73; CHECK-NEXT:    leal (%rdi,%rsi,4), %eax
74; CHECK-NEXT:    retq
75  %t4 = and i16 %t1, 8
76  %t5 = zext i16 %t4 to i32
77  %sh = shl i32 %t5, 2
78  %t6 = add i32 %sh, %t0
79  ret i32 %t6
80}
81
82define i32 @and_i16_shl_zext_add_i32(i32 %t0, i16 %t1) {
83; CHECK-LABEL: and_i16_shl_zext_add_i32:
84; CHECK:       # %bb.0:
85; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
86; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
87; CHECK-NEXT:    andl $8, %esi
88; CHECK-NEXT:    leal (%rdi,%rsi,4), %eax
89; CHECK-NEXT:    retq
90  %t4 = and i16 %t1, 8
91  %sh = shl i16 %t4, 2
92  %t5 = zext i16 %sh to i32
93  %t6 = add i32 %t5, %t0
94  ret i32 %t6
95}
96
97define i64 @and_i8_zext_shl_add_i64(i64 %t0, i8 %t1) {
98; CHECK-LABEL: and_i8_zext_shl_add_i64:
99; CHECK:       # %bb.0:
100; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
101; CHECK-NEXT:    andl $8, %esi
102; CHECK-NEXT:    leaq (%rdi,%rsi,2), %rax
103; CHECK-NEXT:    retq
104  %t4 = and i8 %t1, 8
105  %t5 = zext i8 %t4 to i64
106  %sh = shl i64 %t5, 1
107  %t6 = add i64 %sh, %t0
108  ret i64 %t6
109}
110
111define i64 @and_i8_shl_zext_add_i64(i64 %t0, i8 %t1) {
112; CHECK-LABEL: and_i8_shl_zext_add_i64:
113; CHECK:       # %bb.0:
114; CHECK-NEXT:    andb $8, %sil
115; CHECK-NEXT:    movzbl %sil, %eax
116; CHECK-NEXT:    leaq (%rdi,%rax,2), %rax
117; CHECK-NEXT:    retq
118  %t4 = and i8 %t1, 8
119  %sh = shl i8 %t4, 1
120  %t5 = zext i8 %sh to i64
121  %t6 = add i64 %t5, %t0
122  ret i64 %t6
123}
124
125define i64 @and_i32_zext_shl_add_i64(i64 %t0, i32 %t1) {
126; CHECK-LABEL: and_i32_zext_shl_add_i64:
127; CHECK:       # %bb.0:
128; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
129; CHECK-NEXT:    andl $8, %esi
130; CHECK-NEXT:    leaq (%rdi,%rsi,8), %rax
131; CHECK-NEXT:    retq
132  %t4 = and i32 %t1, 8
133  %t5 = zext i32 %t4 to i64
134  %sh = shl i64 %t5, 3
135  %t6 = add i64 %sh, %t0
136  ret i64 %t6
137}
138
139define i64 @and_i32_shl_zext_add_i64(i64 %t0, i32 %t1) {
140; CHECK-LABEL: and_i32_shl_zext_add_i64:
141; CHECK:       # %bb.0:
142; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
143; CHECK-NEXT:    andl $8, %esi
144; CHECK-NEXT:    leaq (%rdi,%rsi,8), %rax
145; CHECK-NEXT:    retq
146  %t4 = and i32 %t1, 8
147  %sh = shl i32 %t4, 3
148  %t5 = zext i32 %sh to i64
149  %t6 = add i64 %t5, %t0
150  ret i64 %t6
151}
152
153; Negative test - shift can't be converted to scale factor.
154
155define i64 @and_i32_zext_shl_add_i64_overshift(i64 %t0, i32 %t1) {
156; CHECK-LABEL: and_i32_zext_shl_add_i64_overshift:
157; CHECK:       # %bb.0:
158; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
159; CHECK-NEXT:    andl $8, %esi
160; CHECK-NEXT:    shlq $4, %rsi
161; CHECK-NEXT:    leaq (%rsi,%rdi), %rax
162; CHECK-NEXT:    retq
163  %t4 = and i32 %t1, 8
164  %t5 = zext i32 %t4 to i64
165  %sh = shl i64 %t5, 4
166  %t6 = add i64 %sh, %t0
167  ret i64 %t6
168}
169
170define i64 @and_i32_shl_zext_add_i64_overshift(i64 %t0, i32 %t1) {
171; CHECK-LABEL: and_i32_shl_zext_add_i64_overshift:
172; CHECK:       # %bb.0:
173; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
174; CHECK-NEXT:    andl $8, %esi
175; CHECK-NEXT:    shll $4, %esi
176; CHECK-NEXT:    leaq (%rsi,%rdi), %rax
177; CHECK-NEXT:    retq
178  %t4 = and i32 %t1, 8
179  %sh = shl i32 %t4, 4
180  %t5 = zext i32 %sh to i64
181  %t6 = add i64 %t5, %t0
182  ret i64 %t6
183}
184