diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f5b124103b7b..4a9e3a27d147 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +Fri Jun 5 01:12:15 1998 H.J. Lu (hjl@gnu.org) + + * 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. + Thu Jun 4 16:09:51 1998 Dave Brolley * dbxout.c (dbxout_type): Output arrays of bits as if diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index da08da1ff8af..73d89dc8cdda 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 f060c05aee14..b2ee298ca192 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")