Fix PR45230, PR45231, and PR45370: fold_stmt_inplace after replace_exp.

2010-12-08  Richard Guenther  <rguenther@suse.de>
	    Sebastian Pop  <sebastian.pop@amd.com>

	PR tree-optimization/45230
	PR tree-optimization/45231
	PR tree-optimization/45370
	* sese.c (rename_uses): Returns a bool.  Call
	recompute_tree_invariant_for_addr_expr only on the RHS of a
	GIMPLE_ASSIGN.
	(graphite_copy_stmts_from_block): Call fold_stmt_inplace when
	rename_uses returns true.
	* tree-ssa-copy.c (replace_exp): Add a comment about calling
	fold_stmt_inplace after replace_exp.

	* gcc.dg/graphite/id-pr45230-1.c: New.
	* gcc.dg/graphite/id-pr45231.c: New.
	* gfortran.dg/graphite/id-pr45370.f90: New.

Co-Authored-By: Sebastian Pop <sebastian.pop@amd.com>

From-SVN: r167609
This commit is contained in:
Richard Guenther 2010-12-08 23:01:40 +00:00 committed by Sebastian Pop
parent 09c2d63aa4
commit fd66ea1a6f
7 changed files with 316 additions and 7 deletions

View File

@ -1,3 +1,17 @@
2010-12-08 Richard Guenther <rguenther@suse.de>
Sebastian Pop <sebastian.pop@amd.com>
PR tree-optimization/45230
PR tree-optimization/45231
PR tree-optimization/45370
* sese.c (rename_uses): Returns a bool. Call
recompute_tree_invariant_for_addr_expr only on the RHS of a
GIMPLE_ASSIGN.
(graphite_copy_stmts_from_block): Call fold_stmt_inplace when
rename_uses returns true.
* tree-ssa-copy.c (replace_exp): Add a comment about calling
fold_stmt_inplace after replace_exp.
2010-12-08 Mike Stump <mikestump@comcast.net>
PR debug/46749

View File

@ -470,14 +470,15 @@ set_rename (htab_t rename_map, tree old_name, tree expr)
substitution map RENAME_MAP, inserting the gimplification code at
GSI_TGT, for the translation REGION, with the original copied
statement in LOOP, and using the induction variable renaming map
IV_MAP. */
IV_MAP. Returns true when something has been renamed. */
static void
static bool
rename_uses (gimple copy, htab_t rename_map, gimple_stmt_iterator *gsi_tgt,
sese region, loop_p loop, VEC (tree, heap) *iv_map)
{
use_operand_p use_p;
ssa_op_iter op_iter;
bool changed = false;
if (is_gimple_debug (copy))
{
@ -486,7 +487,7 @@ rename_uses (gimple copy, htab_t rename_map, gimple_stmt_iterator *gsi_tgt,
else
gcc_unreachable ();
return;
return false;
}
FOR_EACH_SSA_USE_OPERAND (use_p, copy, op_iter, SSA_OP_ALL_USES)
@ -500,6 +501,7 @@ rename_uses (gimple copy, htab_t rename_map, gimple_stmt_iterator *gsi_tgt,
|| SSA_NAME_IS_DEFAULT_DEF (old_name))
continue;
changed = true;
new_expr = get_rename (rename_map, old_name);
if (new_expr)
{
@ -547,8 +549,8 @@ rename_uses (gimple copy, htab_t rename_map, gimple_stmt_iterator *gsi_tgt,
gsi_insert_seq_before (gsi_tgt, stmts, GSI_SAME_STMT);
replace_exp (use_p, new_expr);
if (TREE_CODE (new_expr) == INTEGER_CST)
if (TREE_CODE (new_expr) == INTEGER_CST
&& is_gimple_assign (copy))
{
tree rhs = gimple_assign_rhs1 (copy);
@ -558,6 +560,8 @@ rename_uses (gimple copy, htab_t rename_map, gimple_stmt_iterator *gsi_tgt,
set_rename (rename_map, old_name, new_expr);
}
return changed;
}
/* Duplicates the statements of basic block BB into basic block NEW_BB
@ -611,7 +615,8 @@ graphite_copy_stmts_from_block (basic_block bb, basic_block new_bb,
set_rename (rename_map, old_name, new_name);
}
rename_uses (copy, rename_map, &gsi_tgt, region, loop, iv_map);
if (rename_uses (copy, rename_map, &gsi_tgt, region, loop, iv_map))
fold_stmt_inplace (copy);
update_stmt (copy);
}

View File

@ -1,3 +1,13 @@
2010-12-08 Richard Guenther <rguenther@suse.de>
Sebastian Pop <sebastian.pop@amd.com>
PR tree-optimization/45230
PR tree-optimization/45231
PR tree-optimization/45370
* gcc.dg/graphite/id-pr45230-1.c: New.
* gcc.dg/graphite/id-pr45231.c: New.
* gfortran.dg/graphite/id-pr45370.f90: New.
2010-12-08 Nathan Froyd <froydnj@codesourcery.com>
PR c++/45329

View File

@ -0,0 +1,140 @@
/* Copyright (C) 2002 Free Software Foundation.
Test strncmp with various combinations of pointer alignments and lengths to
make sure any optimizations in the library are correct.
Written by Michael Meissner, March 9, 2002. */
#include <string.h>
#include <stddef.h>
#ifndef MAX_OFFSET
#define MAX_OFFSET (sizeof (long long))
#endif
#ifndef MAX_TEST
#define MAX_TEST (8 * sizeof (long long))
#endif
#ifndef MAX_EXTRA
#define MAX_EXTRA (sizeof (long long))
#endif
#define MAX_LENGTH (MAX_OFFSET + MAX_TEST + MAX_EXTRA)
static union {
unsigned char buf[MAX_LENGTH];
long long align_int;
long double align_fp;
} u1, u2;
void
test (const unsigned char *s1, const unsigned char *s2, size_t len, int expected)
{
int value = strncmp ((char *) s1, (char *) s2, len);
if (expected < 0 && value >= 0)
__builtin_abort ();
else if (expected == 0 && value != 0)
__builtin_abort ();
else if (expected > 0 && value <= 0)
__builtin_abort ();
}
main ()
{
size_t off1, off2, len, i;
unsigned char *buf1, *buf2;
unsigned char *mod1, *mod2;
unsigned char *p1, *p2;
for (off1 = 0; off1 < MAX_OFFSET; off1++)
for (off2 = 0; off2 < MAX_OFFSET; off2++)
for (len = 0; len < MAX_TEST; len++)
{
p1 = u1.buf;
for (i = 0; i < off1; i++)
*p1++ = '\0';
buf1 = p1;
for (i = 0; i < len; i++)
*p1++ = 'a';
mod1 = p1;
for (i = 0; i < MAX_EXTRA; i++)
*p1++ = 'x';
p2 = u2.buf;
for (i = 0; i < off2; i++)
*p2++ = '\0';
buf2 = p2;
for (i = 0; i < len; i++)
*p2++ = 'a';
mod2 = p2;
for (i = 0; i < MAX_EXTRA; i++)
*p2++ = 'x';
mod1[0] = '\0';
mod2[0] = '\0';
test (buf1, buf2, MAX_LENGTH, 0);
test (buf1, buf2, len, 0);
mod1[0] = 'a';
mod1[1] = '\0';
mod2[0] = '\0';
test (buf1, buf2, MAX_LENGTH, +1);
test (buf1, buf2, len, 0);
mod1[0] = '\0';
mod2[0] = 'a';
mod2[1] = '\0';
test (buf1, buf2, MAX_LENGTH, -1);
test (buf1, buf2, len, 0);
mod1[0] = 'b';
mod1[1] = '\0';
mod2[0] = 'c';
mod2[1] = '\0';
test (buf1, buf2, MAX_LENGTH, -1);
test (buf1, buf2, len, 0);
mod1[0] = 'c';
mod1[1] = '\0';
mod2[0] = 'b';
mod2[1] = '\0';
test (buf1, buf2, MAX_LENGTH, +1);
test (buf1, buf2, len, 0);
mod1[0] = 'b';
mod1[1] = '\0';
mod2[0] = (unsigned char)'\251';
mod2[1] = '\0';
test (buf1, buf2, MAX_LENGTH, -1);
test (buf1, buf2, len, 0);
mod1[0] = (unsigned char)'\251';
mod1[1] = '\0';
mod2[0] = 'b';
mod2[1] = '\0';
test (buf1, buf2, MAX_LENGTH, +1);
test (buf1, buf2, len, 0);
mod1[0] = (unsigned char)'\251';
mod1[1] = '\0';
mod2[0] = (unsigned char)'\252';
mod2[1] = '\0';
test (buf1, buf2, MAX_LENGTH, -1);
test (buf1, buf2, len, 0);
mod1[0] = (unsigned char)'\252';
mod1[1] = '\0';
mod2[0] = (unsigned char)'\251';
mod2[1] = '\0';
test (buf1, buf2, MAX_LENGTH, +1);
test (buf1, buf2, len, 0);
}
__builtin_exit (0);
}

View File

@ -0,0 +1,37 @@
void
f (n, ppt, xrot)
{
int tileWidth;
int nlwSrc;
int srcx;
int v3, v4;
register unsigned long ca1, cx1, ca2, cx2;
unsigned long *pSrcLine;
register unsigned long *pDst;
register unsigned long *pSrc;
register unsigned long b, tmp;
unsigned long tileEndMask;
int v1, v2;
int tileEndPart;
int needFirst;
tileEndPart = 0;
v1 = tileEndPart << 5;
v2 = 32 - v1;
while (n--)
{
if ((srcx = (ppt - xrot) % tileWidth) < 0)
if (needFirst)
if (nlwSrc == 1)
{
tmp = b;
if (tileEndPart)
b = (*pSrc & tileEndMask) | (*pSrcLine >> v1);
}
if (tileEndPart)
b = (tmp << v1) | (b >> v2);
if (v4 != 32)
*pDst = (*pDst & ((tmp << v3) | (b >> v4) & ca1 ^ cx1)
^ (((tmp << v3) | (b >> v4)) & ca2 ^ cx2));
*pDst = *pDst & tmp;
}
}

View File

@ -0,0 +1,100 @@
!
type :: t
real :: r
integer :: i
character(3) :: chr
end type t
type :: t2
real :: r(2, 2)
integer :: i
character(3) :: chr
end type t2
type :: s
type(t), pointer :: t(:)
end type s
integer, parameter :: sh(2) = (/2,2/)
real, parameter :: a1(2,2) = reshape ((/1.0,2.0,3.0,4.0/),sh)
real, parameter :: a2(2,2) = reshape ((/5.0,6.0,7.0,8.0/),sh)
type(t), target :: tar1(2) = (/t(1.0, 2, "abc"), t(3.0, 4, "efg")/)
character(4), target :: tar2(2) = (/"abcd","efgh"/)
type(s), target :: tar3
character(2), target :: tar4(2) = (/"ab","cd"/)
type(t2), target :: tar5(2) = (/t2(a1, 2, "abc"), t2(a2, 4, "efg")/)
integer, pointer :: ptr(:)
character(2), pointer :: ptr2(:)
real, pointer :: ptr3(:)
!_______________component subreference___________
ptr => tar1%i
ptr = ptr + 1 ! check the scalarizer is OK
if (any (ptr .ne. (/3, 5/))) call abort ()
if (any ((/ptr(1), ptr(2)/) .ne. (/3, 5/))) call abort ()
if (any (tar1%i .ne. (/3, 5/))) call abort ()
! Make sure that the other components are not touched.
if (any (tar1%r .ne. (/1.0, 3.0/))) call abort ()
if (any (tar1%chr .ne. (/"abc", "efg"/))) call abort ()
! Check that the pointer is passed correctly as an actual argument.
call foo (ptr)
if (any (tar1%i .ne. (/2, 4/))) call abort ()
! And that dummy pointers are OK too.
call bar (ptr)
if (any (tar1%i .ne. (/101, 103/))) call abort ()
!_______________substring subreference___________
ptr2 => tar2(:)(2:3)
ptr2 = ptr2(:)(2:2)//"z" ! again, check the scalarizer
if (any (ptr2 .ne. (/"cz", "gz"/))) call abort ()
if (any ((/ptr2(1), ptr2(2)/) .ne. (/"cz", "gz"/))) call abort ()
if (any (tar2 .ne. (/"aczd", "egzh"/))) call abort ()
!_______________substring component subreference___________
ptr2 => tar1(:)%chr(1:2)
ptr2 = ptr2(:)(2:2)//"q" ! yet again, check the scalarizer
if (any (ptr2 .ne. (/"bq","fq"/))) call abort ()
if (any (tar1%chr .ne. (/"bqc","fqg"/))) call abort ()
!_______________trailing array element subreference___________
ptr3 => tar5%r(1,2)
ptr3 = (/99.0, 999.0/)
if (any (tar5(1)%r .ne. reshape ((/1.0,2.0,99.0,4.0/), sh))) call abort ()
if (any (tar5(2)%r .ne. reshape ((/5.0,6.0,999.0,8.0/), sh))) call abort ()
!_______________forall assignment___________
ptr2 => tar2(:)(1:2)
forall (i = 1:2) ptr2(i)(1:1) = "z"
if (any (tar2 .ne. (/"zczd", "zgzh"/))) call abort ()
!_______________something more complicated___________
tar3%t => tar1
ptr3 => tar3%t%r
ptr3 = cos (ptr3)
if (any (abs(ptr3 - (/cos(1.0_4), cos(3.0_4)/)) >= epsilon(1.0_4))) call abort ()
ptr2 => tar3%t(:)%chr(2:3)
ptr2 = " x"
if (any (tar1%chr .ne. (/"b x", "f x"/))) call abort ()
!_______________check non-subref works still___________
ptr2 => tar4
if (any (ptr2 .ne. (/"ab","cd"/))) call abort ()
contains
subroutine foo (arg)
integer :: arg(:)
arg = arg - 1
end subroutine
subroutine bar (arg)
integer, pointer :: arg(:)
arg = arg + 99
end subroutine
end

View File

@ -191,7 +191,10 @@ propagate_value (use_operand_p op_p, tree val)
Use this version when not const/copy propagating values. For example,
PRE uses this version when building expressions as they would appear
in specific blocks taking into account actions of PHI nodes. */
in specific blocks taking into account actions of PHI nodes.
The statement in which an expression has been replaced should be
folded using fold_stmt_inplace. */
void
replace_exp (use_operand_p op_p, tree val)