Index: lib/Target/PowerPC/PPCISelDAGToDAG.cpp =================================================================== --- lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -242,6 +242,17 @@ SDNode *transferMemOperands(SDNode *N, SDNode *Result); }; + + 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 +469,91 @@ && isInt32Immediate(N->getOperand(1).getNode(), Imm); } +static bool useP9VSXScalarComparisonInstr(SDNode *N, SelectCCSummary &Summary) { + + 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); + case ISD::CondCode::SETGE: + Summary.IsStrict = false; + 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; + 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); + 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; +} + SDNode *PPCDAGToDAGISel::getFrameIndex(SDNode *SN, SDNode *N, unsigned Offset) { SDLoc dl(SN); int FI = cast(N)->getIndex(); @@ -2730,7 +2826,43 @@ CR0Reg, SRIdxVal, SDValue(AndI.getNode(), 1) /* glue */); } + case ISD::SELECT_CC: { + + if (PPCSubTarget->hasP9Vector()) { + SelectCCSummary Summary; + if (useP9VSXScalarComparisonInstr(N, Summary)) { + if (Summary.Leave) break; // Will be handled in tablegen. + if (Summary.CC == ISD::CondCode::SETNE) { + SDNode *mask = CurDAG->getMachineNode(PPC::XSCMPEQDP, dl, MVT::v2i64, + Summary.Comp0, Summary.Comp1); + return CurDAG->getMachineNode(PPC::XXSELS, dl, Summary.RetType, + Summary.Ret0, + Summary.Ret1, + SDValue(mask, 0)); + } + if (Summary.Comp0 == Summary.Ret0 && Summary.Comp1 == Summary.Ret1) + return CurDAG->getMachineNode(PPC::XSMAXCDP, dl, Summary.RetType, + Summary.Ret0, Summary.Ret1); + else if (Summary.Comp0 == Summary.Ret1 && Summary.Comp1 == Summary.Ret0) + return CurDAG->getMachineNode(PPC::XSMINCDP, dl, Summary.RetType, + Summary.Ret0, Summary.Ret1); + else if (CurDAG->getTarget().Options.NoNaNsFPMath) { + SDNode *mask = nullptr; + if (Summary.IsStrict) + mask = CurDAG->getMachineNode(PPC::XSCMPGTDP, dl, MVT::v2i64, + Summary.Comp0, Summary.Comp1); + else + mask = CurDAG->getMachineNode(PPC::XSCMPGEDP, dl, MVT::v2i64, + Summary.Comp0, Summary.Comp1); + return CurDAG->getMachineNode(PPC::XXSELS, dl, Summary.RetType, + Summary.Ret0, + Summary.Ret1, + SDValue(mask, 0)); + } + } + } + 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 @@ -6238,6 +6238,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.hasP9Vector()) + 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,11 @@ (outs vsrc:$XT), (ins vsrc:$XA, vsrc:$XB, vsrc:$XC), "xxsel $XT, $XA, $XB, $XC", IIC_VecPerm, []>; + let isCodeGenOnly = 1 in + def XXSELS : XX4Form<60, 3, + (outs vsfrc:$XT), (ins vsfrc:$XA, vsfrc:$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, []>; @@ -1921,6 +1926,13 @@ IIC_FPCompare, []>; def XSCMPNEDP : XX3_XT5_XA5_XB5<60, 27, "xscmpnedp", vsrc, vsfrc, vsfrc, IIC_FPCompare, []>; + + def : Pat <(f64 (selectcc f64:$XC, f64:$XD, f64:$XA, f64:$XB, SETOEQ )), + (XXSELS $XA, $XB, (XSCMPEQDP $XC, $XD))>; + + def : Pat <(f64 (selectcc f64:$XC, f64:$XD, f64:$XA, f64:$XB, SETEQ )), + (XXSELS $XA, $XB, (XSCMPEQDP $XC, $XD))>; + // Vector Compare Not Equal def XVCMPNEDP : XX3Form_Rc<60, 123, (outs vsrc:$XT), (ins vsrc:$XA, vsrc:$XB), @@ -2053,16 +2065,23 @@ //===--------------------------------------------------------------------===// // 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, [(set f64:$XT, + (selectcc f64:$XA, f64:$XB, + f64:$XA, f64:$XB, SETOGT))]>; 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, []>; + def XSMINCDP : XX3_XT5_XA5_XB5<60, 136, "xsmincdp", vsfrc, vsfrc, vsfrc, + IIC_VecFP, [(set f64:$XT, + (selectcc f64:$XA, f64:$XB, + f64:$XA, f64:$XB, SETOLT))]>; def XSMINJDP : XX3_XT5_XA5_XB5<60, 152, "xsminjdp", vsrc, vsfrc, vsfrc, IIC_VecFP, []>; + def : Pat <(f64 (selectcc f64:$XB, f64:$XA, f64:$XA, f64:$XB, SETOLT)), + (XSMAXCDP $XA, $XB)>; + def : Pat <(f64 (selectcc f64:$XB, f64:$XA, f64:$XA, f64:$XB, SETOGT)), + (XSMINCDP $XA, $XB)>; //===--------------------------------------------------------------------===// // Vector Byte-Reverse H/W/D/Q Word Index: test/CodeGen/PowerPC/vsx-p9.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/vsx-p9.ll @@ -0,0 +1,998 @@ +; RUN: llc -mcpu=pwr9 -mattr=+power9-vector < %s | FileCheck %s + +attributes #1 = {"no-nans-fp-math"="true"} + +attributes #2 = {"no-nans-fp-math"="false"} + +define double @max_test1(double %x, double %y) #1 { + +; CHECK-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 +; CHECK: 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 + +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 @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 @fast_max_test1(double %x, double %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_max_test2(double %x, double %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_min_test1(double %x, double %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_min_test2(double %x, double %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_max_test1_float(float %x, float %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_max_test2_float(float %x, float %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_min_test1_float(float %x, float %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_min_test2_float(float %x, float %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_max_test1_eq(double %x, double %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_max_test2_eq(double %x, double %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_min_test1_eq(double %x, double %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_min_test2_eq(double %x, double %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_max_test1_float_eq(float %x, float %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_max_test2_float_eq(float %x, float %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_min_test1_float_eq(float %x, float %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_min_test2_float_eq(float %x, float %y) #2 { + +; CHECK-LABEL: @fast_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 @fast_double_ugt(double %x, double %y, double %a, double %b) #1 { + +; CHECK-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 + +} + +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 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_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 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_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 + +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 + +} + +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 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_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 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_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 + +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 @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 + +} +