On 05/24/2011 03:34 PM, Jeff Law wrote:
> 
> This has gone latent on the trunk, but the underlying issue hasn't been
> resolved.
> 
> ira.c::update_equiv_regs can create REG_EQUIV notes for equivalences
> which are local to a block rather than the traditional function-wide
> equivalences we typically work with.
> 
> This occurs when we have an insn that loads a pseudo from a MEM and the
> pseudo is used within only a single block and the MEM remains unchanged
> through the life of the pseudo.
> 
> Starting with the assumption that we're going to create a block local
> pseudo under the rules noted above, consider this RTL:
> 
> (set (reg X) (some address))
> (set (reg Y) (mem (reg X)))
> (use Y)
> 
> 
> We're going to create an equivalence between (reg Y) and its memory
> location in update_equiv_regs.  Assume IRA is able to allocate a hard
> reg for reg X, but not reg Y.
> 
> reload's strategy in this situation will be to remove the insn which
> creates the equivalence between reg Y and the memory location.  Uses of
> reg Y will be replaced with the equivalent memory location.
> 
> That's all fine and good, except reload uses delete_dead_insn, which
> deletes the equivalencing insn, but also recursively tries to remove the
> prior insn if it becomes dead as a result of removing the equivalencing
> insn.
> 
> Anyway, continuing with our example, reg X gets a hard reg, so our RTL
> will look something like
> 
> (set (reg 0) (some address))
> (set (reg Y) (mem (reg 0)))
> (use Y)
> 
> Then we remove the equivalencing insn resulting in
> 
> (set (reg 0) (some address)
> (use Y)
> 
> And we recurse from delete_dead_insn and determine that the first insn
> was dead as well, so it gets removed leaving:
> 
> (use Y)
> 
> We then replace Y with its equivalent memory location
> 
> (use (mem (reg 0))
> 
> At which point we lose because hard reg 0 is no longer initialized.
> 
> 
> The code in question is literally 20 years old and predates running any
> real dead code elimination after reload.  ISTM the right thing to do is
> stop using delete_dead_insn in this code and let the post-reload DCE
> pass do its job.  That allows us to continue to record the block local
> equivalence.

Sounds like the right thing to do. OK. (Can we eliminate the other caller?)

I've looked at code generation; it appears unchanged on i686-linux,
which I think is the expected result. There are minor differences in
assembly output on mips64-linux. If you want to look at it, I'm
attaching a testcase - compile with "-O2 -fno-reorder-blocks".


Bernd
  typedef _Bool bool;
  typedef struct {  volatile int counter; }
 atomic_t;
struct list_head {  struct list_head *next, *prev; };
   typedef void (*ctor_fn_t)(void);
struct kref {  atomic_t refcount; };
  struct kobject {  const char *name;  struct list_head entry;  struct kobject 
*parent;  struct kset *kset;  struct kobj_type *ktype;  struct sysfs_dirent 
*sd;  struct kref kref;  unsigned int state_initialized:1;  unsigned int 
state_in_sysfs:1;  unsigned int state_add_uevent_sent:1;  unsigned int 
state_remove_uevent_sent:1;  unsigned int uevent_suppress:1; };
  static inline __attribute__((always_inline)) void      _do_trace_module_get 
 (void (*probe)(char *name, bool wait, unsigned long ip)) { return -38; }
  struct module_kobject {  struct kobject kobj;  struct module *mod;  struct 
kobject *drivers_dir;  struct module_param_attrs *mp; };
enum module_state {  MODULE_STATE_LIVE,  MODULE_STATE_COMING,  
MODULE_STATE_GOING, };
  struct module {  enum module_state state;    struct list_head list;    char 
name[(64 - sizeof(unsigned long))];    struct module_kobject mkobj;  struct 
module_attribute *modinfo_attrs;  const char *version;  const char *srcversion; 
 struct kobject *holders_dir;    const struct kernel_symbol *syms;  const 
unsigned long *crcs;  unsigned int num_syms;    struct kernel_param *kp;  
unsigned int num_kp;    unsigned int num_gpl_syms;  const struct kernel_symbol 
*gpl_syms;  const unsigned long *gpl_crcs; 
 struct list_head modules_which_use_me;    struct task_struct *waiter;    void 
(*exit)(void);   struct module_ref {   unsigned int incs;   unsigned int decs;  
} *refptr;      ctor_fn_t *ctors;  unsigned int num_ctors;  };
static inline __attribute__((always_inline)) int bscnl_emit(char *buf, int 
buflen, int rbot, int rtop, int len) {  if (len > 0)   len += scnprintf(buf + 
len, buflen - len, ",");  if (rbot == rtop)   len += scnprintf(buf + len, 
buflen - len, "%d", rbot);  else   len += scnprintf(buf + len, buflen - len, 
"%d-%d", rbot, rtop);  return len; }
int bitmap_scnlistprintf(char *buf, unsigned int buflen,  const unsigned long 
*maskp, int nmaskbits) {  int len = 0;   int cur, rbot, rtop;   if (buflen == 
0)   return 0;  buf[0] = 0;   rbot = cur = find_next_bit((maskp), (nmaskbits), 
0);  while (cur < nmaskbits) {   rtop = cur;   cur = find_next_bit(maskp, 
nmaskbits, cur+1);   if (cur >= nmaskbits || cur > rtop + 1) {    len = 
bscnl_emit(buf, buflen, rbot, rtop, len);    rbot = cur;   }  }  return len; }

Reply via email to