------- 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