This is the mail archive of the gcc@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]

Redundant Load Elimination in GCSE


I am trying to implement an optimization in the GCSE/PRE to remove
redundant loads especially those that come after stores.
I have two problems in the current implementation of the GCSE:

Problem 1:
The current implementation of GCSE, removes redundant loads due to loads,
and it doesn't catch all the cases.
In the current GCSE implementation , the "expr_equiv_p"  checks if the
expressions are identical.
Thus, If there are two memory references that have different pseudo
register numbers, but they point to the same memory,
the memory expressions are not considered equivalent. In this case we need
alias information which is available in alias.c.
The function rtx_equal_for_memref_p (from alias.c) can do this for us. It
can check if two pseudo registers point to the same memory address and then
consider the two memory addresses as equivalent.
The question is: Is there are a reason not to use the
rtx_equal_for_memref_p to check for memory expressions equivalence?

Problem 2:
In the current implementation the redundant loads due to previous store to
the same location are not eliminated in any case.
This because stores are not considered as an evaluation of a memory
expression.
In my opinion (correct me if I am wrong), we can consider a store
expression (a pseudo to a memory) as setting the pseudo to the same value
as the memory in addition to changing the value stored in the memory. In
other words, it is equivalent to performing a load (to the same pseudo)
immediately after the store .
Thus, we can say that a store can make the memory expression available (in
that pseudo) at end of its basic block, put never anticipatable to the
beginning of the basic block.
So , if in the case of load we did the following (taken from hash_scan_set
in gcse.c):

        /* An expression is not anticipatable if its operands are
           modified before this insn or if this is not the only SET in
           this insn.  */
        int antic_p = oprs_anticipatable_p (src, insn) && single_set
(insn);
        /* An expression is not available if its operands are
           subsequently modified, including this insn.  It's also not
           available if this is a branch, because we can't insert
           a set after the branch.  */
        int avail_p = (oprs_available_p (src, insn) && ! JUMP_P (insn));

        insert_expr_in_table (src, GET_MODE (dest), insn, antic_p, avail_p,
table);

in case of store we can do the following:
        int antic_p = 0; /*Store is never anticipatable*/
        /* An expression is not available if its operands are
           subsequently modified, including this insn.  It's also not
           available if this is a branch, because we can't insert
           a set after the branch.  */
        int avail_p = (oprs_available_p (dest, insn) && ! JUMP_P (insn));
        insert_expr_in_table (dest, GET_MODE (dest), insn, antic_p,
avail_p, table);

Is there a reason not to do this?

Regards,
  Mostafa Hagog
 Systems and Software  Department
 IBM Research Lab in Haifa
 e-mail: mustafa@il.ibm.com
 Phone: +972 4 829-6518   Fax: +972 4 829-6116



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