Skip to content

Commit

Permalink
[PowerPC] Support test data class intrinsic of 128-bit float
Browse files Browse the repository at this point in the history
We've exploited test data class instructions introduced in ISA 3.0.
This change unifies the scalar intrinsics into ppc_test_data_class
and add support for 128-bit precision float values using xststdcqp.

Vector versions of the intrinsic can't be unified because they return
vector int instead of int.

Reviewed By: shchenz

Differential Revision: https://reviews.llvm.org/D138105
  • Loading branch information
ecnelises committed Dec 7, 2022
1 parent 49e928b commit 62f20f5
Show file tree
Hide file tree
Showing 10 changed files with 43 additions and 33 deletions.
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Expand Up @@ -10004,7 +10004,7 @@ def err_ppc_builtin_requires_abi : Error<
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<
Expand Down
13 changes: 3 additions & 10 deletions clang/lib/CodeGen/CGBuiltin.cpp
Expand Up @@ -16669,16 +16669,9 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
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));
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Sema/SemaChecking.cpp
Expand Up @@ -4271,10 +4271,11 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
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",
Expand Down
6 changes: 6 additions & 0 deletions clang/test/CodeGen/PowerPC/builtins-ppc-p9-f128.c
Expand Up @@ -60,3 +60,9 @@ unsigned long long int extract_exp(void) {
// 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]]
}
Expand Up @@ -44,5 +44,5 @@ int test_test_data_class_f() {
}

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}}
}
8 changes: 4 additions & 4 deletions clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-test.c
Expand Up @@ -54,7 +54,7 @@ int test_builtin_ppc_compare_exp_eq() {

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
Expand All @@ -63,7 +63,7 @@ int test_builtin_ppc_test_data_class_d() {

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
Expand Down Expand Up @@ -108,7 +108,7 @@ int test_compare_exp_eq() {

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
Expand All @@ -117,7 +117,7 @@ int test_test_data_class_d() {

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
Expand Down
9 changes: 3 additions & 6 deletions llvm/include/llvm/IR/IntrinsicsPowerPC.td
Expand Up @@ -1893,12 +1893,9 @@ let TargetPrefix = "ppc" in {
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<ArgIndex<1>>]>;
def int_ppc_test_data_class_f : DefaultAttrsIntrinsic<[llvm_i32_ty],
[llvm_float_ty, llvm_i32_ty],
[IntrNoMem, ImmArg<ArgIndex<1>>]>;
def int_ppc_test_data_class : Intrinsic<[llvm_i32_ty],
[llvm_anyfloat_ty, llvm_i32_ty],
[IntrNoMem, ImmArg<ArgIndex<1>>]>;
def int_ppc_fnabs
: ClangBuiltin<"__builtin_ppc_fnabs">,
DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>;
Expand Down
10 changes: 5 additions & 5 deletions llvm/lib/Target/PowerPC/PPCISelLowering.cpp
Expand Up @@ -10689,11 +10689,11 @@ SDValue PPCTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
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,
Expand Down
13 changes: 13 additions & 0 deletions llvm/test/CodeGen/PowerPC/builtins-ppc-p9-f128.ll
Expand Up @@ -136,3 +136,16 @@ entry:
; 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)
8 changes: 4 additions & 4 deletions llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-test.ll
Expand Up @@ -77,11 +77,11 @@ define i32 @test_builtin_ppc_test_data_class_d(double %d) {
; 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:
Expand All @@ -92,8 +92,8 @@ define i32 @test_builtin_ppc_test_data_class_f(float %f) {
; 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)

0 comments on commit 62f20f5

Please sign in to comment.