Index: lib/Target/PowerPC/PPC.td =================================================================== --- lib/Target/PowerPC/PPC.td +++ lib/Target/PowerPC/PPC.td @@ -167,6 +167,14 @@ "Enable POWER9 vector instructions", [FeatureISA3_0, FeatureP8Vector, FeatureP9Altivec]>; +def FeatureP9VSXScalarCmpMaxMin : SubtargetFeature<"power9-vsx-"# + "scalar-cmp-max-min", + "HasP9VSXScalarFPCompMinMax", + "true", + "Enable POWER9 VSX scalar "# + "instructions for FP "# + "compare, max, and min", + [FeatureP9Vector]>; /* Since new processors generally contain a superset of features of those that came before them, the idea is to make implementations of new processors @@ -200,7 +208,7 @@ list Power8FeatureList = !listconcat(Power7FeatureList, Power8SpecificFeatures); list Power9SpecificFeatures = - [FeatureP9Altivec, FeatureP9Vector, FeatureISA3_0]; + [FeatureP9VSXScalarCmpMaxMin, FeatureP9Altivec, FeatureP9Vector, FeatureISA3_0]; list Power9FeatureList = !listconcat(Power8FeatureList, Power9SpecificFeatures); } Index: lib/Target/PowerPC/PPCISelDAGToDAG.cpp =================================================================== --- lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -242,6 +242,19 @@ void transferMemOperands(SDNode *N, SDNode *Result); }; + + // The struct below is used by mayUseP9VSXScalarComparisonInstr to summarize + // information about the SELECT_CC node passed to it. + struct SelectCCSummary { + SDValue Ret0; + SDValue Ret1; + bool IsStrict; + SDValue Comp0; + SDValue Comp1; + EVT RetType; + bool Leave; + ISD::CondCode CC; + } ; } /// InsertVRSaveCode - Once the entire function has been instruction selected, @@ -458,6 +471,109 @@ && isInt32Immediate(N->getOperand(1).getNode(), Imm); } +// This function looks for specific patterns that can be replaced by +// ISA 3.0 instructions. There are two main pattern sets that we check for. +// The first set is some vairations of +// select_cc t5, t6, t2, t4, setogt:ch +// The key property here is that all first four operands of select_cc are +// float and double. So we compare FP numbers to select from FP numbers. +// The second set are variations of +// t17: i1 = setcc t4, t2, setge:ch +// t19: i1 = setcc t4, t2, seto:ch +// t20: i1 = and t17, t19 +// t23: f64 = select_cc t20, Constant:i1<0>, t4, t2, setne:ch +// Here we also compare FPs to select from FPs, but the comparison is done +// through a more complicated pattern which is a result of expansion of +// some condition codes during operation legalization. +static bool mayUseP9VSXScalarComparisonInstr(SDNode *N, SelectCCSummary &Summary) { + + assert((N->getOpcode() == ISD::SELECT_CC) && "Expected SELECT_CC node."); + + if (N->getValueType(0) != MVT::f64 && N->getValueType(0) != MVT::f32) + return false; + + + Summary.RetType = N->getValueType(0); + Summary.Ret0 = N->getOperand(2); + Summary.Ret1 = N->getOperand(3); + + ISD::CondCode CC = cast(N->getOperand(4))->get(); + + Summary.CC = ISD::CondCode::SETO; + Summary.Leave = false; + if (N->getOperand(0).getValueType() == MVT::f32 || + N->getOperand(0).getValueType() == MVT::f64) { + + if (CC == ISD::CondCode::SETOEQ || CC == ISD::CondCode::SETEQ ) { + Summary.Leave = true; // Will handle this in tablegen. + return true; + } + + Summary.IsStrict = true; + + switch (CC) { + case ISD::CondCode::SETNE: + Summary.CC = ISD::CondCode::SETNE; + std::swap(Summary.Ret0, Summary.Ret1); + // fall-through + case ISD::CondCode::SETGE: + Summary.IsStrict = false; + // fall-through + case ISD::CondCode::SETOGT: + case ISD::CondCode::SETGT: + Summary.Comp0 = N->getOperand(0); + Summary.Comp1 = N->getOperand(1); + break; + case ISD::CondCode::SETLE: + Summary.IsStrict = false; + // fall-through + case ISD::CondCode::SETOLT: + case ISD::CondCode::SETLT: + Summary.Comp0 = N->getOperand(1); + Summary.Comp1 = N->getOperand(0); + break; + default: return false; + } + } else if (N->getOperand(0).getValueType() == MVT::i1) { + ConstantSDNode *N1C = dyn_cast(N->getOperand(1)); + if (!N1C || ! N1C->getConstantIntValue()->isZero() || + N->getOperand(0).getOpcode() != ISD::AND || + N->getOperand(0).getOperand(0).getOpcode() != ISD::SETCC || + N->getOperand(0).getOperand(1).getOpcode() != ISD::SETCC) + return false; + + ISD::CondCode CC1 = cast + (N->getOperand(0).getOperand(1). + getOperand(2))->get(); + + if (CC1 != ISD::CondCode::SETO) return false; + + ISD::CondCode CC0 = cast + (N->getOperand(0).getOperand(0). + getOperand(2))->get(); + + Summary.IsStrict = false; + switch (CC0) { + case ISD::CondCode::SETNE: + Summary.CC = ISD::CondCode::SETNE; + std::swap(Summary.Ret0, Summary.Ret1); + // fall-through + case ISD::CondCode::SETGE: + Summary.Comp0 = N->getOperand(0).getOperand(0).getOperand(0); + Summary.Comp1 = N->getOperand(0).getOperand(0).getOperand(1); + break; + case ISD::CondCode::SETLE: + Summary.Comp0 = N->getOperand(0).getOperand(0).getOperand(1); + Summary.Comp1 = N->getOperand(0).getOperand(0).getOperand(0); + break; + default: + return false; + } + } else return false; + + return true; +} + void PPCDAGToDAGISel::selectFrameIndex(SDNode *SN, SDNode *N, unsigned Offset) { SDLoc dl(SN); int FI = cast(N)->getIndex(); @@ -2765,6 +2881,59 @@ return; } case ISD::SELECT_CC: { + + if (PPCSubTarget->hasP9VSXScalarFPCompMinMax()) { + SelectCCSummary Summary; + if (mayUseP9VSXScalarComparisonInstr(N, Summary)) { + if (Summary.Leave) break; // Will be handled in tablegen. + + unsigned SelectOpcode = (Summary.RetType == MVT::f32) ? + PPC::XXSEL_SP : PPC::XXSEL_DP; + + if (Summary.CC == ISD::CondCode::SETNE) { + unsigned CmpOpcode = (Summary.Comp0->getValueType(0) == MVT::f32) ? + PPC::XSCMPEQDP_SP : PPC::XSCMPEQDP; + + SDNode *mask = CurDAG->getMachineNode(CmpOpcode, dl, MVT::v2i64, + Summary.Comp0, Summary.Comp1); + CurDAG->SelectNodeTo(N, SelectOpcode, Summary.RetType, + Summary.Ret0, Summary.Ret1, SDValue(mask, 0)); + return; + } + if (Summary.Comp0 == Summary.Ret0 && Summary.Comp1 == Summary.Ret1) { + unsigned MaxOpcode = (Summary.RetType == MVT::f32) ? + PPC::XSMAXCDP_SP : PPC::XSMAXCDP; + CurDAG->SelectNodeTo(N, MaxOpcode, Summary.RetType, + Summary.Ret0, Summary.Ret1); + return; + } + else if (Summary.Comp0 == Summary.Ret1 && Summary.Comp1 == Summary.Ret0) { + unsigned MinOpcode = (Summary.RetType == MVT::f32) ? + PPC::XSMINCDP_SP : PPC::XSMINCDP; + CurDAG->SelectNodeTo(N, MinOpcode, Summary.RetType, + Summary.Ret0, Summary.Ret1); + return; + } + else if (CurDAG->getTarget().Options.NoNaNsFPMath) { + SDNode *mask = nullptr; + if (Summary.IsStrict) { + unsigned CmpOpcode = (Summary.Comp0->getValueType(0) == MVT::f32) ? + PPC::XSCMPGTDP_SP : PPC::XSCMPGTDP; + mask = CurDAG->getMachineNode(CmpOpcode, dl, MVT::v2i64, + Summary.Comp0, Summary.Comp1); + } else { + unsigned CmpOpcode = (Summary.Comp0->getValueType(0) == MVT::f32) ? + PPC::XSCMPGEDP_SP : PPC::XSCMPGEDP; + mask = CurDAG->getMachineNode(CmpOpcode, dl, MVT::v2i64, + Summary.Comp0, Summary.Comp1); + } + CurDAG->SelectNodeTo(N, SelectOpcode, Summary.RetType, + Summary.Ret0, Summary.Ret1, SDValue(mask, 0)); + return; + } + } + } + ISD::CondCode CC = cast(N->getOperand(4))->get(); EVT PtrVT = CurDAG->getTargetLoweringInfo().getPointerTy(CurDAG->getDataLayout()); Index: lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCISelLowering.cpp +++ lib/Target/PowerPC/PPCISelLowering.cpp @@ -6248,6 +6248,10 @@ /// LowerSELECT_CC - Lower floating point select_cc's into fsel instruction when /// possible. SDValue PPCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { + + if (Subtarget.hasP9VSXScalarFPCompMinMax()) + return Op; + // Not FP? Not a fsel. if (!Op.getOperand(0).getValueType().isFloatingPoint() || !Op.getOperand(2).getValueType().isFloatingPoint()) Index: lib/Target/PowerPC/PPCInstrVSX.td =================================================================== --- lib/Target/PowerPC/PPCInstrVSX.td +++ lib/Target/PowerPC/PPCInstrVSX.td @@ -770,6 +770,15 @@ (outs vsrc:$XT), (ins vsrc:$XA, vsrc:$XB, vsrc:$XC), "xxsel $XT, $XA, $XB, $XC", IIC_VecPerm, []>; + let isCodeGenOnly = 1 in { + def XXSEL_DP : XX4Form<60, 3, + (outs vsfrc:$XT), (ins vsfrc:$XA, vsfrc:$XB, vsrc:$XC), + "xxsel $XT, $XA, $XB, $XC", IIC_VecPerm, []>; + def XXSEL_SP : XX4Form<60, 3, + (outs vssrc:$XT), (ins vssrc:$XA, vssrc:$XB, vsrc:$XC), + "xxsel $XT, $XA, $XB, $XC", IIC_VecPerm, []>; + } + def XXSLDWI : XX3Form_2<60, 2, (outs vsrc:$XT), (ins vsrc:$XA, vsrc:$XB, u2imm:$SHW), "xxsldwi $XT, $XA, $XB, $SHW", IIC_VecPerm, []>; @@ -1803,6 +1812,7 @@ // The following VSX instructions were introduced in Power ISA 3.0 def HasP9Vector : Predicate<"PPCSubTarget->hasP9Vector()">; +def HasP9VSXScalarFPCompMinMax : Predicate<"PPCSubTarget->hasP9VSXScalarFPCompMinMax()">; let Predicates = [HasP9Vector] in { // [PO VRT XO VRB XO /] @@ -1916,13 +1926,54 @@ // Use vsrc for XT, because the entire register of XT is set. // XT.dword[1] = 0x0000_0000_0000_0000 def XSCMPEQDP : XX3_XT5_XA5_XB5<60, 3, "xscmpeqdp", vsrc, vsfrc, vsfrc, - IIC_FPCompare, []>; + IIC_FPCompare, []>, + Requires<[HasP9VSXScalarFPCompMinMax]>; def XSCMPGEDP : XX3_XT5_XA5_XB5<60, 19, "xscmpgedp", vsrc, vsfrc, vsfrc, - IIC_FPCompare, []>; + IIC_FPCompare, []>, + Requires<[HasP9VSXScalarFPCompMinMax]>; def XSCMPGTDP : XX3_XT5_XA5_XB5<60, 11, "xscmpgtdp", vsrc, vsfrc, vsfrc, - IIC_FPCompare, []>; + IIC_FPCompare, []>, + Requires<[HasP9VSXScalarFPCompMinMax]>; def XSCMPNEDP : XX3_XT5_XA5_XB5<60, 27, "xscmpnedp", vsrc, vsfrc, vsfrc, - IIC_FPCompare, []>; + IIC_FPCompare, []>, + Requires<[HasP9VSXScalarFPCompMinMax]>; + + let isCodeGenOnly = 1 in { + def XSCMPEQDP_SP : XX3_XT5_XA5_XB5<60, 3, "xscmpeqdp", vsrc, vssrc, vssrc, + IIC_FPCompare, []>, + Requires<[HasP9VSXScalarFPCompMinMax]>; + def XSCMPGEDP_SP : XX3_XT5_XA5_XB5<60, 19, "xscmpgedp", vsrc, vssrc, vssrc, + IIC_FPCompare, []>, + Requires<[HasP9VSXScalarFPCompMinMax]>; + def XSCMPGTDP_SP : XX3_XT5_XA5_XB5<60, 11, "xscmpgtdp", vsrc, vssrc, vssrc, + IIC_FPCompare, []>, + Requires<[HasP9VSXScalarFPCompMinMax]>; + } + + def : Pat <(f64 (selectcc f64:$XC, f64:$XD, f64:$XA, f64:$XB, SETOEQ )), + (XXSEL_DP $XA, $XB, (XSCMPEQDP $XC, $XD))>; + + def : Pat <(f64 (selectcc f64:$XC, f64:$XD, f64:$XA, f64:$XB, SETEQ )), + (XXSEL_DP $XA, $XB, (XSCMPEQDP $XC, $XD))>; + + def : Pat <(f32 (selectcc f32:$XC, f32:$XD, f32:$XA, f32:$XB, SETOEQ )), + (XXSEL_SP $XA, $XB, (XSCMPEQDP_SP $XC, $XD))>; + + def : Pat <(f32 (selectcc f32:$XC, f32:$XD, f32:$XA, f32:$XB, SETEQ )), + (XXSEL_SP $XA, $XB, (XSCMPEQDP_SP $XC, $XD))>; + + def : Pat <(f64 (selectcc f32:$XC, f32:$XD, f64:$XA, f64:$XB, SETOEQ )), + (XXSEL_DP $XA, $XB, (XSCMPEQDP_SP $XC, $XD))>; + + def : Pat <(f64 (selectcc f32:$XC, f32:$XD, f64:$XA, f64:$XB, SETEQ )), + (XXSEL_DP $XA, $XB, (XSCMPEQDP_SP $XC, $XD))>; + + def : Pat <(f32 (selectcc f64:$XC, f64:$XD, f32:$XA, f32:$XB, SETOEQ )), + (XXSEL_SP $XA, $XB, (XSCMPEQDP $XC, $XD))>; + + def : Pat <(f32 (selectcc f64:$XC, f64:$XD, f32:$XA, f32:$XB, SETEQ )), + (XXSEL_SP $XA, $XB, (XSCMPEQDP $XC, $XD))>; + // Vector Compare Not Equal def XVCMPNEDP : XX3Form_Rc<60, 123, (outs vsrc:$XT), (ins vsrc:$XA, vsrc:$XB), @@ -2056,14 +2107,33 @@ // Maximum/Minimum Type-C/Type-J DP // XT.dword[1] = 0xUUUU_UUUU_UUUU_UUUU, so we use vsrc for XT - def XSMAXCDP : XX3_XT5_XA5_XB5<60, 128, "xsmaxcdp", vsrc, vsfrc, vsfrc, - IIC_VecFP, []>; + def XSMAXCDP : XX3_XT5_XA5_XB5<60, 128, "xsmaxcdp", vsfrc, vsfrc, vsfrc, + IIC_VecFP, []>, + Requires<[HasP9VSXScalarFPCompMinMax]>; def XSMAXJDP : XX3_XT5_XA5_XB5<60, 144, "xsmaxjdp", vsrc, vsfrc, vsfrc, - IIC_VecFP, []>; - def XSMINCDP : XX3_XT5_XA5_XB5<60, 136, "xsmincdp", vsrc, vsfrc, vsfrc, - IIC_VecFP, []>; + IIC_VecFP, []>, + Requires<[HasP9VSXScalarFPCompMinMax]>; + def XSMINCDP : XX3_XT5_XA5_XB5<60, 136, "xsmincdp", vsfrc, vsfrc, vsfrc, + IIC_VecFP, []>, + Requires<[HasP9VSXScalarFPCompMinMax]>; def XSMINJDP : XX3_XT5_XA5_XB5<60, 152, "xsminjdp", vsrc, vsfrc, vsfrc, - IIC_VecFP, []>; + IIC_VecFP, []>, + Requires<[HasP9VSXScalarFPCompMinMax]>; + + let isCodeGenOnly = 1 in { + def XSMAXCDP_SP : XX3_XT5_XA5_XB5<60, 128, "xsmaxcdp", vssrc, vssrc, vssrc, + IIC_VecFP, []>, + Requires<[HasP9VSXScalarFPCompMinMax]>; + def XSMAXJDP_SP : XX3_XT5_XA5_XB5<60, 144, "xsmaxjdp", vsrc, vssrc, vssrc, + IIC_VecFP, []>, + Requires<[HasP9VSXScalarFPCompMinMax]>; + def XSMINCDP_SP : XX3_XT5_XA5_XB5<60, 136, "xsmincdp", vssrc, vssrc, vssrc, + IIC_VecFP, []>, + Requires<[HasP9VSXScalarFPCompMinMax]>; + def XSMINJDP_SP : XX3_XT5_XA5_XB5<60, 152, "xsminjdp", vsrc, vssrc, vssrc, + IIC_VecFP, []>, + Requires<[HasP9VSXScalarFPCompMinMax]>; + } //===--------------------------------------------------------------------===// Index: lib/Target/PowerPC/PPCSubtarget.h =================================================================== --- lib/Target/PowerPC/PPCSubtarget.h +++ lib/Target/PowerPC/PPCSubtarget.h @@ -132,6 +132,7 @@ bool HasFusion; bool HasFloat128; bool IsISA3_0; + bool HasP9VSXScalarFPCompMinMax; POPCNTDKind HasPOPCNTD; @@ -275,6 +276,9 @@ bool hasFusion() const { return HasFusion; } bool hasFloat128() const { return HasFloat128; } bool isISA3_0() const { return IsISA3_0; } + bool hasP9VSXScalarFPCompMinMax() const { + return HasP9VSXScalarFPCompMinMax; + } POPCNTDKind hasPOPCNTD() const { return HasPOPCNTD; } Index: lib/Target/PowerPC/PPCSubtarget.cpp =================================================================== --- lib/Target/PowerPC/PPCSubtarget.cpp +++ lib/Target/PowerPC/PPCSubtarget.cpp @@ -105,6 +105,7 @@ HasFusion = false; HasFloat128 = false; IsISA3_0 = false; + HasP9VSXScalarFPCompMinMax = false; HasPOPCNTD = POPCNTD_Unavailable; } Index: test/CodeGen/PowerPC/vsx-p9-maxmin.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/vsx-p9-maxmin.ll @@ -0,0 +1,1536 @@ +; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: -mcpu=pwr9 -mattr=+power9-vsx-scalar-cmp-max-min < %s | FileCheck %s +; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: -mcpu=pwr9 -mattr=-power9-vsx-scalar-cmp-max-min < %s \ +; RUN: | FileCheck --check-prefix DISABLED %s + +attributes #1 = {"no-nans-fp-math"="true"} + +attributes #2 = {"no-nans-fp-math"="false"} + +; This file contains a total of 104 tests in three different parts. Each part +; starts with a comment describing combinations of tests covered. First part +; has 64 tests. Second part has 32 tests. Last part includes 8 tests. +; The second test for disabled case is done only once for each instruction + +; There are 64 testcases for max/min. 2 data types (float, double), +; 8 condition codes, 2 operations (max, min), 2 no-nan status (#1, #2). + +define double @max_test1(double %x, double %y) #1 { + +; CHECK-LABEL: @max_test1 +; DISABLED-LABEL: @max_test1 + +entry: + %cmp = fcmp ogt double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK: xsmaxcdp 1, 1, 2 +; DISABLED-NOT: xsmaxcdp +; CHECK: blr +; DISABLED: blr + +} + +define double @max_test2(double %x, double %y) #1 { + +; CHECK-LABEL: @max_test2 + +entry: + %cmp = fcmp olt double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xsmaxcdp 1, 2, 1 +; CHECK: blr + +} + +define double @min_test1(double %x, double %y) #1 { + +; CHECK-LABEL: @min_test1 + +entry: + %cmp = fcmp ogt double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xsmincdp 1, 2, 1 +; CHECK: blr + +} + +define double @min_test2(double %x, double %y) #1 { + +; CHECK-LABEL: @min_test2 +; DISABLED-LABEL: @min_test2 + +entry: + %cmp = fcmp olt double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK: xsmincdp 1, 1, 2 +; DISABLED-NOT: xsmincdp +; CHECK: blr +; DISABLED: blr + +} + +define float @max_test1_float(float %x, float %y) #1 { + +; CHECK-LABEL: @max_test1_float + +entry: + %cmp = fcmp ogt float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK: xsmaxcdp 1, 1, 2 +; CHECK: blr + +} + +define float @max_test2_float(float %x, float %y) #1 { + +; CHECK-LABEL: @max_test2_float + +entry: + %cmp = fcmp olt float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xsmaxcdp 1, 2, 1 +; CHECK: blr + +} + +define float @min_test1_float(float %x, float %y) #1 { + +; CHECK-LABEL: @min_test1_float + +entry: + %cmp = fcmp ogt float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xsmincdp 1, 2, 1 +; CHECK: blr + +} + +define float @min_test2_float(float %x, float %y) #1 { + +; CHECK-LABEL: @min_test2_float + +entry: + %cmp = fcmp olt float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK: xsmincdp 1, 1, 2 +; CHECK: blr + +} + + +define double @max_test1_eq(double %x, double %y) #1 { + +; CHECK-LABEL: @max_test1_eq + +entry: + %cmp = fcmp oge double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK: xsmaxcdp 1, 1, 2 +; CHECK: blr + +} + +define double @max_test2_eq(double %x, double %y) #1 { + +; CHECK-LABEL: @max_test2_eq + +entry: + %cmp = fcmp ole double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xsmaxcdp 1, 2, 1 +; CHECK: blr + +} + +define double @min_test1_eq(double %x, double %y) #1 { + +; CHECK-LABEL: @min_test1_eq + +entry: + %cmp = fcmp oge double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xsmincdp 1, 2, 1 +; CHECK: blr + +} + +define double @min_test2_eq(double %x, double %y) #1 { + +; CHECK-LABEL: @min_test2_eq + +entry: + %cmp = fcmp ole double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK: xsmincdp 1, 1, 2 +; CHECK: blr + +} + +define float @max_test1_float_eq(float %x, float %y) #1 { + +; CHECK-LABEL: @max_test1_float_eq + +entry: + %cmp = fcmp oge float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK: xsmaxcdp 1, 1, 2 +; CHECK: blr + +} + +define float @max_test2_float_eq(float %x, float %y) #1 { + +; CHECK-LABEL: @max_test2_float_eq + +entry: + %cmp = fcmp ole float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xsmaxcdp 1, 2, 1 +; CHECK: blr + +} + +define float @min_test1_float_eq(float %x, float %y) #1 { + +; CHECK-LABEL: @min_test1_float_eq + +entry: + %cmp = fcmp oge float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xsmincdp 1, 2, 1 +; CHECK: blr + +} + +define float @min_test2_float_eq(float %x, float %y) #1 { + +; CHECK-LABEL: @min_test2_float_eq + +entry: + %cmp = fcmp ole float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK: xsmincdp 1, 1, 2 +; CHECK: blr + +} + +define double @nan_max_test1(double %x, double %y) #2 { + +; CHECK-LABEL: @nan_max_test1 + +entry: + %cmp = fcmp ogt double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK: xsmaxcdp 1, 1, 2 +; CHECK: blr + +} + +define double @nan_max_test2(double %x, double %y) #2 { + +; CHECK-LABEL: @nan_max_test2 + +entry: + %cmp = fcmp olt double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xsmaxcdp 1, 2, 1 +; CHECK: blr + +} + +define double @nan_min_test1(double %x, double %y) #2 { + +; CHECK-LABEL: @nan_min_test1 + +entry: + %cmp = fcmp ogt double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xsmincdp 1, 2, 1 +; CHECK: blr + +} + +define double @nan_min_test2(double %x, double %y) #2 { + +; CHECK-LABEL: @nan_min_test2 + +entry: + %cmp = fcmp olt double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK: xsmincdp 1, 1, 2 +; CHECK: blr + +} + +define float @nan_max_test1_float(float %x, float %y) #2 { + +; CHECK-LABEL: @nan_max_test1_float + +entry: + %cmp = fcmp ogt float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK: xsmaxcdp 1, 1, 2 +; CHECK: blr + +} + +define float @nan_max_test2_float(float %x, float %y) #2 { + +; CHECK-LABEL: @nan_max_test2_float + +entry: + %cmp = fcmp olt float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xsmaxcdp 1, 2, 1 +; CHECK: blr + +} + +define float @nan_min_test1_float(float %x, float %y) #2 { + +; CHECK-LABEL: @nan_min_test1_float + +entry: + %cmp = fcmp ogt float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xsmincdp 1, 2, 1 +; CHECK: blr + +} + +define float @nan_min_test2_float(float %x, float %y) #2 { + +; CHECK-LABEL: @nan_min_test2_float + +entry: + %cmp = fcmp olt float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK: xsmincdp 1, 1, 2 +; CHECK: blr + +} + + +define double @nan_max_test1_eq(double %x, double %y) #2 { + +; CHECK-LABEL: @nan_max_test1_eq + +entry: + %cmp = fcmp oge double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK: xsmaxcdp 1, 1, 2 +; CHECK: blr + +} + +define double @nan_max_test2_eq(double %x, double %y) #2 { + +; CHECK-LABEL: @nan_max_test2_eq + +entry: + %cmp = fcmp ole double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xsmaxcdp 1, 2, 1 +; CHECK: blr + +} + +define double @nan_min_test1_eq(double %x, double %y) #2 { + +; CHECK-LABEL: @nan_min_test1_eq + +entry: + %cmp = fcmp oge double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xsmincdp 1, 2, 1 +; CHECK: blr + +} + +define double @nan_min_test2_eq(double %x, double %y) #2 { + +; CHECK-LABEL: @nan_min_test2_eq + +entry: + %cmp = fcmp ole double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK: xsmincdp 1, 1, 2 +; CHECK: blr + +} + +define float @nan_max_test1_float_eq(float %x, float %y) #2 { + +; CHECK-LABEL: @nan_max_test1_float_eq + +entry: + %cmp = fcmp oge float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK: xsmaxcdp 1, 1, 2 +; CHECK: blr + +} + +define float @nan_max_test2_float_eq(float %x, float %y) #2 { + +; CHECK-LABEL: @nan_max_test2_float_eq + +entry: + %cmp = fcmp ole float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xsmaxcdp 1, 2, 1 +; CHECK: blr + +} + +define float @nan_min_test1_float_eq(float %x, float %y) #2 { + +; CHECK-LABEL: @nan_min_test1_float_eq + +entry: + %cmp = fcmp oge float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xsmincdp 1, 2, 1 +; CHECK: blr + +} + +define float @nan_min_test2_float_eq(float %x, float %y) #2 { + +; CHECK-LABEL: @nan_min_test2_float_eq + +entry: + %cmp = fcmp ole float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK: xsmincdp 1, 1, 2 +; CHECK: blr + +} + +define double @max_test1_unordered(double %x, double %y) #1 { + +; CHECK-LABEL: @max_test1_unordered + +entry: + %cmp = fcmp ugt double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK: xsmaxcdp 1, 1, 2 +; CHECK: blr + +} + +define double @max_test2_unordered(double %x, double %y) #1 { + +; CHECK-LABEL: @max_test2_unordered + +entry: + %cmp = fcmp ult double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xsmaxcdp 1, 2, 1 +; CHECK: blr + +} + +define double @min_test1_unordered(double %x, double %y) #1 { + +; CHECK-LABEL: @min_test1_unordered + +entry: + %cmp = fcmp ugt double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xsmincdp 1, 2, 1 +; CHECK: blr + +} + +define double @min_test2_unordered(double %x, double %y) #1 { + +; CHECK-LABEL: @min_test2_unordered + +entry: + %cmp = fcmp ult double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK: xsmincdp 1, 1, 2 +; CHECK: blr + +} + +define float @max_test1_float_unordered(float %x, float %y) #1 { + +; CHECK-LABEL: @max_test1_float_unordered + +entry: + %cmp = fcmp ugt float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK: xsmaxcdp 1, 1, 2 +; CHECK: blr + +} + +define float @max_test2_float_unordered(float %x, float %y) #1 { + +; CHECK-LABEL: @max_test2_float_unordered + +entry: + %cmp = fcmp ult float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xsmaxcdp 1, 2, 1 +; CHECK: blr + +} + +define float @min_test1_float_unordered(float %x, float %y) #1 { + +; CHECK-LABEL: @min_test1_float_unordered + +entry: + %cmp = fcmp ugt float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xsmincdp 1, 2, 1 +; CHECK: blr + +} + +define float @min_test2_float_unordered(float %x, float %y) #1 { + +; CHECK-LABEL: @min_test2_float_unordered + +entry: + %cmp = fcmp ult float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK: xsmincdp 1, 1, 2 +; CHECK: blr + +} + + +define double @max_test1_eq_unordered(double %x, double %y) #1 { + +; CHECK-LABEL: @max_test1_eq_unordered + +entry: + %cmp = fcmp uge double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK: xsmaxcdp 1, 1, 2 +; CHECK: blr + +} + +define double @max_test2_eq_unordered(double %x, double %y) #1 { + +; CHECK-LABEL: @max_test2_eq_unordered + +entry: + %cmp = fcmp ule double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xsmaxcdp 1, 2, 1 +; CHECK: blr + +} + +define double @min_test1_eq_unordered(double %x, double %y) #1 { + +; CHECK-LABEL: @min_test1_eq_unordered + +entry: + %cmp = fcmp uge double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xsmincdp 1, 2, 1 +; CHECK: blr + +} + +define double @min_test2_eq_unordered(double %x, double %y) #1 { + +; CHECK-LABEL: @min_test2_eq_unordered + +entry: + %cmp = fcmp ule double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK: xsmincdp 1, 1, 2 +; CHECK: blr + +} + +define float @max_test1_float_eq_unordered(float %x, float %y) #1 { + +; CHECK-LABEL: @max_test1_float_eq_unordered + +entry: + %cmp = fcmp uge float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK: xsmaxcdp 1, 1, 2 +; CHECK: blr + +} + +define float @max_test2_float_eq_unordered(float %x, float %y) #1 { + +; CHECK-LABEL: @max_test2_float_eq_unordered + +entry: + %cmp = fcmp ule float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xsmaxcdp 1, 2, 1 +; CHECK: blr + +} + +define float @min_test1_float_eq_unordered(float %x, float %y) #1 { + +; CHECK-LABEL: @min_test1_float_eq_unordered + +entry: + %cmp = fcmp uge float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xsmincdp 1, 2, 1 +; CHECK: blr + +} + +define float @min_test2_float_eq_unordered(float %x, float %y) #1 { + +; CHECK-LABEL: @min_test2_float_eq_unordered + +entry: + %cmp = fcmp ule float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK: xsmincdp 1, 1, 2 +; CHECK: blr + +} + +define double @max_test1_unordered_nan(double %x, double %y) #2 { + +; CHECK-LABEL: @max_test1_unordered_nan + +entry: + %cmp = fcmp ugt double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK-NOT: xsmaxcdp +; CHECK: blr + +} + +define double @max_test2_unordered_nan(double %x, double %y) #2 { + +; CHECK-LABEL: @max_test2_unordered_nan + +entry: + %cmp = fcmp ult double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK-NOT: xsmaxcdp +; CHECK: blr + +} + +define double @min_test1_unordered_nan(double %x, double %y) #2 { + +; CHECK-LABEL: @min_test1_unordered_nan + +entry: + %cmp = fcmp ugt double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK-NOT: xsmincdp +; CHECK: blr + +} + +define double @min_test2_unordered_nan(double %x, double %y) #2 { + +; CHECK-LABEL: @min_test2_unordered_nan + +entry: + %cmp = fcmp ult double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK-NOT: xsmincdp +; CHECK: blr + +} + +define float @max_test1_float_unordered_nan(float %x, float %y) #2 { + +; CHECK-LABEL: @max_test1_float_unordered_nan + +entry: + %cmp = fcmp ugt float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK-NOT: xsmaxcdp +; CHECK: blr + +} + +define float @max_test2_float_unordered_nan(float %x, float %y) #2 { + +; CHECK-LABEL: @max_test2_float_unordered_nan + +entry: + %cmp = fcmp ult float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK-NOT: xsmaxcdp +; CHECK: blr + +} + +define float @min_test1_float_unordered_nan(float %x, float %y) #2 { + +; CHECK-LABEL: @min_test1_float_unordered_nan + +entry: + %cmp = fcmp ugt float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK-NOT: xsmincdp +; CHECK: blr + +} + +define float @min_test2_float_unordered_nan(float %x, float %y) #2 { + +; CHECK-LABEL: @min_test2_float_unordered_nan + +entry: + %cmp = fcmp ult float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK-NOT: xsmincdp +; CHECK: blr + +} + +define double @max_test1_eq_unordered_nan(double %x, double %y) #2 { + +; CHECK-LABEL: @max_test1_eq_unordered_nan + +entry: + %cmp = fcmp uge double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK-NOT: xsmaxcdp +; CHECK: blr + +} + +define double @max_test2_eq_unordered_nan(double %x, double %y) #2 { + +; CHECK-LABEL: @max_test2_eq_unordered_nan + +entry: + %cmp = fcmp ule double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK-NOT: xsmaxcdp +; CHECK: blr + +} + +define double @min_test1_eq_unordered_nan(double %x, double %y) #2 { + +; CHECK-LABEL: @min_test1_eq_unordered_nan + +entry: + %cmp = fcmp uge double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK-NOT: xsmincdp +; CHECK: blr + +} + +define double @min_test2_eq_unordered_nan(double %x, double %y) #2 { + +; CHECK-LABEL: @min_test2_eq_unordered_nan + +entry: + %cmp = fcmp ule double %x, %y + %x.y = select i1 %cmp, double %x, double %y + ret double %x.y + +; CHECK-NOT: xsmincdp +; CHECK: blr + +} + +define float @max_test1_float_eq_unordered_nan(float %x, float %y) #2 { + +; CHECK-LABEL: @max_test1_float_eq_unordered_nan + +entry: + %cmp = fcmp uge float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK-NOT: xsmaxcdp +; CHECK: blr + +} + +define float @max_test2_float_eq_unordered_nan(float %x, float %y) #2 { + +; CHECK-LABEL: @max_test2_float_eq_unordered_nan + +entry: + %cmp = fcmp ule float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK-NOT: xsmaxcdp +; CHECK: blr + +} + +define float @min_test1_float_eq_unordered_nan(float %x, float %y) #2 { + +; CHECK-LABEL: @min_test1_float_eq_unordered_nan + +entry: + %cmp = fcmp uge float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK-NOT: xsmincdp +; CHECK: blr + +} + +define float @min_test2_float_eq_unordered_nan(float %x, float %y) #2 { + +; CHECK-LABEL: @min_test2_float_eq_unordered_nan + +entry: + %cmp = fcmp ule float %x, %y + %x.y = select i1 %cmp, float %x, float %y + ret float %x.y + +; CHECK-NOT: xsmincdp +; CHECK: blr + +} + +; 32 more tests for the following combinations: 2 data types (float, double) +; 8 condition codes, and 2 non-status (#1, #2). + +define double @fast_double_ugt(double %x, double %y, double %a, double %b) #1 { + +; CHECK-LABEL: @fast_double_ugt +; DISABLED-LABEL: @fast_double_ugt + +entry: + %cmp = fcmp fast ugt double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK: xscmpgtdp [[MASK:[0-9]+]], 2, 1 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr +; DISABLED-NOT: xscmpgtdp +; DISABLED: blr + +} + +define double @nan_double_ugt(double %x, double %y, double %a, double %b) #2 { + +; CHECK-LABEL: @nan_double_ugt + +entry: + %cmp = fcmp fast ugt double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + +define double @fast_double_ult(double %x, double %y, double %a, double %b) #1 { + +; CHECK-LABEL: @fast_double_ult + +entry: + %cmp = fcmp fast ult double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK: xscmpgtdp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr + +} + +define double @nan_double_ult(double %x, double %y, double %a, double %b) #2 { + +; CHECK-LABEL: @nan_double_ult + +entry: + %cmp = fcmp fast ult double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + +define double @fast_double_ogt(double %x, double %y, double %a, double %b) #1 { + +; CHECK-LABEL: @fast_double_ogt + +entry: + %cmp = fcmp fast ogt double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK: xscmpgtdp [[MASK:[0-9]+]], 2, 1 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr + +} + +define double @nan_double_ogt(double %x, double %y, double %a, double %b) #2 { + +; CHECK-LABEL: @nan_double_ogt + +entry: + %cmp = fcmp fast ogt double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + +define double @fast_double_olt(double %x, double %y, double %a, double %b) #1 { + +; CHECK-LABEL: @fast_double_olt + +entry: + %cmp = fcmp fast olt double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK: xscmpgtdp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr + +} + +define double @nan_double_olt(double %x, double %y, double %a, double %b) #2 { + +; CHECK-LABEL: @nan_double_olt + +entry: + %cmp = fcmp fast olt double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + +define float @fast_float_ugt(float %x, float %y, float %a, float %b) #1 { + +; CHECK-LABEL: @fast_float_ugt + +entry: + %cmp = fcmp fast ugt float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK: xscmpgtdp [[MASK:[0-9]+]], 2, 1 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr + +} + +define float @nan_float_ugt(float %x, float %y, float %a, float %b) #2 { + +; CHECK-LABEL: @nan_float_ugt + +entry: + %cmp = fcmp fast ugt float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + +define float @fast_float_ult(float %x, float %y, float %a, float %b) #1 { + +; CHECK-LABEL: @fast_float_ult + +entry: + %cmp = fcmp fast ult float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK: xscmpgtdp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr + +} + +define float @nan_float_ult(float %x, float %y, float %a, float %b) #2 { + +; CHECK-LABEL: @nan_float_ult + +entry: + %cmp = fcmp fast ult float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + + +define float @fast_float_ogt(float %x, float %y, float %a, float %b) #1 { + +; CHECK-LABEL: @fast_float_ogt + +entry: + %cmp = fcmp fast ogt float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK: xscmpgtdp [[MASK:[0-9]+]], 2, 1 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr + +} + +define float @nan_float_ogt(float %x, float %y, float %a, float %b) #2 { + +; CHECK-LABEL: @nan_float_ogt + +entry: + %cmp = fcmp fast ogt float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + +define float @fast_float_olt(float %x, float %y, float %a, float %b) #1 { + +; CHECK-LABEL: @fast_float_olt + +entry: + %cmp = fcmp fast olt float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK: xscmpgtdp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr + +} + +define float @nan_float_olt(float %x, float %y, float %a, float %b) #2 { + +; CHECK-LABEL: @nan_float_olt + +entry: + %cmp = fcmp fast olt float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + +define double @fast_double_uge(double %x, double %y, double %a, double %b) #1 { + +; CHECK-LABEL: @fast_double_uge +; DISABLED-LABEL: @fast_double_uge + +entry: + %cmp = fcmp fast uge double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK: xscmpgedp [[MASK:[0-9]+]], 2, 1 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr +; DISABLED-NOT: xscmpgedp +; DISABLED: blr + +} + +define double @nan_double_uge(double %x, double %y, double %a, double %b) #2 { + +; CHECK-LABEL: @nan_double_uge + +entry: + %cmp = fcmp fast uge double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + +define double @fast_double_ule(double %x, double %y, double %a, double %b) #1 { + +; CHECK-LABEL: @fast_double_ule + +entry: + %cmp = fcmp fast ule double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK: xscmpgedp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr + +} + +define double @nan_double_ule(double %x, double %y, double %a, double %b) #2 { + +; CHECK-LABEL: @nan_double_ule + +entry: + %cmp = fcmp fast ule double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + +define double @fast_double_oge(double %x, double %y, double %a, double %b) #1 { + +; CHECK-LABEL: @fast_double_oge + +entry: + %cmp = fcmp fast oge double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK: xscmpgedp [[MASK:[0-9]+]], 2, 1 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr + +} + +define double @nan_double_oge(double %x, double %y, double %a, double %b) #2 { + +; CHECK-LABEL: @nan_double_oge + +entry: + %cmp = fcmp fast oge double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + +define double @fast_double_ole(double %x, double %y, double %a, double %b) #1 { + +; CHECK-LABEL: @fast_double_ole + +entry: + %cmp = fcmp fast ole double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK: xscmpgedp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr + +} + +define double @nan_double_ole(double %x, double %y, double %a, double %b) #2 { + +; CHECK-LABEL: @nan_double_ole + +entry: + %cmp = fcmp fast ole double %y, %x + %b.a = select i1 %cmp, double %b, double %a + ret double %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + +define float @fast_float_uge(float %x, float %y, float %a, float %b) #1 { + +; CHECK-LABEL: @fast_float_uge + +entry: + %cmp = fcmp fast uge float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK: xscmpgedp [[MASK:[0-9]+]], 2, 1 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr + +} + +define float @nan_float_uge(float %x, float %y, float %a, float %b) #2 { + +; CHECK-LABEL: @nan_float_uge + +entry: + %cmp = fcmp fast uge float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + +define float @fast_float_ule(float %x, float %y, float %a, float %b) #1 { + +; CHECK-LABEL: @fast_float_ule + +entry: + %cmp = fcmp fast ule float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK: xscmpgedp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr + +} + +define float @nan_float_ule(float %x, float %y, float %a, float %b) #2 { + +; CHECK-LABEL: @nan_float_ule + +entry: + %cmp = fcmp fast ule float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + + +define float @fast_float_oge(float %x, float %y, float %a, float %b) #1 { + +; CHECK-LABEL: @fast_float_oge + +entry: + %cmp = fcmp fast oge float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK: xscmpgedp [[MASK:[0-9]+]], 2, 1 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr + +} + +define float @nan_float_oge(float %x, float %y, float %a, float %b) #2 { + +; CHECK-LABEL: @nan_float_oge + +entry: + %cmp = fcmp fast oge float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + +define float @fast_float_ole(float %x, float %y, float %a, float %b) #1 { + +; CHECK-LABEL: @fast_float_ole + +entry: + %cmp = fcmp fast ole float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK: xscmpgedp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 4, 3, [[MASK]] +; CHECK: blr + +} + +define float @nan_float_ole(float %x, float %y, float %a, float %b) #2 { + +; CHECK-LABEL: @nan_float_ole + +entry: + %cmp = fcmp fast ole float %y, %x + %b.a = select i1 %cmp, float %b, float %a + ret float %b.a + +; CHECK-NOT: xscmpgtdp +; CHECK-NOT: xscmpgedp +; CHECK: blr + +} + +define double @one_test_fast(double %x, double %y) #1 { + +; CHECK-LABEL: @one_test_fast +; DISABLED-LABEL: @one_test_fast + +entry: + %cmp = fcmp one double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xscmpeqdp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 1, 2, [[MASK]] +; CHECK: blr +; DISABLED-NOT: xscmpeqdp +; DISABLED: blr + +} + +define double @one_test(double %x, double %y) #2 { + +; CHECK-LABEL: @one_test + +entry: + %cmp = fcmp one double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xscmpeqdp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 1, 2, [[MASK]] +; CHECK: blr + +} + +define double @oeq_test_fast(double %x, double %y) #1 { + +; CHECK-LABEL: @oeq_test_fast + +entry: + %cmp = fcmp oeq double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xscmpeqdp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 2, 1, [[MASK]] +; CHECK: blr + +} + +define double @oeq_test(double %x, double %y) #2 { + +; CHECK-LABEL: @oeq_test + +entry: + %cmp = fcmp oeq double %x, %y + %y.x = select i1 %cmp, double %y, double %x + ret double %y.x + +; CHECK: xscmpeqdp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 2, 1, [[MASK]] +; CHECK: blr + +} + +define float @one_test_fast_float(float %x, float %y) #1 { + +; CHECK-LABEL: @one_test_fast_float + +entry: + %cmp = fcmp one float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xscmpeqdp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 1, 2, [[MASK]] +; CHECK: blr + +} + +define float @one_test_float(float %x, float %y) #2 { + +; CHECK-LABEL: @one_test_float + +entry: + %cmp = fcmp one float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xscmpeqdp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 1, 2, [[MASK]] +; CHECK: blr + +} + +define float @oeq_test_fast_float(float %x, float %y) #1 { + +; CHECK-LABEL: @oeq_test_fast_float + +entry: + %cmp = fcmp oeq float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xscmpeqdp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 2, 1, [[MASK]] +; CHECK: blr + +} + +define float @oeq_test_float(float %x, float %y) #2 { + +; CHECK-LABEL: @oeq_test_float + +entry: + %cmp = fcmp oeq float %x, %y + %y.x = select i1 %cmp, float %y, float %x + ret float %y.x + +; CHECK: xscmpeqdp [[MASK:[0-9]+]], 1, 2 +; CHECK: xxsel 1, 2, 1, [[MASK]] +; CHECK: blr + +}