aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2015-08-12 14:27:40 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2015-08-12 14:27:40 +0000
commit7fd9012e478d7f759500bfa32ace358227853c2b (patch)
treeaca7b04ebfc6e0072000a94b403cb157edf421d6 /gcc
parentc0ba5a8b0cd64aa0d1024756bdf2c095199f289c (diff)
downloadgcc-7fd9012e478d7f759500bfa32ace358227853c2b.zip
gcc-7fd9012e478d7f759500bfa32ace358227853c2b.tar.gz
gcc-7fd9012e478d7f759500bfa32ace358227853c2b.tar.bz2
tree-ssa-sccvn.c (vn_nary_op_compute_hash): Also canonicalize comparison operand order and commutative ternary op operand order.
2015-08-12 Richard Biener <rguenther@suse.de> * tree-ssa-sccvn.c (vn_nary_op_compute_hash): Also canonicalize comparison operand order and commutative ternary op operand order. (sccvn_dom_walker::cond_stack): New state to track temporary expressions. (sccvn_dom_walker::after_dom_children): Remove tempoary expressions no longer valid. (sccvn_dom_walker::record_cond): Add a single temporary conditional expression. (sccvn_dom_walker::record_conds): Add a temporary conditional expressions and all related expressions also true/false. (sccvn_dom_walker::before_dom_children): Record temporary expressions based on the controlling condition of a single predecessor. When trying to simplify a conditional statement lookup expressions we might have inserted earlier. * gcc.dg/tree-ssa/ssa-fre-47.c: New testcase. * gcc.dg/tree-ssa/ssa-fre-48.c: Likewise. * gcc.dg/tree-ssa/ssa-fre-49.c: Likewise. * g++.dg/tree-ssa/pr61034.C: Adjust. * gcc.dg/fold-compare-2.c: Likewise. * gcc.dg/pr50763.c: Likewise. * gcc.dg/predict-3.c: Likewise. * gcc.dg/tree-ssa/20030709-2.c: Likewise. * gcc.dg/tree-ssa/pr19831-3.c: Likewise. * gcc.dg/tree-ssa/pr20657.c: Likewise. * gcc.dg/tree-ssa/pr21001.c: Likewise. * gcc.dg/tree-ssa/pr37508.c: Likewise. * gcc.dg/tree-ssa/vrp04.c: Likewise. * gcc.dg/tree-ssa/vrp07.c: Likewise. * gcc.dg/tree-ssa/vrp09.c: Likewise. * gcc.dg/tree-ssa/vrp16.c: Likewise. * gcc.dg/tree-ssa/vrp20.c: Likewise. * gcc.dg/tree-ssa/vrp25.c: Likewise. * gcc.dg/tree-ssa/vrp87.c: Likewise. From-SVN: r226814
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/testsuite/ChangeLog22
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr61034.C2
-rw-r--r--gcc/testsuite/gcc.dg/fold-compare-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/pr50763.c4
-rw-r--r--gcc/testsuite/gcc.dg/predict-3.c6
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/20030709-2.c8
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr19831-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr20657.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr21001.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr37508.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp04.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp07.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp09.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp16.c9
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp20.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp25.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp87.c13
-rw-r--r--gcc/tree-ssa-sccvn.c149
19 files changed, 223 insertions, 39 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0665009..6028d26 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@
+2015-08-12 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (vn_nary_op_compute_hash): Also canonicalize
+ comparison operand order and commutative ternary op operand order.
+ (sccvn_dom_walker::cond_stack): New state to track temporary
+ expressions.
+ (sccvn_dom_walker::after_dom_children): Remove tempoary expressions
+ no longer valid.
+ (sccvn_dom_walker::record_cond): Add a single temporary conditional
+ expression.
+ (sccvn_dom_walker::record_conds): Add a temporary conditional
+ expressions and all related expressions also true/false.
+ (sccvn_dom_walker::before_dom_children): Record temporary
+ expressions based on the controlling condition of a single
+ predecessor. When trying to simplify a conditional statement
+ lookup expressions we might have inserted earlier.
+
2015-08-12 Yvan Roux <yvan.roux@linaro.org>
PR target/67127
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b712e5f..15b0b41 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,25 @@
+2015-08-12 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/ssa-fre-47.c: New testcase.
+ * gcc.dg/tree-ssa/ssa-fre-48.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-fre-49.c: Likewise.
+ * g++.dg/tree-ssa/pr61034.C: Adjust.
+ * gcc.dg/fold-compare-2.c: Likewise.
+ * gcc.dg/pr50763.c: Likewise.
+ * gcc.dg/predict-3.c: Likewise.
+ * gcc.dg/tree-ssa/20030709-2.c: Likewise.
+ * gcc.dg/tree-ssa/pr19831-3.c: Likewise.
+ * gcc.dg/tree-ssa/pr20657.c: Likewise.
+ * gcc.dg/tree-ssa/pr21001.c: Likewise.
+ * gcc.dg/tree-ssa/pr37508.c: Likewise.
+ * gcc.dg/tree-ssa/vrp04.c: Likewise.
+ * gcc.dg/tree-ssa/vrp07.c: Likewise.
+ * gcc.dg/tree-ssa/vrp09.c: Likewise.
+ * gcc.dg/tree-ssa/vrp16.c: Likewise.
+ * gcc.dg/tree-ssa/vrp20.c: Likewise.
+ * gcc.dg/tree-ssa/vrp25.c: Likewise.
+ * gcc.dg/tree-ssa/vrp87.c: Likewise.
+
2015-08-12 Nathan Sidwell <nathan@acm.org>
* gcc.dg/vrp-min-max-1.c: New.
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr61034.C b/gcc/testsuite/g++.dg/tree-ssa/pr61034.C
index 14fd85a..628eb10 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr61034.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr61034.C
@@ -43,5 +43,5 @@ bool f(I a, I b, I c, I d) {
// This works only if everything is inlined into 'f'.
// { dg-final { scan-tree-dump-times ";; Function" 1 "fre2" } }
-// { dg-final { scan-tree-dump-times "free" 18 "fre2" } }
+// { dg-final { scan-tree-dump-times "free" 10 "fre2" } }
// { dg-final { scan-tree-dump-times "unreachable" 11 "fre2" } }
diff --git a/gcc/testsuite/gcc.dg/fold-compare-2.c b/gcc/testsuite/gcc.dg/fold-compare-2.c
index f94fe04..16f0fd9 100644
--- a/gcc/testsuite/gcc.dg/fold-compare-2.c
+++ b/gcc/testsuite/gcc.dg/fold-compare-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fno-tree-tail-merge -fdump-tree-vrp1" } */
+/* { dg-options "-O2 -fdump-tree-fre1" } */
extern void abort (void);
@@ -15,5 +15,5 @@ main(void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "Removing basic block" 2 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Removing basic block" 2 "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/pr50763.c b/gcc/testsuite/gcc.dg/pr50763.c
index b233e93..102056f 100644
--- a/gcc/testsuite/gcc.dg/pr50763.c
+++ b/gcc/testsuite/gcc.dg/pr50763.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-tail-merge -fno-tree-dominator-opts -fdump-tree-pre" } */
+/* { dg-options "-O2 -ftree-tail-merge -fno-tree-dominator-opts" } */
int bar (int i);
@@ -11,5 +11,3 @@ foo (int c, int d)
d = 33;
while (c == d);
}
-
-/* { dg-final { scan-tree-dump-times "== 33" 2 "pre"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-3.c b/gcc/testsuite/gcc.dg/predict-3.c
index 2335201..e1be7cc 100644
--- a/gcc/testsuite/gcc.dg/predict-3.c
+++ b/gcc/testsuite/gcc.dg/predict-3.c
@@ -12,6 +12,10 @@ void foo (int bound)
{
if (i < bound - 2)
global += bar (i);
+ /* The following test is redundant with the loop bound check in the
+ for stmt and thus eliminated by FRE which makes the controlled
+ stmt always executed and thus equivalent to 100%. Thus the
+ heuristic only applies three times. */
if (i <= bound)
global += bar (i);
if (i + 1 < bound)
@@ -21,4 +25,4 @@ void foo (int bound)
}
}
-/* { dg-final { scan-tree-dump-times "loop iv compare heuristics: 100.0%" 4 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop iv compare heuristics: 100.0%" 3 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030709-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030709-2.c
index aeff341..d4f42f93 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/20030709-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/20030709-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-cddce2" } */
+/* { dg-options "-O -fdump-tree-dce2" } */
struct rtx_def;
typedef struct rtx_def *rtx;
@@ -42,13 +42,13 @@ get_alias_set (t)
/* There should be precisely one load of ->decl.rtl. If there is
more than, then the dominator optimizations failed. */
-/* { dg-final { scan-tree-dump-times "->decl\\.rtl" 1 "cddce2"} } */
+/* { dg-final { scan-tree-dump-times "->decl\\.rtl" 1 "dce2"} } */
/* There should be no loads of .rtmem since the complex return statement
is just "return 0". */
-/* { dg-final { scan-tree-dump-times ".rtmem" 0 "cddce2"} } */
+/* { dg-final { scan-tree-dump-times ".rtmem" 0 "dce2"} } */
/* There should be one IF statement (the complex return statement should
collapse down to a simple return 0 without any conditionals). */
-/* { dg-final { scan-tree-dump-times "if " 1 "cddce2"} } */
+/* { dg-final { scan-tree-dump-times "if " 1 "dce2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19831-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-3.c
index f78a17f..f5cb72d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr19831-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-optimized" } */
void test2(void)
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20657.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20657.c
index c1317a7..727ca4c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr20657.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20657.c
@@ -3,7 +3,7 @@
statement, which was needed to eliminate the second "if" statement. */
/* { dg-do compile } */
-/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp1-details" } */
+/* { dg-options "-O2 -fno-tree-dominator-opts -fno-tree-fre -fdump-tree-vrp1-details" } */
int
foo (int a)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21001.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21001.c
index 05b495b..482d530 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr21001.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21001.c
@@ -5,7 +5,7 @@
range information out of the conditional. */
/* { dg-do compile } */
-/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp1-details" } */
+/* { dg-options "-O2 -fno-tree-dominator-opts -fno-tree-fre -fdump-tree-vrp1-details" } */
int
foo (int a)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr37508.c b/gcc/testsuite/gcc.dg/tree-ssa/pr37508.c
index aa33626..0963cd9 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr37508.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr37508.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1" } */
+/* { dg-options "-O2 -fno-tree-fre -fdump-tree-vrp1" } */
struct foo1 {
int i:1;
@@ -10,9 +10,10 @@ struct foo2 {
int test1 (struct foo1 *x)
{
- if (x->i == 0)
+ int i = x->i;
+ if (i == 0)
return 1;
- else if (x->i == -1)
+ else if (i == -1)
return 1;
return 0;
}
@@ -37,9 +38,10 @@ int test3 (struct foo1 *x)
int test4 (struct foo2 *x)
{
- if (x->i == 0)
+ unsigned int i = x->i;
+ if (i == 0)
return 1;
- else if (x->i == 1)
+ else if (i == 1)
return 1;
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp04.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp04.c
index 8af269f..61b7a47 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp04.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp04.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1" } */
+/* { dg-options "-O2 -fno-tree-fre -fdump-tree-vrp1" } */
int
foo (int a, int b)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp07.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp07.c
index 3bc6869..a5bd670 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp07.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp07.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fno-tree-fre -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */
int
foo (int i, int *p)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp09.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp09.c
index 98be0af..d42a566 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp09.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp09.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1 -std=gnu89" } */
+/* { dg-options "-O2 -fno-tree-fre -fdump-tree-vrp1 -std=gnu89" } */
foo (int *p)
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp16.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp16.c
index 00a8e1a..8f5d5c8 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp16.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp16.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
+/* { dg-options "-O2 -fno-tree-fre -fdump-tree-vrp1-details" } */
extern void abort (void) __attribute__ ((__noreturn__));
@@ -12,9 +12,10 @@ struct rtx_def
int
nonlocal_mentioned_p (rtx x)
{
- if (x->code == 6 || x->code == 7)
- if (x->code == 7)
- if (x->code != 7)
+ int code = x->code;
+ if (code == 6 || code == 7)
+ if (code == 7)
+ if (code != 7)
abort ();
}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp20.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp20.c
index 012d05a..60d1731 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp20.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp20.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-fwrapv -O1 -ftree-vrp -fdump-tree-vrp1" } */
+/* { dg-options "-fwrapv -O1 -fno-tree-fre -ftree-vrp -fdump-tree-vrp1" } */
extern void abort ();
extern void exit (int);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp25.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp25.c
index 30da333..cbc4ec3 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp25.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp25.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
+/* { dg-options "-O2 -fno-tree-fre -fdump-tree-vrp1-details" } */
extern void abort ();
extern void arf ();
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp87.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp87.c
index 7641c97..e81dd36 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp87.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp87.c
@@ -1,8 +1,8 @@
/* Setting LOGICAL_OP_NON_SHORT_CIRCUIT to 0 leads to two conditional jumps
- when evaluating an && condition. VRP is not able to optimize this. */
+ when evaluating an && condition. */
/* { dg-do compile { target { ! { logical_op_short_circuit || { m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* } } } } } */
-/* { dg-options "-O2 -fdump-tree-vrp2-details -fdump-tree-cddce2-details" } */
+/* { dg-options "-O2 -fdump-tree-fre1-details" } */
struct bitmap_head_def;
typedef struct bitmap_head_def *bitmap;
@@ -74,9 +74,6 @@ bitmap_ior_into (bitmap a, const_bitmap b)
return changed;
}
-/* Verify that VRP simplified an "if" statement. */
-/* { dg-final { scan-tree-dump "Folded into: if.*" "vrp2"} } */
-/* Verify that DCE after VRP2 eliminates a dead conversion
- to a (Bool). */
-/* { dg-final { scan-tree-dump "Deleting.*_Bool.*;" "cddce2"} } */
-
+/* Verify that FRE simplified an if stmt. */
+/* { dg-final { scan-tree-dump "Replaced a_elt_\[0-9\]+ != 0B with 1" "fre1" } } */
+/* { dg-final { scan-tree-dump "Replaced _\[0-9\]+ & _\[0-9\]+ with _\[0-9\]+" "fre1" } } */
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index eca0d44..003433c 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -2365,10 +2365,18 @@ vn_nary_op_compute_hash (const vn_nary_op_t vno1)
if (TREE_CODE (vno1->op[i]) == SSA_NAME)
vno1->op[i] = SSA_VAL (vno1->op[i]);
- if (vno1->length == 2
- && commutative_tree_code (vno1->opcode)
+ if (((vno1->length == 2
+ && commutative_tree_code (vno1->opcode))
+ || (vno1->length == 3
+ && commutative_ternary_tree_code (vno1->opcode)))
&& tree_swap_operands_p (vno1->op[0], vno1->op[1], false))
std::swap (vno1->op[0], vno1->op[1]);
+ else if (TREE_CODE_CLASS (vno1->opcode) == tcc_comparison
+ && tree_swap_operands_p (vno1->op[0], vno1->op[1], false))
+ {
+ std::swap (vno1->op[0], vno1->op[1]);
+ vno1->opcode = swap_tree_comparison (vno1->opcode);
+ }
hstate.add_int (vno1->opcode);
for (i = 0; i < vno1->length; ++i)
@@ -4281,13 +4289,105 @@ set_hashtable_value_ids (void)
class sccvn_dom_walker : public dom_walker
{
public:
- sccvn_dom_walker () : dom_walker (CDI_DOMINATORS), fail (false) {}
+ sccvn_dom_walker ()
+ : dom_walker (CDI_DOMINATORS), fail (false), cond_stack (vNULL) {}
virtual void before_dom_children (basic_block);
+ virtual void after_dom_children (basic_block);
+
+ void record_cond (basic_block,
+ enum tree_code code, tree lhs, tree rhs, bool value);
+ void record_conds (basic_block,
+ enum tree_code code, tree lhs, tree rhs, bool value);
bool fail;
+ vec<std::pair <basic_block, std::pair <vn_nary_op_t, vn_nary_op_t> > >
+ cond_stack;
};
+/* Record a temporary condition for the BB and its dominated blocks. */
+
+void
+sccvn_dom_walker::record_cond (basic_block bb,
+ enum tree_code code, tree lhs, tree rhs,
+ bool value)
+{
+ tree ops[2] = { lhs, rhs };
+ vn_nary_op_t old = NULL;
+ if (vn_nary_op_lookup_pieces (2, code, boolean_type_node, ops, &old))
+ current_info->nary->remove_elt_with_hash (old, old->hashcode);
+ vn_nary_op_t cond
+ = vn_nary_op_insert_pieces (2, code, boolean_type_node, ops,
+ value
+ ? boolean_true_node
+ : boolean_false_node, 0);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Recording temporarily ");
+ print_generic_expr (dump_file, ops[0], TDF_SLIM);
+ fprintf (dump_file, " %s ", get_tree_code_name (code));
+ print_generic_expr (dump_file, ops[1], TDF_SLIM);
+ fprintf (dump_file, " == %s%s\n",
+ value ? "true" : "false",
+ old ? " (old entry saved)" : "");
+ }
+ cond_stack.safe_push (std::make_pair (bb, std::make_pair (cond, old)));
+}
+
+/* Record temporary conditions for the BB and its dominated blocks
+ according to LHS CODE RHS == VALUE and its dominated conditions. */
+
+void
+sccvn_dom_walker::record_conds (basic_block bb,
+ enum tree_code code, tree lhs, tree rhs,
+ bool value)
+{
+ /* Record the original condition. */
+ record_cond (bb, code, lhs, rhs, value);
+
+ if (!value)
+ return;
+
+ /* Record dominated conditions if the condition is true. Note that
+ the inversion is already recorded. */
+ switch (code)
+ {
+ case LT_EXPR:
+ case GT_EXPR:
+ record_cond (bb, code == LT_EXPR ? LE_EXPR : GE_EXPR, lhs, rhs, true);
+ record_cond (bb, NE_EXPR, lhs, rhs, true);
+ record_cond (bb, EQ_EXPR, lhs, rhs, false);
+ break;
+
+ case EQ_EXPR:
+ record_cond (bb, LE_EXPR, lhs, rhs, true);
+ record_cond (bb, GE_EXPR, lhs, rhs, true);
+ record_cond (bb, LT_EXPR, lhs, rhs, false);
+ record_cond (bb, GT_EXPR, lhs, rhs, false);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* Restore expressions and values derived from conditionals. */
+
+void
+sccvn_dom_walker::after_dom_children (basic_block bb)
+{
+ while (!cond_stack.is_empty ()
+ && cond_stack.last ().first == bb)
+ {
+ vn_nary_op_t cond = cond_stack.last ().second.first;
+ vn_nary_op_t old = cond_stack.last ().second.second;
+ current_info->nary->remove_elt_with_hash (cond, cond->hashcode);
+ if (old)
+ vn_nary_op_insert_into (old, current_info->nary, false);
+ cond_stack.pop ();
+ }
+}
+
/* Value number all statements in BB. */
void
@@ -4320,6 +4420,39 @@ sccvn_dom_walker::before_dom_children (basic_block bb)
return;
}
+ /* If we have a single predecessor record the equivalence from a
+ possible condition on the predecessor edge. */
+ if (single_pred_p (bb))
+ {
+ edge e = single_pred_edge (bb);
+ /* Check if there are multiple executable successor edges in
+ the source block. Otherwise there is no additional info
+ to be recorded. */
+ edge e2;
+ FOR_EACH_EDGE (e2, ei, e->src->succs)
+ if (e2 != e
+ && e2->flags & EDGE_EXECUTABLE)
+ break;
+ if (e2 && (e2->flags & EDGE_EXECUTABLE))
+ {
+
+ gimple stmt = last_stmt (e->src);
+ if (stmt
+ && gimple_code (stmt) == GIMPLE_COND)
+ {
+ enum tree_code code = gimple_cond_code (stmt);
+ tree lhs = gimple_cond_lhs (stmt);
+ tree rhs = gimple_cond_rhs (stmt);
+ record_conds (bb, code, lhs, rhs,
+ (e->flags & EDGE_TRUE_VALUE) != 0);
+ code = invert_tree_comparison (code, HONOR_NANS (lhs));
+ if (code != ERROR_MARK)
+ record_conds (bb, code, lhs, rhs,
+ (e->flags & EDGE_TRUE_VALUE) == 0);
+ }
+ }
+ }
+
/* Value-number all defs in the basic-block. */
for (gphi_iterator gsi = gsi_start_phis (bb);
!gsi_end_p (gsi); gsi_next (&gsi))
@@ -4389,6 +4522,16 @@ sccvn_dom_walker::before_dom_children (basic_block bb)
rhs = vn_get_expr_for (rhs);
val = fold_binary (gimple_cond_code (stmt),
boolean_type_node, lhs, rhs);
+ /* If that didn't simplify to a constant see if we have recorded
+ temporary expressions from taken edges. */
+ if (!val || TREE_CODE (val) != INTEGER_CST)
+ {
+ tree ops[2];
+ ops[0] = gimple_cond_lhs (stmt);
+ ops[1] = gimple_cond_rhs (stmt);
+ val = vn_nary_op_lookup_pieces (2, gimple_cond_code (stmt),
+ boolean_type_node, ops, NULL);
+ }
break;
}
case GIMPLE_SWITCH: