diff --git a/clang/include/clang/Basic/BuiltinsSystemZ.def b/clang/include/clang/Basic/BuiltinsSystemZ.def new file mode 100644 index 000000000000..613e9de9d75a --- /dev/null +++ b/clang/include/clang/Basic/BuiltinsSystemZ.def @@ -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 diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 7866e5471e2f..fdac850d71af 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -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">; diff --git a/clang/include/clang/Basic/TargetBuiltins.h b/clang/include/clang/Basic/TargetBuiltins.h index e112c654b5d0..5c5d940d668c 100644 --- a/clang/include/clang/Basic/TargetBuiltins.h +++ b/clang/include/clang/Basic/TargetBuiltins.h @@ -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 diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index ddd693a1c963..1d32574cc607 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -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); diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 2964cbaeac88..48a3a7c1cbf3 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -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(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 &Features) const override { + if (CPU == "zEC12") + Features["transactional-execution"] = true; + } + + bool handleTargetFeatures(std::vector &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(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[] = { diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 90ca218a8375..44e791008289 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -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; + } +} diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 2473ab6898ef..701008d523eb 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -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); diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index daaea63c7162..3a57129d63ee 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -1418,6 +1418,18 @@ static const char *getSystemZTargetCPU(const ArgList &Args) { return "z10"; } +static void getSystemZTargetFeatures(const ArgList &Args, + std::vector &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); diff --git a/clang/lib/Headers/htmintrin.h b/clang/lib/Headers/htmintrin.h index 4598ee06b50c..0088c7ccab93 100644 --- a/clang/lib/Headers/htmintrin.h +++ b/clang/lib/Headers/htmintrin.h @@ -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 */ diff --git a/clang/lib/Headers/htmxlintrin.h b/clang/lib/Headers/htmxlintrin.h index 8791afef9480..30f524d5df49 100644 --- a/clang/lib/Headers/htmxlintrin.h +++ b/clang/lib/Headers/htmxlintrin.h @@ -212,4 +212,152 @@ __TM_failure_code(void* const TM_buff) #endif /* __powerpc__ */ +#ifdef __s390__ + +#include + +/* 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 */ diff --git a/clang/lib/Headers/s390intrin.h b/clang/lib/Headers/s390intrin.h new file mode 100644 index 000000000000..b20989552d4d --- /dev/null +++ b/clang/lib/Headers/s390intrin.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 " is for s390 only" +#endif + +#ifdef __HTM__ +#include +#endif + +#endif /* __S390INTRIN_H*/ diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 3e3d60e05311..0501f63e90b2 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -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) { diff --git a/clang/test/CodeGen/builtins-systemz-error.c b/clang/test/CodeGen/builtins-systemz-error.c new file mode 100644 index 000000000000..73431b0a320e --- /dev/null +++ b/clang/test/CodeGen/builtins-systemz-error.c @@ -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}} +} + diff --git a/clang/test/CodeGen/builtins-systemz.c b/clang/test/CodeGen/builtins-systemz.c new file mode 100644 index 000000000000..f5de7009acba --- /dev/null +++ b/clang/test/CodeGen/builtins-systemz.c @@ -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 +#include + +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 + +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); +} + diff --git a/clang/test/Driver/systemz-features.cpp b/clang/test/Driver/systemz-features.cpp new file mode 100644 index 000000000000..25937d1cdce8 --- /dev/null +++ b/clang/test/Driver/systemz-features.cpp @@ -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" + diff --git a/clang/test/Preprocessor/predefined-arch-macros.c b/clang/test/Preprocessor/predefined-arch-macros.c index 6e3743da951e..9fee3b62940c 100644 --- a/clang/test/Preprocessor/predefined-arch-macros.c +++ b/clang/test/Preprocessor/predefined-arch-macros.c @@ -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