II->setArgOperand(1, Arg0);
return II;
}
+
+ // FIXME: Simplifications should be in instsimplify.
if (Value *V = simplifyMinnumMaxnum(*II))
return replaceInstUsesWith(*II, V);
+
+ Value *X, *Y;
+ if (match(Arg0, m_FNeg(m_Value(X))) && match(Arg1, m_FNeg(m_Value(Y))) &&
+ (Arg0->hasOneUse() || Arg1->hasOneUse())) {
+ // If both operands are negated, invert the call and negate the result:
+ // minnum(-X, -Y) --> -(maxnum(X, Y))
+ // maxnum(-X, -Y) --> -(minnum(X, Y))
+ Intrinsic::ID NewIID = II->getIntrinsicID() == Intrinsic::maxnum ?
+ Intrinsic::minnum : Intrinsic::maxnum;
+ Value *NewCall = Builder.CreateIntrinsic(NewIID, { X, Y }, II);
+ Instruction *FNeg = BinaryOperator::CreateFNeg(NewCall);
+ FNeg->copyIRFlags(II);
+ return FNeg;
+ }
break;
}
case Intrinsic::fmuladd: {
define <2 x float> @neg_neg(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @neg_neg(
-; CHECK-NEXT: [[NEGX:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[X:%.*]]
-; CHECK-NEXT: [[NEGY:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[Y:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call <2 x float> @llvm.maxnum.v2f32(<2 x float> [[NEGX]], <2 x float> [[NEGY]])
+; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.minnum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]])
+; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[TMP1]]
; CHECK-NEXT: ret <2 x float> [[R]]
;
%negx = fsub <2 x float> <float -0.0, float -0.0>, %x
}
; FMF is not required, but it should be propagated from the intrinsic (not the fnegs).
-; Also, make sure this works with vectors.
define float @neg_neg_vec_fmf(float %x, float %y) {
; CHECK-LABEL: @neg_neg_vec_fmf(
-; CHECK-NEXT: [[NEGX:%.*]] = fsub arcp float -0.000000e+00, [[X:%.*]]
-; CHECK-NEXT: [[NEGY:%.*]] = fsub afn float -0.000000e+00, [[Y:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call fast float @llvm.maxnum.f32(float [[NEGX]], float [[NEGY]])
+; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT: [[R:%.*]] = fsub fast float -0.000000e+00, [[TMP1]]
; CHECK-NEXT: ret float [[R]]
;
%negx = fsub arcp float -0.0, %x
define float @neg_neg_extra_use_x(float %x, float %y) {
; CHECK-LABEL: @neg_neg_extra_use_x(
; CHECK-NEXT: [[NEGX:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
-; CHECK-NEXT: [[NEGY:%.*]] = fsub float -0.000000e+00, [[Y:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.maxnum.f32(float [[NEGX]], float [[NEGY]])
+; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X]], float [[Y:%.*]])
+; CHECK-NEXT: [[R:%.*]] = fsub float -0.000000e+00, [[TMP1]]
; CHECK-NEXT: call void @use(float [[NEGX]])
; CHECK-NEXT: ret float [[R]]
;
define float @neg_neg_extra_use_y(float %x, float %y) {
; CHECK-LABEL: @neg_neg_extra_use_y(
-; CHECK-NEXT: [[NEGX:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
; CHECK-NEXT: [[NEGY:%.*]] = fsub float -0.000000e+00, [[Y:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.maxnum.f32(float [[NEGX]], float [[NEGY]])
+; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y]])
+; CHECK-NEXT: [[R:%.*]] = fsub float -0.000000e+00, [[TMP1]]
; CHECK-NEXT: call void @use(float [[NEGY]])
; CHECK-NEXT: ret float [[R]]
;
define double @neg_neg(double %x, double %y) {
; CHECK-LABEL: @neg_neg(
-; CHECK-NEXT: [[NEGX:%.*]] = fsub double -0.000000e+00, [[X:%.*]]
-; CHECK-NEXT: [[NEGY:%.*]] = fsub double -0.000000e+00, [[Y:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call double @llvm.minnum.f64(double [[NEGX]], double [[NEGY]])
+; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]])
+; CHECK-NEXT: [[R:%.*]] = fsub double -0.000000e+00, [[TMP1]]
; CHECK-NEXT: ret double [[R]]
;
%negx = fsub double -0.0, %x
define <2 x double> @neg_neg_vec_fmf(<2 x double> %x, <2 x double> %y) {
; CHECK-LABEL: @neg_neg_vec_fmf(
-; CHECK-NEXT: [[NEGX:%.*]] = fsub reassoc <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[X:%.*]]
-; CHECK-NEXT: [[NEGY:%.*]] = fsub fast <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[Y:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call nnan ninf <2 x double> @llvm.minnum.v2f64(<2 x double> [[NEGX]], <2 x double> [[NEGY]])
+; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf <2 x double> @llvm.maxnum.v2f64(<2 x double> [[X:%.*]], <2 x double> [[Y:%.*]])
+; CHECK-NEXT: [[R:%.*]] = fsub nnan ninf <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[TMP1]]
; CHECK-NEXT: ret <2 x double> [[R]]
;
%negx = fsub reassoc <2 x double> <double -0.0, double -0.0>, %x
define double @neg_neg_extra_use_x(double %x, double %y) {
; CHECK-LABEL: @neg_neg_extra_use_x(
; CHECK-NEXT: [[NEGX:%.*]] = fsub double -0.000000e+00, [[X:%.*]]
-; CHECK-NEXT: [[NEGY:%.*]] = fsub double -0.000000e+00, [[Y:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call double @llvm.minnum.f64(double [[NEGX]], double [[NEGY]])
+; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maxnum.f64(double [[X]], double [[Y:%.*]])
+; CHECK-NEXT: [[R:%.*]] = fsub double -0.000000e+00, [[TMP1]]
; CHECK-NEXT: call void @use(double [[NEGX]])
; CHECK-NEXT: ret double [[R]]
;
define double @neg_neg_extra_use_y(double %x, double %y) {
; CHECK-LABEL: @neg_neg_extra_use_y(
-; CHECK-NEXT: [[NEGX:%.*]] = fsub double -0.000000e+00, [[X:%.*]]
; CHECK-NEXT: [[NEGY:%.*]] = fsub double -0.000000e+00, [[Y:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call double @llvm.minnum.f64(double [[NEGX]], double [[NEGY]])
+; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maxnum.f64(double [[X:%.*]], double [[Y]])
+; CHECK-NEXT: [[R:%.*]] = fsub double -0.000000e+00, [[TMP1]]
; CHECK-NEXT: call void @use(double [[NEGY]])
; CHECK-NEXT: ret double [[R]]
;