1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
3
4; InstCombine and DAGCombiner transform an 'add' into an 'or'
5; if there are no common bits from the incoming operands.
6; LEA instruction selection should be able to see through that
7; transform and reduce add/shift/or instruction counts.
8
9define i32 @or_shift1_and1(i32 %x, i32 %y) {
10; CHECK-LABEL: or_shift1_and1:
11; CHECK:       # BB#0:
12; CHECK-NEXT:    andl $1, %esi
13; CHECK-NEXT:    leal (%rsi,%rdi,2), %eax
14; CHECK-NEXT:    retq
15
16  %shl = shl i32 %x, 1
17  %and = and i32 %y, 1
18  %or = or i32 %and, %shl
19  ret i32 %or
20}
21
22define i32 @or_shift1_and1_swapped(i32 %x, i32 %y) {
23; CHECK-LABEL: or_shift1_and1_swapped:
24; CHECK:       # BB#0:
25; CHECK-NEXT:    andl $1, %esi
26; CHECK-NEXT:    leal (%rsi,%rdi,2), %eax
27; CHECK-NEXT:    retq
28
29  %shl = shl i32 %x, 1
30  %and = and i32 %y, 1
31  %or = or i32 %shl, %and
32  ret i32 %or
33}
34
35define i32 @or_shift2_and1(i32 %x, i32 %y) {
36; CHECK-LABEL: or_shift2_and1:
37; CHECK:       # BB#0:
38; CHECK-NEXT:    andl $1, %esi
39; CHECK-NEXT:    leal (%rsi,%rdi,4), %eax
40; CHECK-NEXT:    retq
41
42  %shl = shl i32 %x, 2
43  %and = and i32 %y, 1
44  %or = or i32 %shl, %and
45  ret i32 %or
46}
47
48define i32 @or_shift3_and1(i32 %x, i32 %y) {
49; CHECK-LABEL: or_shift3_and1:
50; CHECK:       # BB#0:
51; CHECK-NEXT:    andl $1, %esi
52; CHECK-NEXT:    leal (%rsi,%rdi,8), %eax
53; CHECK-NEXT:    retq
54
55  %shl = shl i32 %x, 3
56  %and = and i32 %y, 1
57  %or = or i32 %shl, %and
58  ret i32 %or
59}
60
61define i32 @or_shift3_and7(i32 %x, i32 %y) {
62; CHECK-LABEL: or_shift3_and7:
63; CHECK:       # BB#0:
64; CHECK-NEXT:    andl $7, %esi
65; CHECK-NEXT:    leal (%rsi,%rdi,8), %eax
66; CHECK-NEXT:    retq
67
68  %shl = shl i32 %x, 3
69  %and = and i32 %y, 7
70  %or = or i32 %shl, %and
71  ret i32 %or
72}
73
74; The shift is too big for an LEA.
75
76define i32 @or_shift4_and1(i32 %x, i32 %y) {
77; CHECK-LABEL: or_shift4_and1:
78; CHECK:       # BB#0:
79; CHECK-NEXT:    shll $4, %edi
80; CHECK-NEXT:    andl $1, %esi
81; CHECK-NEXT:    leal (%rsi,%rdi), %eax
82; CHECK-NEXT:    retq
83
84  %shl = shl i32 %x, 4
85  %and = and i32 %y, 1
86  %or = or i32 %shl, %and
87  ret i32 %or
88}
89
90; The mask is too big for the shift, so the 'or' isn't equivalent to an 'add'.
91
92define i32 @or_shift3_and8(i32 %x, i32 %y) {
93; CHECK-LABEL: or_shift3_and8:
94; CHECK:       # BB#0:
95; CHECK-NEXT:    leal (,%rdi,8), %eax
96; CHECK-NEXT:    andl $8, %esi
97; CHECK-NEXT:    orl %esi, %eax
98; CHECK-NEXT:    retq
99
100  %shl = shl i32 %x, 3
101  %and = and i32 %y, 8
102  %or = or i32 %shl, %and
103  ret i32 %or
104}
105
106; 64-bit operands should work too.
107
108define i64 @or_shift1_and1_64(i64 %x, i64 %y) {
109; CHECK-LABEL: or_shift1_and1_64:
110; CHECK:       # BB#0:
111; CHECK-NEXT:    andl $1, %esi
112; CHECK-NEXT:    leaq (%rsi,%rdi,2), %rax
113; CHECK-NEXT:    retq
114
115  %shl = shl i64 %x, 1
116  %and = and i64 %y, 1
117  %or = or i64 %and, %shl
118  ret i64 %or
119}
120
121