diff options
author | Segher Boessenkool <segher@kernel.crashing.org> | 2015-07-23 16:37:57 +0200 |
---|---|---|
committer | Segher Boessenkool <segher@gcc.gnu.org> | 2015-07-23 16:37:57 +0200 |
commit | a34f4f64689e3a109f3091f74af4750c1010e961 (patch) | |
tree | a103141f48cbcaad89dd2e61e71a83d28bd869c8 /gcc | |
parent | d057c8669b2ca758096697826647bdc06f77c336 (diff) | |
download | gcc-a34f4f64689e3a109f3091f74af4750c1010e961.zip gcc-a34f4f64689e3a109f3091f74af4750c1010e961.tar.gz gcc-a34f4f64689e3a109f3091f74af4750c1010e961.tar.bz2 |
re PR target/66217 (PowerPC rotate/shift/mask instructions not optimal)
PR target/66217
* config/rs6000/rs6000-protos.h (rs6000_emit_2insn_and): Change
prototype.
* config/rs6000/rs6000.c (rs6000_emit_dot_insn): New function.
(rs6000_emit_2insn_and): Handle dot forms.
* config/rs6000/rs6000.md (and<mode>3): Adjust.
(*and<mode>3_2insn): Remove TODO. Adjust. Add "type" attr.
(*and<mode>3_2insn_dot, *and<mode>3_2insn_dot2): New.
From-SVN: r226112
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 55 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 56 |
4 files changed, 109 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cc07d76..4097750 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2015-07-23 Segher Boessenkool <segher@kernel.crashing.org> + + PR target/66217 + * config/rs6000/rs6000-protos.h (rs6000_emit_2insn_and): Change + prototype. + * config/rs6000/rs6000.c (rs6000_emit_dot_insn): New function. + (rs6000_emit_2insn_and): Handle dot forms. + * config/rs6000/rs6000.md (and<mode>3): Adjust. + (*and<mode>3_2insn): Remove TODO. Adjust. Add "type" attr. + (*and<mode>3_2insn_dot, *and<mode>3_2insn_dot2): New. + 2015-07-23 Richard Biener <rguenther@suse.de> * generic-match-head.c: Include cgraph.h. diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 30a7128ca..f5d3476 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -77,7 +77,7 @@ extern const char *rs6000_insn_for_and_mask (machine_mode, rtx *, bool); extern const char *rs6000_insn_for_shift_mask (machine_mode, rtx *, bool); extern const char *rs6000_insn_for_insert_mask (machine_mode, rtx *, bool); extern bool rs6000_is_valid_2insn_and (rtx, machine_mode); -extern void rs6000_emit_2insn_and (machine_mode, rtx *, bool, bool); +extern void rs6000_emit_2insn_and (machine_mode, rtx *, bool, int); 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); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 3f0fe4f..2eecde6 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -16735,20 +16735,54 @@ rs6000_is_valid_2insn_and (rtx c, machine_mode mode) return rs6000_is_valid_and_mask (GEN_INT (val + bit3 - bit2), mode); } +/* Emit a potentially record-form instruction, setting DST from SRC. + If DOT is 0, that is all; otherwise, set CCREG to the result of the + signed comparison of DST with zero. If DOT is 1, the generated RTL + doesn't care about the DST result; if DOT is 2, it does. If CCREG + is CR0 do a single dot insn (as a PARALLEL); otherwise, do a SET and + a separate COMPARE. */ + +static void +rs6000_emit_dot_insn (rtx dst, rtx src, int dot, rtx ccreg) +{ + if (dot == 0) + { + emit_move_insn (dst, src); + return; + } + + if (cc_reg_not_cr0_operand (ccreg, CCmode)) + { + emit_move_insn (dst, src); + emit_move_insn (ccreg, gen_rtx_COMPARE (CCmode, dst, const0_rtx)); + return; + } + + rtx ccset = gen_rtx_SET (ccreg, gen_rtx_COMPARE (CCmode, src, const0_rtx)); + if (dot == 1) + { + rtx clobber = gen_rtx_CLOBBER (VOIDmode, dst); + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, ccset, clobber))); + } + else + { + rtx set = gen_rtx_SET (dst, src); + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, ccset, set))); + } +} + /* Emit the two insns to do an AND in mode MODE, with operands OPERANDS. If EXPAND is true, split rotate-and-mask instructions we generate to their constituent parts as well (this is used during expand); if DOT - is true, make the last insn a record-form instruction. */ + is 1, make the last insn a record-form instruction clobbering the + destination GPR and setting the CC reg (from operands[3]); if 2, set + that GPR as well as the CC reg. */ void -rs6000_emit_2insn_and (machine_mode mode, rtx *operands, bool expand, bool dot) +rs6000_emit_2insn_and (machine_mode mode, rtx *operands, bool expand, int dot) { gcc_assert (!(expand && dot)); - /* We do not actually handle record form yet. */ - if (dot) - gcc_unreachable (); - unsigned HOST_WIDE_INT val = INTVAL (operands[2]); /* If it is one stretch of ones, it is DImode; shift left, mask, then @@ -16773,7 +16807,8 @@ rs6000_emit_2insn_and (machine_mode mode, rtx *operands, bool expand, bool dot) rtx tmp = gen_rtx_ASHIFT (mode, operands[1], GEN_INT (shift)); tmp = gen_rtx_AND (mode, tmp, GEN_INT (val << shift)); emit_move_insn (operands[0], tmp); - emit_insn (gen_lshrdi3 (operands[0], operands[0], GEN_INT (shift))); + tmp = gen_rtx_LSHIFTRT (mode, operands[0], GEN_INT (shift)); + rs6000_emit_dot_insn (operands[0], tmp, dot, dot ? operands[3] : 0); } return; } @@ -16799,7 +16834,7 @@ rs6000_emit_2insn_and (machine_mode mode, rtx *operands, bool expand, bool dot) rtx tmp = gen_rtx_AND (mode, operands[1], GEN_INT (mask1)); emit_move_insn (reg, tmp); tmp = gen_rtx_AND (mode, reg, GEN_INT (mask2)); - emit_move_insn (operands[0], tmp); + rs6000_emit_dot_insn (operands[0], tmp, dot, dot ? operands[3] : 0); return; } @@ -16816,7 +16851,7 @@ rs6000_emit_2insn_and (machine_mode mode, rtx *operands, bool expand, bool dot) rtx reg_low = gen_lowpart (SImode, reg); emit_move_insn (reg_low, tmp); tmp = gen_rtx_AND (mode, reg, GEN_INT (mask2)); - emit_move_insn (operands[0], tmp); + rs6000_emit_dot_insn (operands[0], tmp, dot, dot ? operands[3] : 0); return; } @@ -16845,7 +16880,7 @@ rs6000_emit_2insn_and (machine_mode mode, rtx *operands, bool expand, bool dot) emit_move_insn (operands[0], tmp); tmp = gen_rtx_ROTATE (mode, operands[0], GEN_INT (right)); tmp = gen_rtx_AND (mode, tmp, GEN_INT (mask2)); - emit_move_insn (operands[0], tmp); + rs6000_emit_dot_insn (operands[0], tmp, dot, dot ? operands[3] : 0); } } diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 4e64a36..f7fa399 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -2913,7 +2913,7 @@ if (rs6000_is_valid_2insn_and (operands[2], <MODE>mode)) { - rs6000_emit_2insn_and (<MODE>mode, operands, true, false); + rs6000_emit_2insn_and (<MODE>mode, operands, true, 0); DONE; } @@ -3139,7 +3139,6 @@ (set_attr "length" "4,8")]) -; TODO: dots of this (define_insn_and_split "*and<mode>3_2insn" [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r") @@ -3152,10 +3151,59 @@ "&& 1" [(pc)] { - rs6000_emit_2insn_and (<MODE>mode, operands, false, false); + rs6000_emit_2insn_and (<MODE>mode, operands, false, 0); DONE; } - [(set_attr "length" "8")]) + [(set_attr "type" "shift") + (set_attr "length" "8")]) + +(define_insn_and_split "*and<mode>3_2insn_dot" + [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y") + (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r") + (match_operand:GPR 2 "const_int_operand" "n,n")) + (const_int 0))) + (clobber (match_scratch:GPR 0 "=r,r"))] + "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff) + && rs6000_gen_cell_microcode + && rs6000_is_valid_2insn_and (operands[2], <MODE>mode) + && !(rs6000_is_valid_and_mask (operands[2], <MODE>mode) + || (logical_const_operand (operands[2], <MODE>mode) + && rs6000_gen_cell_microcode))" + "#" + "&& reload_completed" + [(pc)] +{ + rs6000_emit_2insn_and (<MODE>mode, operands, false, 1); + DONE; +} + [(set_attr "type" "shift") + (set_attr "dot" "yes") + (set_attr "length" "8,12")]) + +(define_insn_and_split "*and<mode>3_2insn_dot2" + [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y") + (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r") + (match_operand:GPR 2 "const_int_operand" "n,n")) + (const_int 0))) + (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r") + (and:GPR (match_dup 1) + (match_dup 2)))] + "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff) + && rs6000_gen_cell_microcode + && rs6000_is_valid_2insn_and (operands[2], <MODE>mode) + && !(rs6000_is_valid_and_mask (operands[2], <MODE>mode) + || (logical_const_operand (operands[2], <MODE>mode) + && rs6000_gen_cell_microcode))" + "#" + "&& reload_completed" + [(pc)] +{ + rs6000_emit_2insn_and (<MODE>mode, operands, false, 2); + DONE; +} + [(set_attr "type" "shift") + (set_attr "dot" "yes") + (set_attr "length" "8,12")]) (define_expand "<code><mode>3" |