summaryrefslogtreecommitdiff
path: root/gcc/postreload.c
diff options
context:
space:
mode:
authoramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>2013-05-30 11:07:05 +0000
committeramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>2013-05-30 11:07:05 +0000
commit5bea3269f082640f7314ed8db23137a982d97177 (patch)
treee04afbe88c9a495644dda56fb1c9e33e6253b249 /gcc/postreload.c
parent72cf5e1121bea5f6f52ce30fe20a885562128f61 (diff)
downloadgcc-5bea3269f082640f7314ed8db23137a982d97177.tar.gz
PR rtl-optimization/57439
* postreload.c (move2add_valid_value_p): Check that we have a zero subreg_regno_offset when accessing the register in the requested mode. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@199449 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/postreload.c')
-rw-r--r--gcc/postreload.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/gcc/postreload.c b/gcc/postreload.c
index 558ab8b867e..f340503f69c 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -1726,10 +1726,27 @@ move2add_record_sym_value (rtx reg, rtx sym, rtx off)
static bool
move2add_valid_value_p (int regno, enum machine_mode mode)
{
- if (reg_set_luid[regno] <= move2add_last_label_luid
- || !MODES_OK_FOR_MOVE2ADD (mode, reg_mode[regno]))
+ if (reg_set_luid[regno] <= move2add_last_label_luid)
return false;
+ if (mode != reg_mode[regno])
+ {
+ if (!MODES_OK_FOR_MOVE2ADD (mode, reg_mode[regno]))
+ return false;
+ /* The value loaded into regno in reg_mode[regno] is also valid in
+ mode after truncation only if (REG:mode regno) is the lowpart of
+ (REG:reg_mode[regno] regno). Now, for big endian, the starting
+ regno of the lowpart might be different. */
+ int s_off = subreg_lowpart_offset (mode, reg_mode[regno]);
+ s_off = subreg_regno_offset (regno, reg_mode[regno], s_off, mode);
+ if (s_off != 0)
+ /* We could in principle adjust regno, check reg_mode[regno] to be
+ BLKmode, and return s_off to the caller (vs. -1 for failure),
+ but we currently have no callers that could make use of this
+ information. */
+ return false;
+ }
+
for (int i = hard_regno_nregs[regno][mode] - 1; i > 0; i--)
if (reg_mode[regno + i] != BLKmode)
return false;