Bah. After all that effort, it turns out that -- by design -- there is one special case where CONST_INTs are not sign-extended. Nonzero/true BImode integers are stored as STORE_FLAG_VALUE, which can be 1 rather than -1. So (const_int 1) can be a valid BImode integer -- and consequently (const_int -1) can be wrong -- even though BImode only has 1 bit.
It might be nice to change that, but for wide-int I think we should just treat rtxes like trees for now. Tested on powerpc64-linux-gnu and x86_64-linux-gnu. It fixes some ICEs seen on bfin-elf. OK to install? Thanks, Richard Index: gcc/rtl.h =================================================================== --- gcc/rtl.h (revision 204311) +++ gcc/rtl.h (working copy) @@ -1408,7 +1408,9 @@ { static const enum precision_type precision_type = VAR_PRECISION; static const bool host_dependent_precision = false; - static const bool is_sign_extended = true; + /* This ought to be true, except for the special case that BImode + is canonicalized to STORE_FLAG_VALUE, which might be 1. */ + static const bool is_sign_extended = false; static unsigned int get_precision (const rtx_mode_t &); static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int, const rtx_mode_t &); @@ -1430,10 +1432,6 @@ switch (GET_CODE (x.first)) { case CONST_INT: - if (precision < HOST_BITS_PER_WIDE_INT) - gcc_checking_assert (INTVAL (x.first) - == sext_hwi (INTVAL (x.first), precision)); - return wi::storage_ref (&INTVAL (x.first), 1, precision); case CONST_WIDE_INT: