From patchwork Wed Mar 19 19:25:03 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bill Schmidt X-Patchwork-Id: 331835 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id E03AE2C009A for ; Thu, 20 Mar 2014 06:25:19 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:subject:from:to:cc:date:content-type :content-transfer-encoding:mime-version; q=dns; s=default; b=pll qMagA6IubWpNS2ao4b+TR6dLrk2iSzIkty73xIS9mVzlhoKp5P0ZdKYp7DrUeleR fBHlVYhPUxULtgRD/nxIIllC0iQ3Xr+NZW4AMYm79PJwwbfucNbQ82lkIkOYokbq QS/OwXxDQ8NMkPrJJwdvMdxYxZC4zOYOV9IKnm5A= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:subject:from:to:cc:date:content-type :content-transfer-encoding:mime-version; s=default; bh=n9nBwiMOU Pya4e5bqW86XzZ1k6o=; b=Sla7wFWeFwuwkPqHOtsw2AltfnO46FGLlGYXRd1jp jSPRAGa0Hq5MmnFUxk7a0GvLF3MgGSw/eOQ+VR2ttv7B0pTGN9UgTRQfYpvHb/0h cxHRd1xUb06NMUkGQuSu2HLmc1XFDUiUdpxIMvH0x6DaTdrEwDaN4maZKOjEP/IX 6M= Received: (qmail 8014 invoked by alias); 19 Mar 2014 19:25:10 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 7994 invoked by uid 89); 19 Mar 2014 19:25:09 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.5 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: e28smtp02.in.ibm.com Received: from e28smtp02.in.ibm.com (HELO e28smtp02.in.ibm.com) (122.248.162.2) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Wed, 19 Mar 2014 19:25:02 +0000 Received: from /spool/local by e28smtp02.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 20 Mar 2014 00:54:56 +0530 Received: from d28dlp03.in.ibm.com (9.184.220.128) by e28smtp02.in.ibm.com (192.168.1.132) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 20 Mar 2014 00:54:54 +0530 Received: from d28relay01.in.ibm.com (d28relay01.in.ibm.com [9.184.220.58]) by d28dlp03.in.ibm.com (Postfix) with ESMTP id 2585E1258048 for ; Thu, 20 Mar 2014 00:57:14 +0530 (IST) Received: from d28av04.in.ibm.com (d28av04.in.ibm.com [9.184.220.66]) by d28relay01.in.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id s2JJOm3A3670442 for ; Thu, 20 Mar 2014 00:54:48 +0530 Received: from d28av04.in.ibm.com (localhost [127.0.0.1]) by d28av04.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id s2JJOr31001242 for ; Thu, 20 Mar 2014 00:54:53 +0530 Received: from [9.50.16.86] (dyn9050016086.mts.ibm.com [9.50.16.86] (may be forged)) by d28av04.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id s2JJOoho001133; Thu, 20 Mar 2014 00:54:51 +0530 Message-ID: <1395257103.17148.4.camel@gnopaine> Subject: [4.8, PATCH 2/26] Backport Power8 and LE support: HTM support From: Bill Schmidt To: gcc-patches@gcc.gnu.org Cc: dje.gcc@gmail.com, jakub@redhat.com, rguenther@suse.de Date: Wed, 19 Mar 2014 14:25:03 -0500 Mime-Version: 1.0 X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 14031919-5816-0000-0000-00000CF163CE X-IsSubscribed: yes Hi, This patch (diff-p8-htm) backports hardware transactional memory support. Copying Jakub and Richard for the libitm support. Thanks, Bill [gcc] 2014-03-29 Bill Schmidt Backport from mainline 2013-12-03 Peter Bergner * config/rs6000/htmintrin.h (_TEXASR_INSTRUCTION_FETCH_CONFLICT): Fix typo in macro name. (_TEXASRU_INSTRUCTION_FETCH_CONFLICT): Likewise. Backport from mainline r205233. 2013-11-21 Peter Bergner * doc/extend.texi: Document htm builtins. Backport from mainline 2013-07-17 Iain Sandoe * config/rs6000/darwin.h (REGISTER_NAMES): Add HTM registers. Backport from mainline 2013-07-16 Peter Bergner * config/rs6000/rs6000.c (rs6000_option_override_internal): Do not enable extra ISA flags with TARGET_HTM. 2013-07-16 Jakub Jelinek Peter Bergner * config/rs6000/rs6000.h (FIRST_PSEUDO_REGISTERS): Mention HTM registers in the comment. (DWARF_FRAME_REGISTERS): Subtract also the 3 HTM registers. (DWARF_REG_TO_UNWIND_COLUMN): Use DWARF_FRAME_REGISTERS rather than FIRST_PSEUDO_REGISTERS. * config.gcc (powerpc*-*-*): Install htmintrin.h and htmxlintrin.h. * config/rs6000/t-rs6000 (MD_INCLUDES): Add htm.md. * config/rs6000/rs6000.opt: Add -mhtm option. * config/rs6000/rs6000-cpus.def (POWERPC_MASKS): Add OPTION_MASK_HTM. (ISA_2_7_MASKS_SERVER): Add OPTION_MASK_HTM. * config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Define __HTM__ if the HTM instructions are available. * config/rs6000/predicates.md (u3bit_cint_operand, u10bit_cint_operand, htm_spr_reg_operand): New define_predicates. * config/rs6000/rs6000.md (define_attr "type"): Add htm. (TFHAR_REGNO, TFIAR_REGNO, TEXASR_REGNO): New define_constants. Include htm.md. * config/rs6000/rs6000-builtin.def (BU_HTM_0, BU_HTM_1, BU_HTM_2, BU_HTM_3, BU_HTM_SPR0, BU_HTM_SPR1): Add support macros for defining HTM builtin functions. * config/rs6000/rs6000.c (RS6000_BUILTIN_H): New macro. (rs6000_reg_names, alt_reg_names): Add HTM SPR register names. (rs6000_init_hard_regno_mode_ok): Add support for HTM instructions. (rs6000_builtin_mask_calculate): Likewise. (rs6000_option_override_internal): Likewise. (bdesc_htm): Add new HTM builtin support. (htm_spr_num): New function. (htm_spr_regno): Likewise. (rs6000_htm_spr_icode): Likewise. (htm_expand_builtin): Likewise. (htm_init_builtins): Likewise. (rs6000_expand_builtin): Add support for HTM builtin functions. (rs6000_init_builtins): Likewise. (rs6000_invalid_builtin, rs6000_opt_mask): Add support for -mhtm option. * config/rs6000/rs6000.h (ASM_CPU_SPEC): Add support for -mhtm. (TARGET_HTM, MASK_HTM): Define macros. (FIRST_PSEUDO_REGISTER): Adjust for new HTM SPR registers. (FIXED_REGISTERS): Likewise. (CALL_USED_REGISTERS): Likewise. (CALL_REALLY_USED_REGISTERS): Likewise. (REG_ALLOC_ORDER): Likewise. (enum reg_class): Likewise. (REG_CLASS_NAMES): Likewise. (REG_CLASS_CONTENTS): Likewise. (REGISTER_NAMES): Likewise. (ADDITIONAL_REGISTER_NAMES): Likewise. (RS6000_BTC_SPR, RS6000_BTC_VOID, RS6000_BTC_32BIT, RS6000_BTC_64BIT, RS6000_BTC_MISC_MASK, RS6000_BTM_HTM): New macros. (RS6000_BTM_COMMON): Add RS6000_BTM_HTM. * config/rs6000/htm.md: New file. * config/rs6000/htmintrin.h: New file. * config/rs6000/htmxlintrin.h: New file. [libitm] 2014-03-29 Bill Schmidt Backport from mainline * acinclude.m4 (LIBITM_CHECK_AS_HTM): New. * configure: Rebuild. * configure.tgt (target_cpu): Add -mhtm to XCFLAGS. * config/powerpc/target.h: Include sys/auxv.h and htmintrin.h. (USE_HTM_FASTPATH): Define. (_TBEGIN_STARTED, _TBEGIN_INDETERMINATE, _TBEGIN_PERSISTENT, _HTM_RETRIES) New macros. (htm_abort, htm_abort_should_retry, htm_available, htm_begin, htm_init, htm_begin_success, htm_commit, htm_transaction_active): New functions. [gcc/testsuite] 2014-03-29 Bill Schmidt Backport from mainline * lib/target-supports.exp (check_effective_target_powerpc_htm_ok): New function to test if HTM is available. * gcc.target/powerpc/htm-xl-intrin-1.c: New test. * gcc.target/powerpc/htm-builtin-1.c: New test. Index: gcc-4_8-test/gcc/config.gcc =================================================================== --- gcc-4_8-test.orig/gcc/config.gcc +++ gcc-4_8-test/gcc/config.gcc @@ -420,7 +420,7 @@ picochip-*-*) ;; powerpc*-*-*) cpu_type=rs6000 - extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h spu2vmx.h vec_types.h si2vmx.h" + extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h spu2vmx.h vec_types.h si2vmx.h htmintrin.h htmxlintrin.h" need_64bit_hwint=yes case x$with_cpu in xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[345678]|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|Xe6500) Index: gcc-4_8-test/gcc/config/rs6000/htm.md =================================================================== --- /dev/null +++ gcc-4_8-test/gcc/config/rs6000/htm.md @@ -0,0 +1,366 @@ +;; Hardware Transactional Memory (HTM) patterns. +;; Copyright (C) 2013 Free Software Foundation, Inc. +;; Contributed by Peter Bergner . + +;; This file is part of GCC. + +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published +;; by the Free Software Foundation; either version 3, or (at your +;; option) any later version. + +;; GCC is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; . + +(define_constants + [(TFHAR_SPR 128) + (TFIAR_SPR 129) + (TEXASR_SPR 130) + (TEXASRU_SPR 131) + (MAX_HTM_OPERANDS 4) + ]) + +;; +;; UNSPEC_VOLATILE usage +;; + +(define_c_enum "unspecv" + [UNSPECV_HTM_TABORT + UNSPECV_HTM_TABORTDC + UNSPECV_HTM_TABORTDCI + UNSPECV_HTM_TABORTWC + UNSPECV_HTM_TABORTWCI + UNSPECV_HTM_TBEGIN + UNSPECV_HTM_TCHECK + UNSPECV_HTM_TEND + UNSPECV_HTM_TRECHKPT + UNSPECV_HTM_TRECLAIM + UNSPECV_HTM_TSR + 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" "") + (minus:SI (const_int 1) (match_dup 3)))] + "TARGET_HTM" +{ + operands[2] = gen_rtx_REG (CCmode, CR0_REGNO); + operands[3] = gen_reg_rtx (SImode); +}) + +(define_insn "*tabort_internal" + [(set (match_operand:CC 1 "cc_reg_operand" "=x") + (unspec_volatile:CC [(match_operand:SI 0 "int_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" "") + (minus:SI (const_int 1) (match_dup 5)))] + "TARGET_HTM" +{ + operands[4] = gen_rtx_REG (CCmode, CR0_REGNO); + operands[5] = gen_reg_rtx (SImode); +}) + +(define_insn "*tabortdc_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_TABORTDC))] + "TARGET_HTM" + "tabortdc. %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" "") + (minus:SI (const_int 1) (match_dup 5)))] + "TARGET_HTM" +{ + operands[4] = gen_rtx_REG (CCmode, CR0_REGNO); + operands[5] = gen_reg_rtx (SImode); +}) + +(define_insn "*tabortdci_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_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" "") + (minus:SI (const_int 1) (match_dup 5)))] + "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))] + "TARGET_HTM" + "tabortwc. %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" "") + (minus:SI (const_int 1) (match_dup 5)))] + "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 24))) + (parallel [(set (match_operand:SI 0 "int_reg_operand" "") + (and:SI (match_dup 3) (const_int 15))) + (clobber (scratch:CC))])] + "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" "") + (minus:SI (const_int 1) (match_dup 3)))] + "TARGET_HTM" +{ + operands[2] = gen_rtx_REG (CCmode, CR0_REGNO); + operands[3] = gen_reg_rtx (SImode); +}) + +(define_insn "*tbegin_internal" + [(set (match_operand:CC 1 "cc_reg_operand" "=x") + (unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")] + UNSPECV_HTM_TBEGIN))] + "TARGET_HTM" + "tbegin. %0" + [(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" "") + (minus:SI (const_int 1) (match_dup 3)))] + "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")] + 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" "") + (minus:SI (const_int 1) (match_dup 3)))] + "TARGET_HTM" +{ + operands[2] = gen_rtx_REG (CCmode, CR0_REGNO); + operands[3] = gen_reg_rtx (SImode); +}) + +(define_insn "*tend_internal" + [(set (match_operand:CC 1 "cc_reg_operand" "=x") + (unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")] + UNSPECV_HTM_TEND))] + "TARGET_HTM" + "tend. %0" + [(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" "") + (minus:SI (const_int 1) (match_dup 2)))] + "TARGET_HTM" +{ + operands[1] = gen_rtx_REG (CCmode, CR0_REGNO); + operands[2] = gen_reg_rtx (SImode); +}) + +(define_insn "*trechkpt_internal" + [(set (match_operand:CC 0 "cc_reg_operand" "=x") + (unspec_volatile:CC [(const_int 0)] + UNSPECV_HTM_TRECHKPT))] + "TARGET_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" "") + (minus:SI (const_int 1) (match_dup 3)))] + "TARGET_HTM" +{ + operands[2] = gen_rtx_REG (CCmode, CR0_REGNO); + operands[3] = gen_reg_rtx (SImode); +}) + +(define_insn "*treclaim_internal" + [(set (match_operand:CC 1 "cc_reg_operand" "=x") + (unspec_volatile:CC [(match_operand:SI 0 "gpc_reg_operand" "r")] + UNSPECV_HTM_TRECLAIM))] + "TARGET_HTM" + "treclaim. %0" + [(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" "") + (minus:SI (const_int 1) (match_dup 3)))] + "TARGET_HTM" +{ + operands[2] = gen_rtx_REG (CCmode, CR0_REGNO); + operands[3] = gen_reg_rtx (SImode); +}) + +(define_insn "*tsr_internal" + [(set (match_operand:CC 1 "cc_reg_operand" "=x") + (unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")] + UNSPECV_HTM_TSR))] + "TARGET_HTM" + "tsr. %0" + [(set_attr "type" "htm") + (set_attr "length" "4")]) + +(define_insn "htm_mfspr_" + [(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))] + "TARGET_HTM" + "mfspr %0,%1"; + [(set_attr "type" "htm") + (set_attr "length" "4")]) + +(define_insn "htm_mtspr_" + [(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))] + "TARGET_HTM" + "mtspr %1,%0"; + [(set_attr "type" "htm") + (set_attr "length" "4")]) Index: gcc-4_8-test/gcc/config/rs6000/htmintrin.h =================================================================== --- /dev/null +++ gcc-4_8-test/gcc/config/rs6000/htmintrin.h @@ -0,0 +1,131 @@ +/* Hardware Transactional Memory (HTM) intrinsics. + Copyright (C) 2013 Free Software Foundation, Inc. + Contributed by Peter Bergner . + + This file is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your option) + any later version. + + This file is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef __HTM__ +# error "HTM instruction set not enabled" +#endif /* __HTM__ */ + +#ifndef _HTMINTRIN_H +#define _HTMINTRIN_H + +#include + +typedef uint64_t texasr_t; +typedef uint32_t texasru_t; +typedef uint32_t texasrl_t; +typedef uintptr_t tfiar_t; +typedef uintptr_t tfhar_t; + +#define _HTM_STATE(CR0) ((CR0 >> 1) & 0x3) +#define _HTM_NONTRANSACTIONAL 0x0 +#define _HTM_SUSPENDED 0x1 +#define _HTM_TRANSACTIONAL 0x2 + +/* The following macros use the IBM bit numbering for BITNUM + as used in the ISA documentation. */ + +#define _TEXASR_EXTRACT_BITS(TEXASR,BITNUM,SIZE) \ + (((TEXASR) >> (63-(BITNUM))) & ((1<<(SIZE))-1)) +#define _TEXASRU_EXTRACT_BITS(TEXASR,BITNUM,SIZE) \ + (((TEXASR) >> (31-(BITNUM))) & ((1<<(SIZE))-1)) + +#define _TEXASR_FAILURE_CODE(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 7, 8) +#define _TEXASRU_FAILURE_CODE(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 7, 8) + +#define _TEXASR_FAILURE_PERSISTENT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 7, 1) +#define _TEXASRU_FAILURE_PERSISTENT(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 7, 1) + +#define _TEXASR_DISALLOWED(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 8, 1) +#define _TEXASRU_DISALLOWED(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 8, 1) + +#define _TEXASR_NESTING_OVERFLOW(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 9, 1) +#define _TEXASRU_NESTING_OVERFLOW(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 9, 1) + +#define _TEXASR_FOOTPRINT_OVERFLOW(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 10, 1) +#define _TEXASRU_FOOTPRINT_OVERFLOW(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 10, 1) + +#define _TEXASR_SELF_INDUCED_CONFLICT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 11, 1) +#define _TEXASRU_SELF_INDUCED_CONFLICT(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 11, 1) + +#define _TEXASR_NON_TRANSACTIONAL_CONFLICT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 12, 1) +#define _TEXASRU_NON_TRANSACTIONAL_CONFLICT(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 12, 1) + +#define _TEXASR_TRANSACTION_CONFLICT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 13, 1) +#define _TEXASRU_TRANSACTION_CONFLICT(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 13, 1) + +#define _TEXASR_TRANSLATION_INVALIDATION_CONFLICT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 14, 1) +#define _TEXASRU_TRANSLATION_INVALIDATION_CONFLICT(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 14, 1) + +#define _TEXASR_IMPLEMENTAION_SPECIFIC(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 15, 1) +#define _TEXASRU_IMPLEMENTAION_SPECIFIC(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 15, 1) + +#define _TEXASR_INSTRUCTION_FETCH_CONFLICT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 16, 1) +#define _TEXASRU_INSTRUCTION_FETCH_CONFLICT(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 16, 1) + +#define _TEXASR_ABORT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 31, 1) +#define _TEXASRU_ABORT(TEXASRU) \ + _TEXASRU_EXTRACT_BITS(TEXASRU, 31, 1) + + +#define _TEXASR_SUSPENDED(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 32, 1) + +#define _TEXASR_PRIVILEGE(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 35, 2) + +#define _TEXASR_FAILURE_SUMMARY(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 36, 1) + +#define _TEXASR_TFIAR_EXACT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 37, 1) + +#define _TEXASR_ROT(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 38, 1) + +#define _TEXASR_TRANSACTION_LEVEL(TEXASR) \ + _TEXASR_EXTRACT_BITS(TEXASR, 63, 12) + +#endif /* _HTMINTRIN_H */ Index: gcc-4_8-test/gcc/config/rs6000/htmxlintrin.h =================================================================== --- /dev/null +++ gcc-4_8-test/gcc/config/rs6000/htmxlintrin.h @@ -0,0 +1,208 @@ +/* XL compiler Hardware Transactional Memory (HTM) execution intrinsics. + Copyright (C) 2013 Free Software Foundation, Inc. + Contributed by Peter Bergner . + + This file is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your option) + any later version. + + This file is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef __HTM__ +# error "HTM instruction set not enabled" +#endif /* __HTM__ */ + +#ifndef _HTMXLINTRIN_H +#define _HTMXLINTRIN_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define _TEXASR_PTR(TM_BUF) \ + ((texasr_t *)((TM_BUF)+0)) +#define _TEXASRU_PTR(TM_BUF) \ + ((texasru_t *)((TM_BUF)+0)) +#define _TEXASRL_PTR(TM_BUF) \ + ((texasrl_t *)((TM_BUF)+4)) +#define _TFIAR_PTR(TM_BUF) \ + ((tfiar_t *)((TM_BUF)+8)) + +typedef char TM_buff_type[16]; + +extern __inline long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_simple_begin (void) +{ + if (__builtin_expect (__builtin_tbegin (0), 1)) + return 1; + return 0; +} + +extern __inline long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_begin (void* const TM_buff) +{ + *_TEXASRL_PTR (TM_buff) = 0; + if (__builtin_expect (__builtin_tbegin (0), 1)) + return 1; +#ifdef __powerpc64__ + *_TEXASR_PTR (TM_buff) = __builtin_get_texasr (); +#else + *_TEXASRU_PTR (TM_buff) = __builtin_get_texasru (); + *_TEXASRL_PTR (TM_buff) = __builtin_get_texasr (); +#endif + *_TFIAR_PTR (TM_buff) = __builtin_get_tfiar (); + return 0; +} + +extern __inline long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_end (void) +{ + if (__builtin_expect (__builtin_tend (0), 1)) + return 1; + return 0; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_abort (void) +{ + __builtin_tabort (0); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_named_abort (unsigned char const code) +{ + __builtin_tabort (code); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_resume (void) +{ + __builtin_tresume (); +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_suspend (void) +{ + __builtin_tsuspend (); +} + +extern __inline long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_is_user_abort (void* const TM_buff) +{ + texasru_t texasru = *_TEXASRU_PTR (TM_buff); + return _TEXASRU_ABORT (texasru); +} + +extern __inline long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_is_named_user_abort (void* const TM_buff, unsigned char *code) +{ + texasru_t texasru = *_TEXASRU_PTR (TM_buff); + + *code = _TEXASRU_FAILURE_CODE (texasru); + return _TEXASRU_ABORT (texasru); +} + +extern __inline long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_is_illegal (void* const TM_buff) +{ + texasru_t texasru = *_TEXASRU_PTR (TM_buff); + return _TEXASRU_DISALLOWED (texasru); +} + +extern __inline long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_is_footprint_exceeded (void* const TM_buff) +{ + texasru_t texasru = *_TEXASRU_PTR (TM_buff); + return _TEXASRU_FOOTPRINT_OVERFLOW (texasru); +} + +extern __inline long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_nesting_depth (void* const TM_buff) +{ + texasrl_t texasrl; + + if (_HTM_STATE (__builtin_ttest ()) == _HTM_NONTRANSACTIONAL) + { + texasrl = *_TEXASRL_PTR (TM_buff); + if (!_TEXASR_FAILURE_SUMMARY (texasrl)) + texasrl = 0; + } + else + texasrl = (texasrl_t) __builtin_get_texasr (); + + return _TEXASR_TRANSACTION_LEVEL (texasrl); +} + +extern __inline long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_is_nested_too_deep(void* const TM_buff) +{ + texasru_t texasru = *_TEXASRU_PTR (TM_buff); + return _TEXASRU_NESTING_OVERFLOW (texasru); +} + +extern __inline long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_is_conflict(void* const TM_buff) +{ + texasru_t texasru = *_TEXASRU_PTR (TM_buff); + /* Return TEXASR bits 11 (Self-Induced Conflict) through + 14 (Translation Invalidation Conflict). */ + return (_TEXASRU_EXTRACT_BITS (texasru, 14, 4)) ? 1 : 0; +} + +extern __inline long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_is_failure_persistent(void* const TM_buff) +{ + texasru_t texasru = *_TEXASRU_PTR (TM_buff); + return _TEXASRU_FAILURE_PERSISTENT (texasru); +} + +extern __inline long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_failure_address(void* const TM_buff) +{ + return *_TFIAR_PTR (TM_buff); +} + +extern __inline long long +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__TM_failure_code(void* const TM_buff) +{ + return *_TEXASR_PTR (TM_buff); +} + +#ifdef __cplusplus +} +#endif + +#endif /* _HTMXLINTRIN_H */ Index: gcc-4_8-test/gcc/config/rs6000/predicates.md =================================================================== --- gcc-4_8-test.orig/gcc/config/rs6000/predicates.md +++ gcc-4_8-test/gcc/config/rs6000/predicates.md @@ -124,6 +124,11 @@ (and (match_code "const_int") (match_test "INTVAL (op) >= -16 && INTVAL (op) <= 15"))) +;; Return 1 if op is a unsigned 3-bit constant integer. +(define_predicate "u3bit_cint_operand" + (and (match_code "const_int") + (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 7"))) + ;; Return 1 if op is a unsigned 5-bit constant integer. (define_predicate "u5bit_cint_operand" (and (match_code "const_int") @@ -135,6 +140,11 @@ (and (match_code "const_int") (match_test "INTVAL (op) >= -128 && INTVAL (op) <= 127"))) +;; Return 1 if op is a unsigned 10-bit constant integer. +(define_predicate "u10bit_cint_operand" + (and (match_code "const_int") + (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 1023"))) + ;; Return 1 if op is a constant integer that can fit in a D field. (define_predicate "short_cint_operand" (and (match_code "const_int") @@ -226,6 +236,33 @@ return (REGNO (op) != FIRST_GPR_REGNO); }) +;; Return 1 if op is a HTM specific SPR register. +(define_predicate "htm_spr_reg_operand" + (match_operand 0 "register_operand") +{ + if (!TARGET_HTM) + return 0; + + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + if (!REG_P (op)) + return 0; + + switch (REGNO (op)) + { + case TFHAR_REGNO: + case TFIAR_REGNO: + case TEXASR_REGNO: + return 1; + default: + break; + } + + /* Unknown SPR. */ + return 0; +}) + ;; Return 1 if op is a general purpose register that is an even register ;; which suitable for a load/store quad operation (define_predicate "quad_int_reg_operand" Index: gcc-4_8-test/gcc/config/rs6000/rs6000-builtin.def =================================================================== --- gcc-4_8-test.orig/gcc/config/rs6000/rs6000-builtin.def +++ gcc-4_8-test/gcc/config/rs6000/rs6000-builtin.def @@ -30,6 +30,7 @@ RS6000_BUILTIN_A -- ABS builtins RS6000_BUILTIN_D -- DST builtins RS6000_BUILTIN_E -- SPE EVSEL builtins. + RS6000_BUILTIN_H -- HTM builtins RS6000_BUILTIN_P -- Altivec, VSX, ISA 2.07 vector predicate builtins RS6000_BUILTIN_Q -- Paired floating point VSX predicate builtins RS6000_BUILTIN_S -- SPE predicate builtins @@ -66,6 +67,10 @@ #error "RS6000_BUILTIN_E is not defined." #endif +#ifndef RS6000_BUILTIN_H + #error "RS6000_BUILTIN_H is not defined." +#endif + #ifndef RS6000_BUILTIN_P #error "RS6000_BUILTIN_P is not defined." #endif @@ -403,6 +408,56 @@ | RS6000_BTC_TERNARY), \ CODE_FOR_nothing) /* ICODE */ +/* HTM convenience macros. */ +#define BU_HTM_0(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_" NAME, /* NAME */ \ + RS6000_BTM_HTM, /* MASK */ \ + RS6000_BTC_ ## ATTR, /* ATTR */ \ + CODE_FOR_ ## ICODE) /* ICODE */ + +#define BU_HTM_1(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), \ + CODE_FOR_ ## ICODE) /* ICODE */ + +#define BU_HTM_2(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_" NAME, /* NAME */ \ + RS6000_BTM_HTM, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_BINARY), \ + CODE_FOR_ ## ICODE) /* ICODE */ + +#define BU_HTM_3(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_" NAME, /* NAME */ \ + RS6000_BTM_HTM, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | 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) \ + 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 */ + /* SPE convenience macros. */ #define BU_SPE_1(ENUM, NAME, ATTR, ICODE) \ RS6000_BUILTIN_1 (SPE_BUILTIN_ ## ENUM, /* ENUM */ \ @@ -1367,6 +1422,33 @@ BU_CRYPTO_OVERLOAD_3 (VPERMXOR, "vpermx BU_CRYPTO_OVERLOAD_3 (VSHASIGMA, "vshasigma") +/* 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) + + /* 3 argument paired floating point builtins. */ BU_PAIRED_3 (MSUB, "msub", FP, fmsv2sf4) BU_PAIRED_3 (MADD, "madd", FP, fmav2sf4) @@ -1665,10 +1747,10 @@ BU_SPECIAL_X (RS6000_BUILTIN_RSQRTF, "__ RS6000_BTC_FP) BU_SPECIAL_X (RS6000_BUILTIN_GET_TB, "__builtin_ppc_get_timebase", - RS6000_BTM_ALWAYS, RS6000_BTC_MISC) + RS6000_BTM_ALWAYS, RS6000_BTC_MISC) BU_SPECIAL_X (RS6000_BUILTIN_MFTB, "__builtin_ppc_mftb", - RS6000_BTM_ALWAYS, RS6000_BTC_MISC) + RS6000_BTM_ALWAYS, RS6000_BTC_MISC) /* Darwin CfString builtin. */ BU_SPECIAL_X (RS6000_BUILTIN_CFSTRING, "__builtin_cfstring", RS6000_BTM_ALWAYS, Index: gcc-4_8-test/gcc/config/rs6000/rs6000-c.c =================================================================== --- gcc-4_8-test.orig/gcc/config/rs6000/rs6000-c.c +++ gcc-4_8-test/gcc/config/rs6000/rs6000-c.c @@ -333,6 +333,8 @@ rs6000_target_modify_macros (bool define } if ((flags & OPTION_MASK_VSX) != 0) rs6000_define_or_undefine_macro (define_p, "__VSX__"); + if ((flags & OPTION_MASK_HTM) != 0) + rs6000_define_or_undefine_macro (define_p, "__HTM__"); if ((flags & OPTION_MASK_P8_VECTOR) != 0) rs6000_define_or_undefine_macro (define_p, "__POWER8_VECTOR__"); if ((flags & OPTION_MASK_CRYPTO) != 0) Index: gcc-4_8-test/gcc/config/rs6000/rs6000-cpus.def =================================================================== --- gcc-4_8-test.orig/gcc/config/rs6000/rs6000-cpus.def +++ gcc-4_8-test/gcc/config/rs6000/rs6000-cpus.def @@ -52,6 +52,7 @@ | OPTION_MASK_P8_VECTOR \ | OPTION_MASK_CRYPTO \ | OPTION_MASK_DIRECT_MOVE \ + | OPTION_MASK_HTM \ | OPTION_MASK_QUAD_MEMORY) #define POWERPC_7400_MASK (OPTION_MASK_PPC_GFXOPT | OPTION_MASK_ALTIVEC) @@ -75,6 +76,7 @@ | OPTION_MASK_DIRECT_MOVE \ | OPTION_MASK_DLMZB \ | OPTION_MASK_FPRND \ + | OPTION_MASK_HTM \ | OPTION_MASK_ISEL \ | OPTION_MASK_MFCRF \ | OPTION_MASK_MFPGPR \ Index: gcc-4_8-test/gcc/config/rs6000/rs6000.c =================================================================== --- gcc-4_8-test.orig/gcc/config/rs6000/rs6000.c +++ gcc-4_8-test/gcc/config/rs6000/rs6000.c @@ -970,6 +970,7 @@ struct processor_costs ppca2_cost = { #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_E +#undef RS6000_BUILTIN_H #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_Q #undef RS6000_BUILTIN_S @@ -993,6 +994,9 @@ struct processor_costs ppca2_cost = { #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) \ { NAME, ICODE, MASK, ATTR }, +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) \ + { NAME, ICODE, MASK, ATTR }, + #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) \ { NAME, ICODE, MASK, ATTR }, @@ -1023,6 +1027,7 @@ static const struct rs6000_builtin_info_ #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_E +#undef RS6000_BUILTIN_H #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_Q #undef RS6000_BUILTIN_S @@ -1063,6 +1068,7 @@ static void rs6000_common_init_builtins static void paired_init_builtins (void); static rtx paired_expand_predicate_builtin (enum insn_code, tree, rtx); static void spe_init_builtins (void); +static void htm_init_builtins (void); static rtx spe_expand_predicate_builtin (enum insn_code, tree, rtx); static rtx spe_expand_evsel_builtin (enum insn_code, tree, rtx); static int rs6000_emit_int_cmove (rtx, rtx, rtx, rtx); @@ -1190,7 +1196,9 @@ char rs6000_reg_names[][8] = /* SPE registers. */ "spe_acc", "spefscr", /* Soft frame pointer. */ - "sfp" + "sfp", + /* HTM SPR registers. */ + "tfhar", "tfiar", "texasr" }; #ifdef TARGET_REGNAMES @@ -1216,7 +1224,9 @@ static const char alt_reg_names[][8] = /* SPE registers. */ "spe_acc", "spefscr", /* Soft frame pointer. */ - "sfp" + "sfp", + /* HTM SPR registers. */ + "tfhar", "tfiar", "texasr" }; #endif @@ -2396,6 +2406,9 @@ rs6000_init_hard_regno_mode_ok (bool glo rs6000_regno_regclass[VSCR_REGNO] = VRSAVE_REGS; rs6000_regno_regclass[SPE_ACC_REGNO] = SPE_ACC_REGS; rs6000_regno_regclass[SPEFSCR_REGNO] = SPEFSCR_REGS; + rs6000_regno_regclass[TFHAR_REGNO] = SPR_REGS; + rs6000_regno_regclass[TFIAR_REGNO] = SPR_REGS; + rs6000_regno_regclass[TEXASR_REGNO] = SPR_REGS; rs6000_regno_regclass[ARG_POINTER_REGNUM] = BASE_REGS; rs6000_regno_regclass[FRAME_POINTER_REGNUM] = BASE_REGS; @@ -2954,7 +2967,8 @@ rs6000_builtin_mask_calculate (void) | ((TARGET_POPCNTD) ? RS6000_BTM_POPCNTD : 0) | ((rs6000_cpu == PROCESSOR_CELL) ? RS6000_BTM_CELL : 0) | ((TARGET_P8_VECTOR) ? RS6000_BTM_P8_VECTOR : 0) - | ((TARGET_CRYPTO) ? RS6000_BTM_CRYPTO : 0)); + | ((TARGET_CRYPTO) ? RS6000_BTM_CRYPTO : 0) + | ((TARGET_HTM) ? RS6000_BTM_HTM : 0)); } /* Override command line options. Mostly we process the processor type and @@ -10394,6 +10408,7 @@ def_builtin (const char *name, tree type #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_E +#undef RS6000_BUILTIN_H #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_Q #undef RS6000_BUILTIN_S @@ -10407,6 +10422,7 @@ def_builtin (const char *name, tree type #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE) @@ -10425,6 +10441,7 @@ static const struct builtin_description #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_E +#undef RS6000_BUILTIN_H #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_Q #undef RS6000_BUILTIN_S @@ -10438,6 +10455,7 @@ static const struct builtin_description { MASK, ICODE, NAME, ENUM }, #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE) @@ -10456,6 +10474,7 @@ static const struct builtin_description #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_E +#undef RS6000_BUILTIN_H #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_Q #undef RS6000_BUILTIN_S @@ -10469,6 +10488,7 @@ static const struct builtin_description #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE) @@ -10485,6 +10505,7 @@ static const struct builtin_description #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_E +#undef RS6000_BUILTIN_H #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_Q #undef RS6000_BUILTIN_S @@ -10496,6 +10517,7 @@ static const struct builtin_description #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) \ { MASK, ICODE, NAME, ENUM }, @@ -10517,6 +10539,7 @@ static const struct builtin_description #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_E +#undef RS6000_BUILTIN_H #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_Q #undef RS6000_BUILTIN_S @@ -10528,6 +10551,7 @@ static const struct builtin_description #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE) \ @@ -10547,6 +10571,7 @@ static const struct builtin_description #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_E +#undef RS6000_BUILTIN_H #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_Q #undef RS6000_BUILTIN_S @@ -10560,6 +10585,7 @@ static const struct builtin_description #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) \ { MASK, ICODE, NAME, ENUM }, +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE) @@ -10577,6 +10603,7 @@ static const struct builtin_description #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_E +#undef RS6000_BUILTIN_H #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_Q #undef RS6000_BUILTIN_S @@ -10588,6 +10615,7 @@ static const struct builtin_description #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) \ { MASK, ICODE, NAME, ENUM }, @@ -10608,6 +10636,7 @@ static const struct builtin_description #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_E +#undef RS6000_BUILTIN_H #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_Q #undef RS6000_BUILTIN_S @@ -10621,6 +10650,7 @@ static const struct builtin_description #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE) @@ -10638,8 +10668,9 @@ static const struct builtin_description #undef RS6000_BUILTIN_2 #undef RS6000_BUILTIN_3 #undef RS6000_BUILTIN_A -#undef RS6000_BUILTIN_E #undef RS6000_BUILTIN_D +#undef RS6000_BUILTIN_E +#undef RS6000_BUILTIN_H #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_Q #undef RS6000_BUILTIN_S @@ -10653,6 +10684,7 @@ static const struct builtin_description #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE) @@ -10663,17 +10695,49 @@ static const struct builtin_description #include "rs6000-builtin.def" }; +/* HTM builtins. */ #undef RS6000_BUILTIN_1 #undef RS6000_BUILTIN_2 #undef RS6000_BUILTIN_3 #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_E +#undef RS6000_BUILTIN_H #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_Q #undef RS6000_BUILTIN_S #undef RS6000_BUILTIN_X +#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) \ + { MASK, ICODE, NAME, ENUM }, + +#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) + +static const struct builtin_description bdesc_htm[] = +{ +#include "rs6000-builtin.def" +}; + +#undef RS6000_BUILTIN_1 +#undef RS6000_BUILTIN_2 +#undef RS6000_BUILTIN_3 +#undef RS6000_BUILTIN_A +#undef RS6000_BUILTIN_D +#undef RS6000_BUILTIN_E +#undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_P +#undef RS6000_BUILTIN_Q +#undef RS6000_BUILTIN_S + /* Return true if a builtin function is overloaded. */ bool rs6000_overloaded_builtin_p (enum rs6000_builtins fncode) @@ -11143,6 +11207,197 @@ altivec_expand_stv_builtin (enum insn_co return NULL_RTX; } +/* Return the appropriate SPR number associated with the given builtin. */ +static inline HOST_WIDE_INT +htm_spr_num (enum rs6000_builtins code) +{ + if (code == HTM_BUILTIN_GET_TFHAR + || code == HTM_BUILTIN_SET_TFHAR) + return TFHAR_SPR; + else if (code == HTM_BUILTIN_GET_TFIAR + || code == HTM_BUILTIN_SET_TFIAR) + return TFIAR_SPR; + else if (code == HTM_BUILTIN_GET_TEXASR + || code == HTM_BUILTIN_SET_TEXASR) + return TEXASR_SPR; + gcc_assert (code == HTM_BUILTIN_GET_TEXASRU + || code == HTM_BUILTIN_SET_TEXASRU); + return TEXASRU_SPR; +} + +/* Return the appropriate SPR regno associated with the given builtin. */ +static inline HOST_WIDE_INT +htm_spr_regno (enum rs6000_builtins code) +{ + if (code == HTM_BUILTIN_GET_TFHAR + || code == HTM_BUILTIN_SET_TFHAR) + return TFHAR_REGNO; + else if (code == HTM_BUILTIN_GET_TFIAR + || code == HTM_BUILTIN_SET_TFIAR) + return TFIAR_REGNO; + gcc_assert (code == HTM_BUILTIN_GET_TEXASR + || code == HTM_BUILTIN_SET_TEXASR + || code == HTM_BUILTIN_GET_TEXASRU + || code == HTM_BUILTIN_SET_TEXASRU); + return TEXASR_REGNO; +} + +/* Return the correct ICODE value depending on whether we are + setting or reading the HTM SPRs. */ +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; + else + return (TARGET_64BIT) ? CODE_FOR_htm_mtspr_di : CODE_FOR_htm_mtspr_si; +} + +/* Expand the HTM builtin in EXP and store the result in TARGET. + Store true in *EXPANDEDP if we found a builtin to expand. */ +static rtx +htm_expand_builtin (tree exp, rtx target, bool * expandedp) +{ + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); + bool nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node; + enum rs6000_builtins fcode = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl); + const struct builtin_description *d; + size_t i; + + *expandedp = false; + + /* Expand the HTM builtins. */ + d = bdesc_htm; + for (i = 0; i < ARRAY_SIZE (bdesc_htm); i++, d++) + if (d->code == fcode) + { + rtx op[MAX_HTM_OPERANDS], pat; + int nopnds = 0; + tree arg; + call_expr_arg_iterator iter; + unsigned attr = rs6000_builtin_info[fcode].attr; + enum insn_code icode = d->icode; + + if (attr & RS6000_BTC_SPR) + icode = rs6000_htm_spr_icode (nonvoid); + + if (nonvoid) + { + enum machine_mode tmode = insn_data[icode].operand[0].mode; + if (!target + || GET_MODE (target) != tmode + || !(*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + 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; + + insn_op = &insn_data[icode].operand[nopnds]; + + op[nopnds] = expand_normal (arg); + + if (!(*insn_op->predicate) (op[nopnds], insn_op->mode)) + { + if (!strcmp (insn_op->constraint, "n")) + { + int arg_num = (nonvoid) ? nopnds : nopnds + 1; + if (!CONST_INT_P (op[nopnds])) + error ("argument %d must be an unsigned literal", arg_num); + else + error ("argument %d is an unsigned literal that is " + "out of range", arg_num); + return const0_rtx; + } + op[nopnds] = copy_to_mode_reg (insn_op->mode, op[nopnds]); + } + + nopnds++; + } + + /* Handle the builtins for extended mnemonics. These accept + no arguments, but map to builtins that take arguments. */ + switch (fcode) + { + case HTM_BUILTIN_TENDALL: /* Alias for: tend. 1 */ + case HTM_BUILTIN_TRESUME: /* Alias for: tsr. 1 */ + op[nopnds++] = GEN_INT (1); +#ifdef ENABLE_CHECKING + attr |= RS6000_BTC_UNARY; +#endif + break; + case HTM_BUILTIN_TSUSPEND: /* Alias for: tsr. 0 */ + op[nopnds++] = GEN_INT (0); +#ifdef ENABLE_CHECKING + attr |= RS6000_BTC_UNARY; +#endif + break; + default: + break; + } + + /* 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) + { + op[nopnds++] = gen_rtx_CONST_INT (Pmode, htm_spr_num (fcode)); + op[nopnds++] = gen_rtx_REG (Pmode, htm_spr_regno (fcode)); + } + +#ifdef ENABLE_CHECKING + int expected_nopnds = 0; + if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_UNARY) + expected_nopnds = 1; + else if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_BINARY) + expected_nopnds = 2; + else if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_TERNARY) + expected_nopnds = 3; + if (!(attr & RS6000_BTC_VOID)) + expected_nopnds += 1; + if (attr & RS6000_BTC_SPR) + expected_nopnds += 2; + + gcc_assert (nopnds == expected_nopnds && nopnds <= MAX_HTM_OPERANDS); +#endif + + switch (nopnds) + { + case 0: + pat = GEN_FCN (icode) (NULL_RTX); + break; + case 1: + pat = GEN_FCN (icode) (op[0]); + break; + case 2: + pat = GEN_FCN (icode) (op[0], op[1]); + break; + case 3: + pat = GEN_FCN (icode) (op[0], op[1], op[2]); + break; + case 4: + pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]); + break; + default: + gcc_unreachable (); + } + if (!pat) + return NULL_RTX; + emit_insn (pat); + + *expandedp = true; + if (nonvoid) + return target; + return const0_rtx; + } + + return NULL_RTX; +} + static rtx rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target) { @@ -12224,6 +12479,8 @@ rs6000_invalid_builtin (enum rs6000_buil error ("Builtin function %s is only valid for the cell processor", name); else if ((fnmask & RS6000_BTM_VSX) != 0) error ("Builtin function %s requires the -mvsx option", name); + else if ((fnmask & RS6000_BTM_HTM) != 0) + error ("Builtin function %s requires the -mhtm option", name); else if ((fnmask & RS6000_BTM_ALTIVEC) != 0) error ("Builtin function %s requires the -maltivec option", name); else if ((fnmask & RS6000_BTM_PAIRED) != 0) @@ -12403,6 +12660,13 @@ rs6000_expand_builtin (tree exp, rtx tar if (success) return ret; } + if (TARGET_HTM) + { + ret = htm_expand_builtin (exp, target, &success); + + if (success) + return ret; + } gcc_assert (TARGET_ALTIVEC || TARGET_VSX || TARGET_SPE || TARGET_PAIRED_FLOAT); @@ -12585,6 +12849,9 @@ rs6000_init_builtins (void) spe_init_builtins (); if (TARGET_EXTRA_BUILTINS) altivec_init_builtins (); + if (TARGET_HTM) + htm_init_builtins (); + if (TARGET_EXTRA_BUILTINS || TARGET_SPE || TARGET_PAIRED_FLOAT) rs6000_common_init_builtins (); @@ -13324,6 +13591,79 @@ altivec_init_builtins (void) def_builtin ("__builtin_vec_ext_v2di", ftype, VSX_BUILTIN_VEC_EXT_V2DI); } +static void +htm_init_builtins (void) +{ + HOST_WIDE_INT builtin_mask = rs6000_builtin_mask; + const struct builtin_description *d; + size_t i; + + d = bdesc_htm; + for (i = 0; i < ARRAY_SIZE (bdesc_htm); i++, d++) + { + tree op[MAX_HTM_OPERANDS], type; + HOST_WIDE_INT mask = d->mask; + unsigned attr = rs6000_builtin_info[d->code].attr; + 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; + + if ((mask & builtin_mask) != mask) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "htm_builtin, skip binary %s\n", d->name); + continue; + } + + if (d->name == 0) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "htm_builtin, bdesc_htm[%ld] no name\n", + (long unsigned) i); + continue; + } + + op[nopnds++] = (void_func) ? void_type_node : argtype; + + if (attr_args == RS6000_BTC_UNARY) + op[nopnds++] = argtype; + else if (attr_args == RS6000_BTC_BINARY) + { + op[nopnds++] = argtype; + op[nopnds++] = argtype; + } + else if (attr_args == RS6000_BTC_TERNARY) + { + op[nopnds++] = argtype; + op[nopnds++] = argtype; + op[nopnds++] = argtype; + } + + switch (nopnds) + { + case 1: + type = build_function_type_list (op[0], NULL_TREE); + break; + case 2: + type = build_function_type_list (op[0], op[1], NULL_TREE); + break; + case 3: + type = build_function_type_list (op[0], op[1], op[2], NULL_TREE); + break; + case 4: + type = build_function_type_list (op[0], op[1], op[2], op[3], + NULL_TREE); + break; + default: + gcc_unreachable (); + } + + def_builtin (d->name, type, d->code); + } +} + /* Hash function for builtin functions with up to 3 arguments and a return type. */ static unsigned @@ -29201,6 +29541,7 @@ static struct rs6000_opt_mask const rs60 { "dlmzb", OPTION_MASK_DLMZB, false, true }, { "fprnd", OPTION_MASK_FPRND, false, true }, { "hard-dfp", OPTION_MASK_DFP, false, true }, + { "htm", OPTION_MASK_HTM, false, true }, { "isel", OPTION_MASK_ISEL, false, true }, { "mfcrf", OPTION_MASK_MFCRF, false, true }, { "mfpgpr", OPTION_MASK_MFPGPR, false, true }, @@ -29262,6 +29603,7 @@ static struct rs6000_opt_mask const rs60 { "cell", RS6000_BTM_CELL, false, false }, { "power8-vector", RS6000_BTM_P8_VECTOR, false, false }, { "crypto", RS6000_BTM_CRYPTO, false, false }, + { "htm", RS6000_BTM_HTM, false, false }, }; /* Option variables that we want to support inside attribute((target)) and Index: gcc-4_8-test/gcc/config/rs6000/rs6000.h =================================================================== --- gcc-4_8-test.orig/gcc/config/rs6000/rs6000.h +++ gcc-4_8-test/gcc/config/rs6000/rs6000.h @@ -164,7 +164,7 @@ %{mcpu=e6500: -me6500} \ %{maltivec: -maltivec} \ %{mvsx: -mvsx %{!maltivec: -maltivec} %{!mcpu*: %(asm_cpu_power7)}} \ -%{mpower8-vector|mcrypto|mdirect-move: %{!mcpu*: %(asm_cpu_power8)}} \ +%{mpower8-vector|mcrypto|mdirect-move|mhtm: %{!mcpu*: %(asm_cpu_power8)}} \ -many" #define CPP_DEFAULT_SPEC "" @@ -285,9 +285,11 @@ extern const char *host_detect_local_cpu #ifndef HAVE_AS_POWER8 #undef TARGET_DIRECT_MOVE #undef TARGET_CRYPTO +#undef TARGET_HTM #undef TARGET_P8_VECTOR #define TARGET_DIRECT_MOVE 0 #define TARGET_CRYPTO 0 +#define TARGET_HTM 0 #define TARGET_P8_VECTOR 0 #endif @@ -543,6 +545,7 @@ extern int rs6000_vector_align[]; #define MASK_FPRND OPTION_MASK_FPRND #define MASK_P8_FUSION OPTION_MASK_P8_FUSION #define MASK_HARD_FLOAT OPTION_MASK_HARD_FLOAT +#define MASK_HTM OPTION_MASK_HTM #define MASK_ISEL OPTION_MASK_ISEL #define MASK_MFCRF OPTION_MASK_MFCRF #define MASK_MFPGPR OPTION_MASK_MFPGPR @@ -917,15 +920,17 @@ extern unsigned rs6000_pointer_size; in inline functions. Another pseudo (not included in DWARF_FRAME_REGISTERS) is soft frame - pointer, which is eventually eliminated in favor of SP or FP. */ + pointer, which is eventually eliminated in favor of SP or FP. -#define FIRST_PSEUDO_REGISTER 114 + The 3 HTM registers aren't also included in DWARF_FRAME_REGISTERS. */ + +#define FIRST_PSEUDO_REGISTER 117 /* This must be included for pre gcc 3.0 glibc compatibility. */ #define PRE_GCC3_DWARF_FRAME_REGISTERS 77 /* Add 32 dwarf columns for synthetic SPE registers. */ -#define DWARF_FRAME_REGISTERS ((FIRST_PSEUDO_REGISTER - 1) + 32) +#define DWARF_FRAME_REGISTERS ((FIRST_PSEUDO_REGISTER - 4) + 32) /* The SPE has an additional 32 synthetic registers, with DWARF debug info numbering for these registers starting at 1200. While eh_frame @@ -941,7 +946,7 @@ extern unsigned rs6000_pointer_size; We must map them here to avoid huge unwinder tables mostly consisting of unused space. */ #define DWARF_REG_TO_UNWIND_COLUMN(r) \ - ((r) > 1200 ? ((r) - 1200 + FIRST_PSEUDO_REGISTER - 1) : (r)) + ((r) > 1200 ? ((r) - 1200 + (DWARF_FRAME_REGISTERS - 32)) : (r)) /* Use standard DWARF numbering for DWARF debugging information. */ #define DBX_REGISTER_NUMBER(REGNO) rs6000_dbx_register_number (REGNO) @@ -981,7 +986,7 @@ extern unsigned rs6000_pointer_size; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 1, 1 \ - , 1, 1, 1 \ + , 1, 1, 1, 1, 1, 1 \ } /* 1 for registers not available across function calls. @@ -1001,7 +1006,7 @@ extern unsigned rs6000_pointer_size; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 1, 1 \ - , 1, 1, 1 \ + , 1, 1, 1, 1, 1, 1 \ } /* Like `CALL_USED_REGISTERS' except this macro doesn't require that @@ -1020,7 +1025,7 @@ extern unsigned rs6000_pointer_size; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0 \ - , 0, 0, 0 \ + , 0, 0, 0, 0, 0, 0 \ } #define TOTAL_ALTIVEC_REGS (LAST_ALTIVEC_REGNO - FIRST_ALTIVEC_REGNO + 1) @@ -1059,6 +1064,9 @@ extern unsigned rs6000_pointer_size; vrsave, vscr (fixed) spe_acc, spefscr (fixed) sfp (fixed) + tfhar (fixed) + tfiar (fixed) + texasr (fixed) */ #if FIXED_R2 == 1 @@ -1100,7 +1108,7 @@ extern unsigned rs6000_pointer_size; 96, 95, 94, 93, 92, 91, \ 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, \ 109, 110, \ - 111, 112, 113 \ + 111, 112, 113, 114, 115, 116 \ } /* True if register is floating-point. */ @@ -1324,6 +1332,7 @@ enum reg_class VSCR_REGS, SPE_ACC_REGS, SPEFSCR_REGS, + SPR_REGS, NON_SPECIAL_REGS, LINK_REGS, CTR_REGS, @@ -1354,6 +1363,7 @@ enum reg_class "VSCR_REGS", \ "SPE_ACC_REGS", \ "SPEFSCR_REGS", \ + "SPR_REGS", \ "NON_SPECIAL_REGS", \ "LINK_REGS", \ "CTR_REGS", \ @@ -1383,6 +1393,7 @@ enum reg_class { 0x00000000, 0x00000000, 0x00000000, 0x00004000 }, /* VSCR_REGS */ \ { 0x00000000, 0x00000000, 0x00000000, 0x00008000 }, /* SPE_ACC_REGS */ \ { 0x00000000, 0x00000000, 0x00000000, 0x00010000 }, /* SPEFSCR_REGS */ \ + { 0x00000000, 0x00000000, 0x00000000, 0x00040000 }, /* SPR_REGS */ \ { 0xffffffff, 0xffffffff, 0x00000008, 0x00020000 }, /* NON_SPECIAL_REGS */ \ { 0x00000000, 0x00000000, 0x00000002, 0x00000000 }, /* LINK_REGS */ \ { 0x00000000, 0x00000000, 0x00000004, 0x00000000 }, /* CTR_REGS */ \ @@ -1393,7 +1404,7 @@ enum reg_class { 0x00000000, 0x00000000, 0x00000ff0, 0x00000000 }, /* CR_REGS */ \ { 0xffffffff, 0x00000000, 0x00000ffe, 0x00020000 }, /* NON_FLOAT_REGS */ \ { 0x00000000, 0x00000000, 0x00001000, 0x00000000 }, /* CA_REGS */ \ - { 0xffffffff, 0xffffffff, 0xfffffffe, 0x0003ffff } /* ALL_REGS */ \ + { 0xffffffff, 0xffffffff, 0xfffffffe, 0x0007ffff } /* ALL_REGS */ \ } /* The same information, inverted: @@ -2310,6 +2321,9 @@ extern char rs6000_reg_names[][8]; /* re &rs6000_reg_names[111][0], /* spe_acc */ \ &rs6000_reg_names[112][0], /* spefscr */ \ &rs6000_reg_names[113][0], /* sfp */ \ + &rs6000_reg_names[114][0], /* tfhar */ \ + &rs6000_reg_names[115][0], /* tfiar */ \ + &rs6000_reg_names[116][0], /* texasr */ \ } /* Table of additional register names to use in user input. */ @@ -2363,7 +2377,9 @@ extern char rs6000_reg_names[][8]; /* re {"vs48", 93}, {"vs49", 94}, {"vs50", 95}, {"vs51", 96}, \ {"vs52", 97}, {"vs53", 98}, {"vs54", 99}, {"vs55", 100}, \ {"vs56", 101},{"vs57", 102},{"vs58", 103},{"vs59", 104}, \ - {"vs60", 105},{"vs61", 106},{"vs62", 107},{"vs63", 108} } + {"vs60", 105},{"vs61", 106},{"vs62", 107},{"vs63", 108}, \ + /* Transactional Memory Facility (HTM) Registers. */ \ + {"tfhar", 114}, {"tfiar", 115}, {"texasr", 116} } /* This is how to output an element of a case-vector that is relative. */ @@ -2452,7 +2468,12 @@ extern int frame_pointer_needed; #define RS6000_BTC_ATTR_MASK 0x00000700 /* Mask of the attributes. */ /* Miscellaneous information. */ -#define RS6000_BTC_OVERLOADED 0x4000000 /* function is overloaded. */ +#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_MISC_MASK 0x1f000000 /* Mask of the misc info. */ /* Convenience macros to document the instruction type. */ #define RS6000_BTC_MEM RS6000_BTC_MISC /* load/store touches mem. */ @@ -2466,6 +2487,7 @@ extern int frame_pointer_needed; #define RS6000_BTM_VSX MASK_VSX /* VSX (vector/scalar). */ #define RS6000_BTM_P8_VECTOR MASK_P8_VECTOR /* ISA 2.07 vector. */ #define RS6000_BTM_CRYPTO MASK_CRYPTO /* crypto funcs. */ +#define RS6000_BTM_HTM MASK_HTM /* hardware TM funcs. */ #define RS6000_BTM_SPE MASK_STRING /* E500 */ #define RS6000_BTM_PAIRED MASK_MULHW /* 750CL paired insns. */ #define RS6000_BTM_FRE MASK_POPCNTB /* FRE instruction. */ @@ -2483,6 +2505,7 @@ extern int frame_pointer_needed; | RS6000_BTM_FRES \ | RS6000_BTM_FRSQRTE \ | RS6000_BTM_FRSQRTES \ + | RS6000_BTM_HTM \ | RS6000_BTM_POPCNTD \ | RS6000_BTM_CELL) @@ -2494,6 +2517,7 @@ extern int frame_pointer_needed; #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_E +#undef RS6000_BUILTIN_H #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_Q #undef RS6000_BUILTIN_S @@ -2505,6 +2529,7 @@ extern int frame_pointer_needed; #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) ENUM, #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) ENUM, #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) ENUM, +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) ENUM, #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) ENUM, #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) ENUM, #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE) ENUM, @@ -2523,6 +2548,7 @@ enum rs6000_builtins #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_E +#undef RS6000_BUILTIN_H #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_Q #undef RS6000_BUILTIN_S Index: gcc-4_8-test/gcc/config/rs6000/rs6000.md =================================================================== --- gcc-4_8-test.orig/gcc/config/rs6000/rs6000.md +++ gcc-4_8-test/gcc/config/rs6000/rs6000.md @@ -53,6 +53,9 @@ (SPE_ACC_REGNO 111) (SPEFSCR_REGNO 112) (FRAME_POINTER_REGNUM 113) + (TFHAR_REGNO 114) + (TFIAR_REGNO 115) + (TEXASR_REGNO 116) ; ABI defined stack offsets for storing the TOC pointer with AIX calls. (TOC_SAVE_OFFSET_32BIT 20) @@ -152,7 +155,7 @@ ;; Define an insn type attribute. This is used in function unit delay ;; computations. -(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,vecdouble,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel,popcnt,crypto" +(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,vecdouble,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel,popcnt,crypto,htm" (const_string "integer")) ;; Define floating point instruction sub-types for use with Xfpu.md @@ -15145,3 +15148,4 @@ (include "dfp.md") (include "paired.md") (include "crypto.md") +(include "htm.md") Index: gcc-4_8-test/gcc/config/rs6000/rs6000.opt =================================================================== --- gcc-4_8-test.orig/gcc/config/rs6000/rs6000.opt +++ gcc-4_8-test/gcc/config/rs6000/rs6000.opt @@ -542,6 +542,10 @@ mdirect-move Target Report Mask(DIRECT_MOVE) Var(rs6000_isa_flags) Use ISA 2.07 direct move between GPR & VSX register instructions +mhtm +Target Report Mask(HTM) Var(rs6000_isa_flags) +Use ISA 2.07 transactional memory (HTM) instructions + mquad-memory Target Report Mask(QUAD_MEMORY) Var(rs6000_isa_flags) Generate the quad word memory instructions (lq/stq/lqarx/stqcx). Index: gcc-4_8-test/gcc/config/rs6000/t-rs6000 =================================================================== --- gcc-4_8-test.orig/gcc/config/rs6000/t-rs6000 +++ gcc-4_8-test/gcc/config/rs6000/t-rs6000 @@ -72,6 +72,7 @@ MD_INCLUDES = $(srcdir)/config/rs6000/rs $(srcdir)/config/rs6000/vsx.md \ $(srcdir)/config/rs6000/altivec.md \ $(srcdir)/config/rs6000/crypto.md \ + $(srcdir)/config/rs6000/htm.md \ $(srcdir)/config/rs6000/spe.md \ $(srcdir)/config/rs6000/dfp.md \ $(srcdir)/config/rs6000/paired.md Index: gcc-4_8-test/gcc/testsuite/gcc.target/powerpc/htm-builtin-1.c =================================================================== --- /dev/null +++ gcc-4_8-test/gcc/testsuite/gcc.target/powerpc/htm-builtin-1.c @@ -0,0 +1,51 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_htm_ok } */ +/* { dg-options "-O2 -mhtm" } */ + +/* { 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 "tabortwc\\." 1 } } */ +/* { dg-final { scan-assembler-times "tabortwci\\." 2 } } */ +/* { dg-final { scan-assembler-times "tcheck\\." 1 } } */ +/* { dg-final { scan-assembler-times "trechkpt\\." 1 } } */ +/* { dg-final { scan-assembler-times "treclaim\\." 1 } } */ +/* { dg-final { scan-assembler-times "tsr\\." 3 } } */ +/* { dg-final { scan-assembler-times "mfspr" 4 } } */ +/* { dg-final { scan-assembler-times "mtspr" 4 } } */ + +void use_builtins (long *p, char code, long *a, long *b) +{ + p[0] = __builtin_tbegin (0); + p[1] = __builtin_tend (0); + p[2] = __builtin_tendall (); + p[3] = __builtin_tabort (0); + p[4] = __builtin_tabort (code); + + p[5] = __builtin_tabortdc (0xf, a[5], b[5]); + p[6] = __builtin_tabortdci (0xf, a[6], 13); + p[7] = __builtin_tabortwc (0xf, a[7], b[7]); + p[8] = __builtin_tabortwci (0xf, a[8], 13); + + p[9] = __builtin_tcheck (5); + p[10] = __builtin_trechkpt (); + p[11] = __builtin_treclaim (0); + p[12] = __builtin_tresume (); + p[13] = __builtin_tsuspend (); + p[14] = __builtin_tsr (0); + p[15] = __builtin_ttest (); /* This expands to a tabortwci. */ + + + p[16] = __builtin_get_texasr (); + p[17] = __builtin_get_texasru (); + p[18] = __builtin_get_tfhar (); + p[19] = __builtin_get_tfiar (); + + __builtin_set_texasr (a[20]); + __builtin_set_texasru (a[21]); + __builtin_set_tfhar (a[22]); + __builtin_set_tfiar (a[23]); +} Index: gcc-4_8-test/gcc/testsuite/gcc.target/powerpc/htm-xl-intrin-1.c =================================================================== --- /dev/null +++ gcc-4_8-test/gcc/testsuite/gcc.target/powerpc/htm-xl-intrin-1.c @@ -0,0 +1,32 @@ +/* This checks the availability of the XL compiler intrinsics for + transactional execution with the expected prototypes. */ + +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_htm_ok } */ +/* { dg-options "-O2 -mhtm" } */ + +#include + +void +foo (void *TM_buff, long *result, unsigned char *code) +{ + *result++ = __TM_simple_begin (); + *result++ = __TM_begin (TM_buff); + *result++ = __TM_end (); + __TM_abort (); + __TM_named_abort (*code); + __TM_resume (); + __TM_suspend (); + *result++ = __TM_is_user_abort (TM_buff); + *result++ = __TM_is_named_user_abort (TM_buff, code); + *result++ = __TM_is_illegal (TM_buff); + *result++ = __TM_is_footprint_exceeded (TM_buff); + *result++ = __TM_nesting_depth (TM_buff); + *result++ = __TM_is_nested_too_deep (TM_buff); + *result++ = __TM_is_conflict (TM_buff); + *result++ = __TM_is_failure_persistent (TM_buff); + *result++ = __TM_failure_address (TM_buff); + *result++ = __TM_failure_code (TM_buff); +} + Index: gcc-4_8-test/gcc/testsuite/lib/target-supports.exp =================================================================== --- gcc-4_8-test.orig/gcc/testsuite/lib/target-supports.exp +++ gcc-4_8-test/gcc/testsuite/lib/target-supports.exp @@ -2752,6 +2752,27 @@ proc check_effective_target_powerpc_vsx_ } } +# Return 1 if this is a PowerPC target supporting -mhtm + +proc check_effective_target_powerpc_htm_ok { } { + if { ([istarget powerpc*-*-*] + && ![istarget powerpc-*-linux*paired*]) + || [istarget rs6000-*-*] } { + # HTM is not supported on AIX yet. + if { [istarget powerpc*-*-aix*] } { + return 0 + } + return [check_no_compiler_messages powerpc_htm_ok object { + int main (void) { + asm volatile ("tbegin. 0"); + return 0; + } + } "-mhtm"] + } else { + return 0 + } +} + # Return 1 if this is a PowerPC target supporting -mcpu=cell. proc check_effective_target_powerpc_ppu_ok { } { Index: gcc-4_8-test/libitm/config/powerpc/target.h =================================================================== --- gcc-4_8-test.orig/libitm/config/powerpc/target.h +++ gcc-4_8-test/libitm/config/powerpc/target.h @@ -22,6 +22,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ +#ifdef HAVE_SYS_AUXV_H +#include +#endif + namespace GTM HIDDEN { typedef int v128 __attribute__((vector_size(16), may_alias, aligned(16))); @@ -55,4 +59,82 @@ cpu_relax (void) __asm volatile ("" : : : "memory"); } +// Use HTM if it is supported by the system. +// See gtm_thread::begin_transaction for how these functions are used. +#if defined (__linux__) \ + && defined (HAVE_AS_HTM) \ + && defined (HAVE_GETAUXVAL) \ + && defined (AT_HWCAP2) \ + && defined (PPC_FEATURE2_HAS_HTM) + +#include + +#define USE_HTM_FASTPATH + +#define _TBEGIN_STARTED 0 +#define _TBEGIN_INDETERMINATE 1 +#define _TBEGIN_PERSISTENT 2 + +/* Number of retries for transient failures. */ +#define _HTM_RETRIES 10 + +static inline bool +htm_available (void) +{ + return (getauxval (AT_HWCAP2) & PPC_FEATURE2_HAS_HTM) ? true : false; +} + +static inline uint32_t +htm_init (void) +{ + // Maximum number of times we try to execute a transaction + // as a HW transaction. + return htm_available () ? _HTM_RETRIES : 0; +} + +static inline uint32_t +htm_begin (void) +{ + if (__builtin_expect (__builtin_tbegin (0), 1)) + return _TBEGIN_STARTED; + + if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ())) + return _TBEGIN_PERSISTENT; + + return _TBEGIN_INDETERMINATE; +} + +static inline bool +htm_begin_success (uint32_t begin_ret) +{ + return begin_ret == _TBEGIN_STARTED; +} + +static inline void +htm_commit (void) +{ + __builtin_tend (0); +} + +static inline void +htm_abort (void) +{ + __builtin_tabort (0); +} + +static inline bool +htm_abort_should_retry (uint32_t begin_ret) +{ + return begin_ret != _TBEGIN_PERSISTENT; +} + +/* Returns true iff a hardware transaction is currently being executed. */ +static inline bool +htm_transaction_active (void) +{ + return (_HTM_STATE (__builtin_ttest ()) == _HTM_TRANSACTIONAL); +} + +#endif + } // namespace GTM Index: gcc-4_8-test/libitm/configure.tgt =================================================================== --- gcc-4_8-test.orig/libitm/configure.tgt +++ gcc-4_8-test/libitm/configure.tgt @@ -47,7 +47,10 @@ fi # work out any special compilation flags as necessary. case "${target_cpu}" in alpha*) ARCH=alpha ;; - rs6000 | powerpc*) ARCH=powerpc ;; + rs6000 | powerpc*) + XCFLAGS="${XCFLAGS} -mhtm" + ARCH=powerpc + ;; arm*) ARCH=arm ;; Index: gcc-4_8-test/gcc/config/rs6000/darwin.h =================================================================== --- gcc-4_8-test.orig/gcc/config/rs6000/darwin.h +++ gcc-4_8-test/gcc/config/rs6000/darwin.h @@ -205,7 +205,8 @@ extern int darwin_emit_branch_islands; "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", \ "vrsave", "vscr", \ "spe_acc", "spefscr", \ - "sfp" \ + "sfp", \ + "tfhar", "tfiar", "texasr" \ } /* This outputs NAME to FILE. */ Index: gcc-4_8-test/gcc/doc/extend.texi =================================================================== --- gcc-4_8-test.orig/gcc/doc/extend.texi +++ gcc-4_8-test/gcc/doc/extend.texi @@ -8804,6 +8804,7 @@ instructions, but allow the compiler to * picoChip Built-in Functions:: * PowerPC Built-in Functions:: * PowerPC AltiVec/VSX Built-in Functions:: +* PowerPC Hardware Transactional Memory Built-in Functions:: * RX Built-in Functions:: * S/390 System z Built-in Functions:: * SH Built-in Functions:: @@ -14266,6 +14267,196 @@ The second argument to the @var{__builti integer that is 0 or 1. The third argument to these builtin functions must be a constant integer in the range of 0 to 15. +@node PowerPC Hardware Transactional Memory Built-in Functions +@subsection PowerPC Hardware Transactional Memory Built-in Functions +GCC provides two interfaces for accessing the Hardware Transactional +Memory (HTM) instructions available on some of the PowerPC family +of prcoessors (eg, POWER8). The two interfaces come in a low level +interface, consisting of built-in functions specific to PowerPC and a +higher level interface consisting of inline functions that are common +between PowerPC and S/390. + +@subsubsection PowerPC HTM Low Level Built-in Functions + +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. + +@smallexample +unsigned int __builtin_tbegin (unsigned int) +unsigned int __builtin_tend (unsigned int) + +unsigned int __builtin_tabort (unsigned int) +unsigned int __builtin_tabortdc (unsigned int, unsigned int, unsigned int) +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_treclaim (unsigned int) +unsigned int __builtin_trechkpt (void) +unsigned int __builtin_tsr (unsigned int) +@end smallexample + +In addition to the above HTM built-ins, we have added built-ins for +some common extended mnemonics of the HTM instructions: + +@smallexample +unsigned int __builtin_tendall (void) +unsigned int __builtin_tresume (void) +unsigned int __builtin_tsuspend (void) +@end smallexample + +The following set of built-in functions are available to gain access +to the HTM specific special purpose registers. + +@smallexample +unsigned long __builtin_get_texasr (void) +unsigned long __builtin_get_texasru (void) +unsigned long __builtin_get_tfhar (void) +unsigned long __builtin_get_tfiar (void) + +void __builtin_set_texasr (unsigned long); +void __builtin_set_texasru (unsigned long); +void __builtin_set_tfhar (unsigned long); +void __builtin_set_tfiar (unsigned long); +@end smallexample + +Example usage of these low level built-in functions may look like: + +@smallexample +#include + +int num_retries = 10; + +while (1) + @{ + if (__builtin_tbegin (0)) + @{ + /* Transaction State Initiated. */ + if (is_locked (lock)) + __builtin_tabort (0); + ... transaction code... + __builtin_tend (0); + break; + @} + else + @{ + /* Transaction State Failed. Use locks if the transaction + failure is "persistent" or we've tried too many times. */ + if (num_retries-- <= 0 + || _TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ())) + @{ + acquire_lock (lock); + ... non transactional fallback path... + release_lock (lock); + break; + @} + @} + @} +@end smallexample + +One final built-in function has been added that returns the value of +the 2-bit Transaction State field of the Machine Status Register (MSR) +as stored in @code{CR0}. + +@smallexample +unsigned long __builtin_ttest (void) +@end smallexample + +This built-in can be used to determine the current transaction state +using the following code example: + +@smallexample +#include + +unsigned char tx_state = _HTM_STATE (__builtin_ttest ()); + +if (tx_state == _HTM_TRANSACTIONAL) + @{ + /* Code to use in transactional state. */ + @} +else if (tx_state == _HTM_NONTRANSACTIONAL) + @{ + /* Code to use in non-transactional state. */ + @} +else if (tx_state == _HTM_SUSPENDED) + @{ + /* Code to use in transaction suspended state. */ + @} +@end smallexample + +@subsubsection PowerPC HTM High Level Inline Functions + +The following high level HTM interface is made available by including +@code{} and using @option{-mhtm} or @option{-mcpu=CPU} +where CPU is `power8' or later. This interface is common between PowerPC +and S/390, allowing users to write one HTM source implementation that +can be compiled and executed on either system. + +@smallexample +long __TM_simple_begin (void) +long __TM_begin (void* const TM_buff) +long __TM_end (void) +void __TM_abort (void) +void __TM_named_abort (unsigned char const code) +void __TM_resume (void) +void __TM_suspend (void) + +long __TM_is_user_abort (void* const TM_buff) +long __TM_is_named_user_abort (void* const TM_buff, unsigned char *code) +long __TM_is_illegal (void* const TM_buff) +long __TM_is_footprint_exceeded (void* const TM_buff) +long __TM_nesting_depth (void* const TM_buff) +long __TM_is_nested_too_deep(void* const TM_buff) +long __TM_is_conflict(void* const TM_buff) +long __TM_is_failure_persistent(void* const TM_buff) +long __TM_failure_address(void* const TM_buff) +long long __TM_failure_code(void* const TM_buff) +@end smallexample + +Using these common set of HTM inline functions, we can create +a more portable version of the HTM example in the previous +section that will work on either PowerPC or S/390: + +@smallexample +#include + +int num_retries = 10; +TM_buff_type TM_buff; + +while (1) + @{ + if (__TM_begin (TM_buff)) + @{ + /* Transaction State Initiated. */ + if (is_locked (lock)) + __TM_abort (); + ... transaction code... + __TM_end (); + break; + @} + else + @{ + /* Transaction State Failed. Use locks if the transaction + failure is "persistent" or we've tried too many times. */ + if (num_retries-- <= 0 + || __TM_is_failure_persistent (TM_buff)) + @{ + acquire_lock (lock); + ... non transactional fallback path... + release_lock (lock); + break; + @} + @} + @} +@end smallexample + @node RX Built-in Functions @subsection RX Built-in Functions GCC supports some of the RX instructions which cannot be expressed in Index: gcc-4_8-test/libitm/acinclude.m4 =================================================================== --- gcc-4_8-test.orig/libitm/acinclude.m4 +++ gcc-4_8-test/libitm/acinclude.m4 @@ -134,6 +134,20 @@ s390*) ;; esac]) +dnl Check if as supports HTM instructions. +AC_DEFUN([LIBITM_CHECK_AS_HTM], [ +case "${target_cpu}" in +powerpc*) + AC_CACHE_CHECK([if the assembler supports HTM], libitm_cv_as_htm, [ + AC_TRY_COMPILE([], [asm("tbegin. 0; tend. 0");], + [libitm_cv_as_htm=yes], [libitm_cv_as_htm=no]) + ]) + if test x$libitm_cv_as_htm = xyes; then + AC_DEFINE(HAVE_AS_HTM, 1, [Define to 1 if the assembler supports HTM.]) + fi + ;; +esac]) + sinclude(../libtool.m4) dnl The lines below arrange for aclocal not to bring an installed dnl libtool.m4 into aclocal.m4, while still arranging for automake to Index: gcc-4_8-test/libitm/configure =================================================================== --- gcc-4_8-test.orig/libitm/configure +++ gcc-4_8-test/libitm/configure @@ -17401,6 +17401,43 @@ $as_echo "#define HAVE_AS_HTM 1" >>confd esac LIBITM_CHECK_AS_HTM +case "${target_cpu}" in +powerpc*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the assembler supports HTM" >&5 +$as_echo_n "checking if the assembler supports HTM... " >&6; } +if test "${libitm_cv_as_htm+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +asm("tbegin. 0; tend. 0"); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + libitm_cv_as_htm=yes +else + libitm_cv_as_htm=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libitm_cv_as_htm" >&5 +$as_echo "$libitm_cv_as_htm" >&6; } + if test x$libitm_cv_as_htm = xyes; then + +$as_echo "#define HAVE_AS_HTM 1" >>confdefs.h + + fi + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether weak refs work like ELF" >&5 $as_echo_n "checking whether weak refs work like ELF... " >&6; }