On 2020-10-20 1:33 a.m., Hongtao Liu wrote:
On Mon, Oct 19, 2020 at 11:38 PM Vladimir Makarov <vmaka...@redhat.com> wrote:

On 2020-10-11 8:58 p.m., Hongtao Liu wrote:
Hi:
    This is done in 2 steps:
    1. Extend special memory constraint to handle non MEM_P cases, i.e.
(vec_duplicate:V4SF (mem:SF (addr)))
    2. Refactor implementation of *_bcst{_1,_2,_3} patterns. Add new
predicate bcst_mem_operand and corresponding constraint "Br" to merge
"$(pattern)_bcst{_1,_2,_3}" into "$(pattern)", also delete those
separate "*_bcst{_1,_2,_3}" patterns.

    Bootstrap is ok, regression test on i386 backend is ok.

gcc/ChangeLog:

          PR target/87767
          * ira-costs.c (record_operand_costs): Extract memory operand
          from recog_data.operand[i] for record_address_regs.
          (record_reg_classes): Extract memory operand from OP for
          conditional judgement MEM_P.
          * ira.c (ira_setup_alts): Ditto.
          * lra-constraints.c (extract_mem_from_operand): New function.
          (satisfies_memory_constraint_p): Extract memory operand from
          OP for decompose_mem_address, return false when there's no
          memory operand inside OP.
          (process_alt_operands): Remove MEM_P (op) since it would be
          judged in satisfies_memory_constraint_p.
          * recog.c (asm_operand_ok): Extract memory operand from OP for
          judgement of memory_operand (OP, VOIDmode).
          (constrain_operands): Don't unwrapper unary operator when
          there's memory operand inside.
          * rtl.h (extract_mem_from_operand): New decl.

Thank you for working on the PR.  In general patch is ok for me. The
only thing is

+/* For special_memory_operand, it could be false for MEM_P (op),
+   i.e. bcst_mem_operand in i386 backend.
+   Extract and return real memory operand or op.  */
+rtx
+extract_mem_from_operand (rtx op)
+{
+  if (MEM_P (op))
+    return op;
+  /* Only allow one memory_operand inside special memory operand.  */

The comment contradicts to the below code which returns the first memory 
operand (not the only one).

Yes.

+  subrtx_var_iterator::array_type array;
+  FOR_EACH_SUBRTX_VAR (iter, array, op, ALL)
+    {
+      rtx x = *iter;
+      if (MEM_P (x))
+       return x;
+    }
+
+  return op;
+}
+

I think the code should look like

/* For special_memory_operand, it could be false for MEM_P (op),
     i.e. bcst_mem_operand in i386 backend.
     Extract and return real memory operand or op.  */
rtx
extract_mem_from_operand (rtx op)
{
    if (MEM_P (op))
      return op;
    /* Only allow one memory_operand inside special memory operand.  */
    subrtx_var_iterator::array_type array;
    rtx res = op;
    FOR_EACH_SUBRTX_VAR (iter, array, op, ALL)
      {
        rtx x = *iter;
        if (!MEM_P (x) || res != op)
          return op;
        res = op;
Assume you want to assign res with x.
Also in the iteration, x would first be op which would be false for
MEM_P, then op would be returned.
That's not what you mean, so i changed to

   /* Only allow one memory_operand inside special memory operand.  */
   subrtx_var_iterator::array_type array;
   rtx res = op;
   FOR_EACH_SUBRTX_VAR (iter, array, op, ALL)
     {
       rtx x = *iter;
       if (!MEM_P (x))
         continue;
       /* Return op when there're multiple memory operands.  */
       if (res != op)
         return op;
       else
         res = x;
     }

Actually I wanted to have constraint satisfying rtx with memory covered by **only unary** operator(s).  Your code satisfies memory covered by non-unary operators (e.g. binary ones).

Why do I prefer less general constraint? Because other operands of operator containing the memory might need reloads too and the more general constraint will ignore this. If this situation is impossible now, it might be possible in the future.

My proposed code is wrong as I forgot that FOR_EACH_SUBRTX_VAR processes sub-rtx recursively.  Thank you for starting the discussion.  Now I think the code should look like

/* For special_memory_operand, it could be false for MEM_P (op),
    i.e. bcst_mem_operand in i386 backend.
    Extract and return real memory operand or op.  */
rtx
extract_mem_from_operand (rtx op)
{
  for (rtx x = op;; x = XEXP (x, 0)) {

   if (MEM_P (x))
     return x;
   if (GET_RTX_LENGTH (GET_CODE (x)) != 1 || GET_RTX_FORMAT (GET_CODE (x))[0] != 'e')
     break;

  }

  return op;

}

Let me know what do you think.

Reply via email to