re PR tree-optimization/89475 (Teach ccp about __builtin_bswap{16,32,64})

PR tree-optimization/89475
	* tree-ssa-ccp.c (evaluate_stmt): Handle BUILT_IN_BSWAP{16,32,64}
	calls.

	* gcc.dg/tree-ssa/pr89475.c: New test.

From-SVN: r270680
This commit is contained in:
Jakub Jelinek 2019-04-30 11:07:28 +02:00 committed by Jakub Jelinek
parent 379637d5e2
commit ae8f39886b
5 changed files with 190 additions and 7 deletions

View File

@ -1,3 +1,9 @@
2019-04-30 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/89475
* tree-ssa-ccp.c (evaluate_stmt): Handle BUILT_IN_BSWAP{16,32,64}
calls.
2019-04-30 Martin Liska <mliska@suse.cz> 2019-04-30 Martin Liska <mliska@suse.cz>
PR translation/90274 PR translation/90274

View File

@ -1615,13 +1615,31 @@ encode_tree_to_bitpos (tree expr, unsigned char *ptr, int bitlen, int bitpos,
unsigned int total_bytes) unsigned int total_bytes)
{ {
unsigned int first_byte = bitpos / BITS_PER_UNIT; unsigned int first_byte = bitpos / BITS_PER_UNIT;
tree tmp_int = expr;
bool sub_byte_op_p = ((bitlen % BITS_PER_UNIT) bool sub_byte_op_p = ((bitlen % BITS_PER_UNIT)
|| (bitpos % BITS_PER_UNIT) || (bitpos % BITS_PER_UNIT)
|| !int_mode_for_size (bitlen, 0).exists ()); || !int_mode_for_size (bitlen, 0).exists ());
bool empty_ctor_p
= (TREE_CODE (expr) == CONSTRUCTOR
&& CONSTRUCTOR_NELTS (expr) == 0
&& TYPE_SIZE_UNIT (TREE_TYPE (expr))
&& tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (expr))));
if (!sub_byte_op_p) if (!sub_byte_op_p)
return native_encode_expr (tmp_int, ptr + first_byte, total_bytes) != 0; {
if (first_byte >= total_bytes)
return false;
total_bytes -= first_byte;
if (empty_ctor_p)
{
unsigned HOST_WIDE_INT rhs_bytes
= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
if (rhs_bytes > total_bytes)
return false;
memset (ptr + first_byte, '\0', rhs_bytes);
return true;
}
return native_encode_expr (expr, ptr + first_byte, total_bytes) != 0;
}
/* LITTLE-ENDIAN /* LITTLE-ENDIAN
We are writing a non byte-sized quantity or at a position that is not We are writing a non byte-sized quantity or at a position that is not
@ -1667,14 +1685,29 @@ encode_tree_to_bitpos (tree expr, unsigned char *ptr, int bitlen, int bitpos,
/* We must be dealing with fixed-size data at this point, since the /* We must be dealing with fixed-size data at this point, since the
total size is also fixed. */ total size is also fixed. */
fixed_size_mode mode = as_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (expr))); unsigned int byte_size;
if (empty_ctor_p)
{
unsigned HOST_WIDE_INT rhs_bytes
= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
if (rhs_bytes > total_bytes)
return false;
byte_size = rhs_bytes;
}
else
{
fixed_size_mode mode
= as_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (expr)));
byte_size = GET_MODE_SIZE (mode);
}
/* Allocate an extra byte so that we have space to shift into. */ /* Allocate an extra byte so that we have space to shift into. */
unsigned int byte_size = GET_MODE_SIZE (mode) + 1; byte_size++;
unsigned char *tmpbuf = XALLOCAVEC (unsigned char, byte_size); unsigned char *tmpbuf = XALLOCAVEC (unsigned char, byte_size);
memset (tmpbuf, '\0', byte_size); memset (tmpbuf, '\0', byte_size);
/* The store detection code should only have allowed constants that are /* The store detection code should only have allowed constants that are
accepted by native_encode_expr. */ accepted by native_encode_expr or empty ctors. */
if (native_encode_expr (expr, tmpbuf, byte_size - 1) == 0) if (!empty_ctor_p
&& native_encode_expr (expr, tmpbuf, byte_size - 1) == 0)
gcc_unreachable (); gcc_unreachable ();
/* The native_encode_expr machinery uses TYPE_MODE to determine how many /* The native_encode_expr machinery uses TYPE_MODE to determine how many
@ -4164,7 +4197,8 @@ lhs_valid_for_store_merging_p (tree lhs)
tree_code code = TREE_CODE (lhs); tree_code code = TREE_CODE (lhs);
if (code == ARRAY_REF || code == ARRAY_RANGE_REF || code == MEM_REF if (code == ARRAY_REF || code == ARRAY_RANGE_REF || code == MEM_REF
|| code == COMPONENT_REF || code == BIT_FIELD_REF) || code == COMPONENT_REF || code == BIT_FIELD_REF
|| DECL_P (lhs))
return true; return true;
return false; return false;
@ -4178,6 +4212,11 @@ static bool
rhs_valid_for_store_merging_p (tree rhs) rhs_valid_for_store_merging_p (tree rhs)
{ {
unsigned HOST_WIDE_INT size; unsigned HOST_WIDE_INT size;
if (TREE_CODE (rhs) == CONSTRUCTOR
&& CONSTRUCTOR_NELTS (rhs) == 0
&& TYPE_SIZE_UNIT (TREE_TYPE (rhs))
&& tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (rhs))))
return true;
return (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (rhs))).is_constant (&size) return (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (rhs))).is_constant (&size)
&& native_encode_expr (rhs, NULL, size) != 0); && native_encode_expr (rhs, NULL, size) != 0);
} }

View File

@ -1,3 +1,8 @@
2019-04-30 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/89475
* gcc.dg/tree-ssa/pr89475.c: New test.
2019-04-30 Bin Cheng <bin.cheng@linux.alibaba.com> 2019-04-30 Bin Cheng <bin.cheng@linux.alibaba.com>
PR tree-optimization/90240 PR tree-optimization/90240

View File

@ -0,0 +1,104 @@
/* PR tree-optimization/89475 */
/* { dg-do compile { target { ilp32 || lp64 } } } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
/* { dg-final { scan-tree-dump-not "link_error " "optimized" } } */
void link_error (void);
unsigned short
f0 (unsigned short x)
{
x &= 0xaa55;
x = __builtin_bswap16 (x);
if (x & 0xaa55)
link_error ();
return x;
}
unsigned short
f1 (unsigned short x)
{
x &= 0x55aa;
x = __builtin_bswap16 (x);
if (x & 0x55aa)
link_error ();
return x;
}
unsigned int
f2 (unsigned int x)
{
x &= 0x55aa5aa5U;
x = __builtin_bswap32 (x);
if (x & 0x5aa555aaU)
link_error ();
return x;
}
unsigned long long int
f3 (unsigned long long int x)
{
x &= 0x55aa5aa544cc2211ULL;
x = __builtin_bswap64 (x);
if (x & 0xeedd33bb5aa555aaULL)
link_error ();
return x;
}
unsigned short
f4 (unsigned short x)
{
x = __builtin_bswap32 (x);
if (x != 0)
link_error ();
return x;
}
unsigned int
f5 (unsigned int x)
{
x = __builtin_bswap64 (x);
if (x != 0)
link_error ();
return x;
}
unsigned short
f6 (unsigned short x)
{
x |= 0xaa55;
x = __builtin_bswap16 (x);
if ((x | 0xaa55) != 0xffff)
link_error ();
return x;
}
unsigned short
f7 (unsigned short x)
{
x |= 0x55aa;
x = __builtin_bswap16 (x);
if ((x | 0x55aa) != 0xffff)
link_error ();
return x;
}
unsigned int
f8 (unsigned int x)
{
x |= 0x55aa5aa5U;
x = __builtin_bswap32 (x);
if ((x | 0x5aa555aaU) != 0xffffffffU)
link_error ();
return x;
}
unsigned long long int
f9 (unsigned long long int x)
{
x |= 0x55aa5aa544cc2211ULL;
x = __builtin_bswap64 (x);
if ((x | 0xeedd33bb5aa555aaULL) != 0xffffffffffffffffULL)
link_error ();
return x;
}

View File

@ -1960,6 +1960,35 @@ evaluate_stmt (gimple *stmt)
break; break;
} }
case BUILT_IN_BSWAP16:
case BUILT_IN_BSWAP32:
case BUILT_IN_BSWAP64:
val = get_value_for_expr (gimple_call_arg (stmt, 0), true);
if (val.lattice_val == UNDEFINED)
break;
else if (val.lattice_val == CONSTANT
&& val.value
&& TREE_CODE (val.value) == INTEGER_CST)
{
tree type = TREE_TYPE (gimple_call_lhs (stmt));
int prec = TYPE_PRECISION (type);
wide_int wval = wi::to_wide (val.value);
val.value
= wide_int_to_tree (type,
wide_int::from (wval, prec,
UNSIGNED).bswap ());
val.mask
= widest_int::from (wide_int::from (val.mask, prec,
UNSIGNED).bswap (),
UNSIGNED);
if (wi::sext (val.mask, prec) != -1)
break;
}
val.lattice_val = VARYING;
val.value = NULL_TREE;
val.mask = -1;
break;
default:; default:;
} }
} }