In fold_unary, CASE_CONVERT, the folding of the conversion into a bitwise AND is performed only for INTEGER_TYPE, while it could very likely be performed for BOOLEAN_TYPE and ENUMERAL_TYPE as well: /* Convert (T)(x & c) into (T)x & (T)c, if c is an integer constants (if x has signed type, the sign bit cannot be set in c). This folds extension into the BIT_AND_EXPR. ??? We don't do it for BOOLEAN_TYPE or ENUMERAL_TYPE because they very likely don't have maximal range for their precision and this transformation effectively doesn't preserve non-maximal ranges. */ if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (op0) == BIT_AND_EXPR && TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST) The problem is that the transformation doesn't preserve non-maximal ranges for a given precision and, as a consequence, VRP can draw different conclusions on each side. See gnat.dg/bit_packed_array3.adb.
Confirmed.
during VRP1 removes the casts now. So I don't know if this bug should be closed as fixed or not.