From 1ed200ed06c67c63c037de190ef696aa8425312f Mon Sep 17 00:00:00 2001 From: Nemanja Ivanovic Date: Thu, 9 Apr 2015 23:58:16 +0000 Subject: [PATCH] Add Clang support for remaining integer divide and permute instructions from ISA 2.06 This patch corresponds to review: http://reviews.llvm.org/D8398 It adds some builtin functions to access the extended divide and bit permute instructions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@234547 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsPPC.def | 7 +++ include/clang/Basic/DiagnosticSemaKinds.td | 4 ++ lib/Basic/Targets.cpp | 27 ++++++++++- lib/Sema/SemaChecking.cpp | 22 +++++++++ test/CodeGen/builtins-ppc-p7-disabled.c | 33 ++++++++++++++ test/CodeGen/builtins-ppc-p7.c | 52 ++++++++++++++++++++++ 6 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 test/CodeGen/builtins-ppc-p7-disabled.c create mode 100644 test/CodeGen/builtins-ppc-p7.c diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def index 8cc50db39d..09968182b0 100644 --- a/include/clang/Basic/BuiltinsPPC.def +++ b/include/clang/Basic/BuiltinsPPC.def @@ -283,6 +283,13 @@ BUILTIN(__builtin_set_tfiar, "vLUi", "c") BUILTIN(__builtin_ttest, "LUi", "") +// Scalar built-ins +BUILTIN(__builtin_divwe, "SiSiSi", "") +BUILTIN(__builtin_divweu, "UiUiUi", "") +BUILTIN(__builtin_divde, "SLLiSLLiSLLi", "") +BUILTIN(__builtin_divdeu, "ULLiULLiULLi", "") +BUILTIN(__builtin_bpermd, "SLLiSLLiSLLi", "") + // FIXME: Obviously incomplete. #undef BUILTIN diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 901d50028d..bb2f55c5a0 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -7045,6 +7045,10 @@ def note_neon_vector_initializer_non_portable_q : Note< "constants">; def err_systemz_invalid_tabort_code : Error< "invalid transaction abort code">; +def err_64_bit_builtin_32_bit_tgt : Error< + "this builtin is only available on 64-bit targets">; +def err_ppc_builtin_only_on_pwr7 : Error< + "this builtin is only valid on POWER7 or later CPUs">; def err_builtin_longjmp_unsupported : Error< "__builtin_longjmp is not supported for the current target">; diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 6d6a5d77e8..1512eb7a16 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -744,6 +744,8 @@ class PPCTargetInfo : public TargetInfo { bool HasP8Crypto; bool HasQPX; bool HasHTM; + bool HasBPERMD; + bool HasExtDiv; protected: std::string ABI; @@ -751,7 +753,8 @@ protected: public: PPCTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple), HasVSX(false), HasP8Vector(false), - HasP8Crypto(false), HasQPX(false), HasHTM(false) { + HasP8Crypto(false), HasQPX(false), HasHTM(false), + HasBPERMD(false), HasExtDiv(false) { BigEndian = (Triple.getArch() != llvm::Triple::ppc64le); LongDoubleWidth = LongDoubleAlign = 128; LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble; @@ -1011,6 +1014,16 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector &Features, continue; } + if (Feature == "bpermd") { + HasBPERMD = true; + continue; + } + + if (Feature == "extdiv") { + HasExtDiv = true; + continue; + } + if (Feature == "power8-vector") { HasP8Vector = true; continue; @@ -1233,6 +1246,16 @@ void PPCTargetInfo::getDefaultFeatures(llvm::StringMap &Features) const { .Case("ppc64le", true) .Case("pwr8", true) .Default(false); + Features["bpermd"] = llvm::StringSwitch(CPU) + .Case("ppc64le", true) + .Case("pwr8", true) + .Case("pwr7", true) + .Default(false); + Features["extdiv"] = llvm::StringSwitch(CPU) + .Case("ppc64le", true) + .Case("pwr8", true) + .Case("pwr7", true) + .Default(false); } bool PPCTargetInfo::hasFeature(StringRef Feature) const { @@ -1243,6 +1266,8 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const { .Case("crypto", HasP8Crypto) .Case("qpx", HasQPX) .Case("htm", HasHTM) + .Case("bpermd", HasBPERMD) + .Case("extdiv", HasExtDiv) .Default(false); } diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index d4390e53f0..05eaaec579 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -907,6 +907,28 @@ bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { bool Sema::CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { unsigned i = 0, l = 0, u = 0; + bool Is64BitBltin = BuiltinID == PPC::BI__builtin_divde || + BuiltinID == PPC::BI__builtin_divdeu || + BuiltinID == PPC::BI__builtin_bpermd; + bool IsTarget64Bit = Context.getTargetInfo() + .getTypeWidth(Context + .getTargetInfo() + .getIntPtrType()) == 64; + bool IsBltinExtDiv = BuiltinID == PPC::BI__builtin_divwe || + BuiltinID == PPC::BI__builtin_divweu || + BuiltinID == PPC::BI__builtin_divde || + BuiltinID == PPC::BI__builtin_divdeu; + + if (Is64BitBltin && !IsTarget64Bit) + return Diag(TheCall->getLocStart(), diag::err_64_bit_builtin_32_bit_tgt) + << TheCall->getSourceRange(); + + if ((IsBltinExtDiv && !Context.getTargetInfo().hasFeature("extdiv")) || + (BuiltinID == PPC::BI__builtin_bpermd && + !Context.getTargetInfo().hasFeature("bpermd"))) + return Diag(TheCall->getLocStart(), diag::err_ppc_builtin_only_on_pwr7) + << TheCall->getSourceRange(); + switch (BuiltinID) { default: return false; case PPC::BI__builtin_altivec_crypto_vshasigmaw: diff --git a/test/CodeGen/builtins-ppc-p7-disabled.c b/test/CodeGen/builtins-ppc-p7-disabled.c new file mode 100644 index 0000000000..9ccedd2ce8 --- /dev/null +++ b/test/CodeGen/builtins-ppc-p7-disabled.c @@ -0,0 +1,33 @@ +// REQUIRES: powerpc-registered-target +// RUN: not %clang_cc1 -triple powerpc64-unknown-unknown \ +// RUN: -target-cpu pwr6 -emit-llvm %s -o - 2>&1 \ +// RUN: | FileCheck %s + +// RUN: not %clang_cc1 -triple powerpc-unknown-unknown -emit-llvm %s -o - 2>&1 \ +// RUN: -target-cpu pwr7 | FileCheck %s -check-prefix=CHECK-32 + +void call_p7_builtins(void) +{ + int a = __builtin_divwe(33, 11); + unsigned int b = __builtin_divweu(33U, 11U); + unsigned long long d = __builtin_divde(33ULL, 11ULL); + unsigned long long e = __builtin_divdeu(33ULL, 11ULL); + unsigned long long f = __builtin_bpermd(33ULL, 11ULL); +} + +// CHECK: error: this builtin is only valid on POWER7 or later CPUs +// CHECK: __builtin_divwe +// CHECK: error: this builtin is only valid on POWER7 or later CPUs +// CHECK: __builtin_divweu +// CHECK: error: this builtin is only valid on POWER7 or later CPUs +// CHECK: __builtin_divde +// CHECK: error: this builtin is only valid on POWER7 or later CPUs +// CHECK: __builtin_divdeu +// CHECK: error: this builtin is only valid on POWER7 or later CPUs +// CHECK: __builtin_bpermd +// CHECK-32: error: this builtin is only available on 64-bit targets +// CHECK-32: __builtin_divde +// CHECK-32: error: this builtin is only available on 64-bit targets +// CHECK-32: __builtin_divdeu +// CHECK-32: error: this builtin is only available on 64-bit targets +// CHECK-32: __builtin_bpermd diff --git a/test/CodeGen/builtins-ppc-p7.c b/test/CodeGen/builtins-ppc-p7.c new file mode 100644 index 0000000000..f584410308 --- /dev/null +++ b/test/CodeGen/builtins-ppc-p7.c @@ -0,0 +1,52 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -target-cpu pwr7 \ +// RUN: -emit-llvm %s -o - | FileCheck %s + +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -target-cpu pwr8 \ +// RUN: -emit-llvm %s -o - | FileCheck %s + +// CHECK-LABEL: define signext i32 @test_divwe +int test_divwe(void) +{ + int a = 74; + int b = 32; + return __builtin_divwe(a, b); +// CHECK @llvm.ppc.divwe +} + +// CHECK-LABEL: define zeroext i32 @test_divweu +unsigned int test_divweu(void) +{ + unsigned int a = 74; + unsigned int b = 32; + return __builtin_divweu(a, b); +// CHECK @llvm.ppc.divweu +} + +// CHECK-LABEL: define i64 @test_divde +long long test_divde(void) +{ + long long a = 74LL; + long long b = 32LL; + return __builtin_divde(a, b); +// CHECK @llvm.ppc.divde +} + +// CHECK-LABEL: define i64 @test_divdeu +unsigned long long test_divdeu(void) +{ + unsigned long long a = 74ULL; + unsigned long long b = 32ULL; + return __builtin_divdeu(a, b); +// CHECK @llvm.ppc.divdeu +} + +// CHECK-LABEL: define i64 @test_bpermd +long long test_bpermd(void) +{ + long long a = 74LL; + long long b = 32LL; + return __builtin_bpermd(a, b); +// CHECK @llvm.ppc.bpermd +} + -- 2.40.0