diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10004,7 +10004,7 @@ def err_ppc_invalid_use_mma_type : Error< "invalid use of PPC MMA type">; def err_ppc_invalid_test_data_class_type : Error< - "expected a 'float' or 'double' for the first argument">; + "expected a 'float', 'double' or '__float128' for the first argument">; def err_x86_builtin_invalid_rounding : Error< "invalid rounding argument">; def err_x86_builtin_invalid_scale : Error< 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 @@ -16669,16 +16669,9 @@ case PPC::BI__builtin_ppc_test_data_class: { Value *Op0 = EmitScalarExpr(E->getArg(0)); Value *Op1 = EmitScalarExpr(E->getArg(1)); - llvm::Type *ArgType = Op0->getType(); - unsigned IntrinsicID; - if (ArgType->isDoubleTy()) - IntrinsicID = Intrinsic::ppc_test_data_class_d; - else if (ArgType->isFloatTy()) - IntrinsicID = Intrinsic::ppc_test_data_class_f; - else - llvm_unreachable("Invalid Argument Type"); - return Builder.CreateCall(CGM.getIntrinsic(IntrinsicID), {Op0, Op1}, - "test_data_class"); + return Builder.CreateCall( + CGM.getIntrinsic(Intrinsic::ppc_test_data_class, Op0->getType()), + {Op0, Op1}, "test_data_class"); } case PPC::BI__builtin_ppc_maxfe: { Value *Op0 = EmitScalarExpr(E->getArg(0)); 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 @@ -4271,10 +4271,11 @@ diag::err_ppc_builtin_requires_vsx); case PPC::BI__builtin_ppc_test_data_class: { // Check if the first argument of the __builtin_ppc_test_data_class call is - // valid. The argument must be either a 'float' or a 'double'. + // valid. The argument must be 'float' or 'double' or '__float128'. QualType ArgType = TheCall->getArg(0)->getType(); if (ArgType != QualType(Context.FloatTy) && - ArgType != QualType(Context.DoubleTy)) + ArgType != QualType(Context.DoubleTy) && + ArgType != QualType(Context.Float128Ty)) return Diag(TheCall->getBeginLoc(), diag::err_ppc_invalid_test_data_class_type); return SemaFeatureCheck(*this, TheCall, "isa-v30-instructions", diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-p9-f128.c b/clang/test/CodeGen/PowerPC/builtins-ppc-p9-f128.c --- a/clang/test/CodeGen/PowerPC/builtins-ppc-p9-f128.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-p9-f128.c @@ -60,3 +60,9 @@ // CHECK-NEXT: ret i64 } +int test_data_class_f128(__float128 q) { + return __builtin_ppc_test_data_class(q, 0); +// CHECK-LABEL: @test_data_class_f128 +// CHECK: [[TMP:%.*]] = call i32 @llvm.ppc.test.data.class.f128(fp128 %0, i32 0) +// CHECK-NEXT: ret i32 [[TMP]] +} diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-pwr9-error.c b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-pwr9-error.c --- a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-pwr9-error.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-pwr9-error.c @@ -44,5 +44,5 @@ } int test_test_data_class_type() { - return __test_data_class(ui, 0); // expected-error {{expected a 'float' or 'double' for the first argument}} + return __test_data_class(ui, 0); // expected-error {{expected a 'float', 'double' or '__float128' for the first argument}} } diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-test.c b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-test.c --- a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-test.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-test.c @@ -54,7 +54,7 @@ int test_builtin_ppc_test_data_class_d() { // CHECK-LABEL: @test_builtin_ppc_test_data_class_d -// CHECK: [[TMP:%.*]] = call i32 @llvm.ppc.test.data.class.d(double %0, i32 0) +// CHECK: [[TMP:%.*]] = call i32 @llvm.ppc.test.data.class.f64(double %0, i32 0) // CHECK-NEXT: ret i32 [[TMP]] // CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs // CHECK-NOVSX-ERR: error: this builtin requires VSX to be enabled @@ -63,7 +63,7 @@ int test_builtin_ppc_test_data_class_f() { // CHECK-LABEL: @test_builtin_ppc_test_data_class_f -// CHECK: [[TMP:%.*]] = call i32 @llvm.ppc.test.data.class.f(float %0, i32 0) +// CHECK: [[TMP:%.*]] = call i32 @llvm.ppc.test.data.class.f32(float %0, i32 0) // CHECK-NEXT: ret i32 [[TMP]] // CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs // CHECK-NOVSX-ERR: error: this builtin requires VSX to be enabled @@ -108,7 +108,7 @@ int test_test_data_class_d() { // CHECK-LABEL: @test_test_data_class_d -// CHECK: [[TMP:%.*]] = call i32 @llvm.ppc.test.data.class.d(double %0, i32 127) +// CHECK: [[TMP:%.*]] = call i32 @llvm.ppc.test.data.class.f64(double %0, i32 127) // CHECK-NEXT: ret i32 [[TMP]] // CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs // CHECK-NOVSX-ERR: error: this builtin requires VSX to be enabled @@ -117,7 +117,7 @@ int test_test_data_class_f() { // CHECK-LABEL: @test_test_data_class_f -// CHECK: [[TMP:%.*]] = call i32 @llvm.ppc.test.data.class.f(float %0, i32 127) +// CHECK: [[TMP:%.*]] = call i32 @llvm.ppc.test.data.class.f32(float %0, i32 127) // CHECK-NEXT: ret i32 [[TMP]] // CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs // CHECK-NOVSX-ERR: error: this builtin requires VSX to be enabled 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 @@ -1893,12 +1893,9 @@ DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_double_ty, llvm_double_ty], [IntrNoMem]>; - def int_ppc_test_data_class_d : DefaultAttrsIntrinsic<[llvm_i32_ty], - [llvm_double_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; - def int_ppc_test_data_class_f : DefaultAttrsIntrinsic<[llvm_i32_ty], - [llvm_float_ty, llvm_i32_ty], - [IntrNoMem, ImmArg>]>; + def int_ppc_test_data_class : Intrinsic<[llvm_i32_ty], + [llvm_anyfloat_ty, llvm_i32_ty], + [IntrNoMem, ImmArg>]>; def int_ppc_fnabs : ClangBuiltin<"__builtin_ppc_fnabs">, DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; 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 @@ -10689,11 +10689,11 @@ DAG.getTargetConstant(Pred, dl, MVT::i32)}), 0); } - case Intrinsic::ppc_test_data_class_d: - case Intrinsic::ppc_test_data_class_f: { - unsigned CmprOpc = PPC::XSTSTDCDP; - if (IntrinsicID == Intrinsic::ppc_test_data_class_f) - CmprOpc = PPC::XSTSTDCSP; + case Intrinsic::ppc_test_data_class: { + EVT OpVT = Op.getOperand(1).getValueType(); + unsigned CmprOpc = OpVT == MVT::f128 ? PPC::XSTSTDCQP + : (OpVT == MVT::f64 ? PPC::XSTSTDCDP + : PPC::XSTSTDCSP); return SDValue( DAG.getMachineNode( PPC::SELECT_CC_I4, dl, MVT::i32, diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-p9-f128.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-p9-f128.ll --- a/llvm/test/CodeGen/PowerPC/builtins-ppc-p9-f128.ll +++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-p9-f128.ll @@ -136,3 +136,16 @@ ; Function Attrs: nounwind readnone declare i64 @llvm.ppc.scalar.extract.expq(fp128) +define i32 @test_data_class_f128(fp128 %d) { +entry: + %test_data_class = tail call i32 @llvm.ppc.test.data.class.f128(fp128 %d, i32 0) + ret i32 %test_data_class +; CHECK-LABEL: test_data_class_f128: +; CHECK: xststdcqp cr0, v2, 0 +; CHECK-NEXT: li r3, 0 +; CHECK-NEXT: li r4, 1 +; CHECK-NEXT: iseleq r3, r4, r3 +; CHECK-NEXT: blr +} + +declare i32 @llvm.ppc.test.data.class.f128(fp128, i32 immarg) diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-test.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-test.ll --- a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-test.ll +++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-test.ll @@ -77,11 +77,11 @@ ; CHECK-NEXT: iseleq 3, 4, 3 ; CHECK-NEXT: blr entry: - %test_data_class = tail call i32 @llvm.ppc.test.data.class.d(double %d, i32 0) + %test_data_class = tail call i32 @llvm.ppc.test.data.class.f64(double %d, i32 0) ret i32 %test_data_class } -declare i32 @llvm.ppc.test.data.class.d(double, i32 immarg) +declare i32 @llvm.ppc.test.data.class.f64(double, i32 immarg) define i32 @test_builtin_ppc_test_data_class_f(float %f) { ; CHECK-LABEL: test_builtin_ppc_test_data_class_f: @@ -92,8 +92,8 @@ ; CHECK-NEXT: iseleq 3, 4, 3 ; CHECK-NEXT: blr entry: - %test_data_class = tail call i32 @llvm.ppc.test.data.class.f(float %f, i32 127) + %test_data_class = tail call i32 @llvm.ppc.test.data.class.f32(float %f, i32 127) ret i32 %test_data_class } -declare i32 @llvm.ppc.test.data.class.f(float, i32 immarg) +declare i32 @llvm.ppc.test.data.class.f32(float, i32 immarg)