re PR tree-optimization/61517 (wrong code at -Os and above on x86_64-linux-gnu)

2014-06-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>

    gcc/
    PR tree-optimization/61517
    * tree-ssa-math-opts.c (find_bswap_or_nop_1): Adapt to return a stmt
    whose rhs's first tree is the source expression instead of the
    expression itself.
    (find_bswap_or_nop): Likewise.
    (bsap_replace): Rename stmt in cur_stmt. Pass gsi by value and src as a
    gimple stmt whose rhs's first tree is the source. In the memory source
    case, move the stmt to be replaced close to one of the original load to
    avoid the problem of a store between the load and the stmt's original
    location.
    (pass_optimize_bswap::execute): Adapt to change in bswap_replace's
    signature.

    gcc/testsuite/
    * gcc.c-torture/execute/bswap-2.c (incorrect_read_le32): New.
    (incorrect_read_be32): Likewise.
    (main): Call incorrect_read_* to test stmt replacement is made by
    bswap at the right place.
    * gcc.c-torture/execute/pr61517.c: New test.

From-SVN: r211778
This commit is contained in:
Thomas Preud'homme 2014-06-18 10:43:50 +00:00 committed by Thomas Preud'homme
parent a0f37b26c5
commit a31d2741d4
5 changed files with 172 additions and 83 deletions

View File

@ -1,3 +1,18 @@
2014-06-18 Thomas Preud'homme <thomas.preudhomme@arm.com>
PR tree-optimization/61517
* tree-ssa-math-opts.c (find_bswap_or_nop_1): Adapt to return a stmt
whose rhs's first tree is the source expression instead of the
expression itself.
(find_bswap_or_nop): Likewise.
(bsap_replace): Rename stmt in cur_stmt. Pass gsi by value and src as a
gimple stmt whose rhs's first tree is the source. In the memory source
case, move the stmt to be replaced close to one of the original load to
avoid the problem of a store between the load and the stmt's original
location.
(pass_optimize_bswap::execute): Adapt to change in bswap_replace's
signature.
2014-06-18 Andreas Schwab <schwab@suse.de> 2014-06-18 Andreas Schwab <schwab@suse.de>
PR rtl-optimization/54555 PR rtl-optimization/54555

View File

@ -1,3 +1,12 @@
2014-06-18 Thomas Preud'homme <thomas.preudhomme@arm.com>
PR tree-optimization/61517
* gcc.c-torture/execute/bswap-2.c (incorrect_read_le32): New.
(incorrect_read_be32): Likewise.
(main): Call incorrect_read_* to test stmt replacement is made by
bswap at the right place.
* gcc.c-torture/execute/pr61517.c: New test.
2014-06-18 Andreas Schwab <schwab@suse.de> 2014-06-18 Andreas Schwab <schwab@suse.de>
PR rtl-optimization/54555 PR rtl-optimization/54555

View File

@ -66,6 +66,32 @@ fake_read_be32 (char *x, char *y)
return c3 | c2 << 8 | c1 << 16 | c0 << 24; return c3 | c2 << 8 | c1 << 16 | c0 << 24;
} }
__attribute__ ((noinline, noclone)) uint32_t
incorrect_read_le32 (char *x, char *y)
{
unsigned char c0, c1, c2, c3;
c0 = x[0];
c1 = x[1];
c2 = x[2];
c3 = x[3];
*y = 1;
return c0 | c1 << 8 | c2 << 16 | c3 << 24;
}
__attribute__ ((noinline, noclone)) uint32_t
incorrect_read_be32 (char *x, char *y)
{
unsigned char c0, c1, c2, c3;
c0 = x[0];
c1 = x[1];
c2 = x[2];
c3 = x[3];
*y = 1;
return c3 | c2 << 8 | c1 << 16 | c0 << 24;
}
int int
main () main ()
{ {
@ -92,8 +118,17 @@ main ()
out = fake_read_le32 (cin, &cin[2]); out = fake_read_le32 (cin, &cin[2]);
if (out != 0x89018583) if (out != 0x89018583)
__builtin_abort (); __builtin_abort ();
cin[2] = 0x87;
out = fake_read_be32 (cin, &cin[2]); out = fake_read_be32 (cin, &cin[2]);
if (out != 0x83850189) if (out != 0x83850189)
__builtin_abort (); __builtin_abort ();
cin[2] = 0x87;
out = incorrect_read_le32 (cin, &cin[2]);
if (out != 0x89878583)
__builtin_abort ();
cin[2] = 0x87;
out = incorrect_read_be32 (cin, &cin[2]);
if (out != 0x83858789)
__builtin_abort ();
return 0; return 0;
} }

View File

@ -0,0 +1,19 @@
int a, b, *c = &a;
unsigned short d;
int
main ()
{
unsigned int e = a;
*c = 1;
if (!b)
{
d = e;
*c = d | e;
}
if (a != 0)
__builtin_abort ();
return 0;
}

View File

@ -1806,28 +1806,28 @@ find_bswap_or_nop_load (gimple stmt, tree ref, struct symbolic_number *n)
/* find_bswap_or_nop_1 invokes itself recursively with N and tries to perform /* find_bswap_or_nop_1 invokes itself recursively with N and tries to perform
the operation given by the rhs of STMT on the result. If the operation the operation given by the rhs of STMT on the result. If the operation
could successfully be executed the function returns the tree expression of could successfully be executed the function returns a gimple stmt whose
the source operand and NULL otherwise. */ rhs's first tree is the expression of the source operand and NULL
otherwise. */
static tree static gimple
find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit) find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
{ {
enum tree_code code; enum tree_code code;
tree rhs1, rhs2 = NULL; tree rhs1, rhs2 = NULL;
gimple rhs1_stmt, rhs2_stmt; gimple rhs1_stmt, rhs2_stmt, source_stmt1;
tree source_expr1;
enum gimple_rhs_class rhs_class; enum gimple_rhs_class rhs_class;
if (!limit || !is_gimple_assign (stmt)) if (!limit || !is_gimple_assign (stmt))
return NULL_TREE; return NULL;
rhs1 = gimple_assign_rhs1 (stmt); rhs1 = gimple_assign_rhs1 (stmt);
if (find_bswap_or_nop_load (stmt, rhs1, n)) if (find_bswap_or_nop_load (stmt, rhs1, n))
return rhs1; return stmt;
if (TREE_CODE (rhs1) != SSA_NAME) if (TREE_CODE (rhs1) != SSA_NAME)
return NULL_TREE; return NULL;
code = gimple_assign_rhs_code (stmt); code = gimple_assign_rhs_code (stmt);
rhs_class = gimple_assign_rhs_class (stmt); rhs_class = gimple_assign_rhs_class (stmt);
@ -1850,18 +1850,18 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
&& code != RROTATE_EXPR && code != RROTATE_EXPR
&& code != NOP_EXPR && code != NOP_EXPR
&& code != CONVERT_EXPR) && code != CONVERT_EXPR)
return NULL_TREE; return NULL;
source_expr1 = find_bswap_or_nop_1 (rhs1_stmt, n, limit - 1); source_stmt1 = find_bswap_or_nop_1 (rhs1_stmt, n, limit - 1);
/* If find_bswap_or_nop_1 returned NULL, STMT is a leaf node and /* If find_bswap_or_nop_1 returned NULL, STMT is a leaf node and
we have to initialize the symbolic number. */ we have to initialize the symbolic number. */
if (!source_expr1) if (!source_stmt1)
{ {
if (gimple_assign_load_p (stmt) if (gimple_assign_load_p (stmt)
|| !init_symbolic_number (n, rhs1)) || !init_symbolic_number (n, rhs1))
return NULL_TREE; return NULL;
source_expr1 = rhs1; source_stmt1 = stmt;
} }
switch (code) switch (code)
@ -1875,7 +1875,7 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
/* Only constants masking full bytes are allowed. */ /* Only constants masking full bytes are allowed. */
for (i = 0; i < size; i++, tmp >>= BITS_PER_UNIT) for (i = 0; i < size; i++, tmp >>= BITS_PER_UNIT)
if ((tmp & 0xff) != 0 && (tmp & 0xff) != 0xff) if ((tmp & 0xff) != 0 && (tmp & 0xff) != 0xff)
return NULL_TREE; return NULL;
n->n &= val; n->n &= val;
} }
@ -1885,7 +1885,7 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
case LROTATE_EXPR: case LROTATE_EXPR:
case RROTATE_EXPR: case RROTATE_EXPR:
if (!do_shift_rotate (code, n, (int)TREE_INT_CST_LOW (rhs2))) if (!do_shift_rotate (code, n, (int)TREE_INT_CST_LOW (rhs2)))
return NULL_TREE; return NULL;
break; break;
CASE_CONVERT: CASE_CONVERT:
{ {
@ -1895,16 +1895,16 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
type = gimple_expr_type (stmt); type = gimple_expr_type (stmt);
type_size = TYPE_PRECISION (type); type_size = TYPE_PRECISION (type);
if (type_size % BITS_PER_UNIT != 0) if (type_size % BITS_PER_UNIT != 0)
return NULL_TREE; return NULL;
if (type_size > (int)sizeof (uint64_t) * 8) if (type_size > (int)sizeof (uint64_t) * 8)
return NULL_TREE; return NULL;
/* Sign extension: result is dependent on the value. */ /* Sign extension: result is dependent on the value. */
old_type_size = TYPE_PRECISION (n->type); old_type_size = TYPE_PRECISION (n->type);
if (!TYPE_UNSIGNED (n->type) if (!TYPE_UNSIGNED (n->type)
&& type_size > old_type_size && type_size > old_type_size
&& n->n & (0xff << (old_type_size - 8))) && n->n & (0xff << (old_type_size - 8)))
return NULL_TREE; return NULL;
if (type_size / BITS_PER_UNIT < (int)(sizeof (int64_t))) if (type_size / BITS_PER_UNIT < (int)(sizeof (int64_t)))
{ {
@ -1918,9 +1918,9 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
} }
break; break;
default: default:
return NULL_TREE; return NULL;
}; };
return verify_symbolic_number_p (n, stmt) ? source_expr1 : NULL; return verify_symbolic_number_p (n, stmt) ? source_stmt1 : NULL;
} }
/* Handle binary rhs. */ /* Handle binary rhs. */
@ -1930,37 +1930,38 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
int i, size; int i, size;
struct symbolic_number n1, n2; struct symbolic_number n1, n2;
uint64_t mask; uint64_t mask;
tree source_expr2; gimple source_stmt2;
if (code != BIT_IOR_EXPR) if (code != BIT_IOR_EXPR)
return NULL_TREE; return NULL;
if (TREE_CODE (rhs2) != SSA_NAME) if (TREE_CODE (rhs2) != SSA_NAME)
return NULL_TREE; return NULL;
rhs2_stmt = SSA_NAME_DEF_STMT (rhs2); rhs2_stmt = SSA_NAME_DEF_STMT (rhs2);
switch (code) switch (code)
{ {
case BIT_IOR_EXPR: case BIT_IOR_EXPR:
source_expr1 = find_bswap_or_nop_1 (rhs1_stmt, &n1, limit - 1); source_stmt1 = find_bswap_or_nop_1 (rhs1_stmt, &n1, limit - 1);
if (!source_expr1) if (!source_stmt1)
return NULL_TREE; return NULL;
source_expr2 = find_bswap_or_nop_1 (rhs2_stmt, &n2, limit - 1); source_stmt2 = find_bswap_or_nop_1 (rhs2_stmt, &n2, limit - 1);
if (!source_expr2) if (!source_stmt2)
return NULL_TREE; return NULL;
if (TYPE_PRECISION (n1.type) != TYPE_PRECISION (n2.type)) if (TYPE_PRECISION (n1.type) != TYPE_PRECISION (n2.type))
return NULL_TREE; return NULL;
if (!n1.vuse != !n2.vuse || if (!n1.vuse != !n2.vuse ||
(n1.vuse && !operand_equal_p (n1.vuse, n2.vuse, 0))) (n1.vuse && !operand_equal_p (n1.vuse, n2.vuse, 0)))
return NULL_TREE; return NULL;
if (source_expr1 != source_expr2) if (gimple_assign_rhs1 (source_stmt1)
!= gimple_assign_rhs1 (source_stmt2))
{ {
int64_t inc, mask; int64_t inc, mask;
unsigned i; unsigned i;
@ -1969,10 +1970,10 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
if (!n1.base_addr || !n2.base_addr if (!n1.base_addr || !n2.base_addr
|| !operand_equal_p (n1.base_addr, n2.base_addr, 0)) || !operand_equal_p (n1.base_addr, n2.base_addr, 0))
return NULL_TREE; return NULL;
if (!n1.offset != !n2.offset || if (!n1.offset != !n2.offset ||
(n1.offset && !operand_equal_p (n1.offset, n2.offset, 0))) (n1.offset && !operand_equal_p (n1.offset, n2.offset, 0)))
return NULL_TREE; return NULL;
/* We swap n1 with n2 to have n1 < n2. */ /* We swap n1 with n2 to have n1 < n2. */
if (n2.bytepos < n1.bytepos) if (n2.bytepos < n1.bytepos)
@ -1982,14 +1983,14 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
tmpn = n2; tmpn = n2;
n2 = n1; n2 = n1;
n1 = tmpn; n1 = tmpn;
source_expr1 = source_expr2; source_stmt1 = source_stmt2;
} }
off_sub = n2.bytepos - n1.bytepos; off_sub = n2.bytepos - n1.bytepos;
/* Check that the range of memory covered < biggest int size. */ /* Check that the range of memory covered < biggest int size. */
if (off_sub + n2.range > (int) sizeof (int64_t)) if (off_sub + n2.range > (int) sizeof (int64_t))
return NULL_TREE; return NULL;
n->range = n2.range + off_sub; n->range = n2.range + off_sub;
/* Reinterpret byte marks in symbolic number holding the value of /* Reinterpret byte marks in symbolic number holding the value of
@ -2028,20 +2029,20 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
masked1 = n1.n & mask; masked1 = n1.n & mask;
masked2 = n2.n & mask; masked2 = n2.n & mask;
if (masked1 && masked2 && masked1 != masked2) if (masked1 && masked2 && masked1 != masked2)
return NULL_TREE; return NULL;
} }
n->n = n1.n | n2.n; n->n = n1.n | n2.n;
if (!verify_symbolic_number_p (n, stmt)) if (!verify_symbolic_number_p (n, stmt))
return NULL_TREE; return NULL;
break; break;
default: default:
return NULL_TREE; return NULL;
} }
return source_expr1; return source_stmt1;
} }
return NULL_TREE; return NULL;
} }
/* Check if STMT completes a bswap implementation or a read in a given /* Check if STMT completes a bswap implementation or a read in a given
@ -2049,9 +2050,10 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
accordingly. It also sets N to represent the kind of operations accordingly. It also sets N to represent the kind of operations
performed: size of the resulting expression and whether it works on performed: size of the resulting expression and whether it works on
a memory source, and if so alias-set and vuse. At last, the a memory source, and if so alias-set and vuse. At last, the
function returns the source tree expression. */ function returns a stmt whose rhs's first tree is the source
expression. */
static tree static gimple
find_bswap_or_nop (gimple stmt, struct symbolic_number *n, bool *bswap) find_bswap_or_nop (gimple stmt, struct symbolic_number *n, bool *bswap)
{ {
/* The number which the find_bswap_or_nop_1 result should match in order /* The number which the find_bswap_or_nop_1 result should match in order
@ -2060,7 +2062,7 @@ find_bswap_or_nop (gimple stmt, struct symbolic_number *n, bool *bswap)
uint64_t cmpxchg = CMPXCHG; uint64_t cmpxchg = CMPXCHG;
uint64_t cmpnop = CMPNOP; uint64_t cmpnop = CMPNOP;
tree source_expr; gimple source_stmt;
int limit; int limit;
/* The last parameter determines the depth search limit. It usually /* The last parameter determines the depth search limit. It usually
@ -2070,10 +2072,10 @@ find_bswap_or_nop (gimple stmt, struct symbolic_number *n, bool *bswap)
in libgcc, and for initial shift/and operation of the src operand. */ in libgcc, and for initial shift/and operation of the src operand. */
limit = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (gimple_expr_type (stmt))); limit = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (gimple_expr_type (stmt)));
limit += 1 + (int) ceil_log2 ((unsigned HOST_WIDE_INT) limit); limit += 1 + (int) ceil_log2 ((unsigned HOST_WIDE_INT) limit);
source_expr = find_bswap_or_nop_1 (stmt, n, limit); source_stmt = find_bswap_or_nop_1 (stmt, n, limit);
if (!source_expr) if (!source_stmt)
return NULL_TREE; return NULL;
/* Find real size of result (highest non zero byte). */ /* Find real size of result (highest non zero byte). */
if (n->base_addr) if (n->base_addr)
@ -2103,14 +2105,14 @@ find_bswap_or_nop (gimple stmt, struct symbolic_number *n, bool *bswap)
else if (n->n == cmpxchg) else if (n->n == cmpxchg)
*bswap = true; *bswap = true;
else else
return NULL_TREE; return NULL;
/* Useless bit manipulation performed by code. */ /* Useless bit manipulation performed by code. */
if (!n->base_addr && n->n == cmpnop) if (!n->base_addr && n->n == cmpnop)
return NULL_TREE; return NULL;
n->range *= BITS_PER_UNIT; n->range *= BITS_PER_UNIT;
return source_expr; return source_stmt;
} }
namespace { namespace {
@ -2146,26 +2148,30 @@ public:
}; // class pass_optimize_bswap }; // class pass_optimize_bswap
/* Perform the bswap optimization: replace the statement STMT at GSI /* Perform the bswap optimization: replace the statement CUR_STMT at
with load type, VUSE and set-alias as described by N if a memory GSI with a load of type, VUSE and set-alias as described by N if a
source is involved (N->base_addr is non null), followed by the memory source is involved (N->base_addr is non null), followed by
builtin bswap invocation in FNDECL if BSWAP is true. SRC gives the builtin bswap invocation in FNDECL if BSWAP is true. SRC_STMT
the source on which STMT is operating and N->range gives the gives where should the replacement be made. It also gives the
size of the expression involved for maintaining some statistics. */ source on which CUR_STMT is operating via its rhs's first tree nad
N->range gives the size of the expression involved for maintaining
some statistics. */
static bool static bool
bswap_replace (gimple stmt, gimple_stmt_iterator *gsi, tree src, tree fndecl, bswap_replace (gimple cur_stmt, gimple_stmt_iterator gsi, gimple src_stmt,
tree bswap_type, tree load_type, struct symbolic_number *n, tree fndecl, tree bswap_type, tree load_type,
bool bswap) struct symbolic_number *n, bool bswap)
{ {
tree tmp, tgt; tree src, tmp, tgt;
gimple call; gimple call;
tgt = gimple_assign_lhs (stmt); src = gimple_assign_rhs1 (src_stmt);
tgt = gimple_assign_lhs (cur_stmt);
/* Need to load the value from memory first. */ /* Need to load the value from memory first. */
if (n->base_addr) if (n->base_addr)
{ {
gimple_stmt_iterator gsi_ins = gsi_for_stmt (src_stmt);
tree addr_expr, addr_tmp, val_expr, val_tmp; tree addr_expr, addr_tmp, val_expr, val_tmp;
tree load_offset_ptr, aligned_load_type; tree load_offset_ptr, aligned_load_type;
gimple addr_stmt, load_stmt; gimple addr_stmt, load_stmt;
@ -2175,6 +2181,9 @@ bswap_replace (gimple stmt, gimple_stmt_iterator *gsi, tree src, tree fndecl,
if (bswap && SLOW_UNALIGNED_ACCESS (TYPE_MODE (load_type), align)) if (bswap && SLOW_UNALIGNED_ACCESS (TYPE_MODE (load_type), align))
return false; return false;
gsi_move_before (&gsi, &gsi_ins);
gsi = gsi_for_stmt (cur_stmt);
/* Compute address to load from and cast according to the size /* Compute address to load from and cast according to the size
of the load. */ of the load. */
addr_expr = build_fold_addr_expr (unshare_expr (src)); addr_expr = build_fold_addr_expr (unshare_expr (src));
@ -2185,7 +2194,7 @@ bswap_replace (gimple stmt, gimple_stmt_iterator *gsi, tree src, tree fndecl,
addr_tmp = make_temp_ssa_name (TREE_TYPE (addr_expr), NULL, addr_tmp = make_temp_ssa_name (TREE_TYPE (addr_expr), NULL,
"load_src"); "load_src");
addr_stmt = gimple_build_assign (addr_tmp, addr_expr); addr_stmt = gimple_build_assign (addr_tmp, addr_expr);
gsi_insert_before (gsi, addr_stmt, GSI_SAME_STMT); gsi_insert_before (&gsi, addr_stmt, GSI_SAME_STMT);
} }
/* Perform the load. */ /* Perform the load. */
@ -2215,21 +2224,24 @@ bswap_replace (gimple stmt, gimple_stmt_iterator *gsi, tree src, tree fndecl,
"load_dst"); "load_dst");
load_stmt = gimple_build_assign (val_tmp, val_expr); load_stmt = gimple_build_assign (val_tmp, val_expr);
gimple_set_vuse (load_stmt, n->vuse); gimple_set_vuse (load_stmt, n->vuse);
gsi_insert_before (gsi, load_stmt, GSI_SAME_STMT); gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
gimple_assign_set_rhs_with_ops_1 (gsi, NOP_EXPR, val_tmp, gimple_assign_set_rhs_with_ops_1 (&gsi, NOP_EXPR, val_tmp,
NULL_TREE, NULL_TREE); NULL_TREE, NULL_TREE);
} }
else else
gimple_assign_set_rhs_with_ops_1 (gsi, MEM_REF, val_expr, {
gimple_assign_set_rhs_with_ops_1 (&gsi, MEM_REF, val_expr,
NULL_TREE, NULL_TREE); NULL_TREE, NULL_TREE);
update_stmt (gsi_stmt (*gsi)); gimple_set_vuse (cur_stmt, n->vuse);
}
update_stmt (cur_stmt);
if (dump_file) if (dump_file)
{ {
fprintf (dump_file, fprintf (dump_file,
"%d bit load in target endianness found at: ", "%d bit load in target endianness found at: ",
(int)n->range); (int)n->range);
print_gimple_stmt (dump_file, stmt, 0, 0); print_gimple_stmt (dump_file, cur_stmt, 0, 0);
} }
return true; return true;
} }
@ -2238,7 +2250,7 @@ bswap_replace (gimple stmt, gimple_stmt_iterator *gsi, tree src, tree fndecl,
val_tmp = make_temp_ssa_name (aligned_load_type, NULL, "load_dst"); val_tmp = make_temp_ssa_name (aligned_load_type, NULL, "load_dst");
load_stmt = gimple_build_assign (val_tmp, val_expr); load_stmt = gimple_build_assign (val_tmp, val_expr);
gimple_set_vuse (load_stmt, n->vuse); gimple_set_vuse (load_stmt, n->vuse);
gsi_insert_before (gsi, load_stmt, GSI_SAME_STMT); gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
} }
src = val_tmp; src = val_tmp;
} }
@ -2261,7 +2273,7 @@ bswap_replace (gimple stmt, gimple_stmt_iterator *gsi, tree src, tree fndecl,
gimple convert_stmt; gimple convert_stmt;
tmp = make_temp_ssa_name (bswap_type, NULL, "bswapsrc"); tmp = make_temp_ssa_name (bswap_type, NULL, "bswapsrc");
convert_stmt = gimple_build_assign_with_ops (NOP_EXPR, tmp, src, NULL); convert_stmt = gimple_build_assign_with_ops (NOP_EXPR, tmp, src, NULL);
gsi_insert_before (gsi, convert_stmt, GSI_SAME_STMT); gsi_insert_before (&gsi, convert_stmt, GSI_SAME_STMT);
} }
call = gimple_build_call (fndecl, 1, tmp); call = gimple_build_call (fndecl, 1, tmp);
@ -2274,7 +2286,7 @@ bswap_replace (gimple stmt, gimple_stmt_iterator *gsi, tree src, tree fndecl,
gimple convert_stmt; gimple convert_stmt;
tmp = make_temp_ssa_name (bswap_type, NULL, "bswapdst"); tmp = make_temp_ssa_name (bswap_type, NULL, "bswapdst");
convert_stmt = gimple_build_assign_with_ops (NOP_EXPR, tgt, tmp, NULL); convert_stmt = gimple_build_assign_with_ops (NOP_EXPR, tgt, tmp, NULL);
gsi_insert_after (gsi, convert_stmt, GSI_SAME_STMT); gsi_insert_after (&gsi, convert_stmt, GSI_SAME_STMT);
} }
gimple_call_set_lhs (call, tmp); gimple_call_set_lhs (call, tmp);
@ -2283,11 +2295,11 @@ bswap_replace (gimple stmt, gimple_stmt_iterator *gsi, tree src, tree fndecl,
{ {
fprintf (dump_file, "%d bit bswap implementation found at: ", fprintf (dump_file, "%d bit bswap implementation found at: ",
(int)n->range); (int)n->range);
print_gimple_stmt (dump_file, stmt, 0, 0); print_gimple_stmt (dump_file, cur_stmt, 0, 0);
} }
gsi_insert_after (gsi, call, GSI_SAME_STMT); gsi_insert_after (&gsi, call, GSI_SAME_STMT);
gsi_remove (gsi, true); gsi_remove (&gsi, true);
return true; return true;
} }
@ -2348,19 +2360,18 @@ pass_optimize_bswap::execute (function *fun)
patterns, the wider variant wouldn't be detected. */ patterns, the wider variant wouldn't be detected. */
for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi)) for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
{ {
gimple stmt = gsi_stmt (gsi); gimple src_stmt, cur_stmt = gsi_stmt (gsi);
tree fndecl = NULL_TREE, bswap_type = NULL_TREE; tree fndecl = NULL_TREE, bswap_type = NULL_TREE, load_type;
tree src, load_type;
struct symbolic_number n; struct symbolic_number n;
bool bswap; bool bswap;
if (!is_gimple_assign (stmt) if (!is_gimple_assign (cur_stmt)
|| gimple_assign_rhs_code (stmt) != BIT_IOR_EXPR) || gimple_assign_rhs_code (cur_stmt) != BIT_IOR_EXPR)
continue; continue;
src = find_bswap_or_nop (stmt, &n, &bswap); src_stmt = find_bswap_or_nop (cur_stmt, &n, &bswap);
if (!src) if (!src_stmt)
continue; continue;
switch (n.range) switch (n.range)
@ -2396,8 +2407,8 @@ pass_optimize_bswap::execute (function *fun)
if (bswap && !fndecl) if (bswap && !fndecl)
continue; continue;
if (bswap_replace (stmt, &gsi, src, fndecl, bswap_type, load_type, if (bswap_replace (cur_stmt, gsi, src_stmt, fndecl, bswap_type,
&n, bswap)) load_type, &n, bswap))
changed = true; changed = true;
} }
} }