diff options
author | geoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-03-25 19:50:53 +0000 |
---|---|---|
committer | geoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-03-25 19:50:53 +0000 |
commit | 965e7256d9c6beb266cd5ca44e3eecaa8a297f0a (patch) | |
tree | 9939aa9903cc9a3b806d05e10fea5a51aabf6ae0 | |
parent | 80b6664d4e47b4e6f45dc7a84a64062d3cdc6701 (diff) | |
download | gcc-965e7256d9c6beb266cd5ca44e3eecaa8a297f0a.tar.gz |
* config/rs6000/rs6000.md (UNSPEC constants): Add UNSPEC_STFIWX.
(fix_truncdfsi2): Allow registers or memory as destination.
When TARGET_PPC_GFXOPT, generate simplified pattern.
(fix_truncdfsi2_internal): Use define_insn_and_split.
(fix_truncdfsi2_internal_gfxopt): New.
(fctiwz): Don't confuse register allocation by giving it no choices.
(stfiwx): New.
* config/rs6000/rs6000.h (EXTRA_CONSTRAINT): Add 'Z'.
(EXTRA_MEMORY_CONSTRAINT): Likewise.
* config/rs6000/rs6000.c (indexed_or_indirect_operand): New.
* config/rs6000/rs6000-protos.h (indexed_or_indirect_operand): New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@97058 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 19 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.h | 4 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 61 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/ppc-stfiwx.c | 8 |
7 files changed, 94 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5acc17367d6..e99685a65bd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2005-03-25 Geoffrey Keating <geoffk@apple.com> + + * config/rs6000/rs6000.md (UNSPEC constants): Add UNSPEC_STFIWX. + (fix_truncdfsi2): Allow registers or memory as destination. + When TARGET_PPC_GFXOPT, generate simplified pattern. + (fix_truncdfsi2_internal): Use define_insn_and_split. + (fix_truncdfsi2_internal_gfxopt): New. + (fctiwz): Don't confuse register allocation by giving it no choices. + (stfiwx): New. + * config/rs6000/rs6000.h (EXTRA_CONSTRAINT): Add 'Z'. + (EXTRA_MEMORY_CONSTRAINT): Likewise. + * config/rs6000/rs6000.c (indexed_or_indirect_operand): New. + * config/rs6000/rs6000-protos.h (indexed_or_indirect_operand): New. + 2005-03-25 Kazu Hirata <kazu@cs.umass.edu> * dominance.c (free_dominance_info): Speed up by freeing et diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 018de14ec2d..dd8590cf9e1 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -49,6 +49,7 @@ extern bool rs6000_legitimate_offset_address_p (enum machine_mode, rtx, int); extern rtx rs6000_got_register (rtx); extern rtx find_addr_reg (rtx); extern int word_offset_memref_operand (rtx, enum machine_mode); +extern int indexed_or_indirect_operand (rtx, enum machine_mode); extern rtx gen_easy_vector_constant_add_self (rtx); extern const char *output_vec_const_move (rtx *); extern void build_mask64_2_operands (rtx, rtx *); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 0cf135f01af..3fc857a459b 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -2297,6 +2297,25 @@ word_offset_memref_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) return (off % 4) == 0; } +/* Return true if the operand is an indirect or indexed memory operand. */ + +int +indexed_or_indirect_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +{ + rtx addr; + if (!memory_operand (op, mode)) + return 0; + + addr = XEXP (op, 0); + if (GET_CODE (addr) == REG) + return 1; + if (GET_CODE (addr) == PLUS + && GET_CODE (XEXP (addr, 0)) == REG + && GET_CODE (XEXP (addr, 1)) == REG) + return 1; + return 0; +} + /* Return true if either operand is a general purpose register. */ bool diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 8e7a2543dc1..adef69579d7 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1357,6 +1357,7 @@ enum reg_class 'U' is for V.4 small data references. 'W' is a vector constant that can be easily generated (no mem refs). 'Y' is a indexed or word-aligned displacement memory operand. + 'Z' is an indexed or indirect memory operand. 't' is for AND masks that can be performed by two rldic{l,r} insns. */ #define EXTRA_CONSTRAINT(OP, C) \ @@ -1372,6 +1373,7 @@ enum reg_class && !mask64_operand (OP, DImode)) \ : (C) == 'W' ? (easy_vector_constant (OP, GET_MODE (OP))) \ : (C) == 'Y' ? (word_offset_memref_operand (OP, GET_MODE (OP))) \ + : (C) == 'Z' ? (indexed_or_indirect_operand (OP, GET_MODE (OP))) \ : 0) /* Define which constraints are memory constraints. Tell reload @@ -1379,7 +1381,7 @@ enum reg_class memory address into a base register if required. */ #define EXTRA_MEMORY_CONSTRAINT(C, STR) \ - ((C) == 'Q' || (C) == 'Y') + ((C) == 'Q' || (C) == 'Y' || (C) == 'Z') /* Given an rtx X being reloaded into a reg required to be in class CLASS, return the class of reg to actually use. diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index fc4b6f1cfb2..b9fa39c386d 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -51,6 +51,7 @@ (UNSPEC_TLSTLS 29) (UNSPEC_FIX_TRUNC_TF 30) ; fadd, rounding towards zero (UNSPEC_MV_CR_GT 31) ; move_from_CR_eq_bit + (UNSPEC_STFIWX 32) ]) ;; @@ -5272,7 +5273,7 @@ }") (define_expand "fix_truncdfsi2" - [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "") + [(parallel [(set (match_operand:SI 0 "reg_or_mem_operand" "") (fix:SI (match_operand:DF 1 "gpc_reg_operand" ""))) (clobber (match_dup 2)) (clobber (match_dup 3))])] @@ -5286,28 +5287,29 @@ DONE; } operands[2] = gen_reg_rtx (DImode); + if (TARGET_PPC_GFXOPT) + { + rtx orig_dest = operands[0]; + if (GET_CODE (orig_dest) != MEM) + operands[0] = assign_stack_temp (SImode, GET_MODE_SIZE (SImode), 0); + emit_insn (gen_fix_truncdfsi2_internal_gfxopt (operands[0], operands[1], + operands[2])); + if (operands[0] != orig_dest) + emit_move_insn (orig_dest, operands[0]); + DONE; + } operands[3] = assign_stack_temp (DImode, GET_MODE_SIZE (DImode), 0); }") -(define_insn "*fix_truncdfsi2_internal" +(define_insn_and_split "*fix_truncdfsi2_internal" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))) (clobber (match_operand:DI 2 "gpc_reg_operand" "=f")) (clobber (match_operand:DI 3 "memory_operand" "=o"))] "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS" "#" - [(set_attr "length" "16")]) - -(define_split - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (fix:SI (match_operand:DF 1 "gpc_reg_operand" ""))) - (clobber (match_operand:DI 2 "gpc_reg_operand" "")) - (clobber (match_operand:DI 3 "offsettable_mem_operand" ""))] - "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (fix:SI (match_operand:DF 1 "gpc_reg_operand" ""))) - (clobber (match_operand:DI 2 "gpc_reg_operand" "")) - (clobber (match_operand:DI 3 "offsettable_mem_operand" ""))] + "&& 1" + [(pc)] " { rtx lowword; @@ -5321,20 +5323,47 @@ emit_move_insn (operands[3], operands[2]); emit_move_insn (operands[0], gen_rtx_MEM (SImode, lowword)); DONE; -}") +}" + [(set_attr "length" "16")]) + +(define_insn_and_split "fix_truncdfsi2_internal_gfxopt" + [(set (match_operand:SI 0 "memory_operand" "=Z") + (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))) + (clobber (match_operand:DI 2 "gpc_reg_operand" "=f"))] + "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS + && TARGET_PPC_GFXOPT" + "#" + "&& 1" + [(pc)] + " +{ + emit_insn (gen_fctiwz (operands[2], operands[1])); + emit_insn (gen_stfiwx (operands[0], operands[2])); + DONE; +}" + [(set_attr "length" "16")]) ; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ)) ; rather than (set (subreg:SI (reg)) (fix:SI ...)) ; because the first makes it clear that operand 0 is not live ; before the instruction. (define_insn "fctiwz" - [(set (match_operand:DI 0 "gpc_reg_operand" "=*f") + [(set (match_operand:DI 0 "gpc_reg_operand" "=f") (unspec:DI [(fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))] UNSPEC_FCTIWZ))] "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS" "{fcirz|fctiwz} %0,%1" [(set_attr "type" "fp")]) +; An UNSPEC is used so we don't have to support SImode in FP registers. +(define_insn "stfiwx" + [(set (match_operand:SI 0 "memory_operand" "=Z") + (unspec:SI [(match_operand:DI 1 "gpc_reg_operand" "f")] + UNSPEC_STFIWX))] + "TARGET_PPC_GFXOPT" + "stfiwx %1,%y0" + [(set_attr "type" "fpstore")]) + (define_expand "floatsisf2" [(set (match_operand:SF 0 "gpc_reg_operand" "") (float:SF (match_operand:SI 1 "gpc_reg_operand" "")))] diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d6da70773d7..7594edc797a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2005-03-25 Geoffrey Keating <geoffk@apple.com> + + * gcc.dg/ppc-stfiwx.c: New. + 2005-03-25 Steve Ellcey <sje@cup.hp.com> PR target/19888 diff --git a/gcc/testsuite/gcc.dg/ppc-stfiwx.c b/gcc/testsuite/gcc.dg/ppc-stfiwx.c new file mode 100644 index 00000000000..47a29ed3f17 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ppc-stfiwx.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target powerpc*-*-* } } */ +/* { dg-options "-mpowerpc-gfxopt" } */ +/* { dg-final { scan-assembler "stfiwx" } } */ + +int foo (double x) +{ + return x; +} |