From patchwork Tue Feb 3 20:35:29 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleg Endo X-Patchwork-Id: 436023 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 F0B921401DE for ; Wed, 4 Feb 2015 07:37:03 +1100 (AEDT) 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:date:content-type:mime-version; q= dns; s=default; b=EITZhjWJ0RfSqe5QGhY1kH4z5jR0IYA8db4Raftq4P6pyW il7TiDQqdXqvlBjjyWLPV8hhoBGUja4KsaHPbPlbzsbiKqjVrxzdzvMof/LfwI+F 9Djo+uquTeu6ys/ox4vk8Etq3b++ed6N5rHm4IHm9x4ivaWmQ9/NU8Sh+c+14= 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:date:content-type:mime-version; s= default; bh=6Mu579GdVrOXhkgmtcpTV2p7bD4=; b=Q6x7FgG1iY9Ug2TPJ9rL f5SeJ8O4NhmD6i5FLZLVIrPWk6DsbLFdcaPyMLVwlG1hT0wOwa9LBxmzsrbgL0Sp k5qyGu3LSnP5QUqxGJZXoZ1CG2anvJax7eg90qzp4zj1rBHmsj0ARqR7ul/nbQ4E YuxUjwLUsaSgKgQpyDpnDGc= Received: (qmail 27786 invoked by alias); 3 Feb 2015 20:35:41 -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 27766 invoked by uid 89); 3 Feb 2015 20:35:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.4 required=5.0 tests=AWL, BAYES_50, RCVD_IN_DNSWL_NONE, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mailout10.t-online.de Received: from mailout10.t-online.de (HELO mailout10.t-online.de) (194.25.134.21) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Tue, 03 Feb 2015 20:35:37 +0000 Received: from fwd29.aul.t-online.de (fwd29.aul.t-online.de [172.20.26.134]) by mailout10.t-online.de (Postfix) with SMTP id 05AD02E54B5 for ; Tue, 3 Feb 2015 21:35:32 +0100 (CET) Received: from [192.168.0.105] (bRO7awZCghT6S1fN81TO3RnzmWGsWXPZrs-xpPVpYfsrxKFkXIyqFGZRs8L62MgQ4G@[84.180.120.77]) by fwd29.t-online.de with (TLSv1.2:ECDHE-RSA-AES256-SHA encrypted) esmtp id 1YIkC3-2ar3lw0; Tue, 3 Feb 2015 21:35:31 +0100 Message-ID: <1422995729.7441.35.camel@yam-132-YW-E178-FTW> Subject: [SH][committed] Use shorter atomic sequences if result values are unused From: Oleg Endo To: gcc-patches Date: Tue, 03 Feb 2015 21:35:29 +0100 Mime-Version: 1.0 X-IsSubscribed: yes Hi, When the result values of atomic ops, such as the previous value of an atomic_fetch_add, are unused, it's possible to use shorter asm sequences on SH. The attached patch does that by checking the reg unused notes of the insns in split1 and replacing them with the simpler variants, if the result value operand is unused. This patch introduces a problem where memory aliasing info is lost, because the mem operands are passed to the emitted insns not as such, but only as the register holding the address. This will be fixed with PR 64661. Committed as r220376. Tested with make -k check-gcc RUNTESTFLAGS="sh.exp --target_board=sh-sim \{-m2/-ml,-m2/-mb,-m2a/-mb,-m2e/-ml,-m2e/-mb,-m3/-ml,-m3/-mb,-m3e/-ml,-m3e/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}" to verify that the insns/splits actually work. Will observe daily sh4-linux test results for fallouts. Cheers, Oleg gcc/ChangeLog: PR target/64660 * config/sh/sync.md (atomic__hard, atomic_not_hard, atomic__soft_tcb, atomic_not_soft_tcb, atomic_nand_hard, atomic_nand_soft_tcb): New insns. (atomic_fetch_si_hard): Convert to insn_and_split. Split into atomic__fetchsi_hard if operands[0] is unused. (define_insn "atomic_fetch_notsi_hard): Convert to insn_and_split. Split into atomic_not_fetchsi_hard if operands[0] is unused. (atomic_fetch__hard): Convert to insn_and_split. Split into atomic__hard if operands[0] is unused. (atomic_fetch_not_hard): Convert to insn_and_split. Split into atomic_not_hard if operands[0] is unused. (atomic_fetch__soft_gusa): Convert to insn_and_split. Split into atomic__fetch_soft_gusa if operands[0] is unused. (atomic_fetch_not_soft_gusa): Convert to insn_and_split. Split into atomic_not_fetch_soft_gusa if operands[0] is unused. (atomic_fetch__soft_tcb): Convert to insn_and_split. Split into atomic__soft_tcb if operands[0] is unused. (atomic_fetch_not_soft_tcb): Convert to insn_and_split. Split into atomic_not_soft_tcb if operands[0] is unused. (atomic_fetch__soft_imask): Convert to insn_and_split. Split into atomic__fetch_soft_imask if operands[0] is unused. (atomic_fetch_not_soft_imask): Convert to insn_and_split. Split into atomic_not_fetch_soft_imask is operands[0] is unused. (atomic_fetch_nandsi_hard): Convert to insn_and_split. Split into atomic_nand_fetchsi_hard if operands[0] is unused. (atomic_fetch_nand_hard): Convert to insn_and_split. Split into atomic_nand_hard if operands[0] is unused. (atomic_fetch_nand_soft_gusa): Convert to insn_and_split. Split into atomic_nand_fetch_soft_gusa if operands[0] is unused. (atomic_fetch_nand_soft_tcb): Convert to insn_and_split. Split into atomic_nand_soft_tcb if operands[0] is unused. (atomic_fetch_nand_soft_imask): Convert to insn_and_split. Split into atomic_nand_fetch_soft_imask if operands[0] is unused. (atomic__fetch_hard): Convert to insn_and_split. Split into atomic__hard if operands[0] is unused. (atomic_not_fetch_hard): Convert to insn_and_split. Split into atomic_not_hard if operands[0] is unused. (atomic__fetch_soft_tcb): Convert to insn_and_split. Split into atomic__soft_tcb if operands[0] is unused. (atomic_not_fetch_soft_tcb): Convert to insn_and_split. Split into atomic_not_soft_tcb if operands[0] is unused. (atomic_nand_fetch_hard): Convert to insn_and_split. Split into atomic_nand_hard if operands[0] is unused. (atomic_nand_fetch_soft_tcb): Convert to insn_and_split. Split into atomic_nand_soft_tcb if operands[0] is unused. gcc/testsuite/ChangeLog: PR target/64660 * gcc.target/sh/pr64660-0.h: New. * gcc.target/sh/pr64660-1.c: New. * gcc.target/sh/pr64660-2.c: New. * gcc.target/sh/pr64660-3.c: New. * gcc.target/sh/pr64660-4.c: New. Index: gcc/testsuite/gcc.target/sh/pr64660-2.c =================================================================== --- gcc/testsuite/gcc.target/sh/pr64660-2.c (revision 0) +++ gcc/testsuite/gcc.target/sh/pr64660-2.c (revision 0) @@ -0,0 +1,13 @@ +/* Check that the appropriate atomic insns are used if the result values + are unused. */ +/* { dg-do compile { target { atomic_model_soft_tcb_available } } } */ +/* { dg-options "-dp -O2 -matomic-model=soft-tcb,gbr-offset=0,strict" } */ +/* { dg-final { scan-assembler-times "atomic_add" 12 } } */ +/* { dg-final { scan-assembler-times "atomic_and" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_or" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_xor" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_nand" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_not" 12 } } */ +/* { dg-final { scan-assembler-not "fetch" } } */ + +#include "pr64660-0.h" Index: gcc/testsuite/gcc.target/sh/pr64660-3.c =================================================================== --- gcc/testsuite/gcc.target/sh/pr64660-3.c (revision 0) +++ gcc/testsuite/gcc.target/sh/pr64660-3.c (revision 0) @@ -0,0 +1,12 @@ +/* Check that the appropriate atomic insns are used if the result values + are unused. */ +/* { dg-do compile { target { atomic_model_soft_imask_available } } } */ +/* { dg-options "-dp -O2 -matomic-model=soft-imask,strict -mno-usermode" } */ +/* { dg-final { scan-assembler-times "atomic_add_fetch" 12 } } */ +/* { dg-final { scan-assembler-times "atomic_and_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_or_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_xor_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_nand_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_not_fetch" 12 } } */ + +#include "pr64660-0.h" Index: gcc/testsuite/gcc.target/sh/pr64660-4.c =================================================================== --- gcc/testsuite/gcc.target/sh/pr64660-4.c (revision 0) +++ gcc/testsuite/gcc.target/sh/pr64660-4.c (revision 0) @@ -0,0 +1,17 @@ +/* Check that atomic not ops are generated. */ +/* { dg-do compile { target { atomic_model_hard_llcs_available } } } */ +/* { dg-options "-dp -O2 -matomic-model=hard-llcs,strict" } */ +/* { dg-final { scan-assembler-times "atomic_add" 12 } } */ +/* { dg-final { scan-assembler-times "atomic_add_fetch" 4 } } */ +/* { dg-final { scan-assembler-times "atomic_and" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_and_fetch" 2 } } */ +/* { dg-final { scan-assembler-times "atomic_or" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_or_fetch" 2 } } */ +/* { dg-final { scan-assembler-times "atomic_xor" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_xor_fetch" 2 } } */ +/* { dg-final { scan-assembler-times "atomic_nand" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_nand_fetch" 2 } } */ +/* { dg-final { scan-assembler-times "atomic_not" 12 } } */ +/* { dg-final { scan-assembler-times "atomic_not_fetch" 4 } } */ + +#include "pr64660-0.h" Index: gcc/testsuite/gcc.target/sh/pr64660-0.h =================================================================== --- gcc/testsuite/gcc.target/sh/pr64660-0.h (revision 0) +++ gcc/testsuite/gcc.target/sh/pr64660-0.h (revision 0) @@ -0,0 +1,44 @@ +/* Check that the appropriate atomic insns are used if the result values + are unused. */ + +#define concat_1(x, y) x ## y +#define concat(x, y) concat_1 (x, y) +#define makefuncname(name) concat (concat (test_, __LINE__), name) + +#define emitfuncs(name,val)\ + void makefuncname (_0) (char* mem)\ + {\ + name (mem, val, __ATOMIC_ACQ_REL);\ + }\ + void makefuncname (_1) (short* mem)\ + {\ + name (mem, val, __ATOMIC_ACQ_REL);\ + }\ + void makefuncname (_2) (int* mem)\ + {\ + name (mem, val, __ATOMIC_ACQ_REL);\ + }\ + +emitfuncs (__atomic_add_fetch, 1) +emitfuncs (__atomic_fetch_add, 1) + +emitfuncs (__atomic_sub_fetch, 1) +emitfuncs (__atomic_fetch_sub, 1) + +emitfuncs (__atomic_and_fetch, 1) +emitfuncs (__atomic_fetch_and, 1) + +emitfuncs (__atomic_or_fetch, 1) +emitfuncs (__atomic_fetch_or, 1) + +emitfuncs (__atomic_xor_fetch, 1) +emitfuncs (__atomic_fetch_xor, 1) + +emitfuncs (__atomic_nand_fetch, 1) +emitfuncs (__atomic_fetch_nand, 1) + +emitfuncs (__atomic_xor_fetch, -1) +emitfuncs (__atomic_fetch_xor, -1) + +emitfuncs (__atomic_nand_fetch, -1) +emitfuncs (__atomic_fetch_nand, -1) Index: gcc/testsuite/gcc.target/sh/pr64660-1.c =================================================================== --- gcc/testsuite/gcc.target/sh/pr64660-1.c (revision 0) +++ gcc/testsuite/gcc.target/sh/pr64660-1.c (revision 0) @@ -0,0 +1,12 @@ +/* Check that the appropriate atomic insns are used if the result values + are unused. */ +/* { dg-do compile { target { atomic_model_soft_gusa_available } } } */ +/* { dg-options "-dp -O2 -matomic-model=soft-gusa,strict" } */ +/* { dg-final { scan-assembler-times "atomic_add_fetch" 12 } } */ +/* { dg-final { scan-assembler-times "atomic_and_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_or_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_xor_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_nand_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_not_fetch" 12 } } */ + +#include "pr64660-0.h" Index: gcc/config/sh/sync.md =================================================================== --- gcc/config/sh/sync.md (revision 220371) +++ gcc/config/sh/sync.md (working copy) @@ -651,7 +651,7 @@ DONE; }) -(define_insn "atomic_fetch_si_hard" +(define_insn_and_split "atomic_fetch_si_hard" [(set (match_operand:SI 0 "arith_reg_dest" "=&r") (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:SI (match_dup 1)) @@ -671,10 +671,17 @@ " movco.l r0,@%1" "\n" " bf 0b"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic__fetchsi_hard (gen_reg_rtx (SImode), + operands[1], operands[2])); +} [(set_attr "length" "10")]) ;; Combine pattern for xor (val, -1) / nand (val, -1). -(define_insn "atomic_fetch_notsi_hard" +(define_insn_and_split "atomic_fetch_notsi_hard" [(set (match_operand:SI 0 "arith_reg_dest" "=&r") (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:SI (match_dup 1)) @@ -690,9 +697,15 @@ " movco.l r0,@%1" "\n" " bf 0b"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_not_fetchsi_hard (gen_reg_rtx (SImode), operands[1])); +} [(set_attr "length" "10")]) -(define_insn "atomic_fetch__hard" +(define_insn_and_split "atomic_fetch__hard" [(set (match_operand:QIHI 0 "arith_reg_dest" "=&r") (mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHI (match_dup 1)) @@ -722,10 +735,45 @@ " movco.l r0,@%3" "\n" " bf 0b"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic__hard (operands[1], operands[2])); +} [(set_attr "length" "28")]) +(define_insn "atomic__hard" + [(set (mem:QIHI (match_operand:SI 0 "arith_reg_operand" "r")) + (unspec:QIHI + [(FETCHOP:QIHI (mem:QIHI (match_dup 0)) + (match_operand:QIHI 1 "" + ""))] + UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) + (clobber (reg:SI R0_REG)) + (clobber (match_scratch:SI 2 "=&r")) + (clobber (match_scratch:SI 3 "=0"))] + "TARGET_ATOMIC_HARD_LLCS" +{ + return "\r mov #-4,%2" "\n" + " and %0,%2" "\n" + " xor %2,%0" "\n" + " add r15,%0" "\n" + " add #-4,%0" "\n" + "0: movli.l @%2,r0" "\n" + " mov.l r0,@-r15" "\n" + " mov. @%0,r0" "\n" + " %1,r0" "\n" + " mov. r0,@%0" "\n" + " mov.l @r15+,r0" "\n" + " movco.l r0,@%2" "\n" + " bf 0b"; +} + [(set_attr "length" "26")]) + ;; Combine pattern for xor (val, -1) / nand (val, -1). -(define_insn "atomic_fetch_not_hard" +(define_insn_and_split "atomic_fetch_not_hard" [(set (match_operand:QIHI 0 "arith_reg_dest" "=&r") (mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHI (match_dup 1)) @@ -750,9 +798,40 @@ " movco.l r0,@%2" "\n" " bf 0b"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_not_hard (operands[1])); +} [(set_attr "length" "26")]) -(define_insn "atomic_fetch__soft_gusa" +(define_insn "atomic_not_hard" + [(set (mem:QIHI (match_operand:SI 0 "arith_reg_operand" "r")) + (unspec:QIHI [(not:QIHI (mem:QIHI (match_dup 0)))] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) + (clobber (reg:SI R0_REG)) + (clobber (match_scratch:SI 1 "=&r")) + (clobber (match_scratch:SI 2 "=0"))] + "TARGET_ATOMIC_HARD_LLCS" +{ + return "\r mov #-4,%1" "\n" + " and %0,%1" "\n" + " xor %1,%0" "\n" + " add r15,%0" "\n" + " add #-4,%0" "\n" + "0: movli.l @%1,r0" "\n" + " mov.l r0,@-r15" "\n" + " mov. @%0,r0" "\n" + " not r0,r0" "\n" + " mov. r0,@%0" "\n" + " mov.l @r15+,r0" "\n" + " movco.l r0,@%1" "\n" + " bf 0b"; +} + [(set_attr "length" "26")]) + +(define_insn_and_split "atomic_fetch__soft_gusa" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&u") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "u"))) (set (mem:QIHISI (match_dup 1)) @@ -777,10 +856,17 @@ " mov. %3,@%1" "\n" "1: mov r1,r15"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic__fetch_soft_gusa ( + gen_reg_rtx (mode), operands[1], operands[2])); +} [(set_attr "length" "18")]) ;; Combine pattern for xor (val, -1) / nand (val, -1). -(define_insn "atomic_fetch_not_soft_gusa" +(define_insn_and_split "atomic_fetch_not_soft_gusa" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&u") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "u"))) (set (mem:QIHISI (match_dup 1)) @@ -799,9 +885,16 @@ " mov. %2,@%1" "\n" "1: mov r1,r15"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_not_fetch_soft_gusa (gen_reg_rtx (mode), + operands[1])); +} [(set_attr "length" "16")]) -(define_insn "atomic_fetch__soft_tcb" +(define_insn_and_split "atomic_fetch__soft_tcb" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHISI (match_dup 1)) @@ -827,10 +920,42 @@ "1: mov #0,r0" "\n" " mov.l r0,@(%O3,gbr)"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic__soft_tcb ( + operands[1], operands[2], operands[3])); +} [(set_attr "length" "20")]) +(define_insn "atomic__soft_tcb" + [(set (mem:QIHISI (match_operand:SI 0 "arith_reg_operand" "r")) + (unspec:QIHISI + [(FETCHOP:QIHISI + (mem:QIHISI (match_dup 0)) + (match_operand:QIHISI 1 "" + ""))] + UNSPEC_ATOMIC)) + (use (match_operand:SI 2 "gbr_displacement")) + (clobber (reg:SI R0_REG)) + (clobber (reg:SI R1_REG))] + "TARGET_ATOMIC_SOFT_TCB" +{ + return "\r mova 1f,r0" "\n" + " mov #(0f-1f),r1" "\n" + " .align 2" "\n" + " mov.l r0,@(%O2,gbr)" "\n" + "0: mov. @%0,r0" "\n" + " %1,r0" "\n" + " mov. r0,@%0" "\n" + "1: mov #0,r0" "\n" + " mov.l r0,@(%O2,gbr)"; +} + [(set_attr "length" "18")]) + ;; Combine pattern for xor (val, -1) / nand (val, -1). -(define_insn "atomic_fetch_not_soft_tcb" +(define_insn_and_split "atomic_fetch_not_soft_tcb" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHISI (match_dup 1)) @@ -851,9 +976,35 @@ "1: mov #0,r0" "\n" " mov.l r0,@(%O2,gbr)"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_not_soft_tcb (operands[1], operands[2])); +} [(set_attr "length" "20")]) -(define_insn "atomic_fetch__soft_imask" +(define_insn "atomic_not_soft_tcb" + [(set (mem:QIHISI (match_operand:SI 0 "arith_reg_operand" "r")) + (unspec:QIHISI [(not:QIHISI (mem:QIHISI (match_dup 0)))] UNSPEC_ATOMIC)) + (use (match_operand:SI 1 "gbr_displacement")) + (clobber (reg:SI R0_REG)) + (clobber (reg:SI R1_REG))] + "TARGET_ATOMIC_SOFT_TCB" +{ + return "\r mova 1f,r0" "\n" + " mov #(0f-1f),r1" "\n" + " .align 2" "\n" + " mov.l r0,@(%O1,gbr)" "\n" + "0: mov. @%0,r0" "\n" + " not r0,r0" "\n" + " mov. r0,@%0" "\n" + "1: mov #0,r0" "\n" + " mov.l r0,@(%O1,gbr)"; +} + [(set_attr "length" "18")]) + +(define_insn_and_split "atomic_fetch__soft_imask" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHISI (match_dup 1)) @@ -877,10 +1028,17 @@ " mov. r0,@%1" "\n" " ldc %3,sr"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic__fetch_soft_imask ( + gen_reg_rtx (mode), operands[1], operands[2])); +} [(set_attr "length" "18")]) ;; Combine pattern for xor (val, -1) / nand (val, -1). -(define_insn "atomic_fetch_not_soft_imask" +(define_insn_and_split "atomic_fetch_not_soft_imask" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHISI (match_dup 1)) @@ -899,6 +1057,13 @@ " mov. r0,@%1" "\n" " ldc %2,sr"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_not_fetch_soft_imask (gen_reg_rtx (mode), + operands[1])); +} [(set_attr "length" "18")]) (define_expand "atomic_fetch_nand" @@ -942,7 +1107,7 @@ DONE; }) -(define_insn "atomic_fetch_nandsi_hard" +(define_insn_and_split "atomic_fetch_nandsi_hard" [(set (match_operand:SI 0 "arith_reg_dest" "=&r") (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:SI (match_dup 1)) @@ -962,9 +1127,16 @@ " movco.l r0,@%1" "\n" " bf 0b"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_nand_fetchsi_hard (gen_reg_rtx (SImode), operands[1], + operands[2])); +} [(set_attr "length" "12")]) -(define_insn "atomic_fetch_nand_hard" +(define_insn_and_split "atomic_fetch_nand_hard" [(set (match_operand:QIHI 0 "arith_reg_dest" "=&r") (mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHI (match_dup 1)) @@ -994,9 +1166,44 @@ " movco.l r0,@%3" "\n" " bf 0b"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_nand_hard (operands[1], operands[2])); +} [(set_attr "length" "30")]) -(define_insn "atomic_fetch_nand_soft_gusa" +(define_insn "atomic_nand_hard" + [(set (mem:QIHI (match_operand:SI 0 "arith_reg_operand" "r")) + (unspec:QIHI + [(not:QIHI (and:QIHI (mem:QIHI (match_dup 0)) + (match_operand:QIHI 1 "logical_operand" "rK08")))] + UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) + (clobber (reg:SI R0_REG)) + (clobber (match_scratch:SI 2 "=&r")) + (clobber (match_scratch:SI 3 "=0"))] + "TARGET_ATOMIC_HARD_LLCS" +{ + return "\r mov #-4,%2" "\n" + " and %0,%2" "\n" + " xor %2,%0" "\n" + " add r15,%0" "\n" + " add #-4,%0" "\n" + "0: movli.l @%2,r0" "\n" + " mov.l r0,@-r15" "\n" + " mov. @%0,r0" "\n" + " and %1,r0" "\n" + " not r0,r0" "\n" + " mov. r0,@%0" "\n" + " mov.l @r15+,r0" "\n" + " movco.l r0,@%2" "\n" + " bf 0b"; +} + [(set_attr "length" "28")]) + +(define_insn_and_split "atomic_fetch_nand_soft_gusa" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&u") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "u"))) (set (mem:QIHISI (match_dup 1)) @@ -1021,9 +1228,16 @@ " mov. %3,@%1" "\n" "1: mov r1,r15"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_nand_fetch_soft_gusa (gen_reg_rtx (mode), + operands[1], operands[2])); +} [(set_attr "length" "20")]) -(define_insn "atomic_fetch_nand_soft_tcb" +(define_insn_and_split "atomic_fetch_nand_soft_tcb" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHISI (match_dup 1)) @@ -1049,9 +1263,41 @@ "1: mov #0,r0" "\n" " mov.l r0,@(%O3,gbr)"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_nand_soft_tcb (operands[1], operands[2], + operands[3])); +} [(set_attr "length" "22")]) -(define_insn "atomic_fetch_nand_soft_imask" +(define_insn "atomic_nand_soft_tcb" + [(set (mem:QIHISI (match_operand:SI 0 "arith_reg_operand" "r")) + (unspec:QIHISI + [(not:QIHISI + (and:QIHISI (mem:QIHISI (match_dup 0)) + (match_operand:QIHISI 1 "logical_operand" "rK08")))] + UNSPEC_ATOMIC)) + (use (match_operand:SI 2 "gbr_displacement")) + (clobber (reg:SI R0_REG)) + (clobber (reg:SI R1_REG))] + "TARGET_ATOMIC_SOFT_TCB" +{ + return "\r mova 1f,r0" "\n" + " .align 2" "\n" + " mov #(0f-1f),r1" "\n" + " mov.l r0,@(%O2,gbr)" "\n" + "0: mov. @%0,r0" "\n" + " and %1,r0" "\n" + " not r0,r0" "\n" + " mov. r0,@%0" "\n" + "1: mov #0,r0" "\n" + " mov.l r0,@(%O2,gbr)"; +} + [(set_attr "length" "20")]) + +(define_insn_and_split "atomic_fetch_nand_soft_imask" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHISI (match_dup 1)) @@ -1075,6 +1321,13 @@ " mov. r0,@%1" "\n" " ldc %3,sr"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_nand_fetch_soft_imask (gen_reg_rtx (mode), + operands[1], operands[2])); +} [(set_attr "length" "20")]) ;;------------------------------------------------------------------------------ @@ -1160,7 +1413,7 @@ } [(set_attr "length" "8")]) -(define_insn "atomic__fetch_hard" +(define_insn_and_split "atomic__fetch_hard" [(set (match_operand:QIHI 0 "arith_reg_dest" "=&r") (FETCHOP:QIHI (mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r")) @@ -1191,10 +1444,16 @@ " movco.l r0,@%3" "\n" " bf 0b"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic__hard (operands[1], operands[2])); +} [(set_attr "length" "28")]) ;; Combine pattern for xor (val, -1) / nand (val, -1). -(define_insn "atomic_not_fetch_hard" +(define_insn_and_split "atomic_not_fetch_hard" [(set (match_operand:QIHI 0 "arith_reg_dest" "=&r") (not:QIHI (mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r")))) (set (mem:QIHI (match_dup 1)) @@ -1220,6 +1479,12 @@ " movco.l r0,@%2" "\n" " bf 0b"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_not_hard (operands[1])); +} [(set_attr "length" "28")]) (define_insn "atomic__fetch_soft_gusa" @@ -1268,7 +1533,7 @@ } [(set_attr "length" "16")]) -(define_insn "atomic__fetch_soft_tcb" +(define_insn_and_split "atomic__fetch_soft_tcb" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (FETCHOP:QIHISI (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r")) @@ -1294,10 +1559,17 @@ " mov #0,r0" "\n" " mov.l r0,@(%O3,gbr)"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic__soft_tcb ( + operands[1], operands[2], operands[3])); +} [(set_attr "length" "20")]) ;; Combine pattern for xor (val, -1) / nand (val, -1). -(define_insn "atomic_not_fetch_soft_tcb" +(define_insn_and_split "atomic_not_fetch_soft_tcb" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (not:QIHISI (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r")))) (set (mem:QIHISI (match_dup 1)) @@ -1318,6 +1590,12 @@ " mov #0,r0" "\n" " mov.l r0,@(%O2,gbr)"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_not_soft_tcb (operands[1], operands[2])); +} [(set_attr "length" "20")]) (define_insn "atomic__fetch_soft_imask" @@ -1426,7 +1704,7 @@ } [(set_attr "length" "10")]) -(define_insn "atomic_nand_fetch_hard" +(define_insn_and_split "atomic_nand_fetch_hard" [(set (match_operand:QIHI 0 "arith_reg_dest" "=&r") (not:QIHI (and:QIHI (mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r")) @@ -1456,6 +1734,12 @@ " movco.l r0,@%3" "\n" " bf 0b"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_nand_hard (operands[1], operands[2])); +} [(set_attr "length" "28")]) (define_insn "atomic_nand_fetch_soft_gusa" @@ -1483,7 +1767,7 @@ } [(set_attr "length" "18")]) -(define_insn "atomic_nand_fetch_soft_tcb" +(define_insn_and_split "atomic_nand_fetch_soft_tcb" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (not:QIHISI (and:QIHISI (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r")) @@ -1509,6 +1793,13 @@ "1: mov #0,r0" "\n" " mov.l r0,@(%O3,gbr)"; } + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_nand_soft_tcb (operands[1], operands[2], + operands[3])); +} [(set_attr "length" "22")]) (define_insn "atomic_nand_fetch_soft_imask"