From b7d19263fe7c484b127c133eb33e9743f0642e5e Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Wed, 3 Sep 2014 08:06:09 +0000 Subject: [PATCH] re PR bootstrap/61078 (ESA mode bootstrap failure since r209897) 2014-09-03 Andreas Krebbel 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 PR target/61078 * gcc.target/s390/pr61078.c: New testcase. From-SVN: r214850 --- gcc/ChangeLog | 6 +++ gcc/config/s390/s390.md | 54 +++++++++++++++++++++++-- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.target/s390/pr61078.c | 26 ++++++++++++ 4 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.target/s390/pr61078.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 00603fa4f9a..448eec8bdfb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2014-09-03 Andreas Krebbel + + 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 * config/nds32/nds32.h (PIC_OFFSET_TABLE_REGNUM): Define. diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index dde529cc684..bcfe8f94f7a 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -7366,13 +7366,27 @@ [(set_attr "op_type" "RR") (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 7c71898205d..63105ca7b8e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-09-03 Andreas Krebbel + + PR target/61078 + * gcc.target/s390/pr61078.c: New testcase. + 2014-09-03 Uros Bizjak * 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 00000000000..2f95eba8e9e --- /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; +} -- 2.30.2