> On Aug 28, 2017, at 12:57 PM, Bill Schmidt <wschm...@linux.vnet.ibm.com> > wrote: > > 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.
I think you still need the specific test for whether the original bump fits in an HWI, since wide_int_to_tree will convert to a tree that only stores a single HWI, right? I'll test with that remaining in place but otherwise follow the direction of your suggestion. Bill > > 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