aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2013-05-17 17:32:50 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2013-05-17 17:32:50 +0200
commit07b5d54c9074c902e47f7f3b7f92d3ca540d8fdc (patch)
tree2fb4ea4adfb26ac3284ac3d647b485a077682d1d
parent1acc4169f868d25fcec45925a36b4931ec61efc0 (diff)
downloadgcc-07b5d54c9074c902e47f7f3b7f92d3ca540d8fdc.zip
gcc-07b5d54c9074c902e47f7f3b7f92d3ca540d8fdc.tar.gz
gcc-07b5d54c9074c902e47f7f3b7f92d3ca540d8fdc.tar.bz2
re PR rtl-optimization/57281 (x86_64-linux loop fails to terminate at -O3 -m32)
PR rtl-optimization/57281 PR rtl-optimization/57300 * config/i386/i386.md (extendsidi2_1 dead reg splitter): Remove. (extendsidi2_1 peephole2s): Add instead 2 new peephole2s, that undo what the other splitter did if the registers are dead. * gcc.dg/pr57300.c: New test. * gcc.c-torture/execute/pr57281.c: New test. From-SVN: r199021
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/i386/i386.md56
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr57281.c25
-rw-r--r--gcc/testsuite/gcc.dg/pr57300.c21
5 files changed, 101 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8dfc0ce..98ce704 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2013-05-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/57281
+ PR rtl-optimization/57300
+ * config/i386/i386.md (extendsidi2_1 dead reg splitter): Remove.
+ (extendsidi2_1 peephole2s): Add instead 2 new peephole2s, that undo
+ what the other splitter did if the registers are dead.
+
2013-05-17 Uros Bizjak <ubizjak@gmail.com>
Backport from mainline
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 2e450e3..455fb63 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -3647,22 +3647,8 @@
"!TARGET_64BIT"
"#")
-;; Extend to memory case when source register does die.
-(define_split
- [(set (match_operand:DI 0 "memory_operand")
- (sign_extend:DI (match_operand:SI 1 "register_operand")))
- (clobber (reg:CC FLAGS_REG))
- (clobber (match_operand:SI 2 "register_operand"))]
- "(reload_completed
- && dead_or_set_p (insn, operands[1])
- && !reg_mentioned_p (operands[1], operands[0]))"
- [(set (match_dup 3) (match_dup 1))
- (parallel [(set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31)))
- (clobber (reg:CC FLAGS_REG))])
- (set (match_dup 4) (match_dup 1))]
- "split_double_mode (DImode, &operands[0], 1, &operands[3], &operands[4]);")
-
-;; Extend to memory case when source register does not die.
+;; Split the memory case. If the source register doesn't die, it will stay
+;; this way, if it does die, following peephole2s take care of it.
(define_split
[(set (match_operand:DI 0 "memory_operand")
(sign_extend:DI (match_operand:SI 1 "register_operand")))
@@ -3691,6 +3677,44 @@
DONE;
})
+;; Peepholes for the case where the source register does die, after
+;; being split with the above splitter.
+(define_peephole2
+ [(set (match_operand:SI 0 "memory_operand")
+ (match_operand:SI 1 "register_operand"))
+ (set (match_operand:SI 2 "register_operand") (match_dup 1))
+ (parallel [(set (match_dup 2)
+ (ashiftrt:SI (match_dup 2) (const_int 31)))
+ (clobber (reg:CC FLAGS_REG))])
+ (set (match_operand:SI 3 "memory_operand") (match_dup 2))]
+ "REGNO (operands[1]) != REGNO (operands[2])
+ && peep2_reg_dead_p (2, operands[1])
+ && peep2_reg_dead_p (4, operands[2])
+ && !reg_mentioned_p (operands[2], operands[3])"
+ [(set (match_dup 0) (match_dup 1))
+ (parallel [(set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31)))
+ (clobber (reg:CC FLAGS_REG))])
+ (set (match_dup 3) (match_dup 1))])
+
+(define_peephole2
+ [(set (match_operand:SI 0 "memory_operand")
+ (match_operand:SI 1 "register_operand"))
+ (parallel [(set (match_operand:SI 2 "register_operand")
+ (ashiftrt:SI (match_dup 1) (const_int 31)))
+ (clobber (reg:CC FLAGS_REG))])
+ (set (match_operand:SI 3 "memory_operand") (match_dup 2))]
+ "/* cltd is shorter than sarl $31, %eax */
+ !optimize_function_for_size_p (cfun)
+ && true_regnum (operands[1]) == AX_REG
+ && true_regnum (operands[2]) == DX_REG
+ && peep2_reg_dead_p (2, operands[1])
+ && peep2_reg_dead_p (3, operands[2])
+ && !reg_mentioned_p (operands[2], operands[3])"
+ [(set (match_dup 0) (match_dup 1))
+ (parallel [(set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31)))
+ (clobber (reg:CC FLAGS_REG))])
+ (set (match_dup 3) (match_dup 1))])
+
;; Extend to register case. Optimize case where source and destination
;; registers match and cases where we can use cltd.
(define_split
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7f55104..21f4b5d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2013-05-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/57281
+ PR rtl-optimization/57300
+ * gcc.dg/pr57300.c: New test.
+ * gcc.c-torture/execute/pr57281.c: New test.
+
2013-05-16 Dodji Seketeli <dodji@redhat.com>
PR c++/56782 - Regression with empty pack expansions
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr57281.c b/gcc/testsuite/gcc.c-torture/execute/pr57281.c
new file mode 100644
index 0000000..db3db10
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr57281.c
@@ -0,0 +1,25 @@
+/* PR rtl-optimization/57281 */
+
+int a = 1, b, d, *e = &d;
+long long c, *g = &c;
+volatile long long f;
+
+int
+foo (int h)
+{
+ int j = *g = b;
+ return h == 0 ? j : 0;
+}
+
+int
+main ()
+{
+ int h = a;
+ for (; b != -20; b--)
+ {
+ (int) f;
+ *e = 0;
+ *e = foo (h);
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr57300.c b/gcc/testsuite/gcc.dg/pr57300.c
new file mode 100644
index 0000000..13a272d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr57300.c
@@ -0,0 +1,21 @@
+/* PR rtl-optimization/57300 */
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+
+extern void abort (void);
+int a, b, d[10];
+long long c;
+
+int
+main ()
+{
+ int e;
+ for (e = 0; e < 10; e++)
+ d[e] = 1;
+ if (d[0])
+ c = a = (b == 0 || 1 % b);
+ if (a != 1)
+ abort ();
+ return 0;
+}