Index: lib/Target/PowerPC/PPCISelDAGToDAG.cpp =================================================================== --- lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -69,6 +69,7 @@ #define DEBUG_TYPE "ppc-codegen" +STATISTIC(NumMinMax, "Number select_cc changed to floating point min/max/cmp."); STATISTIC(NumSextSetcc, "Number of (sext(setcc)) nodes expanded into GPR sequence."); STATISTIC(NumZextSetcc, @@ -316,6 +317,18 @@ 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; // SELECT_CC value to select when condition matches + SDValue Ret1; // SELECT_CC value to select when condition does not match + bool IsStrict; // Flag describing whether the condition code is strict + SDValue Comp0; // Set to the larger value of the select compare values + SDValue Comp1; // Set to the smaller value of the select compare values + EVT RetType; // The return type of the SELECT_CC node + bool Leave; // Flag to state whether this node will be expanded in TableGen + ISD::CondCode CC; // The condition code of this SELECT_CC node +}; } // end anonymous namespace /// InsertVRSaveCode - Once the entire function has been instruction selected, @@ -517,6 +530,110 @@ && 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); + return true; + 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); + return true; + 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); + return true; + case ISD::CondCode::SETLE: + Summary.Comp0 = N->getOperand(0).getOperand(0).getOperand(1); + Summary.Comp1 = N->getOperand(0).getOperand(0).getOperand(0); + return true; + default: + return false; + } + } else + return false; +} + void PPCDAGToDAGISel::selectFrameIndex(SDNode *SN, SDNode *N, unsigned Offset) { SDLoc dl(SN); int FI = cast(N)->getIndex(); @@ -4271,7 +4388,68 @@ SRIdxVal, SDValue(AndI.getNode(), 1) /* glue */); return; } + case ISD::SELECT_CC: { + if (PPCSubTarget->hasP9Vector()) { + SelectCCSummary Summary; + if (mayUseP9VSXScalarComparisonInstr(N, Summary)) { + if (Summary.Leave) + break; // Will be handled in tablegen. + + NumMinMax++; + unsigned SelectOpcode = + (Summary.RetType == MVT::f32) ? PPC::XXSEL_SP : PPC::XXSEL_DP; + // Check for selects which can be transformed to compare equal + 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.Ret1, + Summary.Ret0, SDValue(mask, 0)); + return; + } + // Check for selects which can be transformed to MAX + 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; + } + // Check for selects which can be transformed to MIN + 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) { + // Check for select of 2 floating points based on comparison of 2 + // different floating points. + 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.Ret1, + Summary.Ret0, 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 @@ -6698,6 +6698,11 @@ /// LowerSELECT_CC - Lower floating point select_cc's into fsel instruction when /// possible. SDValue PPCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { + // We have floating point min/max and compare instructions that we can use for + // power9. + 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 @@ -871,6 +871,14 @@ def XXSEL : XX4Form<60, 3, (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), @@ -2436,6 +2444,40 @@ IIC_FPCompare, []>; def XSCMPNEDP : XX3_XT5_XA5_XB5<60, 27, "xscmpnedp", vsrc, vsfrc, vsfrc, IIC_FPCompare, []>; + + let isCodeGenOnly = 1 in { + def XSCMPEQDP_SP : XX3_XT5_XA5_XB5<60, 3, "xscmpeqdp", vsrc, vssrc, vssrc, + IIC_FPCompare, []>; + def XSCMPGEDP_SP : XX3_XT5_XA5_XB5<60, 19, "xscmpgedp", vsrc, vssrc, vssrc, + IIC_FPCompare, []>; + def XSCMPGTDP_SP : XX3_XT5_XA5_XB5<60, 11, "xscmpgtdp", vsrc, vssrc, vssrc, + IIC_FPCompare, []>; + } + + def : Pat <(f64 (selectcc f64:$XC, f64:$XD, f64:$XA, f64:$XB, SETOEQ )), + (XXSEL_DP $XB, $XA, (XSCMPEQDP $XC, $XD))>; + + def : Pat <(f64 (selectcc f64:$XC, f64:$XD, f64:$XA, f64:$XB, SETEQ )), + (XXSEL_DP $XB, $XA, (XSCMPEQDP $XC, $XD))>; + + def : Pat <(f32 (selectcc f32:$XC, f32:$XD, f32:$XA, f32:$XB, SETOEQ )), + (XXSEL_SP $XB, $XA, (XSCMPEQDP_SP $XC, $XD))>; + + def : Pat <(f32 (selectcc f32:$XC, f32:$XD, f32:$XA, f32:$XB, SETEQ )), + (XXSEL_SP $XB, $XA, (XSCMPEQDP_SP $XC, $XD))>; + + def : Pat <(f64 (selectcc f32:$XC, f32:$XD, f64:$XA, f64:$XB, SETOEQ )), + (XXSEL_DP $XB, $XA, (XSCMPEQDP_SP $XC, $XD))>; + + def : Pat <(f64 (selectcc f32:$XC, f32:$XD, f64:$XA, f64:$XB, SETEQ )), + (XXSEL_DP $XB, $XA, (XSCMPEQDP_SP $XC, $XD))>; + + def : Pat <(f32 (selectcc f64:$XC, f64:$XD, f32:$XA, f32:$XB, SETOEQ )), + (XXSEL_SP $XB, $XA, (XSCMPEQDP $XC, $XD))>; + + def : Pat <(f32 (selectcc f64:$XC, f64:$XD, f32:$XA, f32:$XB, SETEQ )), + (XXSEL_SP $XB, $XA, (XSCMPEQDP $XC, $XD))>; + let UseVSXReg = 1 in { // Vector Compare Not Equal def XVCMPNEDP : XX3Form_Rc<60, 123, @@ -2613,15 +2655,26 @@ // 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, + def XSMAXCDP : XX3_XT5_XA5_XB5<60, 128, "xsmaxcdp", vsfrc, vsfrc, vsfrc, IIC_VecFP, []>; 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, + def XSMINCDP : XX3_XT5_XA5_XB5<60, 136, "xsmincdp", vsfrc, vsfrc, vsfrc, IIC_VecFP, []>; def XSMINJDP : XX3_XT5_XA5_XB5<60, 152, "xsminjdp", vsrc, vsfrc, vsfrc, IIC_VecFP, []>; + let isCodeGenOnly = 1 in { + def XSMAXCDP_SP : XX3_XT5_XA5_XB5<60, 128, "xsmaxcdp", vssrc, vssrc, vssrc, + IIC_VecFP, []>; + def XSMAXJDP_SP : XX3_XT5_XA5_XB5<60, 144, "xsmaxjdp", vsrc, vssrc, vssrc, + IIC_VecFP, []>; + def XSMINCDP_SP : XX3_XT5_XA5_XB5<60, 136, "xsmincdp", vssrc, vssrc, vssrc, + IIC_VecFP, []>; + def XSMINJDP_SP : XX3_XT5_XA5_XB5<60, 152, "xsminjdp", vsrc, vssrc, vssrc, + IIC_VecFP, []>; + } + //===--------------------------------------------------------------------===// // Vector Byte-Reverse H/W/D/Q Word Index: test/CodeGen/PowerPC/vsx-p9-maxmin.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/vsx-p9-maxmin.ll @@ -0,0 +1,1533 @@ +; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 < %s | FileCheck %s +; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr8 < %s | 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, 3, 4, [[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, 3, 4, [[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, 3, 4, [[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, 3, 4, [[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, 3, 4, [[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, 3, 4, [[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, 3, 4, [[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, 3, 4, [[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, 3, 4, [[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, 3, 4, [[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, 3, 4, [[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, 3, 4, [[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, 3, 4, [[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, 3, 4, [[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, 3, 4, [[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, 3, 4, [[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, 2, 1, [[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, 2, 1, [[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, 1, 2, [[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, 1, 2, [[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, 2, 1, [[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, 2, 1, [[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, 1, 2, [[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, 1, 2, [[MASK]] +; CHECK: blr + +}