Richard Biener <rguent...@suse.de> writes: >> @@ -812,33 +997,80 @@ split_constant_offset_1 (tree type, tree op0, enum >> tree_code code, tree op1, >> } >> } >> >> -/* Expresses EXP as VAR + OFF, where off is a constant. The type of OFF >> - will be ssizetype. */ >> +/* If EXP has pointer type, try to express it as: >> + >> + POINTER_PLUS <*VAR, (sizetype) *OFF> >> + >> + where: >> + >> + - *VAR has the same type as EXP >> + - *OFF is a constant of type ssizetype. >> + >> + If EXP has an integral type, try to express (sizetype) EXP as: >> + >> + *VAR + (sizetype) *OFF >> + >> + where: >> + >> + - *VAR has type sizetype >> + - *OFF is a constant of type ssizetype. >> + >> + If EXP_RANGE is nonnull, set it to the range of EXP. >> + >> + CACHE caches {*VAR, *OFF} pairs for SSA names that we've previously >> + visited. LIMIT counts down the number of SSA names that we are >> + allowed to process before giving up. */ >> >> static void >> -split_constant_offset (tree exp, tree *var, tree *off, >> +split_constant_offset (tree exp, tree *var, tree *off, value_range >> *exp_range, >> hash_map<tree, std::pair<tree, tree> > &cache, >> unsigned *limit) >> { >> - tree type = TREE_TYPE (exp), op0, op1, e, o; >> + tree type = TREE_TYPE (exp), op0, op1; >> enum tree_code code; >> >> - *var = exp; >> - *off = ssize_int (0); >> + code = TREE_CODE (exp); >> + if (exp_range) >> + { >> + *exp_range = type; >> + if (code == SSA_NAME) >> + { >> + wide_int var_min, var_max; >> + value_range_kind vr_kind = get_range_info (exp, &var_min, &var_max); >> + wide_int var_nonzero = get_nonzero_bits (exp); >> + vr_kind = intersect_range_with_nonzero_bits (vr_kind, >> + &var_min, &var_max, >> + var_nonzero, >> + TYPE_SIGN (type)); >> + if (vr_kind == VR_RANGE) >> + *exp_range = value_range (type, var_min, var_max); >> + } >> + } >> >> - if (tree_is_chrec (exp) >> - || get_gimple_rhs_class (TREE_CODE (exp)) == GIMPLE_TERNARY_RHS) >> - return; >> + if (!tree_is_chrec (exp) >> + && get_gimple_rhs_class (TREE_CODE (exp)) != GIMPLE_TERNARY_RHS) >> + { >> + extract_ops_from_tree (exp, &code, &op0, &op1); >> + if (split_constant_offset_1 (type, op0, code, op1, var, off, >> + exp_range, cache, limit)) >> + return; >> + } >> >> - code = TREE_CODE (exp); >> - extract_ops_from_tree (exp, &code, &op0, &op1); >> - if (split_constant_offset_1 (type, op0, code, op1, &e, &o, cache, limit)) >> + *var = exp; >> + if (INTEGRAL_TYPE_P (type)) >> + *var = fold_convert (sizetype, *var); >> + *off = ssize_int (0); >> + if (exp_range && code != SSA_NAME) >> { >> - *var = e; >> - *off = o; >> + wide_int var_min, var_max; >> + if (determine_value_range (exp, &var_min, &var_max) == VR_RANGE) >> + *exp_range = value_range (type, var_min, var_max); > > So this call is only for the case the recursion failed, otherwise > we build exp_range during the recursive call, correct?
Yeah, that's right. > The patch is OK. Thanks. For the record, now also tested on x86_64-linux-gnu. I'm not sure what to do about backports though. It seems a bit invasive for GCC 8 and 9 at least (PR95396). Richard