summaryrefslogtreecommitdiff
path: root/gcc/recog.c
diff options
context:
space:
mode:
authoramacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4>2001-04-03 15:06:12 +0000
committeramacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4>2001-04-03 15:06:12 +0000
commit701e46d0e8a0465eb15923f104e7d741c4b1c8ca (patch)
tree28cfaed9a88de9b20638576026f15f0a1d8b06e6 /gcc/recog.c
parent71a7798b95e455db6c69e9e5207232fda5730bc5 (diff)
downloadgcc-701e46d0e8a0465eb15923f104e7d741c4b1c8ca.tar.gz
2001-04-03 Jakub Jelinek <jakub@redhat.com>
David S. Miller <davem@pierdol.cobaltmicro.com> Andrew MacLeod <amacleod@redhat.com> Use byte offsets in SUBREGs instead of words. * alias.c (nonlocal_mentioned_p): Use subreg_regno function. * caller-save.c (mark_set_regs): Change callers of subreg_hard_regno to pass new argument. (add_stored_regs): Use subreg_regno_offset function. * calls.c (expand_call): For non-paradoxical SUBREG take endianess into account. (precompute_arguments): Use gen_lowpart_SUBREG. * combine.c (try_combine): Replace explicit XEXP with SUBREG_REG. (combine_simplify_rtx): Rework to use SUBREG_BYTE. (simplify_set): Rework to use SUBREG_BYTE. (expand_field_assignment): Use SUBREG_BYTE. (make_extraction): Use SUBREG_BYTE. (if_then_else_cond): Use SUBREG_BYTE. (apply_distributive_law): Use SUBREG_BYTE and fixup subreg comments. (gen_lowpart_for_combine): Compute full byte offset. * cse.c (mention_regs): Use SUBREG_BYTE. (remove_invalid_subreg_refs): Rework to use SUBREG_BYTE. (canon_hash): Use SUBREG_BYTE. (fold_rtx): Pass SUBREG_BYTE div UNITS_PER_WORD to operand_subword. (gen_lowpart_if_possible): Formatting. * dbxout.c (dbxout_symbol_location): Compute SUBREG hard regnos correctly. * dwarf2out.c (is_pseudo_reg): Fixup explicit XEXP into SUBREG_REG (mem_loc_descriptor): Fixup explicit XEXP into SUBREG_REG (loc_descriptor): Fixup explicit XEXP into SUBREG_REG * dwarfout.c (is_pseudo_reg): Fixup explicit XEXP into SUBREG_REG (output_mem_loc_descriptor): Fixup explicit XEXP into SUBREG_REG (output_loc_descriptor): Fixup explicit XEXP into SUBREG_REG * emit-rtl.c (gen_rtx_SUBREG): New function, used to verify certain invariants about SUBREGs the compiler creates. (gen_lowpart_SUBREG): New function. (subreg_hard_regno): New function to get the final register number. (gen_lowpart_common): Use SUBREG_BYTE. (gen_imagpart): Spacing nits. (subreg_realpart_p): Use SUBREG_BYTE. (gen_highpart): Use SUBREG_BYTE. (subreg_lowpart_p): Always compute endian corrected goal offset, even at the byte level, then compare against that. (constant_subword): New function, pulled out all constant cases from operand_subword and changed second argument name to offset. (operand_subword): Detect non REG/SUBREG/CONCAT/MEM cases early and call constant_subword to do the work. Return const0_rtx if looking for a word outside of OP. (operand_subword_force): Change second arg name to offset. * expmed.c (store_bit_field): Use SUBREG_BYTE. (store_split_bit_field): Use SUBREG_BYTE. (extract_bit_field): Use SUBREG_BYTE. (extract_split_bit_field): Use SUBREG_BYTE. (expand_shift): Use SUBREG_BYTE. * expr.c (store_expr, expand_expr): Use gen_lowpart_SUBREG. * final.c (alter_subreg) Use subreg_hard_regno and SUBREG_BYTE. * flow.c (set_noop_p): Use SUBREG_BYTE. (mark_set_1): Remove ALTER_HARD_SUBREG. Use subreg_regno_offset instead. * function.c (fixup_var_refs_1): Fixup explicit XEXP into a SUBREG_REG. (fixup_memory_subreg): Use SUBREG_BYTE and remove byte endian correction code. (optimize_bit_field): Use SUBREG_BYTE. (purge_addressof_1): Use SUBREG_BYTE. (purge_single_hard_subreg_set): Use subreg_regno_offset function. (assign_params): Mark arguments SUBREG_PROMOTED_VAR_P if they are actually promoted by the caller and PROMOTE_FOR_CALLS_ONLY is true. * gengenrtl.c (special_rtx): Add SUBREG. * global.c (mark_reg_store): Use SUBREG_BYTE. (set_preference): Rework to use subreg_regno_offset and SUBREG_BYTE. * ifcvt (noce_emit_move_insn): Use SUBREG_BYTE. * integrate.c (copy_rtx_and_substitute): Use SUBREG_BYTE and make sure final byte offset is congruent to subreg's mode size. (subst_constants): Use SUBREG_BYTE. (mark_stores): Use subreg_regno_offset function. * jump.c (rtx_renumbered_equal_p, true_regnum): Use subreg_regno_offset function and SUBREG_BYTE. * local-alloc.c (combine_regs): Use subreg_regno_offset function. (reg_is_born): Use subreg_hard_regno. * recog.c (valid_replace_rtx_1): Use SUBREG_BYTE and remove byte endian correction code. Don't combine subregs unless resulting offset aligns with type. Fix subreg constant extraction for DImode. Simplify SUBREG of VOIDmode CONST_DOUBLE. (general_operand): Remove dead mode_altering_drug code. (indirect_operand): Use SUBREG_BYTE. (constrain_operands): Use subreg_regno_offset function. * reg-stack.c (get_true_reg): Use subreg_regno_offset function. * regmove.c (regmove_optimize): Use SUBREG_BYTE. (optimize_reg_copy_3): Use gen_lowpart_SUBREG. * regs.h (REG_SIZE): Allow target to override. (REGMODE_NATURAL_SIZE): New macro which target can override. * reload.c (reload_inner_reg_of_subreg): subreg_regno should be used on the entire subreg rtx. (push_reload): Use SUBREG_BYTE in comments and code. (find_dummy_reload): Use subreg_regno_offset. Only adjust offsets for hard registers inside subregs. (operands_match_p): Use subreg_regno_offset. (find_reloads): Use SUBREG_BYTE and only advance offset for subregs containing hard regs. (find_reload_toplev): Use SUBREG_BYTE. Remove byte endian corrections when fixing up MEM subregs. (find_reloads_address_1): Use SUBREG_BYTE, subreg_regno, and subreg_regno_offset where appropriate. (find_reloads_subreg_address): Use SUBREG_BYTE. Remove byte endian corrections when fixing up MEM subregs. (subst_reloads): When combining two subregs, make sure final offset is congruent to subreg's mode size. (find_replacement): Use SUBREG_BYTE and subreg_regno_offset. (refers_to_regno_for_reload_p): Use subreg_regno. (reg_overlap_mentioned_for_reload_p): Use subreg_regno_offset. * reload1.c (eliminate_regs) Use SUBREG_BYTE. Remove byte endian correction code for memory subreg fixups. (forget_old_reload_1): Use subreg_regno_offset. (choose_reload_regs): Use subreg_regno. (emit_input_reload_insns): Use SUBREG_BYTE. (reload_combine_note_store): Use subreg_regno_offset. (move2add_note_store): Use subreg_regno_offset. * resource.c (update_live_status, mark_referenced_resources): Use subreg_regno function. (mark_set_resources): Use subreg_regno function. * rtl.h (SUBREG_WORD): Rename to SUBREG_BYTE. (subreg_regno_offset, subreg_regno): Define prototypes. (subreg_hard_regno, constant_subword, gen_rtx_SUBREG): Newi functions. (gen_lowpart_SUBREG): Add prototype. * rtl.texi (subreg): Update to reflect new byte offset representation. Add mentioning of the effect that BYTES_BIG_ENDIAN has on subregs now. * rtlanal.c (refers_to_regno_p): Use subreg_regno. (reg_overlap_mentioned_p): Use subreg_regno. (replace_regs); Make sure final offset of combined subreg is congruent to size of subreg's mode. (subreg_regno_offset): New function. (subreg_regno): New function. * sched-vis.c (print_value): Change SUBREG_WORD to SUBREG_BYTE. * sdbout.c (sdbout_symbol): Compute offset using alter_subreg. * stmt.c (expand_anon_union_decl): Use gen_lowpart_SUBREG. * tm.texi (ALTER_HARD_SUBREG): Remove, it is now dead. (SUBREG_REGNO_OFFSET): Describe SUBREG_REGNO_OFFSET overrides. * config/a29k/a29k.c (gpc_reg_operand): Use subreg_regno. (a29k_get_reloaded_address): Use SUBREG_BYTE. (print_operand): Use SUBREG_BYTE. * config/alpha/alpha.c (print_operand_address): Use SUBREG_BYTE. * config/arm/arm.c (arm_reload_in_hi): Use SUBREG_BYTE. (arm_reload_out_hi): Use SUBREG_BYTE. * config/d30v/d30v.c (d30v_split_double): Use subreg_regno_offset instead of SUBREG_WORD. (d30v_print_operand_memory_reference): Use subreg_regno_offset. * config/dsp16xx/dsp16xx.md (extendqihi2, zero_extendqihi2): Fix SUBREG creation to use byte offset. * config/h8300/h8300.md (Unnamed HImode zero extraction and 16bit inverted load insns): Fix explicit rtl subregs to use byte offsets. * config/i370/i370.md (cmpstrsi, movstrsi, mulsi3, divsi3, udivsi3, umodsi3): Generate SUBREGs with byte offsets. * config/i860/i860.c (single_insn_src_p): Use SUBREG_BYTE. * config/i860/i860.md (mulsi3_big): Fixup explicit SUBREGs in rtl to use byte offsets. (unnamed fmlow.dd insn): Fixup SUBREGS to use byte offsets. * config/i960/i960.md (extendhisi2): Generate SUBREGs with byte offsets, also make sure it is congruent to SUBREG's mode size. (extendqisi2, extendqihi2, zero_extendhisi2, zero_extendqisi2, unnamed ldob insn): Generate SUBREGs with byte offset. (zero_extendqihi2): SUBREG's are byte offsets. * config/m68hc11/m68hc11.c (m68hc11_gen_lowpart): Use SUBREG_BYTE. (m68hc11_gen_highpart): Use SUBREG_BYTE. * config/m68k/m68k.md (zero_extendhisi2, zero_extendqihi2, zero-extendqisi2): Generate SUBREGs with byte offset. (umulsidi3, mulsidi3, subreghi1ashrdi_const32, subregsi1ashrdi_const32, subreg1lshrdi_const32): Fixup explicit subregs in rtl to use byte offsets. * config/m88k/m88k.md (extendsidi2): fixup subregs to use byte offset. * config/mips/mips.c (mips_move_1word): Use subreg_regno_offset. (mips_move_2words): Use subreg_regno_offset. (mips_secondary_reload_class): Use subreg_regno_offset. * config/mips/mips.md (DImode plus, minus, move, and logical op splits): Fixup explicit subregs in rtl to use byte offsets. * config/mn10200/mn10200.c (print_operand): Use subreg_regno function. * config/mn10300/mn10300.c (print_operand): Use subreg_regno function. * config/ns32k/ns32k.md (udivmoddisi4): Fix explicit subregs in rtl to use byte offsets. * config/pa/pa.c (emit_move_sequence): Use SUBREG_BYTE. * config/pa/pa.md (floatunssisf2, floatunssidf2, mulsi3): fix explicit subregs to use byte offsets. * config/pdp11/pdp11.md (zero_extendhisi2, modhi3, modhi3+1): Fixup explicit subregs in rtl to use byte offsets. * config/romp/romp.c (memory_offset_in_range_p): Use SUBREG_BYTE and remove byte endian correction code. * config/sh/sh.c (output_movedouble): Use subreg_regno. (gen_ashift_hi): Use SUBREG_BYTE. (regs_used): Use subreg_regno_offset. (machine_dependent_reorg): Use subreg_regno_offset. * config/sh/sh.h (INDEX_REGISTER_RTX_P): Use SUBREG_BYTE. * config/sh/sh.md (DImode and DFmode move splits): Use subreg_regno. (movdf_i4): Subregs are byte offsets now. * config/sparc/sparc.c (ultra_find_type): Use SUBREG_BYTE. * config/sparc/sparc.h (ALTER_HARD_SUBREG): Removed. (REGMODE_NATURAL_SIZE): Override. (REG_SIZE): For SUBREG check float mode on SUBREG_REG's mode. * config/sparc/sparc.md (TFmode move splits): Generate SUBREGs with byte offsets. (zero_extendhisi2, zero_extendqidi2_insn, extendhisi2, extendqihi2, sign_extendqihi2_insn, sign_extendqisi2_insn, extendqidi2): Generate SUBREGs with byte offsets, also make sure it is congruent to SUBREG's mode size. (smulsi3_highpart_v8plus): Fix explicit subregs in rtl to use byte offsets. (cmp_siqi_trunc, cmp_siqi_trunc_set, cmp_diqi_trunc, cmp_diqi_trunc_set, lshrdi3_v8plus+1, lshrdi3_v8plus+2, lshrdi3_v8plus+3, lshrdi3_v8plus+4): Use proper SUBREG_BYTE offset for non-paradoxical subregs in patterns. * config/v850/v850.c (print_operand, output_move_double): Use subreg_regno function. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@41058 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/recog.c')
-rw-r--r--gcc/recog.c150
1 files changed, 99 insertions, 51 deletions
diff --git a/gcc/recog.c b/gcc/recog.c
index 1596a019067..e278f985529 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -517,13 +517,15 @@ validate_replace_rtx_1 (loc, from, to, object)
if (GET_CODE (XEXP (x, 0)) == SUBREG)
{
if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) <= UNITS_PER_WORD)
- to = operand_subword (to, SUBREG_WORD (XEXP (x, 0)),
+ to = operand_subword (to,
+ (SUBREG_BYTE (XEXP (x, 0))
+ / UNITS_PER_WORD),
0, GET_MODE (from));
else if (GET_MODE_CLASS (GET_MODE (from)) == MODE_INT
&& (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
<= HOST_BITS_PER_WIDE_INT))
{
- int i = SUBREG_WORD (XEXP (x, 0)) * BITS_PER_WORD;
+ int i = SUBREG_BYTE (XEXP (x, 0)) * BITS_PER_UNIT;
HOST_WIDE_INT valh;
unsigned HOST_WIDE_INT vall;
@@ -569,26 +571,21 @@ validate_replace_rtx_1 (loc, from, to, object)
break;
case SUBREG:
- /* In case we are replacing by constant, attempt to simplify it to non-SUBREG
- expression. We can't do this later, since the information about inner mode
- may be lost. */
+ /* In case we are replacing by constant, attempt to simplify it to
+ non-SUBREG expression. We can't do this later, since the information
+ about inner mode may be lost. */
if (CONSTANT_P (to) && rtx_equal_p (SUBREG_REG (x), from))
{
- if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD
- && GET_MODE_SIZE (GET_MODE (from)) > UNITS_PER_WORD
- && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
- {
- rtx temp = operand_subword (to, SUBREG_WORD (x),
- 0, GET_MODE (from));
- if (temp)
- {
- validate_change (object, loc, temp, 1);
- return;
- }
- }
- if (subreg_lowpart_p (x))
+ int offset, part;
+ unsigned HOST_WIDE_INT val;
+
+ /* A paradoxical SUBREG of a VOIDmode constant is the same constant,
+ since we are saying that the high bits don't matter. */
+ if (GET_MODE (to) == VOIDmode
+ && (GET_MODE_SIZE (GET_MODE (x))
+ >= GET_MODE_SIZE (GET_MODE (from))))
{
- rtx new = gen_lowpart_if_possible (GET_MODE (x), to);
+ rtx new = gen_lowpart_if_possible (GET_MODE (x), to);
if (new)
{
validate_change (object, loc, new, 1);
@@ -596,13 +593,67 @@ validate_replace_rtx_1 (loc, from, to, object)
}
}
- /* A paradoxical SUBREG of a VOIDmode constant is the same constant,
- since we are saying that the high bits don't matter. */
- if (GET_MODE (to) == VOIDmode
- && GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (from)))
+ offset = SUBREG_BYTE (x) * BITS_PER_UNIT;
+ switch (GET_CODE (to))
{
- validate_change (object, loc, to, 1);
- return;
+ case CONST_DOUBLE:
+ if (GET_MODE (to) != VOIDmode)
+ break;
+
+ part = offset >= HOST_BITS_PER_WIDE_INT;
+ if ((BITS_PER_WORD > HOST_BITS_PER_WIDE_INT
+ && BYTES_BIG_ENDIAN)
+ || (BITS_PER_WORD <= HOST_BITS_PER_WIDE_INT
+ && WORDS_BIG_ENDIAN))
+ part = !part;
+ val = part ? CONST_DOUBLE_HIGH (to) : CONST_DOUBLE_LOW (to);
+ offset %= HOST_BITS_PER_WIDE_INT;
+
+ /* FALLTHROUGH */
+ case CONST_INT:
+ if (GET_CODE (to) == CONST_INT)
+ val = INTVAL (to);
+
+ {
+ /* Avoid creating bogus SUBREGs */
+ enum machine_mode mode = GET_MODE (x);
+ enum machine_mode inner_mode = GET_MODE (from);
+
+ /* We've already picked the word we want from a double, so
+ pretend this is actually an integer. */
+ if (GET_CODE (to) == CONST_DOUBLE)
+ inner_mode = SImode;
+
+ if (GET_MODE_CLASS (mode) != MODE_INT)
+ abort ();
+
+ if (BYTES_BIG_ENDIAN || WORDS_BIG_ENDIAN)
+ {
+ if (WORDS_BIG_ENDIAN)
+ offset = GET_MODE_BITSIZE (inner_mode)
+ - GET_MODE_BITSIZE (mode) - offset;
+ if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
+ && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+ offset = offset + BITS_PER_WORD - GET_MODE_BITSIZE (mode)
+ - 2 * (offset % BITS_PER_WORD);
+ }
+
+ if (offset >= HOST_BITS_PER_WIDE_INT)
+ to = ((HOST_WIDE_INT) val < 0) ? constm1_rtx : const0_rtx;
+ else
+ {
+ val >>= offset;
+ if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT)
+ val = trunc_int_for_mode (val, mode);
+ to = GEN_INT (val);
+ }
+
+ validate_change (object, loc, to, 1);
+ return;
+ }
+
+ default:
+ break;
}
}
@@ -612,15 +663,26 @@ validate_replace_rtx_1 (loc, from, to, object)
&& rtx_equal_p (SUBREG_REG (x), from))
{
if (GET_MODE (x) == GET_MODE (SUBREG_REG (to))
- && SUBREG_WORD (x) == 0 && SUBREG_WORD (to) == 0)
+ && SUBREG_BYTE (x) == 0 && SUBREG_BYTE (to) == 0)
{
validate_change (object, loc, SUBREG_REG (to), 1);
return;
}
- validate_change (object, loc,
- gen_rtx_SUBREG (GET_MODE (x), SUBREG_REG (to),
- SUBREG_WORD (x) + SUBREG_WORD (to)), 1);
+ /* Make sure the 2 byte counts added together are an even unit
+ of x's mode, and combine them if so. Otherwise we run
+ into problems with something like:
+ (subreg:HI (subreg:QI (SI:55) 3) 0)
+ we end up with an odd offset into a HI which is invalid. */
+
+ if (SUBREG_BYTE (to) % GET_MODE_SIZE (GET_MODE (x)) == 0)
+ validate_change (object, loc,
+ gen_rtx_SUBREG (GET_MODE (x), SUBREG_REG (to),
+ SUBREG_BYTE(x) + SUBREG_BYTE (to)),
+ 1);
+ else
+ validate_change (object, loc, to, 1);
+
return;
}
@@ -636,15 +698,10 @@ validate_replace_rtx_1 (loc, from, to, object)
&& ! MEM_VOLATILE_P (to)
&& GET_MODE_SIZE (GET_MODE (x)) <= GET_MODE_SIZE (GET_MODE (to)))
{
- int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
+ int offset = SUBREG_BYTE (x);
enum machine_mode mode = GET_MODE (x);
rtx new;
- if (BYTES_BIG_ENDIAN)
- offset += (MIN (UNITS_PER_WORD,
- GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
- - MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
-
new = gen_rtx_MEM (mode, plus_constant (XEXP (to, 0), offset));
MEM_COPY_ATTRIBUTES (new, to);
validate_change (object, loc, new, 1);
@@ -694,8 +751,8 @@ validate_replace_rtx_1 (loc, from, to, object)
int offset = pos / BITS_PER_UNIT;
rtx newmem;
- /* If the bytes and bits are counted differently, we
- must adjust the offset. */
+ /* If the bytes and bits are counted differently, we
+ must adjust the offset. */
if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
offset = (GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (wanted_mode)
- offset);
@@ -1040,7 +1097,6 @@ general_operand (op, mode)
enum machine_mode mode;
{
register enum rtx_code code = GET_CODE (op);
- int mode_altering_drug = 0;
if (mode == VOIDmode)
mode = GET_MODE (op);
@@ -1078,11 +1134,6 @@ general_operand (op, mode)
op = SUBREG_REG (op);
code = GET_CODE (op);
-#if 0
- /* No longer needed, since (SUBREG (MEM...))
- will load the MEM into a reload reg in the MEM's own mode. */
- mode_altering_drug = 1;
-#endif
}
if (code == REG)
@@ -1113,8 +1164,6 @@ general_operand (op, mode)
return 0;
win:
- if (mode_altering_drug)
- return ! mode_dependent_address_p (XEXP (op, 0));
return 1;
}
@@ -1467,13 +1516,9 @@ indirect_operand (op, mode)
if (! reload_completed
&& GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == MEM)
{
- register int offset = SUBREG_WORD (op) * UNITS_PER_WORD;
+ register int offset = SUBREG_BYTE (op);
rtx inner = SUBREG_REG (op);
- if (BYTES_BIG_ENDIAN)
- offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (op)))
- - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (inner))));
-
if (mode != VOIDmode && GET_MODE (op) != mode)
return 0;
@@ -2482,7 +2527,10 @@ constrain_operands (strict)
{
if (GET_CODE (SUBREG_REG (op)) == REG
&& REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
- offset = SUBREG_WORD (op);
+ offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
+ GET_MODE (SUBREG_REG (op)),
+ SUBREG_BYTE (op),
+ GET_MODE (op));
op = SUBREG_REG (op);
}