xref: /llvm-project/llvm/test/Transforms/InstCombine/bitwiselogic-bitmanip.ll (revision 29f98d6c25e237d311038ce225f0b3109925d400)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4define i32 @test_or_fshl(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh) {
5; CHECK-LABEL: define i32 @test_or_fshl(
6; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH:%.*]]) {
7; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[A]], [[C]]
8; CHECK-NEXT:    [[TMP2:%.*]] = or i32 [[B]], [[D]]
9; CHECK-NEXT:    [[RET:%.*]] = call i32 @llvm.fshl.i32(i32 [[TMP1]], i32 [[TMP2]], i32 [[SH]])
10; CHECK-NEXT:    ret i32 [[RET]]
11;
12  %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh)
13  %val2 = call i32 @llvm.fshl.i32(i32 %c, i32 %d, i32 %sh)
14  %ret = or i32 %val1, %val2
15  ret i32 %ret
16}
17define i32 @test_and_fshl(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh) {
18; CHECK-LABEL: define i32 @test_and_fshl(
19; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH:%.*]]) {
20; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[A]], [[C]]
21; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[B]], [[D]]
22; CHECK-NEXT:    [[RET:%.*]] = call i32 @llvm.fshl.i32(i32 [[TMP1]], i32 [[TMP2]], i32 [[SH]])
23; CHECK-NEXT:    ret i32 [[RET]]
24;
25  %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh)
26  %val2 = call i32 @llvm.fshl.i32(i32 %c, i32 %d, i32 %sh)
27  %ret = and i32 %val1, %val2
28  ret i32 %ret
29}
30define i32 @test_xor_fshl(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh) {
31; CHECK-LABEL: define i32 @test_xor_fshl(
32; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH:%.*]]) {
33; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A]], [[C]]
34; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[B]], [[D]]
35; CHECK-NEXT:    [[RET:%.*]] = call i32 @llvm.fshl.i32(i32 [[TMP1]], i32 [[TMP2]], i32 [[SH]])
36; CHECK-NEXT:    ret i32 [[RET]]
37;
38  %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh)
39  %val2 = call i32 @llvm.fshl.i32(i32 %c, i32 %d, i32 %sh)
40  %ret = xor i32 %val1, %val2
41  ret i32 %ret
42}
43define i32 @test_or_fshr(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh) {
44; CHECK-LABEL: define i32 @test_or_fshr(
45; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH:%.*]]) {
46; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[A]], [[C]]
47; CHECK-NEXT:    [[TMP2:%.*]] = or i32 [[B]], [[D]]
48; CHECK-NEXT:    [[RET:%.*]] = call i32 @llvm.fshr.i32(i32 [[TMP1]], i32 [[TMP2]], i32 [[SH]])
49; CHECK-NEXT:    ret i32 [[RET]]
50;
51  %val1 = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %sh)
52  %val2 = call i32 @llvm.fshr.i32(i32 %c, i32 %d, i32 %sh)
53  %ret = or i32 %val1, %val2
54  ret i32 %ret
55}
56define i32 @test_or_fshl_cascade(i32 %a, i32 %b, i32 %c) {
57; CHECK-LABEL: define i32 @test_or_fshl_cascade(
58; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]]) {
59; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[A]], [[B]]
60; CHECK-NEXT:    [[TMP2:%.*]] = or i32 [[A]], [[B]]
61; CHECK-NEXT:    [[TMP3:%.*]] = or i32 [[TMP1]], [[C]]
62; CHECK-NEXT:    [[TMP4:%.*]] = or i32 [[TMP2]], [[C]]
63; CHECK-NEXT:    [[OR2:%.*]] = call i32 @llvm.fshl.i32(i32 [[TMP3]], i32 [[TMP4]], i32 24)
64; CHECK-NEXT:    ret i32 [[OR2]]
65;
66  %fshl1 = call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 24)
67  %fshl2 = call i32 @llvm.fshl.i32(i32 %b, i32 %b, i32 24)
68  %fshl3 = call i32 @llvm.fshl.i32(i32 %c, i32 %c, i32 24)
69  %or1 = or i32 %fshl1, %fshl2
70  %or2 = or i32 %or1, %fshl3
71  ret i32 %or2
72}
73define i32 @test_or_bitreverse(i32 %a, i32 %b) {
74; CHECK-LABEL: define i32 @test_or_bitreverse(
75; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
76; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[A]], [[B]]
77; CHECK-NEXT:    [[RET:%.*]] = call i32 @llvm.bitreverse.i32(i32 [[TMP1]])
78; CHECK-NEXT:    ret i32 [[RET]]
79;
80  %val1 = call i32 @llvm.bitreverse.i32(i32 %a)
81  %val2 = call i32 @llvm.bitreverse.i32(i32 %b)
82  %ret = or i32 %val1, %val2
83  ret i32 %ret
84}
85define i32 @test_or_bitreverse_constant(i32 %a, i32 %b) {
86; CHECK-LABEL: define i32 @test_or_bitreverse_constant(
87; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
88; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[A]], 255
89; CHECK-NEXT:    [[RET:%.*]] = call i32 @llvm.bitreverse.i32(i32 [[TMP1]])
90; CHECK-NEXT:    ret i32 [[RET]]
91;
92  %val1 = call i32 @llvm.bitreverse.i32(i32 %a)
93  %ret = or i32 %val1, 4278190080
94  ret i32 %ret
95}
96define i32 @test_or_bswap(i32 %a, i32 %b) {
97; CHECK-LABEL: define i32 @test_or_bswap(
98; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
99; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[A]], [[B]]
100; CHECK-NEXT:    [[RET:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP1]])
101; CHECK-NEXT:    ret i32 [[RET]]
102;
103  %val1 = call i32 @llvm.bswap.i32(i32 %a)
104  %val2 = call i32 @llvm.bswap.i32(i32 %b)
105  %ret = or i32 %val1, %val2
106  ret i32 %ret
107}
108define i32 @test_or_bswap_constant(i32 %a, i32 %b) {
109; CHECK-LABEL: define i32 @test_or_bswap_constant(
110; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
111; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[A]], 255
112; CHECK-NEXT:    [[RET:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP1]])
113; CHECK-NEXT:    ret i32 [[RET]]
114;
115  %val1 = call i32 @llvm.bswap.i32(i32 %a)
116  %ret = or i32 %val1, 4278190080
117  ret i32 %ret
118}
119
120; Negative tests
121
122define i32 @test_or_fshl_fshr(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh) {
123; CHECK-LABEL: define i32 @test_or_fshl_fshr(
124; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH:%.*]]) {
125; CHECK-NEXT:    [[VAL1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A]], i32 [[B]], i32 [[SH]])
126; CHECK-NEXT:    [[VAL2:%.*]] = call i32 @llvm.fshr.i32(i32 [[C]], i32 [[D]], i32 [[SH]])
127; CHECK-NEXT:    [[RET:%.*]] = or i32 [[VAL1]], [[VAL2]]
128; CHECK-NEXT:    ret i32 [[RET]]
129;
130  %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh)
131  %val2 = call i32 @llvm.fshr.i32(i32 %c, i32 %d, i32 %sh)
132  %ret = or i32 %val1, %val2
133  ret i32 %ret
134}
135define i32 @test_or_bitreverse_bswap(i32 %a, i32 %b) {
136; CHECK-LABEL: define i32 @test_or_bitreverse_bswap(
137; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
138; CHECK-NEXT:    [[VAL1:%.*]] = call i32 @llvm.bitreverse.i32(i32 [[A]])
139; CHECK-NEXT:    [[VAL2:%.*]] = call i32 @llvm.bswap.i32(i32 [[B]])
140; CHECK-NEXT:    [[RET:%.*]] = or i32 [[VAL1]], [[VAL2]]
141; CHECK-NEXT:    ret i32 [[RET]]
142;
143  %val1 = call i32 @llvm.bitreverse.i32(i32 %a)
144  %val2 = call i32 @llvm.bswap.i32(i32 %b)
145  %ret = or i32 %val1, %val2
146  ret i32 %ret
147}
148define i32 @test_or_fshl_mismatched_shamt(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh1, i32 %sh2) {
149; CHECK-LABEL: define i32 @test_or_fshl_mismatched_shamt(
150; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH1:%.*]], i32 [[SH2:%.*]]) {
151; CHECK-NEXT:    [[VAL1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A]], i32 [[B]], i32 [[SH1]])
152; CHECK-NEXT:    [[VAL2:%.*]] = call i32 @llvm.fshl.i32(i32 [[C]], i32 [[D]], i32 [[SH2]])
153; CHECK-NEXT:    [[RET:%.*]] = or i32 [[VAL1]], [[VAL2]]
154; CHECK-NEXT:    ret i32 [[RET]]
155;
156  %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh1)
157  %val2 = call i32 @llvm.fshl.i32(i32 %c, i32 %d, i32 %sh2)
158  %ret = or i32 %val1, %val2
159  ret i32 %ret
160}
161define i32 @test_add_fshl(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh) {
162; CHECK-LABEL: define i32 @test_add_fshl(
163; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH:%.*]]) {
164; CHECK-NEXT:    [[VAL1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A]], i32 [[B]], i32 [[SH]])
165; CHECK-NEXT:    [[VAL2:%.*]] = call i32 @llvm.fshl.i32(i32 [[C]], i32 [[D]], i32 [[SH]])
166; CHECK-NEXT:    [[RET:%.*]] = add i32 [[VAL1]], [[VAL2]]
167; CHECK-NEXT:    ret i32 [[RET]]
168;
169  %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh)
170  %val2 = call i32 @llvm.fshl.i32(i32 %c, i32 %d, i32 %sh)
171  %ret = add i32 %val1, %val2
172  ret i32 %ret
173}
174define i32 @test_or_fshl_multiuse(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh) {
175; CHECK-LABEL: define i32 @test_or_fshl_multiuse(
176; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH:%.*]]) {
177; CHECK-NEXT:    [[VAL1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A]], i32 [[B]], i32 [[SH]])
178; CHECK-NEXT:    call void @use(i32 [[VAL1]])
179; CHECK-NEXT:    [[VAL2:%.*]] = call i32 @llvm.fshl.i32(i32 [[C]], i32 [[D]], i32 [[SH]])
180; CHECK-NEXT:    [[RET:%.*]] = or i32 [[VAL1]], [[VAL2]]
181; CHECK-NEXT:    ret i32 [[RET]]
182;
183  %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh)
184  call void @use(i32 %val1)
185  %val2 = call i32 @llvm.fshl.i32(i32 %c, i32 %d, i32 %sh)
186  %ret = or i32 %val1, %val2
187  ret i32 %ret
188}
189define i32 @test_or_bitreverse_multiuse(i32 %a, i32 %b) {
190; CHECK-LABEL: define i32 @test_or_bitreverse_multiuse(
191; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
192; CHECK-NEXT:    [[VAL1:%.*]] = call i32 @llvm.bitreverse.i32(i32 [[A]])
193; CHECK-NEXT:    call void @use(i32 [[VAL1]])
194; CHECK-NEXT:    [[VAL2:%.*]] = call i32 @llvm.bitreverse.i32(i32 [[B]])
195; CHECK-NEXT:    [[RET:%.*]] = or i32 [[VAL1]], [[VAL2]]
196; CHECK-NEXT:    ret i32 [[RET]]
197;
198  %val1 = call i32 @llvm.bitreverse.i32(i32 %a)
199  call void @use(i32 %val1)
200  %val2 = call i32 @llvm.bitreverse.i32(i32 %b)
201  %ret = or i32 %val1, %val2
202  ret i32 %ret
203}
204define i32 @test_or_fshl_constant(i32 %a, i32 %b, i32 %sh) {
205; CHECK-LABEL: define i32 @test_or_fshl_constant(
206; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[SH:%.*]]) {
207; CHECK-NEXT:    [[VAL1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A]], i32 [[B]], i32 [[SH]])
208; CHECK-NEXT:    [[RET:%.*]] = or i32 [[VAL1]], -16777216
209; CHECK-NEXT:    ret i32 [[RET]]
210;
211  %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh)
212  %ret = or i32 %val1, 4278190080
213  ret i32 %ret
214}
215
216declare void @use(i32)
217declare i32 @llvm.fshl.i32(i32, i32, i32)
218declare i32 @llvm.fshr.i32(i32, i32, i32)
219declare i32 @llvm.bitreverse.i32(i32)
220declare i32 @llvm.bswap.i32(i32)
221