https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98069
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |rsandifo at gcc dot gnu.org --- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> --- So before vectorization we have var_3.0_1 = var_3; iftmp.3_10 = var_3.0_1 != 0 ? -2147483648 : 0; _2 = (int) iftmp.3_10; d_11 = -2147483648 - _2; which should compute to 0. Now somewhere (split_constant_offset I'd bet) things go wrong and we produce in dataref analysis base_address: &arr_165 offset from base address: (ssizetype) ((sizetype) -_2 * 2) constant offset from base address: -4294967296 step: 2 base alignment: 32 base misalignment: 0 offset alignment: 2 step alignment: 2 base_object: arr_165 Access function 0: {d_11, +, 1}_2 from { ((sizetype) d_21) * 2, +, 2 }_2 as offset IV which split_constant_offset makes into { (sizetype) -_2 * 2, +, 2 }_2 + -4294967296. The logic is that we can dive into the (sizetype) extension from int since the operation on int cannot overflow (undefined behavior). We then strip the -2147483648 constant, thinking we can associate this as (sizetype)(0 - _2) + -2147483648 but of course 0 - _2 now overflows and we happily fold it to -_2. So here: static bool split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1, tree *var, tree *off, hash_map<tree, std::pair<tree, tree> > &cache, unsigned *limit) { ... case PLUS_EXPR: case MINUS_EXPR: if (TREE_CODE (op1) == INTEGER_CST) { split_constant_offset (op0, &var0, &off0, cache, limit); *var = var0; *off = size_binop (ocode, off0, fold_convert (ssizetype, op1)); return true; } split_constant_offset (op0, &var0, &off0, cache, limit); split_constant_offset (op1, &var1, &off1, cache, limit); *var = fold_build2 (code, type, var0, var1); we have to make sure that the expression we fold cannot overflow or use unsigned arithmetic. In fact, using unsigned arithmetic looks like the only reasonable thing since splitting out any constant is not trivially valid. We're doing (var0 + off0) +- (var1 + off1) -> (var0 +- var1) + (off0 + off1) where we know the left side doesn't overflow. This makes associating across the multiplication invalid where we do ((sizetype) (A +- B)) * 2 -> ((sizetype) A) * 2 +- B * 2 and thus from 0 * 2 we go to -2147483648 * 2 + -4294967296. Using unsigned arithmetic to make the inner op no longer undefined doesn't help here. So it looks like we cannot use TYPE_OVERFLOW_UNDEFINED to validate looking across widening conversions. Which points to the same area as PR97960.