diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -55,6 +55,10 @@ XSMAXCDP, XSMINCDP, + /// XSMAXCQP, XSMINCQP - C-type min/max instructions for quad-precision. + XSMAXCQP, + XSMINCQP, + /// FCFID - The FCFID instruction, taking an f64 operand and producing /// and f64 value containing the FP representation of the integer that /// was temporarily in the f64 operand. diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1340,6 +1340,10 @@ setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v2i32, Legal); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v2i64, Legal); } + + if (Subtarget.hasP10Vector()) { + setOperationAction(ISD::SELECT_CC, MVT::f128, Custom); + } } if (Subtarget.pairedVectorMemops() && Enable256BitVector) { @@ -1684,6 +1688,8 @@ case PPCISD::FSEL: return "PPCISD::FSEL"; case PPCISD::XSMAXCDP: return "PPCISD::XSMAXCDP"; case PPCISD::XSMINCDP: return "PPCISD::XSMINCDP"; + case PPCISD::XSMAXCQP: return "PPCISD::XSMAXCQP"; + case PPCISD::XSMINCQP: return "PPCISD::XSMINCQP"; case PPCISD::FCFID: return "PPCISD::FCFID"; case PPCISD::FCFIDU: return "PPCISD::FCFIDU"; case PPCISD::FCFIDS: return "PPCISD::FCFIDS"; @@ -8015,10 +8021,16 @@ break; case ISD::SETOGT: case ISD::SETGT: - return DAG.getNode(PPCISD::XSMAXCDP, dl, Op.getValueType(), LHS, RHS); + if (Subtarget.hasP10Vector() && CmpVT == MVT::f128) + return DAG.getNode(PPCISD::XSMAXCQP, dl, Op.getValueType(), LHS, RHS); + else + return DAG.getNode(PPCISD::XSMAXCDP, dl, Op.getValueType(), LHS, RHS); case ISD::SETOLT: case ISD::SETLT: - return DAG.getNode(PPCISD::XSMINCDP, dl, Op.getValueType(), LHS, RHS); + if (Subtarget.hasP10Vector() && CmpVT == MVT::f128) + return DAG.getNode(PPCISD::XSMINCQP, dl, Op.getValueType(), LHS, RHS); + else + return DAG.getNode(PPCISD::XSMINCDP, dl, Op.getValueType(), LHS, RHS); } } diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -220,6 +220,8 @@ SDTCisFP<0>, SDTCisVT<1, f64>]>, []>; def PPCxsmaxc : SDNode<"PPCISD::XSMAXCDP", SDT_PPCFPMinMax, []>; def PPCxsminc : SDNode<"PPCISD::XSMINCDP", SDT_PPCFPMinMax, []>; +def PPCxsmaxcq : SDNode<"PPCISD::XSMAXCQP", SDT_PPCFPMinMax, []>; +def PPCxsmincq : SDNode<"PPCISD::XSMINCQP", SDT_PPCFPMinMax, []>; def PPChi : SDNode<"PPCISD::Hi", SDTIntBinOp, []>; def PPClo : SDNode<"PPCISD::Lo", SDTIntBinOp, []>; def PPCtoc_entry: SDNode<"PPCISD::TOC_ENTRY", SDTIntBinOp, diff --git a/llvm/lib/Target/PowerPC/PPCInstrPrefix.td b/llvm/lib/Target/PowerPC/PPCInstrPrefix.td --- a/llvm/lib/Target/PowerPC/PPCInstrPrefix.td +++ b/llvm/lib/Target/PowerPC/PPCInstrPrefix.td @@ -1912,8 +1912,10 @@ } let Predicates = [Power10Instrs] in { - def XSMAXCQP : X_VT5_VA5_VB5<63, 676, "xsmaxcqp", []>; - def XSMINCQP : X_VT5_VA5_VB5<63, 740, "xsmincqp", []>; + def XSMAXCQP : X_VT5_VA5_VB5<63, 676, "xsmaxcqp", + [(set f128:$vT, (PPCxsmaxcq f128:$vA, f128:$vB))]>; + def XSMINCQP : X_VT5_VA5_VB5<63, 740, "xsmincqp", + [(set f128:$vT, (PPCxsmincq f128:$vA, f128:$vB))]>; def XSCMPEQQP : X_VT5_VA5_VB5<63, 68, "xscmpeqqp", []>; def XSCMPGEQP : X_VT5_VA5_VB5<63, 196, "xscmpgeqp", []>; def XSCMPGTQP : X_VT5_VA5_VB5<63, 228, "xscmpgtqp", []>; diff --git a/llvm/test/CodeGen/PowerPC/scalar-min-max-p10.ll b/llvm/test/CodeGen/PowerPC/scalar-min-max-p10.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/scalar-min-max-p10.ll @@ -0,0 +1,53 @@ +; RUN: llc -mcpu=pwr10 -ppc-asm-full-reg-names --enable-unsafe-fp-math \ +; RUN: -verify-machineinstrs --enable-no-signed-zeros-fp-math \ +; RUN: --enable-no-nans-fp-math \ +; RUN: -mtriple=powerpc64le-unknown-unknown < %s | FileCheck %s +; RUN: llc -mcpu=pwr10 -ppc-asm-full-reg-names -verify-machineinstrs \ +; RUN: -mtriple=powerpc64le-unknown-unknown < %s | FileCheck %s +define dso_local fp128 @testqmax(fp128 %a, fp128 %b) local_unnamed_addr { +; CHECK-LABEL: testqmax: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xsmaxcqp v2, v2, v3 +; CHECK-NEXT: blr +; +entry: + %cmp = fcmp ogt fp128 %a, %b + %cond = select i1 %cmp, fp128 %a, fp128 %b + ret fp128 %cond +} + +define dso_local fp128 @testqmin(fp128 %a, fp128 %b) local_unnamed_addr { +; CHECK-LABEL: testqmin: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xsmincqp v2, v2, v3 +; CHECK-NEXT: blr +; +entry: + %cmp = fcmp olt fp128 %a, %b + %cond = select i1 %cmp, fp128 %a, fp128 %b + ret fp128 %cond +} + +define dso_local fp128 @testqmax_fast(fp128 %a, fp128 %b) local_unnamed_addr { +; CHECK-LABEL: testqmax_fast: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xsmaxcqp v2, v2, v3 +; CHECK-NEXT: blr +; +entry: + %cmp = fcmp nnan ninf ogt fp128 %a, %b + %cond = select i1 %cmp, fp128 %a, fp128 %b + ret fp128 %cond +} + +define dso_local fp128 @testqmin_fast(fp128 %a, fp128 %b) local_unnamed_addr { +; CHECK-LABEL: testqmin_fast: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xsmincqp v2, v2, v3 +; CHECK-NEXT: blr +; +entry: + %cmp = fcmp nnan ninf olt fp128 %a, %b + %cond = select i1 %cmp, fp128 %a, fp128 %b + ret fp128 %cond +}