forked from OSchip/llvm-project
[SystemZ] Support transactional execution on zEC12
The zEC12 provides the transactional-execution facility. This is exposed to users via a set of builtin routines on other compilers. This patch adds clang support to enable those builtins. In partciular, the patch: - enables the transactional-execution feature by default on zEC12 - allows to override presence of that feature via the -mhtm/-mno-htm options - adds a predefined macro __HTM__ if the feature is enabled - adds support for the transactional-execution GCC builtins - adds Sema checking to verify the __builtin_tabort abort code - adds the s390intrin.h header file (for GCC compatibility) - adds s390 sections to the htmintrin.h and htmxlintrin.h header files Since this is first use of target-specific intrinsics on the platform, the patch creates the include/clang/Basic/BuiltinsSystemZ.def file and hooks it up in TargetBuiltins.h and lib/Basic/Targets.cpp. An associated LLVM patch adds the required LLVM IR intrinsics. For reference, the transactional-execution instructions are documented in the z/Architecture Principles of Operation for the zEC12: http://publibfp.boulder.ibm.com/cgi-bin/bookmgr/download/DZ9ZR009.pdf The associated builtins are documented in the GCC manual: http://gcc.gnu.org/onlinedocs/gcc/S_002f390-System-z-Built-in-Functions.html The htmxlintrin.h intrinsics provided for compatibility with the IBM XL compiler are documented in the "z/OS XL C/C++ Programming Guide". llvm-svn: 233804
This commit is contained in:
parent
57c85f53ba
commit
3a610ebf1e
|
@ -0,0 +1,27 @@
|
|||
//===-- BuiltinsSystemZ.def - SystemZ Builtin function database -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the SystemZ-specific builtin function database. Users of
|
||||
// this file must define the BUILTIN macro to make use of this information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// The format of this database matches clang/Basic/Builtins.def.
|
||||
|
||||
// Transactional-memory intrinsics
|
||||
BUILTIN(__builtin_tbegin, "iv*", "j")
|
||||
BUILTIN(__builtin_tbegin_nofloat, "iv*", "j")
|
||||
BUILTIN(__builtin_tbeginc, "v", "nj")
|
||||
BUILTIN(__builtin_tabort, "vi", "r")
|
||||
BUILTIN(__builtin_tend, "i", "n")
|
||||
BUILTIN(__builtin_tx_nesting_depth, "i", "nc")
|
||||
BUILTIN(__builtin_tx_assist, "vi", "n")
|
||||
BUILTIN(__builtin_non_tx_store, "vULi*ULi", "")
|
||||
|
||||
#undef BUILTIN
|
|
@ -7040,6 +7040,8 @@ def note_neon_vector_initializer_non_portable_q : Note<
|
|||
"consider using vld1q_%0%1() to initialize a vector from memory, or "
|
||||
"vcombine_%0%1(vcreate_%0%1(), vcreate_%0%1()) to initialize from integer "
|
||||
"constants">;
|
||||
def err_systemz_invalid_tabort_code : Error<
|
||||
"invalid transaction abort code">;
|
||||
|
||||
def err_builtin_longjmp_unsupported : Error<
|
||||
"__builtin_longjmp is not supported for the current target">;
|
||||
|
|
|
@ -175,6 +175,15 @@ namespace clang {
|
|||
};
|
||||
}
|
||||
|
||||
/// \brief SystemZ builtins
|
||||
namespace SystemZ {
|
||||
enum {
|
||||
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
|
||||
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
|
||||
#include "clang/Basic/BuiltinsSystemZ.def"
|
||||
LastTSBuiltin
|
||||
};
|
||||
}
|
||||
} // end namespace clang.
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8458,6 +8458,7 @@ private:
|
|||
|
||||
bool CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
|
||||
bool CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
|
||||
bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
|
||||
bool CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
|
||||
bool CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
|
||||
|
||||
|
|
|
@ -5407,10 +5407,14 @@ public:
|
|||
};
|
||||
|
||||
class SystemZTargetInfo : public TargetInfo {
|
||||
static const Builtin::Info BuiltinInfo[];
|
||||
static const char *const GCCRegNames[];
|
||||
std::string CPU;
|
||||
bool HasTransactionalExecution;
|
||||
|
||||
public:
|
||||
SystemZTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
|
||||
SystemZTargetInfo(const llvm::Triple &Triple)
|
||||
: TargetInfo(Triple), CPU("z10"), HasTransactionalExecution(false) {
|
||||
IntMaxType = SignedLong;
|
||||
Int64Type = SignedLong;
|
||||
TLSSupported = true;
|
||||
|
@ -5430,12 +5434,13 @@ public:
|
|||
Builder.defineMacro("__s390x__");
|
||||
Builder.defineMacro("__zarch__");
|
||||
Builder.defineMacro("__LONG_DOUBLE_128__");
|
||||
if (HasTransactionalExecution)
|
||||
Builder.defineMacro("__HTM__");
|
||||
}
|
||||
void getTargetBuiltins(const Builtin::Info *&Records,
|
||||
unsigned &NumRecords) const override {
|
||||
// FIXME: Implement.
|
||||
Records = nullptr;
|
||||
NumRecords = 0;
|
||||
Records = BuiltinInfo;
|
||||
NumRecords = clang::SystemZ::LastTSBuiltin-Builtin::FirstTSBuiltin;
|
||||
}
|
||||
|
||||
void getGCCRegNames(const char *const *&Names,
|
||||
|
@ -5456,16 +5461,41 @@ public:
|
|||
return TargetInfo::SystemZBuiltinVaList;
|
||||
}
|
||||
bool setCPU(const std::string &Name) override {
|
||||
CPU = Name;
|
||||
bool CPUKnown = llvm::StringSwitch<bool>(Name)
|
||||
.Case("z10", true)
|
||||
.Case("z196", true)
|
||||
.Case("zEC12", true)
|
||||
.Default(false);
|
||||
|
||||
// No need to store the CPU yet. There aren't any CPU-specific
|
||||
// macros to define.
|
||||
return CPUKnown;
|
||||
}
|
||||
void getDefaultFeatures(llvm::StringMap<bool> &Features) const override {
|
||||
if (CPU == "zEC12")
|
||||
Features["transactional-execution"] = true;
|
||||
}
|
||||
|
||||
bool handleTargetFeatures(std::vector<std::string> &Features,
|
||||
DiagnosticsEngine &Diags) override {
|
||||
HasTransactionalExecution = false;
|
||||
for (unsigned i = 0, e = Features.size(); i != e; ++i) {
|
||||
if (Features[i] == "+transactional-execution")
|
||||
HasTransactionalExecution = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hasFeature(StringRef Feature) const override {
|
||||
return llvm::StringSwitch<bool>(Feature)
|
||||
.Case("transactional-execution", HasTransactionalExecution)
|
||||
.Default(false);
|
||||
}
|
||||
};
|
||||
|
||||
const Builtin::Info SystemZTargetInfo::BuiltinInfo[] = {
|
||||
#define BUILTIN(ID, TYPE, ATTRS) \
|
||||
{ #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
|
||||
#include "clang/Basic/BuiltinsSystemZ.def"
|
||||
};
|
||||
|
||||
const char *const SystemZTargetInfo::GCCRegNames[] = {
|
||||
|
|
|
@ -1865,6 +1865,8 @@ Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
|
|||
case llvm::Triple::r600:
|
||||
case llvm::Triple::amdgcn:
|
||||
return EmitR600BuiltinExpr(BuiltinID, E);
|
||||
case llvm::Triple::systemz:
|
||||
return EmitSystemZBuiltinExpr(BuiltinID, E);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -6475,3 +6477,41 @@ Value *CodeGenFunction::EmitR600BuiltinExpr(unsigned BuiltinID,
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID,
|
||||
const CallExpr *E) {
|
||||
switch (BuiltinID) {
|
||||
case SystemZ::BI__builtin_tbegin: {
|
||||
Value *TDB = EmitScalarExpr(E->getArg(0));
|
||||
Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff0c);
|
||||
Value *F = CGM.getIntrinsic(Intrinsic::s390_tbegin);
|
||||
return Builder.CreateCall2(F, TDB, Control);
|
||||
}
|
||||
case SystemZ::BI__builtin_tbegin_nofloat: {
|
||||
Value *TDB = EmitScalarExpr(E->getArg(0));
|
||||
Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff0c);
|
||||
Value *F = CGM.getIntrinsic(Intrinsic::s390_tbegin_nofloat);
|
||||
return Builder.CreateCall2(F, TDB, Control);
|
||||
}
|
||||
case SystemZ::BI__builtin_tbeginc: {
|
||||
Value *TDB = llvm::ConstantPointerNull::get(Int8PtrTy);
|
||||
Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff08);
|
||||
Value *F = CGM.getIntrinsic(Intrinsic::s390_tbeginc);
|
||||
return Builder.CreateCall2(F, TDB, Control);
|
||||
}
|
||||
case SystemZ::BI__builtin_tabort: {
|
||||
Value *Data = EmitScalarExpr(E->getArg(0));
|
||||
Value *F = CGM.getIntrinsic(Intrinsic::s390_tabort);
|
||||
return Builder.CreateCall(F, Builder.CreateSExt(Data, Int64Ty, "tabort"));
|
||||
}
|
||||
case SystemZ::BI__builtin_non_tx_store: {
|
||||
Value *Address = EmitScalarExpr(E->getArg(0));
|
||||
Value *Data = EmitScalarExpr(E->getArg(1));
|
||||
Value *F = CGM.getIntrinsic(Intrinsic::s390_ntstg);
|
||||
return Builder.CreateCall2(F, Data, Address);
|
||||
}
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2434,6 +2434,7 @@ public:
|
|||
llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
|
||||
llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
|
||||
llvm::Value *EmitR600BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
|
||||
llvm::Value *EmitSystemZBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
|
||||
|
||||
llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E);
|
||||
llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E);
|
||||
|
|
|
@ -1418,6 +1418,18 @@ static const char *getSystemZTargetCPU(const ArgList &Args) {
|
|||
return "z10";
|
||||
}
|
||||
|
||||
static void getSystemZTargetFeatures(const ArgList &Args,
|
||||
std::vector<const char *> &Features) {
|
||||
// -m(no-)htm overrides use of the transactional-execution facility.
|
||||
if (Arg *A = Args.getLastArg(options::OPT_mhtm,
|
||||
options::OPT_mno_htm)) {
|
||||
if (A->getOption().matches(options::OPT_mhtm))
|
||||
Features.push_back("+transactional-execution");
|
||||
else
|
||||
Features.push_back("-transactional-execution");
|
||||
}
|
||||
}
|
||||
|
||||
static const char *getX86TargetCPU(const ArgList &Args,
|
||||
const llvm::Triple &Triple) {
|
||||
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
|
||||
|
@ -1896,6 +1908,9 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
|||
case llvm::Triple::sparcv9:
|
||||
getSparcTargetFeatures(Args, Features);
|
||||
break;
|
||||
case llvm::Triple::systemz:
|
||||
getSystemZTargetFeatures(Args, Features);
|
||||
break;
|
||||
case llvm::Triple::aarch64:
|
||||
case llvm::Triple::aarch64_be:
|
||||
getAArch64TargetFeatures(D, Args, Features);
|
||||
|
|
|
@ -128,4 +128,99 @@ typedef uintptr_t tfhar_t;
|
|||
|
||||
#endif /* __powerpc */
|
||||
|
||||
#ifdef __s390__
|
||||
|
||||
/* Condition codes generated by tbegin */
|
||||
#define _HTM_TBEGIN_STARTED 0
|
||||
#define _HTM_TBEGIN_INDETERMINATE 1
|
||||
#define _HTM_TBEGIN_TRANSIENT 2
|
||||
#define _HTM_TBEGIN_PERSISTENT 3
|
||||
|
||||
/* The abort codes below this threshold are reserved for machine use. */
|
||||
#define _HTM_FIRST_USER_ABORT_CODE 256
|
||||
|
||||
/* The transaction diagnostic block is it is defined in the Principles
|
||||
of Operation chapter 5-91. */
|
||||
|
||||
struct __htm_tdb {
|
||||
unsigned char format; /* 0 */
|
||||
unsigned char flags;
|
||||
unsigned char reserved1[4];
|
||||
unsigned short nesting_depth;
|
||||
unsigned long long abort_code; /* 8 */
|
||||
unsigned long long conflict_token; /* 16 */
|
||||
unsigned long long atia; /* 24 */
|
||||
unsigned char eaid; /* 32 */
|
||||
unsigned char dxc;
|
||||
unsigned char reserved2[2];
|
||||
unsigned int program_int_id;
|
||||
unsigned long long exception_id; /* 40 */
|
||||
unsigned long long bea; /* 48 */
|
||||
unsigned char reserved3[72]; /* 56 */
|
||||
unsigned long long gprs[16]; /* 128 */
|
||||
} __attribute__((__packed__, __aligned__ (8)));
|
||||
|
||||
|
||||
/* Helper intrinsics to retry tbegin in case of transient failure. */
|
||||
|
||||
static __inline int __attribute__((__always_inline__, __nodebug__))
|
||||
__builtin_tbegin_retry_null (int retry)
|
||||
{
|
||||
int cc, i = 0;
|
||||
|
||||
while ((cc = __builtin_tbegin(0)) == _HTM_TBEGIN_TRANSIENT
|
||||
&& i++ < retry)
|
||||
__builtin_tx_assist(i);
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
static __inline int __attribute__((__always_inline__, __nodebug__))
|
||||
__builtin_tbegin_retry_tdb (void *tdb, int retry)
|
||||
{
|
||||
int cc, i = 0;
|
||||
|
||||
while ((cc = __builtin_tbegin(tdb)) == _HTM_TBEGIN_TRANSIENT
|
||||
&& i++ < retry)
|
||||
__builtin_tx_assist(i);
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
#define __builtin_tbegin_retry(tdb, retry) \
|
||||
(__builtin_constant_p(tdb == 0) && tdb == 0 ? \
|
||||
__builtin_tbegin_retry_null(retry) : \
|
||||
__builtin_tbegin_retry_tdb(tdb, retry))
|
||||
|
||||
static __inline int __attribute__((__always_inline__, __nodebug__))
|
||||
__builtin_tbegin_retry_nofloat_null (int retry)
|
||||
{
|
||||
int cc, i = 0;
|
||||
|
||||
while ((cc = __builtin_tbegin_nofloat(0)) == _HTM_TBEGIN_TRANSIENT
|
||||
&& i++ < retry)
|
||||
__builtin_tx_assist(i);
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
static __inline int __attribute__((__always_inline__, __nodebug__))
|
||||
__builtin_tbegin_retry_nofloat_tdb (void *tdb, int retry)
|
||||
{
|
||||
int cc, i = 0;
|
||||
|
||||
while ((cc = __builtin_tbegin_nofloat(tdb)) == _HTM_TBEGIN_TRANSIENT
|
||||
&& i++ < retry)
|
||||
__builtin_tx_assist(i);
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
#define __builtin_tbegin_retry_nofloat(tdb, retry) \
|
||||
(__builtin_constant_p(tdb == 0) && tdb == 0 ? \
|
||||
__builtin_tbegin_retry_nofloat_null(retry) : \
|
||||
__builtin_tbegin_retry_nofloat_tdb(tdb, retry))
|
||||
|
||||
#endif /* __s390__ */
|
||||
|
||||
#endif /* __HTMINTRIN_H */
|
||||
|
|
|
@ -212,4 +212,152 @@ __TM_failure_code(void* const TM_buff)
|
|||
|
||||
#endif /* __powerpc__ */
|
||||
|
||||
#ifdef __s390__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* These intrinsics are being made available for compatibility with
|
||||
the IBM XL compiler. For documentation please see the "z/OS XL
|
||||
C/C++ Programming Guide" publically available on the web. */
|
||||
|
||||
static __inline long __attribute__((__always_inline__, __nodebug__))
|
||||
__TM_simple_begin ()
|
||||
{
|
||||
return __builtin_tbegin_nofloat (0);
|
||||
}
|
||||
|
||||
static __inline long __attribute__((__always_inline__, __nodebug__))
|
||||
__TM_begin (void* const tdb)
|
||||
{
|
||||
return __builtin_tbegin_nofloat (tdb);
|
||||
}
|
||||
|
||||
static __inline long __attribute__((__always_inline__, __nodebug__))
|
||||
__TM_end ()
|
||||
{
|
||||
return __builtin_tend ();
|
||||
}
|
||||
|
||||
static __inline void __attribute__((__always_inline__))
|
||||
__TM_abort ()
|
||||
{
|
||||
return __builtin_tabort (_HTM_FIRST_USER_ABORT_CODE);
|
||||
}
|
||||
|
||||
static __inline void __attribute__((__always_inline__, __nodebug__))
|
||||
__TM_named_abort (unsigned char const code)
|
||||
{
|
||||
return __builtin_tabort ((int)_HTM_FIRST_USER_ABORT_CODE + code);
|
||||
}
|
||||
|
||||
static __inline void __attribute__((__always_inline__, __nodebug__))
|
||||
__TM_non_transactional_store (void* const addr, long long const value)
|
||||
{
|
||||
__builtin_non_tx_store ((uint64_t*)addr, (uint64_t)value);
|
||||
}
|
||||
|
||||
static __inline long __attribute__((__always_inline__, __nodebug__))
|
||||
__TM_nesting_depth (void* const tdb_ptr)
|
||||
{
|
||||
int depth = __builtin_tx_nesting_depth ();
|
||||
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
|
||||
|
||||
if (depth != 0)
|
||||
return depth;
|
||||
|
||||
if (tdb->format != 1)
|
||||
return 0;
|
||||
return tdb->nesting_depth;
|
||||
}
|
||||
|
||||
/* Transaction failure diagnostics */
|
||||
|
||||
static __inline long __attribute__((__always_inline__, __nodebug__))
|
||||
__TM_is_user_abort (void* const tdb_ptr)
|
||||
{
|
||||
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
|
||||
|
||||
if (tdb->format != 1)
|
||||
return 0;
|
||||
|
||||
return !!(tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE);
|
||||
}
|
||||
|
||||
static __inline long __attribute__((__always_inline__, __nodebug__))
|
||||
__TM_is_named_user_abort (void* const tdb_ptr, unsigned char* code)
|
||||
{
|
||||
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
|
||||
|
||||
if (tdb->format != 1)
|
||||
return 0;
|
||||
|
||||
if (tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE)
|
||||
{
|
||||
*code = tdb->abort_code - _HTM_FIRST_USER_ABORT_CODE;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline long __attribute__((__always_inline__, __nodebug__))
|
||||
__TM_is_illegal (void* const tdb_ptr)
|
||||
{
|
||||
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
|
||||
|
||||
return (tdb->format == 1
|
||||
&& (tdb->abort_code == 4 /* unfiltered program interruption */
|
||||
|| tdb->abort_code == 11 /* restricted instruction */));
|
||||
}
|
||||
|
||||
static __inline long __attribute__((__always_inline__, __nodebug__))
|
||||
__TM_is_footprint_exceeded (void* const tdb_ptr)
|
||||
{
|
||||
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
|
||||
|
||||
return (tdb->format == 1
|
||||
&& (tdb->abort_code == 7 /* fetch overflow */
|
||||
|| tdb->abort_code == 8 /* store overflow */));
|
||||
}
|
||||
|
||||
static __inline long __attribute__((__always_inline__, __nodebug__))
|
||||
__TM_is_nested_too_deep (void* const tdb_ptr)
|
||||
{
|
||||
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
|
||||
|
||||
return tdb->format == 1 && tdb->abort_code == 13; /* depth exceeded */
|
||||
}
|
||||
|
||||
static __inline long __attribute__((__always_inline__, __nodebug__))
|
||||
__TM_is_conflict (void* const tdb_ptr)
|
||||
{
|
||||
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
|
||||
|
||||
return (tdb->format == 1
|
||||
&& (tdb->abort_code == 9 /* fetch conflict */
|
||||
|| tdb->abort_code == 10 /* store conflict */));
|
||||
}
|
||||
|
||||
static __inline long __attribute__((__always_inline__, __nodebug__))
|
||||
__TM_is_failure_persistent (long const result)
|
||||
{
|
||||
return result == _HTM_TBEGIN_PERSISTENT;
|
||||
}
|
||||
|
||||
static __inline long __attribute__((__always_inline__, __nodebug__))
|
||||
__TM_failure_address (void* const tdb_ptr)
|
||||
{
|
||||
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
|
||||
return tdb->atia;
|
||||
}
|
||||
|
||||
static __inline long __attribute__((__always_inline__, __nodebug__))
|
||||
__TM_failure_code (void* const tdb_ptr)
|
||||
{
|
||||
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
|
||||
|
||||
return tdb->abort_code;
|
||||
}
|
||||
|
||||
#endif /* __s390__ */
|
||||
|
||||
#endif /* __HTMXLINTRIN_H */
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*===---- s390intrin.h - SystemZ intrinsics --------------------------------===
|
||||
*
|
||||
* 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 __S390INTRIN_H
|
||||
#define __S390INTRIN_H
|
||||
|
||||
#ifndef __s390__
|
||||
#error "<s390intrin.h> is for s390 only"
|
||||
#endif
|
||||
|
||||
#ifdef __HTM__
|
||||
#include <htmintrin.h>
|
||||
#endif
|
||||
|
||||
#endif /* __S390INTRIN_H*/
|
|
@ -546,6 +546,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
|
|||
if (CheckMipsBuiltinFunctionCall(BuiltinID, TheCall))
|
||||
return ExprError();
|
||||
break;
|
||||
case llvm::Triple::systemz:
|
||||
if (CheckSystemZBuiltinFunctionCall(BuiltinID, TheCall))
|
||||
return ExprError();
|
||||
break;
|
||||
case llvm::Triple::x86:
|
||||
case llvm::Triple::x86_64:
|
||||
if (CheckX86BuiltinFunctionCall(BuiltinID, TheCall))
|
||||
|
@ -922,6 +926,20 @@ bool Sema::CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
|
|||
return SemaBuiltinConstantArgRange(TheCall, i, l, u);
|
||||
}
|
||||
|
||||
bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID,
|
||||
CallExpr *TheCall) {
|
||||
if (BuiltinID == SystemZ::BI__builtin_tabort) {
|
||||
Expr *Arg = TheCall->getArg(0);
|
||||
llvm::APSInt AbortCode(32);
|
||||
if (Arg->isIntegerConstantExpr(AbortCode, Context) &&
|
||||
AbortCode.getSExtValue() >= 0 && AbortCode.getSExtValue() < 256)
|
||||
return Diag(Arg->getLocStart(), diag::err_systemz_invalid_tabort_code)
|
||||
<< Arg->getSourceRange();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
|
||||
unsigned i = 0, l = 0, u = 0;
|
||||
switch (BuiltinID) {
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
// REQUIRES: systemz-registered-target
|
||||
// RUN: %clang_cc1 -target-cpu zEC12 -triple s390x-unknown-unknown \
|
||||
// RUN: -Wall -Wno-unused -Werror -fsyntax-only -verify %s
|
||||
|
||||
void test1(void) {
|
||||
__builtin_tabort (0); // expected-error {{invalid transaction abort code}}
|
||||
__builtin_tabort (255); // expected-error {{invalid transaction abort code}}
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
// REQUIRES: systemz-registered-target
|
||||
// RUN: %clang_cc1 -target-cpu zEC12 -triple s390x-ibm-linux -Wall -Wno-unused -Werror -emit-llvm %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -target-cpu zEC12 -triple s390x-ibm-linux -Wall -Wno-unused -Werror -emit-llvm -x c++ %s -o - | FileCheck %s
|
||||
|
||||
#include <stdint.h>
|
||||
#include <htmintrin.h>
|
||||
|
||||
int global = 0;
|
||||
uint64_t g;
|
||||
struct __htm_tdb global_tdb;
|
||||
|
||||
void test_htm1(struct __htm_tdb *tdb, int reg, int *mem, uint64_t *mem64) {
|
||||
// CHECK-LABEL: test_htm1
|
||||
|
||||
__builtin_tbegin ((void *)0);
|
||||
// CHECK: call i32 @llvm.s390.tbegin(i8* null, i32 65292)
|
||||
__builtin_tbegin ((void *)0x12345678);
|
||||
// CHECK: call i32 @llvm.s390.tbegin(i8* inttoptr (i64 305419896 to i8*), i32 65292)
|
||||
__builtin_tbegin (tdb);
|
||||
// CHECK: call i32 @llvm.s390.tbegin(i8* %{{.*}}, i32 65292)
|
||||
__builtin_tbegin (&global_tdb);
|
||||
// CHECK: call i32 @llvm.s390.tbegin(i8* getelementptr inbounds (%struct.__htm_tdb, %struct.__htm_tdb* @global_tdb, i32 0, i32 0), i32 65292)
|
||||
|
||||
__builtin_tbegin_nofloat ((void *)0);
|
||||
// CHECK: call i32 @llvm.s390.tbegin.nofloat(i8* null, i32 65292)
|
||||
__builtin_tbegin_nofloat ((void *)0x12345678);
|
||||
// CHECK: call i32 @llvm.s390.tbegin.nofloat(i8* inttoptr (i64 305419896 to i8*), i32 65292)
|
||||
__builtin_tbegin_nofloat (tdb);
|
||||
// CHECK: call i32 @llvm.s390.tbegin.nofloat(i8* %{{.*}}, i32 65292)
|
||||
__builtin_tbegin_nofloat (&global_tdb);
|
||||
// CHECK: call i32 @llvm.s390.tbegin.nofloat(i8* getelementptr inbounds (%struct.__htm_tdb, %struct.__htm_tdb* @global_tdb, i32 0, i32 0), i32 65292)
|
||||
|
||||
__builtin_tbegin_retry ((void *)0, 6);
|
||||
// CHECK: call i32 @llvm.s390.tbegin(i8* null, i32 65292)
|
||||
// CHECK: call void @llvm.s390.ppa.txassist(i32 %{{.*}})
|
||||
__builtin_tbegin_retry ((void *)0x12345678, 6);
|
||||
// CHECK: call i32 @llvm.s390.tbegin(i8* %{{.*}}, i32 65292)
|
||||
// CHECK: call void @llvm.s390.ppa.txassist(i32 %{{.*}})
|
||||
__builtin_tbegin_retry (tdb, 6);
|
||||
// CHECK: call i32 @llvm.s390.tbegin(i8* %{{.*}}, i32 65292)
|
||||
// CHECK: call void @llvm.s390.ppa.txassist(i32 %{{.*}})
|
||||
__builtin_tbegin_retry (&global_tdb, 6);
|
||||
// CHECK: call i32 @llvm.s390.tbegin(i8* %{{.*}}, i32 65292)
|
||||
// CHECK: call void @llvm.s390.ppa.txassist(i32 %{{.*}})
|
||||
|
||||
__builtin_tbegin_retry_nofloat ((void *)0, 6);
|
||||
// CHECK: call i32 @llvm.s390.tbegin.nofloat(i8* null, i32 65292)
|
||||
// CHECK: call void @llvm.s390.ppa.txassist(i32 %{{.*}})
|
||||
__builtin_tbegin_retry_nofloat ((void *)0x12345678, 6);
|
||||
// CHECK: call i32 @llvm.s390.tbegin.nofloat(i8* %{{.*}}, i32 65292)
|
||||
// CHECK: call void @llvm.s390.ppa.txassist(i32 %{{.*}})
|
||||
__builtin_tbegin_retry_nofloat (tdb, 6);
|
||||
// CHECK: call i32 @llvm.s390.tbegin.nofloat(i8* %{{.*}}, i32 65292)
|
||||
// CHECK: call void @llvm.s390.ppa.txassist(i32 %{{.*}})
|
||||
__builtin_tbegin_retry_nofloat (&global_tdb, 6);
|
||||
// CHECK: call i32 @llvm.s390.tbegin.nofloat(i8* %{{.*}}, i32 65292)
|
||||
// CHECK: call void @llvm.s390.ppa.txassist(i32 %{{.*}})
|
||||
|
||||
__builtin_tbeginc ();
|
||||
// CHECK: call void @llvm.s390.tbeginc(i8* null, i32 65288)
|
||||
|
||||
__builtin_tabort (256);
|
||||
// CHECK: call void @llvm.s390.tabort(i64 256)
|
||||
__builtin_tabort (-1);
|
||||
// CHECK: call void @llvm.s390.tabort(i64 -1)
|
||||
__builtin_tabort (reg);
|
||||
// CHECK: call void @llvm.s390.tabort(i64 %{{.*}})
|
||||
|
||||
__builtin_tend();
|
||||
// CHECK: call i32 @llvm.s390.tend()
|
||||
|
||||
int n = __builtin_tx_nesting_depth();
|
||||
// CHECK: call i32 @llvm.s390.etnd()
|
||||
|
||||
__builtin_non_tx_store (mem64, 0);
|
||||
// CHECK: call void @llvm.s390.ntstg(i64 0, i64* %{{.*}})
|
||||
const uint64_t val_var = 0x1122334455667788;
|
||||
__builtin_non_tx_store (mem64, val_var);
|
||||
// CHECK: call void @llvm.s390.ntstg(i64 1234605616436508552, i64* %{{.*}})
|
||||
__builtin_non_tx_store (mem64, (uint64_t)reg);
|
||||
// CHECK: call void @llvm.s390.ntstg(i64 %{{.*}}, i64* %{{.*}})
|
||||
__builtin_non_tx_store (mem64, g);
|
||||
// CHECK: call void @llvm.s390.ntstg(i64 %{{.*}}, i64* %{{.*}})
|
||||
__builtin_non_tx_store ((uint64_t *)0, 0);
|
||||
// CHECK: call void @llvm.s390.ntstg(i64 0, i64* null)
|
||||
__builtin_non_tx_store ((uint64_t *)0x12345678, 0);
|
||||
// CHECK: call void @llvm.s390.ntstg(i64 0, i64* inttoptr (i64 305419896 to i64*))
|
||||
__builtin_non_tx_store (&g, 23);
|
||||
// CHECK: call void @llvm.s390.ntstg(i64 23, i64* @g)
|
||||
__builtin_non_tx_store (&g, reg);
|
||||
// CHECK: call void @llvm.s390.ntstg(i64 %{{.*}}, i64* @g)
|
||||
__builtin_non_tx_store (&g, *mem);
|
||||
// CHECK: call void @llvm.s390.ntstg(i64 %{{.*}}, i64* @g)
|
||||
__builtin_non_tx_store (&g, global);
|
||||
// CHECK: call void @llvm.s390.ntstg(i64 %{{.*}}, i64* @g)
|
||||
|
||||
__builtin_tx_assist (0);
|
||||
// CHECK: call void @llvm.s390.ppa.txassist(i32 0)
|
||||
__builtin_tx_assist (1);
|
||||
// CHECK: call void @llvm.s390.ppa.txassist(i32 1)
|
||||
__builtin_tx_assist (reg);
|
||||
// CHECK: call void @llvm.s390.ppa.txassist(i32 %{{.*}})
|
||||
__builtin_tx_assist (*mem);
|
||||
// CHECK: call void @llvm.s390.ppa.txassist(i32 %{{.*}})
|
||||
__builtin_tx_assist (global);
|
||||
// CHECK: call void @llvm.s390.ppa.txassist(i32 %{{.*}})
|
||||
}
|
||||
|
||||
#include <htmxlintrin.h>
|
||||
|
||||
void test_htmxl1(void) {
|
||||
// CHECK-LABEL: test_htmxl1
|
||||
|
||||
struct __htm_tdb tdb_struct;
|
||||
void * const tdb = &tdb_struct;
|
||||
long result;
|
||||
unsigned char code;
|
||||
|
||||
result = __TM_simple_begin ();
|
||||
// CHECK: call i32 @llvm.s390.tbegin.nofloat(i8* null, i32 65292)
|
||||
result = __TM_begin (tdb);
|
||||
// CHECK: call i32 @llvm.s390.tbegin.nofloat(i8* %{{.*}}, i32 65292)
|
||||
result = __TM_end ();
|
||||
// CHECK: call i32 @llvm.s390.tend()
|
||||
__TM_abort ();
|
||||
// CHECK: call void @llvm.s390.tabort(i64 256)
|
||||
__TM_named_abort (42);
|
||||
// CHECK: call void @llvm.s390.tabort(i64 %{{.*}})
|
||||
__TM_non_transactional_store (&g, 42);
|
||||
// CHECK: call void @llvm.s390.ntstg(i64 %{{.*}}, i64* %{{.*}})
|
||||
result = __TM_nesting_depth (tdb);
|
||||
// CHECK: call i32 @llvm.s390.etnd()
|
||||
|
||||
result = __TM_is_user_abort (tdb);
|
||||
result = __TM_is_named_user_abort (tdb, &code);
|
||||
result = __TM_is_illegal (tdb);
|
||||
result = __TM_is_footprint_exceeded (tdb);
|
||||
result = __TM_is_nested_too_deep (tdb);
|
||||
result = __TM_is_conflict (tdb);
|
||||
result = __TM_is_failure_persistent (result);
|
||||
result = __TM_failure_address (tdb);
|
||||
result = __TM_failure_code (tdb);
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
// RUN: %clang -target s390x-unknown-linux-gnu %s -### -o %t.o 2>&1 | FileCheck -check-prefix=CHECK-DEFAULT %s
|
||||
// CHECK-DEFAULT-NOT: "-target-feature" "+transactional-execution"
|
||||
// CHECK-DEFAULT-NOT: "-target-feature" "-transactional-execution"
|
||||
|
||||
// RUN: %clang -target s390x-unknown-linux-gnu %s -mhtm -### -o %t.o 2>&1 | FileCheck -check-prefix=CHECK-HTM %s
|
||||
// RUN: %clang -target s390x-unknown-linux-gnu %s -mno-htm -mhtm -### -o %t.o 2>&1 | FileCheck -check-prefix=CHECK-HTM %s
|
||||
// CHECK-HTM: "-target-feature" "+transactional-execution"
|
||||
// CHECK-HTM-NOT: "-target-feature" "-transactional-execution"
|
||||
|
||||
// RUN: %clang -target s390x-unknown-linux-gnu %s -mno-htm -### -o %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOHTM %s
|
||||
// RUN: %clang -target s390x-unknown-linux-gnu %s -mhtm -mno-htm -### -o %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOHTM %s
|
||||
// CHECK-NOHTM: "-target-feature" "-transactional-execution"
|
||||
// CHECK-NOHTM-NOT: "-target-feature" "+transactional-execution"
|
||||
|
|
@ -1675,3 +1675,30 @@
|
|||
//
|
||||
// CHECK_PPC_CRYPTO_M64: #define __CRYPTO__
|
||||
//
|
||||
|
||||
// Begin SystemZ/GCC/Linux tests ----------------
|
||||
//
|
||||
// RUN: %clang -march=z10 -E -dM %s -o - 2>&1 \
|
||||
// RUN: -target s390x-unknown-linux \
|
||||
// RUN: | FileCheck %s -check-prefix=CHECK_SYSTEMZ_Z10
|
||||
//
|
||||
// CHECK_SYSTEMZ_Z10: #define __LONG_DOUBLE_128__ 1
|
||||
// CHECK_SYSTEMZ_Z10: #define __s390__ 1
|
||||
// CHECK_SYSTEMZ_Z10: #define __s390x__ 1
|
||||
// CHECK_SYSTEMZ_Z10: #define __zarch__ 1
|
||||
//
|
||||
// RUN: %clang -march=zEC12 -E -dM %s -o - 2>&1 \
|
||||
// RUN: -target s390x-unknown-linux \
|
||||
// RUN: | FileCheck %s -check-prefix=CHECK_SYSTEMZ_ZEC12
|
||||
//
|
||||
// CHECK_SYSTEMZ_ZEC12: #define __HTM__ 1
|
||||
// CHECK_SYSTEMZ_ZEC12: #define __LONG_DOUBLE_128__ 1
|
||||
// CHECK_SYSTEMZ_ZEC12: #define __s390__ 1
|
||||
// CHECK_SYSTEMZ_ZEC12: #define __s390x__ 1
|
||||
// CHECK_SYSTEMZ_ZEC12: #define __zarch__ 1
|
||||
//
|
||||
// RUN: %clang -mhtm -E -dM %s -o - 2>&1 \
|
||||
// RUN: -target s390x-unknown-linux \
|
||||
// RUN: | FileCheck %s -check-prefix=CHECK_SYSTEMZ_HTM
|
||||
//
|
||||
// CHECK_SYSTEMZ_HTM: #define __HTM__ 1
|
||||
|
|
Loading…
Reference in New Issue