1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S < %s -instcombine | FileCheck %s
3
4; Fold
5;   (X & (- Y)) - X
6; to
7;   - (X & (Y - 1))
8;
9; This allows us to possibly hoist said negation further out.
10
11; https://bugs.llvm.org/show_bug.cgi?id=44448
12
13; Base tests
14
15define i8 @t0(i8 %x, i8 %y) {
16; CHECK-LABEL: @t0(
17; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], -1
18; CHECK-NEXT:    [[TMP2:%.*]] = and i8 [[TMP1]], [[X:%.*]]
19; CHECK-NEXT:    [[NEGBIAS:%.*]] = sub i8 0, [[TMP2]]
20; CHECK-NEXT:    ret i8 [[NEGBIAS]]
21;
22  %negy = sub i8 0, %y
23  %unbiasedx = and i8 %negy, %x
24  %negbias = sub i8 %unbiasedx, %x
25  ret i8 %negbias
26}
27
28declare i8 @gen8()
29
30define i8 @t1_commutative(i8 %y) {
31; CHECK-LABEL: @t1_commutative(
32; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
33; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], -1
34; CHECK-NEXT:    [[TMP2:%.*]] = and i8 [[X]], [[TMP1]]
35; CHECK-NEXT:    [[NEGBIAS:%.*]] = sub i8 0, [[TMP2]]
36; CHECK-NEXT:    ret i8 [[NEGBIAS]]
37;
38  %x = call i8 @gen8()
39  %negy = sub i8 0, %y
40  %unbiasedx = and i8 %x, %negy ; commutative, swapped
41  %negbias = sub i8 %unbiasedx, %x
42  ret i8 %negbias
43}
44
45define <2 x i8> @t2_vec(<2 x i8> %x, <2 x i8> %y) {
46; CHECK-LABEL: @t2_vec(
47; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i8> [[Y:%.*]], <i8 -1, i8 -1>
48; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i8> [[TMP1]], [[X:%.*]]
49; CHECK-NEXT:    [[NEGBIAS:%.*]] = sub <2 x i8> zeroinitializer, [[TMP2]]
50; CHECK-NEXT:    ret <2 x i8> [[NEGBIAS]]
51;
52  %negy = sub <2 x i8> <i8 0, i8 0>, %y
53  %unbiasedx = and <2 x i8> %negy, %x
54  %negbias = sub <2 x i8> %unbiasedx, %x
55  ret <2 x i8> %negbias
56}
57
58define <2 x i8> @t3_vec_undef(<2 x i8> %x, <2 x i8> %y) {
59; CHECK-LABEL: @t3_vec_undef(
60; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i8> [[Y:%.*]], <i8 -1, i8 -1>
61; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i8> [[TMP1]], [[X:%.*]]
62; CHECK-NEXT:    [[NEGBIAS:%.*]] = sub <2 x i8> zeroinitializer, [[TMP2]]
63; CHECK-NEXT:    ret <2 x i8> [[NEGBIAS]]
64;
65  %negy = sub <2 x i8> <i8 0, i8 undef>, %y
66  %unbiasedx = and <2 x i8> %negy, %x
67  %negbias = sub <2 x i8> %unbiasedx, %x
68  ret <2 x i8> %negbias
69}
70
71; Extra uses always prevent fold
72
73declare void @use8(i8)
74
75define i8 @n4_extrause0(i8 %x, i8 %y) {
76; CHECK-LABEL: @n4_extrause0(
77; CHECK-NEXT:    [[NEGY:%.*]] = sub i8 0, [[Y:%.*]]
78; CHECK-NEXT:    call void @use8(i8 [[NEGY]])
79; CHECK-NEXT:    [[UNBIASEDX:%.*]] = and i8 [[NEGY]], [[X:%.*]]
80; CHECK-NEXT:    [[NEGBIAS:%.*]] = sub i8 [[UNBIASEDX]], [[X]]
81; CHECK-NEXT:    ret i8 [[NEGBIAS]]
82;
83  %negy = sub i8 0, %y
84  call void @use8(i8 %negy)
85  %unbiasedx = and i8 %negy, %x
86  %negbias = sub i8 %unbiasedx, %x
87  ret i8 %negbias
88}
89define i8 @n5_extrause1(i8 %x, i8 %y) {
90; CHECK-LABEL: @n5_extrause1(
91; CHECK-NEXT:    [[NEGY:%.*]] = sub i8 0, [[Y:%.*]]
92; CHECK-NEXT:    [[UNBIASEDX:%.*]] = and i8 [[NEGY]], [[X:%.*]]
93; CHECK-NEXT:    call void @use8(i8 [[UNBIASEDX]])
94; CHECK-NEXT:    [[NEGBIAS:%.*]] = sub i8 [[UNBIASEDX]], [[X]]
95; CHECK-NEXT:    ret i8 [[NEGBIAS]]
96;
97  %negy = sub i8 0, %y
98  %unbiasedx = and i8 %negy, %x
99  call void @use8(i8 %unbiasedx)
100  %negbias = sub i8 %unbiasedx, %x
101  ret i8 %negbias
102}
103define i8 @n6_extrause2(i8 %x, i8 %y) {
104; CHECK-LABEL: @n6_extrause2(
105; CHECK-NEXT:    [[NEGY:%.*]] = sub i8 0, [[Y:%.*]]
106; CHECK-NEXT:    call void @use8(i8 [[NEGY]])
107; CHECK-NEXT:    [[UNBIASEDX:%.*]] = and i8 [[NEGY]], [[X:%.*]]
108; CHECK-NEXT:    call void @use8(i8 [[UNBIASEDX]])
109; CHECK-NEXT:    [[NEGBIAS:%.*]] = sub i8 [[UNBIASEDX]], [[X]]
110; CHECK-NEXT:    ret i8 [[NEGBIAS]]
111;
112  %negy = sub i8 0, %y
113  call void @use8(i8 %negy)
114  %unbiasedx = and i8 %negy, %x
115  call void @use8(i8 %unbiasedx)
116  %negbias = sub i8 %unbiasedx, %x
117  ret i8 %negbias
118}
119
120; Negative tests
121
122define i8 @n7(i8 %x, i8 %y) {
123; CHECK-LABEL: @n7(
124; CHECK-NEXT:    [[NEGY_NOT:%.*]] = add i8 [[Y:%.*]], -1
125; CHECK-NEXT:    [[NEGBIAS:%.*]] = and i8 [[NEGY_NOT]], [[X:%.*]]
126; CHECK-NEXT:    ret i8 [[NEGBIAS]]
127;
128  %negy = sub i8 0, %y
129  %unbiasedx = and i8 %negy, %x
130  %negbias = sub i8 %x, %unbiasedx ; wrong order
131  ret i8 %negbias
132}
133
134define i8 @n8(i8 %x, i8 %y) {
135; CHECK-LABEL: @n8(
136; CHECK-NEXT:    [[NEGY:%.*]] = sub i8 1, [[Y:%.*]]
137; CHECK-NEXT:    [[UNBIASEDX:%.*]] = and i8 [[NEGY]], [[X:%.*]]
138; CHECK-NEXT:    [[NEGBIAS:%.*]] = sub i8 [[UNBIASEDX]], [[X]]
139; CHECK-NEXT:    ret i8 [[NEGBIAS]]
140;
141  %negy = sub i8 1, %y ; not negation
142  %unbiasedx = and i8 %negy, %x
143  %negbias = sub i8 %unbiasedx, %x
144  ret i8 %negbias
145}
146
147define i8 @n9(i8 %x0, i8 %x1, i8 %y) {
148; CHECK-LABEL: @n9(
149; CHECK-NEXT:    [[NEGY:%.*]] = sub i8 0, [[Y:%.*]]
150; CHECK-NEXT:    [[UNBIASEDX:%.*]] = and i8 [[NEGY]], [[X1:%.*]]
151; CHECK-NEXT:    [[NEGBIAS:%.*]] = sub i8 [[UNBIASEDX]], [[X0:%.*]]
152; CHECK-NEXT:    ret i8 [[NEGBIAS]]
153;
154  %negy = sub i8 0, %y
155  %unbiasedx = and i8 %x1, %negy ; not %x0
156  %negbias = sub i8 %unbiasedx, %x0 ; not %x1
157  ret i8 %negbias
158}
159