* [PATCH] rs6000: Add dot forms of and<mode>3_2insn
@ 2015-07-23 14:31 Segher Boessenkool
2015-07-23 14:45 ` David Edelsohn
0 siblings, 1 reply; 2+ messages in thread
From: Segher Boessenkool @ 2015-07-23 14:31 UTC (permalink / raw)
To: gcc-patches; +Cc: dje.gcc, Segher Boessenkool
This does one of the TODOs I added: it adds dot forms of the ANDs done
with two machine insns. It uses a new helper function (rs6000_emit_dot_insn)
that probably can be used more often; it is quite general in any case.
Bootstrapped and tested on powerpc64-linux, using {-m32,-m32/-mpowerpc64,
-m64,-m64/-mlra}; no regressions. Code size on both 32-bit and 64-bit
improves.
Is this okay for trunk?
Segher
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.
---
gcc/config/rs6000/rs6000-protos.h | 2 +-
gcc/config/rs6000/rs6000.c | 55 +++++++++++++++++++++++++++++++-------
gcc/config/rs6000/rs6000.md | 56 ++++++++++++++++++++++++++++++++++++---
3 files changed, 98 insertions(+), 15 deletions(-)
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 30a7128..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 1fb1f32..fe8ce71 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -16736,20 +16736,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
@@ -16774,7 +16808,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;
}
@@ -16800,7 +16835,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;
}
@@ -16817,7 +16852,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;
}
@@ -16846,7 +16881,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);
}
}
\f
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index d37a4b5..997675a 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -2913,7 +2913,7 @@ (define_expand "and<mode>3"
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 @@ (define_insn_and_split "*and<mode>3_mask_dot2"
(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 @@ (define_insn_and_split "*and<mode>3_2insn"
"&& 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"
--
1.8.1.4
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] rs6000: Add dot forms of and<mode>3_2insn
2015-07-23 14:31 [PATCH] rs6000: Add dot forms of and<mode>3_2insn Segher Boessenkool
@ 2015-07-23 14:45 ` David Edelsohn
0 siblings, 0 replies; 2+ messages in thread
From: David Edelsohn @ 2015-07-23 14:45 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: GCC Patches
On Thu, Jul 23, 2015 at 10:21 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> This does one of the TODOs I added: it adds dot forms of the ANDs done
> with two machine insns. It uses a new helper function (rs6000_emit_dot_insn)
> that probably can be used more often; it is quite general in any case.
>
> Bootstrapped and tested on powerpc64-linux, using {-m32,-m32/-mpowerpc64,
> -m64,-m64/-mlra}; no regressions. Code size on both 32-bit and 64-bit
> improves.
>
> Is this okay for trunk?
>
>
> Segher
>
>
> 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.
Okay.
Thanks, David
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2015-07-23 14:25 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-23 14:31 [PATCH] rs6000: Add dot forms of and<mode>3_2insn Segher Boessenkool
2015-07-23 14:45 ` David Edelsohn
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).