On November 21, 2014 8:04:39 PM CET, Jakub Jelinek <ja...@redhat.com> wrote: >Hi! > >As discussed on IRC and in the PR, these internal calls are quite >unique for VRP in that they return _Complex integer result, >which VRP doesn't track, but then extract using >REALPART_EXPR/IMAGPART_EXPR >the two results from that _Complex int and to generate good code >it is desirable to get proper ranges of those two results. >The problem is that right now this works only on the first VRP >iteration, >the REALPART_EXPR/IMAGPART_EXPR statements are handled if their operand >is set by {ADD,SUB,MUL}_OVERFLOW. If we iterate because a VR of one >of the internal call arguments changes, nothing in the propagator marks >the REALPART_EXPR/IMAGPART_EXPR statements for reconsideration. > >The following patch handles this, by making the internal calls >interesting >to the propagator and returning the right SSA_PROP_* for it (depending >on >whether any of the value ranges of the REALPART_EXPR/IMAGPART_EXPR >immediate >uses would change or not). > >Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok. Thanks, Richard. >2014-11-21 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/64006 > * tree-vrp.c (stmt_interesting_for_vrp): Return true > for {ADD,SUB,MUL}_OVERFLOW internal calls. > (vrp_visit_assignment_or_call): For {ADD,SUB,MUL}_OVERFLOW > internal calls, check if any REALPART_EXPR/IMAGPART_EXPR > immediate uses would change their value ranges and return > SSA_PROP_INTERESTING if so, or SSA_PROP_NOT_INTERESTING > if there are some REALPART_EXPR/IMAGPART_EXPR immediate uses > interesting for vrp. > > * gcc.c-torture/execute/pr64006.c: New test. > >--- gcc/tree-vrp.c.jj 2014-11-21 10:17:05.000000000 +0100 >+++ gcc/tree-vrp.c 2014-11-21 13:12:09.895013334 +0100 >@@ -6949,6 +6949,20 @@ stmt_interesting_for_vrp (gimple stmt) > && (is_gimple_call (stmt) > || !gimple_vuse (stmt))) > return true; >+ else if (is_gimple_call (stmt) && gimple_call_internal_p (stmt)) >+ switch (gimple_call_internal_fn (stmt)) >+ { >+ case IFN_ADD_OVERFLOW: >+ case IFN_SUB_OVERFLOW: >+ case IFN_MUL_OVERFLOW: >+ /* These internal calls return _Complex integer type, >+ but are interesting to VRP nevertheless. */ >+ if (lhs && TREE_CODE (lhs) == SSA_NAME) >+ return true; >+ break; >+ default: >+ break; >+ } > } > else if (gimple_code (stmt) == GIMPLE_COND > || gimple_code (stmt) == GIMPLE_SWITCH) >@@ -7101,6 +7115,74 @@ vrp_visit_assignment_or_call (gimple stm > > return SSA_PROP_NOT_INTERESTING; > } >+ else if (is_gimple_call (stmt) && gimple_call_internal_p (stmt)) >+ switch (gimple_call_internal_fn (stmt)) >+ { >+ case IFN_ADD_OVERFLOW: >+ case IFN_SUB_OVERFLOW: >+ case IFN_MUL_OVERFLOW: >+ /* These internal calls return _Complex integer type, >+ which VRP does not track, but the immediate uses >+ thereof might be interesting. */ >+ if (lhs && TREE_CODE (lhs) == SSA_NAME) >+ { >+ imm_use_iterator iter; >+ use_operand_p use_p; >+ enum ssa_prop_result res = SSA_PROP_VARYING; >+ >+ set_value_range_to_varying (get_value_range (lhs)); >+ >+ FOR_EACH_IMM_USE_FAST (use_p, iter, lhs) >+ { >+ gimple use_stmt = USE_STMT (use_p); >+ if (!is_gimple_assign (use_stmt)) >+ continue; >+ enum tree_code rhs_code = gimple_assign_rhs_code (use_stmt); >+ if (rhs_code != REALPART_EXPR && rhs_code != IMAGPART_EXPR) >+ continue; >+ tree rhs1 = gimple_assign_rhs1 (use_stmt); >+ tree use_lhs = gimple_assign_lhs (use_stmt); >+ if (TREE_CODE (rhs1) != rhs_code >+ || TREE_OPERAND (rhs1, 0) != lhs >+ || TREE_CODE (use_lhs) != SSA_NAME >+ || !stmt_interesting_for_vrp (use_stmt) >+ || (!INTEGRAL_TYPE_P (TREE_TYPE (use_lhs)) >+ || !TYPE_MIN_VALUE (TREE_TYPE (use_lhs)) >+ || !TYPE_MAX_VALUE (TREE_TYPE (use_lhs)))) >+ continue; >+ >+ /* If there is a change in the value range for any of the >+ REALPART_EXPR/IMAGPART_EXPR immediate uses, return >+ SSA_PROP_INTERESTING. If there are any REALPART_EXPR >+ or IMAGPART_EXPR immediate uses, but none of them have >+ a change in their value ranges, return >+ SSA_PROP_NOT_INTERESTING. If there are no >+ {REAL,IMAG}PART_EXPR uses at all, >+ return SSA_PROP_VARYING. */ >+ value_range_t new_vr = VR_INITIALIZER; >+ extract_range_basic (&new_vr, use_stmt); >+ value_range_t *old_vr = get_value_range (use_lhs); >+ if (old_vr->type != new_vr.type >+ || !vrp_operand_equal_p (old_vr->min, new_vr.min) >+ || !vrp_operand_equal_p (old_vr->max, new_vr.max) >+ || !vrp_bitmap_equal_p (old_vr->equiv, new_vr.equiv)) >+ res = SSA_PROP_INTERESTING; >+ else >+ res = SSA_PROP_NOT_INTERESTING; >+ BITMAP_FREE (new_vr.equiv); >+ if (res == SSA_PROP_INTERESTING) >+ { >+ *output_p = lhs; >+ return res; >+ } >+ } >+ >+ return res; >+ } >+ break; >+ default: >+ break; >+ } > > /* Every other statement produces no useful ranges. */ > FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF) >--- gcc/testsuite/gcc.c-torture/execute/pr64006.c.jj 2014-11-21 >13:22:08.185160990 +0100 >+++ gcc/testsuite/gcc.c-torture/execute/pr64006.c 2014-11-21 >13:29:28.259119733 +0100 >@@ -0,0 +1,26 @@ >+/* PR tree-optimization/64006 */ >+ >+int v; >+ >+long __attribute__ ((noinline, noclone)) >+test (long *x, int y) >+{ >+ int i; >+ long s = 1; >+ for (i = 0; i < y; i++) >+ if (__builtin_mul_overflow (s, x[i], &s)) >+ v++; >+ return s; >+} >+ >+int >+main () >+{ >+ long d[7] = { 975, 975, 975, 975, 975, 975, 975 }; >+ long r = test (d, 7); >+ if (sizeof (long) * __CHAR_BIT__ == 64 && v != 1) >+ __builtin_abort (); >+ else if (sizeof (long) * __CHAR_BIT__ == 32 && v != 4) >+ __builtin_abort (); >+ return 0; >+} > > Jakub