This patch adds Hardware Transaction Memory (HTM) support supported by ISA 2.07 (POWER8). The intrinsic support is based on GCC one [1], but currently only the 'PowerPC HTM Low Level Built-in Function' are implemented.
Along with builtins a new driver switch is added to enable/disable HTM instruction support (-mhtm) and a header with common definitions (mostly to parse the TFHAR register value). The HTM switch also sets a preprocessor builtin __HTM__. The HTM usage requires a recently newer kernel with PPC HTM enabled. Tested on powerpc64 and powerpc64le. This is send along a llvm patch to enabled the builtins and option switch. [1] https://gcc.gnu.org/onlinedocs/gcc/PowerPC-Hardware-Transactional-Memory-Built-in-Functions.html --- include/clang/Basic/BuiltinsPPC.def | 31 +++++++++ include/clang/Driver/Options.td | 2 + lib/Basic/Targets.cpp | 11 +++- lib/CodeGen/CGBuiltin.cpp | 86 ++++++++++++++++++++++++ lib/Headers/htmintrin.h | 127 ++++++++++++++++++++++++++++++++++++ test/CodeGen/builtins-ppc-htm.c | 62 ++++++++++++++++++ 6 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 lib/Headers/htmintrin.h create mode 100644 test/CodeGen/builtins-ppc-htm.c diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def index e42af42..cfaceb5 100644 --- a/include/clang/Basic/BuiltinsPPC.def +++ b/include/clang/Basic/BuiltinsPPC.def @@ -223,6 +223,37 @@ BUILTIN(__builtin_vsx_xsmindp, "ddd", "") BUILTIN(__builtin_vsx_xvdivdp, "V2dV2dV2d", "") BUILTIN(__builtin_vsx_xvdivsp, "V4fV4fV4f", "") +// HTM builtins +BUILTIN(__builtin_tbegin, "UiUIi", "") +BUILTIN(__builtin_tend, "UiUIi", "") + +BUILTIN(__builtin_tabort, "UiUi", "") +BUILTIN(__builtin_tabortdc, "UiUiUiUi", "") +BUILTIN(__builtin_tabortdci, "UiUiUii", "") +BUILTIN(__builtin_tabortwc, "UiUiUiUi", "") +BUILTIN(__builtin_tabortwci, "UiUiUii", "") + +BUILTIN(__builtin_tcheck, "UiUi", "") +BUILTIN(__builtin_treclaim, "UiUi", "") +BUILTIN(__builtin_trechkpt, "Ui", "") +BUILTIN(__builtin_tsr, "UiUi", "") + +BUILTIN(__builtin_tendall, "Ui", "") +BUILTIN(__builtin_tresume, "Ui", "") +BUILTIN(__builtin_tsuspend, "Ui", "") + +BUILTIN(__builtin_get_texasr, "LUi", "c") +BUILTIN(__builtin_get_texasru, "LUi", "c") +BUILTIN(__builtin_get_tfhar, "LUi", "c") +BUILTIN(__builtin_get_tfiar, "LUi", "c") + +BUILTIN(__builtin_set_texasr, "vLUi", "c") +BUILTIN(__builtin_set_texasru, "vLUi", "c") +BUILTIN(__builtin_set_tfhar, "vLUi", "c") +BUILTIN(__builtin_set_tfiar, "vLUi", "c") + +BUILTIN(__builtin_ttest, "LUi", "") + // FIXME: Obviously incomplete. #undef BUILTIN diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 80f68ef..30553aa 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1230,6 +1230,8 @@ def mpower8_vector : Flag<["-"], "mpower8-vector">, Group<m_ppc_Features_Group>; def mno_power8_vector : Flag<["-"], "mno-power8-vector">, Group<m_ppc_Features_Group>; +def mhtm : Flag<["-"], "mhtm">, Group<m_ppc_Features_Group>; +def mno_htm : Flag<["-"], "mno-htm">, Group<m_ppc_Features_Group>; def mfprnd : Flag<["-"], "mfprnd">, Group<m_ppc_Features_Group>; def mno_fprnd : Flag<["-"], "mno-fprnd">, Group<m_ppc_Features_Group>; def mcmpb : Flag<["-"], "mcmpb">, Group<m_ppc_Features_Group>; diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index f9da2bf..6c8183b 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -704,13 +704,14 @@ class PPCTargetInfo : public TargetInfo { // Target cpu features. bool HasVSX; bool HasP8Vector; + bool HasHTM; protected: std::string ABI; public: PPCTargetInfo(const llvm::Triple &Triple) - : TargetInfo(Triple), HasVSX(false), HasP8Vector(false) { + : TargetInfo(Triple), HasVSX(false), HasP8Vector(false), HasHTM(false) { BigEndian = (Triple.getArch() != llvm::Triple::ppc64le); LongDoubleWidth = LongDoubleAlign = 128; LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble; @@ -971,6 +972,11 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, continue; } + if (Feature == "htm") { + HasHTM = true; + continue; + } + // TODO: Finish this list and add an assert that we've handled them // all. } @@ -1123,6 +1129,8 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__VSX__"); if (HasP8Vector) Builder.defineMacro("__POWER8_VECTOR__"); + if (HasHTM) + Builder.defineMacro("__HTM__"); // FIXME: The following are not yet generated here by Clang, but are // generated by GCC: @@ -1168,6 +1176,7 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const { .Case("powerpc", true) .Case("vsx", HasVSX) .Case("power8-vector", HasP8Vector) + .Case("htm", HasHTM) .Default(false); } diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 859ad3e..b622d59 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -6347,6 +6347,92 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, llvm::Function *F = CGM.getIntrinsic(ID); return Builder.CreateCall(F, Ops, ""); } + + // HTM builtins + case PPC::BI__builtin_tbegin: + case PPC::BI__builtin_tend: + case PPC::BI__builtin_tcheck: + case PPC::BI__builtin_tsr: { + unsigned int MaxValue; + // The HTM instructions only accepts one argument and with limited range. + ConstantInt *CI = dyn_cast<ConstantInt>(Ops[0]); + assert(CI); + switch (BuiltinID) { + case PPC::BI__builtin_tbegin: + ID = Intrinsic::ppc_tbegin; + MaxValue = 1; + break; + case PPC::BI__builtin_tend: + ID = Intrinsic::ppc_tend; + MaxValue = 1; + break; + case PPC::BI__builtin_tsr: + ID = Intrinsic::ppc_tsr; + MaxValue = 7; + break; + case PPC::BI__builtin_tcheck: + ID = Intrinsic::ppc_tcheck; + MaxValue = 7; + break; + } + if (CI->getZExtValue() > MaxValue) { + CGM.ErrorUnsupported(E->getArg(0), "argument out of range (should be 0 or 1)"); + return llvm::UndefValue::get(Ops[0]->getType()); + } + + llvm::Function *F = CGM.getIntrinsic(ID); + return Builder.CreateCall(F, Ops, ""); + } + case PPC::BI__builtin_tabortdc: + case PPC::BI__builtin_tabortwc: { + // For wd and dc variant of tabort first argument must be a 5-bits constant + // integer + ConstantInt *CI = dyn_cast<ConstantInt>(Ops[0]); + assert(CI); + if (CI->getZExtValue() > 31) { + CGM.ErrorUnsupported(E->getArg(0), "argument out of range (should be 0-31)"); + return llvm::UndefValue::get(Ops[0]->getType()); + } + switch (BuiltinID) { + case PPC::BI__builtin_tabortdc: + ID = Intrinsic::ppc_tabortdc; + break; + case PPC::BI__builtin_tabortwc: + ID = Intrinsic::ppc_tabortwc; + break; + } + llvm::Function *F = CGM.getIntrinsic(ID); + return Builder.CreateCall(F, Ops, ""); + } + case PPC::BI__builtin_tabortdci: + case PPC::BI__builtin_tabortwci: { + // For wd and dc variant of tabort first and third argument must be a + // 5-bits constant integer + ConstantInt *CI = dyn_cast<ConstantInt>(Ops[0]); + assert(CI); + if (CI->getZExtValue() > 31) { + CGM.ErrorUnsupported(E->getArg(0), "argument out of range (should be 0-31)"); + return llvm::UndefValue::get(Ops[0]->getType()); + } + CI = dyn_cast<ConstantInt>(Ops[2]); + assert(CI); + if (CI->getZExtValue() > 31) { + CGM.ErrorUnsupported(E->getArg(2), "argument out of range (should be 0-31)"); + return llvm::UndefValue::get(Ops[2]->getType()); + } + switch (BuiltinID) { + default: llvm_unreachable("Unsupported htm intrinsic!"); + case PPC::BI__builtin_tabortdci: + ID = Intrinsic::ppc_tabortdci; + break; + case PPC::BI__builtin_tabortwci: + ID = Intrinsic::ppc_tabortwci; + break; + } + llvm::Function *F = CGM.getIntrinsic(ID); + return Builder.CreateCall(F, Ops, ""); + } + } } diff --git a/lib/Headers/htmintrin.h b/lib/Headers/htmintrin.h new file mode 100644 index 0000000..9f6b166 --- /dev/null +++ b/lib/Headers/htmintrin.h @@ -0,0 +1,127 @@ +/*===---- htmintrin.h - Standard header for PowerPC HTM ---------------===*\ + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * +\*===----------------------------------------------------------------------===*/ + +#ifndef __HTMINTRIN_H +#define __HTMINTRIN_H + +#ifndef __HTM__ +#error "HTM instruction set not enabled" +#endif + +#include <stdint.h> + +typedef uint64_t texasr_t; +typedef uint32_t texasru_t; +typedef uint32_t texasrl_t; +typedef uintptr_t tfiar_t; +typedef uintptr_t tfhar_t; + +#define _HTM_STATE(CR0) ((CR0 >> 1) & 0x3) +#define _HTM_NONTRANSACTIONAL 0x0 +#define _HTM_SUSPENDED 0x1 +#define _HTM_TRANSACTIONAL 0x2 + +#define _TEXASR_EXTRACT_BITS(TEXASR,BITNUM,SIZE) \ + (((TEXASR) >> (63-(BITNUM))) & ((1<<(SIZE))-1)) +#define _TEXASRU_EXTRACT_BITS(TEXASR,BITNUM,SIZE) \ + (((TEXASR) >> (31-(BITNUM))) & ((1<<(SIZE))-1)) + +#define _TEXASR_FAILURE_CODE(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 7, 8) +#define _TEXASRU_FAILURE_CODE(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 7, 8) + +#define _TEXASR_FAILURE_PERSISTENT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 7, 1) +#define _TEXASRU_FAILURE_PERSISTENT(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 7, 1) + +#define _TEXASR_DISALLOWED(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 8, 1) +#define _TEXASRU_DISALLOWED(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 8, 1) + +#define _TEXASR_NESTING_OVERFLOW(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 9, 1) +#define _TEXASRU_NESTING_OVERFLOW(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 9, 1) + +#define _TEXASR_FOOTPRINT_OVERFLOW(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 10, 1) +#define _TEXASRU_FOOTPRINT_OVERFLOW(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 10, 1) + +#define _TEXASR_SELF_INDUCED_CONFLICT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 11, 1) +#define _TEXASRU_SELF_INDUCED_CONFLICT(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 11, 1) + +#define _TEXASR_NON_TRANSACTIONAL_CONFLICT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 12, 1) +#define _TEXASRU_NON_TRANSACTIONAL_CONFLICT(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 12, 1) + +#define _TEXASR_TRANSACTION_CONFLICT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 13, 1) +#define _TEXASRU_TRANSACTION_CONFLICT(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 13, 1) + +#define _TEXASR_TRANSLATION_INVALIDATION_CONFLICT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 14, 1) +#define _TEXASRU_TRANSLATION_INVALIDATION_CONFLICT(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 14, 1) + +#define _TEXASR_IMPLEMENTAION_SPECIFIC(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 15, 1) +#define _TEXASRU_IMPLEMENTAION_SPECIFIC(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 15, 1) + +#define _TEXASR_INSTRUCTION_FETCH_CONFLICT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 16, 1) +#define _TEXASRU_INSTRUCTION_FETCH_CONFLICT(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 16, 1) + +#define _TEXASR_ABORT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 31, 1) +#define _TEXASRU_ABORT(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 31, 1) + + +#define _TEXASR_SUSPENDED(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 32, 1) + +#define _TEXASR_PRIVILEGE(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 35, 2) + +#define _TEXASR_FAILURE_SUMMARY(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 36, 1) + +#define _TEXASR_TFIAR_EXACT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 37, 1) + +#define _TEXASR_ROT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 38, 1) + +#define _TEXASR_TRANSACTION_LEVEL(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 63, 12) + +#endif /* __HTMINTRIN_H */ diff --git a/test/CodeGen/builtins-ppc-htm.c b/test/CodeGen/builtins-ppc-htm.c new file mode 100644 index 0000000..663c814 --- /dev/null +++ b/test/CodeGen/builtins-ppc-htm.c @@ -0,0 +1,62 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -faltivec -target-feature +htm -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck %s + +void test1(long int *r, int code, long int *a, long int *b) { +// CHECK-LABEL: define void @test1 + + r[0] = __builtin_tbegin (0); +// CHECK: @llvm.ppc.tbegin + r[1] = __builtin_tbegin (1); +// CHECK: @llvm.ppc.tbegin + r[2] = __builtin_tend (0); +// CHECK: @llvm.ppc.tend + r[3] = __builtin_tendall (); +// CHECK: @llvm.ppc.tendall + + r[4] = __builtin_tabort (code); +// CHECK: @llvm.ppc.tabort + r[5] = __builtin_tabort (0x1); +// CHECK: @llvm.ppc.tabort + r[6] = __builtin_tabortdc (0xf, a[0], b[0]); +// CHECK: @llvm.ppc.tabortdc + r[7] = __builtin_tabortdci (0xf, a[1], 0x1); +// CHECK: @llvm.ppc.tabortdc + r[8] = __builtin_tabortwc (0xf, a[2], b[2]); +// CHECK: @llvm.ppc.tabortwc + r[9] = __builtin_tabortwci (0xf, a[3], 0x1); +// CHECK: @llvm.ppc.tabortwc + + r[10] = __builtin_tcheck (0x1); +// CHECK: @llvm.ppc.tcheck + r[11] = __builtin_trechkpt (); +// CHECK: @llvm.ppc.trechkpt + r[12] = __builtin_treclaim (0); +// CHECK: @llvm.ppc.treclaim + r[13] = __builtin_tresume (); +// CHECK: @llvm.ppc.tresume + r[14] = __builtin_tsuspend (); +// CHECK: @llvm.ppc.tsuspend + r[15] = __builtin_tsr (0); +// CHECK: @llvm.ppc.tsr + + r[16] = __builtin_ttest (); +// CHECK: @llvm.ppc.ttest + + r[17] = __builtin_get_texasr (); +// CHECK: @llvm.ppc.get.texasr + r[18] = __builtin_get_texasru (); +// CHECK: @llvm.ppc.get.texasru + r[19] = __builtin_get_tfhar (); +// CHECK: @llvm.ppc.get.tfhar + r[20] = __builtin_get_tfiar (); +// CHECK: @llvm.ppc.get.tfiar + + __builtin_set_texasr (a[21]); +// CHECK: @llvm.ppc.set.texasr + __builtin_set_texasru (a[22]); +// CHECK: @llvm.ppc.set.texasru + __builtin_set_tfhar (a[23]); +// CHECK: @llvm.ppc.set.tfhar + __builtin_set_tfiar (a[24]); +// CHECK: @llvm.ppc.set.tfiar +} _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
