From 6399761a4a77d5e5996c8e82eba042f4a26a4c3d Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Wed, 20 Jun 2012 00:59:08 +0000 Subject: [PATCH] constraints.md (ZR): New constraint. 2012-06-19 Tom de Vries Maxim Kuvyrkov * config/mips/constraints.md (ZR): New constraint. * config/mips/predicates.md (mem_noofs_operand): New predicate. * config/mips/mips.c (mips_print_operand): Handle new print modifier. * config/mips/mips.h (TARGET_XLP): Define. (TARGET_SYNC_AFTER_SC): Update. (ISA_HAS_SWAP, ISA_HAS_LDADD): Define. * config/mips/sync.md (atomic_exchange, atomic_fetch_add): Use XLP-specific swap and ldadd patterns. (atomic_exchange_swap, atomic_fetch_add_ldadd): New patterns. Co-Authored-By: Maxim Kuvyrkov From-SVN: r188804 --- gcc/ChangeLog | 13 ++++++++ gcc/config/mips/constraints.md | 5 +++ gcc/config/mips/mips.c | 8 ++++- gcc/config/mips/mips.h | 6 +++- gcc/config/mips/predicates.md | 4 +++ gcc/config/mips/sync.md | 60 +++++++++++++++++++++++++++++++--- 6 files changed, 90 insertions(+), 6 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 069b61c9535..0b679ae5d8b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2012-06-19 Tom de Vries + Maxim Kuvyrkov + + * config/mips/constraints.md (ZR): New constraint. + * config/mips/predicates.md (mem_noofs_operand): New predicate. + * config/mips/mips.c (mips_print_operand): Handle new print modifier. + * config/mips/mips.h (TARGET_XLP): Define. + (TARGET_SYNC_AFTER_SC): Update. + (ISA_HAS_SWAP, ISA_HAS_LDADD): Define. + * config/mips/sync.md (atomic_exchange, atomic_fetch_add): Use + XLP-specific swap and ldadd patterns. + (atomic_exchange_swap, atomic_fetch_add_ldadd): New patterns. + 2012-06-19 Tom de Vries Maxim Kuvyrkov diff --git a/gcc/config/mips/constraints.md b/gcc/config/mips/constraints.md index 2bfb2aaf2c5..b543217c43a 100644 --- a/gcc/config/mips/constraints.md +++ b/gcc/config/mips/constraints.md @@ -231,3 +231,8 @@ (define_constraint "Yx" "@internal" (match_operand 0 "low_bitmask_operand")) + +(define_memory_constraint "ZR" + "@internal + An address valid for loading/storing register exclusive" + (match_operand 0 "mem_noofs_operand")) diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index f37c19499d7..64b486d1d0b 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -7806,7 +7806,8 @@ mips_print_operand_punct_valid_p (unsigned char code) 'D' Print the second part of a double-word register or memory operand. 'L' Print the low-order register in a double-word register operand. 'M' Print high-order register in a double-word register operand. - 'z' Print $0 if OP is zero, otherwise print OP normally. */ + 'z' Print $0 if OP is zero, otherwise print OP normally. + 'b' Print the address of a memory operand, without offset. */ static void mips_print_operand (FILE *file, rtx op, int letter) @@ -7935,6 +7936,11 @@ mips_print_operand (FILE *file, rtx op, int letter) case MEM: if (letter == 'D') output_address (plus_constant (Pmode, XEXP (op, 0), 4)); + else if (letter == 'b') + { + gcc_assert (REG_P (XEXP (op, 0))); + mips_print_operand (file, XEXP (op, 0), 0); + } else if (letter && letter != 'z') output_operand_lossage ("invalid use of '%%%c'", letter); else diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 97f38b2c49b..d8b0c6384e2 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -223,6 +223,7 @@ struct mips_cpu_info { #define TARGET_SB1 (mips_arch == PROCESSOR_SB1 \ || mips_arch == PROCESSOR_SB1A) #define TARGET_SR71K (mips_arch == PROCESSOR_SR71000) +#define TARGET_XLP (mips_arch == PROCESSOR_XLP) /* Scheduling target defines. */ #define TUNE_20KC (mips_tune == PROCESSOR_20KC) @@ -311,7 +312,7 @@ struct mips_cpu_info { stores. It does not tell anything about ordering of loads and stores prior to and following the SC, only about the SC itself and those loads and stores follow it. */ -#define TARGET_SYNC_AFTER_SC (!TARGET_OCTEON) +#define TARGET_SYNC_AFTER_SC (!TARGET_OCTEON && !TARGET_XLP) /* Define preprocessor macros for the -march and -mtune options. PREFIX is either _MIPS_ARCH or _MIPS_TUNE, INFO is the selected @@ -1054,6 +1055,9 @@ struct mips_cpu_info { ? TARGET_LLSC && !TARGET_MIPS16 \ : ISA_HAS_LL_SC) +#define ISA_HAS_SWAP (TARGET_XLP) +#define ISA_HAS_LDADD (TARGET_XLP) + /* ISA includes the baddu instruction. */ #define ISA_HAS_BADDU (TARGET_OCTEON && !TARGET_MIPS16) diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md index 57b1af2de3e..97971e9a205 100644 --- a/gcc/config/mips/predicates.md +++ b/gcc/config/mips/predicates.md @@ -370,3 +370,7 @@ (define_predicate "small_data_pattern" (and (match_code "set,parallel,unspec,unspec_volatile,prefetch") (match_test "mips_small_data_pattern_p (op)"))) + +(define_predicate "mem_noofs_operand" + (and (match_code "mem") + (match_code "reg" "0"))) diff --git a/gcc/config/mips/sync.md b/gcc/config/mips/sync.md index 604aefa3d0e..0a7905a3300 100644 --- a/gcc/config/mips/sync.md +++ b/gcc/config/mips/sync.md @@ -607,8 +607,22 @@ (match_operand:GPR 1 "memory_operand") (match_operand:GPR 2 "arith_operand") (match_operand:SI 3 "const_int_operand")] - "GENERATE_LL_SC" + "GENERATE_LL_SC || ISA_HAS_SWAP" { + if (ISA_HAS_SWAP) + { + if (!mem_noofs_operand (operands[1], mode)) + { + rtx addr; + + addr = force_reg (Pmode, XEXP (operands[1], 0)); + operands[1] = replace_equiv_address (operands[1], addr); + } + operands[2] = force_reg (mode, operands[2]); + emit_insn (gen_atomic_exchange_swap (operands[0], operands[1], + operands[2])); + } + else emit_insn (gen_atomic_exchange_llsc (operands[0], operands[1], operands[2], operands[3])); DONE; @@ -623,7 +637,7 @@ UNSPEC_ATOMIC_EXCHANGE)) (unspec_volatile:GPR [(match_operand:SI 3 "const_int_operand")] UNSPEC_ATOMIC_EXCHANGE)] - "GENERATE_LL_SC" + "GENERATE_LL_SC && !ISA_HAS_SWAP" { return mips_output_sync_loop (insn, operands); } [(set_attr "sync_insn1" "li,move") (set_attr "sync_oldval" "0") @@ -631,13 +645,38 @@ (set_attr "sync_insn1_op2" "2") (set_attr "sync_memmodel" "3")]) +;; XLP issues implicit sync for SWAP/LDADD, so no need for an explicit one. +(define_insn "atomic_exchange_swap" + [(set (match_operand:GPR 0 "register_operand" "=d") + (unspec_volatile:GPR [(match_operand:GPR 1 "mem_noofs_operand" "+ZR")] + UNSPEC_ATOMIC_EXCHANGE)) + (set (match_dup 1) + (unspec_volatile:GPR [(match_operand:GPR 2 "register_operand" "0")] + UNSPEC_ATOMIC_EXCHANGE))] + "ISA_HAS_SWAP" + "swap\t%0,%b1") + (define_expand "atomic_fetch_add" [(match_operand:GPR 0 "register_operand") (match_operand:GPR 1 "memory_operand") (match_operand:GPR 2 "arith_operand") (match_operand:SI 3 "const_int_operand")] - "GENERATE_LL_SC" + "GENERATE_LL_SC || ISA_HAS_LDADD" { + if (ISA_HAS_LDADD) + { + if (!mem_noofs_operand (operands[1], mode)) + { + rtx addr; + + addr = force_reg (Pmode, XEXP (operands[1], 0)); + operands[1] = replace_equiv_address (operands[1], addr); + } + operands[2] = force_reg (mode, operands[2]); + emit_insn (gen_atomic_fetch_add_ldadd (operands[0], operands[1], + operands[2])); + } + else emit_insn (gen_atomic_fetch_add_llsc (operands[0], operands[1], operands[2], operands[3])); DONE; @@ -654,10 +693,23 @@ UNSPEC_ATOMIC_FETCH_OP)) (unspec_volatile:GPR [(match_operand:SI 3 "const_int_operand")] UNSPEC_ATOMIC_FETCH_OP)] - "GENERATE_LL_SC" + "GENERATE_LL_SC && !ISA_HAS_LDADD" { return mips_output_sync_loop (insn, operands); } [(set_attr "sync_insn1" "addiu,addu") (set_attr "sync_oldval" "0") (set_attr "sync_mem" "1") (set_attr "sync_insn1_op2" "2") (set_attr "sync_memmodel" "3")]) + +;; XLP issues implicit sync for SWAP/LDADD, so no need for an explicit one. +(define_insn "atomic_fetch_add_ldadd" + [(set (match_operand:GPR 0 "register_operand" "=d") + (unspec_volatile:GPR [(match_operand:GPR 1 "mem_noofs_operand" "+ZR")] + UNSPEC_ATOMIC_FETCH_OP)) + (set (match_dup 1) + (unspec_volatile:GPR + [(plus:GPR (match_dup 1) + (match_operand:GPR 2 "register_operand" "0"))] + UNSPEC_ATOMIC_FETCH_OP))] + "ISA_HAS_LDADD" + "ldadd\t%0,%b1") -- 2.30.2