re PR tree-optimization/83298 (wrong code at -O1, -O2 and -O3 on x86_64-linux-gnu)

PR tree-optimization/83298
	PR tree-optimization/83362
	PR tree-optimization/83383
	* gimple-ssa-evrp-analyze.h (class evrp_range_analyzer): Make
	push_value_range a public interface.  Add new argument to
	record_ranges_from_stmt.
	* gimple-ssa-evrp-analyze.c
	(evrp_range_analyzer::record_ranges_from_stmt): Add new argument.
	Update comments.  Handle recording temporary equivalences.
	* tree-ssa-dom.c (dom_opt_opt_walker::before_dom_children): Add
	new argument to call to evrp_range_analyzer::record_ranges_from_stmt.
	* gimple-ssa-evrp.c (evrp_dom_walker::before_dom_children): Likewise.
	* tree-ssa-threadedge.c: Include alloc-pool.h, vr-values.h and
	gimple-ssa-evrp-analyze.h.
	(record_temporary_equivalences_from_phis): Add new argument.  When
	the PHI arg is an SSA_NAME, set the result's range to the range
	of the PHI arg.
	(record_temporary_equivalences_from_stmts_at_dest): Record ranges
	from statements too.
	(thread_through_normal_block): Accept new argument, evrp_range_analyzer.
	Pass it down to children as needed.
	(thread_outgoing_edges): Likewise.
	(thread_across_edge): Likewise.   Push/pop range state as needed.
	* tree-ssa-threadedge.h (thread_outgoing_edges): Update prototype.

	PR tree-optimization/83298
	PR tree-optimization/83362
	PR tree-optimization/83383
	* gcc.c-torture/execute/pr83298.c: New test.
	* gcc.c-torture/execute/pr83362.c New test.
	* gcc.c-torture/execute/pr83383.c New test.

From-SVN: r255593
This commit is contained in:
Jeff Law 2017-12-12 15:46:46 -07:00 committed by Jeff Law
parent 708eab9b5b
commit df80fc5328
12 changed files with 222 additions and 23 deletions

View file

@ -1,3 +1,30 @@
2017-12-12 Jeff Law <law@redhat.com>
PR tree-optimization/83298
PR tree-optimization/83362
PR tree-optimization/83383
* gimple-ssa-evrp-analyze.h (class evrp_range_analyzer): Make
push_value_range a public interface. Add new argument to
record_ranges_from_stmt.
* gimple-ssa-evrp-analyze.c
(evrp_range_analyzer::record_ranges_from_stmt): Add new argument.
Update comments. Handle recording temporary equivalences.
* tree-ssa-dom.c (dom_opt_opt_walker::before_dom_children): Add
new argument to call to evrp_range_analyzer::record_ranges_from_stmt.
* gimple-ssa-evrp.c (evrp_dom_walker::before_dom_children): Likewise.
* tree-ssa-threadedge.c: Include alloc-pool.h, vr-values.h and
gimple-ssa-evrp-analyze.h.
(record_temporary_equivalences_from_phis): Add new argument. When
the PHI arg is an SSA_NAME, set the result's range to the range
of the PHI arg.
(record_temporary_equivalences_from_stmts_at_dest): Record ranges
from statements too.
(thread_through_normal_block): Accept new argument, evrp_range_analyzer.
Pass it down to children as needed.
(thread_outgoing_edges): Likewise.
(thread_across_edge): Likewise. Push/pop range state as needed.
* tree-ssa-threadedge.h (thread_outgoing_edges): Update prototype.
2017-12-12 Julia Koval <julia.koval@intel.com>
* config/i386/i386.c (PTA_SKYLAKE_AVX512): Add PTA_CLWB.

View file

@ -56,10 +56,20 @@ evrp_range_analyzer::evrp_range_analyzer () : stack (10)
vr_values = new class vr_values;
}
/* Push an unwinding marker onto the unwinding stack. */
void
evrp_range_analyzer::push_marker ()
{
stack.safe_push (std::make_pair (NULL_TREE, (value_range *)NULL));
}
/* Analyze ranges as we enter basic block BB. */
void
evrp_range_analyzer::enter (basic_block bb)
{
stack.safe_push (std::make_pair (NULL_TREE, (value_range *)NULL));
push_marker ();
record_ranges_from_incoming_edge (bb);
record_ranges_from_phis (bb);
bb->flags |= BB_VISITED;
@ -259,8 +269,13 @@ evrp_range_analyzer::record_ranges_from_phis (basic_block bb)
}
}
/* Record ranges from STMT into our VR_VALUES class. If TEMPORARY is
true, then this is a temporary equivalence and should be recorded
into the unwind table. Othewise record the equivalence into the
global table. */
void
evrp_range_analyzer::record_ranges_from_stmt (gimple *stmt)
evrp_range_analyzer::record_ranges_from_stmt (gimple *stmt, bool temporary)
{
tree output = NULL_TREE;
@ -273,10 +288,36 @@ evrp_range_analyzer::record_ranges_from_stmt (gimple *stmt)
vr_values->extract_range_from_stmt (stmt, &taken_edge, &output, &vr);
if (output)
{
vr_values->update_value_range (output, &vr);
/* Set the SSA with the value range. There are two cases to
consider. First (the the most common) is we are processing
STMT in a context where its resulting range globally holds
and thus it can be reflected into the global ranges and need
not be unwound as we leave scope.
/* Set the SSA with the value range. */
set_ssa_range_info (output, &vr);
The second case occurs if we are processing a statement in
a context where the resulting range must not be reflected
into the global tables and must be unwound as we leave
the current context. This happens in jump threading for
example. */
if (!temporary)
{
/* Case one. We can just update the underlying range
information as well as the global information. */
vr_values->update_value_range (output, &vr);
set_ssa_range_info (output, &vr);
}
else
{
/* We're going to need to unwind this range. We can
not use VR as that's a stack object. We have to allocate
a new range and push the old range onto the stack. We
also have to be very careful about sharing the underlying
bitmaps. Ugh. */
value_range *new_vr = vr_values->allocate_value_range ();
*new_vr = vr;
new_vr->equiv = NULL;
push_value_range (output, new_vr);
}
}
else
vr_values->set_defs_to_varying (stmt);
@ -333,10 +374,10 @@ evrp_range_analyzer::record_ranges_from_stmt (gimple *stmt)
}
}
/* Restore/pop VRs valid only for BB when we leave BB. */
/* Unwind recorded ranges to their most recent state. */
void
evrp_range_analyzer::leave (basic_block bb ATTRIBUTE_UNUSED)
evrp_range_analyzer::pop_to_marker (void)
{
gcc_checking_assert (!stack.is_empty ());
while (stack.last ().first != NULL_TREE)
@ -344,6 +385,15 @@ evrp_range_analyzer::leave (basic_block bb ATTRIBUTE_UNUSED)
stack.pop ();
}
/* Restore/pop VRs valid only for BB when we leave BB. */
void
evrp_range_analyzer::leave (basic_block bb ATTRIBUTE_UNUSED)
{
pop_to_marker ();
}
/* Push the Value Range of VAR to the stack and update it with new VR. */
void

View file

@ -31,13 +31,18 @@ class evrp_range_analyzer
}
void enter (basic_block);
void push_marker (void);
void pop_to_marker (void);
void leave (basic_block);
void record_ranges_from_stmt (gimple *);
void record_ranges_from_stmt (gimple *, bool);
/* Main interface to retrieve range information. */
value_range *get_value_range (const_tree op)
{ return vr_values->get_value_range (op); }
/* Record a new unwindable range. */
void push_value_range (tree var, value_range *vr);
/* Dump all the current value ranges. This is primarily
a debugging interface. */
void dump_all_value_ranges (FILE *fp)
@ -57,7 +62,6 @@ class evrp_range_analyzer
DISABLE_COPY_AND_ASSIGN (evrp_range_analyzer);
class vr_values *vr_values;
void push_value_range (tree var, value_range *vr);
value_range *pop_value_range (tree var);
value_range *try_find_new_range (tree, tree op, tree_code code, tree limit);
void record_ranges_from_incoming_edge (basic_block);

View file

@ -134,7 +134,7 @@ evrp_dom_walker::before_dom_children (basic_block bb)
print_gimple_stmt (dump_file, stmt, 0);
}
evrp_range_analyzer.record_ranges_from_stmt (stmt);
evrp_range_analyzer.record_ranges_from_stmt (stmt, false);
if (gcond *cond = dyn_cast <gcond *> (stmt))
{

View file

@ -1,3 +1,12 @@
2017-12-12 Jeff Law <law@redhat.com>
PR tree-optimization/83298
PR tree-optimization/83362
PR tree-optimization/83383
* gcc.c-torture/execute/pr83298.c: New test.
* gcc.c-torture/execute/pr83362.c New test.
* gcc.c-torture/execute/pr83383.c New test.
2017-12-12 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* lib/gcc-dg.exp (process-message): Avoid additional whitespace in

View file

@ -0,0 +1,11 @@
int a, b, c = 1;
int main ()
{
for (; b < 1; b++)
;
if (!(c * (a < 1)))
__builtin_abort ();
return 0;
}

View file

@ -0,0 +1,31 @@
typedef unsigned char u8;
typedef unsigned int u32;
u32 a, b, d, e;
u8 c;
static u32 __attribute__ ((noinline, noclone))
foo (u32 p)
{
do
{
e /= 0xfff;
if (p > c)
d = 0;
e -= 3;
e *= b <= a;
}
while (e >= 88030);
return e;
}
int
main (void)
{
u32 x = foo (1164);
if (x != 0xfd)
__builtin_abort ();
return 0;
}

View file

@ -0,0 +1,25 @@
/* PR tree-optimization/83383 */
unsigned long long int a = 16ULL;
unsigned char b = 195;
unsigned long long int c = ~0ULL;
unsigned char d = 1;
unsigned long long int e[2] = { 3625445792498952486ULL, 0 };
unsigned long long int f[2] = { 0, 8985037393681294663ULL };
unsigned long long int g = 5052410635626804928ULL;
void
foo ()
{
a = ((signed char) a) < b;
c = (d ? e[0] : 0) - (f[1] * a ? 1 : g);
}
int
main()
{
foo ();
if (a != 1 || c != 3625445792498952485ULL)
__builtin_abort ();
return 0;
}

View file

@ -1433,7 +1433,7 @@ dom_opt_dom_walker::before_dom_children (basic_block bb)
edge taken_edge = NULL;
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
evrp_range_analyzer.record_ranges_from_stmt (gsi_stmt (gsi));
evrp_range_analyzer.record_ranges_from_stmt (gsi_stmt (gsi), false);
taken_edge = this->optimize_stmt (bb, gsi);
}
@ -1456,6 +1456,7 @@ dom_opt_dom_walker::after_dom_children (basic_block bb)
x_vr_values = evrp_range_analyzer.get_vr_values ();
thread_outgoing_edges (bb, m_dummy_cond, m_const_and_copies,
m_avail_exprs_stack,
&evrp_range_analyzer,
simplify_stmt_for_jump_threading);
x_vr_values = NULL;

View file

@ -37,6 +37,9 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-dom.h"
#include "gimple-fold.h"
#include "cfganal.h"
#include "alloc-pool.h"
#include "vr-values.h"
#include "gimple-ssa-evrp-analyze.h"
/* To avoid code explosion due to jump threading, we limit the
number of statements we are going to copy. This variable
@ -114,17 +117,16 @@ potentially_threadable_block (basic_block bb)
}
/* Record temporary equivalences created by PHIs at the target of the
edge E. Record unwind information for the equivalences onto STACK.
edge E. Record unwind information for the equivalences into
CONST_AND_COPIES and EVRP_RANGE_DATA.
If a PHI which prevents threading is encountered, then return FALSE
indicating we should not thread this edge, else return TRUE.
If SRC_MAP/DST_MAP exist, then mark the source and destination SSA_NAMEs
of any equivalences recorded. We use this to make invalidation after
traversing back edges less painful. */
indicating we should not thread this edge, else return TRUE. */
static bool
record_temporary_equivalences_from_phis (edge e, const_and_copies *const_and_copies)
record_temporary_equivalences_from_phis (edge e,
const_and_copies *const_and_copies,
evrp_range_analyzer *evrp_range_analyzer)
{
gphi_iterator gsi;
@ -152,6 +154,14 @@ record_temporary_equivalences_from_phis (edge e, const_and_copies *const_and_cop
stmt_count++;
const_and_copies->record_const_or_copy (dst, src);
/* Also update the value range associated with DST, using
the range from SRC. */
if (evrp_range_analyzer && TREE_CODE (src) == SSA_NAME)
{
value_range *vr = evrp_range_analyzer->get_value_range (src);
evrp_range_analyzer->push_value_range (dst, vr);
}
}
return true;
}
@ -191,6 +201,7 @@ static gimple *
record_temporary_equivalences_from_stmts_at_dest (edge e,
const_and_copies *const_and_copies,
avail_exprs_stack *avail_exprs_stack,
evrp_range_analyzer *evrp_range_analyzer,
pfn_simplify simplify)
{
gimple *stmt = NULL;
@ -235,6 +246,11 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
if (stmt_count > max_stmt_count)
return NULL;
/* These are temporary ranges, do nto reflect them back into
the global range data. */
if (evrp_range_analyzer)
evrp_range_analyzer->record_ranges_from_stmt (stmt, true);
/* If this is not a statement that sets an SSA_NAME to a new
value, then do not try to simplify this statement as it will
not simplify in any way that is helpful for jump threading. */
@ -981,6 +997,7 @@ thread_through_normal_block (edge e,
gcond *dummy_cond,
const_and_copies *const_and_copies,
avail_exprs_stack *avail_exprs_stack,
evrp_range_analyzer *evrp_range_analyzer,
pfn_simplify simplify,
vec<jump_thread_edge *> *path,
bitmap visited)
@ -992,7 +1009,8 @@ thread_through_normal_block (edge e,
Note that if we found a PHI that made the block non-threadable, then
we need to bubble that up to our caller in the same manner we do
when we prematurely stop processing statements below. */
if (!record_temporary_equivalences_from_phis (e, const_and_copies))
if (!record_temporary_equivalences_from_phis (e, const_and_copies,
evrp_range_analyzer))
return -1;
/* Now walk each statement recording any context sensitive
@ -1000,6 +1018,7 @@ thread_through_normal_block (edge e,
gimple *stmt
= record_temporary_equivalences_from_stmts_at_dest (e, const_and_copies,
avail_exprs_stack,
evrp_range_analyzer,
simplify);
/* There's two reasons STMT might be null, and distinguishing
@ -1114,12 +1133,15 @@ thread_across_edge (gcond *dummy_cond,
edge e,
class const_and_copies *const_and_copies,
class avail_exprs_stack *avail_exprs_stack,
class evrp_range_analyzer *evrp_range_analyzer,
pfn_simplify simplify)
{
bitmap visited = BITMAP_ALLOC (NULL);
const_and_copies->push_marker ();
avail_exprs_stack->push_marker ();
if (evrp_range_analyzer)
evrp_range_analyzer->push_marker ();
stmt_count = 0;
@ -1133,6 +1155,7 @@ thread_across_edge (gcond *dummy_cond,
threaded = thread_through_normal_block (e, dummy_cond,
const_and_copies,
avail_exprs_stack,
evrp_range_analyzer,
simplify, path,
visited);
else
@ -1144,6 +1167,8 @@ thread_across_edge (gcond *dummy_cond,
e->dest);
const_and_copies->pop_to_marker ();
avail_exprs_stack->pop_to_marker ();
if (evrp_range_analyzer)
evrp_range_analyzer->pop_to_marker ();
BITMAP_FREE (visited);
register_jump_thread (path);
return;
@ -1169,6 +1194,8 @@ thread_across_edge (gcond *dummy_cond,
BITMAP_FREE (visited);
const_and_copies->pop_to_marker ();
avail_exprs_stack->pop_to_marker ();
if (evrp_range_analyzer)
evrp_range_analyzer->pop_to_marker ();
return;
}
}
@ -1196,6 +1223,8 @@ thread_across_edge (gcond *dummy_cond,
{
const_and_copies->pop_to_marker ();
avail_exprs_stack->pop_to_marker ();
if (evrp_range_analyzer)
evrp_range_analyzer->pop_to_marker ();
BITMAP_FREE (visited);
return;
}
@ -1211,6 +1240,8 @@ thread_across_edge (gcond *dummy_cond,
for each of E->dest's successors. */
const_and_copies->push_marker ();
avail_exprs_stack->push_marker ();
if (evrp_range_analyzer)
evrp_range_analyzer->push_marker ();
/* Avoid threading to any block we have already visited. */
bitmap_clear (visited);
@ -1238,6 +1269,7 @@ thread_across_edge (gcond *dummy_cond,
found = thread_through_normal_block (path->last ()->e, dummy_cond,
const_and_copies,
avail_exprs_stack,
evrp_range_analyzer,
simplify, path,
visited) > 0;
@ -1253,12 +1285,16 @@ thread_across_edge (gcond *dummy_cond,
delete_jump_thread_path (path);
/* And unwind the equivalence table. */
if (evrp_range_analyzer)
evrp_range_analyzer->pop_to_marker ();
avail_exprs_stack->pop_to_marker ();
const_and_copies->pop_to_marker ();
}
BITMAP_FREE (visited);
}
if (evrp_range_analyzer)
evrp_range_analyzer->pop_to_marker ();
const_and_copies->pop_to_marker ();
avail_exprs_stack->pop_to_marker ();
}
@ -1280,6 +1316,7 @@ void
thread_outgoing_edges (basic_block bb, gcond *dummy_cond,
class const_and_copies *const_and_copies,
class avail_exprs_stack *avail_exprs_stack,
class evrp_range_analyzer *evrp_range_analyzer,
tree (*simplify) (gimple *, gimple *,
class avail_exprs_stack *,
basic_block))
@ -1297,7 +1334,7 @@ thread_outgoing_edges (basic_block bb, gcond *dummy_cond,
{
thread_across_edge (dummy_cond, single_succ_edge (bb),
const_and_copies, avail_exprs_stack,
simplify);
evrp_range_analyzer, simplify);
}
else if ((last = last_stmt (bb))
&& gimple_code (last) == GIMPLE_COND
@ -1313,11 +1350,13 @@ thread_outgoing_edges (basic_block bb, gcond *dummy_cond,
more than one predecessor and more than one successor. */
if (potentially_threadable_block (true_edge->dest))
thread_across_edge (dummy_cond, true_edge,
const_and_copies, avail_exprs_stack, simplify);
const_and_copies, avail_exprs_stack,
evrp_range_analyzer, simplify);
/* Similarly for the ELSE arm. */
if (potentially_threadable_block (false_edge->dest))
thread_across_edge (dummy_cond, false_edge,
const_and_copies, avail_exprs_stack, simplify);
const_and_copies, avail_exprs_stack,
evrp_range_analyzer, simplify);
}
}

View file

@ -30,9 +30,11 @@ extern void threadedge_initialize_values (void);
extern void threadedge_finalize_values (void);
extern bool potentially_threadable_block (basic_block);
extern void propagate_threaded_block_debug_into (basic_block, basic_block);
class evrp_range_analyzer;
extern void thread_outgoing_edges (basic_block, gcond *,
const_and_copies *,
avail_exprs_stack *,
evrp_range_analyzer *,
tree (*) (gimple *, gimple *,
avail_exprs_stack *, basic_block));

View file

@ -6677,7 +6677,7 @@ vrp_dom_walker::after_dom_children (basic_block bb)
x_vr_values = vr_values;
thread_outgoing_edges (bb, m_dummy_cond, m_const_and_copies,
m_avail_exprs_stack,
m_avail_exprs_stack, NULL,
simplify_stmt_for_jump_threading);
x_vr_values = NULL;