diff options
author | Jan Hubicka <jh@suse.cz> | 2001-01-14 09:14:03 +0000 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2001-01-14 09:14:03 +0000 |
commit | a1b8572cac7c96128e10c2e93f8c7ef71d3d6d5d (patch) | |
tree | ef4ee7257a074a8c3351697865670bbd0a49b8bd | |
parent | 264ddbaa683da65a254b012d178149830339d502 (diff) | |
download | gcc-a1b8572cac7c96128e10c2e93f8c7ef71d3d6d5d.zip gcc-a1b8572cac7c96128e10c2e93f8c7ef71d3d6d5d.tar.gz gcc-a1b8572cac7c96128e10c2e93f8c7ef71d3d6d5d.tar.bz2 |
i386.c (ix86_expand_compare): Add bypass_test and second_test parameters.
* i386.c (ix86_expand_compare): Add bypass_test and second_test
parameters.
(ix86_expand_branch): Update.
(ix86_expand_setcc): Update to handle multiple test conditions.
(expand_int_movcc): Likewise.
(expand_fp_movcc): Likewise.
* i386-protos.h (ix86_expand_compare): New.
* i386.md (andqi_?_slp, orqi_?_slp): New.
(conditional trap expander): Update call to ix86_expand_compare.
From-SVN: r39005
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 106 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 48 |
4 files changed, 155 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a07f54b..7d82db9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +Sun Jan 14 10:09:48 MET 2001 Jan hubicka <jh@suse.cz> + + * i386.c (ix86_expand_compare): Add bypass_test and second_test + parameters. + (ix86_expand_branch): Update. + (ix86_expand_setcc): Update to handle multiple test conditions. + (expand_int_movcc): Likewise. + (expand_fp_movcc): Likewise. + * i386-protos.h (ix86_expand_compare): New. + * i386.md (andqi_?_slp, orqi_?_slp): New. + (conditional trap expander): Update call to ix86_expand_compare. + 2001-01-14 Richard Henderson <rth@redhat.com> * config/vax/vax.md: Use nonimmediate_operand instead of diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 3bf2ea8..cd44c4b 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -101,7 +101,7 @@ extern void ix86_expand_unary_operator PARAMS ((enum rtx_code, enum machine_mode extern int ix86_unary_operator_ok PARAMS ((enum rtx_code, enum machine_mode, rtx[])); extern int ix86_match_ccmode PARAMS ((rtx, enum machine_mode)); -extern rtx ix86_expand_compare PARAMS ((enum rtx_code)); +extern rtx ix86_expand_compare PARAMS ((enum rtx_code, rtx *, rtx *)); extern int ix86_use_fcomi_compare PARAMS ((enum rtx_code)); extern void ix86_expand_branch PARAMS ((enum rtx_code, rtx)); extern int ix86_expand_setcc PARAMS ((enum rtx_code, rtx)); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index eb8a852..6508478 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -5161,16 +5161,22 @@ ix86_expand_fp_compare (code, op0, op1, scratch, second_test, bypass_test) } rtx -ix86_expand_compare (code) +ix86_expand_compare (code, second_test, bypass_test) enum rtx_code code; + rtx *second_test, *bypass_test; { rtx op0, op1, ret; op0 = ix86_compare_op0; op1 = ix86_compare_op1; + if (second_test) + *second_test = NULL_RTX; + if (bypass_test) + *bypass_test = NULL_RTX; + if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT) ret = ix86_expand_fp_compare (code, op0, op1, gen_reg_rtx (HImode), - NULL, NULL); + second_test, bypass_test); else ret = ix86_expand_int_compare (code, op0, op1); @@ -5189,7 +5195,7 @@ ix86_expand_branch (code, label) case QImode: case HImode: case SImode: - tmp = ix86_expand_compare (code); + tmp = ix86_expand_compare (code, NULL, NULL); tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, gen_rtx_LABEL_REF (VOIDmode, label), pc_rtx); @@ -5404,7 +5410,8 @@ ix86_expand_setcc (code, dest) enum rtx_code code; rtx dest; { - rtx ret, tmp; + rtx ret, tmp, tmpreg; + rtx second_test, bypass_test; int type; if (GET_MODE (ix86_compare_op0) == DImode) @@ -5430,13 +5437,15 @@ ix86_expand_setcc (code, dest) if (type == 0) emit_move_insn (dest, const0_rtx); - ret = ix86_expand_compare (code); + ret = ix86_expand_compare (code, &second_test, &bypass_test); PUT_MODE (ret, QImode); tmp = dest; + tmpreg = dest; if (type == 0) { tmp = gen_lowpart (QImode, dest); + tmpreg = tmp; tmp = gen_rtx_STRICT_LOW_PART (VOIDmode, tmp); } else if (type == 1) @@ -5445,9 +5454,31 @@ ix86_expand_setcc (code, dest) tmp = gen_reg_rtx (QImode); else tmp = gen_lowpart (QImode, dest); + tmpreg = tmp; } emit_insn (gen_rtx_SET (VOIDmode, tmp, ret)); + if (bypass_test || second_test) + { + rtx test = second_test; + int bypass = 0; + rtx tmp2 = gen_reg_rtx (QImode); + if (bypass_test) + { + if (second_test) + abort(); + test = bypass_test; + bypass = 1; + PUT_CODE (test, reverse_condition_maybe_unordered (GET_CODE (test))); + } + PUT_MODE (test, QImode); + emit_insn (gen_rtx_SET (VOIDmode, tmp2, test)); + + if (bypass) + emit_insn (gen_andqi3 (tmp, tmpreg, tmp2)); + else + emit_insn (gen_iorqi3 (tmp, tmpreg, tmp2)); + } if (type == 1) { @@ -5469,6 +5500,7 @@ ix86_expand_int_movcc (operands) { enum rtx_code code = GET_CODE (operands[1]), compare_code; rtx compare_seq, compare_op; + rtx second_test, bypass_test; /* When the compare code is not LTU or GEU, we can not use sbbl case. In case comparsion is done with immediate, we can convert it to LTU or @@ -5489,7 +5521,7 @@ ix86_expand_int_movcc (operands) } start_sequence (); - compare_op = ix86_expand_compare (code); + compare_op = ix86_expand_compare (code, &second_test, &bypass_test); compare_seq = gen_sequence (); end_sequence (); @@ -5507,7 +5539,8 @@ ix86_expand_int_movcc (operands) HOST_WIDE_INT cf = INTVAL (operands[3]); HOST_WIDE_INT diff; - if (compare_code == LTU || compare_code == GEU) + if ((compare_code == LTU || compare_code == GEU) + && !second_test && !bypass_test) { /* Detect overlap between destination and compare sources. */ @@ -5796,11 +5829,36 @@ ix86_expand_int_movcc (operands) if (! nonimmediate_operand (operands[3], GET_MODE (operands[0]))) operands[3] = force_reg (GET_MODE (operands[0]), operands[3]); + if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3])) + { + rtx tmp = gen_reg_rtx (GET_MODE (operands[0])); + emit_move_insn (tmp, operands[3]); + operands[3] = tmp; + } + if (second_test && reg_overlap_mentioned_p (operands[0], operands[2])) + { + rtx tmp = gen_reg_rtx (GET_MODE (operands[0])); + emit_move_insn (tmp, operands[2]); + operands[2] = tmp; + } + emit_insn (compare_seq); emit_insn (gen_rtx_SET (VOIDmode, operands[0], gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), compare_op, operands[2], operands[3]))); + if (bypass_test) + emit_insn (gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), + bypass_test, + operands[3], + operands[0]))); + if (second_test) + emit_insn (gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), + second_test, + operands[2], + operands[0]))); return 1; /* DONE */ } @@ -5811,25 +5869,39 @@ ix86_expand_fp_movcc (operands) { enum rtx_code code; rtx tmp; - rtx compare_op; + rtx compare_op, second_test, bypass_test; /* The floating point conditional move instructions don't directly support conditions resulting from a signed integer comparison. */ code = GET_CODE (operands[1]); - compare_op = ix86_expand_compare (code); + compare_op = ix86_expand_compare (code, &second_test, &bypass_test); /* The floating point conditional move instructions don't directly support signed integer comparisons. */ - if (!fcmov_comparison_operator (compare_op, GET_MODE (XEXP (compare_op, 0)))) + if (!fcmov_comparison_operator (compare_op, VOIDmode)) { + if (second_test != NULL || bypass_test != NULL) + abort(); tmp = gen_reg_rtx (QImode); ix86_expand_setcc (code, tmp); code = NE; ix86_compare_op0 = tmp; ix86_compare_op1 = const0_rtx; - compare_op = ix86_expand_compare (code); + compare_op = ix86_expand_compare (code, &second_test, &bypass_test); + } + if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3])) + { + tmp = gen_reg_rtx (GET_MODE (operands[0])); + emit_move_insn (tmp, operands[3]); + operands[3] = tmp; + } + if (second_test && reg_overlap_mentioned_p (operands[0], operands[2])) + { + tmp = gen_reg_rtx (GET_MODE (operands[0])); + emit_move_insn (tmp, operands[2]); + operands[2] = tmp; } emit_insn (gen_rtx_SET (VOIDmode, operands[0], @@ -5837,6 +5909,18 @@ ix86_expand_fp_movcc (operands) compare_op, operands[2], operands[3]))); + if (bypass_test) + emit_insn (gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), + bypass_test, + operands[3], + operands[0]))); + if (second_test) + emit_insn (gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), + second_test, + operands[2], + operands[0]))); return 1; } diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 12d7e39..5e53f14 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -6263,6 +6263,16 @@ [(set_attr "type" "alu") (set_attr "mode" "QI,QI,SI")]) +(define_insn "*andqi_1_slp" + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) + (and:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "qi,qmi"))) + (clobber (reg:CC 17))] + "" + "and{b}\\t{%1, %0|%0, %1}" + [(set_attr "type" "alu1") + (set_attr "mode" "QI")]) + (define_insn "*andqi_2" [(set (reg 17) (compare (and:QI @@ -6280,6 +6290,19 @@ [(set_attr "type" "alu") (set_attr "mode" "QI,QI,SI")]) +(define_insn "*andqi_2_slp" + [(set (reg 17) + (compare (and:QI + (match_operand:QI 0 "nonimmediate_operand" "+q,qm") + (match_operand:QI 1 "nonimmediate_operand" "qmi,qi")) + (const_int 0))) + (set (strict_low_part (match_dup 0)) + (and:QI (match_dup 0) (match_dup 1)))] + "ix86_match_ccmode (insn, CCNOmode)" + "and{b}\\t{%1, %0|%0, %1}" + [(set_attr "type" "alu1") + (set_attr "mode" "QI")]) + ;; ??? A bug in recog prevents it from recognizing a const_int as an ;; operand to zero_extend in andqi_ext_1. It was checking explicitly ;; for a QImode operand, which of course failed. @@ -6479,6 +6502,16 @@ or{b}\\t{%2, %0|%0, %2} or{l}\\t{%k2, %k0|%k0, %k2}" [(set_attr "type" "alu") + (set_attr "mode" "QI,QI,SI")]) + +(define_insn "*iorqi_1_slp" + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+q,m")) + (ior:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "qmi,qi"))) + (clobber (reg:CC 17))] + "" + "or{b}\\t{%1, %0|%0, %1}" + [(set_attr "type" "alu1") (set_attr "mode" "QI")]) (define_insn "*iorqi_2" @@ -6494,6 +6527,18 @@ [(set_attr "type" "alu") (set_attr "mode" "QI")]) +(define_insn "*iorqi_2_slp" + [(set (reg 17) + (compare (ior:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm") + (match_operand:QI 1 "general_operand" "qim,qi")) + (const_int 0))) + (set (strict_low_part (match_dup 0)) + (ior:QI (match_dup 0) (match_dup 1)))] + "ix86_match_ccmode (insn, CCNOmode)" + "or{b}\\t{%1, %0|%0, %1}" + [(set_attr "type" "alu1") + (set_attr "mode" "QI")]) + (define_insn "*iorqi_3" [(set (reg 17) (compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0") @@ -12496,7 +12541,8 @@ " { emit_insn (gen_rtx_TRAP_IF (VOIDmode, - ix86_expand_compare (GET_CODE (operands[0])), + ix86_expand_compare (GET_CODE (operands[0]), + NULL_RTX, NULL_RTX), operands[1])); DONE; }") |