The validity check in do_check_validity was passing the address mode
(GET_MODE of the address RTX, e.g. DImode) to memory_address_addr_space_p
instead of the memory access mode (GET_MODE of the MEM RTX, e.g. SImode).
The first argument to memory_address_addr_space_p is the mode of the
memory access, not the address mode.

On targets where address validity depends on the access width (e.g.
alignment-sensitive modes, vector modes), this could accept an illegal
offset or reject a valid one.

Rename the variable to 'addr_mode' for address construction and add a
separate 'mem_mode' for the validity check.

gcc/ChangeLog:

        * fold-mem-offsets.cc (do_check_validity): fix wrong mode
        and rename arguments to avoid future confusion
---

 gcc/fold-mem-offsets.cc | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/gcc/fold-mem-offsets.cc b/gcc/fold-mem-offsets.cc
index 9ac4a59ace6b..1cd2dc036c2f 100644
--- a/gcc/fold-mem-offsets.cc
+++ b/gcc/fold-mem-offsets.cc
@@ -688,14 +688,16 @@ do_check_validity (rtx_insn *insn, fold_mem_info *info)
   int icode = INSN_CODE (insn);
   INSN_CODE (insn) = -1;
   rtx mem_addr = XEXP (mem, 0);
-  machine_mode mode = GET_MODE (mem_addr);
+  machine_mode addr_mode = GET_MODE (mem_addr);
+  machine_mode mem_mode = GET_MODE (mem);
   if (new_offset != 0)
-    XEXP (mem, 0) = gen_rtx_PLUS (mode, reg, gen_int_mode (new_offset, mode));
+    XEXP (mem, 0) = gen_rtx_PLUS (addr_mode, reg,
+                                  gen_int_mode (new_offset, addr_mode));
   else
     XEXP (mem, 0) = reg;
 
   bool illegal = insn_invalid_p (insn, false)
-                || !memory_address_addr_space_p (mode, XEXP (mem, 0),
+                || !memory_address_addr_space_p (mem_mode, XEXP (mem, 0),
                                                  MEM_ADDR_SPACE (mem));
 
   /* Restore the instruction.  */
-- 
2.34.1

Reply via email to