@@ -155,3 +155,87 @@ define <4 x double> @fdiv_op0_constant_fneg_vec(<4 x double> %x) {
155
155
%r = fsub <4 x double > <double -0 .0 , double -0 .0 , double -0 .0 , double -0 .0 >, %d
156
156
ret <4 x double > %r
157
157
}
158
+
159
+ ; Sink FP negation through a select:
160
+ ; c ? -x : -y --> -(c ? x : y)
161
+
162
+ define <2 x double > @fneg_fneg_sel (<2 x double > %x , <2 x double > %y , i1 %cond ) {
163
+ ; CHECK-LABEL: @fneg_fneg_sel(
164
+ ; CHECK-NEXT: [[N1:%.*]] = fneg <2 x double> [[X:%.*]]
165
+ ; CHECK-NEXT: [[N2:%.*]] = fneg <2 x double> [[Y:%.*]]
166
+ ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x double> [[N1]], <2 x double> [[N2]]
167
+ ; CHECK-NEXT: ret <2 x double> [[SEL]]
168
+ ;
169
+ %n1 = fneg <2 x double > %x
170
+ %n2 = fneg <2 x double > %y
171
+ %sel = select i1 %cond , <2 x double > %n1 , <2 x double > %n2
172
+ ret <2 x double > %sel
173
+ }
174
+
175
+ ; An extra use is allowed.
176
+
177
+ define float @fneg_fneg_sel_extra_use1 (float %x , float %y , i1 %cond ) {
178
+ ; CHECK-LABEL: @fneg_fneg_sel_extra_use1(
179
+ ; CHECK-NEXT: [[N1:%.*]] = fneg float [[X:%.*]]
180
+ ; CHECK-NEXT: call void @use(float [[N1]])
181
+ ; CHECK-NEXT: [[N2:%.*]] = fneg float [[Y:%.*]]
182
+ ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], float [[N1]], float [[N2]]
183
+ ; CHECK-NEXT: ret float [[SEL]]
184
+ ;
185
+ %n1 = fneg float %x
186
+ call void @use (float %n1 )
187
+ %n2 = fneg float %y
188
+ %sel = select i1 %cond , float %n1 , float %n2
189
+ ret float %sel
190
+ }
191
+
192
+ define float @fneg_fneg_sel_extra_use2 (float %x , float %y , i1 %cond ) {
193
+ ; CHECK-LABEL: @fneg_fneg_sel_extra_use2(
194
+ ; CHECK-NEXT: [[N1:%.*]] = fneg float [[X:%.*]]
195
+ ; CHECK-NEXT: [[N2:%.*]] = fneg float [[Y:%.*]]
196
+ ; CHECK-NEXT: call void @use(float [[N2]])
197
+ ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], float [[N1]], float [[N2]]
198
+ ; CHECK-NEXT: ret float [[SEL]]
199
+ ;
200
+ %n1 = fneg float %x
201
+ %n2 = fneg float %y
202
+ call void @use (float %n2 )
203
+ %sel = select i1 %cond , float %n1 , float %n2
204
+ ret float %sel
205
+ }
206
+
207
+ ; Legacy form of fneg should work too.
208
+
209
+ define float @fsub_fsub_sel_extra_use1 (float %x , float %y , i1 %cond ) {
210
+ ; CHECK-LABEL: @fsub_fsub_sel_extra_use1(
211
+ ; CHECK-NEXT: [[N1:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
212
+ ; CHECK-NEXT: call void @use(float [[N1]])
213
+ ; CHECK-NEXT: [[N2:%.*]] = fsub float -0.000000e+00, [[Y:%.*]]
214
+ ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], float [[N1]], float [[N2]]
215
+ ; CHECK-NEXT: ret float [[SEL]]
216
+ ;
217
+ %n1 = fsub float -0 .0 , %x
218
+ call void @use (float %n1 )
219
+ %n2 = fsub float -0 .0 , %y
220
+ %sel = select i1 %cond , float %n1 , float %n2
221
+ ret float %sel
222
+ }
223
+
224
+ ; Negative test: but 2 extra uses would require an extra instruction.
225
+
226
+ define float @fneg_fneg_sel_extra_use3 (float %x , float %y , i1 %cond ) {
227
+ ; CHECK-LABEL: @fneg_fneg_sel_extra_use3(
228
+ ; CHECK-NEXT: [[N1:%.*]] = fneg float [[X:%.*]]
229
+ ; CHECK-NEXT: call void @use(float [[N1]])
230
+ ; CHECK-NEXT: [[N2:%.*]] = fneg float [[Y:%.*]]
231
+ ; CHECK-NEXT: call void @use(float [[N2]])
232
+ ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], float [[N1]], float [[N2]]
233
+ ; CHECK-NEXT: ret float [[SEL]]
234
+ ;
235
+ %n1 = fneg float %x
236
+ call void @use (float %n1 )
237
+ %n2 = fneg float %y
238
+ call void @use (float %n2 )
239
+ %sel = select i1 %cond , float %n1 , float %n2
240
+ ret float %sel
241
+ }
0 commit comments