Commit df80fc53 by Jeff Law Committed by Jeff Law

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
parent 708eab9b
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.
......@@ -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::enter (basic_block bb)
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)
{
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. */
set_ssa_range_info (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.
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
......
......@@ -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);
......
......@@ -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))
{
......
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
......
int a, b, c = 1;
int main ()
{
for (; b < 1; b++)
;
if (!(c * (a < 1)))
__builtin_abort ();
return 0;
}
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;
}
/* 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;
}
......@@ -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;
......
......@@ -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);
}
}
......@@ -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));
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment