Commit 7fc5cca3 by Segher Boessenkool Committed by Segher Boessenkool

re PR target/66217 (PowerPC rotate/shift/mask instructions not optimal)

	PR target/66217
	* config/rs6000/constraints.md ("S", "T", "t"): Delete.  Update
	"available letters" comment.
	* config/rs6000/predicates.md (mask_operand, mask_operand_wrap,
	mask64_operand, mask64_2_operand, any_mask_operand, and64_2_operand,
	and_2rld_operand):  Delete.
	(and_operand): Adjust.
	(rotate_mask_operator): New.
	* config/rs6000/rs6000-protos.h (build_mask64_2_operands,
	includes_lshift_p, includes_rshift_p, includes_rldic_lshift_p,
	includes_rldicr_lshift_p, insvdi_rshift_rlwimi_p, extract_MB,
	extract_ME): Delete.
	(rs6000_is_valid_mask, rs6000_is_valid_and_mask,
	rs6000_is_valid_shift_mask, rs6000_is_valid_insert_mask,
	rs6000_insn_for_and_mask, rs6000_insn_for_shift_mask,
	rs6000_insn_for_insert_mask, rs6000_is_valid_2insn_and,
	rs6000_emit_2insn_and): New.
	* config/rs6000/rs6000.c (num_insns_constant): Adjust.
	(build_mask64_2_operands, includes_lshift_p, includes_rshift_p,
	includes_rldic_lshift_p, includes_rldicr_lshift_p,
	insvdi_rshift_rlwimi_p, extract_MB, extract_ME): Delete.
	(rs6000_is_valid_mask, rs6000_is_valid_and_mask,
	rs6000_insn_for_and_mask, rs6000_is_valid_shift_mask,
	s6000_insn_for_shift_mask, rs6000_is_valid_insert_mask,
	rs6000_insn_for_insert_mask, rs6000_is_valid_2insn_and,
	rs6000_emit_2insn_and): New.
	(print_operand) <'b', 'B', 'm', 'M', 's', 'S', 'W'>: Delete.
	(rs6000_rtx_costs) <CONST_INT>: Delete mask_operand and mask64_operand
	handling.
	<NOT>: Don't fall through to next case.
	<AND>: Handle the various rotate-and-mask cases directly.
	<IOR>: Always cost as one insn.
	* config/rs6000/rs6000.md (splitter for bswap:SI): Adjust.
	(and<mode>3): Adjust expander for the new patterns.
	(and<mode>3_imm, and<mode>3_imm_dot, and<mode>3_imm_dot2,
	and<mode>3_imm_mask_dot, and<mode>3_imm_mask_dot2): Adjust condition.
	(*and<mode>3_imm_dot_shifted): New.
	(*and<mode>3_mask): Delete, rewrite as ...
	(and<mode>3_mask): ... New.
	(*and<mode>3_mask_dot, *and<mode>3_mask_dot): Rewrite.
	(andsi3_internal0_nomc): Delete.
	(*andsi3_internal6): Delete.
	(*and<mode>3_2insn): New.
	(insv, insvsi_internal, *insvsi_internal1, *insvsi_internal2,
	*insvsi_internal3, *insvsi_internal4, *insvsi_internal5,
	*insvsi_internal6, insvdi_internal, *insvdi_internal2,
	*insvdi_internal3): Delete.
	(*rotl<mode>3_mask, *rotl<mode>3_mask_dot, *rotl<mode>3_mask_dot2,
	*rotl<mode>3_insert, *rotl<mode>3_insert_2, *rotl<mode>3_insert_3,
	*rotl<mode>3_insert_4, two splitters for multi-precision shifts,
	*ior<mode>_mask): New.
	(extzv, extzvdi_internal, *extzvdi_internal1, *extzvdi_internal2,
	*rotlsi3_mask, *rotlsi3_mask_dot, *rotlsi3_mask_dot2,
	*ashlsi3_imm_mask, *ashlsi3_imm_mask_dot, *ashlsi3_imm_mask_dot2,
	*lshrsi3_imm_mask, *lshrsi3_imm_mask_dot, *lshrsi3_imm_mask_dot2):
	Delete.
	(ashr<mode>3): Delete expander.
	(*ashr<mode>3): Rename to ...
	(ashr<mode>3): ... This.
	(ashrdi3_no_power, *ashrdisi3_noppc64be): Delete.
	(*rotldi3_internal4, *rotldi3_internal5 and split,
	*rotldi3_internal6 and split, *ashldi3_internal4, ashldi3_internal5
	and split, *ashldi3_internal6 and split, *ashldi3_internal7,
	ashldi3_internal8 and split, *ashldi3_internal9 and split): Delete.
	(*anddi3_2rld, *anddi3_2rld_dot, *anddi3_2rld_dot2): Delete.
	(splitter for loading a mask): Adjust.
	* doc/md.texi (Machine Constraints): Remove q, S, T, t constraints.

From-SVN: r226005
parent f3e9a059
2015-07-20 Segher Boessenkool <segher@kernel.crashing.org>
PR target/66217
* config/rs6000/constraints.md ("S", "T", "t"): Delete. Update
"available letters" comment.
* config/rs6000/predicates.md (mask_operand, mask_operand_wrap,
mask64_operand, mask64_2_operand, any_mask_operand, and64_2_operand,
and_2rld_operand): Delete.
(and_operand): Adjust.
(rotate_mask_operator): New.
* config/rs6000/rs6000-protos.h (build_mask64_2_operands,
includes_lshift_p, includes_rshift_p, includes_rldic_lshift_p,
includes_rldicr_lshift_p, insvdi_rshift_rlwimi_p, extract_MB,
extract_ME): Delete.
(rs6000_is_valid_mask, rs6000_is_valid_and_mask,
rs6000_is_valid_shift_mask, rs6000_is_valid_insert_mask,
rs6000_insn_for_and_mask, rs6000_insn_for_shift_mask,
rs6000_insn_for_insert_mask, rs6000_is_valid_2insn_and,
rs6000_emit_2insn_and): New.
* config/rs6000/rs6000.c (num_insns_constant): Adjust.
(build_mask64_2_operands, includes_lshift_p, includes_rshift_p,
includes_rldic_lshift_p, includes_rldicr_lshift_p,
insvdi_rshift_rlwimi_p, extract_MB, extract_ME): Delete.
(rs6000_is_valid_mask, rs6000_is_valid_and_mask,
rs6000_insn_for_and_mask, rs6000_is_valid_shift_mask,
s6000_insn_for_shift_mask, rs6000_is_valid_insert_mask,
rs6000_insn_for_insert_mask, rs6000_is_valid_2insn_and,
rs6000_emit_2insn_and): New.
(print_operand) <'b', 'B', 'm', 'M', 's', 'S', 'W'>: Delete.
(rs6000_rtx_costs) <CONST_INT>: Delete mask_operand and mask64_operand
handling.
<NOT>: Don't fall through to next case.
<AND>: Handle the various rotate-and-mask cases directly.
<IOR>: Always cost as one insn.
* config/rs6000/rs6000.md (splitter for bswap:SI): Adjust.
(and<mode>3): Adjust expander for the new patterns.
(and<mode>3_imm, and<mode>3_imm_dot, and<mode>3_imm_dot2,
and<mode>3_imm_mask_dot, and<mode>3_imm_mask_dot2): Adjust condition.
(*and<mode>3_imm_dot_shifted): New.
(*and<mode>3_mask): Delete, rewrite as ...
(and<mode>3_mask): ... New.
(*and<mode>3_mask_dot, *and<mode>3_mask_dot): Rewrite.
(andsi3_internal0_nomc): Delete.
(*andsi3_internal6): Delete.
(*and<mode>3_2insn): New.
(insv, insvsi_internal, *insvsi_internal1, *insvsi_internal2,
*insvsi_internal3, *insvsi_internal4, *insvsi_internal5,
*insvsi_internal6, insvdi_internal, *insvdi_internal2,
*insvdi_internal3): Delete.
(*rotl<mode>3_mask, *rotl<mode>3_mask_dot, *rotl<mode>3_mask_dot2,
*rotl<mode>3_insert, *rotl<mode>3_insert_2, *rotl<mode>3_insert_3,
*rotl<mode>3_insert_4, two splitters for multi-precision shifts,
*ior<mode>_mask): New.
(extzv, extzvdi_internal, *extzvdi_internal1, *extzvdi_internal2,
*rotlsi3_mask, *rotlsi3_mask_dot, *rotlsi3_mask_dot2,
*ashlsi3_imm_mask, *ashlsi3_imm_mask_dot, *ashlsi3_imm_mask_dot2,
*lshrsi3_imm_mask, *lshrsi3_imm_mask_dot, *lshrsi3_imm_mask_dot2):
Delete.
(ashr<mode>3): Delete expander.
(*ashr<mode>3): Rename to ...
(ashr<mode>3): ... This.
(ashrdi3_no_power, *ashrdisi3_noppc64be): Delete.
(*rotldi3_internal4, *rotldi3_internal5 and split,
*rotldi3_internal6 and split, *ashldi3_internal4, ashldi3_internal5
and split, *ashldi3_internal6 and split, *ashldi3_internal7,
ashldi3_internal8 and split, *ashldi3_internal9 and split): Delete.
(*anddi3_2rld, *anddi3_2rld_dot, *anddi3_2rld_dot2): Delete.
(splitter for loading a mask): Adjust.
* doc/md.texi (Machine Constraints): Remove q, S, T, t constraints.
2015-07-20 Marek Polacek <polacek@redhat.com>
* genemit.c (print_code, gen_exp, gen_insn, gen_expand, gen_split,
......
......@@ -17,7 +17,7 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
;; Available constraint letters: "e", "k", "q", "u", "A", "B", "C", "D"
;; Available constraint letters: e k q t u A B C D S T
;; Register constraints
......@@ -230,29 +230,11 @@ usually better to use @samp{m} or @samp{es} in @code{asm} statements)"
;; General constraints
(define_constraint "S"
"Constant that can be placed into a 64-bit mask operand"
(and (match_test "TARGET_POWERPC64")
(match_operand 0 "mask64_operand")))
(define_constraint "T"
"Constant that can be placed into a 32-bit mask operand"
(match_operand 0 "mask_operand"))
(define_constraint "U"
"V.4 small data reference"
(and (match_test "DEFAULT_ABI == ABI_V4")
(match_test "small_data_operand (op, mode)")))
(define_constraint "t"
"AND masks that can be performed by two rldic{l,r} insns
(but excluding those that could match other constraints of anddi3)"
(and (and (and (match_operand 0 "mask64_2_operand")
(match_test "(fixed_regs[CR0_REGNO]
|| !logical_operand (op, DImode))"))
(not (match_operand 0 "mask_operand")))
(not (match_operand 0 "mask64_operand"))))
(define_constraint "W"
"vector constant that does not require memory"
(match_operand 0 "easy_vector_constant"))
......
......@@ -751,178 +751,14 @@
(and (not (match_operand 0 "logical_operand"))
(match_operand 0 "reg_or_logical_cint_operand"))))
;; Return 1 if op is a constant that can be encoded in a 32-bit mask,
;; suitable for use with rlwinm (no more than two 1->0 or 0->1
;; transitions). Reject all ones and all zeros, since these should have
;; been optimized away and confuse the making of MB and ME.
(define_predicate "mask_operand"
(match_code "const_int")
{
unsigned HOST_WIDE_INT c, lsb;
c = INTVAL (op);
if (TARGET_POWERPC64)
{
/* Fail if the mask is not 32-bit. */
if (mode == DImode && (c & ~(unsigned HOST_WIDE_INT) 0xffffffff) != 0)
return 0;
/* Fail if the mask wraps around because the upper 32-bits of the
mask will all be 1s, contrary to GCC's internal view. */
if ((c & 0x80000001) == 0x80000001)
return 0;
}
/* We don't change the number of transitions by inverting,
so make sure we start with the LS bit zero. */
if (c & 1)
c = ~c;
/* Reject all zeros or all ones. */
if (c == 0)
return 0;
/* Find the first transition. */
lsb = c & -c;
/* Invert to look for a second transition. */
c = ~c;
/* Erase first transition. */
c &= -lsb;
/* Find the second transition (if any). */
lsb = c & -c;
/* Match if all the bits above are 1's (or c is zero). */
return c == -lsb;
})
;; Return 1 for the PowerPC64 rlwinm corner case.
(define_predicate "mask_operand_wrap"
(match_code "const_int")
{
unsigned HOST_WIDE_INT c, lsb;
c = INTVAL (op);
if ((c & 0x80000001) != 0x80000001)
return 0;
c = ~c;
if (c == 0)
return 0;
lsb = c & -c;
c = ~c;
c &= -lsb;
lsb = c & -c;
return c == -lsb;
})
;; Return 1 if the operand is a constant that is a PowerPC64 mask
;; suitable for use with rldicl or rldicr (no more than one 1->0 or 0->1
;; transition). Reject all zeros, since zero should have been
;; optimized away and confuses the making of MB and ME.
(define_predicate "mask64_operand"
(match_code "const_int")
{
unsigned HOST_WIDE_INT c, lsb;
c = INTVAL (op);
/* Reject all zeros. */
if (c == 0)
return 0;
/* We don't change the number of transitions by inverting,
so make sure we start with the LS bit zero. */
if (c & 1)
c = ~c;
/* Find the first transition. */
lsb = c & -c;
/* Match if all the bits above are 1's (or c is zero). */
return c == -lsb;
})
;; Like mask64_operand, but allow up to three transitions. This
;; predicate is used by insn patterns that generate two rldicl or
;; rldicr machine insns.
(define_predicate "mask64_2_operand"
(match_code "const_int")
{
unsigned HOST_WIDE_INT c, lsb;
c = INTVAL (op);
/* Disallow all zeros. */
if (c == 0)
return 0;
/* We don't change the number of transitions by inverting,
so make sure we start with the LS bit zero. */
if (c & 1)
c = ~c;
/* Find the first transition. */
lsb = c & -c;
/* Invert to look for a second transition. */
c = ~c;
/* Erase first transition. */
c &= -lsb;
/* Find the second transition. */
lsb = c & -c;
/* Invert to look for a third transition. */
c = ~c;
/* Erase second transition. */
c &= -lsb;
/* Find the third transition (if any). */
lsb = c & -c;
/* Match if all the bits above are 1's (or c is zero). */
return c == -lsb;
})
;; Match a mask_operand or a mask64_operand.
(define_predicate "any_mask_operand"
(ior (match_operand 0 "mask_operand")
(and (match_test "TARGET_POWERPC64 && mode == DImode")
(match_operand 0 "mask64_operand"))))
;; Like and_operand, but also match constants that can be implemented
;; with two rldicl or rldicr insns.
(define_predicate "and64_2_operand"
(ior (match_operand 0 "mask64_2_operand")
(if_then_else (match_test "fixed_regs[CR0_REGNO]")
(match_operand 0 "gpc_reg_operand")
(match_operand 0 "logical_operand"))))
;; Return 1 if the operand is either a non-special register or a
;; constant that can be used as the operand of a logical AND.
(define_predicate "and_operand"
(ior (match_operand 0 "mask_operand")
(and (match_test "TARGET_POWERPC64 && mode == DImode")
(match_operand 0 "mask64_operand"))
(ior (match_test "rs6000_is_valid_and_mask (op, mode)")
(if_then_else (match_test "fixed_regs[CR0_REGNO]")
(match_operand 0 "gpc_reg_operand")
(match_operand 0 "logical_operand"))))
;; Return 1 if the operand is a constant that can be used as the operand
;; of a logical AND, implemented with two rld* insns, and it cannot be done
;; using just one insn.
(define_predicate "and_2rld_operand"
(and (match_operand 0 "and64_2_operand")
(not (match_operand 0 "and_operand"))))
;; Return 1 if the operand is either a logical operand or a short cint operand.
(define_predicate "scc_eq_operand"
(ior (match_operand 0 "logical_operand")
......@@ -1128,6 +964,10 @@
return nonimmediate_operand (op, mode);
})
;; Return true if operand is an operator used in rotate-and-mask instructions.
(define_predicate "rotate_mask_operator"
(match_code "rotate,ashift,lshiftrt"))
;; Return true if operand is boolean operator.
(define_predicate "boolean_operator"
(match_code "and,ior,xor"))
......
......@@ -66,15 +66,18 @@ extern void altivec_expand_stvex_be (rtx, rtx, machine_mode, unsigned);
extern void rs6000_expand_extract_even (rtx, rtx, rtx);
extern void rs6000_expand_interleave (rtx, rtx, rtx, bool);
extern void rs6000_scale_v2df (rtx, rtx, int);
extern void build_mask64_2_operands (rtx, rtx *);
extern int expand_block_clear (rtx[]);
extern int expand_block_move (rtx[]);
extern const char * rs6000_output_load_multiple (rtx[]);
extern int includes_lshift_p (rtx, rtx);
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 bool rs6000_is_valid_mask (rtx, int *, int *, machine_mode);
extern bool rs6000_is_valid_and_mask (rtx, machine_mode);
extern bool rs6000_is_valid_shift_mask (rtx, rtx, machine_mode);
extern bool rs6000_is_valid_insert_mask (rtx, rtx, machine_mode);
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 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);
......@@ -102,8 +105,6 @@ extern void paired_expand_vector_move (rtx operands[]);
extern int ccr_bit (rtx, int);
extern int extract_MB (rtx);
extern int extract_ME (rtx);
extern void rs6000_output_function_entry (FILE *, const char *);
extern void print_operand (FILE *, rtx, int);
extern void print_operand_address (FILE *, rtx);
......
......@@ -3173,9 +3173,6 @@ instructions.
@item h
@samp{MQ}, @samp{CTR}, or @samp{LINK} register
@item q
@samp{MQ} register
@item c
@samp{CTR} register
......@@ -3268,18 +3265,9 @@ AIX TOC entry
Address operand that is an indexed or indirect from a register (@samp{p} is
preferable for @code{asm} statements)
@item S
Constant suitable as a 64-bit mask operand
@item T
Constant suitable as a 32-bit mask operand
@item U
System V Release 4 small data area reference
@item t
AND masks that can be performed by two rldic@{l, r@} instructions
@item W
Vector constant that does not require memory
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment