[Bug rtl-optimization/40209] ICE in iv_analyze_def caused by stale REG_UNUSED note

steven at gcc dot gnu dot org gcc-bugzilla@gcc.gnu.org
Fri Jul 24 17:05:00 GMT 2009



------- Comment #6 from steven at gcc dot gnu dot org  2009-07-24 17:04 -------
Then we should write a new function, something like this in df.h perhaps:

/* Given an INSN, return a SET expression if the insn has only one
   SET whose SET_DEST is used.  If SET_DEST is memory, then the SET is
   assumed to be used somewhere, always.

   This means that:
   * If an insn has multiple SETs to only registers, but only one of those
     SETs is used, return that one set.
   * If an insn has multiple SETs to only registers, but none one of those
     SETs is used, return NULL_RTX.
   * If an insn has multiple SETs to registers and/or memory, but the SETs to
     registers are dead, return the one memory SET, or NULL_RTX if there are
     multiple sets to memory.

   Only accept INSNs.  single_set() can take a pattern, but that is 
   "old skool" style that should be abolished.

   May miss some single_set SETs that single_set() can find, because this
   function just looks for the number of uses of a register to determine
   whether a set is used (which may fail for hard registers and for unusual
   situations with pseudos that somehow are set twice but never used) whereas
   single_set() uses liveness information through REG_UNUSED notes.  Still,
   I expect that, in practice, this function works just as well as 
   single_set().

   One more caveat: The DF user must use incremental scanning, or the
   DF_REG_USE_COUNT may be wrong.  The result of df_single_set would be
   unconservative for new registers since the last scan (DF_REG_USE_COUNT
   will still be 0, indicating the new reg is unused and its SET can be
   ignored).  */

rtx
df_single_set (rtx insn)
{
  rtx pat;

  gcc_assert (INSN_P (insn));

  /* ??? Could even just fall back if the current DF mode is not incremental
         scanning.  */
  pat = PATTERN (insn);
  if (GET_CODE (pat) == SET)
    return pat;
  else if (GET_CODE (pat) == PARALLEL)
    {
      int i;
      rtx set = NULL_RTX;
      for (i = 0; i < XVECLEN (pat, 0); i++)
        {
          rtx sub = XVECEXP (pat, 0, i);
          switch (GET_CODE (sub))
          {
          case USE:
          case CLOBBER:
            break;

          case SET:
            if (! set)
              {
                rtx dest = SET_DEST (set);
                if (GET_CODE (dest) == SUBREG)
                  dest = SUBREG_REG (dest);
                if (! REG_P (dest)
                    || DF_REG_USE_COUNT (dest) > 0)
                  set = sub;
              }
            else
              return NULL_RTX;
            break;

          default:
            return NULL_RTX;
          }
        }
    }
  else
    return NULL_RTX;
}


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40209



More information about the Gcc-bugs mailing list