I notice that the following testcase:

    int x[4];
    void f1 (long long n) { while (n-- != 0) x[n] = 1; }
    void f2 (long long n) { while (n-- != 0) x[n] = 1; }
    void f3 (long long n) { while (n-- != 0) x[n] = 1; }

when compiled with optimisation enabled on i386-linux-gnu, causes us to
go through the main make_decl_rtl path 3 times for x.  I.e. we create
three separate (mem (symbol_ref ...))s for it.

This happens because tree-ssa-loop-ivopts.c:prepare_decl_rtl replaces
the original DECL_RTL with one of its own making:

    static tree
    prepare_decl_rtl (tree *expr_p, int *ws, void *data)
    {
      [...]
      switch (TREE_CODE (*expr_p))
        {
        case ADDR_EXPR:
          for (expr_p = &TREE_OPERAND (*expr_p, 0);
               handled_component_p (*expr_p);
               expr_p = &TREE_OPERAND (*expr_p, 0))
            continue;
          obj = *expr_p;
          if (DECL_P (obj))
            x = produce_memory_decl_rtl (obj, regno);
      [...]
      if (x)
        {
          VEC_safe_push (tree, heap, decl_rtl_to_reset, obj);
          SET_DECL_RTL (obj, x);
        }
    }

and the DECL_RTL is then nullified after the pass has finished.

There don't seem to be many comments explaining why we're doing
what we're doing here, so I'm not sure whether this was the intended
behaviour or not.  Do we really want to kick out existing DECL_RTLs,
or is there simply a missing !DECL_RTL_SET_P in the DECL_P condition:

          if (DECL_P (obj))
            x = produce_memory_decl_rtl (obj, regno);

?

(FWIW, this shows up for "int" ivs on mips64-elf, which is why I noticed.)

Richard

Reply via email to