https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70310
--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> --- So we end up with 0 < 0 from tree aa1 = tree_vec_extract (gsi, comp_inner_type, a1, width, index); tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2, width, index); aa = build2 (TREE_CODE (a), cond_type, aa1, aa2); which we then somehow fold to -1(OVF) because fold_invert_truthvalue makes 0 >= 0 from 0 < 0 which we then feed into fold_cond_expr_with_comparison which hits case GE_EXPR: /* If C1 is C2 + 1, this is max(A, C2), with the same care as above. */ if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type), OEP_ONLY_CONST) && operand_equal_p (arg01, const_binop (PLUS_EXPR, arg2, build_int_cst (type, 1)), OEP_ONLY_CONST)) { tem = fold_build2_loc (loc, MAX_EXPR, TREE_TYPE (arg00), arg00, fold_convert_loc (loc, TREE_TYPE (arg00), arg2)); _but_ arg00 is unsigned! It looks like this transform isn't fully correct for mixed sign compare op vs. result type. Note we also aggressively strip nops in this function. For this particular bug it's of course best to simplify the comparison.