return new FPExtInst(NewCall, II->getType());
}
+ // max X, -X --> fabs X
+ // min X, -X --> -(fabs X)
+ // TODO: Remove one-use limitation? That is obviously better for max.
+ // It would be an extra instruction for min (fnabs), but that is
+ // still likely better for analysis and codegen.
+ if ((match(Arg0, m_OneUse(m_FNeg(m_Value(X)))) && Arg1 == X) ||
+ (match(Arg1, m_OneUse(m_FNeg(m_Value(X)))) && Arg0 == X)) {
+ Value *R = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, X, II);
+ if (IID == Intrinsic::minimum || IID == Intrinsic::minnum)
+ R = Builder.CreateFNegFMF(R, II);
+ return replaceInstUsesWith(*II, R);
+ }
+
break;
}
case Intrinsic::fmuladd: {
define float @negated_op(float %x) {
; CHECK-LABEL: @negated_op(
-; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[NEGX]])
-; CHECK-NEXT: ret float [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
+; CHECK-NEXT: ret float [[TMP1]]
;
%negx = fneg float %x
%r = call float @llvm.maximum.f32(float %x, float %negx)
define <2 x double> @negated_op_fmf_commute_vec(<2 x double> %x) {
; CHECK-LABEL: @negated_op_fmf_commute_vec(
-; CHECK-NEXT: [[NEGX:%.*]] = fneg <2 x double> [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call nnan ninf nsz <2 x double> @llvm.maximum.v2f64(<2 x double> [[NEGX]], <2 x double> [[X]])
-; CHECK-NEXT: ret <2 x double> [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz <2 x double> @llvm.fabs.v2f64(<2 x double> [[X:%.*]])
+; CHECK-NEXT: ret <2 x double> [[TMP1]]
;
%negx = fneg <2 x double> %x
%r = call nsz nnan ninf <2 x double> @llvm.maximum.v2f64(<2 x double> %negx, <2 x double> %x)
define float @negated_op(float %x) {
; CHECK-LABEL: @negated_op(
-; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.maxnum.f32(float [[NEGX]], float [[X]])
-; CHECK-NEXT: ret float [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
+; CHECK-NEXT: ret float [[TMP1]]
;
%negx = fneg float %x
%r = call float @llvm.maxnum.f32(float %negx, float %x)
define <2 x double> @negated_op_fmf_commute_vec(<2 x double> %x) {
; CHECK-LABEL: @negated_op_fmf_commute_vec(
-; CHECK-NEXT: [[NEGX:%.*]] = fneg <2 x double> [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call nnan ninf nsz <2 x double> @llvm.maxnum.v2f64(<2 x double> [[X]], <2 x double> [[NEGX]])
-; CHECK-NEXT: ret <2 x double> [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz <2 x double> @llvm.fabs.v2f64(<2 x double> [[X:%.*]])
+; CHECK-NEXT: ret <2 x double> [[TMP1]]
;
%negx = fneg <2 x double> %x
%r = call nsz nnan ninf <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double> %negx)
define float @negated_op(float %x) {
; CHECK-LABEL: @negated_op(
-; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[NEGX]])
-; CHECK-NEXT: ret float [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
+; CHECK-NEXT: [[TMP2:%.*]] = fneg float [[TMP1]]
+; CHECK-NEXT: ret float [[TMP2]]
;
%negx = fneg float %x
%r = call float @llvm.minimum.f32(float %x, float %negx)
define <2 x double> @negated_op_fmf_commute_vec(<2 x double> %x) {
; CHECK-LABEL: @negated_op_fmf_commute_vec(
-; CHECK-NEXT: [[NEGX:%.*]] = fneg <2 x double> [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call nnan ninf nsz <2 x double> @llvm.minimum.v2f64(<2 x double> [[NEGX]], <2 x double> [[X]])
-; CHECK-NEXT: ret <2 x double> [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz <2 x double> @llvm.fabs.v2f64(<2 x double> [[X:%.*]])
+; CHECK-NEXT: [[TMP2:%.*]] = fneg nnan ninf nsz <2 x double> [[TMP1]]
+; CHECK-NEXT: ret <2 x double> [[TMP2]]
;
%negx = fneg <2 x double> %x
%r = call nsz nnan ninf <2 x double> @llvm.minimum.v2f64(<2 x double> %negx, <2 x double> %x)
define float @negated_op(float %x) {
; CHECK-LABEL: @negated_op(
-; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.minnum.f32(float [[X]], float [[NEGX]])
-; CHECK-NEXT: ret float [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
+; CHECK-NEXT: [[TMP2:%.*]] = fneg float [[TMP1]]
+; CHECK-NEXT: ret float [[TMP2]]
;
%negx = fneg float %x
%r = call float @llvm.minnum.f32(float %x, float %negx)
define <2 x double> @negated_op_fmf_commute_vec(<2 x double> %x) {
; CHECK-LABEL: @negated_op_fmf_commute_vec(
-; CHECK-NEXT: [[NEGX:%.*]] = fneg <2 x double> [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call nnan ninf nsz <2 x double> @llvm.minnum.v2f64(<2 x double> [[NEGX]], <2 x double> [[X]])
-; CHECK-NEXT: ret <2 x double> [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz <2 x double> @llvm.fabs.v2f64(<2 x double> [[X:%.*]])
+; CHECK-NEXT: [[TMP2:%.*]] = fneg nnan ninf nsz <2 x double> [[TMP1]]
+; CHECK-NEXT: ret <2 x double> [[TMP2]]
;
%negx = fneg <2 x double> %x
%r = call nsz nnan ninf <2 x double> @llvm.minnum.v2f64(<2 x double> %negx, <2 x double> %x)