diff options
author | Jakub Jelinek <jakub@redhat.com> | 2001-04-03 17:06:12 +0200 |
---|---|---|
committer | Andrew Macleod <amacleod@gcc.gnu.org> | 2001-04-03 15:06:12 +0000 |
commit | ddef6bc7a3c885433f0b8a611cdbb4bef0ce4bc3 (patch) | |
tree | 28cfaed9a88de9b20638576026f15f0a1d8b06e6 /gcc/reload.c | |
parent | 924c96ebc4c736cd20d0a36a3973686854e2a152 (diff) | |
download | gcc-ddef6bc7a3c885433f0b8a611cdbb4bef0ce4bc3.zip gcc-ddef6bc7a3c885433f0b8a611cdbb4bef0ce4bc3.tar.gz gcc-ddef6bc7a3c885433f0b8a611cdbb4bef0ce4bc3.tar.bz2 |
Use byte offsets in SUBREGs instead of words.
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.
Co-Authored-By: Andrew MacLeod <amacleod@redhat.com>
Co-Authored-By: David S. Miller <davem@pierdol.cobaltmicro.com>
From-SVN: r41058
Diffstat (limited to 'gcc/reload.c')
-rw-r--r-- | gcc/reload.c | 165 |
1 files changed, 119 insertions, 46 deletions
diff --git a/gcc/reload.c b/gcc/reload.c index 9849aed..ea5bea6 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -791,7 +791,7 @@ reload_inner_reg_of_subreg (x, mode) return 0; /* If INNER is not ok for MODE, then INNER will need reloading. */ - if (! HARD_REGNO_MODE_OK (REGNO (inner) + SUBREG_WORD (x), mode)) + if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode)) return 1; /* If the outer part is a word or smaller, INNER larger than a @@ -938,13 +938,12 @@ push_reload (in, out, inloc, outloc, class, Finally, reload the inner expression if it is a register that is in the class whose registers cannot be referenced in a different size - and M1 is not the same size as M2. If SUBREG_WORD is nonzero, we + and M1 is not the same size as M2. If SUBREG_BYTE is nonzero, we cannot reload just the inside since we might end up with the wrong register class. But if it is inside a STRICT_LOW_PART, we have no choice, so we hope we do get the right register class there. */ if (in != 0 && GET_CODE (in) == SUBREG - && (SUBREG_WORD (in) == 0 || strict_low) #ifdef CLASS_CANNOT_CHANGE_MODE && (class != CLASS_CANNOT_CHANGE_MODE || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), inmode)) @@ -978,7 +977,7 @@ push_reload (in, out, inloc, outloc, class, && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER /* The case where out is nonzero is handled differently in the following statement. */ - && (out == 0 || SUBREG_WORD (in) == 0) + && (out == 0 || SUBREG_BYTE (in) == 0) && ((GET_MODE_SIZE (inmode) <= UNITS_PER_WORD && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))) > UNITS_PER_WORD) @@ -986,9 +985,7 @@ push_reload (in, out, inloc, outloc, class, / UNITS_PER_WORD) != HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)), GET_MODE (SUBREG_REG (in))))) - || ! HARD_REGNO_MODE_OK ((REGNO (SUBREG_REG (in)) - + SUBREG_WORD (in)), - inmode))) + || ! HARD_REGNO_MODE_OK (subreg_regno (in), inmode))) #ifdef SECONDARY_INPUT_RELOAD_CLASS || (SECONDARY_INPUT_RELOAD_CLASS (class, inmode, in) != NO_REGS && (SECONDARY_INPUT_RELOAD_CLASS (class, @@ -1028,7 +1025,7 @@ push_reload (in, out, inloc, outloc, class, that case. */ /* Similar issue for (SUBREG constant ...) if it was not handled by the - code above. This can happen if SUBREG_WORD != 0. */ + code above. This can happen if SUBREG_BYTE != 0. */ if (in != 0 && reload_inner_reg_of_subreg (in, inmode)) { @@ -1038,7 +1035,11 @@ push_reload (in, out, inloc, outloc, class, RELOAD_OTHER, we are guaranteed that this inner reload will be output before the outer reload. */ push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), NULL_PTR, - find_valid_class (inmode, SUBREG_WORD (in)), + find_valid_class (inmode, + subreg_regno_offset (REGNO (SUBREG_REG (in)), + GET_MODE (SUBREG_REG (in)), + SUBREG_BYTE (in), + GET_MODE (in))), VOIDmode, VOIDmode, 0, 0, opnum, type); dont_remove_subreg = 1; } @@ -1050,7 +1051,7 @@ push_reload (in, out, inloc, outloc, class, (except in the case of STRICT_LOW_PART, and in that case the constraint should label it input-output.) */ if (out != 0 && GET_CODE (out) == SUBREG - && (SUBREG_WORD (out) == 0 || strict_low) + && (SUBREG_BYTE (out) == 0 || strict_low) #ifdef CLASS_CANNOT_CHANGE_MODE && (class != CLASS_CANNOT_CHANGE_MODE || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)), @@ -1080,9 +1081,7 @@ push_reload (in, out, inloc, outloc, class, / UNITS_PER_WORD) != HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)), GET_MODE (SUBREG_REG (out))))) - || ! HARD_REGNO_MODE_OK ((REGNO (SUBREG_REG (out)) - + SUBREG_WORD (out)), - outmode))) + || ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode))) #ifdef SECONDARY_OUTPUT_RELOAD_CLASS || (SECONDARY_OUTPUT_RELOAD_CLASS (class, outmode, out) != NO_REGS && (SECONDARY_OUTPUT_RELOAD_CLASS (class, @@ -1129,7 +1128,11 @@ push_reload (in, out, inloc, outloc, class, dont_remove_subreg = 1; push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out), &SUBREG_REG (out), - find_valid_class (outmode, SUBREG_WORD (out)), + find_valid_class (outmode, + subreg_regno_offset (REGNO (SUBREG_REG (out)), + GET_MODE (SUBREG_REG (out)), + SUBREG_BYTE (out), + GET_MODE (out))), VOIDmode, VOIDmode, 0, 0, opnum, RELOAD_OTHER); } @@ -1146,16 +1149,14 @@ push_reload (in, out, inloc, outloc, class, if (in != 0 && GET_CODE (in) == SUBREG && GET_CODE (SUBREG_REG (in)) == REG && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER && ! dont_remove_subreg) - in = gen_rtx_REG (GET_MODE (in), - REGNO (SUBREG_REG (in)) + SUBREG_WORD (in)); + in = gen_rtx_REG (GET_MODE (in), subreg_regno (in)); /* Similarly for OUT. */ if (out != 0 && GET_CODE (out) == SUBREG && GET_CODE (SUBREG_REG (out)) == REG && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER && ! dont_remove_subreg) - out = gen_rtx_REG (GET_MODE (out), - REGNO (SUBREG_REG (out)) + SUBREG_WORD (out)); + out = gen_rtx_REG (GET_MODE (out), subreg_regno (out)); /* Narrow down the class of register wanted if that is desirable on this machine for efficiency. */ @@ -1810,15 +1811,28 @@ find_dummy_reload (real_in, real_out, inloc, outloc, || GET_MODE_SIZE (inmode) > UNITS_PER_WORD)) return 0; + /* Note that {in,out}_offset are needed only when 'in' or 'out' + respectively refers to a hard register. */ + /* Find the inside of any subregs. */ while (GET_CODE (out) == SUBREG) { - out_offset = SUBREG_WORD (out); + if (GET_CODE (SUBREG_REG (out)) == REG + && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER) + out_offset += subreg_regno_offset (REGNO (SUBREG_REG (out)), + GET_MODE (SUBREG_REG (out)), + SUBREG_BYTE (out), + GET_MODE (out)); out = SUBREG_REG (out); } while (GET_CODE (in) == SUBREG) { - in_offset = SUBREG_WORD (in); + if (GET_CODE (SUBREG_REG (in)) == REG + && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER) + in_offset += subreg_regno_offset (REGNO (SUBREG_REG (in)), + GET_MODE (SUBREG_REG (in)), + SUBREG_BYTE (in), + GET_MODE (in)); in = SUBREG_REG (in); } @@ -2035,7 +2049,10 @@ operands_match_p (x, y) i = REGNO (SUBREG_REG (x)); if (i >= FIRST_PSEUDO_REGISTER) goto slow; - i += SUBREG_WORD (x); + i += subreg_regno_offset (REGNO (SUBREG_REG (x)), + GET_MODE (SUBREG_REG (x)), + SUBREG_BYTE (x), + GET_MODE (x)); } else i = REGNO (x); @@ -2045,7 +2062,10 @@ operands_match_p (x, y) j = REGNO (SUBREG_REG (y)); if (j >= FIRST_PSEUDO_REGISTER) goto slow; - j += SUBREG_WORD (y); + j += subreg_regno_offset (REGNO (SUBREG_REG (y)), + GET_MODE (SUBREG_REG (y)), + SUBREG_BYTE (y), + GET_MODE (y)); } else j = REGNO (y); @@ -2777,7 +2797,18 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) while (GET_CODE (operand) == SUBREG) { - offset += SUBREG_WORD (operand); + /* Offset only matters when operand is a REG and + it is a hard reg. This is because it is passed + to reg_fits_class_p if it is a REG and all pseudos + return 0 from that function. */ + if (GET_CODE (SUBREG_REG (operand)) == REG + && REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER) + { + offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)), + GET_MODE (SUBREG_REG (operand)), + SUBREG_BYTE (operand), + GET_MODE (operand)); + } operand = SUBREG_REG (operand); /* Force reload if this is a constant or PLUS or if there may be a problem accessing OPERAND in the outer mode. */ @@ -2828,6 +2859,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) ) #endif ) + /* This following hunk of code should no longer be + needed at all with SUBREG_BYTE. If you need this + code back, please explain to me why so I can + fix the real problem. -DaveM */ +#if 0 /* Subreg of a hard reg which can't handle the subreg's mode or which would handle that mode in the wrong number of registers for subregging to work. */ @@ -2841,7 +2877,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) != HARD_REGNO_NREGS (REGNO (operand), GET_MODE (operand)))) || ! HARD_REGNO_MODE_OK (REGNO (operand) + offset, - operand_mode[i])))) + operand_mode[i]))) +#endif + ) force_reload = 1; } @@ -3716,7 +3754,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) rtx operand = recog_data.operand[i]; while (GET_CODE (operand) == SUBREG) - operand = XEXP (operand, 0); + operand = SUBREG_REG (operand); if ((GET_CODE (operand) == MEM || (GET_CODE (operand) == REG && REGNO (operand) >= FIRST_PSEUDO_REGISTER)) @@ -3766,7 +3804,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) operand = *recog_data.operand_loc[i]; while (GET_CODE (operand) == SUBREG) - operand = XEXP (operand, 0); + operand = SUBREG_REG (operand); if (GET_CODE (operand) == REG) { if (modified[i] != RELOAD_WRITE) @@ -3789,7 +3827,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) rtx operand = recog_data.operand[i]; while (GET_CODE (operand) == SUBREG) - operand = XEXP (operand, 0); + operand = SUBREG_REG (operand); if ((GET_CODE (operand) == MEM || (GET_CODE (operand) == REG && REGNO (operand) >= FIRST_PSEUDO_REGISTER)) @@ -4303,7 +4341,7 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn, && regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0 && reg_equiv_constant[regno] != 0 && (tem = operand_subword (reg_equiv_constant[regno], - SUBREG_WORD (x), 0, + SUBREG_BYTE (x) / UNITS_PER_WORD, 0, GET_MODE (SUBREG_REG (x)))) != 0) { /* TEM is now a word sized constant for the bits from X that @@ -4329,7 +4367,7 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn, && (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))) { - int shift = SUBREG_WORD (x) * BITS_PER_WORD; + int shift = SUBREG_BYTE (x) * BITS_PER_UNIT; if (WORDS_BIG_ENDIAN) shift = (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) - GET_MODE_BITSIZE (GET_MODE (x)) @@ -4383,13 +4421,18 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn, the meaning of the memory access. */ enum machine_mode subreg_mode = GET_MODE (SUBREG_REG (x)); + /* SUBREG_REG (x) is a MEM, so we cant take the offset, instead we + calculate the register number as : + SUBREG_BYTE (x) / GET_MODE_SIZE (subreg_mode) */ if (is_set_dest) push_reload (NULL_RTX, SUBREG_REG (x), NULL_PTR, &SUBREG_REG (x), - find_valid_class (subreg_mode, SUBREG_WORD (x)), + find_valid_class (subreg_mode, + SUBREG_BYTE (x) / GET_MODE_SIZE (subreg_mode)), VOIDmode, subreg_mode, 0, 0, opnum, type); else push_reload (SUBREG_REG (x), NULL_RTX, &SUBREG_REG (x), NULL_PTR, - find_valid_class (subreg_mode, SUBREG_WORD (x)), + find_valid_class (subreg_mode, + SUBREG_BYTE (x) / GET_MODE_SIZE (subreg_mode)), subreg_mode, VOIDmode, 0, 0, opnum, type); } @@ -5075,7 +5118,11 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn) code0 = GET_CODE (op0); if (code0 == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER) op0 = gen_rtx_REG (word_mode, - REGNO (op0) + SUBREG_WORD (orig_op0)); + (REGNO (op0) + + subreg_regno_offset (REGNO (SUBREG_REG (orig_op0)), + GET_MODE (SUBREG_REG (orig_op0)), + SUBREG_BYTE (orig_op0), + GET_MODE (orig_op0)))); } if (GET_CODE (op1) == SUBREG) @@ -5083,8 +5130,14 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn) op1 = SUBREG_REG (op1); code1 = GET_CODE (op1); if (code1 == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER) + /* ??? Why is this given op1's mode and above for + ??? op0 SUBREGs we use word_mode? */ op1 = gen_rtx_REG (GET_MODE (op1), - REGNO (op1) + SUBREG_WORD (orig_op1)); + (REGNO (op1) + + subreg_regno_offset (REGNO (SUBREG_REG (orig_op1)), + GET_MODE (SUBREG_REG (orig_op1)), + SUBREG_BYTE (orig_op1), + GET_MODE (orig_op1)))); } if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE @@ -5492,7 +5545,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn) needless copies if SUBREG_REG is multi-word. */ if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER) { - int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x); + int regno = subreg_regno (x); if (! (context ? REGNO_OK_FOR_INDEX_P (regno) : REGNO_MODE_OK_FOR_BASE_P (regno, mode))) @@ -5646,15 +5699,10 @@ find_reloads_subreg_address (x, force_replace, opnum, type, if (force_replace || ! rtx_equal_p (tem, reg_equiv_mem[regno])) { - int offset = SUBREG_WORD (x) * UNITS_PER_WORD; + int offset = SUBREG_BYTE (x); unsigned outer_size = GET_MODE_SIZE (GET_MODE (x)); unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))); - if (BYTES_BIG_ENDIAN) - { - offset += MIN (inner_size, UNITS_PER_WORD); - offset -= MIN (outer_size, UNITS_PER_WORD); - } XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset); PUT_MODE (tem, GET_MODE (x)); @@ -5741,8 +5789,18 @@ subst_reloads (insn) *r->subreg_loc = SUBREG_REG (reloadreg); else { + int final_offset = + SUBREG_BYTE (*r->subreg_loc) + SUBREG_BYTE (reloadreg); + + /* When working with SUBREGs the rule is that the byte + offset must be a multiple of the SUBREG's mode. */ + final_offset = (final_offset / + GET_MODE_SIZE (GET_MODE (*r->subreg_loc))); + final_offset = (final_offset * + GET_MODE_SIZE (GET_MODE (*r->subreg_loc))); + *r->where = SUBREG_REG (reloadreg); - SUBREG_WORD (*r->subreg_loc) += SUBREG_WORD (reloadreg); + SUBREG_BYTE (*r->subreg_loc) = final_offset; } } else @@ -5843,12 +5901,24 @@ find_replacement (loc) if (GET_CODE (reloadreg) == REG) return gen_rtx_REG (GET_MODE (*loc), - REGNO (reloadreg) + SUBREG_WORD (*loc)); + (REGNO (reloadreg) + + subreg_regno_offset (REGNO (SUBREG_REG (*loc)), + GET_MODE (SUBREG_REG (*loc)), + SUBREG_BYTE (*loc), + GET_MODE (*loc)))); else if (GET_MODE (reloadreg) == GET_MODE (*loc)) return reloadreg; else - return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg), - SUBREG_WORD (reloadreg) + SUBREG_WORD (*loc)); + { + int final_offset = SUBREG_BYTE (reloadreg) + SUBREG_BYTE (*loc); + + /* When working with SUBREGs the rule is that the byte + offset must be a multiple of the SUBREG's mode. */ + final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (*loc))); + final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (*loc))); + return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg), + final_offset); + } } } @@ -5925,7 +5995,7 @@ refers_to_regno_for_reload_p (regno, endregno, x, loc) if (GET_CODE (SUBREG_REG (x)) == REG && REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER) { - unsigned int inner_regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x); + unsigned int inner_regno = subreg_regno (x); unsigned int inner_endregno = inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1); @@ -6020,7 +6090,10 @@ reg_overlap_mentioned_for_reload_p (x, in) { regno = REGNO (SUBREG_REG (x)); if (regno < FIRST_PSEUDO_REGISTER) - regno += SUBREG_WORD (x); + regno += subreg_regno_offset (REGNO (SUBREG_REG (x)), + GET_MODE (SUBREG_REG (x)), + SUBREG_BYTE (x), + GET_MODE (x)); } else if (GET_CODE (x) == REG) { |