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 @@ -101,6 +101,8 @@ BUILTIN(__builtin_ppc_compare_exp_gt, "idd", "") BUILTIN(__builtin_ppc_compare_exp_eq, "idd", "") BUILTIN(__builtin_ppc_test_data_class, "idIi", "t") +BUILTIN(__builtin_ppc_swdiv, "ddd", "") +BUILTIN(__builtin_ppc_swdivs, "fff", "") // Compare BUILTIN(__builtin_ppc_cmpeqb, "LLiLLiLLi", "") BUILTIN(__builtin_ppc_cmprb, "iCIiii", "") 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 @@ -243,6 +243,8 @@ Builder.defineMacro("__compare_exp_gt", "__builtin_ppc_compare_exp_gt"); Builder.defineMacro("__compare_exp_eq", "__builtin_ppc_compare_exp_eq"); Builder.defineMacro("__test_data_class", "__builtin_ppc_test_data_class"); + Builder.defineMacro("__swdiv", "__builtin_ppc_swdiv"); + Builder.defineMacro("__swdivs", "__builtin_ppc_swdivs"); } /// 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 @@ -16077,7 +16077,7 @@ *this, E, Intrinsic::sqrt, Intrinsic::experimental_constrained_sqrt)) .getScalarVal(); - case PPC::BI__builtin_ppc_test_data_class: + case PPC::BI__builtin_ppc_test_data_class: { llvm::Type *ArgType = EmitScalarExpr(E->getArg(0))->getType(); unsigned IntrinsicID; if (ArgType->isDoubleTy()) @@ -16089,6 +16089,10 @@ return Builder.CreateCall(CGM.getIntrinsic(IntrinsicID), Ops, "test_data_class"); } + case PPC::BI__builtin_ppc_swdiv: + case PPC::BI__builtin_ppc_swdivs: + return Builder.CreateFDiv(Ops[0], Ops[1], "swdiv"); + } } namespace { diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-swdiv.c b/clang/test/CodeGen/builtins-ppc-xlcompat-swdiv.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-swdiv.c @@ -0,0 +1,80 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu \ +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -ffast-math -ffp-contract=fast \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s --check-prefix CHECK-OFAST + +extern double a; +extern double b; +extern float c; +extern float d; + +// CHECK-LABEL: @test_swdiv( +// CHECK: [[TMP0:%.*]] = load double, double* @a +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @b +// CHECK-NEXT: [[SWDIV:%.*]] = fdiv double [[TMP0]], [[TMP1]] +// CHECK-NEXT: ret double [[SWDIV]] +// +// CHECK-OFAST-LABEL: @test_swdiv( +// CHECK-OFAST: [[TMP0:%.*]] = load double, double* @a +// CHECK-OFAST-NEXT: [[TMP1:%.*]] = load double, double* @b +// CHECK-OFAST-NEXT: [[SWDIV:%.*]] = fdiv fast double [[TMP0]], [[TMP1]] +// CHECK-OFAST-NEXT: ret double [[SWDIV]] +// +double test_swdiv() { + return __swdiv(a, b); +} + +// CHECK-LABEL: @test_swdivs( +// CHECK: [[TMP0:%.*]] = load float, float* @c +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* @d +// CHECK-NEXT: [[SWDIVS:%.*]] = fdiv float [[TMP0]], [[TMP1]] +// CHECK-NEXT: ret float [[SWDIVS]] +// +// CHECK-OFAST-LABEL: @test_swdivs( +// CHECK-OFAST: [[TMP0:%.*]] = load float, float* @c +// CHECK-OFAST-NEXT: [[TMP1:%.*]] = load float, float* @d +// CHECK-OFAST-NEXT: [[SWDIVS:%.*]] = fdiv fast float [[TMP0]], [[TMP1]] +// CHECK-OFAST-NEXT: ret float [[SWDIVS]] +// +float test_swdivs() { + return __swdivs(c, d); +} + +// CHECK-LABEL: @test_builtin_ppc_swdiv( +// CHECK: [[TMP0:%.*]] = load double, double* @a +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @b +// CHECK-NEXT: [[SWDIV:%.*]] = fdiv double [[TMP0]], [[TMP1]] +// CHECK-NEXT: ret double [[SWDIV]] +// +// CHECK-OFAST-LABEL: @test_builtin_ppc_swdiv( +// CHECK-OFAST: [[TMP0:%.*]] = load double, double* @a +// CHECK-OFAST-NEXT: [[TMP1:%.*]] = load double, double* @b +// CHECK-OFAST-NEXT: [[SWDIV:%.*]] = fdiv fast double [[TMP0]], [[TMP1]] +// CHECK-OFAST-NEXT: ret double [[SWDIV]] +// +double test_builtin_ppc_swdiv() { + return __builtin_ppc_swdiv(a, b); +} + +// CHECK-LABEL: @test_builtin_ppc_swdivs( +// CHECK: [[TMP0:%.*]] = load float, float* @c +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* @d +// CHECK-NEXT: [[SWDIVS:%.*]] = fdiv float [[TMP0]], [[TMP1]] +// CHECK-NEXT: ret float [[SWDIVS]] +// +// CHECK-OFAST-LABEL: @test_builtin_ppc_swdivs( +// CHECK-OFAST: [[TMP0:%.*]] = load float, float* @c +// CHECK-OFAST-NEXT: [[TMP1:%.*]] = load float, float* @d +// CHECK-OFAST-NEXT: [[SWDIVS:%.*]] = fdiv fast float [[TMP0]], [[TMP1]] +// CHECK-OFAST-NEXT: ret float [[SWDIVS]] +// +float test_builtin_ppc_swdivs() { + return __builtin_ppc_swdivs(c, d); +} diff --git a/llvm/test/CodeGen/PowerPC/fdiv.ll b/llvm/test/CodeGen/PowerPC/fdiv.ll --- a/llvm/test/CodeGen/PowerPC/fdiv.ll +++ b/llvm/test/CodeGen/PowerPC/fdiv.ll @@ -23,3 +23,16 @@ %3 = fdiv contract reassoc arcp nsz ninf float %0, %1 ret float %3 } + +define dso_local float @fdiv_fast(float %0, float %1) local_unnamed_addr { +; CHECK-LABEL: fdiv_fast: +; CHECK: # %bb.0: +; CHECK-NEXT: xsresp 3, 2 +; CHECK-NEXT: xsmulsp 0, 1, 3 +; CHECK-NEXT: xsnmsubasp 1, 2, 0 +; CHECK-NEXT: xsmaddasp 0, 3, 1 +; CHECK-NEXT: fmr 1, 0 +; CHECK-NEXT: blr + %3 = fdiv fast float %0, %1 + ret float %3 +}