1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; 'Negate' is considered less complex than a normal binop, so the xor should have the binop as the first operand.
5
6define i8 @neg(i8 %x) {
7; CHECK-LABEL: @neg(
8; CHECK-NEXT:    [[BO:%.*]] = udiv i8 [[X:%.*]], 42
9; CHECK-NEXT:    [[NEGX:%.*]] = sub i8 0, [[X]]
10; CHECK-NEXT:    [[R:%.*]] = xor i8 [[BO]], [[NEGX]]
11; CHECK-NEXT:    ret i8 [[R]]
12;
13  %bo = udiv i8 %x, 42
14  %negx = sub i8 0, %x
15  %r = xor i8 %negx, %bo
16  ret i8 %r
17}
18
19define <2 x i8> @neg_vec(<2 x i8> %x) {
20; CHECK-LABEL: @neg_vec(
21; CHECK-NEXT:    [[BO:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 42, i8 -42>
22; CHECK-NEXT:    [[NEGX:%.*]] = sub <2 x i8> zeroinitializer, [[X]]
23; CHECK-NEXT:    [[R:%.*]] = xor <2 x i8> [[BO]], [[NEGX]]
24; CHECK-NEXT:    ret <2 x i8> [[R]]
25;
26  %bo = udiv <2 x i8> %x, <i8 42, i8 -42>
27  %negx = sub <2 x i8> <i8 0, i8 0>, %x
28  %r = xor <2 x i8> %negx, %bo
29  ret <2 x i8> %r
30}
31
32define <2 x i8> @neg_vec_undef(<2 x i8> %x) {
33; CHECK-LABEL: @neg_vec_undef(
34; CHECK-NEXT:    [[BO:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 42, i8 -42>
35; CHECK-NEXT:    [[NEGX:%.*]] = sub <2 x i8> <i8 0, i8 undef>, [[X]]
36; CHECK-NEXT:    [[R:%.*]] = xor <2 x i8> [[BO]], [[NEGX]]
37; CHECK-NEXT:    ret <2 x i8> [[R]]
38;
39  %bo = udiv <2 x i8> %x, <i8 42, i8 -42>
40  %negx = sub <2 x i8> <i8 0, i8 undef>, %x
41  %r = xor <2 x i8> %negx, %bo
42  ret <2 x i8> %r
43}
44
45; 'Not' is considered less complex than a normal binop, so the mul should have the binop as the first operand.
46
47define i8 @not(i8 %x) {
48; CHECK-LABEL: @not(
49; CHECK-NEXT:    [[BO:%.*]] = udiv i8 [[X:%.*]], 42
50; CHECK-NEXT:    [[NOTX:%.*]] = xor i8 [[X]], -1
51; CHECK-NEXT:    [[R:%.*]] = mul i8 [[BO]], [[NOTX]]
52; CHECK-NEXT:    ret i8 [[R]]
53;
54  %bo = udiv i8 %x, 42
55  %notx = xor i8 -1, %x
56  %r = mul i8 %notx, %bo
57  ret i8 %r
58}
59
60define <2 x i8> @not_vec(<2 x i8> %x) {
61; CHECK-LABEL: @not_vec(
62; CHECK-NEXT:    [[BO:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 42, i8 -42>
63; CHECK-NEXT:    [[NOTX:%.*]] = xor <2 x i8> [[X]], <i8 -1, i8 -1>
64; CHECK-NEXT:    [[R:%.*]] = mul <2 x i8> [[BO]], [[NOTX]]
65; CHECK-NEXT:    ret <2 x i8> [[R]]
66;
67  %bo = udiv <2 x i8> %x, <i8 42, i8 -42>
68  %notx = xor <2 x i8> <i8 -1, i8 -1>, %x
69  %r = mul <2 x i8> %notx, %bo
70  ret <2 x i8> %r
71}
72
73define <2 x i8> @not_vec_undef(<2 x i8> %x) {
74; CHECK-LABEL: @not_vec_undef(
75; CHECK-NEXT:    [[BO:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 42, i8 -42>
76; CHECK-NEXT:    [[NOTX:%.*]] = xor <2 x i8> [[X]], <i8 -1, i8 undef>
77; CHECK-NEXT:    [[R:%.*]] = mul <2 x i8> [[BO]], [[NOTX]]
78; CHECK-NEXT:    ret <2 x i8> [[R]]
79;
80  %bo = udiv <2 x i8> %x, <i8 42, i8 -42>
81  %notx = xor <2 x i8> <i8 -1, i8 undef>, %x
82  %r = mul <2 x i8> %notx, %bo
83  ret <2 x i8> %r
84}
85
86; 'Fneg' is considered less complex than a normal binop, so the fmul should have the binop as the first operand.
87; Extra uses are required to ensure that the fneg is not canonicalized after the fmul.
88
89declare void @use(float)
90declare void @use_vec(<2 x float>)
91
92define float @fneg(float %x) {
93; CHECK-LABEL: @fneg(
94; CHECK-NEXT:    [[BO:%.*]] = fdiv float [[X:%.*]], 4.200000e+01
95; CHECK-NEXT:    [[FNEGX:%.*]] = fneg float [[X]]
96; CHECK-NEXT:    [[R:%.*]] = fmul float [[BO]], [[FNEGX]]
97; CHECK-NEXT:    call void @use(float [[FNEGX]])
98; CHECK-NEXT:    ret float [[R]]
99;
100  %bo = fdiv float %x, 42.0
101  %fnegx = fsub float -0.0, %x
102  %r = fmul float %fnegx, %bo
103  call void @use(float %fnegx)
104  ret float %r
105}
106
107define float @unary_fneg(float %x) {
108; CHECK-LABEL: @unary_fneg(
109; CHECK-NEXT:    [[BO:%.*]] = fdiv float [[X:%.*]], 4.200000e+01
110; CHECK-NEXT:    [[FNEGX:%.*]] = fneg float [[X]]
111; CHECK-NEXT:    [[R:%.*]] = fmul float [[BO]], [[FNEGX]]
112; CHECK-NEXT:    call void @use(float [[FNEGX]])
113; CHECK-NEXT:    ret float [[R]]
114;
115  %bo = fdiv float %x, 42.0
116  %fnegx = fneg float %x
117  %r = fmul float %fnegx, %bo
118  call void @use(float %fnegx)
119  ret float %r
120}
121
122define <2 x float> @fneg_vec(<2 x float> %x) {
123; CHECK-LABEL: @fneg_vec(
124; CHECK-NEXT:    [[BO:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.200000e+01, float -4.200000e+01>
125; CHECK-NEXT:    [[FNEGX:%.*]] = fneg <2 x float> [[X]]
126; CHECK-NEXT:    [[R:%.*]] = fmul <2 x float> [[BO]], [[FNEGX]]
127; CHECK-NEXT:    call void @use_vec(<2 x float> [[FNEGX]])
128; CHECK-NEXT:    ret <2 x float> [[R]]
129;
130  %bo = fdiv <2 x float> %x, <float 42.0, float -42.0>
131  %fnegx = fsub <2 x float> <float -0.0, float -0.0>, %x
132  %r = fmul <2 x float> %fnegx, %bo
133  call void @use_vec(<2 x float> %fnegx)
134  ret <2 x float> %r
135}
136
137define <2 x float> @fneg_vec_undef(<2 x float> %x) {
138; CHECK-LABEL: @fneg_vec_undef(
139; CHECK-NEXT:    [[BO:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.200000e+01, float -4.200000e+01>
140; CHECK-NEXT:    [[FNEGX:%.*]] = fneg <2 x float> [[X]]
141; CHECK-NEXT:    [[R:%.*]] = fmul <2 x float> [[BO]], [[FNEGX]]
142; CHECK-NEXT:    call void @use_vec(<2 x float> [[FNEGX]])
143; CHECK-NEXT:    ret <2 x float> [[R]]
144;
145  %bo = fdiv <2 x float> %x, <float 42.0, float -42.0>
146  %fnegx = fsub <2 x float> <float -0.0, float undef>, %x
147  %r = fmul <2 x float> %fnegx, %bo
148  call void @use_vec(<2 x float> %fnegx)
149  ret <2 x float> %r
150}
151
152define <2 x float> @unary_fneg_vec(<2 x float> %x) {
153; CHECK-LABEL: @unary_fneg_vec(
154; CHECK-NEXT:    [[BO:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.200000e+01, float -4.200000e+01>
155; CHECK-NEXT:    [[FNEGX:%.*]] = fneg <2 x float> [[X]]
156; CHECK-NEXT:    [[R:%.*]] = fmul <2 x float> [[BO]], [[FNEGX]]
157; CHECK-NEXT:    call void @use_vec(<2 x float> [[FNEGX]])
158; CHECK-NEXT:    ret <2 x float> [[R]]
159;
160  %bo = fdiv <2 x float> %x, <float 42.0, float -42.0>
161  %fnegx = fneg <2 x float> %x
162  %r = fmul <2 x float> %fnegx, %bo
163  call void @use_vec(<2 x float> %fnegx)
164  ret <2 x float> %r
165}
166
167