diff options
author | krebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-09-03 08:06:09 +0000 |
---|---|---|
committer | krebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-09-03 08:06:09 +0000 |
commit | 2bd387ca3808109f9bf9a3e36966bcc3ea793c75 (patch) | |
tree | 0ec221d20517879803b72379a28760cd84f31bb3 /gcc/config/s390 | |
parent | 845d5572d14e4a3b04a835b9a21a4fd8c1be8344 (diff) | |
download | gcc-2bd387ca3808109f9bf9a3e36966bcc3ea793c75.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@214850 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/s390')
-rw-r--r-- | gcc/config/s390/s390.md | 54 |
1 files changed, 51 insertions, 3 deletions
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<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). ; |