public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* stfiwx for rs6000
@ 2005-03-25 19:54 Geoffrey Keating
  2005-03-25 20:11 ` David Edelsohn
  2005-03-30 18:50 ` Richard Henderson
  0 siblings, 2 replies; 7+ messages in thread
From: Geoffrey Keating @ 2005-03-25 19:54 UTC (permalink / raw)
  To: gcc-patches


This patch adds minimal support for the 'stfiwx' instruction to the
rs6000 backend.  I say 'minimal' because even though it is used, the
benefit of it is only that 4 bytes are saved on the stack per
temporary, rather than what you'd really like, which is that it will
store directory into a variable in memory if that's more efficient.  I
couldn't work out how to make it store into user memory, after trying
several possibilities; combine won't do it, and when I tried to just say
that "this instruction requires a memory operand", reload would fail.

But, 4 bytes is 4 bytes.  In fact, sometimes it's hundreds of bytes if
there are many temporaries.

Bootstrapped & tested on powerpc-darwin8.

-- 
- Geoffrey Keating <geoffk@apple.com>

===File ~/patches/rs6000-stfiwx-2.patch=====================
2005-03-24  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.

Index: testsuite/ChangeLog
2005-03-25  Geoffrey Keating  <geoffk@apple.com>

	* gcc.dg/ppc-stfiwx.c: New.

Index: config/rs6000/rs6000-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000-protos.h,v
retrieving revision 1.96
diff -u -p -u -p -r1.96 rs6000-protos.h
--- config/rs6000/rs6000-protos.h	14 Mar 2005 07:24:24 -0000	1.96
+++ config/rs6000/rs6000-protos.h	25 Mar 2005 19:44:38 -0000
@@ -49,6 +49,7 @@ extern bool rs6000_legitimate_offset_add
 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: config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.796
diff -u -p -u -p -r1.796 rs6000.c
--- config/rs6000/rs6000.c	20 Mar 2005 23:25:14 -0000	1.796
+++ config/rs6000/rs6000.c	25 Mar 2005 19:44:38 -0000
@@ -2297,6 +2297,25 @@ word_offset_memref_operand (rtx op, enum
   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: config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.357
diff -u -p -u -p -r1.357 rs6000.h
--- config/rs6000/rs6000.h	14 Mar 2005 07:24:29 -0000	1.357
+++ config/rs6000/rs6000.h	25 Mar 2005 19:44:40 -0000
@@ -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: config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.355
diff -u -p -u -p -r1.355 rs6000.md
--- config/rs6000/rs6000.md	16 Mar 2005 18:29:26 -0000	1.355
+++ config/rs6000/rs6000.md	25 Mar 2005 19:44:40 -0000
@@ -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" "")))]
Index: testsuite/gcc.dg/ppc-stfiwx.c
===================================================================
RCS file: testsuite/gcc.dg/ppc-stfiwx.c
diff -N testsuite/gcc.dg/ppc-stfiwx.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/ppc-stfiwx.c	25 Mar 2005 19:44:43 -0000
@@ -0,0 +1,8 @@
+/* { dg-do compile { target powerpc*-*-* } } */
+/* { dg-options "-mpowerpc-gfxopt" } */
+/* { dg-final { scan-assembler "stfiwx" } } */
+
+int foo (double x)
+{
+  return x;
+}
============================================================

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: stfiwx for rs6000
  2005-03-25 19:54 stfiwx for rs6000 Geoffrey Keating
@ 2005-03-25 20:11 ` David Edelsohn
  2005-03-25 20:16   ` Andrew Pinski
  2005-03-30 18:50 ` Richard Henderson
  1 sibling, 1 reply; 7+ messages in thread
From: David Edelsohn @ 2005-03-25 20:11 UTC (permalink / raw)
  To: gkeating; +Cc: gcc-patches

> This patch adds minimal support for the 'stfiwx' instruction to the
> rs6000 backend.

Great.

> 	* config/rs6000/rs6000.c (indexed_or_indirect_operand): New. 
> 	* config/rs6000/rs6000-protos.h (indexed_or_indirect_operand): New.

Why didn't this go into predicates.md?

David

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: stfiwx for rs6000
  2005-03-25 20:11 ` David Edelsohn
@ 2005-03-25 20:16   ` Andrew Pinski
  2005-03-25 20:26     ` David Edelsohn
  0 siblings, 1 reply; 7+ messages in thread
From: Andrew Pinski @ 2005-03-25 20:16 UTC (permalink / raw)
  To: David Edelsohn; +Cc: gcc-patches, gkeating


On Mar 25, 2005, at 3:06 PM, David Edelsohn wrote:

>> This patch adds minimal support for the 'stfiwx' instruction to the
>> rs6000 backend.
>
> Great.
>
>> 	* config/rs6000/rs6000.c (indexed_or_indirect_operand): New.
>> 	* config/rs6000/rs6000-protos.h (indexed_or_indirect_operand): New.
>
> Why didn't this go into predicates.md?

I was wondering the same thing until I notice that some
of the functions used in EXTRA_CONSTRAINT are only defined
in rs6000.c.

-- Pinski

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: stfiwx for rs6000
  2005-03-25 20:16   ` Andrew Pinski
@ 2005-03-25 20:26     ` David Edelsohn
  2005-03-26  3:51       ` Geoffrey Keating
  0 siblings, 1 reply; 7+ messages in thread
From: David Edelsohn @ 2005-03-25 20:26 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: gcc-patches, gkeating

>>>>> Andrew Pinski writes:

Andrew> I was wondering the same thing until I notice that some
Andrew> of the functions used in EXTRA_CONSTRAINT are only defined
Andrew> in rs6000.c.

	Most of them now are defined in predicates.md.
word_offset_memrf_operand and indexed_or_indirect_operand should be moved
to predicates.md as a C block with (match_operand 0 "memory_operand").
I'll look into it this weekend after the initial patch settles.

David

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: stfiwx for rs6000
  2005-03-25 20:26     ` David Edelsohn
@ 2005-03-26  3:51       ` Geoffrey Keating
  2005-03-26  7:40         ` David Edelsohn
  0 siblings, 1 reply; 7+ messages in thread
From: Geoffrey Keating @ 2005-03-26  3:51 UTC (permalink / raw)
  To: David Edelsohn; +Cc: GCC Patches, Andrew Pinski

[-- Attachment #1: Type: text/plain, Size: 1969 bytes --]


On 25/03/2005, at 12:16 PM, David Edelsohn wrote:

>>>>>> Andrew Pinski writes:
>
> Andrew> I was wondering the same thing until I notice that some
> Andrew> of the functions used in EXTRA_CONSTRAINT are only defined
> Andrew> in rs6000.c.
>
> 	Most of them now are defined in predicates.md.
> word_offset_memrf_operand and indexed_or_indirect_operand should be 
> moved
> to predicates.md as a C block with (match_operand 0 "memory_operand").
> I'll look into it this weekend after the initial patch settles.

Like this?

word_offset_memref_operand is somewhat tricky.  I'm pretty sure, but 
not 100%, that I'm doing the same as the original code, but am not at 
all sure that the original code is right.

*** predicates.md.~1.8.~        Thu Mar 24 18:52:44 2005
--- predicates.md       Fri Mar 25 16:16:22 2005
***************
*** 358,363 ****
--- 358,379 ----
                                            || reload_in_progress,
                                            mode, XEXP (op, 0))")))

+ ;; Return 1 if the operand is an indexed or indirect memory operand.
+ (define_predicate "indexed_or_indirect_operand"
+   (and (match_operand 0 "memory_operand")
+        (match_test "REG_P (XEXP (op, 0))
+                   || (GET_CODE (XEXP (op, 0)) == PLUS
+                       && REG_P (XEXP (XEXP (op, 0), 0))
+                       && REG_P (XEXP (XEXP (op, 0), 1)))")))
+
+ ;; Return 1 if the operand is a memory operand with an address 
divisible by 4
+ (define_predicate "word_offset_memref_operand"
+   (and (match_operand 0 "memory_operand")
+        (match_test "GET_CODE (XEXP (op, 0)) != PLUS
+                   || ! REG_P (XEXP (XEXP (op, 0), 0))
+                   || GET_CODE (XEXP (XEXP (op, 0), 1)) != CONST_INT
+                   || INTVAL (XEXP (XEXP (op, 0), 1)) % 4 == 0")))
+
   ;; Return 1 if the operand is either a non-special register or can be 
used
   ;; as the operand of a `mode' add insn.
   (define_predicate "add_operand"


[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 2408 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: stfiwx for rs6000
  2005-03-26  3:51       ` Geoffrey Keating
@ 2005-03-26  7:40         ` David Edelsohn
  0 siblings, 0 replies; 7+ messages in thread
From: David Edelsohn @ 2005-03-26  7:40 UTC (permalink / raw)
  To: Geoffrey Keating; +Cc: GCC Patches, Andrew Pinski

	We can do it like your proposed conversion of maintain more of the
original C design like:

(define_predicate "word_offset_memref_operand"
  (match_operand 0 "memory_operand)
{
  rtx addr;
  int off = 0;

  addr = XEXP (op, 0);
  if (GET_CODE (addr) == PLUS
      && GET_CODE (XEXP (addr, 0)) == REG
      && GET_CODE (XEXP (addr, 1)) == CONST_INT)
    off = INTVAL (XEXP (addr, 1));

  return (off % 4) == 0;
}

David

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: stfiwx for rs6000
  2005-03-25 19:54 stfiwx for rs6000 Geoffrey Keating
  2005-03-25 20:11 ` David Edelsohn
@ 2005-03-30 18:50 ` Richard Henderson
  1 sibling, 0 replies; 7+ messages in thread
From: Richard Henderson @ 2005-03-30 18:50 UTC (permalink / raw)
  To: Geoffrey Keating; +Cc: gcc-patches

On Fri, Mar 25, 2005 at 11:49:34AM -0800, Geoffrey Keating wrote:
> This patch adds minimal support for the 'stfiwx' instruction to the
> rs6000 backend.  I say 'minimal' because even though it is used, the
> benefit of it is only that 4 bytes are saved on the stack per
> temporary, rather than what you'd really like, which is that it will
> store directory into a variable in memory if that's more efficient.  I
> couldn't work out how to make it store into user memory, after trying
> several possibilities; combine won't do it, and when I tried to just say
> that "this instruction requires a memory operand", reload would fail.

It seems to work for me on Alpha, where I have very similar constraints.
I notice that I use a subreg in the pattern; perhaps that matters?


r~

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2005-03-30 18:48 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-03-25 19:54 stfiwx for rs6000 Geoffrey Keating
2005-03-25 20:11 ` David Edelsohn
2005-03-25 20:16   ` Andrew Pinski
2005-03-25 20:26     ` David Edelsohn
2005-03-26  3:51       ` Geoffrey Keating
2005-03-26  7:40         ` David Edelsohn
2005-03-30 18:50 ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).