diff mbox

[avr] Fix PR 65657 - read from __memx address space tramples arguments to function call

Message ID 552FE82D.5040501@gjlay.de
State New
Headers show

Commit Message

Georg-Johann Lay April 16, 2015, 4:49 p.m. UTC
...and the sketch against 4.9
diff mbox

Patch

Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c	(revision 221321)
+++ config/avr/avr.c	(working copy)
@@ -287,6 +287,94 @@  avr_to_int_mode (rtx x)
 }
 
 
+static void
+avr_rest_of_handle_expand_xload (void)
+{
+  basic_block bb;
+
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      rtx insn, next;
+
+      FOR_BB_INSNS_SAFE (bb, insn, next)
+        {
+          enum attr_fixregs fixregs;
+
+          if (-1 == recog_memoized (insn)
+              || FIXREGS_NO == (fixregs = get_attr_fixregs (insn)))
+            {
+              continue;
+            }
+            
+          avr_edump ("%?: Must fix insn:\n  %r\n\n", insn);
+          if (dump_file)
+            avr_fdump (dump_file, ";; Fixing insn :\n  %r\n\n", insn);
+
+          extract_insn (insn);
+
+          switch (fixregs)
+            {
+            default:
+              gcc_unreachable();
+
+            case FIXREGS_XLOADQI_A:
+              if (dump_file)
+                avr_fdump (dump_file, "$2 = %r\n\n", recog_data.operand[2]);
+              break;
+
+            case FIXREGS_XLOAD_A:
+              if (dump_file)
+                {
+                  avr_fdump (dump_file, "$2 = %r\n", recog_data.operand[2]);
+                  avr_fdump (dump_file, "$3 = %r\n", recog_data.operand[3]);
+                  avr_fdump (dump_file, "$4 = %r\n\n", recog_data.operand[4]);
+                }
+              break;
+            }
+        } // insn
+    }
+}
+
+
+static const pass_data avr_pass_data_expand_xload =
+{
+  RTL_PASS,       // type
+  "",             // name (will be patched)
+  OPTGROUP_NONE,  // optinfo_flags
+  false,          // has_gate
+  true,           // has_execute
+  TV_NONE,        // tv_id
+  0,              // properties_required
+  0,              // properties_provided
+  0,              // properties_destroyed
+  0,              // todo_flags_start
+  // todo_flags_finish
+  TODO_df_finish | TODO_verify_rtl_sharing | TODO_verify_flow
+};
+
+
+class avr_pass_expand_xload : public rtl_opt_pass
+{
+public:
+  avr_pass_expand_xload (gcc::context *ctxt, const char *name)
+    : rtl_opt_pass (avr_pass_data_expand_xload, ctxt)
+  {
+    this->name = name;
+  }
+
+  unsigned int execute (void)
+  {
+    df_lr_add_problem ();
+    df_live_add_problem ();
+    df_analyze ();
+
+    avr_rest_of_handle_expand_xload();
+
+    return 0;
+  }
+}; // avr_pass_recompute_notes
+
+
 static const pass_data avr_pass_data_recompute_notes =
 {
   RTL_PASS,       // type
@@ -326,6 +414,11 @@  public:
 static void
 avr_register_passes (void)
 {
+  /* This avr-specific fixed PR63633 for the case of mov insns.  */
+
+  register_pass (new avr_pass_expand_xload (g, "avr-expand-xload"),
+                 PASS_POS_INSERT_BEFORE, "split1", 1);
+
   /* This avr-specific pass (re)computes insn notes, in particular REG_DEAD
      notes which are used by `avr.c::reg_unused_after' and branch offset
      computations.  These notes must be correct, i.e. there must be no
Index: config/avr/avr.md
===================================================================
--- config/avr/avr.md	(revision 221321)
+++ config/avr/avr.md	(working copy)
@@ -165,6 +165,13 @@  (define_attr "isa"
    standard"
   (const_string "standard"))
 
+
+(define_attr "fixregs"
+  "xload_A, xloadQI_A,
+   no"
+  (const_string "no"))
+
+
 (define_attr "enabled" ""
   (cond [(eq_attr "isa" "standard")
          (const_int 1)
@@ -494,9 +501,9 @@  (define_insn "load_<mode>_libgcc"
 ;; "xload8qi_A"
 ;; "xload8qq_A" "xload8uqq_A"
 (define_insn_and_split "xload8<mode>_A"
-  [(set (match_operand:ALL1 0 "register_operand" "=r")
-        (match_operand:ALL1 1 "memory_operand"    "m"))
-   (clobber (reg:HI REG_Z))]
+  [(set (match_operand:ALL1 0 "register_operand"  "=r")
+        (match_operand:ALL1 1 "memory_operand"     "m"))
+   (clobber (match_operand:HI 2 "scratch_operand" "=z"))] ;; HI 30
   "can_create_pseudo_p()
    && !avr_xload_libgcc_p (<MODE>mode)
    && avr_mem_memx_p (operands[1])
@@ -505,6 +512,8 @@  (define_insn_and_split "xload8<mode>_A"
   "&& 1"
   [(clobber (const_int 0))]
   {
+    gcc_assert (SCRATCH != GET_CODE (operands[2]));
+
     /* ; Split away the high part of the address.  GCC's register allocator
        ; in not able to allocate segment registers and reload the resulting
        ; expressions.  Notice that no address register can hold a PSImode.  */
@@ -520,7 +529,9 @@  (define_insn_and_split "xload8<mode>_A"
     set_mem_addr_space (SET_SRC (single_set (insn)),
                                  MEM_ADDR_SPACE (operands[1]));
     DONE;
-  })
+  }
+  [(set_attr "fixregs" "xloadQI_A")])
+
 
 ;; "xloadqi_A" "xloadqq_A" "xloaduqq_A"
 ;; "xloadhi_A" "xloadhq_A" "xloaduhq_A" "xloadha_A" "xloaduha_A"
@@ -530,9 +541,9 @@  (define_insn_and_split "xload8<mode>_A"
 (define_insn_and_split "xload<mode>_A"
   [(set (match_operand:MOVMODE 0 "register_operand" "=r")
         (match_operand:MOVMODE 1 "memory_operand"    "m"))
-   (clobber (reg:MOVMODE 22))
-   (clobber (reg:QI 21))
-   (clobber (reg:HI REG_Z))]
+   (clobber (match_operand:MOVMODE 2 "scratch_operand" "=r"))   ;; MOVMODE 22
+   (clobber (match_operand:QI 3      "scratch_operand" "=r"))   ;; QI 21
+   (clobber (match_operand:HI 4      "scratch_operand" "=z"))]  ;; HI 30 (Z)
   "can_create_pseudo_p()
    && avr_mem_memx_p (operands[1])
    && REG_P (XEXP (operands[1], 0))"
@@ -540,6 +551,10 @@  (define_insn_and_split "xload<mode>_A"
   "&& 1"
   [(clobber (const_int 0))]
   {
+    gcc_assert (SCRATCH != GET_CODE (operands[2]));
+    gcc_assert (SCRATCH != GET_CODE (operands[3]));
+    gcc_assert (SCRATCH != GET_CODE (operands[4]));
+
     rtx addr = XEXP (operands[1], 0);
     rtx reg_z = gen_rtx_REG (HImode, REG_Z);
     rtx addr_hi8 = simplify_gen_subreg (QImode, addr, PSImode, 2);
@@ -558,7 +573,9 @@  (define_insn_and_split "xload<mode>_A"
     emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, 22));
 
     DONE;
-  })
+  }
+  [(set_attr "fixregs" "xload_A")])
+
 
 ;; Move value from address space memx to a register
 ;; These insns must be prior to respective generic move insn.
@@ -638,10 +655,10 @@  (define_expand "mov<mode>"
         if (!avr_xload_libgcc_p (<MODE>mode))
           /* ; No <mode> here because gen_xload8<mode>_A only iterates over ALL1.
              ; insn-emit does not depend on the mode, it's all about operands.  */
-          emit_insn (gen_xload8qi_A (dest, src));
+          emit_insn (gen_xload8qi_A (dest, src, gen_rtx_SCRATCH (HImode)));
         else
-          emit_insn (gen_xload<mode>_A (dest, src));
-
+          emit_insn (gen_xload<mode>_A (dest, src, gen_rtx_SCRATCH (<MODE>mode),
+                                        gen_rtx_SCRATCH (QImode), gen_rtx_SCRATCH (HImode)));
         DONE;
       }