OSDN Git Service

* config/rs6000/rs6000.md (UNSPEC constants): Add UNSPEC_STFIWX.
authorgeoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 25 Mar 2005 19:50:53 +0000 (19:50 +0000)
committergeoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 25 Mar 2005 19:50:53 +0000 (19:50 +0000)
(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

gcc/ChangeLog
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/ppc-stfiwx.c [new file with mode: 0644]

index 5acc173..e99685a 100644 (file)
@@ -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
index 018de14..dd8590c 100644 (file)
@@ -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 *);
index 0cf135f..3fc857a 100644 (file)
@@ -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
index 8e7a254..adef695 100644 (file)
@@ -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.
index fc4b6f1..b9fa39c 100644 (file)
@@ -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)
   ])
 
 ;;
 }")
 
 (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))])]
      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;
   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" "")))]
index d6da707..7594edc 100644 (file)
@@ -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 (file)
index 0000000..47a29ed
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do compile { target powerpc*-*-* } } */
+/* { dg-options "-mpowerpc-gfxopt" } */
+/* { dg-final { scan-assembler "stfiwx" } } */
+
+int foo (double x)
+{
+  return x;
+}