aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndreas Krebbel <Andreas.Krebbel@de.ibm.com>2014-09-03 08:06:09 +0000
committerAndreas Krebbel <krebbel@gcc.gnu.org>2014-09-03 08:06:09 +0000
commitb7d19263fe7c484b127c133eb33e9743f0642e5e (patch)
tree0ec221d20517879803b72379a28760cd84f31bb3 /gcc
parent64a08b7f989fa4a1bace97187e5665ebeb6ea586 (diff)
downloadgcc-b7d19263fe7c484b127c133eb33e9743f0642e5e.zip
gcc-b7d19263fe7c484b127c133eb33e9743f0642e5e.tar.gz
gcc-b7d19263fe7c484b127c133eb33e9743f0642e5e.tar.bz2
re PR bootstrap/61078 (ESA mode bootstrap failure since r209897)
2014-09-03 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> PR target/61078 * config/s390/s390.md ("*negdi2_31"): Add s390_split_ok_p check and add a second splitter to handle the remaining cases. 2014-09-03 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> PR target/61078 * gcc.target/s390/pr61078.c: New testcase. From-SVN: r214850
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/s390/s390.md54
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/s390/pr61078.c26
4 files changed, 88 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 00603fa..448eec8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2014-09-03 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ PR target/61078
+ * config/s390/s390.md ("*negdi2_31"): Add s390_split_ok_p check
+ and add a second splitter to handle the remaining cases.
+
2014-09-03 Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32.h (PIC_OFFSET_TABLE_REGNUM): Define.
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index dde529c..bcfe8f9 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -7366,13 +7366,27 @@
[(set_attr "op_type" "RR<E>")
(set_attr "z10prop" "z10_super_c_E1")])
-(define_insn_and_split "*negdi2_31"
+(define_insn "*negdi2_31"
[(set (match_operand:DI 0 "register_operand" "=d")
(neg:DI (match_operand:DI 1 "register_operand" "d")))
(clobber (reg:CC CC_REGNUM))]
"!TARGET_ZARCH"
- "#"
- "&& reload_completed"
+ "#")
+
+; Split a DImode NEG on 31bit into 2 SImode NEGs
+
+; Doing the twos complement separately on the SImode parts does an
+; unwanted +1 on the high part which needs to be subtracted afterwards
+; ... unless the +1 on the low part created an overflow.
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (neg:DI (match_operand:DI 1 "register_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_ZARCH
+ && (REGNO (operands[0]) == REGNO (operands[1])
+ || s390_split_ok_p (operands[0], operands[1], DImode, 0))
+ && reload_completed"
[(parallel
[(set (match_dup 2) (neg:SI (match_dup 3)))
(clobber (reg:CC CC_REGNUM))])
@@ -7394,6 +7408,40 @@
operands[5] = operand_subword (operands[1], 1, 0, DImode);
operands[6] = gen_label_rtx ();")
+; Like above but first make a copy of the low part of the src operand
+; since it might overlap with the high part of the destination.
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (neg:DI (match_operand:DI 1 "register_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_ZARCH
+ && s390_split_ok_p (operands[0], operands[1], DImode, 1)
+ && reload_completed"
+ [; Make a backup of op5 first
+ (set (match_dup 4) (match_dup 5))
+ ; Setting op2 here might clobber op5
+ (parallel
+ [(set (match_dup 2) (neg:SI (match_dup 3)))
+ (clobber (reg:CC CC_REGNUM))])
+ (parallel
+ [(set (reg:CCAP CC_REGNUM)
+ (compare:CCAP (neg:SI (match_dup 4)) (const_int 0)))
+ (set (match_dup 4) (neg:SI (match_dup 4)))])
+ (set (pc)
+ (if_then_else (ne (reg:CCAP CC_REGNUM) (const_int 0))
+ (pc)
+ (label_ref (match_dup 6))))
+ (parallel
+ [(set (match_dup 2) (plus:SI (match_dup 2) (const_int -1)))
+ (clobber (reg:CC CC_REGNUM))])
+ (match_dup 6)]
+ "operands[2] = operand_subword (operands[0], 0, 0, DImode);
+ operands[3] = operand_subword (operands[1], 0, 0, DImode);
+ operands[4] = operand_subword (operands[0], 1, 0, DImode);
+ operands[5] = operand_subword (operands[1], 1, 0, DImode);
+ operands[6] = gen_label_rtx ();")
+
;
; neg(df|sf)2 instruction pattern(s).
;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7c71898..63105ca 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-09-03 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ PR target/61078
+ * gcc.target/s390/pr61078.c: New testcase.
+
2014-09-03 Uros Bizjak <ubizjak@gmail.com>
* gcc.dg/20111227-2.c: Compile only for x86 targets.
diff --git a/gcc/testsuite/gcc.target/s390/pr61078.c b/gcc/testsuite/gcc.target/s390/pr61078.c
new file mode 100644
index 0000000..2f95eba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr61078.c
@@ -0,0 +1,26 @@
+/* This testcase is extracted from s390_emit_prologue. The negation
+ of a 64bit value got split incorrectly on 31 bit. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -mesa -m31" } */
+
+extern void abort (void);
+
+long long frame_size = 42;
+
+int __attribute__((noinline))
+foo (int a __attribute__((unused)), long long b)
+{
+ return (int)b;
+}
+
+int
+main ()
+{
+ if (frame_size > 0)
+ {
+ if (foo (0, -frame_size) != -42)
+ abort ();
+ }
+ return 0;
+}