Commit bfe51f42 by Alan Modra Committed by Alan Modra

re PR target/61098 (Poor code setting count register for large loops)

	PR target/61098
	* config/rs6000/rs6000.c (rs6000_emit_set_const): Remove unneeded
	params and return a bool.  Remove dead code.  Update comment.
	Assert we have a const_int source.  Remove bogus code from
	32-bit HWI days.  Move !TARGET_POWERPC64 handling, and correct
	handling of constants > 2G and reg_equal note, from..
	(rs6000_emit_set_long_const): ..here.  Remove unneeded param and
	return value.  Update comment.  If we can, use a new pseudo
	for intermediate calculations.
	* config/rs6000/rs6000-protos.h (rs6000_emit_set_const): Update
	prototype.
	* config/rs6000/rs6000.md (movsi_internal1_single+1): Update
	call to rs6000_emit_set_const in splitter.
	(movdi_internal64+2, +3): Likewise.

From-SVN: r210932
parent a9243bfc
2014-05-26 Alan Modra <amodra@gmail.com>
PR target/61098
* config/rs6000/rs6000.c (rs6000_emit_set_const): Remove unneeded
params and return a bool. Remove dead code. Update comment.
Assert we have a const_int source. Remove bogus code from
32-bit HWI days. Move !TARGET_POWERPC64 handling, and correct
handling of constants > 2G and reg_equal note, from..
(rs6000_emit_set_long_const): ..here. Remove unneeded param and
return value. Update comment. If we can, use a new pseudo
for intermediate calculations.
* config/rs6000/rs6000-protos.h (rs6000_emit_set_const): Update
prototype.
* config/rs6000/rs6000.md (movsi_internal1_single+1): Update
call to rs6000_emit_set_const in splitter.
(movdi_internal64+2, +3): Likewise.
2014-05-26 Richard Biener <rguenther@suse.de> 2014-05-26 Richard Biener <rguenther@suse.de>
* system.h: Define __STDC_FORMAT_MACROS before * system.h: Define __STDC_FORMAT_MACROS before
......
...@@ -114,7 +114,7 @@ extern void rs6000_emit_cbranch (enum machine_mode, rtx[]); ...@@ -114,7 +114,7 @@ extern void rs6000_emit_cbranch (enum machine_mode, rtx[]);
extern char * output_cbranch (rtx, const char *, int, rtx); extern char * output_cbranch (rtx, const char *, int, rtx);
extern char * output_e500_flip_gt_bit (rtx, rtx); extern char * output_e500_flip_gt_bit (rtx, rtx);
extern const char * output_probe_stack_range (rtx, rtx); extern const char * output_probe_stack_range (rtx, rtx);
extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int); extern bool rs6000_emit_set_const (rtx, rtx);
extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx); extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx);
extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx); extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx);
extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx); extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx);
......
...@@ -1068,7 +1068,7 @@ static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *); ...@@ -1068,7 +1068,7 @@ static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *); static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *); static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *);
static tree rs6000_builtin_vectorized_libmass (tree, tree, tree); static tree rs6000_builtin_vectorized_libmass (tree, tree, tree);
static rtx rs6000_emit_set_long_const (rtx, HOST_WIDE_INT, HOST_WIDE_INT); static void rs6000_emit_set_long_const (rtx, HOST_WIDE_INT);
static int rs6000_memory_move_cost (enum machine_mode, reg_class_t, bool); static int rs6000_memory_move_cost (enum machine_mode, reg_class_t, bool);
static bool rs6000_debug_rtx_costs (rtx, int, int, int, int *, bool); static bool rs6000_debug_rtx_costs (rtx, int, int, int, int *, bool);
static int rs6000_debug_address_cost (rtx, enum machine_mode, addr_space_t, static int rs6000_debug_address_cost (rtx, enum machine_mode, addr_space_t,
...@@ -7849,53 +7849,50 @@ rs6000_conditional_register_usage (void) ...@@ -7849,53 +7849,50 @@ rs6000_conditional_register_usage (void)
} }
/* Try to output insns to set TARGET equal to the constant C if it can /* Output insns to set DEST equal to the constant SOURCE as a series of
be done in less than N insns. Do all computations in MODE. lis, ori and shl instructions and return TRUE. */
Returns the place where the output has been placed if it can be
done and the insns have been emitted. If it would take more than N
insns, zero is returned and no insns and emitted. */
rtx bool
rs6000_emit_set_const (rtx dest, enum machine_mode mode, rs6000_emit_set_const (rtx dest, rtx source)
rtx source, int n ATTRIBUTE_UNUSED)
{ {
rtx result, insn, set; enum machine_mode mode = GET_MODE (dest);
HOST_WIDE_INT c0, c1; rtx temp, insn, set;
HOST_WIDE_INT c;
gcc_checking_assert (CONST_INT_P (source));
c = INTVAL (source);
switch (mode) switch (mode)
{ {
case QImode: case QImode:
case HImode: case HImode:
if (dest == NULL)
dest = gen_reg_rtx (mode);
emit_insn (gen_rtx_SET (VOIDmode, dest, source)); emit_insn (gen_rtx_SET (VOIDmode, dest, source));
return dest; return true;
case SImode: case SImode:
result = !can_create_pseudo_p () ? dest : gen_reg_rtx (SImode); temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (SImode);
emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (result), emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (temp),
GEN_INT (INTVAL (source) GEN_INT (c & ~(HOST_WIDE_INT) 0xffff)));
& (~ (HOST_WIDE_INT) 0xffff))));
emit_insn (gen_rtx_SET (VOIDmode, dest, emit_insn (gen_rtx_SET (VOIDmode, dest,
gen_rtx_IOR (SImode, copy_rtx (result), gen_rtx_IOR (SImode, copy_rtx (temp),
GEN_INT (INTVAL (source) & 0xffff)))); GEN_INT (c & 0xffff))));
result = dest;
break; break;
case DImode: case DImode:
switch (GET_CODE (source)) if (!TARGET_POWERPC64)
{ {
case CONST_INT: rtx hi, lo;
c0 = INTVAL (source);
c1 = -(c0 < 0);
break;
default: hi = operand_subword_force (copy_rtx (dest), WORDS_BIG_ENDIAN == 0,
gcc_unreachable (); DImode);
lo = operand_subword_force (dest, WORDS_BIG_ENDIAN != 0,
DImode);
emit_move_insn (hi, GEN_INT (c >> 32));
c = ((c & 0xffffffff) ^ 0x80000000) - 0x80000000;
emit_move_insn (lo, GEN_INT (c));
} }
else
result = rs6000_emit_set_long_const (dest, c0, c1); rs6000_emit_set_long_const (dest, c);
break; break;
default: default:
...@@ -7905,107 +7902,103 @@ rs6000_emit_set_const (rtx dest, enum machine_mode mode, ...@@ -7905,107 +7902,103 @@ rs6000_emit_set_const (rtx dest, enum machine_mode mode,
insn = get_last_insn (); insn = get_last_insn ();
set = single_set (insn); set = single_set (insn);
if (! CONSTANT_P (SET_SRC (set))) if (! CONSTANT_P (SET_SRC (set)))
set_unique_reg_note (insn, REG_EQUAL, source); set_unique_reg_note (insn, REG_EQUAL, GEN_INT (c));
return result; return true;
} }
/* Having failed to find a 3 insn sequence in rs6000_emit_set_const, /* Subroutine of rs6000_emit_set_const, handling PowerPC64 DImode.
fall back to a straight forward decomposition. We do this to avoid Output insns to set DEST equal to the constant C as a series of
exponential run times encountered when looking for longer sequences lis, ori and shl instructions. */
with rs6000_emit_set_const. */
static rtx
rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c1, HOST_WIDE_INT c2)
{
if (!TARGET_POWERPC64)
{
rtx operand1, operand2;
operand1 = operand_subword_force (dest, WORDS_BIG_ENDIAN == 0, static void
DImode); rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c)
operand2 = operand_subword_force (copy_rtx (dest), WORDS_BIG_ENDIAN != 0, {
DImode); rtx temp;
emit_move_insn (operand1, GEN_INT (c1)); HOST_WIDE_INT ud1, ud2, ud3, ud4;
emit_move_insn (operand2, GEN_INT (c2));
ud1 = c & 0xffff;
c = c >> 16;
ud2 = c & 0xffff;
c = c >> 16;
ud3 = c & 0xffff;
c = c >> 16;
ud4 = c & 0xffff;
if ((ud4 == 0xffff && ud3 == 0xffff && ud2 == 0xffff && (ud1 & 0x8000))
|| (ud4 == 0 && ud3 == 0 && ud2 == 0 && ! (ud1 & 0x8000)))
emit_move_insn (dest, GEN_INT ((ud1 ^ 0x8000) - 0x8000));
else if ((ud4 == 0xffff && ud3 == 0xffff && (ud2 & 0x8000))
|| (ud4 == 0 && ud3 == 0 && ! (ud2 & 0x8000)))
{
temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode);
emit_move_insn (ud1 != 0 ? copy_rtx (temp) : dest,
GEN_INT (((ud2 << 16) ^ 0x80000000) - 0x80000000));
if (ud1 != 0)
emit_move_insn (dest,
gen_rtx_IOR (DImode, copy_rtx (temp),
GEN_INT (ud1)));
}
else if (ud3 == 0 && ud4 == 0)
{
temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode);
gcc_assert (ud2 & 0x8000);
emit_move_insn (copy_rtx (temp),
GEN_INT (((ud2 << 16) ^ 0x80000000) - 0x80000000));
if (ud1 != 0)
emit_move_insn (copy_rtx (temp),
gen_rtx_IOR (DImode, copy_rtx (temp),
GEN_INT (ud1)));
emit_move_insn (dest,
gen_rtx_ZERO_EXTEND (DImode,
gen_lowpart (SImode,
copy_rtx (temp))));
}
else if ((ud4 == 0xffff && (ud3 & 0x8000))
|| (ud4 == 0 && ! (ud3 & 0x8000)))
{
temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode);
emit_move_insn (copy_rtx (temp),
GEN_INT (((ud3 << 16) ^ 0x80000000) - 0x80000000));
if (ud2 != 0)
emit_move_insn (copy_rtx (temp),
gen_rtx_IOR (DImode, copy_rtx (temp),
GEN_INT (ud2)));
emit_move_insn (ud1 != 0 ? copy_rtx (temp) : dest,
gen_rtx_ASHIFT (DImode, copy_rtx (temp),
GEN_INT (16)));
if (ud1 != 0)
emit_move_insn (dest,
gen_rtx_IOR (DImode, copy_rtx (temp),
GEN_INT (ud1)));
} }
else else
{ {
HOST_WIDE_INT ud1, ud2, ud3, ud4; temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode);
ud1 = c1 & 0xffff; emit_move_insn (copy_rtx (temp),
ud2 = (c1 & 0xffff0000) >> 16; GEN_INT (((ud4 << 16) ^ 0x80000000) - 0x80000000));
c2 = c1 >> 32; if (ud3 != 0)
ud3 = c2 & 0xffff; emit_move_insn (copy_rtx (temp),
ud4 = (c2 & 0xffff0000) >> 16; gen_rtx_IOR (DImode, copy_rtx (temp),
GEN_INT (ud3)));
if ((ud4 == 0xffff && ud3 == 0xffff && ud2 == 0xffff && (ud1 & 0x8000))
|| (ud4 == 0 && ud3 == 0 && ud2 == 0 && ! (ud1 & 0x8000))) emit_move_insn (ud2 != 0 || ud1 != 0 ? copy_rtx (temp) : dest,
emit_move_insn (dest, GEN_INT ((ud1 ^ 0x8000) - 0x8000)); gen_rtx_ASHIFT (DImode, copy_rtx (temp),
GEN_INT (32)));
else if ((ud4 == 0xffff && ud3 == 0xffff && (ud2 & 0x8000)) if (ud2 != 0)
|| (ud4 == 0 && ud3 == 0 && ! (ud2 & 0x8000))) emit_move_insn (ud1 != 0 ? copy_rtx (temp) : dest,
{ gen_rtx_IOR (DImode, copy_rtx (temp),
emit_move_insn (dest, GEN_INT (((ud2 << 16) ^ 0x80000000) GEN_INT (ud2 << 16)));
- 0x80000000)); if (ud1 != 0)
if (ud1 != 0) emit_move_insn (dest,
emit_move_insn (copy_rtx (dest), gen_rtx_IOR (DImode, copy_rtx (temp),
gen_rtx_IOR (DImode, copy_rtx (dest), GEN_INT (ud1)));
GEN_INT (ud1)));
}
else if (ud3 == 0 && ud4 == 0)
{
gcc_assert (ud2 & 0x8000);
emit_move_insn (dest, GEN_INT (((ud2 << 16) ^ 0x80000000)
- 0x80000000));
if (ud1 != 0)
emit_move_insn (copy_rtx (dest),
gen_rtx_IOR (DImode, copy_rtx (dest),
GEN_INT (ud1)));
emit_move_insn (copy_rtx (dest),
gen_rtx_ZERO_EXTEND (DImode,
gen_lowpart (SImode,
copy_rtx (dest))));
}
else if ((ud4 == 0xffff && (ud3 & 0x8000))
|| (ud4 == 0 && ! (ud3 & 0x8000)))
{
emit_move_insn (dest, GEN_INT (((ud3 << 16) ^ 0x80000000)
- 0x80000000));
if (ud2 != 0)
emit_move_insn (copy_rtx (dest),
gen_rtx_IOR (DImode, copy_rtx (dest),
GEN_INT (ud2)));
emit_move_insn (copy_rtx (dest),
gen_rtx_ASHIFT (DImode, copy_rtx (dest),
GEN_INT (16)));
if (ud1 != 0)
emit_move_insn (copy_rtx (dest),
gen_rtx_IOR (DImode, copy_rtx (dest),
GEN_INT (ud1)));
}
else
{
emit_move_insn (dest, GEN_INT (((ud4 << 16) ^ 0x80000000)
- 0x80000000));
if (ud3 != 0)
emit_move_insn (copy_rtx (dest),
gen_rtx_IOR (DImode, copy_rtx (dest),
GEN_INT (ud3)));
emit_move_insn (copy_rtx (dest),
gen_rtx_ASHIFT (DImode, copy_rtx (dest),
GEN_INT (32)));
if (ud2 != 0)
emit_move_insn (copy_rtx (dest),
gen_rtx_IOR (DImode, copy_rtx (dest),
GEN_INT (ud2 << 16)));
if (ud1 != 0)
emit_move_insn (copy_rtx (dest),
gen_rtx_IOR (DImode, copy_rtx (dest),
GEN_INT (ud1)));
}
} }
return dest;
} }
/* Helper for the following. Get rid of [r+r] memory refs /* Helper for the following. Get rid of [r+r] memory refs
......
...@@ -9064,9 +9064,8 @@ ...@@ -9064,9 +9064,8 @@
(ior:SI (match_dup 0) (ior:SI (match_dup 0)
(match_dup 3)))] (match_dup 3)))]
" "
{ rtx tem = rs6000_emit_set_const (operands[0], SImode, operands[1], 2); {
if (rs6000_emit_set_const (operands[0], operands[1]))
if (tem == operands[0])
DONE; DONE;
else else
FAIL; FAIL;
...@@ -10137,9 +10136,8 @@ ...@@ -10137,9 +10136,8 @@
[(set (match_dup 0) (match_dup 2)) [(set (match_dup 0) (match_dup 2))
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
" "
{ rtx tem = rs6000_emit_set_const (operands[0], DImode, operands[1], 5); {
if (rs6000_emit_set_const (operands[0], operands[1]))
if (tem == operands[0])
DONE; DONE;
else else
FAIL; FAIL;
...@@ -10152,9 +10150,8 @@ ...@@ -10152,9 +10150,8 @@
[(set (match_dup 0) (match_dup 2)) [(set (match_dup 0) (match_dup 2))
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
" "
{ rtx tem = rs6000_emit_set_const (operands[0], DImode, operands[1], 5); {
if (rs6000_emit_set_const (operands[0], operands[1]))
if (tem == operands[0])
DONE; DONE;
else else
FAIL; FAIL;
......
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