diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def --- a/clang/include/clang/Basic/BuiltinsPPC.def +++ b/clang/include/clang/Basic/BuiltinsPPC.def @@ -152,6 +152,13 @@ BUILTIN(__builtin_ppc_mtspr, "vIiULi", "") BUILTIN(__builtin_ppc_stfiw, "viC*d", "") BUILTIN(__builtin_ppc_addex, "LLiLLiLLiCIi", "") +// select +BUILTIN(__builtin_ppc_maxfe, "LdLdLdLd.", "t") +BUILTIN(__builtin_ppc_maxfl, "dddd.", "t") +BUILTIN(__builtin_ppc_maxfs, "ffff.", "t") +BUILTIN(__builtin_ppc_minfe, "LdLdLdLd.", "t") +BUILTIN(__builtin_ppc_minfl, "dddd.", "t") +BUILTIN(__builtin_ppc_minfs, "ffff.", "t") BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n") diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -247,6 +247,12 @@ Builder.defineMacro("__test_data_class", "__builtin_ppc_test_data_class"); Builder.defineMacro("__swdiv", "__builtin_ppc_swdiv"); Builder.defineMacro("__swdivs", "__builtin_ppc_swdivs"); + Builder.defineMacro("__builtin_maxfe", "__builtin_ppc_maxfe"); + Builder.defineMacro("__builtin_maxfl", "__builtin_ppc_maxfl"); + Builder.defineMacro("__builtin_maxfs", "__builtin_ppc_maxfs"); + Builder.defineMacro("__builtin_minfe", "__builtin_ppc_minfe"); + Builder.defineMacro("__builtin_minfl", "__builtin_ppc_minfl"); + Builder.defineMacro("__builtin_minfs", "__builtin_ppc_minfs"); } /// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -16302,6 +16302,18 @@ return Builder.CreateCall(CGM.getIntrinsic(IntrinsicID), Ops, "test_data_class"); } + case PPC::BI__builtin_ppc_maxfe: + return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_maxfe), Ops); + case PPC::BI__builtin_ppc_maxfl: + return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_maxfl), Ops); + case PPC::BI__builtin_ppc_maxfs: + return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_maxfs), Ops); + case PPC::BI__builtin_ppc_minfe: + return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_minfe), Ops); + case PPC::BI__builtin_ppc_minfl: + return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_minfl), Ops); + case PPC::BI__builtin_ppc_minfs: + return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_minfs), Ops); case PPC::BI__builtin_ppc_swdiv: case PPC::BI__builtin_ppc_swdivs: return Builder.CreateFDiv(Ops[0], Ops[1], "swdiv"); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3904,6 +3904,33 @@ diag::err_ppc_builtin_requires_vsx) || SemaBuiltinConstantArgRange(TheCall, 1, 0, 127); } + case PPC::BI__builtin_ppc_maxfe: + case PPC::BI__builtin_ppc_minfe: + case PPC::BI__builtin_ppc_maxfl: + case PPC::BI__builtin_ppc_minfl: + case PPC::BI__builtin_ppc_maxfs: + case PPC::BI__builtin_ppc_minfs: { + if (Context.getTargetInfo().getTriple().isOSAIX() && + (BuiltinID == PPC::BI__builtin_ppc_maxfe || + BuiltinID == PPC::BI__builtin_ppc_minfe)) + return Diag(TheCall->getBeginLoc(), diag::err_target_unsupported_type) + << "builtin" << true << 128 << QualType(Context.LongDoubleTy) + << false << Context.getTargetInfo().getTriple().str(); + // Argument type should be exact. + QualType ArgType = QualType(Context.LongDoubleTy); + if (BuiltinID == PPC::BI__builtin_ppc_maxfl || + BuiltinID == PPC::BI__builtin_ppc_minfl) + ArgType = QualType(Context.DoubleTy); + else if (BuiltinID == PPC::BI__builtin_ppc_maxfs || + BuiltinID == PPC::BI__builtin_ppc_minfs) + ArgType = QualType(Context.FloatTy); + for (unsigned I = 0, E = TheCall->getNumArgs(); I < E; ++I) + if (TheCall->getArg(I)->getType() != ArgType) + return Diag(TheCall->getBeginLoc(), + diag::err_typecheck_convert_incompatible) + << TheCall->getArg(I)->getType() << ArgType << 1 << 0 << 0; + return false; + } case PPC::BI__builtin_ppc_load8r: case PPC::BI__builtin_ppc_store8r: return SemaFeatureCheck(*this, TheCall, "isa-v206-instructions", diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc.c b/clang/test/CodeGen/PowerPC/builtins-ppc.c --- a/clang/test/CodeGen/PowerPC/builtins-ppc.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc.c @@ -46,3 +46,31 @@ // CHECK: call ppc_fp128 @llvm.ppc.pack.longdouble(double %0, double %1) return __builtin_pack_longdouble(x, y); } + +void test_builtin_ppc_maxminfe(long double a, long double b, long double c, + long double d) { + volatile long double res; + // CHECK: call ppc_fp128 (ppc_fp128, ppc_fp128, ppc_fp128, ...) @llvm.ppc.maxfe(ppc_fp128 %0, ppc_fp128 %1, ppc_fp128 %2, ppc_fp128 %3) + res = __builtin_ppc_maxfe(a, b, c, d); + + // CHECK: call ppc_fp128 (ppc_fp128, ppc_fp128, ppc_fp128, ...) @llvm.ppc.minfe(ppc_fp128 %5, ppc_fp128 %6, ppc_fp128 %7, ppc_fp128 %8) + res = __builtin_ppc_minfe(a, b, c, d); +} + +void test_builtin_ppc_maxminfl(double a, double b, double c, double d) { + volatile double res; + // CHECK: call double (double, double, double, ...) @llvm.ppc.maxfl(double %0, double %1, double %2, double %3) + res = __builtin_ppc_maxfl(a, b, c, d); + + // CHECK: call double (double, double, double, ...) @llvm.ppc.minfl(double %5, double %6, double %7, double %8) + res = __builtin_ppc_minfl(a, b, c, d); +} + +void test_builtin_ppc_maxminfs(float a, float b, float c, float d) { + volatile float res; + // CHECK: call float (float, float, float, ...) @llvm.ppc.maxfs(float %0, float %1, float %2, float %3) + res = __builtin_ppc_maxfs(a, b, c, d); + + // CHECK: call float (float, float, float, ...) @llvm.ppc.minfs(float %5, float %6, float %7, float %8) + res = __builtin_ppc_minfs(a, b, c, d); +} diff --git a/clang/test/Sema/builtins-ppc.c b/clang/test/Sema/builtins-ppc.c --- a/clang/test/Sema/builtins-ppc.c +++ b/clang/test/Sema/builtins-ppc.c @@ -10,6 +10,12 @@ // RUN: -triple powerpc64le-unknown-unknown -DTEST_CRYPTO -fsyntax-only \ // RUN: -target-feature +vsx -verify %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -DTEST_MAXMIN -fsyntax-only \ +// RUN: -verify %s + +// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -DTEST_MAXMIN -fsyntax-only \ +// RUN: -verify %s + #ifdef TEST_HTM void test_htm() { __builtin_tbegin(4); // expected-error-re {{argument value {{.*}} is outside the valid range}} @@ -54,3 +60,25 @@ #endif +#ifdef TEST_MAXMIN +void test_maxmin() { + long double fe; + double fl; + float fs; +#ifdef _AIX + __builtin_ppc_maxfe(fe, fe, fe, fe); // expected-error-re {{builtin requires 128 bit size 'long double' type support, but target {{.*}} does not support it}} + __builtin_ppc_minfe(fe, fe, fe, fe); // expected-error-re {{builtin requires 128 bit size 'long double' type support, but target {{.*}} does not support it}} + __builtin_ppc_maxfl(fs, fs, fs, fs); // expected-error-re {{passing {{.*}} to parameter of incompatible type {{.*}}}} + __builtin_ppc_minfl(fs, fs, fs, fs); // expected-error-re {{passing {{.*}} to parameter of incompatible type {{.*}}}} + __builtin_ppc_maxfs(fe, fe, fe, fe); // expected-error-re {{passing {{.*}} to parameter of incompatible type {{.*}}}} + __builtin_ppc_minfs(fe, fe, fe, fe); // expected-error-re {{passing {{.*}} to parameter of incompatible type {{.*}}}} +#else + __builtin_ppc_maxfe(fl, fl, fl, fl); // expected-error-re {{passing {{.*}} to parameter of incompatible type {{.*}}}} + __builtin_ppc_minfe(fl, fl, fl, fl); // expected-error-re {{passing {{.*}} to parameter of incompatible type {{.*}}}} + __builtin_ppc_maxfl(fs, fs, fs, fs); // expected-error-re {{passing {{.*}} to parameter of incompatible type {{.*}}}} + __builtin_ppc_minfl(fs, fs, fs, fs); // expected-error-re {{passing {{.*}} to parameter of incompatible type {{.*}}}} + __builtin_ppc_maxfs(fe, fe, fe, fe); // expected-error-re {{passing {{.*}} to parameter of incompatible type {{.*}}}} + __builtin_ppc_minfs(fe, fe, fe, fe); // expected-error-re {{passing {{.*}} to parameter of incompatible type {{.*}}}} +#endif +} +#endif diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td --- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td +++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td @@ -160,6 +160,37 @@ def int_ppc_fctuwz : GCCBuiltin<"__builtin_ppc_fctuwz">, Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + + // XL compatible select functions + // TODO: Add llvm_f128_ty support. + def int_ppc_maxfe + : Intrinsic< + [llvm_ppcf128_ty], + [llvm_ppcf128_ty, llvm_ppcf128_ty, llvm_ppcf128_ty, llvm_vararg_ty], + [IntrNoMem]>; + def int_ppc_maxfl + : Intrinsic< + [llvm_double_ty], + [llvm_double_ty, llvm_double_ty, llvm_double_ty, llvm_vararg_ty], + [IntrNoMem]>; + def int_ppc_maxfs + : Intrinsic<[llvm_float_ty], + [llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_vararg_ty], + [IntrNoMem]>; + def int_ppc_minfe + : Intrinsic< + [llvm_ppcf128_ty], + [llvm_ppcf128_ty, llvm_ppcf128_ty, llvm_ppcf128_ty, llvm_vararg_ty], + [IntrNoMem]>; + def int_ppc_minfl + : Intrinsic< + [llvm_double_ty], + [llvm_double_ty, llvm_double_ty, llvm_double_ty, llvm_vararg_ty], + [IntrNoMem]>; + def int_ppc_minfs + : Intrinsic<[llvm_float_ty], + [llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_vararg_ty], + [IntrNoMem]>; } let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". 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 @@ -10563,6 +10563,30 @@ dl, SDValue()); return Result.first; } + case Intrinsic::ppc_maxfe: + case Intrinsic::ppc_maxfl: + case Intrinsic::ppc_maxfs: + case Intrinsic::ppc_minfe: + case Intrinsic::ppc_minfl: + case Intrinsic::ppc_minfs: { + EVT VT = Op.getValueType(); + assert( + all_of(Op->ops().drop_front(4), + [VT](const SDUse &Use) { return Use.getValueType() == VT; }) && + "ppc_[max|min]f[e|l|s] must have uniform type arguments"); + ISD::CondCode CC = ISD::SETGT; + if (IntrinsicID == Intrinsic::ppc_minfe || + IntrinsicID == Intrinsic::ppc_minfl || + IntrinsicID == Intrinsic::ppc_minfs) + CC = ISD::SETLT; + unsigned I = Op.getNumOperands() - 2, Cnt = I; + SDValue Res = Op.getOperand(I); + for (--I; Cnt != 0; --Cnt, I = (--I == 0 ? (Op.getNumOperands() - 1) : I)) { + Res = + DAG.getSelectCC(dl, Res, Op.getOperand(I), Res, Op.getOperand(I), CC); + } + return Res; + } } // If this is a lowered altivec predicate compare, CompareOpc is set to the @@ -11223,6 +11247,8 @@ Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::ppcf128, N->getOperand(2), N->getOperand(1))); break; + case Intrinsic::ppc_maxfe: + case Intrinsic::ppc_minfe: case Intrinsic::ppc_fnmsub: case Intrinsic::ppc_convert_f128_to_ppcf128: Results.push_back(LowerINTRINSIC_WO_CHAIN(SDValue(N, 0), DAG)); diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-maxmin.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-maxmin.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-maxmin.ll @@ -0,0 +1,257 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mcpu=pwr9 -verify-machineinstrs -mtriple=powerpc64le-unknown-linux \ +; RUN: < %s | FileCheck --check-prefixes=CHECK,CHECK-P9 %s +; RUN: llc -mcpu=pwr8 -verify-machineinstrs -mtriple=powerpc64le-unknown-linux \ +; RUN: < %s | FileCheck --check-prefixes=CHECK,CHECK-P8 %s + +declare ppc_fp128 @llvm.ppc.maxfe(ppc_fp128 %a, ppc_fp128 %b, ppc_fp128 %c, ...) +define ppc_fp128 @test_maxfe(ppc_fp128 %a, ppc_fp128 %b, ppc_fp128 %c, ppc_fp128 %d) { +; CHECK-LABEL: test_maxfe: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: fcmpu 0, 6, 4 +; CHECK-NEXT: fcmpu 1, 5, 3 +; CHECK-NEXT: crand 20, 6, 1 +; CHECK-NEXT: cror 20, 5, 20 +; CHECK-NEXT: bc 12, 20, .LBB0_2 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: fmr 6, 4 +; CHECK-NEXT: .LBB0_2: # %entry +; CHECK-NEXT: fcmpu 0, 6, 2 +; CHECK-NEXT: bc 12, 20, .LBB0_4 +; CHECK-NEXT: # %bb.3: # %entry +; CHECK-NEXT: fmr 5, 3 +; CHECK-NEXT: .LBB0_4: # %entry +; CHECK-NEXT: fcmpu 1, 5, 1 +; CHECK-NEXT: crand 20, 6, 1 +; CHECK-NEXT: cror 20, 5, 20 +; CHECK-NEXT: bc 12, 20, .LBB0_6 +; CHECK-NEXT: # %bb.5: # %entry +; CHECK-NEXT: fmr 6, 2 +; CHECK-NEXT: .LBB0_6: # %entry +; CHECK-NEXT: fcmpu 0, 6, 8 +; CHECK-NEXT: bc 12, 20, .LBB0_8 +; CHECK-NEXT: # %bb.7: # %entry +; CHECK-NEXT: fmr 5, 1 +; CHECK-NEXT: .LBB0_8: # %entry +; CHECK-NEXT: fcmpu 1, 5, 7 +; CHECK-NEXT: crand 20, 6, 1 +; CHECK-NEXT: cror 20, 5, 20 +; CHECK-NEXT: bc 12, 20, .LBB0_10 +; CHECK-NEXT: # %bb.9: # %entry +; CHECK-NEXT: fmr 5, 7 +; CHECK-NEXT: .LBB0_10: # %entry +; CHECK-NEXT: bc 12, 20, .LBB0_12 +; CHECK-NEXT: # %bb.11: # %entry +; CHECK-NEXT: fmr 6, 8 +; CHECK-NEXT: .LBB0_12: # %entry +; CHECK-NEXT: fmr 1, 5 +; CHECK-NEXT: fmr 2, 6 +; CHECK-NEXT: blr +entry: + %0 = call ppc_fp128 (ppc_fp128, ppc_fp128, ppc_fp128, ...) @llvm.ppc.maxfe(ppc_fp128 %a, ppc_fp128 %b, ppc_fp128 %c, ppc_fp128 %d) + ret ppc_fp128 %0 +} + +declare double @llvm.ppc.maxfl(double %a, double %b, double %c, ...) +define double @test_maxfl(double %a, double %b, double %c, double %d) { +; CHECK-P9-LABEL: test_maxfl: +; CHECK-P9: # %bb.0: # %entry +; CHECK-P9-NEXT: xsmaxcdp 0, 3, 2 +; CHECK-P9-NEXT: xsmaxcdp 0, 0, 1 +; CHECK-P9-NEXT: xsmaxcdp 1, 0, 4 +; CHECK-P9-NEXT: blr +; +; CHECK-P8-LABEL: test_maxfl: +; CHECK-P8: # %bb.0: # %entry +; CHECK-P8-NEXT: xscmpudp 0, 3, 2 +; CHECK-P8-NEXT: ble 0, .LBB1_4 +; CHECK-P8-NEXT: # %bb.1: # %entry +; CHECK-P8-NEXT: xscmpudp 0, 3, 1 +; CHECK-P8-NEXT: ble 0, .LBB1_5 +; CHECK-P8-NEXT: .LBB1_2: # %entry +; CHECK-P8-NEXT: xscmpudp 0, 3, 4 +; CHECK-P8-NEXT: ble 0, .LBB1_6 +; CHECK-P8-NEXT: .LBB1_3: # %entry +; CHECK-P8-NEXT: fmr 1, 3 +; CHECK-P8-NEXT: blr +; CHECK-P8-NEXT: .LBB1_4: # %entry +; CHECK-P8-NEXT: fmr 3, 2 +; CHECK-P8-NEXT: xscmpudp 0, 3, 1 +; CHECK-P8-NEXT: bgt 0, .LBB1_2 +; CHECK-P8-NEXT: .LBB1_5: # %entry +; CHECK-P8-NEXT: fmr 3, 1 +; CHECK-P8-NEXT: xscmpudp 0, 3, 4 +; CHECK-P8-NEXT: bgt 0, .LBB1_3 +; CHECK-P8-NEXT: .LBB1_6: # %entry +; CHECK-P8-NEXT: fmr 3, 4 +; CHECK-P8-NEXT: fmr 1, 3 +; CHECK-P8-NEXT: blr +entry: + %0 = call double (double, double, double, ...) @llvm.ppc.maxfl(double %a, double %b, double %c, double %d) + ret double %0 +} + +declare float @llvm.ppc.maxfs(float %a, float %b, float %c, ...) +define float @test_maxfs(float %a, float %b, float %c, float %d) { +; CHECK-P9-LABEL: test_maxfs: +; CHECK-P9: # %bb.0: # %entry +; CHECK-P9-NEXT: xsmaxcdp 0, 3, 2 +; CHECK-P9-NEXT: xsmaxcdp 0, 0, 1 +; CHECK-P9-NEXT: xsmaxcdp 1, 0, 4 +; CHECK-P9-NEXT: blr +; +; CHECK-P8-LABEL: test_maxfs: +; CHECK-P8: # %bb.0: # %entry +; CHECK-P8-NEXT: fcmpu 0, 3, 2 +; CHECK-P8-NEXT: ble 0, .LBB2_4 +; CHECK-P8-NEXT: # %bb.1: # %entry +; CHECK-P8-NEXT: fcmpu 0, 3, 1 +; CHECK-P8-NEXT: ble 0, .LBB2_5 +; CHECK-P8-NEXT: .LBB2_2: # %entry +; CHECK-P8-NEXT: fcmpu 0, 3, 4 +; CHECK-P8-NEXT: ble 0, .LBB2_6 +; CHECK-P8-NEXT: .LBB2_3: # %entry +; CHECK-P8-NEXT: fmr 1, 3 +; CHECK-P8-NEXT: blr +; CHECK-P8-NEXT: .LBB2_4: # %entry +; CHECK-P8-NEXT: fmr 3, 2 +; CHECK-P8-NEXT: fcmpu 0, 3, 1 +; CHECK-P8-NEXT: bgt 0, .LBB2_2 +; CHECK-P8-NEXT: .LBB2_5: # %entry +; CHECK-P8-NEXT: fmr 3, 1 +; CHECK-P8-NEXT: fcmpu 0, 3, 4 +; CHECK-P8-NEXT: bgt 0, .LBB2_3 +; CHECK-P8-NEXT: .LBB2_6: # %entry +; CHECK-P8-NEXT: fmr 3, 4 +; CHECK-P8-NEXT: fmr 1, 3 +; CHECK-P8-NEXT: blr +entry: + %0 = call float (float, float, float, ...) @llvm.ppc.maxfs(float %a, float %b, float %c, float %d) + ret float %0 +} + +declare ppc_fp128 @llvm.ppc.minfe(ppc_fp128 %a, ppc_fp128 %b, ppc_fp128 %c, ...) +define ppc_fp128 @test_minfe(ppc_fp128 %a, ppc_fp128 %b, ppc_fp128 %c, ppc_fp128 %d) { +; CHECK-LABEL: test_minfe: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: fcmpu 0, 6, 4 +; CHECK-NEXT: fcmpu 1, 5, 3 +; CHECK-NEXT: crand 20, 6, 0 +; CHECK-NEXT: cror 20, 4, 20 +; CHECK-NEXT: bc 12, 20, .LBB3_2 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: fmr 6, 4 +; CHECK-NEXT: .LBB3_2: # %entry +; CHECK-NEXT: fcmpu 0, 6, 2 +; CHECK-NEXT: bc 12, 20, .LBB3_4 +; CHECK-NEXT: # %bb.3: # %entry +; CHECK-NEXT: fmr 5, 3 +; CHECK-NEXT: .LBB3_4: # %entry +; CHECK-NEXT: fcmpu 1, 5, 1 +; CHECK-NEXT: crand 20, 6, 0 +; CHECK-NEXT: cror 20, 4, 20 +; CHECK-NEXT: bc 12, 20, .LBB3_6 +; CHECK-NEXT: # %bb.5: # %entry +; CHECK-NEXT: fmr 6, 2 +; CHECK-NEXT: .LBB3_6: # %entry +; CHECK-NEXT: fcmpu 0, 6, 8 +; CHECK-NEXT: bc 12, 20, .LBB3_8 +; CHECK-NEXT: # %bb.7: # %entry +; CHECK-NEXT: fmr 5, 1 +; CHECK-NEXT: .LBB3_8: # %entry +; CHECK-NEXT: fcmpu 1, 5, 7 +; CHECK-NEXT: crand 20, 6, 0 +; CHECK-NEXT: cror 20, 4, 20 +; CHECK-NEXT: bc 12, 20, .LBB3_10 +; CHECK-NEXT: # %bb.9: # %entry +; CHECK-NEXT: fmr 5, 7 +; CHECK-NEXT: .LBB3_10: # %entry +; CHECK-NEXT: bc 12, 20, .LBB3_12 +; CHECK-NEXT: # %bb.11: # %entry +; CHECK-NEXT: fmr 6, 8 +; CHECK-NEXT: .LBB3_12: # %entry +; CHECK-NEXT: fmr 1, 5 +; CHECK-NEXT: fmr 2, 6 +; CHECK-NEXT: blr +entry: + %0 = call ppc_fp128 (ppc_fp128, ppc_fp128, ppc_fp128, ...) @llvm.ppc.minfe(ppc_fp128 %a, ppc_fp128 %b, ppc_fp128 %c, ppc_fp128 %d) + ret ppc_fp128 %0 +} + +declare double @llvm.ppc.minfl(double %a, double %b, double %c, ...) +define double @test_minfl(double %a, double %b, double %c, double %d) { +; CHECK-P9-LABEL: test_minfl: +; CHECK-P9: # %bb.0: # %entry +; CHECK-P9-NEXT: xsmincdp 0, 3, 2 +; CHECK-P9-NEXT: xsmincdp 0, 0, 1 +; CHECK-P9-NEXT: xsmincdp 1, 0, 4 +; CHECK-P9-NEXT: blr +; +; CHECK-P8-LABEL: test_minfl: +; CHECK-P8: # %bb.0: # %entry +; CHECK-P8-NEXT: xscmpudp 0, 3, 2 +; CHECK-P8-NEXT: bge 0, .LBB4_4 +; CHECK-P8-NEXT: # %bb.1: # %entry +; CHECK-P8-NEXT: xscmpudp 0, 3, 1 +; CHECK-P8-NEXT: bge 0, .LBB4_5 +; CHECK-P8-NEXT: .LBB4_2: # %entry +; CHECK-P8-NEXT: xscmpudp 0, 3, 4 +; CHECK-P8-NEXT: bge 0, .LBB4_6 +; CHECK-P8-NEXT: .LBB4_3: # %entry +; CHECK-P8-NEXT: fmr 1, 3 +; CHECK-P8-NEXT: blr +; CHECK-P8-NEXT: .LBB4_4: # %entry +; CHECK-P8-NEXT: fmr 3, 2 +; CHECK-P8-NEXT: xscmpudp 0, 3, 1 +; CHECK-P8-NEXT: blt 0, .LBB4_2 +; CHECK-P8-NEXT: .LBB4_5: # %entry +; CHECK-P8-NEXT: fmr 3, 1 +; CHECK-P8-NEXT: xscmpudp 0, 3, 4 +; CHECK-P8-NEXT: blt 0, .LBB4_3 +; CHECK-P8-NEXT: .LBB4_6: # %entry +; CHECK-P8-NEXT: fmr 3, 4 +; CHECK-P8-NEXT: fmr 1, 3 +; CHECK-P8-NEXT: blr +entry: + %0 = call double (double, double, double, ...) @llvm.ppc.minfl(double %a, double %b, double %c, double %d) + ret double %0 +} + +declare float @llvm.ppc.minfs(float %a, float %b, float %c, ...) +define float @test_minfs(float %a, float %b, float %c, float %d) { +; CHECK-P9-LABEL: test_minfs: +; CHECK-P9: # %bb.0: # %entry +; CHECK-P9-NEXT: xsmincdp 0, 3, 2 +; CHECK-P9-NEXT: xsmincdp 0, 0, 1 +; CHECK-P9-NEXT: xsmincdp 1, 0, 4 +; CHECK-P9-NEXT: blr +; +; CHECK-P8-LABEL: test_minfs: +; CHECK-P8: # %bb.0: # %entry +; CHECK-P8-NEXT: fcmpu 0, 3, 2 +; CHECK-P8-NEXT: bge 0, .LBB5_4 +; CHECK-P8-NEXT: # %bb.1: # %entry +; CHECK-P8-NEXT: fcmpu 0, 3, 1 +; CHECK-P8-NEXT: bge 0, .LBB5_5 +; CHECK-P8-NEXT: .LBB5_2: # %entry +; CHECK-P8-NEXT: fcmpu 0, 3, 4 +; CHECK-P8-NEXT: bge 0, .LBB5_6 +; CHECK-P8-NEXT: .LBB5_3: # %entry +; CHECK-P8-NEXT: fmr 1, 3 +; CHECK-P8-NEXT: blr +; CHECK-P8-NEXT: .LBB5_4: # %entry +; CHECK-P8-NEXT: fmr 3, 2 +; CHECK-P8-NEXT: fcmpu 0, 3, 1 +; CHECK-P8-NEXT: blt 0, .LBB5_2 +; CHECK-P8-NEXT: .LBB5_5: # %entry +; CHECK-P8-NEXT: fmr 3, 1 +; CHECK-P8-NEXT: fcmpu 0, 3, 4 +; CHECK-P8-NEXT: blt 0, .LBB5_3 +; CHECK-P8-NEXT: .LBB5_6: # %entry +; CHECK-P8-NEXT: fmr 3, 4 +; CHECK-P8-NEXT: fmr 1, 3 +; CHECK-P8-NEXT: blr +entry: + %0 = call float (float, float, float, ...) @llvm.ppc.minfs(float %a, float %b, float %c, float %d) + ret float %0 +}