http://gcc.gnu.org/bugzilla/show_bug.cgi?id=61111
--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> --- I rather suspect a merge error. The following two need to match to not oscillate: /* Minimize the number of bits set in C1, i.e. C1 := C1 & ~C2, unless (C1 & ~C2) | (C2 & C3) for some C3 is a mask of some mode which allows further optimizations. */ c1 &= msk; c2 &= msk; wide_int c3 = c1.and_not (c2); for (w = BITS_PER_UNIT; w <= width; w <<= 1) { wide_int mask = wi::mask (width - w, false, TYPE_PRECISION (type)); if (((c1 | c2) & mask) == mask && c1.and_not (mask) == 0) { c3 = mask; break; } } and /* Avoid the transform if arg1 is a mask of some mode which allows further optimizations. */ int pop = wi::popcount (warg1); if (!(pop >= BITS_PER_UNIT && exact_log2 (pop) != -1 && wi::mask (pop, false, warg1.get_precision ()) == warg1)) return fold_build2_loc (loc, code, type, op0, wide_int_to_tree (type, masked)); where the above is from unsigned HOST_WIDE_INT mask = HOST_WIDE_INT_M1U >> (HOST_BITS_PER_WIDE_INT - w); that doesn't match the wi::mask call which should instead use w, not width - w as argument? That fixes the testcase.