summaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1998-06-05 00:13:57 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1998-06-05 00:13:57 +0000
commitaaf17c05d6455683d7c9dc3ab0b676774fe31058 (patch)
treee981f078bfcfcc87807e3fcb9cb8288abb40c57b /gcc/config
parent5b6fe9aedf81c8eea1ea3d616fdc829d257d41d3 (diff)
downloadgcc-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.c131
-rw-r--r--gcc/config/i386/i386.md194
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")