On Thu, 10 Dec 2020, Richard Sandiford wrote: > 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).
I'd say we try for GCC 10 and only then decide (which means GCC 8 very likely not getting it). Richard.