diff options
author | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-06-05 00:13:57 +0000 |
---|---|---|
committer | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-06-05 00:13:57 +0000 |
commit | aaf17c05d6455683d7c9dc3ab0b676774fe31058 (patch) | |
tree | e981f078bfcfcc87807e3fcb9cb8288abb40c57b /gcc/config | |
parent | 5b6fe9aedf81c8eea1ea3d616fdc829d257d41d3 (diff) | |
download | gcc-aaf17c05d6455683d7c9dc3ab0b676774fe31058.tar.gz |
* i386/i386.c (output_fp_conditional_move): New function
to output floating point conditional move.
(output_int_conditional_move): New function to output integer
conditional move.
* i386/i386.md (movsicci+5, movhicc+5, movdicc+5): Call
output_int_conditional_move () to output int conditional move.
(movsfcc+5, movdfcc+5, movxfcc+5): Call
output_fp_conditional_move () to output floating point
conditional move.
* i386/i386.c (put_condition_code): In INT mode, check
cc_prev_status.flags & CC_NO_OVERFLOW for GE and LT.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@20233 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/i386/i386.c | 131 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 194 |
2 files changed, 135 insertions, 190 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index da08da1ff8a..73d89dc8cdd 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -3097,7 +3097,10 @@ put_condition_code (code, reverse_cc, mode, file) return; case GE: - fputs ("ge", file); + if (cc_prev_status.flags & CC_NO_OVERFLOW) + fputs ("ns", file); + else + fputs ("ge", file); return; case GT: @@ -3109,7 +3112,10 @@ put_condition_code (code, reverse_cc, mode, file) return; case LT: - fputs ("l", file); + if (cc_prev_status.flags & CC_NO_OVERFLOW) + fputs ("s", file); + else + fputs ("l", file); return; case GEU: @@ -5132,3 +5138,124 @@ output_strlen_unroll (operands) return ""; } + +char * +output_fp_conditional_move (which_alternative, operands) + int which_alternative; + rtx operands[]; +{ + int code = GET_CODE (operands[1]); + + /* This is very tricky. We have to do it right. For a code segement + like: + + int foo; + double bar; + .... + foo = foo - x; + if (foo >= 0) + bar = y; + + final_scan_insn () may delete the insn which sets CC. We have to + tell final_scan_insn () if it should be reinserted. When CODE is + GT or LE, we have to check the CC_NO_OVERFLOW bit and return + NULL_PTR to tell final to reinsert the test insn because the + conditional move cannot be handled properly without it. */ + if ((code == GT || code == LE) + && (cc_prev_status.flags & CC_NO_OVERFLOW)) + return NULL_PTR; + + switch (which_alternative) + { + case 0: + /* r <- cond ? arg : r */ + output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); + break; + + case 1: + /* r <- cond ? r : arg */ + output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); + break; + + case 2: + /* r <- cond ? r : arg */ + output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); + output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); + break; + + default: + abort (); + } + + return ""; +} + +char * +output_int_conditional_move (which_alternative, operands) + int which_alternative; + rtx operands[]; +{ + int code = GET_CODE (operands[1]); + enum machine_mode mode; + rtx xops[4]; + + /* This is very tricky. We have to do it right. For a code segement + like: + + int foo, bar; + .... + foo = foo - x; + if (foo >= 0) + bar = y; + + final_scan_insn () may delete the insn which sets CC. We have to + tell final_scan_insn () if it should be reinserted. When CODE is + GT or LE, we have to check the CC_NO_OVERFLOW bit and return + NULL_PTR to tell final to reinsert the test insn because the + conditional move cannot be handled properly without it. */ + if ((code == GT || code == LE) + && (cc_prev_status.flags & CC_NO_OVERFLOW)) + return NULL_PTR; + + mode = GET_MODE (operands [0]); + if (mode == DImode) + { + xops [0] = gen_rtx_SUBREG (SImode, operands [0], 1); + xops [1] = operands [1]; + xops [2] = gen_rtx_SUBREG (SImode, operands [2], 1); + xops [3] = gen_rtx_SUBREG (SImode, operands [3], 1); + } + + switch (which_alternative) + { + case 0: + /* r <- cond ? arg : r */ + output_asm_insn (AS2 (cmov%C1,%2,%0), operands); + if (mode == DImode) + output_asm_insn (AS2 (cmov%C1,%2,%0), xops); + break; + + case 1: + /* r <- cond ? r : arg */ + output_asm_insn (AS2 (cmov%c1,%3,%0), operands); + if (mode == DImode) + output_asm_insn (AS2 (cmov%c1,%3,%0), xops); + break; + + case 2: + /* rm <- cond ? arg1 : arg2 */ + output_asm_insn (AS2 (cmov%C1,%2,%0), operands); + output_asm_insn (AS2 (cmov%c1,%3,%0), operands); + if (mode == DImode) + { + output_asm_insn (AS2 (cmov%C1,%2,%0), xops); + output_asm_insn (AS2 (cmov%c1,%3,%0), xops); + } + break; + + default: + abort (); + } + + return ""; +} diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index f060c05aee1..b2ee298ca19 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -7307,35 +7307,7 @@ byte_xor_operation: (match_operand:SI 2 "nonimmediate_operand" "rm,0,rm") (match_operand:SI 3 "nonimmediate_operand" "0,rm,rm")))] "TARGET_CMOVE && reload_completed" - "* -{ - - switch (which_alternative) - { - case 0: - /* r <- cond ? arg : r */ - output_asm_insn (AS2 (cmov%C1,%2,%0), operands); - break; - - case 1: - /* r <- cond ? r : arg */ - output_asm_insn (AS2 (cmov%c1,%3,%0), operands); - break; - - case 2: - /* r <- cond ? arg1 : arg2 */ - output_asm_insn (AS2 (cmov%C1,%2,%0), operands); - output_asm_insn (AS2 (cmov%c1,%3,%0), operands); - break; - - default: - abort(); - /* NOTREACHED */ - break; - } - - RET; -}") + "* return output_int_conditional_move (which_alternative, operands);") (define_expand "movhicc" [(set (match_operand:HI 0 "register_operand" "") @@ -7410,35 +7382,7 @@ byte_xor_operation: (match_operand:HI 2 "nonimmediate_operand" "rm,0,rm") (match_operand:HI 3 "nonimmediate_operand" "0,rm,rm")))] "TARGET_CMOVE && reload_completed" - "* -{ - - switch (which_alternative) - { - case 0: - /* r <- cond ? arg : r */ - output_asm_insn (AS2 (cmov%C1,%2,%0), operands); - break; - - case 1: - /* r <- cond ? r : arg */ - output_asm_insn (AS2 (cmov%c1,%3,%0), operands); - break; - - case 2: - /* r <- cond ? arg1 : arg2 */ - output_asm_insn (AS2 (cmov%C1,%2,%0), operands); - output_asm_insn (AS2 (cmov%c1,%3,%0), operands); - break; - - default: - abort(); - /* NOTREACHED */ - break; - } - - RET; -}") + "* return output_int_conditional_move (which_alternative, operands);") (define_expand "movsfcc" [(set (match_operand:SF 0 "register_operand" "") @@ -7512,35 +7456,7 @@ byte_xor_operation: (match_operand:SF 2 "register_operand" "f,0,f") (match_operand:SF 3 "register_operand" "0,f,f")))] "TARGET_CMOVE && reload_completed" - "* -{ - - switch (which_alternative) - { - case 0: - /* r <- cond ? arg : r */ - output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); - break; - - case 1: - /* r <- cond ? r : arg */ - output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); - break; - - case 2: - /* r <- cond ? r : arg */ - output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); - output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); - break; - - default: - abort(); - /* NOTREACHED */ - break; - } - - RET; -}") + "* return output_fp_conditional_move (which_alternative, operands);") (define_expand "movdfcc" [(set (match_operand:DF 0 "register_operand" "") @@ -7614,35 +7530,7 @@ byte_xor_operation: (match_operand:DF 2 "register_operand" "f,0,f") (match_operand:DF 3 "register_operand" "0,f,f")))] "TARGET_CMOVE && reload_completed" - "* -{ - - switch (which_alternative) - { - case 0: - /* r <- cond ? arg : r */ - output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); - break; - - case 1: - /* r <- cond ? r : arg */ - output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); - break; - - case 2: - /* r <- cond ? r : arg */ - output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); - output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); - break; - - default: - abort(); - /* NOTREACHED */ - break; - } - - RET; -}") + "* return output_fp_conditional_move (which_alternative, operands);") (define_expand "movxfcc" [(set (match_operand:XF 0 "register_operand" "") @@ -7716,35 +7604,7 @@ byte_xor_operation: (match_operand:XF 2 "register_operand" "f,0,f") (match_operand:XF 3 "register_operand" "0,f,f")))] "TARGET_CMOVE && reload_completed" - "* -{ - - switch (which_alternative) - { - case 0: - /* r <- cond ? arg : r */ - output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); - break; - - case 1: - /* r <- cond ? r : arg */ - output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); - break; - - case 2: - /* r <- cond ? r : arg */ - output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); - output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); - break; - - default: - abort(); - /* NOTREACHED */ - break; - } - - RET; -}") + "* return output_fp_conditional_move (which_alternative, operands);") (define_expand "movdicc" [(set (match_operand:DI 0 "register_operand" "") @@ -7818,49 +7678,7 @@ byte_xor_operation: (match_operand:DI 2 "nonimmediate_operand" "ro,0,ro") (match_operand:DI 3 "nonimmediate_operand" "0,ro,ro")))] "TARGET_CMOVE && reload_completed" - "* -{ - rtx xops[4]; - - xops[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); - xops[1] = operands[1]; - xops[2] = REG_P (operands[2]) - ? gen_rtx_REG (SImode, REGNO (operands[2]) + 1) - : adj_offsettable_operand (operands[2], 4); - xops[3] = REG_P (operands[3]) - ? gen_rtx_REG (SImode, REGNO (operands[3]) + 1) - : adj_offsettable_operand (operands[3], 4); - - switch (which_alternative) - { - case 0: - /* r <- cond ? arg : r */ - output_asm_insn (AS2 (cmov%C1,%2,%0), operands); - output_asm_insn (AS2 (cmov%C1,%2,%0), xops); - break; - - case 1: - /* r <- cond ? r : arg */ - output_asm_insn (AS2 (cmov%c1,%3,%0), operands); - output_asm_insn (AS2 (cmov%c1,%3,%0), xops); - break; - - case 2: - /* r <- cond ? arg1 : arg2 */ - output_asm_insn (AS2 (cmov%C1,%2,%0), operands); - output_asm_insn (AS2 (cmov%C1,%2,%0), xops); - output_asm_insn (AS2 (cmov%c1,%3,%0), operands); - output_asm_insn (AS2 (cmov%c1,%3,%0), xops); - break; - - default: - abort(); - /* NOTREACHED */ - break; - } - - RET; -}") + "* return output_int_conditional_move (which_alternative, operands);") (define_insn "strlensi_unroll" [(set (match_operand:SI 0 "register_operand" "=&r,&r") |