mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-10 21:41:14 +08:00
lower-subreg.c (resolve_subreg_use): Remove assertion.
2007-08-07 Andreas Krebbel <krebbel1@de.ibm.com> * lower-subreg.c (resolve_subreg_use): Remove assertion. (find_decomposable_shift_zext, resolve_shift_zext): New functions. (decompose_multiword_subregs): Use the functions above to decompose multiword shifts and zero-extends. 2007-08-07 Andreas Krebbel <krebbel1@de.ibm.com> * gcc.dg/multiword-1.c: New testcase. From-SVN: r127270
This commit is contained in:
parent
e492980b73
commit
e0892570a8
@ -1,3 +1,10 @@
|
||||
2007-08-07 Andreas Krebbel <krebbel1@de.ibm.com>
|
||||
|
||||
* lower-subreg.c (resolve_subreg_use): Remove assertion.
|
||||
(find_decomposable_shift_zext, resolve_shift_zext): New functions.
|
||||
(decompose_multiword_subregs): Use the functions above to decompose
|
||||
multiword shifts and zero-extends.
|
||||
|
||||
2007-08-07 Rask Ingemann Lambertsen <rask@sygehus.dk>
|
||||
|
||||
* doc/sourcebuild.texi (Test Directives): Fix "compile" and
|
||||
|
@ -525,8 +525,8 @@ resolve_subreg_use (rtx *px, void *data)
|
||||
{
|
||||
/* Return 1 to the caller to indicate that we found a direct
|
||||
reference to a register which is being decomposed. This can
|
||||
happen inside notes. */
|
||||
gcc_assert (!insn);
|
||||
happen inside notes, multiword shift or zero-extend
|
||||
instructions. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -944,6 +944,155 @@ resolve_use (rtx pat, rtx insn)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Checks if INSN is a decomposable multiword-shift or zero-extend and
|
||||
sets the decomposable_context bitmap accordingly. A non-zero value
|
||||
is returned if a decomposable insn has been found. */
|
||||
|
||||
static int
|
||||
find_decomposable_shift_zext (rtx insn)
|
||||
{
|
||||
rtx set;
|
||||
rtx op;
|
||||
rtx op_operand;
|
||||
|
||||
set = single_set (insn);
|
||||
if (!set)
|
||||
return 0;
|
||||
|
||||
op = SET_SRC (set);
|
||||
if (GET_CODE (op) != ASHIFT
|
||||
&& GET_CODE (op) != LSHIFTRT
|
||||
&& GET_CODE (op) != ZERO_EXTEND)
|
||||
return 0;
|
||||
|
||||
op_operand = XEXP (op, 0);
|
||||
if (!REG_P (SET_DEST (set)) || !REG_P (op_operand)
|
||||
|| HARD_REGISTER_NUM_P (REGNO (SET_DEST (set)))
|
||||
|| HARD_REGISTER_NUM_P (REGNO (op_operand))
|
||||
|| !SCALAR_INT_MODE_P (GET_MODE (op)))
|
||||
return 0;
|
||||
|
||||
if (GET_CODE (op) == ZERO_EXTEND)
|
||||
{
|
||||
if (GET_MODE (op_operand) != word_mode
|
||||
|| GET_MODE_BITSIZE (GET_MODE (op)) != 2 * BITS_PER_WORD)
|
||||
return 0;
|
||||
}
|
||||
else /* left or right shift */
|
||||
{
|
||||
if (GET_CODE (XEXP (op, 1)) != CONST_INT
|
||||
|| INTVAL (XEXP (op, 1)) < BITS_PER_WORD
|
||||
|| GET_MODE_BITSIZE (GET_MODE (op_operand)) != 2 * BITS_PER_WORD)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bitmap_set_bit (decomposable_context, REGNO (SET_DEST (set)));
|
||||
|
||||
if (GET_CODE (op) != ZERO_EXTEND)
|
||||
bitmap_set_bit (decomposable_context, REGNO (op_operand));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Decompose a more than word wide shift (in INSN) of a multiword
|
||||
pseudo or a multiword zero-extend of a wordmode pseudo into a move
|
||||
and 'set to zero' insn. Return a pointer to the new insn when a
|
||||
replacement was done. */
|
||||
|
||||
static rtx
|
||||
resolve_shift_zext (rtx insn)
|
||||
{
|
||||
rtx set;
|
||||
rtx op;
|
||||
rtx op_operand;
|
||||
rtx insns;
|
||||
rtx src_reg, dest_reg, dest_zero;
|
||||
int src_reg_num, dest_reg_num, offset1, offset2, src_offset;
|
||||
|
||||
set = single_set (insn);
|
||||
if (!set)
|
||||
return NULL_RTX;
|
||||
|
||||
op = SET_SRC (set);
|
||||
if (GET_CODE (op) != ASHIFT
|
||||
&& GET_CODE (op) != LSHIFTRT
|
||||
&& GET_CODE (op) != ZERO_EXTEND)
|
||||
return NULL_RTX;
|
||||
|
||||
op_operand = XEXP (op, 0);
|
||||
|
||||
if (!resolve_reg_p (SET_DEST (set)) && !resolve_reg_p (op_operand))
|
||||
return NULL_RTX;
|
||||
|
||||
/* src_reg_num is the number of the word mode register which we
|
||||
are operating on. For a left shift and a zero_extend on little
|
||||
endian machines this is register 0. */
|
||||
src_reg_num = GET_CODE (op) == LSHIFTRT ? 1 : 0;
|
||||
|
||||
if (WORDS_BIG_ENDIAN)
|
||||
src_reg_num = 1 - src_reg_num;
|
||||
|
||||
if (GET_CODE (op) == ZERO_EXTEND)
|
||||
dest_reg_num = src_reg_num;
|
||||
else
|
||||
dest_reg_num = 1 - src_reg_num;
|
||||
|
||||
offset1 = UNITS_PER_WORD * dest_reg_num;
|
||||
offset2 = UNITS_PER_WORD * (1 - dest_reg_num);
|
||||
src_offset = UNITS_PER_WORD * src_reg_num;
|
||||
|
||||
if (WORDS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
|
||||
{
|
||||
offset1 += UNITS_PER_WORD - 1;
|
||||
offset2 += UNITS_PER_WORD - 1;
|
||||
src_offset += UNITS_PER_WORD - 1;
|
||||
}
|
||||
|
||||
start_sequence ();
|
||||
|
||||
dest_reg = simplify_gen_subreg_concatn (word_mode, SET_DEST (set),
|
||||
GET_MODE (SET_DEST (set)),
|
||||
offset1);
|
||||
dest_zero = simplify_gen_subreg_concatn (word_mode, SET_DEST (set),
|
||||
GET_MODE (SET_DEST (set)),
|
||||
offset2);
|
||||
src_reg = simplify_gen_subreg_concatn (word_mode, op_operand,
|
||||
GET_MODE (op_operand),
|
||||
src_offset);
|
||||
if (GET_CODE (op) != ZERO_EXTEND)
|
||||
{
|
||||
int shift_count = INTVAL (XEXP (op, 1));
|
||||
if (shift_count > BITS_PER_WORD)
|
||||
src_reg = expand_shift (GET_CODE (op) == ASHIFT ?
|
||||
LSHIFT_EXPR : RSHIFT_EXPR,
|
||||
word_mode, src_reg,
|
||||
build_int_cst (NULL_TREE,
|
||||
shift_count - BITS_PER_WORD),
|
||||
dest_reg, 1);
|
||||
}
|
||||
|
||||
if (dest_reg != src_reg)
|
||||
emit_move_insn (dest_reg, src_reg);
|
||||
emit_move_insn (dest_zero, CONST0_RTX (word_mode));
|
||||
insns = get_insns ();
|
||||
|
||||
end_sequence ();
|
||||
|
||||
emit_insn_before (insns, insn);
|
||||
|
||||
if (dump_file)
|
||||
{
|
||||
rtx in;
|
||||
fprintf (dump_file, "; Replacing insn: %d with insns: ", INSN_UID (insn));
|
||||
for (in = insns; in != insn; in = NEXT_INSN (in))
|
||||
fprintf (dump_file, "%d ", INSN_UID (in));
|
||||
fprintf (dump_file, "\n");
|
||||
}
|
||||
|
||||
delete_insn (insn);
|
||||
return insns;
|
||||
}
|
||||
|
||||
/* Look for registers which are always accessed via word-sized SUBREGs
|
||||
or via copies. Decompose these registers into several word-sized
|
||||
pseudo-registers. */
|
||||
@ -1003,6 +1152,9 @@ decompose_multiword_subregs (void)
|
||||
|| GET_CODE (PATTERN (insn)) == USE)
|
||||
continue;
|
||||
|
||||
if (find_decomposable_shift_zext (insn))
|
||||
continue;
|
||||
|
||||
recog_memoized (insn);
|
||||
extract_insn (insn);
|
||||
|
||||
@ -1152,6 +1304,19 @@ decompose_multiword_subregs (void)
|
||||
SET_BIT (sub_blocks, bb->index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx decomposed_shift;
|
||||
|
||||
decomposed_shift = resolve_shift_zext (insn);
|
||||
if (decomposed_shift != NULL_RTX)
|
||||
{
|
||||
changed = true;
|
||||
insn = decomposed_shift;
|
||||
recog_memoized (insn);
|
||||
extract_insn (insn);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = recog_data.n_operands - 1; i >= 0; --i)
|
||||
for_each_rtx (recog_data.operand_loc[i],
|
||||
|
@ -1,3 +1,7 @@
|
||||
2007-08-07 Andreas Krebbel <krebbel1@de.ibm.com>
|
||||
|
||||
* gcc.dg/multiword-1.c: New testcase.
|
||||
|
||||
2007-08-07 Daniel Franke <franke.daniel@gmail.com>
|
||||
|
||||
* gfortran.dg/namelist_33.f90: Improved tests, adjusted error
|
||||
|
68
gcc/testsuite/gcc.dg/multiword-1.c
Normal file
68
gcc/testsuite/gcc.dg/multiword-1.c
Normal file
@ -0,0 +1,68 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O3" } */
|
||||
/* { dg-require-effective-target ilp32 } */
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned long long u64;
|
||||
|
||||
u64 __attribute__((noinline))
|
||||
foo (u32 high, u32 low)
|
||||
{
|
||||
return ((u64)high << 32) | low;
|
||||
}
|
||||
|
||||
u32 __attribute__((noinline))
|
||||
right (u64 t)
|
||||
{
|
||||
return (u32)(t >> 32);
|
||||
}
|
||||
|
||||
u64 __attribute__((noinline))
|
||||
left (u32 t)
|
||||
{
|
||||
return (u64)t << 32;
|
||||
}
|
||||
|
||||
u32 __attribute__((noinline))
|
||||
right2 (u64 t)
|
||||
{
|
||||
return (u32)(t >> 40);
|
||||
}
|
||||
|
||||
u64 __attribute__((noinline))
|
||||
left2 (u32 t)
|
||||
{
|
||||
return (u64)t << 40;
|
||||
}
|
||||
|
||||
u64 __attribute__((noinline))
|
||||
zeroextend (u32 t)
|
||||
{
|
||||
return (u64)t;
|
||||
}
|
||||
|
||||
extern void abort ();
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
if (foo (13000, 12000) != 55834574860000ULL)
|
||||
abort ();
|
||||
|
||||
if (right (55834574860000ULL) != 13000)
|
||||
abort ();
|
||||
|
||||
if (left (13000) != 55834574848000ULL)
|
||||
abort ();
|
||||
|
||||
if (right2 (55834574860000ULL) != 50)
|
||||
abort ();
|
||||
|
||||
if (left2 (13000) != 14293651161088000ULL)
|
||||
abort ();
|
||||
|
||||
if (zeroextend (13000) != 13000ULL)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user