1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-linux | FileCheck %s -check-prefix=CHECK -check-prefix=ENABLED
3; RUN: llc --disable-x86-lea-opt < %s -mtriple=x86_64-linux | FileCheck %s -check-prefix=CHECK -check-prefix=DISABLED
4
5%struct.anon1 = type { i32, i32, i32 }
6%struct.anon2 = type { i32, [32 x i32], i32 }
7
8@arr1 = external dso_local global [65 x %struct.anon1], align 16
9@arr2 = external dso_local global [65 x %struct.anon2], align 16
10
11define void @test1(i64 %x) nounwind {
12; ENABLED-LABEL: test1:
13; ENABLED:       # %bb.0: # %entry
14; ENABLED-NEXT:    shlq $2, %rdi
15; ENABLED-NEXT:    movl arr1(%rdi,%rdi,2), %ecx
16; ENABLED-NEXT:    leaq arr1+4(%rdi,%rdi,2), %rax
17; ENABLED-NEXT:    subl arr1+4(%rdi,%rdi,2), %ecx
18; ENABLED-NEXT:    addl arr1+8(%rdi,%rdi,2), %ecx
19; ENABLED-NEXT:    cmpl $2, %ecx
20; ENABLED-NEXT:    je .LBB0_3
21; ENABLED-NEXT:  # %bb.1: # %entry
22; ENABLED-NEXT:    cmpl $1, %ecx
23; ENABLED-NEXT:    jne .LBB0_4
24; ENABLED-NEXT:  # %bb.2: # %sw.bb.1
25; ENABLED-NEXT:    movl $111, (%rax)
26; ENABLED-NEXT:    movl $222, 4(%rax)
27; ENABLED-NEXT:    retq
28; ENABLED-NEXT:  .LBB0_3: # %sw.bb.2
29; ENABLED-NEXT:    movl $333, (%rax) # imm = 0x14D
30; ENABLED-NEXT:    movl $444, 4(%rax) # imm = 0x1BC
31; ENABLED-NEXT:  .LBB0_4: # %sw.epilog
32; ENABLED-NEXT:    retq
33;
34; DISABLED-LABEL: test1:
35; DISABLED:       # %bb.0: # %entry
36; DISABLED-NEXT:    shlq $2, %rdi
37; DISABLED-NEXT:    movl arr1(%rdi,%rdi,2), %edx
38; DISABLED-NEXT:    leaq arr1+4(%rdi,%rdi,2), %rax
39; DISABLED-NEXT:    subl arr1+4(%rdi,%rdi,2), %edx
40; DISABLED-NEXT:    leaq arr1+8(%rdi,%rdi,2), %rcx
41; DISABLED-NEXT:    addl arr1+8(%rdi,%rdi,2), %edx
42; DISABLED-NEXT:    cmpl $2, %edx
43; DISABLED-NEXT:    je .LBB0_3
44; DISABLED-NEXT:  # %bb.1: # %entry
45; DISABLED-NEXT:    cmpl $1, %edx
46; DISABLED-NEXT:    jne .LBB0_4
47; DISABLED-NEXT:  # %bb.2: # %sw.bb.1
48; DISABLED-NEXT:    movl $111, (%rax)
49; DISABLED-NEXT:    movl $222, (%rcx)
50; DISABLED-NEXT:    retq
51; DISABLED-NEXT:  .LBB0_3: # %sw.bb.2
52; DISABLED-NEXT:    movl $333, (%rax) # imm = 0x14D
53; DISABLED-NEXT:    movl $444, (%rcx) # imm = 0x1BC
54; DISABLED-NEXT:  .LBB0_4: # %sw.epilog
55; DISABLED-NEXT:    retq
56entry:
57  %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0
58  %tmp = load i32, i32* %a, align 4
59  %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1
60  %tmp1 = load i32, i32* %b, align 4
61  %sub = sub i32 %tmp, %tmp1
62  %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2
63  %tmp2 = load i32, i32* %c, align 4
64  %add = add nsw i32 %sub, %tmp2
65  switch i32 %add, label %sw.epilog [
66    i32 1, label %sw.bb.1
67    i32 2, label %sw.bb.2
68  ]
69
70sw.bb.1:                                          ; preds = %entry
71  store i32 111, i32* %b, align 4
72  store i32 222, i32* %c, align 4
73  br label %sw.epilog
74
75sw.bb.2:                                          ; preds = %entry
76  store i32 333, i32* %b, align 4
77  store i32 444, i32* %c, align 4
78  br label %sw.epilog
79
80sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
81  ret void
82}
83
84define void @test2(i64 %x) nounwind optsize {
85; ENABLED-LABEL: test2:
86; ENABLED:       # %bb.0: # %entry
87; ENABLED-NEXT:    shlq $2, %rdi
88; ENABLED-NEXT:    leaq arr1+4(%rdi,%rdi,2), %rax
89; ENABLED-NEXT:    movl -4(%rax), %ecx
90; ENABLED-NEXT:    subl (%rax), %ecx
91; ENABLED-NEXT:    addl 4(%rax), %ecx
92; ENABLED-NEXT:    cmpl $2, %ecx
93; ENABLED-NEXT:    je .LBB1_3
94; ENABLED-NEXT:  # %bb.1: # %entry
95; ENABLED-NEXT:    cmpl $1, %ecx
96; ENABLED-NEXT:    jne .LBB1_4
97; ENABLED-NEXT:  # %bb.2: # %sw.bb.1
98; ENABLED-NEXT:    movl $111, (%rax)
99; ENABLED-NEXT:    movl $222, 4(%rax)
100; ENABLED-NEXT:    retq
101; ENABLED-NEXT:  .LBB1_3: # %sw.bb.2
102; ENABLED-NEXT:    movl $333, (%rax) # imm = 0x14D
103; ENABLED-NEXT:    movl $444, 4(%rax) # imm = 0x1BC
104; ENABLED-NEXT:  .LBB1_4: # %sw.epilog
105; ENABLED-NEXT:    retq
106;
107; DISABLED-LABEL: test2:
108; DISABLED:       # %bb.0: # %entry
109; DISABLED-NEXT:    shlq $2, %rdi
110; DISABLED-NEXT:    movl arr1(%rdi,%rdi,2), %edx
111; DISABLED-NEXT:    leaq arr1+4(%rdi,%rdi,2), %rax
112; DISABLED-NEXT:    subl arr1+4(%rdi,%rdi,2), %edx
113; DISABLED-NEXT:    leaq arr1+8(%rdi,%rdi,2), %rcx
114; DISABLED-NEXT:    addl arr1+8(%rdi,%rdi,2), %edx
115; DISABLED-NEXT:    cmpl $2, %edx
116; DISABLED-NEXT:    je .LBB1_3
117; DISABLED-NEXT:  # %bb.1: # %entry
118; DISABLED-NEXT:    cmpl $1, %edx
119; DISABLED-NEXT:    jne .LBB1_4
120; DISABLED-NEXT:  # %bb.2: # %sw.bb.1
121; DISABLED-NEXT:    movl $111, (%rax)
122; DISABLED-NEXT:    movl $222, (%rcx)
123; DISABLED-NEXT:    retq
124; DISABLED-NEXT:  .LBB1_3: # %sw.bb.2
125; DISABLED-NEXT:    movl $333, (%rax) # imm = 0x14D
126; DISABLED-NEXT:    movl $444, (%rcx) # imm = 0x1BC
127; DISABLED-NEXT:  .LBB1_4: # %sw.epilog
128; DISABLED-NEXT:    retq
129entry:
130  %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0
131  %tmp = load i32, i32* %a, align 4
132  %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1
133  %tmp1 = load i32, i32* %b, align 4
134  %sub = sub i32 %tmp, %tmp1
135  %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2
136  %tmp2 = load i32, i32* %c, align 4
137  %add = add nsw i32 %sub, %tmp2
138  switch i32 %add, label %sw.epilog [
139    i32 1, label %sw.bb.1
140    i32 2, label %sw.bb.2
141  ]
142
143sw.bb.1:                                          ; preds = %entry
144  store i32 111, i32* %b, align 4
145  store i32 222, i32* %c, align 4
146  br label %sw.epilog
147
148sw.bb.2:                                          ; preds = %entry
149  store i32 333, i32* %b, align 4
150  store i32 444, i32* %c, align 4
151  br label %sw.epilog
152
153sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
154  ret void
155}
156
157; Check that LEA optimization pass takes into account a resultant address
158; displacement when choosing a LEA instruction for replacing a redundant
159; address recalculation.
160
161define void @test3(i64 %x) nounwind optsize {
162; ENABLED-LABEL: test3:
163; ENABLED:       # %bb.0: # %entry
164; ENABLED-NEXT:    movq %rdi, %rax
165; ENABLED-NEXT:    shlq $7, %rax
166; ENABLED-NEXT:    leaq arr2+132(%rax,%rdi,8), %rcx
167; ENABLED-NEXT:    leaq arr2(%rax,%rdi,8), %rax
168; ENABLED-NEXT:    movl (%rcx), %edx
169; ENABLED-NEXT:    addl (%rax), %edx
170; ENABLED-NEXT:    cmpl $2, %edx
171; ENABLED-NEXT:    je .LBB2_3
172; ENABLED-NEXT:  # %bb.1: # %entry
173; ENABLED-NEXT:    cmpl $1, %edx
174; ENABLED-NEXT:    jne .LBB2_4
175; ENABLED-NEXT:  # %bb.2: # %sw.bb.1
176; ENABLED-NEXT:    movl $111, (%rcx)
177; ENABLED-NEXT:    movl $222, (%rax)
178; ENABLED-NEXT:    retq
179; ENABLED-NEXT:  .LBB2_3: # %sw.bb.2
180; ENABLED-NEXT:    movl $333, (%rcx) # imm = 0x14D
181; ENABLED-NEXT:    movl %eax, (%rax)
182; ENABLED-NEXT:  .LBB2_4: # %sw.epilog
183; ENABLED-NEXT:    retq
184;
185; DISABLED-LABEL: test3:
186; DISABLED:       # %bb.0: # %entry
187; DISABLED-NEXT:    movq %rdi, %rsi
188; DISABLED-NEXT:    shlq $7, %rsi
189; DISABLED-NEXT:    leaq arr2+132(%rsi,%rdi,8), %rcx
190; DISABLED-NEXT:    leaq arr2(%rsi,%rdi,8), %rax
191; DISABLED-NEXT:    movl arr2+132(%rsi,%rdi,8), %edx
192; DISABLED-NEXT:    addl arr2(%rsi,%rdi,8), %edx
193; DISABLED-NEXT:    cmpl $2, %edx
194; DISABLED-NEXT:    je .LBB2_3
195; DISABLED-NEXT:  # %bb.1: # %entry
196; DISABLED-NEXT:    cmpl $1, %edx
197; DISABLED-NEXT:    jne .LBB2_4
198; DISABLED-NEXT:  # %bb.2: # %sw.bb.1
199; DISABLED-NEXT:    movl $111, (%rcx)
200; DISABLED-NEXT:    movl $222, (%rax)
201; DISABLED-NEXT:    retq
202; DISABLED-NEXT:  .LBB2_3: # %sw.bb.2
203; DISABLED-NEXT:    movl $333, (%rcx) # imm = 0x14D
204; DISABLED-NEXT:    movl %eax, (%rax)
205; DISABLED-NEXT:  .LBB2_4: # %sw.epilog
206; DISABLED-NEXT:    retq
207entry:
208  %a = getelementptr inbounds [65 x %struct.anon2], [65 x %struct.anon2]* @arr2, i64 0, i64 %x, i32 2
209  %tmp = load i32, i32* %a, align 4
210  %b = getelementptr inbounds [65 x %struct.anon2], [65 x %struct.anon2]* @arr2, i64 0, i64 %x, i32 0
211  %tmp1 = load i32, i32* %b, align 4
212  %add = add nsw i32 %tmp, %tmp1
213  switch i32 %add, label %sw.epilog [
214    i32 1, label %sw.bb.1
215    i32 2, label %sw.bb.2
216  ]
217
218sw.bb.1:                                          ; preds = %entry
219  store i32 111, i32* %a, align 4
220  store i32 222, i32* %b, align 4
221  br label %sw.epilog
222
223sw.bb.2:                                          ; preds = %entry
224  store i32 333, i32* %a, align 4
225  ; Make sure the REG3's definition LEA won't be removed as redundant.
226  %cvt = ptrtoint i32* %b to i32
227  store i32 %cvt, i32* %b, align 4
228  br label %sw.epilog
229
230sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
231  ret void
232
233; REG3's definition is closer to movl than REG2's, but the pass still chooses
234; REG2 because it provides the resultant address displacement fitting 1 byte.
235
236}
237
238define void @test4(i64 %x) nounwind minsize {
239; ENABLED-LABEL: test4:
240; ENABLED:       # %bb.0: # %entry
241; ENABLED-NEXT:    imulq $12, %rdi, %rax
242; ENABLED-NEXT:    leaq arr1+4(%rax), %rax
243; ENABLED-NEXT:    movl -4(%rax), %ecx
244; ENABLED-NEXT:    subl (%rax), %ecx
245; ENABLED-NEXT:    addl 4(%rax), %ecx
246; ENABLED-NEXT:    cmpl $2, %ecx
247; ENABLED-NEXT:    je .LBB3_3
248; ENABLED-NEXT:  # %bb.1: # %entry
249; ENABLED-NEXT:    cmpl $1, %ecx
250; ENABLED-NEXT:    jne .LBB3_4
251; ENABLED-NEXT:  # %bb.2: # %sw.bb.1
252; ENABLED-NEXT:    movl $111, (%rax)
253; ENABLED-NEXT:    movl $222, 4(%rax)
254; ENABLED-NEXT:    retq
255; ENABLED-NEXT:  .LBB3_3: # %sw.bb.2
256; ENABLED-NEXT:    movl $333, (%rax) # imm = 0x14D
257; ENABLED-NEXT:    movl $444, 4(%rax) # imm = 0x1BC
258; ENABLED-NEXT:  .LBB3_4: # %sw.epilog
259; ENABLED-NEXT:    retq
260;
261; DISABLED-LABEL: test4:
262; DISABLED:       # %bb.0: # %entry
263; DISABLED-NEXT:    imulq $12, %rdi, %rsi
264; DISABLED-NEXT:    movl arr1(%rsi), %edx
265; DISABLED-NEXT:    leaq arr1+4(%rsi), %rax
266; DISABLED-NEXT:    subl arr1+4(%rsi), %edx
267; DISABLED-NEXT:    leaq arr1+8(%rsi), %rcx
268; DISABLED-NEXT:    addl arr1+8(%rsi), %edx
269; DISABLED-NEXT:    cmpl $2, %edx
270; DISABLED-NEXT:    je .LBB3_3
271; DISABLED-NEXT:  # %bb.1: # %entry
272; DISABLED-NEXT:    cmpl $1, %edx
273; DISABLED-NEXT:    jne .LBB3_4
274; DISABLED-NEXT:  # %bb.2: # %sw.bb.1
275; DISABLED-NEXT:    movl $111, (%rax)
276; DISABLED-NEXT:    movl $222, (%rcx)
277; DISABLED-NEXT:    retq
278; DISABLED-NEXT:  .LBB3_3: # %sw.bb.2
279; DISABLED-NEXT:    movl $333, (%rax) # imm = 0x14D
280; DISABLED-NEXT:    movl $444, (%rcx) # imm = 0x1BC
281; DISABLED-NEXT:  .LBB3_4: # %sw.epilog
282; DISABLED-NEXT:    retq
283entry:
284  %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0
285  %tmp = load i32, i32* %a, align 4
286  %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1
287  %tmp1 = load i32, i32* %b, align 4
288  %sub = sub i32 %tmp, %tmp1
289  %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2
290  %tmp2 = load i32, i32* %c, align 4
291  %add = add nsw i32 %sub, %tmp2
292  switch i32 %add, label %sw.epilog [
293    i32 1, label %sw.bb.1
294    i32 2, label %sw.bb.2
295  ]
296
297sw.bb.1:                                          ; preds = %entry
298  store i32 111, i32* %b, align 4
299  store i32 222, i32* %c, align 4
300  br label %sw.epilog
301
302sw.bb.2:                                          ; preds = %entry
303  store i32 333, i32* %b, align 4
304  store i32 444, i32* %c, align 4
305  br label %sw.epilog
306
307sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
308  ret void
309}
310
311define  i32 @test5(i32 %x, i32 %y)  #0 {
312; CHECK-LABEL: test5:
313; CHECK:       # %bb.0: # %entry
314; CHECK-NEXT:    movl %edi, %eax
315; CHECK-NEXT:    addl %esi, %esi
316; CHECK-NEXT:    subl %esi, %eax
317; CHECK-NEXT:    retq
318entry:
319  %mul = mul nsw i32 %y, -2
320  %add = add nsw i32 %mul, %x
321  ret i32 %add
322}
323
324define  i32 @test6(i32 %x, i32 %y)  #0 {
325; CHECK-LABEL: test6:
326; CHECK:       # %bb.0: # %entry
327; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
328; CHECK-NEXT:    movl %edi, %eax
329; CHECK-NEXT:    leal (%rsi,%rsi,2), %ecx
330; CHECK-NEXT:    subl %ecx, %eax
331; CHECK-NEXT:    retq
332entry:
333  %mul = mul nsw i32 %y, -3
334  %add = add nsw i32 %mul, %x
335  ret i32 %add
336}
337
338define  i32 @test7(i32 %x, i32 %y)  #0 {
339; CHECK-LABEL: test7:
340; CHECK:       # %bb.0: # %entry
341; CHECK-NEXT:    movl %edi, %eax
342; CHECK-NEXT:    shll $2, %esi
343; CHECK-NEXT:    subl %esi, %eax
344; CHECK-NEXT:    retq
345entry:
346  %mul = mul nsw i32 %y, -4
347  %add = add nsw i32 %mul, %x
348  ret i32 %add
349}
350
351define  i32 @test8(i32 %x, i32 %y)  #0 {
352; CHECK-LABEL: test8:
353; CHECK:       # %bb.0: # %entry
354; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
355; CHECK-NEXT:    leal (,%rsi,4), %eax
356; CHECK-NEXT:    subl %edi, %eax
357; CHECK-NEXT:    retq
358entry:
359  %mul = shl nsw i32 %y, 2
360  %sub = sub nsw i32 %mul, %x
361  ret i32 %sub
362}
363
364
365define  i32 @test9(i32 %x, i32 %y) #0 {
366; CHECK-LABEL: test9:
367; CHECK:       # %bb.0: # %entry
368; CHECK-NEXT:    movl %edi, %eax
369; CHECK-NEXT:    addl %esi, %esi
370; CHECK-NEXT:    subl %esi, %eax
371; CHECK-NEXT:    retq
372entry:
373  %mul = mul nsw i32 -2, %y
374  %add = add nsw i32 %x, %mul
375  ret i32 %add
376}
377
378define  i32 @test10(i32 %x, i32 %y) #0 {
379; CHECK-LABEL: test10:
380; CHECK:       # %bb.0: # %entry
381; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
382; CHECK-NEXT:    movl %edi, %eax
383; CHECK-NEXT:    leal (%rsi,%rsi,2), %ecx
384; CHECK-NEXT:    subl %ecx, %eax
385; CHECK-NEXT:    retq
386entry:
387  %mul = mul nsw i32 -3, %y
388  %add = add nsw i32 %x, %mul
389  ret i32 %add
390}
391
392define  i32 @test11(i32 %x, i32 %y) #0 {
393; CHECK-LABEL: test11:
394; CHECK:       # %bb.0: # %entry
395; CHECK-NEXT:    movl %edi, %eax
396; CHECK-NEXT:    shll $2, %esi
397; CHECK-NEXT:    subl %esi, %eax
398; CHECK-NEXT:    retq
399entry:
400  %mul = mul nsw i32 -4, %y
401  %add = add nsw i32 %x, %mul
402  ret i32 %add
403}
404
405define  i32 @test12(i32 %x, i32 %y) #0 {
406; CHECK-LABEL: test12:
407; CHECK:       # %bb.0: # %entry
408; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
409; CHECK-NEXT:    leal (,%rsi,4), %eax
410; CHECK-NEXT:    subl %edi, %eax
411; CHECK-NEXT:    retq
412entry:
413  %mul = mul nsw i32 4, %y
414  %sub = sub nsw i32 %mul, %x
415  ret i32 %sub
416}
417
418define  i64 @test13(i64 %x, i64 %y) #0 {
419; CHECK-LABEL: test13:
420; CHECK:       # %bb.0: # %entry
421; CHECK-NEXT:    movq %rdi, %rax
422; CHECK-NEXT:    shlq $2, %rsi
423; CHECK-NEXT:    subq %rsi, %rax
424; CHECK-NEXT:    retq
425entry:
426  %mul = mul nsw i64 -4, %y
427  %add = add nsw i64 %x, %mul
428  ret i64 %add
429}
430
431define  i32 @test14(i32 %x, i32 %y) #0 {
432; CHECK-LABEL: test14:
433; CHECK:       # %bb.0: # %entry
434; CHECK-NEXT:    # kill: def $esi killed $esi def $rsi
435; CHECK-NEXT:    leal (,%rsi,4), %eax
436; CHECK-NEXT:    subl %edi, %eax
437; CHECK-NEXT:    retq
438entry:
439  %mul = mul nsw i32 4, %y
440  %sub = sub nsw i32 %mul, %x
441  ret i32 %sub
442}
443
444define  zeroext i16 @test15(i16 zeroext %x, i16 zeroext %y) #0 {
445; CHECK-LABEL: test15:
446; CHECK:       # %bb.0: # %entry
447; CHECK-NEXT:    movl %edi, %eax
448; CHECK-NEXT:    shll $3, %esi
449; CHECK-NEXT:    subl %esi, %eax
450; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
451; CHECK-NEXT:    retq
452entry:
453  %conv = zext i16 %x to i32
454  %conv1 = zext i16 %y to i32
455  %mul = mul nsw i32 -8, %conv1
456  %add = add nsw i32 %conv, %mul
457  %conv2 = trunc i32 %add to i16
458  ret i16 %conv2
459}
460
461attributes #0 = { norecurse nounwind optsize readnone uwtable}
462