This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix register corruption bug in ree


Hi,

While changing register costs for AArch64 (patches to follow), the test
gcc.target/aarch64/vect-mult.c fails. This is caused by ree inserting a TI mode copy of a DI
register. Since TI mode requires 2 registers, this results in silent corruption of the 2nd register.

After split2:

(insn 149 148 147 2 (set (reg:DI 3 x3 [90])
        (reg:DI 2 x2 [90])) vect-mull.c:78 34 {*movdi_aarch64}
     (nil))
(insn 152 127 153 2 (set (reg:TI 32 v0 [90])
        (zero_extend:TI (reg:DI 3 x3 [90]))) vect-mull.c:78 719 {aarch64_movtilow_di}
     (nil))

Ree transforms this into:

(insn 149 148 157 2 (set (reg:TI 32 v0)
        (zero_extend:TI (reg:DI 2 x2 [90]))) vect-mull.c:78 719 {aarch64_movtilow_di}
     (nil))
(insn 157 149 147 2 (set (reg:TI 3 x3)
        (reg:TI 32 v0)) vect-mull.c:78 -1
     (nil))

The TI mode in the second instruction means both x3 and x4 are assigned after expansion in split4
(rather than just x3 in the original instruction), corrupting x4. The fix is to ensure the inserted
copy will set only one register. Also ensure we always call get_extended_src_reg() rather than
assume there is always a single extend.

OK for commit?

Wilco

ChangeLog:
2014-09-04  Wilco Dijkstra  <wdijkstr@arm.com>

	* gcc/ree.c (combine_reaching_defs):
	Ensure inserted copy writes a single register.

---
 gcc/ree.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/gcc/ree.c b/gcc/ree.c
index 856745f..9aa1e36 100644
--- a/gcc/ree.c
+++ b/gcc/ree.c
@@ -743,6 +743,12 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
       if (!SCALAR_INT_MODE_P (GET_MODE (SET_DEST (PATTERN (cand->insn)))))
 	return false;
 
+      /* Ensure the destination of the copy is still a single register.  */
+      if (HARD_REGNO_NREGS (
+	  REGNO (get_extended_src_reg (SET_SRC (PATTERN (cand->insn)))),
+	  GET_MODE (SET_DEST (PATTERN (cand->insn)))) != 1)
+        return false;
+
       /* There's only one reaching def.  */
       rtx def_insn = state->defs_list[0];
 
@@ -792,7 +798,7 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
       start_sequence ();
       rtx pat = PATTERN (cand->insn);
       rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (pat)),
-                                 REGNO (XEXP (SET_SRC (pat), 0)));
+                                 REGNO (get_extended_src_reg (SET_SRC (pat))));
       rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (pat)),
                                  REGNO (SET_DEST (pat)));
       emit_move_insn (new_dst, new_src);
-- 
1.9.1




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]