This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, committed] PowerPC insvdi and extendsfdf2 improvements
- From: David Edelsohn <dje at watson dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 23 Jun 2004 17:29:57 -0400
- Subject: [PATCH, committed] PowerPC insvdi and extendsfdf2 improvements
The following patch implements two new insv combiner patterns to
use the PowerPC rlwimi instruction in 64-bit mode when insv is operating
on the lower 32-bits of the doubleword. The 32-bit PowerPC rlwimi
instruction can specify both the beginning and ending mask locations,
which makes it more powerful than the 64-bit instruction.
The patch also converts extendsfdf2 to a define_insn_and_split
pattern based on a similar pattern created by Richard Sandiford for Mips
that removed redundant slls. The change helps a little in reducing
generation of unnecessary fmr instructions and provides more accurate
scheduling information, but the extra fmrs still exist.
Finally, the patch replaces the rs6000 function to enable the DFA
pipeline interface with the standard GCC hook.
Bootstrapped and tested on powerpc-ibm-aix5.1.0.0 and
powerpc64-linux with no regressions.
David
* config/rs6000/rs6000.c (rs6000_use_dfa_pipeline_interface): Delete.
(TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE): Redefine a hook_int_void_1.
(insvdi_rshift_rlwimi_p): New function.
* config/rs6000/rs6000.md (insvdi_internal2/3): New patterns.
(extendsfdf2): Convert to define_insn_and_split.
* config/rs6000/rs6000-protos.h (insvdi_rshift_rlwimi_p): Prototype.
Index: rs6000-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000-protos.h,v
retrieving revision 1.82
diff -c -p -r1.82 rs6000-protos.h
*** rs6000-protos.h 22 Jun 2004 18:12:34 -0000 1.82
--- rs6000-protos.h 23 Jun 2004 21:12:07 -0000
*************** extern int includes_lshift_p (rtx, rtx);
*** 101,106 ****
--- 101,107 ----
extern int includes_rshift_p (rtx, rtx);
extern int includes_rldic_lshift_p (rtx, rtx);
extern int includes_rldicr_lshift_p (rtx, rtx);
+ extern int insvdi_rshift_rlwimi_p (rtx, rtx, rtx);
extern int registers_ok_for_quad_peep (rtx, rtx);
extern int mems_ok_for_quad_peep (rtx, rtx);
extern bool gpr_or_gpr_p (rtx, rtx);
Index: rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.652
diff -c -p -r1.652 rs6000.c
*** rs6000.c 22 Jun 2004 18:12:35 -0000 1.652
--- rs6000.c 23 Jun 2004 21:12:08 -0000
*************** static void rs6000_xcoff_file_end (void)
*** 353,359 ****
#if TARGET_MACHO
static bool rs6000_binds_local_p (tree);
#endif
- static int rs6000_use_dfa_pipeline_interface (void);
static int rs6000_variable_issue (FILE *, int, rtx, int);
static bool rs6000_rtx_costs (rtx, int, int, int *);
static int rs6000_adjust_cost (rtx, rtx, rtx, int);
--- 353,358 ----
*************** static const char alt_reg_names[][8] =
*** 570,576 ****
#define TARGET_ASM_FUNCTION_EPILOGUE rs6000_output_function_epilogue
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
! #define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE rs6000_use_dfa_pipeline_interface
#undef TARGET_SCHED_VARIABLE_ISSUE
#define TARGET_SCHED_VARIABLE_ISSUE rs6000_variable_issue
--- 569,575 ----
#define TARGET_ASM_FUNCTION_EPILOGUE rs6000_output_function_epilogue
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
! #define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
#undef TARGET_SCHED_VARIABLE_ISSUE
#define TARGET_SCHED_VARIABLE_ISSUE rs6000_variable_issue
*************** includes_rldicr_lshift_p (rtx shiftop, r
*** 8825,8830 ****
--- 8824,8849 ----
return 0;
}
+ /* Return 1 if operands will generate a valid arguments to rlwimi
+ instruction for insert with right shift in 64-bit mode. The mask may
+ not start on the first bit or stop on the last bit because wrap-around
+ effects of instruction do not correspond to semantics of RTL insn. */
+
+ int
+ insvdi_rshift_rlwimi_p (rtx sizeop, rtx startop, rtx shiftop)
+ {
+ if (INTVAL (startop) < 64
+ && INTVAL (startop) > 32
+ && (INTVAL (sizeop) + INTVAL (startop) < 64)
+ && (INTVAL (sizeop) + INTVAL (startop) > 33)
+ && (INTVAL (sizeop) + INTVAL (startop) + INTVAL (shiftop) < 96)
+ && (INTVAL (sizeop) + INTVAL (startop) + INTVAL (shiftop) >= 64)
+ && (64 - (INTVAL (shiftop) & 63)) >= INTVAL (sizeop))
+ return 1;
+
+ return 0;
+ }
+
/* Return 1 if REGNO (reg1) == REGNO (reg2) - 1 making them candidates
for lfq and stfq insns iff the registers are hard registers. */
*************** output_function_profiler (FILE *file, in
*** 14179,14190 ****
}
- static int
- rs6000_use_dfa_pipeline_interface (void)
- {
- return 1;
- }
-
/* Power4 load update and store update instructions are cracked into a
load or store and an integer insn which are executed in the same cycle.
Branches have their own dispatch slot which does not count against the
--- 14198,14203 ----
Index: rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.307
diff -c -p -r1.307 rs6000.md
*** rs6000.md 23 Jun 2004 05:54:21 -0000 1.307
--- rs6000.md 23 Jun 2004 21:12:08 -0000
***************
*** 3090,3095 ****
--- 3090,3135 ----
return \"rldimi %0,%3,%H1,%H2\";
}")
+ (define_insn "*insvdi_internal2"
+ [(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
+ (match_operand:SI 1 "const_int_operand" "i")
+ (match_operand:SI 2 "const_int_operand" "i"))
+ (ashiftrt:DI (match_operand:DI 3 "gpc_reg_operand" "r")
+ (match_operand:SI 4 "const_int_operand" "i")))]
+ "TARGET_POWERPC64
+ && insvdi_rshift_rlwimi_p (operands[1], operands[2], operands[4])"
+ "*
+ {
+ int shift = INTVAL (operands[4]) & 63;
+ int start = (INTVAL (operands[2]) & 63) - 32;
+ int size = INTVAL (operands[1]) & 63;
+
+ operands[4] = GEN_INT (64 - shift - start - size);
+ operands[2] = GEN_INT (start);
+ operands[1] = GEN_INT (start + size - 1);
+ return \"rlwimi %0,%3,%h4,%h2,%h1\";
+ }")
+
+ (define_insn "*insvdi_internal3"
+ [(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
+ (match_operand:SI 1 "const_int_operand" "i")
+ (match_operand:SI 2 "const_int_operand" "i"))
+ (lshiftrt:DI (match_operand:DI 3 "gpc_reg_operand" "r")
+ (match_operand:SI 4 "const_int_operand" "i")))]
+ "TARGET_POWERPC64
+ && insvdi_rshift_rlwimi_p (operands[1], operands[2], operands[4])"
+ "*
+ {
+ int shift = INTVAL (operands[4]) & 63;
+ int start = (INTVAL (operands[2]) & 63) - 32;
+ int size = INTVAL (operands[1]) & 63;
+
+ operands[4] = GEN_INT (64 - shift - start - size);
+ operands[2] = GEN_INT (start);
+ operands[1] = GEN_INT (start + size - 1);
+ return \"rlwimi %0,%3,%h4,%h2,%h1\";
+ }")
+
(define_expand "extzv"
[(set (match_operand 0 "gpc_reg_operand" "")
(zero_extract (match_operand 1 "gpc_reg_operand" "")
***************
*** 4411,4427 ****
;; this case, we just lose precision that we would have otherwise gotten but
;; is not guaranteed. Perhaps this should be tightened up at some point.
! (define_insn "extendsfdf2"
! [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
! (float_extend:DF (match_operand:SF 1 "gpc_reg_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_FPRS"
! "*
{
! if (REGNO (operands[0]) == REGNO (operands[1]))
! return \"\";
! else
! return \"fmr %0,%1\";
! }"
[(set_attr "type" "fp")])
(define_insn "truncdfsf2"
--- 4451,4469 ----
;; this case, we just lose precision that we would have otherwise gotten but
;; is not guaranteed. Perhaps this should be tightened up at some point.
! (define_insn_and_split "extendsfdf2"
! [(set (match_operand:DF 0 "gpc_reg_operand" "=f,?f")
! (float_extend:DF (match_operand:SF 1 "gpc_reg_operand" "0,f")))]
"TARGET_HARD_FLOAT && TARGET_FPRS"
! "@
! #
! fmr %0,%1"
! "&& reload_completed && REGNO (operands[0]) == REGNO (operands[1])"
! [(const_int 0)]
{
! emit_note (NOTE_INSN_DELETED);
! DONE;
! }
[(set_attr "type" "fp")])
(define_insn "truncdfsf2"