This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Still can't make stfiwx actually store directly, but...
- From: Richard Henderson <rth at twiddle dot net>
- To: gkeating at apple dot com
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Tue, 17 May 2005 18:37:31 -0700
- Subject: Re: Still can't make stfiwx actually store directly, but...
I've tested this on all of exactly one test case. With -O2,
fctiwz 1,1
stwu 1,-16(1)
stfd 1,8(1)
lwz 10,12(1)
addi 1,1,16
stw 10,0(3)
blr
With -O2 -mcpu=G5,
stwu 1,-16(1)
fctiwz 0,1
stfiwx 0,0,3
addi 1,1,16
blr
I assume I've missed something that's still allocating a
stack slot for this.
r~
Index: config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.367
diff -u -p -r1.367 rs6000.md
--- config/rs6000/rs6000.md 9 May 2005 22:04:48 -0000 1.367
+++ config/rs6000/rs6000.md 18 May 2005 01:30:58 -0000
@@ -5332,72 +5332,24 @@
; In the TARGET_PPC_GFXOPT case, this could and probably should
; take a memory destination; but actually making this work is hard.
(define_expand "fix_truncdfsi2"
- [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
- (fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))
- (clobber (match_dup 2))
- (clobber (match_dup 3))])]
+ [(set (match_operand:SI 0 "gpc_reg_operand" "")
+ (fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))]
"(TARGET_POWER2 || TARGET_POWERPC)
&& TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
- "
{
+ rtx tmp;
+
if (TARGET_E500_DOUBLE)
{
- emit_insn (gen_spe_fix_truncdfsi2 (operands[0], operands[1]));
- 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]);
+ emit_insn (gen_spe_fix_truncdfsi2 (operands[0], operands[1]));
DONE;
}
- operands[3] = assign_stack_temp (DImode, GET_MODE_SIZE (DImode), 0);
-}")
-
-(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"
- "#"
- "&& (!no_new_pseudos || offsettable_nonstrict_memref_p (operands[3]))"
- [(pc)]
- "
-{
- rtx lowword;
- gcc_assert (MEM_P (operands[3]));
- lowword = adjust_address (operands[3], SImode, WORDS_BIG_ENDIAN ? 4 : 0);
-
- emit_insn (gen_fctiwz (operands[2], operands[1]));
- emit_move_insn (operands[3], operands[2]);
- emit_move_insn (operands[0], 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]));
+ tmp = gen_reg_rtx (DImode);
+ emit_insn (gen_fctiwz (tmp, operands[1]));
+ emit_move_insn (operands[0], gen_lowpart (SImode, tmp));
DONE;
-}"
- [(set_attr "length" "16")])
+})
; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ))
; rather than (set (subreg:SI (reg)) (fix:SI ...))
@@ -5414,12 +5366,34 @@
; 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))]
+ (unspec:SI [(match_operand:DI 1 "gpc_reg_operand" "f")]
+ UNSPEC_STFIWX))]
"TARGET_PPC_GFXOPT"
"stfiwx %1,%y0"
[(set_attr "type" "fpstore")])
+; A pattern to allow combine to figure out when we're ultimately going to
+; be storing the value to memory. In this case we want to use stfiwx.
+; ??? The BYTES_BIG_ENDIAN test is due to the subreg offset. We don't
+; appear to have any way to recognize this sort of thing generically.
+(define_insn_and_split "*stfiwx_be"
+ [(set (match_operand:SI 0 "memory_operand" "=Z")
+ (subreg:SI
+ (unspec:DI [(fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))]
+ UNSPEC_FCTIWZ)
+ 4))
+ (clobber (match_scratch:DI 2 "=f"))]
+ "TARGET_PPC_GFXOPT && BYTES_BIG_ENDIAN"
+ "#"
+ "&& (!no_new_pseudos || reload_completed)"
+ [(const_int 0)]
+{
+ rtx tmp = reload_completed ? operands[2] : gen_reg_rtx (DImode);
+ emit_insn (gen_fctiwz (tmp, operands[1]));
+ emit_insn (gen_stfiwx (operands[0], tmp));
+ DONE;
+})
+
(define_expand "floatsisf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
(float:SF (match_operand:SI 1 "gpc_reg_operand" "")))]