mirror of git://gcc.gnu.org/git/gcc.git
tree-ssa-forwprop.c (truth_valued_ssa_name): New function.
2011-07-07 Kai Tietz <ktietz@redhat.com> * tree-ssa-forwprop.c (truth_valued_ssa_name): New function. (lookup_logical_inverted_value): Likewise. (simplify_bitwise_binary_1): Likewise. (simplify_bitwise_binary): Use simplify_bitwise_binary_1. 2011-07-07 Kai Tietz <ktietz@redhat.com> * gcc.dg/binop-notxor1.c: New test. * gcc.dg/binop-notand4a.c: New test. * gcc.dg/binop-notxor2.c: New test. * gcc.dg/binop-notand3a.c: New test. * gcc.dg/binop-notand2a.c: New test. * gcc.dg/binop-notand6a.c: New test. * gcc.dg/binop-notor1.c: New test. * gcc.dg/binop-notand1a.c: New test. * gcc.dg/binop-notand5a.c: New test. * gcc.dg/binop-notor2.c: New test. From-SVN: r175974
This commit is contained in:
parent
3ce9f09055
commit
0816a42a1f
|
@ -1,3 +1,10 @@
|
|||
2011-07-07 Kai Tietz <ktietz@redhat.com>
|
||||
|
||||
* tree-ssa-forwprop.c (truth_valued_ssa_name): New function.
|
||||
(lookup_logical_inverted_value): Likewise.
|
||||
(simplify_bitwise_binary_1): Likewise.
|
||||
(simplify_bitwise_binary): Use simplify_bitwise_binary_1.
|
||||
|
||||
2011-07-07 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* gcc.c (%[Spec]): Don't document.
|
||||
|
|
|
@ -1,3 +1,16 @@
|
|||
2011-07-07 Kai Tietz <ktietz@redhat.com>
|
||||
|
||||
* gcc.dg/binop-notxor1.c: New test.
|
||||
* gcc.dg/binop-notand4a.c: New test.
|
||||
* gcc.dg/binop-notxor2.c: New test.
|
||||
* gcc.dg/binop-notand3a.c: New test.
|
||||
* gcc.dg/binop-notand2a.c: New test.
|
||||
* gcc.dg/binop-notand6a.c: New test.
|
||||
* gcc.dg/binop-notor1.c: New test.
|
||||
* gcc.dg/binop-notand1a.c: New test.
|
||||
* gcc.dg/binop-notand5a.c: New test.
|
||||
* gcc.dg/binop-notor2.c: New test.
|
||||
|
||||
2011-07-07 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR middle-end/49640
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
|
||||
int
|
||||
foo (char a, unsigned short b)
|
||||
{
|
||||
return (a & !a) | (b & !b);
|
||||
}
|
||||
|
||||
/* As long as comparisons aren't boolified and casts from boolean-types
|
||||
aren't preserved, the folding of X & !X to zero fails. */
|
||||
/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
|
@ -0,0 +1,11 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
|
||||
int
|
||||
foo (int a)
|
||||
{
|
||||
return (!a & 1) != (a == 0);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
|
@ -0,0 +1,11 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
|
||||
int
|
||||
foo (short a)
|
||||
{
|
||||
return (!a & 1) != ((a == 0) & 1);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
|
@ -0,0 +1,13 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
|
||||
int
|
||||
foo (unsigned char a, _Bool b)
|
||||
{
|
||||
return (!a & a) | (b & !b);
|
||||
}
|
||||
|
||||
/* As long as comparisons aren't boolified and casts from boolean-types
|
||||
aren't preserved, the folding of X & !X to zero fails. */
|
||||
/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
|
@ -0,0 +1,11 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
|
||||
int
|
||||
foo (long a, unsigned long b)
|
||||
{
|
||||
return (a & (a == 0)) | (b & !b);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
|
@ -0,0 +1,11 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
|
||||
int
|
||||
foo (unsigned long a, long b)
|
||||
{
|
||||
return (a & !a) | (b & (b == 0));
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
|
@ -0,0 +1,11 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
|
||||
int
|
||||
foo (_Bool a, _Bool b)
|
||||
{
|
||||
return (a | !a) | (!b | b);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "return 1" 1 "optimized" } } */
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
|
@ -0,0 +1,11 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
|
||||
int
|
||||
foo (_Bool a, _Bool b)
|
||||
{
|
||||
return (a | (a == 0)) | ((b ^ 1) | b);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "return 1" 1 "optimized" } } */
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
|
@ -0,0 +1,11 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
|
||||
int
|
||||
foo (_Bool a, _Bool b)
|
||||
{
|
||||
return (a ^ !a) | (!b ^ b);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "return 1" 1 "optimized" } } */
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
|
@ -0,0 +1,11 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
|
||||
int
|
||||
foo (_Bool a, _Bool b)
|
||||
{
|
||||
return (a ^ (a == 0)) | ((b == 0) ^ b);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "return 1" 1 "optimized" } } */
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
|
@ -1602,6 +1602,129 @@ simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Checks if expression has type of one-bit precision, or is a known
|
||||
truth-valued expression. */
|
||||
static bool
|
||||
truth_valued_ssa_name (tree name)
|
||||
{
|
||||
gimple def;
|
||||
tree type = TREE_TYPE (name);
|
||||
|
||||
if (!INTEGRAL_TYPE_P (type))
|
||||
return false;
|
||||
/* Don't check here for BOOLEAN_TYPE as the precision isn't
|
||||
necessarily one and so ~X is not equal to !X. */
|
||||
if (TYPE_PRECISION (type) == 1)
|
||||
return true;
|
||||
def = SSA_NAME_DEF_STMT (name);
|
||||
if (is_gimple_assign (def))
|
||||
return truth_value_p (gimple_assign_rhs_code (def));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Helper routine for simplify_bitwise_binary_1 function.
|
||||
Return for the SSA name NAME the expression X if it mets condition
|
||||
NAME = !X. Otherwise return NULL_TREE.
|
||||
Detected patterns for NAME = !X are:
|
||||
!X and X == 0 for X with integral type.
|
||||
X ^ 1, X != 1,or ~X for X with integral type with precision of one. */
|
||||
static tree
|
||||
lookup_logical_inverted_value (tree name)
|
||||
{
|
||||
tree op1, op2;
|
||||
enum tree_code code;
|
||||
gimple def;
|
||||
|
||||
/* If name has none-intergal type, or isn't a SSA_NAME, then
|
||||
return. */
|
||||
if (TREE_CODE (name) != SSA_NAME
|
||||
|| !INTEGRAL_TYPE_P (TREE_TYPE (name)))
|
||||
return NULL_TREE;
|
||||
def = SSA_NAME_DEF_STMT (name);
|
||||
if (!is_gimple_assign (def))
|
||||
return NULL_TREE;
|
||||
|
||||
code = gimple_assign_rhs_code (def);
|
||||
op1 = gimple_assign_rhs1 (def);
|
||||
op2 = NULL_TREE;
|
||||
|
||||
/* Get for EQ_EXPR or BIT_XOR_EXPR operation the second operand.
|
||||
If CODE isn't an EQ_EXPR, BIT_XOR_EXPR, TRUTH_NOT_EXPR,
|
||||
or BIT_NOT_EXPR, then return. */
|
||||
if (code == EQ_EXPR || code == NE_EXPR
|
||||
|| code == BIT_XOR_EXPR)
|
||||
op2 = gimple_assign_rhs2 (def);
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case TRUTH_NOT_EXPR:
|
||||
return op1;
|
||||
case BIT_NOT_EXPR:
|
||||
if (truth_valued_ssa_name (name))
|
||||
return op1;
|
||||
break;
|
||||
case EQ_EXPR:
|
||||
/* Check if we have X == 0 and X has an integral type. */
|
||||
if (!INTEGRAL_TYPE_P (TREE_TYPE (op1)))
|
||||
break;
|
||||
if (integer_zerop (op2))
|
||||
return op1;
|
||||
break;
|
||||
case NE_EXPR:
|
||||
/* Check if we have X != 1 and X is a truth-valued. */
|
||||
if (!INTEGRAL_TYPE_P (TREE_TYPE (op1)))
|
||||
break;
|
||||
if (integer_onep (op2) && truth_valued_ssa_name (op1))
|
||||
return op1;
|
||||
break;
|
||||
case BIT_XOR_EXPR:
|
||||
/* Check if we have X ^ 1 and X is truth valued. */
|
||||
if (integer_onep (op2) && truth_valued_ssa_name (op1))
|
||||
return op1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Optimize ARG1 CODE ARG2 to a constant for bitwise binary
|
||||
operations CODE, if one operand has the logically inverted
|
||||
value of the other. */
|
||||
static tree
|
||||
simplify_bitwise_binary_1 (enum tree_code code, tree type,
|
||||
tree arg1, tree arg2)
|
||||
{
|
||||
tree anot;
|
||||
|
||||
/* If CODE isn't a bitwise binary operation, return NULL_TREE. */
|
||||
if (code != BIT_AND_EXPR && code != BIT_IOR_EXPR
|
||||
&& code != BIT_XOR_EXPR)
|
||||
return NULL_TREE;
|
||||
|
||||
/* First check if operands ARG1 and ARG2 are equal. If so
|
||||
return NULL_TREE as this optimization is handled fold_stmt. */
|
||||
if (arg1 == arg2)
|
||||
return NULL_TREE;
|
||||
/* See if we have in arguments logical-not patterns. */
|
||||
if (((anot = lookup_logical_inverted_value (arg1)) == NULL_TREE
|
||||
|| anot != arg2)
|
||||
&& ((anot = lookup_logical_inverted_value (arg2)) == NULL_TREE
|
||||
|| anot != arg1))
|
||||
return NULL_TREE;
|
||||
|
||||
/* X & !X -> 0. */
|
||||
if (code == BIT_AND_EXPR)
|
||||
return fold_convert (type, integer_zero_node);
|
||||
/* X | !X -> 1 and X ^ !X -> 1, if X is truth-valued. */
|
||||
if (truth_valued_ssa_name (anot))
|
||||
return fold_convert (type, integer_one_node);
|
||||
|
||||
/* ??? Otherwise result is (X != 0 ? X : 1). not handled. */
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Simplify bitwise binary operations.
|
||||
Return true if a transformation applied, otherwise return false. */
|
||||
|
||||
|
@ -1769,6 +1892,15 @@ simplify_bitwise_binary (gimple_stmt_iterator *gsi)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Try simple folding for X op !X, and X op X. */
|
||||
res = simplify_bitwise_binary_1 (code, TREE_TYPE (arg1), arg1, arg2);
|
||||
if (res != NULL_TREE)
|
||||
{
|
||||
gimple_assign_set_rhs_from_tree (gsi, res);
|
||||
update_stmt (gsi_stmt (*gsi));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue