On Aug 28, 2017, at 7:37 AM, Richard Biener <richard.guent...@gmail.com> wrote: > > On Thu, Aug 3, 2017 at 9:34 PM, Bill Schmidt > <wschm...@linux.vnet.ibm.com> wrote: >> Hi, >> >> Here's v2 of the patch with Jakub's suggestions incorporated. Bootstrapped >> and tested on powerpc64le-linux-gnu with no regressions. Is this ok for >> trunk? >> >> Eventually this should be backported to all active releases as well. >> Ok for that after a week or so of burn-in? (And after 7.2, I imagine.) >> >> Thanks, >> Bill >> >> >> [gcc] >> >> 2017-08-03 Bill Schmidt <wschm...@linux.vnet.ibm.com> >> Jakub Jelinek <ja...@redhat.com> >> >> PR tree-optimization/81503 >> * gimple-ssa-strength-reduction.c (replace_mult_candidate): Ensure >> folded constant fits in the target type. >> >> [gcc/testsuite] >> >> 2017-08-03 Bill Schmidt <wschm...@linux.vnet.ibm.com> >> Jakub Jelinek <ja...@redhat.com> >> >> PR tree-optimization/81503 >> * gcc.c-torture/execute/pr81503.c: New file. >> >> >> Index: gcc/gimple-ssa-strength-reduction.c >> =================================================================== >> --- gcc/gimple-ssa-strength-reduction.c (revision 250791) >> +++ gcc/gimple-ssa-strength-reduction.c (working copy) >> @@ -2074,6 +2074,10 @@ replace_mult_candidate (slsr_cand_t c, tree basis_ >> { >> tree target_type = TREE_TYPE (gimple_assign_lhs (c->cand_stmt)); >> enum tree_code cand_code = gimple_assign_rhs_code (c->cand_stmt); >> + unsigned int prec = TYPE_PRECISION (target_type); >> + tree maxval = (POINTER_TYPE_P (target_type) >> + ? TYPE_MAX_VALUE (sizetype) >> + : TYPE_MAX_VALUE (target_type)); >> >> /* It is highly unlikely, but possible, that the resulting >> bump doesn't fit in a HWI. Abandon the replacement >> @@ -2082,6 +2086,17 @@ replace_mult_candidate (slsr_cand_t c, tree basis_ >> types but allows for safe negation without twisted logic. */ >> if (wi::fits_shwi_p (bump) >> && bump.to_shwi () != HOST_WIDE_INT_MIN >> + /* It is more likely that the bump doesn't fit in the target >> + type, so check whether constraining it to that type changes >> + the value. For a signed type, the value mustn't change. >> + For an unsigned type, the value may only change to a >> + congruent value (for negative bumps). */ >> + && (TYPE_UNSIGNED (target_type) >> + ? wi::eq_p (wi::neg_p (bump) >> + ? bump + wi::to_widest (maxval) + 1 >> + : bump, >> + wi::zext (bump, prec)) >> + : wi::eq_p (bump, wi::sext (bump, prec))) > > Not sure, but would it be fixed in a similar way when writing > > @@ -2089,16 +2089,9 @@ replace_mult_candidate (slsr_cand_t c, t > tree target_type = TREE_TYPE (gimple_assign_lhs (c->cand_stmt)); > enum tree_code cand_code = gimple_assign_rhs_code (c->cand_stmt); > > - /* It is highly unlikely, but possible, that the resulting > - bump doesn't fit in a HWI. Abandon the replacement > - in this case. This does not affect siblings or dependents > - of C. Restriction to signed HWI is conservative for unsigned > - types but allows for safe negation without twisted logic. */ > - if (wi::fits_shwi_p (bump) > - && bump.to_shwi () != HOST_WIDE_INT_MIN > - /* It is not useful to replace casts, copies, negates, or adds of > - an SSA name and a constant. */ > - && cand_code != SSA_NAME > + /* It is not useful to replace casts, copies, negates, or adds of > + an SSA name and a constant. */ > + if (cand_code != SSA_NAME > && !CONVERT_EXPR_CODE_P (cand_code) > && cand_code != PLUS_EXPR > && cand_code != POINTER_PLUS_EXPR > @@ -2109,18 +2102,25 @@ replace_mult_candidate (slsr_cand_t c, t > tree bump_tree; > gimple *stmt_to_print = NULL; > > - /* If the basis name and the candidate's LHS have incompatible > - types, introduce a cast. */ > - if (!useless_type_conversion_p (target_type, TREE_TYPE (basis_name))) > - basis_name = introduce_cast_before_cand (c, target_type, basis_name); > if (wi::neg_p (bump)) > { > code = MINUS_EXPR; > bump = -bump; > } > + /* It is possible that the resulting bump doesn't fit in target_type. > + Abandon the replacement in this case. This does not affect > + siblings or dependents of C. */ > + if (bump != wi::ext (bump, TYPE_PRECISION (target_type), > + TYPE_SIGN (target_type))) > + return; > > bump_tree = wide_int_to_tree (target_type, bump); > > + /* If the basis name and the candidate's LHS have incompatible > + types, introduce a cast. */ > + if (!useless_type_conversion_p (target_type, TREE_TYPE (basis_name))) > + basis_name = introduce_cast_before_cand (c, target_type, basis_name); > + > if (dump_file && (dump_flags & TDF_DETAILS)) > { > fputs ("Replacing: ", dump_file); > > ?
Ah, I see what you're going for. It looks reasonable on the surface. Let me do some testing and think about it a little more. Thanks! Bill > >> /* It is not useful to replace casts, copies, negates, or adds of >> an SSA name and a constant. */ >> && cand_code != SSA_NAME >> Index: gcc/testsuite/gcc.c-torture/execute/pr81503.c >> =================================================================== >> --- gcc/testsuite/gcc.c-torture/execute/pr81503.c (nonexistent) >> +++ gcc/testsuite/gcc.c-torture/execute/pr81503.c (working copy) >> @@ -0,0 +1,15 @@ >> +unsigned short a = 41461; >> +unsigned short b = 3419; >> +int c = 0; >> + >> +void foo() { >> + if (a + b * ~(0 != 5)) >> + c = -~(b * ~(0 != 5)) + 2147483647; >> +} >> + >> +int main() { >> + foo(); >> + if (c != 2147476810) >> + return -1; >> + return 0; >> +} >> >> >> On 8/3/17 1:02 PM, Bill Schmidt wrote: >>>> On Aug 3, 2017, at 11:39 AM, Jakub Jelinek <ja...@redhat.com> wrote: >>>> >>>> On Thu, Aug 03, 2017 at 11:29:44AM -0500, Bill Schmidt wrote: >>>>>> And, wouldn't it be more readable to use: >>>>>> && (TYPE_UNSIGNED (target_type) >>>>>> ? (wi::eq_p (bump, wi::zext (bump, prec)) >>>>>> || wi::eq_p (bump + wi::to_widest (maxval) + 1, >>>>>> wi::zext (bump, prec))) >>>>>> : wi::eq_p (bump, wi::sext (bump, prec))) >>>>>> ? >>>>> Probably. As noted, it's all becoming a bit unreadable with too >>>>> much negative logic in a long conditional, so I want to clean that >>>>> up in a follow-up. >>>>> >>>>>> For TYPE_UNSIGNED, do you actually need any restriction? >>>>>> What kind of bump values are wrong for unsigned types and why? >>>>> If the value of the bump is actually larger than the precision of the >>>>> type (not likely except for quite small types), say 2 * (maxval + 1) >>>>> which is congruent to 0, the replacement is wrong. >>>> Ah, ok. Anyway, for unsigned type, perhaps it could be written as: >>>> && (TYPE_UNSIGNED (target_type) >>>> ? wi::eq_p (wi::neg_p (bump) ? bump + wi::to_widest (maxval) + 1 >>>> : bump, wi::zext (bump, prec)) >>>> : wi::eq_p (bump, wi::sext (bump, prec))) >>>> I mean, if bump >= 0, then the bump + wi::to_widest (maxval) + 1 >>>> value has no chance to be equal to zero extended bump, and >>>> for bump < 0 only that one has a chance. >>> Yeah, that's true. And arguably my case for the really large bump >>> causing problems is kind of thin, because the program is probably >>> already broken in that case anyway. But I think I will sleep better >>> having the check in there, as somebody other than SLSR will catch >>> the bug then. ;-) >>> >>> Thanks for all the help with this one. These corner cases are >>> always tricky, and I appreciate the extra eyeballs. >>> >>> Bill >>> >>>> Jakub