Index: lib/Target/PowerPC/PPCISelDAGToDAG.cpp =================================================================== --- lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -3597,9 +3597,12 @@ } } else if (LHS.getValueType() == MVT::f32) { Opc = PPC::FCMPUS; - } else { - assert(LHS.getValueType() == MVT::f64 && "Unknown vt!"); + } else if (LHS.getValueType() == MVT::f64) { Opc = PPCSubTarget->hasVSX() ? PPC::XSCMPUDP : PPC::FCMPUD; + } else { + assert(LHS.getValueType() == MVT::f128 && "Unknown vt!"); + assert(PPCSubTarget->hasVSX() && "__float128 requires VSX"); + Opc = PPC::XSCMPUQP; } return SDValue(CurDAG->getMachineNode(Opc, dl, MVT::i32, LHS, RHS), 0); } Index: lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCISelLowering.cpp +++ lib/Target/PowerPC/PPCISelLowering.cpp @@ -799,6 +799,12 @@ setOperationAction(ISD::FP_EXTEND, MVT::f128, Legal); setLoadExtAction(ISD::EXTLOAD, MVT::f128, MVT::f64, Expand); setOperationAction(ISD::FMA, MVT::f128, Legal); + setCondCodeAction(ISD::SETULT, MVT::f128, Expand); + setCondCodeAction(ISD::SETUGT, MVT::f128, Expand); + setCondCodeAction(ISD::SETUEQ, MVT::f128, Expand); + setCondCodeAction(ISD::SETOGE, MVT::f128, Expand); + setCondCodeAction(ISD::SETOLE, MVT::f128, Expand); + setCondCodeAction(ISD::SETONE, MVT::f128, Expand); } } Index: lib/Target/PowerPC/PPCInstrInfo.td =================================================================== --- lib/Target/PowerPC/PPCInstrInfo.td +++ lib/Target/PowerPC/PPCInstrInfo.td @@ -3615,6 +3615,37 @@ defm : CRNotPat<(i1 (setcc f64:$s1, f64:$s2, SETO)), (EXTRACT_SUBREG (FCMPUD $s1, $s2), sub_un)>; +// SETCC for f128. +def : Pat<(i1 (setcc f128:$s1, f128:$s2, SETOLT)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_lt)>; +def : Pat<(i1 (setcc f128:$s1, f128:$s2, SETLT)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_lt)>; +def : Pat<(i1 (setcc f128:$s1, f128:$s2, SETOGT)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_gt)>; +def : Pat<(i1 (setcc f128:$s1, f128:$s2, SETGT)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_gt)>; +def : Pat<(i1 (setcc f128:$s1, f128:$s2, SETOEQ)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_eq)>; +def : Pat<(i1 (setcc f128:$s1, f128:$s2, SETEQ)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_eq)>; +def : Pat<(i1 (setcc f128:$s1, f128:$s2, SETUO)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_un)>; + +defm : CRNotPat<(i1 (setcc f128:$s1, f128:$s2, SETUGE)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_lt)>; +defm : CRNotPat<(i1 (setcc f128:$s1, f128:$s2, SETGE)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_lt)>; +defm : CRNotPat<(i1 (setcc f128:$s1, f128:$s2, SETULE)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_gt)>; +defm : CRNotPat<(i1 (setcc f128:$s1, f128:$s2, SETLE)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_gt)>; +defm : CRNotPat<(i1 (setcc f128:$s1, f128:$s2, SETUNE)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_eq)>; +defm : CRNotPat<(i1 (setcc f128:$s1, f128:$s2, SETNE)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_eq)>; +defm : CRNotPat<(i1 (setcc f128:$s1, f128:$s2, SETO)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_un)>; + // match select on i1 variables: def : Pat<(i1 (select i1:$cond, i1:$tval, i1:$fval)), (CROR (CRAND $cond , $tval), Index: test/CodeGen/PowerPC/f128-compare.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/f128-compare.ll @@ -0,0 +1,140 @@ +; RUN: llc -mcpu=pwr9 -mtriple=powerpc64le-unknown-unknown \ +; RUN: -enable-ppc-quad-precision -verify-machineinstrs < %s | FileCheck %s + +@a_qp = common global fp128 0xL00000000000000000000000000000000, align 16 +@b_qp = common global fp128 0xL00000000000000000000000000000000, align 16 + +; Function Attrs: noinline nounwind optnone +define signext i32 @greater_qp() { +entry: + %0 = load fp128, fp128* @a_qp, align 16 + %1 = load fp128, fp128* @b_qp, align 16 + %cmp = fcmp ogt fp128 %0, %1 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK-LABEL: greater_qp +; CHECK: xscmpuqp +; CHECK: blr +} + +; Function Attrs: noinline nounwind optnone +define signext i32 @less_qp() { +entry: + %0 = load fp128, fp128* @a_qp, align 16 + %1 = load fp128, fp128* @b_qp, align 16 + %cmp = fcmp olt fp128 %0, %1 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK-LABEL: less_qp +; CHECK: xscmpuqp +; CHECK: blr +} + +; Function Attrs: noinline nounwind optnone +define signext i32 @greater_eq_qp() { +entry: + %0 = load fp128, fp128* @a_qp, align 16 + %1 = load fp128, fp128* @b_qp, align 16 + %cmp = fcmp oge fp128 %0, %1 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK-LABEL: greater_eq_qp +; CHECK: xscmpuqp +; CHECK: blr +} + +; Function Attrs: noinline nounwind optnone +define signext i32 @less_eq_qp() { +entry: + %0 = load fp128, fp128* @a_qp, align 16 + %1 = load fp128, fp128* @b_qp, align 16 + %cmp = fcmp ole fp128 %0, %1 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK-LABEL: less_eq_qp +; CHECK: xscmpuqp +; CHECK: blr +} + +; Function Attrs: noinline nounwind optnone +define signext i32 @equal_qp() { +entry: + %0 = load fp128, fp128* @a_qp, align 16 + %1 = load fp128, fp128* @b_qp, align 16 + %cmp = fcmp oeq fp128 %0, %1 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK-LABEL: equal_qp +; CHECK: xscmpuqp +; CHECK: blr +} + +; Function Attrs: noinline nounwind optnone +define signext i32 @not_greater_qp() { +entry: + %0 = load fp128, fp128* @a_qp, align 16 + %1 = load fp128, fp128* @b_qp, align 16 + %cmp = fcmp ogt fp128 %0, %1 + %lnot = xor i1 %cmp, true + %lnot.ext = zext i1 %lnot to i32 + ret i32 %lnot.ext +; CHECK-LABEL: not_greater_qp +; CHECK: xscmpuqp +; CHECK: blr +} + +; Function Attrs: noinline nounwind optnone +define signext i32 @not_less_qp() { +entry: + %0 = load fp128, fp128* @a_qp, align 16 + %1 = load fp128, fp128* @b_qp, align 16 + %cmp = fcmp olt fp128 %0, %1 + %lnot = xor i1 %cmp, true + %lnot.ext = zext i1 %lnot to i32 + ret i32 %lnot.ext +; CHECK-LABEL: not_less_qp +; CHECK: xscmpuqp +; CHECK: blr +} + +; Function Attrs: noinline nounwind optnone +define signext i32 @not_greater_eq_qp() { +entry: + %0 = load fp128, fp128* @a_qp, align 16 + %1 = load fp128, fp128* @b_qp, align 16 + %cmp = fcmp oge fp128 %0, %1 + %lnot = xor i1 %cmp, true + %lnot.ext = zext i1 %lnot to i32 + ret i32 %lnot.ext +; CHECK-LABEL: not_greater_eq_qp +; CHECK: xscmpuqp +; CHECK: blr +} + +; Function Attrs: noinline nounwind optnone +define signext i32 @not_less_eq_qp() { +entry: + %0 = load fp128, fp128* @a_qp, align 16 + %1 = load fp128, fp128* @b_qp, align 16 + %cmp = fcmp ole fp128 %0, %1 + %lnot = xor i1 %cmp, true + %lnot.ext = zext i1 %lnot to i32 + ret i32 %lnot.ext +; CHECK-LABEL: not_less_eq_qp +; CHECK: xscmpuqp +; CHECK: blr +} + +; Function Attrs: noinline nounwind optnone +define signext i32 @not_equal_qp() { +entry: + %0 = load fp128, fp128* @a_qp, align 16 + %1 = load fp128, fp128* @b_qp, align 16 + %cmp = fcmp une fp128 %0, %1 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK-LABEL: not_equal_qp +; CHECK: xscmpuqp +; CHECK: blr +} +