re PR target/64579 (__TM_end __builtin_tend failed to return transactional state)
authorPeter Bergner <bergner@vnet.ibm.com>
Mon, 27 Apr 2015 14:52:50 +0000 (09:52 -0500)
committerPeter Bergner <bergner@gcc.gnu.org>
Mon, 27 Apr 2015 14:52:50 +0000 (09:52 -0500)
gcc/
PR target/64579
* config/rs6000/htm.md: Remove all define_expands.
(UNSPECV_HTM_TABORTDC, UNSPECV_HTM_TABORTDCI, UNSPECV_HTM_TABORTWC,
UNSPECV_HTM_TABORTWCI): Remove.
(UNSPECV_HTM_TABORTXC, UNSPECV_HTM_TABORTXCI, UNSPECV_HTM_TTEST): New.
(tabort_internal, tbegin_internal, tcheck_internal, tend_internal,
trechkpt_internal, treclaim_internal, tsr_internal): Rename from this...
(tabort, tbegin, tcheck, tend, trechkpt, treclaim, tsr): ...to this.
(tabortdc_internal, tabortdci_internal, tabortwc_internal,
tabortwci_internal): Remove define_insns.
(tabort<wd>c, tabort<wd>ci): New define_insns.
(tabort): Use gpc_reg_operand.
(tcheck): Remove operand.
(htm_mfspr_<mode>, htm_mtspr_<mode>): Use GPR mode macro.
* config/rs6000/htmxlintrin.h (__TM_end): Use _HTM_TRANSACTIONAL as
expected value.
* config/rs6000/rs6000-builtin.def (BU_HTM_SPR0): Remove.
(BU_HTM_SPR1): Rename to BU_HTM_V1.  Remove use of RS6000_BTC_SPR.
(tabort, tabortdc, tabortdci, tabortwc, tabortwci, tbegin,
tcheck, tend, tendall, trechkpt, treclaim, tresume, tsuspend,
tsr, ttest): Pass in the RS6000_BTC_CR attribute.
(get_tfhar, set_tfhar, get_tfiar, set_tfiar, get_texasr, set_texasr,
get_texasru, set_texasru): Pass in the RS6000_BTC_SPR attribute.
(tcheck): Remove builtin argument.
* config/rs6000/rs6000.c (rs6000_htm_spr_icode): Use TARGET_POWERPC64
not TARGET_64BIT.
(htm_expand_builtin): Fix usage of expandedp.  Disallow usage of the
tabortdc and tabortdci builtins when not in 64-bit mode.
Modify code to handle the loss of the HTM define_expands.
Emit code to copy the CR register to TARGET.
(htm_init_builtins): Modify code to handle the loss of the HTM
define_expands.
* config/rs6000/rs6000.h (RS6000_BTC_32BIT): Delete.
(RS6000_BTC_64BIT): Likewise.
(RS6000_BTC_CR): New macro.
* doc/extend.texi: Update documentation for htm builtins.

gcc/testsuite/

PR target/64579
* gcc.target/powerpc/htm-1.c: New test.
* gcc.target/powerpc/htm-builtin-1.c (__builtin_tabortdc): Only test
on 64-bit compiles.
(__builtin_tabortdci): Likewise.
(__builtin_tcheck): Remove operand.
* lib/target-supports.exp (check_htm_hw_available): New function.

From-SVN: r222467

gcc/ChangeLog
gcc/config/rs6000/htm.md
gcc/config/rs6000/htmxlintrin.h
gcc/config/rs6000/rs6000-builtin.def
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/doc/extend.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/htm-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/htm-builtin-1.c
gcc/testsuite/lib/target-supports.exp

index b211083425e2eb91b6c1b6cf6363c76ba25113c0..e072c940425616b2a3b688f0e31258a7e0dea23c 100644 (file)
@@ -1,3 +1,42 @@
+2015-04-27  Peter Bergner  <bergner@vnet.ibm.com>
+
+       PR target/64579
+       * config/rs6000/htm.md: Remove all define_expands.
+       (UNSPECV_HTM_TABORTDC, UNSPECV_HTM_TABORTDCI, UNSPECV_HTM_TABORTWC,
+       UNSPECV_HTM_TABORTWCI): Remove.
+       (UNSPECV_HTM_TABORTXC, UNSPECV_HTM_TABORTXCI, UNSPECV_HTM_TTEST): New.
+       (tabort_internal, tbegin_internal, tcheck_internal, tend_internal,
+       trechkpt_internal, treclaim_internal, tsr_internal): Rename from this...
+       (tabort, tbegin, tcheck, tend, trechkpt, treclaim, tsr): ...to this.
+       (tabortdc_internal, tabortdci_internal, tabortwc_internal,
+       tabortwci_internal): Remove define_insns.
+       (tabort<wd>c, tabort<wd>ci): New define_insns.
+       (tabort): Use gpc_reg_operand.
+       (tcheck): Remove operand.
+       (htm_mfspr_<mode>, htm_mtspr_<mode>): Use GPR mode macro.
+       * config/rs6000/htmxlintrin.h (__TM_end): Use _HTM_TRANSACTIONAL as
+       expected value.
+       * config/rs6000/rs6000-builtin.def (BU_HTM_SPR0): Remove.
+       (BU_HTM_SPR1): Rename to BU_HTM_V1.  Remove use of RS6000_BTC_SPR.
+       (tabort, tabortdc, tabortdci, tabortwc, tabortwci, tbegin,
+       tcheck, tend, tendall, trechkpt, treclaim, tresume, tsuspend,
+       tsr, ttest): Pass in the RS6000_BTC_CR attribute.
+       (get_tfhar, set_tfhar, get_tfiar, set_tfiar, get_texasr, set_texasr,
+       get_texasru, set_texasru): Pass in the RS6000_BTC_SPR attribute.
+       (tcheck): Remove builtin argument.
+       * config/rs6000/rs6000.c (rs6000_htm_spr_icode): Use TARGET_POWERPC64
+       not TARGET_64BIT.
+       (htm_expand_builtin): Fix usage of expandedp.  Disallow usage of the
+       tabortdc and tabortdci builtins when not in 64-bit mode.
+       Modify code to handle the loss of the HTM define_expands.
+       Emit code to copy the CR register to TARGET.
+       (htm_init_builtins): Modify code to handle the loss of the HTM
+       define_expands.
+       * config/rs6000/rs6000.h (RS6000_BTC_32BIT): Delete.
+       (RS6000_BTC_64BIT): Likewise.
+       (RS6000_BTC_CR): New macro.
+       * doc/extend.texi: Update documentation for htm builtins.
+
 2015-04-27  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * simplify-rtx.c (simplify_gen_binary): Use std::swap instead
index 79fb740521ad9e71b96cb09d9324ffe69c70b0ec..dbfd0db59621210da791d46b9d4677cf6241c31c 100644 (file)
 
 (define_c_enum "unspecv"
   [UNSPECV_HTM_TABORT
-   UNSPECV_HTM_TABORTDC
-   UNSPECV_HTM_TABORTDCI
-   UNSPECV_HTM_TABORTWC
-   UNSPECV_HTM_TABORTWCI
+   UNSPECV_HTM_TABORTXC
+   UNSPECV_HTM_TABORTXCI
    UNSPECV_HTM_TBEGIN
    UNSPECV_HTM_TCHECK
    UNSPECV_HTM_TEND
    UNSPECV_HTM_TRECHKPT
    UNSPECV_HTM_TRECLAIM
    UNSPECV_HTM_TSR
+   UNSPECV_HTM_TTEST
    UNSPECV_HTM_MFSPR
    UNSPECV_HTM_MTSPR
   ])
 
 
-(define_expand "tabort"
-  [(set (match_dup 2)
-       (unspec_volatile:CC [(match_operand:SI 1 "int_reg_operand" "")]
-                           UNSPECV_HTM_TABORT))
-   (set (match_dup 3)
-       (eq:SI (match_dup 2)
-              (const_int 0)))
-   (set (match_operand:SI 0 "int_reg_operand" "")
-       (xor:SI (match_dup 3)
-               (const_int 1)))]
-  "TARGET_HTM"
-{
-  operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
-  operands[3] = gen_reg_rtx (SImode);
-})
-
-(define_insn "*tabort_internal"
+(define_insn "tabort"
   [(set (match_operand:CC 1 "cc_reg_operand" "=x")
-       (unspec_volatile:CC [(match_operand:SI 0 "int_reg_operand" "r")]
+       (unspec_volatile:CC [(match_operand:SI 0 "gpc_reg_operand" "r")]
                            UNSPECV_HTM_TABORT))]
   "TARGET_HTM"
   "tabort. %0"
   [(set_attr "type" "htm")
    (set_attr "length" "4")])
 
-(define_expand "tabortdc"
-  [(set (match_dup 4)
-       (unspec_volatile:CC [(match_operand 1 "u5bit_cint_operand" "n")
-                            (match_operand:SI 2 "gpc_reg_operand" "r")
-                            (match_operand:SI 3 "gpc_reg_operand" "r")]
-                           UNSPECV_HTM_TABORTDC))
-   (set (match_dup 5)
-       (eq:SI (match_dup 4)
-              (const_int 0)))
-   (set (match_operand:SI 0 "int_reg_operand" "")
-       (xor:SI (match_dup 5)
-               (const_int 1)))]
-  "TARGET_HTM"
-{
-  operands[4] = gen_rtx_REG (CCmode, CR0_REGNO);
-  operands[5] = gen_reg_rtx (SImode);
-})
-
-(define_insn "*tabortdc_internal"
+(define_insn "tabort<wd>c"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
-                            (match_operand:SI 1 "gpc_reg_operand" "r")
-                            (match_operand:SI 2 "gpc_reg_operand" "r")]
-                           UNSPECV_HTM_TABORTDC))]
+                            (match_operand:GPR 1 "gpc_reg_operand" "r")
+                            (match_operand:GPR 2 "gpc_reg_operand" "r")]
+                           UNSPECV_HTM_TABORTXC))]
   "TARGET_HTM"
-  "tabortdc. %0,%1,%2"
+  "tabort<wd>c. %0,%1,%2"
   [(set_attr "type" "htm")
    (set_attr "length" "4")])
 
-(define_expand "tabortdci"
-  [(set (match_dup 4)
-       (unspec_volatile:CC [(match_operand 1 "u5bit_cint_operand" "n")
-                            (match_operand:SI 2 "gpc_reg_operand" "r")
-                            (match_operand 3 "s5bit_cint_operand" "n")]
-                           UNSPECV_HTM_TABORTDCI))
-   (set (match_dup 5)
-       (eq:SI (match_dup 4)
-              (const_int 0)))
-   (set (match_operand:SI 0 "int_reg_operand" "")
-       (xor:SI (match_dup 5)
-               (const_int 1)))]
-  "TARGET_HTM"
-{
-  operands[4] = gen_rtx_REG (CCmode, CR0_REGNO);
-  operands[5] = gen_reg_rtx (SImode);
-})
-
-(define_insn "*tabortdci_internal"
+(define_insn "tabort<wd>ci"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
-                            (match_operand:SI 1 "gpc_reg_operand" "r")
+                            (match_operand:GPR 1 "gpc_reg_operand" "r")
                             (match_operand 2 "s5bit_cint_operand" "n")]
-                           UNSPECV_HTM_TABORTDCI))]
-  "TARGET_HTM"
-  "tabortdci. %0,%1,%2"
-  [(set_attr "type" "htm")
-   (set_attr "length" "4")])
-
-(define_expand "tabortwc"
-  [(set (match_dup 4)
-       (unspec_volatile:CC [(match_operand 1 "u5bit_cint_operand" "n")
-                            (match_operand:SI 2 "gpc_reg_operand" "r")
-                            (match_operand:SI 3 "gpc_reg_operand" "r")]
-                           UNSPECV_HTM_TABORTWC))
-   (set (match_dup 5)
-       (eq:SI (match_dup 4)
-              (const_int 0)))
-   (set (match_operand:SI 0 "int_reg_operand" "")
-       (xor:SI (match_dup 5)
-               (const_int 1)))]
-  "TARGET_HTM"
-{
-  operands[4] = gen_rtx_REG (CCmode, CR0_REGNO);
-  operands[5] = gen_reg_rtx (SImode);
-})
-
-(define_insn "*tabortwc_internal"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
-       (unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
-                            (match_operand:SI 1 "gpc_reg_operand" "r")
-                            (match_operand:SI 2 "gpc_reg_operand" "r")]
-                           UNSPECV_HTM_TABORTWC))]
+                           UNSPECV_HTM_TABORTXCI))]
   "TARGET_HTM"
-  "tabortwc. %0,%1,%2"
+  "tabort<wd>ci. %0,%1,%2"
   [(set_attr "type" "htm")
    (set_attr "length" "4")])
 
-(define_expand "tabortwci"
-  [(set (match_dup 4)
-       (unspec_volatile:CC [(match_operand 1 "u5bit_cint_operand" "n")
-                            (match_operand:SI 2 "gpc_reg_operand" "r")
-                            (match_operand 3 "s5bit_cint_operand" "n")]
-                           UNSPECV_HTM_TABORTWCI))
-   (set (match_dup 5)
-       (eq:SI (match_dup 4)
-              (const_int 0)))
-   (set (match_operand:SI 0 "int_reg_operand" "")
-       (xor:SI (match_dup 5)
-               (const_int 1)))]
-  "TARGET_HTM"
-{
-  operands[4] = gen_rtx_REG (CCmode, CR0_REGNO);
-  operands[5] = gen_reg_rtx (SImode);
-})
-
-(define_expand "ttest"
-  [(set (match_dup 1)
-       (unspec_volatile:CC [(const_int 0)
-                            (reg:SI 0)
-                            (const_int 0)]
-                           UNSPECV_HTM_TABORTWCI))
-   (set (subreg:CC (match_dup 2) 0) (match_dup 1))
-   (set (match_dup 3) (lshiftrt:SI (match_dup 2) (const_int 28)))
-   (set (match_operand:SI 0 "int_reg_operand" "")
-       (and:SI (match_dup 3)
-               (const_int 15)))]
-  "TARGET_HTM"
-{
-  operands[1] = gen_rtx_REG (CCmode, CR0_REGNO);
-  operands[2] = gen_reg_rtx (SImode);
-  operands[3] = gen_reg_rtx (SImode);
-})
-
-(define_insn "*tabortwci_internal"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
-       (unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
-                            (match_operand:SI 1 "gpc_reg_operand" "r")
-                            (match_operand 2 "s5bit_cint_operand" "n")]
-                           UNSPECV_HTM_TABORTWCI))]
-  "TARGET_HTM"
-  "tabortwci. %0,%1,%2"
-  [(set_attr "type" "htm")
-   (set_attr "length" "4")])
-
-(define_expand "tbegin"
-  [(set (match_dup 2)
-       (unspec_volatile:CC [(match_operand 1 "const_0_to_1_operand" "n")]
-                           UNSPECV_HTM_TBEGIN))
-   (set (match_dup 3)
-       (eq:SI (match_dup 2)
-              (const_int 0)))
-   (set (match_operand:SI 0 "int_reg_operand" "")
-       (xor:SI (match_dup 3)
-               (const_int 1)))]
-  "TARGET_HTM"
-{
-  operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
-  operands[3] = gen_reg_rtx (SImode);
-})
-
-(define_insn "*tbegin_internal"
+(define_insn "tbegin"
   [(set (match_operand:CC 1 "cc_reg_operand" "=x")
        (unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")]
                            UNSPECV_HTM_TBEGIN))]
   [(set_attr "type" "htm")
    (set_attr "length" "4")])
 
-(define_expand "tcheck"
-  [(set (match_dup 2)
-       (unspec_volatile:CC [(match_operand 1 "u3bit_cint_operand" "n")]
-                           UNSPECV_HTM_TCHECK))
-   (set (match_dup 3)
-       (eq:SI (match_dup 2)
-              (const_int 0)))
-   (set (match_operand:SI 0 "int_reg_operand" "")
-       (xor:SI (match_dup 3)
-               (const_int 1)))]
-  "TARGET_HTM"
-{
-  operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
-  operands[3] = gen_reg_rtx (SImode);
-})
-
-(define_insn "*tcheck_internal"
-  [(set (match_operand:CC 1 "cc_reg_operand" "=x")
-       (unspec_volatile:CC [(match_operand 0 "u3bit_cint_operand" "n")]
+(define_insn "tcheck"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+       (unspec_volatile:CC [(const_int 0)]
                            UNSPECV_HTM_TCHECK))]
   "TARGET_HTM"
   "tcheck %0"
   [(set_attr "type" "htm")
    (set_attr "length" "4")])
 
-(define_expand "tend"
-  [(set (match_dup 2)
-       (unspec_volatile:CC [(match_operand 1 "const_0_to_1_operand" "n")]
-                           UNSPECV_HTM_TEND))
-   (set (match_dup 3)
-       (eq:SI (match_dup 2)
-              (const_int 0)))
-   (set (match_operand:SI 0 "int_reg_operand" "")
-       (xor:SI (match_dup 3)
-               (const_int 1)))]
-  "TARGET_HTM"
-{
-  operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
-  operands[3] = gen_reg_rtx (SImode);
-})
-
-(define_insn "*tend_internal"
+(define_insn "tend"
   [(set (match_operand:CC 1 "cc_reg_operand" "=x")
        (unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")]
                            UNSPECV_HTM_TEND))]
   [(set_attr "type" "htm")
    (set_attr "length" "4")])
 
-(define_expand "trechkpt"
-  [(set (match_dup 1)
-       (unspec_volatile:CC [(const_int 0)]
-                           UNSPECV_HTM_TRECHKPT))
-   (set (match_dup 2)
-       (eq:SI (match_dup 1)
-              (const_int 0)))
-   (set (match_operand:SI 0 "int_reg_operand" "")
-       (xor:SI (match_dup 2)
-               (const_int 1)))]
-  "TARGET_HTM"
-{
-  operands[1] = gen_rtx_REG (CCmode, CR0_REGNO);
-  operands[2] = gen_reg_rtx (SImode);
-})
-
-(define_insn "*trechkpt_internal"
+(define_insn "trechkpt"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (unspec_volatile:CC [(const_int 0)]
                            UNSPECV_HTM_TRECHKPT))]
   [(set_attr "type" "htm")
    (set_attr "length" "4")])
 
-(define_expand "treclaim"
-  [(set (match_dup 2)
-       (unspec_volatile:CC [(match_operand:SI 1 "gpc_reg_operand" "r")]
-                           UNSPECV_HTM_TRECLAIM))
-   (set (match_dup 3)
-       (eq:SI (match_dup 2)
-              (const_int 0)))
-   (set (match_operand:SI 0 "int_reg_operand" "")
-       (xor:SI (match_dup 3)
-               (const_int 1)))]
-  "TARGET_HTM"
-{
-  operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
-  operands[3] = gen_reg_rtx (SImode);
-})
-
-(define_insn "*treclaim_internal"
+(define_insn "treclaim"
   [(set (match_operand:CC 1 "cc_reg_operand" "=x")
        (unspec_volatile:CC [(match_operand:SI 0 "gpc_reg_operand" "r")]
                            UNSPECV_HTM_TRECLAIM))]
   [(set_attr "type" "htm")
    (set_attr "length" "4")])
 
-(define_expand "tsr"
-  [(set (match_dup 2)
-       (unspec_volatile:CC [(match_operand 1 "const_0_to_1_operand" "n")]
-                           UNSPECV_HTM_TSR))
-   (set (match_dup 3)
-       (eq:SI (match_dup 2)
-              (const_int 0)))
-   (set (match_operand:SI 0 "int_reg_operand" "")
-       (xor:SI (match_dup 3)
-               (const_int 1)))]
-  "TARGET_HTM"
-{
-  operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
-  operands[3] = gen_reg_rtx (SImode);
-})
-
-(define_insn "*tsr_internal"
+(define_insn "tsr"
   [(set (match_operand:CC 1 "cc_reg_operand" "=x")
        (unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")]
                            UNSPECV_HTM_TSR))]
   [(set_attr "type" "htm")
    (set_attr "length" "4")])
 
+(define_insn "ttest"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (unspec_volatile:CC [(const_int 0)]
+                           UNSPECV_HTM_TTEST))]
+  "TARGET_HTM"
+  "tabortwci. 0,1,0"
+  [(set_attr "type" "htm")
+   (set_attr "length" "4")])
+
 (define_insn "htm_mfspr_<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
-        (unspec_volatile:P [(match_operand 1 "u10bit_cint_operand" "n")
-                           (match_operand:P 2 "htm_spr_reg_operand" "")]
-                          UNSPECV_HTM_MFSPR))]
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+        (unspec_volatile:GPR [(match_operand 1 "u10bit_cint_operand" "n")
+                             (match_operand:GPR 2 "htm_spr_reg_operand" "")]
+                            UNSPECV_HTM_MFSPR))]
   "TARGET_HTM"
   "mfspr %0,%1";
   [(set_attr "type" "htm")
    (set_attr "length" "4")])
 
 (define_insn "htm_mtspr_<mode>"
-  [(set (match_operand:P 2 "htm_spr_reg_operand" "")
-        (unspec_volatile:P [(match_operand:P 0 "gpc_reg_operand" "r")
-                           (match_operand 1 "u10bit_cint_operand" "n")]
-                           UNSPECV_HTM_MTSPR))]
+  [(set (match_operand:GPR 2 "htm_spr_reg_operand" "")
+        (unspec_volatile:GPR [(match_operand:GPR 0 "gpc_reg_operand" "r")
+                             (match_operand 1 "u10bit_cint_operand" "n")]
+                            UNSPECV_HTM_MTSPR))]
   "TARGET_HTM"
   "mtspr %1,%0";
   [(set_attr "type" "htm")
index bf7c4172b49e4b5fe453f11008671b186c0de9fc..a10771cd4fc5d35b6eff2ec4eb3b7a5c10778ec9 100644 (file)
@@ -81,7 +81,8 @@ extern __inline long
 __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
 __TM_end (void)
 {
-  if (__builtin_expect (__builtin_tend (0), 1))
+  unsigned char status = _HTM_STATE (__builtin_tend (0));
+  if (__builtin_expect (status, _HTM_TRANSACTIONAL))
     return 1;
   return 0;
 }
index 0f384ca2be2f2df6f2a15acf39fe5f839b8acaba..7b79efcedb31000524ac8ac485a054bef70ff9c3 100644 (file)
                     | RS6000_BTC_TERNARY),                             \
                    CODE_FOR_ ## ICODE)                 /* ICODE */
 
-#define BU_HTM_SPR0(ENUM, NAME, ATTR, ICODE)                           \
-  RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM,              /* ENUM */      \
-                   "__builtin_" NAME,                  /* NAME */      \
-                   RS6000_BTM_HTM,                     /* MASK */      \
-                   (RS6000_BTC_ ## ATTR                /* ATTR */      \
-                    | RS6000_BTC_SPR),                                 \
-                   CODE_FOR_ ## ICODE)                 /* ICODE */
-
-#define BU_HTM_SPR1(ENUM, NAME, ATTR, ICODE)                           \
+#define BU_HTM_V1(ENUM, NAME, ATTR, ICODE)                             \
   RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM,              /* ENUM */      \
                    "__builtin_" NAME,                  /* NAME */      \
                    RS6000_BTM_HTM,                     /* MASK */      \
                    (RS6000_BTC_ ## ATTR                /* ATTR */      \
                     | RS6000_BTC_UNARY                                 \
-                    | RS6000_BTC_SPR                                   \
                     | RS6000_BTC_VOID),                                \
                    CODE_FOR_ ## ICODE)                 /* ICODE */
 
@@ -1657,30 +1648,30 @@ BU_CRYPTO_OVERLOAD_3 (VSHASIGMA, "vshasigma")
 
 \f
 /* HTM functions.  */
-BU_HTM_1  (TABORT,     "tabort",       MISC,   tabort)
-BU_HTM_3  (TABORTDC,   "tabortdc",     MISC,   tabortdc)
-BU_HTM_3  (TABORTDCI,  "tabortdci",    MISC,   tabortdci)
-BU_HTM_3  (TABORTWC,   "tabortwc",     MISC,   tabortwc)
-BU_HTM_3  (TABORTWCI,  "tabortwci",    MISC,   tabortwci)
-BU_HTM_1  (TBEGIN,     "tbegin",       MISC,   tbegin)
-BU_HTM_1  (TCHECK,     "tcheck",       MISC,   tcheck)
-BU_HTM_1  (TEND,       "tend",         MISC,   tend)
-BU_HTM_0  (TENDALL,    "tendall",      MISC,   tend)
-BU_HTM_0  (TRECHKPT,   "trechkpt",     MISC,   trechkpt)
-BU_HTM_1  (TRECLAIM,   "treclaim",     MISC,   treclaim)
-BU_HTM_0  (TRESUME,    "tresume",      MISC,   tsr)
-BU_HTM_0  (TSUSPEND,   "tsuspend",     MISC,   tsr)
-BU_HTM_1  (TSR,                "tsr",          MISC,   tsr)
-BU_HTM_0  (TTEST,      "ttest",        MISC,   ttest)
-
-BU_HTM_SPR0 (GET_TFHAR,                "get_tfhar",    MISC,   nothing)
-BU_HTM_SPR1 (SET_TFHAR,                "set_tfhar",    MISC,   nothing)
-BU_HTM_SPR0 (GET_TFIAR,                "get_tfiar",    MISC,   nothing)
-BU_HTM_SPR1 (SET_TFIAR,                "set_tfiar",    MISC,   nothing)
-BU_HTM_SPR0 (GET_TEXASR,       "get_texasr",   MISC,   nothing)
-BU_HTM_SPR1 (SET_TEXASR,       "set_texasr",   MISC,   nothing)
-BU_HTM_SPR0 (GET_TEXASRU,      "get_texasru",  MISC,   nothing)
-BU_HTM_SPR1 (SET_TEXASRU,      "set_texasru",  MISC,   nothing)
+BU_HTM_1  (TABORT,     "tabort",       CR,     tabort)
+BU_HTM_3  (TABORTDC,   "tabortdc",     CR,     tabortdc)
+BU_HTM_3  (TABORTDCI,  "tabortdci",    CR,     tabortdci)
+BU_HTM_3  (TABORTWC,   "tabortwc",     CR,     tabortwc)
+BU_HTM_3  (TABORTWCI,  "tabortwci",    CR,     tabortwci)
+BU_HTM_1  (TBEGIN,     "tbegin",       CR,     tbegin)
+BU_HTM_0  (TCHECK,     "tcheck",       CR,     tcheck)
+BU_HTM_1  (TEND,       "tend",         CR,     tend)
+BU_HTM_0  (TENDALL,    "tendall",      CR,     tend)
+BU_HTM_0  (TRECHKPT,   "trechkpt",     CR,     trechkpt)
+BU_HTM_1  (TRECLAIM,   "treclaim",     CR,     treclaim)
+BU_HTM_0  (TRESUME,    "tresume",      CR,     tsr)
+BU_HTM_0  (TSUSPEND,   "tsuspend",     CR,     tsr)
+BU_HTM_1  (TSR,                "tsr",          CR,     tsr)
+BU_HTM_0  (TTEST,      "ttest",        CR,     ttest)
+
+BU_HTM_0  (GET_TFHAR,  "get_tfhar",    SPR,    nothing)
+BU_HTM_V1 (SET_TFHAR,  "set_tfhar",    SPR,    nothing)
+BU_HTM_0  (GET_TFIAR,  "get_tfiar",    SPR,    nothing)
+BU_HTM_V1 (SET_TFIAR,  "set_tfiar",    SPR,    nothing)
+BU_HTM_0  (GET_TEXASR, "get_texasr",   SPR,    nothing)
+BU_HTM_V1 (SET_TEXASR, "set_texasr",   SPR,    nothing)
+BU_HTM_0  (GET_TEXASRU,        "get_texasru",  SPR,    nothing)
+BU_HTM_V1 (SET_TEXASRU,        "set_texasru",  SPR,    nothing)
 
 \f
 /* 3 argument paired floating point builtins.  */
index 99e3fbbc21e456cb9b4252592bc19b4c2b7f0fa1..3245d46af63552e2c3b060a4c22877116d175add 100644 (file)
@@ -12687,9 +12687,9 @@ static inline enum insn_code
 rs6000_htm_spr_icode (bool nonvoid)
 {
   if (nonvoid)
-    return (TARGET_64BIT) ? CODE_FOR_htm_mfspr_di : CODE_FOR_htm_mfspr_si;
+    return (TARGET_POWERPC64) ? CODE_FOR_htm_mfspr_di : CODE_FOR_htm_mfspr_si;
   else
-    return (TARGET_64BIT) ? CODE_FOR_htm_mtspr_di : CODE_FOR_htm_mtspr_si;
+    return (TARGET_POWERPC64) ? CODE_FOR_htm_mtspr_di : CODE_FOR_htm_mtspr_si;
 }
 
 /* Expand the HTM builtin in EXP and store the result in TARGET.
@@ -12703,7 +12703,17 @@ htm_expand_builtin (tree exp, rtx target, bool * expandedp)
   const struct builtin_description *d;
   size_t i;
 
-  *expandedp = false;
+  *expandedp = true;
+
+  if (!TARGET_POWERPC64
+      && (fcode == HTM_BUILTIN_TABORTDC
+         || fcode == HTM_BUILTIN_TABORTDCI))
+    {
+      size_t uns_fcode = (size_t)fcode;
+      const char *name = rs6000_builtin_info[uns_fcode].name;
+      error ("builtin %s is only valid in 64-bit mode", name);
+      return const0_rtx;
+    }
 
   /* Expand the HTM builtins.  */
   d = bdesc_htm;
@@ -12716,26 +12726,29 @@ htm_expand_builtin (tree exp, rtx target, bool * expandedp)
        call_expr_arg_iterator iter;
        unsigned attr = rs6000_builtin_info[fcode].attr;
        enum insn_code icode = d->icode;
+       const struct insn_operand_data *insn_op;
+       bool uses_spr = (attr & RS6000_BTC_SPR);
+       rtx cr = NULL_RTX;
 
-       if (attr & RS6000_BTC_SPR)
+       if (uses_spr)
          icode = rs6000_htm_spr_icode (nonvoid);
+       insn_op = &insn_data[icode].operand[0];
 
        if (nonvoid)
          {
-           machine_mode tmode = insn_data[icode].operand[0].mode;
+           machine_mode tmode = (uses_spr) ? insn_op->mode : SImode;
            if (!target
                || GET_MODE (target) != tmode
-               || !(*insn_data[icode].operand[0].predicate) (target, tmode))
+               || (uses_spr && !(*insn_op->predicate) (target, tmode)))
              target = gen_reg_rtx (tmode);
-           op[nopnds++] = target;
+           if (uses_spr)
+             op[nopnds++] = target;
          }
 
        FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
        {
-         const struct insn_operand_data *insn_op;
-
          if (arg == error_mark_node || nopnds >= MAX_HTM_OPERANDS)
-           return NULL_RTX;
+           return const0_rtx;
 
          insn_op = &insn_data[icode].operand[nopnds];
 
@@ -12782,10 +12795,17 @@ htm_expand_builtin (tree exp, rtx target, bool * expandedp)
 
        /* If this builtin accesses SPRs, then pass in the appropriate
           SPR number and SPR regno as the last two operands.  */
-       if (attr & RS6000_BTC_SPR)
+       if (uses_spr)
          {
-           op[nopnds++] = gen_rtx_CONST_INT (Pmode, htm_spr_num (fcode));
-           op[nopnds++] = gen_rtx_REG (Pmode, htm_spr_regno (fcode));
+           machine_mode mode = (TARGET_POWERPC64) ? DImode : SImode;
+           op[nopnds++] = gen_rtx_CONST_INT (mode, htm_spr_num (fcode));
+           op[nopnds++] = gen_rtx_REG (mode, htm_spr_regno (fcode));
+         }
+       /* If this builtin accesses a CR, then pass in a scratch
+          CR as the last operand.  */
+       else if (attr & RS6000_BTC_CR)
+         { cr = gen_reg_rtx (CCmode);
+           op[nopnds++] = cr;
          }
 
 #ifdef ENABLE_CHECKING
@@ -12798,7 +12818,7 @@ htm_expand_builtin (tree exp, rtx target, bool * expandedp)
          expected_nopnds = 3;
        if (!(attr & RS6000_BTC_VOID))
          expected_nopnds += 1;
-       if (attr & RS6000_BTC_SPR)
+       if (uses_spr)
          expected_nopnds += 2;
 
        gcc_assert (nopnds == expected_nopnds && nopnds <= MAX_HTM_OPERANDS);
@@ -12825,12 +12845,41 @@ htm_expand_builtin (tree exp, rtx target, bool * expandedp)
          return NULL_RTX;
        emit_insn (pat);
 
-       *expandedp = true;
+       if (attr & RS6000_BTC_CR)
+         {
+           if (fcode == HTM_BUILTIN_TBEGIN)
+             {
+               /* Emit code to set TARGET to true or false depending on
+                  whether the tbegin. instruction successfully or failed
+                  to start a transaction.  We do this by placing the 1's
+                  complement of CR's EQ bit into TARGET.  */
+               rtx scratch = gen_reg_rtx (SImode);
+               emit_insn (gen_rtx_SET (VOIDmode, scratch,
+                                       gen_rtx_EQ (SImode, cr,
+                                                    const0_rtx)));
+               emit_insn (gen_rtx_SET (VOIDmode, target,
+                                       gen_rtx_XOR (SImode, scratch,
+                                                    GEN_INT (1))));
+             }
+           else
+             {
+               /* Emit code to copy the 4-bit condition register field
+                  CR into the least significant end of register TARGET.  */
+               rtx scratch1 = gen_reg_rtx (SImode);
+               rtx scratch2 = gen_reg_rtx (SImode);
+               rtx subreg = simplify_gen_subreg (CCmode, scratch1, SImode, 0);
+               emit_insn (gen_movcc (subreg, cr));
+               emit_insn (gen_lshrsi3 (scratch2, scratch1, GEN_INT (28)));
+               emit_insn (gen_andsi3 (target, scratch2, GEN_INT (0xf)));
+             }
+         }
+
        if (nonvoid)
          return target;
        return const0_rtx;
       }
 
+  *expandedp = false;
   return NULL_RTX;
 }
 
@@ -15319,8 +15368,31 @@ htm_init_builtins (void)
       bool void_func = (attr & RS6000_BTC_VOID);
       int attr_args = (attr & RS6000_BTC_TYPE_MASK);
       int nopnds = 0;
-      tree argtype = (attr & RS6000_BTC_SPR) ? long_unsigned_type_node
-                                            : unsigned_type_node;
+      tree gpr_type_node;
+      tree rettype;
+      tree argtype;
+
+      if (TARGET_32BIT && TARGET_POWERPC64)
+       gpr_type_node = long_long_unsigned_type_node;
+      else
+       gpr_type_node = long_unsigned_type_node;
+
+      if (attr & RS6000_BTC_SPR)
+       {
+         rettype = gpr_type_node;
+         argtype = gpr_type_node;
+       }
+      else if (d->code == HTM_BUILTIN_TABORTDC
+              || d->code == HTM_BUILTIN_TABORTDCI)
+       {
+         rettype = unsigned_type_node;
+         argtype = gpr_type_node;
+       }
+      else
+       {
+         rettype = unsigned_type_node;
+         argtype = unsigned_type_node;
+       }
 
       if ((mask & builtin_mask) != mask)
        {
@@ -15337,7 +15409,7 @@ htm_init_builtins (void)
          continue;
        }
 
-      op[nopnds++] = (void_func) ? void_type_node : argtype;
+      op[nopnds++] = (void_func) ? void_type_node : rettype;
 
       if (attr_args == RS6000_BTC_UNARY)
        op[nopnds++] = argtype;
index b13df1b2b6eb0fa3003da52dc4c1e1d71b05a536..653c2c94e11a6f22d20fe3e33532e4d354c2be5e 100644 (file)
@@ -2574,9 +2574,8 @@ extern int frame_pointer_needed;
 /* Miscellaneous information.  */
 #define RS6000_BTC_SPR         0x01000000      /* function references SPRs.  */
 #define RS6000_BTC_VOID                0x02000000      /* function has no return value.  */
-#define RS6000_BTC_OVERLOADED  0x04000000      /* function is overloaded.  */
-#define RS6000_BTC_32BIT       0x08000000      /* function references SPRs.  */
-#define RS6000_BTC_64BIT       0x10000000      /* function references SPRs.  */
+#define RS6000_BTC_CR          0x04000000      /* function references a CR.  */
+#define RS6000_BTC_OVERLOADED  0x08000000      /* function is overloaded.  */
 #define RS6000_BTC_MISC_MASK   0x1f000000      /* Mask of the misc info.  */
 
 /* Convenience macros to document the instruction type.  */
index 7470e40916687ca5586c260c0fc489e299cd9322..c7a0a3fdd2f6224b3c0beffbe89aa09f01f04a23 100644 (file)
@@ -15121,10 +15121,15 @@ The following low level built-in functions are available with
 @option{-mhtm} or @option{-mcpu=CPU} where CPU is `power8' or later.
 They all generate the machine instruction that is part of the name.
 
-The HTM built-ins return true or false depending on their success and
-their arguments match exactly the type and order of the associated
-hardware instruction's operands.  Refer to the ISA manual for a
-description of each instruction's operands.
+The HTM builtins (with the exception of @code{__builtin_tbegin}) return
+the full 4-bit condition register value set by their associated hardware
+instruction.  The header file @code{htmintrin.h} defines some macros that can
+be used to decipher the return value.  The @code{__builtin_tbegin} builtin
+returns a simple true or false value depending on whether a transaction was
+successfully started or not.  The arguments of the builtins match exactly the
+type and order of the associated hardware instruction's operands, except for
+the @code{__builtin_tcheck} builtin, which does not take any input arguments.
+Refer to the ISA manual for a description of each instruction's operands.
 
 @smallexample
 unsigned int __builtin_tbegin (unsigned int)
@@ -15136,7 +15141,7 @@ unsigned int __builtin_tabortdci (unsigned int, unsigned int, int)
 unsigned int __builtin_tabortwc (unsigned int, unsigned int, unsigned int)
 unsigned int __builtin_tabortwci (unsigned int, unsigned int, int)
 
-unsigned int __builtin_tcheck (unsigned int)
+unsigned int __builtin_tcheck (void)
 unsigned int __builtin_treclaim (unsigned int)
 unsigned int __builtin_trechkpt (void)
 unsigned int __builtin_tsr (unsigned int)
@@ -15271,7 +15276,7 @@ TM_buff_type TM_buff;
 
 while (1)
   @{
-    if (__TM_begin (TM_buff))
+    if (__TM_begin (TM_buff) == _HTM_TBEGIN_STARTED)
       @{
         /* Transaction State Initiated.  */
         if (is_locked (lock))
index c44dc28440db906b0f5ee4ab22083d9a21f1dac3..98aee26e93d90fff68276929e0cea42269dd4653 100644 (file)
@@ -1,3 +1,13 @@
+2015-04-27  Peter Bergner  <bergner@vnet.ibm.com>
+
+       PR target/64579
+       * gcc.target/powerpc/htm-1.c: New test.
+       * gcc.target/powerpc/htm-builtin-1.c (__builtin_tabortdc): Only test
+       on 64-bit compiles.
+       (__builtin_tabortdci): Likewise.
+       (__builtin_tcheck): Remove operand.
+       * lib/target-supports.exp (check_htm_hw_available): New function.
+
 2015-04-27  Richard Biener  <rguenther@suse.de>
 
        * gcc.target/i386/pr65217.c: XFAIL.
diff --git a/gcc/testsuite/gcc.target/powerpc/htm-1.c b/gcc/testsuite/gcc.target/powerpc/htm-1.c
new file mode 100644 (file)
index 0000000..f27e32c
--- /dev/null
@@ -0,0 +1,52 @@
+/* { dg-do run { target { powerpc*-*-* && htm_hw } } } */
+/* { dg-require-effective-target powerpc_htm_ok } */
+/* { dg-options "-mhtm" } */
+
+/* Program to test PowerPC HTM instructions.  */
+
+#include <stdlib.h>
+#include <htmintrin.h>
+
+int
+main (void)
+{
+  long i;
+  unsigned long mask = 0;
+
+repeat:
+  if (__builtin_tbegin (0))
+    {
+      mask++;
+    }
+  else
+    abort();
+
+  if (mask == 1)
+    {
+      __builtin_tsuspend ();
+
+      if (_HTM_STATE (__builtin_tcheck ()) != _HTM_SUSPENDED)
+       abort ();
+
+      __builtin_tresume ();
+
+      if (_HTM_STATE (__builtin_tcheck ()) != _HTM_TRANSACTIONAL)
+       abort ();
+    }
+  else
+    mask++;
+
+  if (_HTM_STATE (__builtin_tendall ()) != _HTM_TRANSACTIONAL)
+    abort ();
+
+  if (mask == 1)
+    goto repeat;
+
+  if (_HTM_STATE (__builtin_tendall ()) != _HTM_NONTRANSACTIONAL)
+    abort ();
+
+  if (mask != 3)
+    abort ();
+
+  return 0;
+}
index 3e4b72919e944b0bb7451203d555565d74d9f198..b232580a20b0b44dfc18cd8cc9d7b1a6ad898c4d 100644 (file)
@@ -6,8 +6,8 @@
 /* { dg-final { scan-assembler-times "tbegin\\." 1 } } */
 /* { dg-final { scan-assembler-times "tend\\." 2 } } */
 /* { dg-final { scan-assembler-times "tabort\\." 2 } } */
-/* { dg-final { scan-assembler-times "tabortdc\\." 1 } } */
-/* { dg-final { scan-assembler-times "tabortdci\\." 1 } } */
+/* { dg-final { scan-assembler-times "tabortdc\\." 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "tabortdci\\." 1 { target lp64 } } } */
 /* { dg-final { scan-assembler-times "tabortwc\\." 1 } } */
 /* { dg-final { scan-assembler-times "tabortwci\\." 2 } } */
 /* { dg-final { scan-assembler-times "tcheck" 1 } } */
@@ -25,12 +25,14 @@ void use_builtins (long *p, char code, long *a, long *b)
   p[3] = __builtin_tabort (0);
   p[4] = __builtin_tabort (code);
 
+#ifdef __powerpc64__
   p[5] = __builtin_tabortdc (0xf, a[5], b[5]);
   p[6] = __builtin_tabortdci (0xf, a[6], 13);
+#endif
   p[7] = __builtin_tabortwc (0xf, a[7], b[7]);
   p[8] = __builtin_tabortwci (0xf, a[8], 13);
 
-  p[9] = __builtin_tcheck (5);
+  p[9] = __builtin_tcheck ();
   p[10] = __builtin_trechkpt ();
   p[11] = __builtin_treclaim (0);
   p[12] = __builtin_tresume ();
index c23d1cbb6e19c9635cd68321e1d77ddd8d9f70dd..c5d0ffe06e2a4a7be2a439631899bf2e14a0293c 100644 (file)
@@ -3279,6 +3279,25 @@ proc check_effective_target_powerpc_htm_ok { } {
     }
 }
 
+# Return 1 if the target supports executing HTM hardware instructions,
+# 0 otherwise.  Cache the result.
+
+proc check_htm_hw_available { } {
+    return [check_cached_effective_target htm_hw_available {
+       # For now, disable on Darwin
+       if { [istarget powerpc-*-eabi] || [istarget powerpc*-*-eabispe] || [istarget *-*-darwin*]} {
+           expr 0
+       } else {
+           check_runtime_nocache htm_hw_available {
+               int main()
+               {
+                 __builtin_ttest ();
+                 return 0;
+               }
+           } "-mhtm"
+       }
+    }]
+}
 # Return 1 if this is a PowerPC target supporting -mcpu=cell.
 
 proc check_effective_target_powerpc_ppu_ok { } {
@@ -5280,6 +5299,7 @@ proc is-effective-target { arg } {
          "p8vector_hw"    { set selected [check_p8vector_hw_available] }
          "ppc_recip_hw"   { set selected [check_ppc_recip_hw_available] }
          "dfp_hw"         { set selected [check_dfp_hw_available] }
+         "htm_hw"         { set selected [check_htm_hw_available] }
          "named_sections" { set selected [check_named_sections_available] }
          "gc_sections"    { set selected [check_gc_sections_available] }
          "cxa_atexit"     { set selected [check_cxa_atexit_available] }
@@ -5303,6 +5323,7 @@ proc is-effective-target-keyword { arg } {
          "p8vector_hw"    { return 1 }
          "ppc_recip_hw"   { return 1 }
          "dfp_hw"         { return 1 }
+         "htm_hw"         { return 1 }
          "named_sections" { return 1 }
          "gc_sections"    { return 1 }
          "cxa_atexit"     { return 1 }