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
This commit is contained in:
parent
d057c8669b
commit
a34f4f6468
4 changed files with 109 additions and 15 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Reference in a new issue