File backport-clang-r233804 of Package llvm

------------------------------------------------------------------------
r233804 | uweigand | 2015-04-01 14:54:25 +0200 (Wed, 01 Apr 2015) | 29 lines

[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".


------------------------------------------------------------------------
Index: tools/clang/test/Driver/systemz-features.cpp
===================================================================
--- /dev/null
+++ tools/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"
+
Index: tools/clang/test/Preprocessor/predefined-arch-macros.c
===================================================================
--- tools/clang/test/Preprocessor/predefined-arch-macros.c.orig
+++ tools/clang/test/Preprocessor/predefined-arch-macros.c
@@ -1446,3 +1446,30 @@
 // RUN:   | FileCheck %s -check-prefix=CHECK_PPC_VSX_M64
 //
 // CHECK_PPC_VSX_M64: #define __VSX__
+
+// 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
Index: tools/clang/test/CodeGen/builtins-systemz.c
===================================================================
--- /dev/null
+++ tools/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 <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* @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* @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);
+}
+
Index: tools/clang/test/CodeGen/builtins-systemz-error.c
===================================================================
--- /dev/null
+++ tools/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}}
+}
+
Index: tools/clang/include/clang/Sema/Sema.h
===================================================================
--- tools/clang/include/clang/Sema/Sema.h.orig
+++ tools/clang/include/clang/Sema/Sema.h
@@ -7846,6 +7846,7 @@ private:
   bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
   bool CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
   bool CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+  bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
 
   bool SemaBuiltinVAStart(CallExpr *TheCall);
   bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
Index: tools/clang/include/clang/Basic/BuiltinsSystemZ.def
===================================================================
--- /dev/null
+++ tools/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
Index: tools/clang/include/clang/Basic/TargetBuiltins.h
===================================================================
--- tools/clang/include/clang/Basic/TargetBuiltins.h.orig
+++ tools/clang/include/clang/Basic/TargetBuiltins.h
@@ -142,6 +142,16 @@ namespace clang {
         LastTSBuiltin
     };
   }
+
+  /// \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
Index: tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- tools/clang/include/clang/Basic/DiagnosticSemaKinds.td.orig
+++ tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6485,6 +6485,9 @@ def err_invalid_neon_type_code : Error<
 def err_argument_invalid_range : Error<
   "argument should be a value from %0 to %1">;
 
+def err_systemz_invalid_tabort_code : Error<
+  "invalid transaction abort code">;
+
 def err_builtin_longjmp_invalid_val : Error<
   "argument to __builtin_longjmp must be a constant 1">;
 
Index: tools/clang/lib/Headers/s390intrin.h
===================================================================
--- /dev/null
+++ tools/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 "<s390intrin.h> is for s390 only"
+#endif
+
+#ifdef __HTM__
+#include <htmintrin.h>
+#endif
+
+#endif /* __S390INTRIN_H*/
Index: tools/clang/lib/Headers/htmxlintrin.h
===================================================================
--- /dev/null
+++ tools/clang/lib/Headers/htmxlintrin.h
@@ -0,0 +1,180 @@
+/*===---- htmxlintrin.h - XL compiler HTM execution 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 __HTMXLINTRIN_H
+#define __HTMXLINTRIN_H
+
+#ifndef __HTM__
+#error "HTM instruction set not enabled"
+#endif
+
+#include <htmintrin.h>
+
+#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  */
Index: tools/clang/lib/Basic/Targets.cpp
===================================================================
--- tools/clang/lib/Basic/Targets.cpp.orig
+++ tools/clang/lib/Basic/Targets.cpp
@@ -4590,10 +4590,14 @@ public:
 
 namespace {
   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;
       UIntMaxType = UnsignedLong;
       Int64Type = SignedLong;
@@ -4615,12 +4619,13 @@ namespace {
       Builder.defineMacro("__s390x__");
       Builder.defineMacro("__zarch__");
       Builder.defineMacro("__LONG_DOUBLE_128__");
+      if (HasTransactionalExecution)
+        Builder.defineMacro("__HTM__");
     }
     virtual void getTargetBuiltins(const Builtin::Info *&Records,
                                    unsigned &NumRecords) const {
-      // FIXME: Implement.
-      Records = 0;
-      NumRecords = 0;
+      Records = BuiltinInfo;
+      NumRecords = clang::SystemZ::LastTSBuiltin-Builtin::FirstTSBuiltin;
     }
 
     virtual void getGCCRegNames(const char *const *&Names,
@@ -4641,16 +4646,41 @@ namespace {
       return TargetInfo::SystemZBuiltinVaList;
     }
     virtual bool setCPU(const std::string &Name) {
+      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;
     }
+    virtual void getDefaultFeatures(llvm::StringMap<bool> &Features) const {
+      if (CPU == "zEC12")
+        Features["transactional-execution"] = true;
+    }
+
+    virtual bool handleTargetFeatures(std::vector<std::string> &Features,
+                                      DiagnosticsEngine &Diags) {
+      HasTransactionalExecution = false;
+      for (unsigned i = 0, e = Features.size(); i != e; ++i) {
+        if (Features[i] == "+transactional-execution")
+          HasTransactionalExecution = true;
+      }
+      return true;
+    }
+
+    virtual bool hasFeature(StringRef Feature) const {
+      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[] = {
Index: tools/clang/lib/Sema/SemaChecking.cpp
===================================================================
--- tools/clang/lib/Sema/SemaChecking.cpp.orig
+++ tools/clang/lib/Sema/SemaChecking.cpp
@@ -317,6 +317,10 @@ Sema::CheckBuiltinFunctionCall(unsigned
         if (CheckMipsBuiltinFunctionCall(BuiltinID, TheCall))
           return ExprError();
         break;
+      case llvm::Triple::systemz:
+        if (CheckSystemZBuiltinFunctionCall(BuiltinID, TheCall))
+          return ExprError();
+        break;
       default:
         break;
     }
@@ -639,6 +643,20 @@ bool Sema::CheckMipsBuiltinFunctionCall(
   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;
+}
+
 /// Given a FunctionDecl's FormatAttr, attempts to populate the FomatStringInfo
 /// parameter with the FormatAttr's correct format_idx and firstDataArg.
 /// Returns true when the format fits the function and the FormatStringInfo has
Index: tools/clang/lib/Driver/Tools.cpp
===================================================================
--- tools/clang/lib/Driver/Tools.cpp.orig
+++ tools/clang/lib/Driver/Tools.cpp
@@ -1275,6 +1275,18 @@ static const char *getSystemZTargetCPU(c
   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)) {
@@ -1531,6 +1543,9 @@ static void getTargetFeatures(const Driv
   case llvm::Triple::sparc:
     getSparcTargetFeatures(Args, Features);
     break;
+  case llvm::Triple::systemz:
+    getSystemZTargetFeatures(Args, Features);
+    break;
   case llvm::Triple::aarch64:
     getAArch64TargetFeatures(D, Args, Features);
     break;
Index: tools/clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- tools/clang/lib/CodeGen/CodeGenFunction.h.orig
+++ tools/clang/lib/CodeGen/CodeGenFunction.h
@@ -2172,6 +2172,7 @@ public:
   llvm::Value *BuildVector(ArrayRef<llvm::Value*> Ops);
   llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
   llvm::Value *EmitPPCBuiltinExpr(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);
Index: tools/clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- tools/clang/lib/CodeGen/CGBuiltin.cpp.orig
+++ tools/clang/lib/CodeGen/CGBuiltin.cpp
@@ -1602,6 +1602,8 @@ Value *CodeGenFunction::EmitTargetBuilti
   case llvm::Triple::ppc64:
   case llvm::Triple::ppc64le:
     return EmitPPCBuiltinExpr(BuiltinID, E);
+  case llvm::Triple::systemz:
+    return EmitSystemZBuiltinExpr(BuiltinID, E);
   default:
     return 0;
   }
@@ -5285,3 +5287,41 @@ Value *CodeGenFunction::EmitPPCBuiltinEx
   }
   }
 }
+
+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 0;
+  }
+}
Index: tools/clang/lib/Headers/htmintrin.h
===================================================================
--- /dev/null
+++ tools/clang/lib/Headers/htmintrin.h
@@ -0,0 +1,125 @@
+/*===---- 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
+
+#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 */
Index: tools/clang/include/clang/Driver/Options.td
===================================================================
--- tools/clang/include/clang/Driver/Options.td.orig
+++ tools/clang/include/clang/Driver/Options.td
@@ -1057,6 +1057,9 @@ def mno_popcntd : Flag<["-"], "mno-popcn
 def mqpx : Flag<["-"], "mqpx">, Group<m_ppc_Features_Group>;
 def mno_qpx : Flag<["-"], "mno-qpx">, Group<m_ppc_Features_Group>;
 
+def mhtm : Flag<["-"], "mhtm">, Group<m_Group>;
+def mno_htm : Flag<["-"], "mno-htm">, Group<m_Group>;
+
 def faltivec : Flag<["-"], "faltivec">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Enable AltiVec vector initializer syntax">;
 def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>, Flags<[CC1Option]>;
openSUSE Build Service is sponsored by