From 74f4459c661b0597a1cb1080a1e6c34db40f921d Mon Sep 17 00:00:00 2001 From: bonzini Date: Tue, 12 May 2009 09:43:48 +0000 Subject: [PATCH] Merge cond-optab branch. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@147425 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 567 ++++++++++++ gcc/combine.c | 29 - gcc/config/alpha/alpha-protos.h | 4 +- gcc/config/alpha/alpha.c | 119 ++- gcc/config/alpha/alpha.h | 18 - gcc/config/alpha/alpha.md | 239 +---- gcc/config/alpha/predicates.md | 6 + gcc/config/arc/arc.c | 17 +- gcc/config/arc/arc.h | 5 - gcc/config/arc/arc.md | 337 +------ gcc/config/arm/arm.c | 4 - gcc/config/arm/arm.h | 4 - gcc/config/arm/arm.md | 448 +++------ gcc/config/arm/predicates.md | 8 +- gcc/config/avr/avr-protos.h | 4 +- gcc/config/avr/avr.c | 43 +- gcc/config/avr/avr.md | 274 +++--- gcc/config/bfin/bfin.c | 18 +- gcc/config/bfin/bfin.h | 1 - gcc/config/bfin/bfin.md | 275 ++---- gcc/config/bfin/predicates.md | 8 +- gcc/config/cris/cris.c | 22 +- gcc/config/cris/cris.md | 130 +-- gcc/config/crx/crx-protos.h | 4 - gcc/config/crx/crx.c | 41 - gcc/config/crx/crx.h | 7 - gcc/config/crx/crx.md | 79 +- gcc/config/fr30/fr30.c | 6 - gcc/config/fr30/fr30.h | 10 - gcc/config/fr30/fr30.md | 176 +--- gcc/config/frv/frv-protos.h | 4 +- gcc/config/frv/frv.c | 29 +- gcc/config/frv/frv.h | 3 - gcc/config/frv/frv.md | 330 +------ gcc/config/h8300/h8300-protos.h | 3 +- gcc/config/h8300/h8300.c | 33 +- gcc/config/h8300/h8300.md | 495 +++++----- gcc/config/i386/i386-protos.h | 2 +- gcc/config/i386/i386.c | 20 +- gcc/config/i386/i386.md | 318 +++++-- gcc/config/ia64/ia64-protos.h | 9 +- gcc/config/ia64/ia64.c | 35 +- gcc/config/ia64/ia64.md | 367 ++++---- gcc/config/ia64/predicates.md | 5 + gcc/config/iq2000/iq2000-protos.h | 2 +- gcc/config/iq2000/iq2000.c | 64 +- gcc/config/iq2000/iq2000.h | 7 - gcc/config/iq2000/iq2000.md | 400 +------- gcc/config/iq2000/predicates.md | 8 + gcc/config/m32c/cond.md | 102 +- gcc/config/m32c/m32c-protos.h | 4 - gcc/config/m32c/m32c.c | 79 +- gcc/config/m32c/m32c.md | 3 - gcc/config/m32r/m32r-protos.h | 1 + gcc/config/m32r/m32r.c | 153 ++- gcc/config/m32r/m32r.h | 6 - gcc/config/m32r/m32r.md | 415 +-------- gcc/config/m68hc11/m68hc11.c | 15 +- gcc/config/m68hc11/m68hc11.h | 2 - gcc/config/m68hc11/m68hc11.md | 297 ++---- gcc/config/m68k/constraints.md | 5 + gcc/config/m68k/m68k.c | 29 +- gcc/config/m68k/m68k.h | 1 - gcc/config/m68k/m68k.md | 553 +++++------ gcc/config/m68k/predicates.md | 23 + gcc/config/mcore/mcore-protos.h | 6 +- gcc/config/mcore/mcore.c | 66 +- gcc/config/mcore/mcore.md | 340 +------ gcc/config/mips/mips-protos.h | 6 +- gcc/config/mips/mips-ps-3d.md | 2 +- gcc/config/mips/mips.c | 118 +-- gcc/config/mips/mips.h | 1 - gcc/config/mips/mips.md | 159 +--- gcc/config/mips/predicates.md | 6 + gcc/config/mmix/mmix-protos.h | 1 - gcc/config/mmix/mmix.c | 62 +- gcc/config/mmix/mmix.h | 5 - gcc/config/mmix/mmix.md | 250 ++--- gcc/config/mmix/predicates.md | 5 + gcc/config/mn10300/mn10300.c | 8 +- gcc/config/mn10300/mn10300.md | 204 ++-- gcc/config/pa/pa-protos.h | 3 +- gcc/config/pa/pa.c | 81 +- gcc/config/pa/pa.h | 12 - gcc/config/pa/pa.md | 531 +---------- gcc/config/pdp11/pdp11-protos.h | 2 +- gcc/config/pdp11/pdp11.c | 23 +- gcc/config/pdp11/pdp11.h | 3 + gcc/config/pdp11/pdp11.md | 522 ++--------- gcc/config/picochip/picochip.md | 113 +-- gcc/config/rs6000/predicates.md | 10 +- gcc/config/rs6000/rs6000-protos.h | 4 +- gcc/config/rs6000/rs6000.c | 153 ++- gcc/config/rs6000/rs6000.h | 6 - gcc/config/rs6000/rs6000.md | 307 ++---- gcc/config/s390/predicates.md | 8 + gcc/config/s390/s390.c | 17 +- gcc/config/s390/s390.h | 6 - gcc/config/s390/s390.md | 208 +++-- gcc/config/score/score-conv.h | 5 - gcc/config/score/score-protos.h | 1 - gcc/config/score/score.c | 18 +- gcc/config/score/score.md | 124 +-- gcc/config/score/score3.c | 13 +- gcc/config/score/score3.h | 1 - gcc/config/score/score7.c | 13 +- gcc/config/score/score7.h | 1 - gcc/config/sh/predicates.md | 11 + gcc/config/sh/sh-protos.h | 8 +- gcc/config/sh/sh.c | 281 ++++-- gcc/config/sh/sh.md | 1643 ++++++++------------------------- gcc/config/sparc/sparc-protos.h | 9 +- gcc/config/sparc/sparc.c | 278 ++++-- gcc/config/sparc/sparc.h | 6 - gcc/config/sparc/sparc.md | 917 +++--------------- gcc/config/spu/spu-protos.h | 3 +- gcc/config/spu/spu.c | 59 +- gcc/config/spu/spu.h | 5 - gcc/config/spu/spu.md | 187 +--- gcc/config/stormy16/stormy16-protos.h | 2 +- gcc/config/stormy16/stormy16.c | 34 +- gcc/config/stormy16/stormy16.h | 7 - gcc/config/stormy16/stormy16.md | 105 +-- gcc/config/v850/v850.c | 5 + gcc/config/v850/v850.md | 302 ++---- gcc/config/vax/vax-protos.h | 2 +- gcc/config/vax/vax.c | 54 +- gcc/config/vax/vax.h | 1 + gcc/config/vax/vax.md | 81 +- gcc/config/xtensa/predicates.md | 3 + gcc/config/xtensa/xtensa-protos.h | 4 +- gcc/config/xtensa/xtensa.c | 63 +- gcc/config/xtensa/xtensa.h | 11 - gcc/config/xtensa/xtensa.md | 77 +- gcc/doc/md.texi | 296 ++---- gcc/doc/tm.texi | 127 ++- gcc/dojump.c | 58 -- gcc/expmed.c | 122 +-- gcc/expr.h | 6 +- gcc/final.c | 19 +- gcc/genopinit.c | 5 +- gcc/ifcvt.c | 6 +- gcc/optabs.c | 384 ++++---- gcc/optabs.h | 29 +- gcc/simplify-rtx.c | 16 +- 145 files changed, 5040 insertions(+), 10335 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9388421627b..cbe7b3097e1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,572 @@ 2009-05-12 Paolo Bonzini + * dojump.c (compare_from_rtx): Delete. + * expmed.c (emit_store_flag): Only try cstore_optab. Canonicalize + any MODE_CC mode to the cstorecc4 pattern. Use prepare_operand, fail + if the comparison does not satisfy the predicate; test predicates for + operands 2 and 3 of a cstore pattern. Don't try cstore optab + further if one existing pattern fails. + * expr.h (compare_from_rtx): Delete. + (prepare_operand): Declare it. + * optabs.c: Change "lib call" to "libcall" throughout. + (bcc_gen_fctn, setcc_gen_code, trap_rtx, + HAVE_conditional_trap, emit_cmp_insn): Delete. + (can_compare_p): Delete cmp_optab case. + (prepare_float_lib_cmp): Return an rtx and a machine mode. + Accept other parameters by value. + (prepare_operand): Make non-static. + (prepare_cmp_insn): Return an rtx and a machine mode. Accept + other parameters by value. Try to widen operands here based on + an optab_methods argument and looking at cbranch_optab. + (emit_cmp_and_jump_insn_1): Accept test and mode, remove widening loop. + Use cbranch_optab directly. + (emit_cmp_and_jump_insns): Fix comment. Adjust call to prepare_cmp_insn + and emit_cmp_and_jump_insn_1, remove obsolete assertion. + (emit_conditional_move, emit_conditional_add): Inline what's needed + of compare_from_rtx, using new prepare_cmp_insn for the rest. + (init_optabs): Init cmp_optab with UNKNOWN, cbranch_optab + with COMPARE. Move cmov_optab and cstore_optab above + with cbranch_optab, move cmp_optab down with ucmp_optab, + remove tst_otpab. Do not initialize trap_rtx. + (gen_cond_trap): Do it here. Use ctrap_optab. Test predicate + for trap code. Do not check HAVE_conditional_trap. Use + prepare_cmp_insn. Accept no predicate for operand 3. + * optabs.h (OTI_cmp): Mark as used only for libcalls. + (OTI_ctrap, ctrap_optab): New. + (tst_optab): Delete. + (bcc_gen_fctn, setcc_gen_code, emit_cmp_insn): Delete. + * ifcvt.c (find_if_header): Replace HAVE_conditional_trap + with lookup of ctrap_optab. + * genopinit.c (cmp_optab, tst_optab, bcc_gen_fctn, + setcc_gen_code): Delete. + (ctrap_optab): New. + + * combine.c (combine_simplify_rtx, simplify_set): Do not + special case comparing against zero for cc0 machines. + * simplify-rtx.c (simplify_binary_operation_1): Never remove + COMPARE on cc0 machines. + (simplify_relational_operation): Return a new expression when + a COMPARE could be removed. + * final.c (final_scan_insn): Compare cc_status values + against LHS of a (compare FOO (const_int 0)) cc0 source. + Also check if cc_status.value is the full compare. + + * doc/md.texi (bCC, sCC, tstMM, cmpMM): Delete. + (cstoreMM4): Document. + (conditional_trap): Document ctrapMM4 instead. + (sync_compare_and_swapMM): Refer to cbranchcc4. + (Dependent Patterns): Eliminate obsolete information referring to + the old jump optimization phase. + (Canonicalization): Include cbranchcc4 case, omit canonicalization + of compares with 0 on cc0 machines. + (Jump Patterns): Refer to MODE_CC jump patterns preferably, + avoiding references to cc0. Remove text about storing operands + in cmpMM. + * doc/tm.texi (Condition Codes): Include blurb on different + condition code representations, separate into subsections for + CC0, MODE_CC and conditional execution. + + * config/alpha/alpha-protos.h (alpha_emit_conditional_branch, + alpha_emit_setcc): Accept operands and a machine mode. + * config/alpha/alpha.c (alpha_emit_conditional_branch): + Get code/op0/op1 from operands, use machine mode argument + instead of alpha_compare.fp_p. Emit the branch here. + (alpha_emit_setcc): Likewise, and return boolean. + (alpha_emit_conditional_move): Likewise. Assert that + cmp_op_mode == cmp_mode, and simplify accordingly. + * config/alpha/alpha.h (struct alpha_compare, alpha_compare): Delete. + * config/alpha/alpha.md (cmpdf, cmptf, cmpdi, bCC, sCC): Delete. + (cbranchdf4, cbranchtf4, cbranchdi4, cstoredf4, cstoretf4, + cstoredi4): Delete. + (stack probe test): Use cbranchdi4. + * config/alpha/predicates.md (alpha_cbranch_operator): New. + + * config/arc/arc.c (gen_compare_reg): Do not emit cmp. + * config/arc/arc.h (movsicc, movsfcc): Use it. + (movdicc, *movdicc_insn, movdfcc, *movdfcc_insn): Remove. + (cbranchsi4, cstoresi4): New. + (cmpsi, bCC and sCC expanders): Remove. + + * config/arm/arm.c (arm_compare_op0, arm_compare_op1): Delete. + * config/arm/arm.h (arm_compare_op0, arm_compare_op1): Delete. + * config/arm/predicates.md (arm_comparison_operator): Only include + floating-point operators if there is a hardware floating-point unit. + * config/arm/arm.md (cbranchsi4, cstoresi4): Enable for TARGET_32BIT, + deferring to cbranch_cc and cstore_cc respectively. + (cbranchsf4, cbranchdf4, cbranchdi4, cstoresf4, cstoredf4, cstoredi4, + cbranch_cc, cstore_cc): New. + (movsicc, movsfcc, movdfcc): Do not use arm_compare_op0 and + arm_compare_op1. + (bCC, sCC, cmpsi, cmpsf, cmpdf, cmpdi): Delete. + + * config/avr/avr-protos.h (out_tstsi, out_tsthi): Adjust prototype. + * config/avr/avr.c (out_tstsi, out_tsthi): Get the tested operand + as an argument. + (adjust_insn_length): Adjust calls. + (avr_reorg): Handle (compare (foo) (const_int 0)). + * config/avr/avr.md (tstqi, tsthi, tstsi): Remove. + (*negated_tstqi, *negated_tsthi, *negated_tstsi): Unmacroize. + (*reversed_tsthi, *reversed_tstsi): Add a scratch for simplicity. + (cmpqi, cmphi, cmpsi): Prepend asterisk, fuse tst[qhs]i here. + (bCC): Remove. + (cbranchqi4, cbranchhi4, cbranchsi4): New. + (tst -> sbrc/sbrs peephole2, cpse peephole): Wrap RHS with COMPARE. + + * config/bfin/bfin.md (cmpbi, cmpsi, bCC, sCC): Delete. + (cbranchsi4, cstorebi4, cstoresi4): New. + (movbisi): This insn is duplicate, split it to zero_extend. + * config/bfin/bfin.c (bfin_compare_op0, bfin_compare_op1): Delete + (bfin_gen_compare): Do not use them. Emit VOIDmode SET, not BImode. + (bfin_optimize_loop): Use cbranch expander. + * config/bfin/bfin.h (bfin_compare_op0, bfin_compare_op1): Delete. + * config/bfin/predicates.md (bfin_cbranch_operator): Rename to... + (bfin_bimode_comparison_operator): ... this. + (bfin_direct_comparison_operator): New. + + * config/cris/cris.c (cris_normal_notice_update_cc): Look + inside (compare FOO (const_int 0)). + (cris_rtx_costs): Handle ZERO_EXTRACT. + * config/cris/cris.md (tstdi, tst, cmpdi): Delete. + (*tstdi_non_v32): Fold in *cmpdi_non_v32. + (*tstdi_v32): Delete. + (*cmpdi_non_v32): Add M alternative for operand 1. + (cmpsi, cmp): Make private. + (*tstsi, *tst_cmp, *tst_non_cmp, *btst): Wrap + LHS with COMPARE. + (cbranch4, cbranchdi4, cstore4): New. + + * config/crx/crx.md (cstore4, cbranchcc4): New. + (cmp, bCOND_internal, b, s): Delete. + (cbranch4, sCOND_internal): Use ordered_comparison_operator. + (cc_reg_operand): New. + (any_cond): Delete. + * config/crx/crx.c (crx_compare_op0, crx_compare_op1, + crx_expand_compare, crx_expand_branch, crx_expand_scond): Delete. + * config/crx/crx.h (crx_compare_op0, crx_compare_op1): Delete. + * config/crx/crx-protos.h (crx_expand_compare, crx_expand_branch, + crx_expand_scond): Delete. + + * config/fr30/fr30.md (cmp, bCC): Delete. + (cbranchsi4): New. + * config/fr30/fr30.c (fr30_compare_op0, fr30_compare_op1): Delete + * config/fr30/fr30.h (fr30_compare_op0, fr30_compare_op1): Delete. + + * config/frv/frv.md (cbranchsi4, cbranchsf4, cbranchdf4, + cstoresi4, cstoresf4, cstoredf4): New. + (cmpdi, cmpsi, cmpsf, cmpdf, bCC, sCC): Remove. + * config/frv/frv-protos.h (frv_emit_cbranch, frv_emit_scc): + Receive the entire operands array. + * config/frv/frv.h (frv_compare_op0, + frv_compare_op1): Delete. + * config/frv/frv.c (frv_compare_op0, + frv_compare_op1): Delete. + * config/frv/frv-protos.h (frv_emit_cbranch, frv_emit_scc): + Get test/op0/op1 from the operands array. + (frv_emit_cond_move): Get test/op0/op1 from the test_rtx. + + * config/h8300/h8300-protos.h (h8300_expand_branch): Accept operands. + (h8300_expand_store): New. + * config/h8300/h8300.c (h8300_rtx_costs): Handle (compare FOO + (const_int 0)). + (h8300_expand_branch): Emit compare here. Adjust for new arguments. + (h8300_expand_store): New. + * config/h8300/h8300.md (btst combine patterns): Wrap with COMPARE + or do not try to produce (set (cc0) REG). + (peepholes): Wrap arguments with COMPARE. Add a peephole to + change a compare into a move to a scratch register. Disable some + peepholes when comparing with zero. + (tstsi, tsthi, tstsi, cmpqi): Make private. + (cmphi): Delete. + (bCC, sCC): Delete. + (cbranchqi4, cbranchhi4, cbranchsi4, cstoreqi4, cstorehi4, + cstoresi4): New. + + * config/i386/i386.c (ix86_expand_int_movcc, ix86_expand_int_addcc, + ix86_expand_fp_movcc): Set ix86_compare_op0 and ix86_compare_op1. + (ix86_emit_i387_log1p): Use gen_cbranchxf4. + (ix86_emit_i387_log1p): Use cbranchxf2. + (ix86_expand_setcc): Return void. + * config/i386/i386-protos.h (ix86_expand_setcc): Return void. + * config/i386/i386.md (cmpti, cmpdi, cmpsi, cmphi, cmpqi, cmpxf, + cmp, cmpcc): Remove. + (cbranchti4, cbranchdi4, cbranchsi4, cbranchhi4, cbranchqi4, cbranchxf4, + cbranch4, cbranchcc4, cstoredi4, cstoresi4, cstorehi4, + cstoreqi4, cstorexf4, cstore4, cstorecc): New. + (sCC and bCC expanders): Remove. + (stack_protect_test): Use cbranchcc4. + + * config/ia64/ia64-protos.h (ia64_compare_op0, ia64_compare_op1): + Delete. + (ia64_expand_compare): Accept three rtx by reference and return void. + * config/ia64/ia64.c (ia64_compare_op0, ia64_compare_op1): Delete. + (ia64_expand_compare): Replace op0/op1 with *op0/*op1. Get code + from *expr. Update *expr with the BImode comparison to do. + * config/ia64/ia64.md (cmpbi, cmpsi, cmpdi, cmpsf, cmpdf, cmpxf, + cmptf, bCC, sCC, conditional_trap): Delete. + (cbranchbi4, cbranchsi4, cbranchdi4, cbranchsf4, cbranchdf4, + cbranchxf4, cbranchtf4, cstorebi4, cstoresi4, cstoredi4, cstoresf4, + cstoredf4, cstorexf4, cstoretf4, ctrapbi4, ctrapsi4, ctrapdi4, + ctrapsf4, ctrapdf4, ctrapxf4, ctraptf4): New. + * config/ia64/predicates.md (ia64_cbranch_operator): New. + + * config/iq2000/iq2000-protos.h (gen_conditional_branch): Change + type of last argument. + * config/iq2000/iq2000.c (branch_cmp, branch_type): Remove. + (gen_conditional_branch): Get code/cmp0/cmp1 from operands, + use machine mode argument instead of branch_type. Remove dead + code for floating-point comparisons. + * config/iq2000/iq2000.h (branch_cmp, branch_type): Remove. + * config/iq2000/iq2000.md (cmpsi, cmpdi, cmpsf, cmpdf, tstsi, + bCC): Remove. + (cbranchsi4, cstoresi4): New. + * config/iq2000/predicates.md (reg_or_const_operand): New. + + * config/m32c/m32c.md (cbranch splitter): Use match_op_dup. + * config/m32c/m32c.md (any_cond, gl_cond): Delete. + (b_op): Rewrite to... + (bcc_op): ... this, using match_operator. + (s_op): Rewrite to... + (scc_op): ... this, using match_operator. + (s_24_op): Rewrite to... + (scc_op_24): ... this, using match_operator. + (s_): Rewrite to... + (cstore4): ... this, using match_operator. + (s__24): Rewrite to... + (cstore4_24): ... this, using match_operator. + * config/m32c/m32c-protos.h (m32c_cmp_flg_0, m32c_pend_compare, + m32c_unpend_compare, m32c_expand_scc): Delete. + * config/m32c/m32c.c (compare_op0, compare_op1, m32c_cmp_flg_0, + m32c_pend_compare, m32c_unpend_compare, m32c_expand_scc): Delete. + (m32c_expand_movcc): Change NE to EQ if necessary. + (m32c_init_libfuncs): Modify cstore optab instead of setcc_gen_code. + + * config/m32r/m32r-protos.h (gen_cond_store): New. + * config/m32r/m32r.c (m32r_compare_op0, m32r_compare_op1): Delete. + (gen_cond_store): New, from sCC patterns. + (m32r_expand_block_move): Use cbranchsi4. + * config/m32r/m32r.h (m32r_compare_op0, m32r_compare_op1): Delete. + * config/m32r/m32r.md (cmpsi, bCC, sCC): Delete. + (cbranchsi4, cstoresi4): New. + + * config/m68hc11/m68hc11.c (m68hc11_compare_op0, m68hc11_compare_op1): + Delete. + (m68hc11_rtx_costs_1, m68hc11_rtx_costs): Handle ZERO_EXTRACT. + (m68hc11_notice_update_cc): Look into a compare with 0. + * config/m68hc11/m68hc11.h (m68hc11_compare_op0, m68hc11_compare_op1): + Delete. + * config/m68hc11/m68hc11.md (tstsi, tsthi, tstqi, cmpsi, + cmphi, cmpqi, bCC): Delete. + (cbranchsi4, cbranchhi4, cbranchqi4): New. + (tstqi_1, tstqi_z_used, tstqi_1, bitcmpqi, bitcmpqi_z_used, + bitcmpqi_12, bitcmphi, various splits and peephole2s): Wrap cc0<-reg + sets with COMPARE. + + * config/m68k/predicates.md (m68k_cstore_comparison_operator, + const0_operand, const1_operand, m68k_subword_comparison_operand): New. + * config/m68k/constraints.md (H): New. + * config/m68k/m68k.md (tstdi): Remove define_expand, use name for + the define_insn below. + (tstsi, tsthi, tst, cmphi, cmpqi, cmp): Delete. + (*tstsi_internal_68020_cf, *tstsi_internal, *tsthi_internal, + *tstqi_internal, tst_6881, tst_cf, many unnamed + patterns): Wrap RHS with COMPARE. + (tst_68881, tst_cf): Use const0_operand. + (*cmpdi_internal): Name this pattern. + (cmpdi): Change to define_insn. + (cbranchdi4, cstoredi4, cbranchsi4, cstoresi4, cbranchhi4, cstorehi4, + cbranchqi4, cstoreqi4, cbranch4, cstore4): New. + (scc0_di, scc0_di_5200, scc_di): Use the ordered_comparison_operator + predicate. + (seq, sne, sgt, sgtu, slt, sltu, sge, sgeu, sle, sleu, sordered, + sunordered, suneq, sunge, sungt, sunle, sunlt, sltgt): Delete + (conditional_trap): Change to... + (ctrapdi4, ctrapsi4, ctraphi4, ctrapqi4): ... these. + (*conditional_trap): Use the ordered_comparison_operator and + const1_operand predicates. + * config/m68k/m68k.c (m68k_last_compare_had_fp_operands): Delete. + (m68k_expand_prologue): Use ctrapsi4 instead of cmpsi+conditional_trap. + (m68k_rtx_costs): Look for ZERO_EXTRACT in a COMPARE. + * config/m68k/m68k.h (m68k_last_compare_had_fp_operands): Delete. + + * config/mcore/mcore-protos.h (arch_compare_op0, arch_compare_op1, + mcore_modify_comparison, mcore_gen_compare_reg): Remove. + (mcore_gen_compare): New. + * config/mcore/mcore.c (arch_compare_op0, arch_compare_op1): Delete. + (mcore_modify_comparison, mcore_gen_compare_reg): Fold into... + (mcore_gen_compare): ... this. + * config/mcore/mcore.md (cmpsi, bCC, sCC): Remove. + (cbranchsi4, cstoresi4): New, using mcore_gen_compare. + (stack probe pattern): Use cbranchsi4. + + * config/mips/predicates.md (mips_cstore_operator): New. + * config/mips/mips-ps-3d.md (movv2sfcc): Do not use cmp_operands. + * config/mips/mips.md (any_cond): Delete. + (conditional_trap): Rename to ctrap4. Adjust predicates, + always succeed. + (fixuns_truncdfsi2, fixuns_truncdfdi2, fixuns_truncsfsi2, + fixuns_truncsfdi2): Use cbranch patterns. + (cmp, cmp): Delete. + (b): Change to cbranch4 and cbranch4. + Adjust call to mips_expand_conditional_branch. + (seq, sne, slt, sle, sgt, sge): Change to cstore4. + * config/mips/mips-protos.h (mips_expand_conditional_branch, + mips_expand_scc, mips_expand_conditional_trap): Adjust prototypes. + * config/mips/mips.c (cmp_operands): Delete. + (mips_emit_compare): Get comparison operands from *op0/*op1. + (mips_expand_scc): Get code/op0/op1/target from operands. Assert + that it succeeds. Use op0/op1 instead of cmp_operands. + (mips_expand_conditional_branch, mips_expand_conditional_move, + mips_expand_conditional_trap): Likewise. + (mips_block_move_loop): Use cbranch patterns. + * config/mips/mips.h (cmp_operands): Delete. + + * config/mmix/mmix.c (mmix_valid_comparison): Delete. + (mmix_gen_compare_reg): Just return a register in the right CC mode. + * config/mmix/mmix.h (mmix_compare_op0, mmix_compare_op1): New. + * config/mmix/mmix.md (cmpdi, cmpdf): Remove. + (*cmpcc_folded): Rename to... + (*cmpdi_folded): this. + (*cmpcc): Rename to... + (*cmps): ... this. + (movdfcc, movdicc): Adjust for new semantics of mmix_gen_compare_reg. + (bCC): Remove. + (cbranchdi4): New. + (cbranchdf4): New. Handle invalid comparisons here. + * config/mmix/predicates.md (float_comparison_operator): New. + + * config/mn10300/mn10300.c (mn10300_rtx_costs): Consider 0 and + zero_extract to be cheap in (compare (zero_extract) (const_int 0). + * config/mn10300/mn10300.md (tst): Delete. + (*tst_extqisi_am33, *tst_extqisi, *tst_exthisi_am33, *tst_exthisi): + Name these patterns and wrap RHS in a compare. + (*cmpsi): Make this pattern private. Include tst. + (*cmpsf): Make this pattern private. + (and and zero_extract cc0 set): Wrap RHS in a COMPARE. + (compare with zero peepholes): Likewise. + (bCC): Remove. + (cbranchsi4, cbranchsf4): New. + (casesi): Use cbranchsi4. + + * config/pa/pa.c (hppa_compare_op0, hppa_compare_op1, + hppa_branch_type): Delete. + (return_addr_rtx): Use cbranchsi4. + (emit_bcond_fp): Accept all operands. Replace CODE with NE. + Emit CCFPmode comparison here. + (gen_cmp_fp): Delete, now part of emit_bcond_fp. + * config/pa/pa.h (enum cmp_type, hppa_compare_op0, hppa_compare_op1, + hppa_branch_type): Delete. + * config/pa/pa.md (cmpdi, cmpsi, cmpsf, cmpdf, sCC, bCC): Delete. + (movsicc, movdicc): Remove references to hppa_compare_op0, + hppa_compare_op1 and compare_from_rtx. + (cbranchdi4, cbranchsi4, cbranchsf4, cbranchdf4, cstoresi4): New. + (casesi): Use cbranchsi4. + + * config/pdp11/pdp11-protos.h (output_jump): Change prototype. + * config/pdp11/pdp11.c (output_jump): Embed opcodes here. + * config/pdp11/pdp11.md (register_or_const0_operand): New. + (cmpdf, cmphi, cmpqi): Make private. Add tst alternatives. + (cmpsi, tstsi, tstdf, tsthi, tstqi): Delete. + (bCC): Delete. + (cbranchdf4, cbranchhi4, cbranchqi4): New. + (*branch, *branch_inverted): New. + + * config/picochip/picochip.md (cbranchhi4): Use + ordered_comparison_operator. + (cmphi, bCC): Remove. + + * config/rs6000/predicates.md (rs6000_cbranch_operator): New. + (trap_comparison_operator): Delete. + * config/rs6000/rs6000-protos.h (rs6000_emit_sCOND, + rs6000_emit_cbranch): Accept mode and operands. + * config/rs6000/rs6000.c (rs6000_compare_op0, rs6000_compare_op1, + rs6000_compare_fp_p): Delete. + (rs6000_generate_compare): Accept mode and comparison. Extract code + and op0/op1 from there. Replace references to rs6000_compare_op0 + and rs6000_compare_op1. + (rs6000_emit_sCOND): Adjust call to rs6000_generate_compare and + extract result from passed operands. + (rs6000_emit_cbranch): Adjust call to rs6000_generate_compare and + extract loc from passed operands. + (rs6000_emit_cmove): Likewise. + * config/rs6000/rs6000.h (rs6000_compare_op0, rs6000_compare_op1, + rs6000_compare_fp_p): Delete. + * config/rs6000/rs6000.md (cmp, cmp, bCC, sCC): Delete. + (cbranch4, cbranch4): New. + (cstore4): New. Consolidate here all choices about when to use + portable or specialized sCC sequences. + (stack_protect_test): Use cbranchsi4. + (conditional_trap): Replace with ctrap4. + (conditional trap insn): Replace trap_comparison_operator with + ordered_comparison_operator. + + * config/s390/s390.c (s390_compare_op0, s390_compare_op1): Delete. + (s390_emit_prologue): Use ctrap. + * config/s390/s390.h (s390_compare_op0, s390_compare_op1): Delete. + * config/s390/predicates.md (s390_eqne_operator, s390_scond_operator): + New predicates replacing... + * config/s390/s390.md (COMPARE, SCOND): ... these iterators. + (cmp, cmp, cmpcc): Delete. + (trunc patterns): Use emit_cmp_and_jump_insns instead of cmp/branch. + (addcc): Do not use s390_compare_op0/op1. + (s): Change to... + (cstore4): ... this. Do not use s390_compare_op0/op1. + (seq): Change to... + (cstorecc4): ... this. Handle EQ or NE equally. + (*sne): Un-privatize for use in cstorecc4. + (b): Change to... + (cbranch4, cbranch4, cbranchcc4): ... these. + (conditional_trap): Replace with... + (ctrap4, ctrap4): ... these. + (stack_protect): Use cbranchcc4. + + * config/score/score-conv.h (cmp_op0, cmp_op1): Delete. + * config/score/score-protos.h (score_gen_cmp): Delete. + * config/score/score.c (cmp_op0, cmp_op1, score_gen_cmp): Delete. + (score_block_move-loop): Use cbranchsi4. + * config/score/score.md (cbranchsi4): New. + (cmpsi, bCC): Delete. + * config/score/score3.c (cmp_op0, cmp_op1, score3_gen_cmp): Delete. + (score3_movsicc): Use ops[1] operands instead of cmp_op0/cmp_op1. + * config/score/score7.c (cmp_op0, cmp_op1, score7_gen_cmp): Delete. + (score7_movsicc): Use ops[1] operands instead of cmp_op0/cmp_op1. + * config/score/score3.h (score3_gen_cmp): Delete. + * config/score/score7.h (score7_gen_cmp): Delete. + + * config/sh/sh-protos.h (prepare_scc_operands): Rename to... + (sh_emit_scc_to_t): ... this. Return void. + (from_compare): Rename to... + (sh_emit_compare_and_branch): ... this. + (sh_emit_compare_and_set): New. + (sh_expand_t_scc): Accept operands. + * config/sh/predicates.md (sh_float_comparison_operator): New. + * config/sh/sh.c (sh_compare_op0, sh_compare_op1): Delete. + (prepare_scc_operands): Rename to... + (sh_emit_scc_to_t): ... this. Return void. Get op0/op1 from arguments. + (sh_emit_cheap_store_flag): New. + (sh_emit_set_t_insn): New. + (from_compare): Rename to... + (sh_emit_compare_and_branch): ... this. Accept mode. Rewrite + handling of TARGET_SH2E floating point to avoid recursive call. + Generate branch here. + (sh_emit_compare_and_set): New. + (sh_expand_t_scc): Get op0/op1 from arguments. + (sh_emit_cheap_store_flag): New. + * config/sh/sh.md (cbranchdi4, cbranchsi4): Include -mno-cbranchdi + cases. + (cbranchdi4_i): Use an "I08" constraint instead of an "i" constraint. + (cmpsi, cmpdi, cmpsf, cmpdf): Delete. + (movsicc, movdicc): Do nothing when it recreated operands from + sh_compare_*. Use sh_emit_cheap_store_flag. Adjust call to + prepare_scc_operands (now sh_emit_scc_to_t). + (udivdi3): Use cstoresi4. + (beq_media, bne_media, bge_media, bgtu_media, bgeu_media, beq, + bne, bgt, blt, ble, bge, bgtu, bltu, bgeu, bleu, bunordered): + Delete. + (cbranchint4_media, cbranchfp4_media): New. + (casesi): Use cbranchdi4. + (seq, slt, sle, sgt, sge, sgtu, sltu, sgeu, sne, sleu, sunordered): + Delete. + (cstore4_media, cstoresi4, cstoredi4, cstoresf4, cstoredf4): New. + (movnegt): Remove second operand. + (cbranchsf4, cbranchdf4): New. + (stack_protect): Use cbranchdi4/cbranchsi4. + + * config/sparc/sparc.c (sparc_compare_op0, sparc_compare_op1): Delete. + (gen_compare_reg): Accept comparison, extract part of it to... + (gen_compare_reg_1): ... this. + (gen_compare_operator): Delete. + (gen_v9_scc): Accept separate destination, comparison code and arms. + Do not use sparc_compare_op0/sparc_compare_op1. + (emit_scc_insn, emit_conditional_branch_insn): New. + (emit_v9_brxx): Make static. Remove useless assertion. + (sparc_emit_float_lib_cmp): Return RTL instead of calling emit_cmp_insn. + (sparc_expand_compare_and_swap_12): Use gen_compare_reg_1+cbranchcc4. + * config/sparc/sparc-protos.h (gen_compare_reg, + sparc_emit_float_lib_cmp): Adjust prototype. + (emit_scc_insn, emit_conditional_branch_insn): New. + (gen_v9_scc, emit_v9_brxx_insn, gen_compare_operator): Delete. + * config/sparc/sparc.h (sparc_compare_op0, sparc_compare_op1): Delete. + * config/sparc/sparc.md (P, I, F, V32, V32I, V64, V64I): Move all + iterators to the top. + (cmpsi, cmpdi, cmpsf, cmpdf, cmptf, seqsi_special_extend, + snesi_special_extend, sCC, bCC, seqdi_special_trunc, + snedi_special_trunc): Delete. + (seqdi_special, snedi_special): Use expansion of seqdi_special_trunc + and snedi_special_trunc. + (cstoresi4, cstoredi4, cstore4, cbranchcc4, cbranchsi4, + cbranchdi4, cbranch4): New. + (movcc, movcc): Handle sparc_emit_float_lib_cmp + here. Use gen_compare_reg instead of gen_compare_operator. + (conditional_trap): Replace with... + (ctrapsi4, ctrapdi4): ... this. + (stack_protect_test): Use cbranchcc4. + + * config/spu/spu-protos.h (spu_emit_branch_or_set): Change second + argument to rtx. + * config/spu/spu.c (spu_compare_op0, spu_compare_op1): Remove. + (spu_emit_branch_or_set): Get code/op0/op1 from second argument. + Change spu_compare_op0/op1 to op0/op1 throughout. Get target + from operands[0] or operands[3] depending on is_set. + * config/spu/spu.h (spu_compare_op0, spu_compare_op1): Remove. + * config/spu/spu.md (cmp, cmp, cmp, + cmpdf, bCC), sCC: Remove. + (cbranch4, cbranch, cbranch4, + cbranchdf4, cstore4, cstore, cstore4, + cstoredf4): New. + (movcc): Accept ordered_comparison_operator, adjust call to + spu_emit_branch_or_set. + + * config/stormy16/stormy16-protos.h (xstormy16_emit_cbranch): + Add two arguments. + * config/stormy16/stormy16.h (xstormy16_compare_op0, + xstormy16_compare_op1): Delete. + * config/stormy16/stormy16.c (xstormy16_compare_op0, + xstormy16_compare_op1): Delete. + (xstormy16_emit_cbranch): Get op0/op1 from the new arguments. + Adjust calls. + * config/stormy16/stormy16.md (cbranchsi4, cbranchhi4): New. + (cmphi, cmpsi, bCC): Remove. + + * config/v850/v850.md (tstsi, cmpsi): Fold into... + (*cmpsi): ... this one. + (cbranchsi4, cstoresi4): New. + (bCC expanders): Delete. + (sCC insns): Fold into... + (*setcc): ... this one. + (casesi): Do not use gen_cmpsi and gen_bgtu. + (various splits): Wrap "naked" RHS of a cc0 set with COMPARE. + (movsicc): Simplify. + * config/v850/v850.c (v850_rtx_costs): Handle ZERO_EXTRACT in COMPARE. + + * config/vax/vax-protos.h (cond_name): New. + (vax_output_conditional_branch): Remove. + * config/vax/vax.c (cond_name): New. + (vax_output_conditional_branch): Remove. + * config/vax/vax.h (PRINT_OPERAND): Dispatch %c to cond_name. + * config/vax/vax.md (tst, tst): Remove. + (cmp, cmp): Privatize. Add constraints for tst. + (bit): Wrap source with (compare). + (b and following unnamed pattern): Rename to *branch and + *branch_reversed. Change macroization to match_operator. + (cbranch4, cbranch4): New. + + * config/xtensa/predicates.md (xtensa_cstoresi_operator): New. + * config/xtensa/xtensa-protos.h (xtensa_expand_conditional_branch): + Change last argument to machine_mode. + (xtensa_expand_scc): Add machine_mode argument. + * config/xtensa/xtensa.c (branch_cmp, branch_type): Remove. + (gen_conditional_move, xtensa_expand_conditional_branch, + xtensa_expand_scc, xtensa_expand_conditional_move): Use mode + instead of branch_type, fetch cmp0/cmp1/test_code from operands[]. + Adjust operand numbers. + * config/xtensa/xtensa.h (enum cmp_type, branch_cmp, branch_type): + Delete. + * config/xtensa/xtensa.md (any_cond, any_scc): Delete. + (cmpsi, cmpsf, b, s): Delete. + (cbranchsi4, cbranchsf4, cstoresi4, cstoresf4): New. + +2009-05-12 Paolo Bonzini + * optabs.c (prepare_cmp_insn): Temporarily disable test that causes spurious differences between trunk and cond-optab branch. diff --git a/gcc/combine.c b/gcc/combine.c index 0c06b2d102c..7cdf396a66c 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -4906,24 +4906,6 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) return gen_lowpart (mode, XEXP (x, 0)); break; -#ifdef HAVE_cc0 - case COMPARE: - /* Convert (compare FOO (const_int 0)) to FOO unless we aren't - using cc0, in which case we want to leave it as a COMPARE - so we can distinguish it from a register-register-copy. */ - if (XEXP (x, 1) == const0_rtx) - return XEXP (x, 0); - - /* x - 0 is the same as x unless x's mode has signed zeros and - allows rounding towards -infinity. Under those conditions, - 0 - 0 is -0. */ - if (!(HONOR_SIGNED_ZEROS (GET_MODE (XEXP (x, 0))) - && HONOR_SIGN_DEPENDENT_ROUNDING (GET_MODE (XEXP (x, 0)))) - && XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 0)))) - return XEXP (x, 0); - break; -#endif - case CONST: /* (const (const X)) can become (const X). Do it this way rather than returning the inner CONST since CONST can be shared with a @@ -5758,17 +5740,6 @@ simplify_set (rtx x) if (other_changed) undobuf.other_insn = other_insn; -#ifdef HAVE_cc0 - /* If we are now comparing against zero, change our source if - needed. If we do not use cc0, we always have a COMPARE. */ - if (op1 == const0_rtx && dest == cc0_rtx) - { - SUBST (SET_SRC (x), op0); - src = op0; - } - else -#endif - /* Otherwise, if we didn't previously have a COMPARE in the correct mode, we need one. */ if (GET_CODE (src) != COMPARE || GET_MODE (src) != compare_mode) diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h index 66c68aebc91..7a12d498246 100644 --- a/gcc/config/alpha/alpha-protos.h +++ b/gcc/config/alpha/alpha-protos.h @@ -88,8 +88,8 @@ extern int check_float_value (enum machine_mode, REAL_VALUE_TYPE *, int); #endif #ifdef RTX_CODE -extern rtx alpha_emit_conditional_branch (enum rtx_code); -extern rtx alpha_emit_setcc (enum rtx_code); +extern void alpha_emit_conditional_branch (rtx[], enum machine_mode); +extern bool alpha_emit_setcc (rtx[], enum machine_mode); extern int alpha_split_conditional_move (enum rtx_code, rtx, rtx, rtx, rtx); extern void alpha_emit_xfloating_arith (enum rtx_code, rtx[]); extern void alpha_emit_xfloating_cvt (enum rtx_code, rtx[]); diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index bb6542a37f9..512599d0982 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -81,11 +81,6 @@ enum alpha_fp_rounding_mode alpha_fprm; enum alpha_fp_trap_mode alpha_fptm; -/* Save information from a "cmpxx" operation until the branch or scc is - emitted. */ - -struct alpha_compare alpha_compare; - /* Nonzero if inside of a function, because the Alpha asm can't handle .files inside of functions. */ @@ -2424,19 +2419,20 @@ alpha_emit_floatuns (rtx operands[2]) /* Generate the comparison for a conditional branch. */ -rtx -alpha_emit_conditional_branch (enum rtx_code code) +void +alpha_emit_conditional_branch (rtx operands[], enum machine_mode cmp_mode) { enum rtx_code cmp_code, branch_code; - enum machine_mode cmp_mode, branch_mode = VOIDmode; - rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1; + enum machine_mode branch_mode = VOIDmode; + enum rtx_code code = GET_CODE (operands[0]); + rtx op0 = operands[1], op1 = operands[2]; rtx tem; - if (alpha_compare.fp_p && GET_MODE (op0) == TFmode) + if (cmp_mode == TFmode) { op0 = alpha_emit_xfloating_compare (&code, op0, op1); op1 = const0_rtx; - alpha_compare.fp_p = 0; + cmp_mode = DImode; } /* The general case: fold the comparison code to the types of compares @@ -2457,7 +2453,7 @@ alpha_emit_conditional_branch (enum rtx_code code) case GE: case GT: case GEU: case GTU: /* For FP, we swap them, for INT, we reverse them. */ - if (alpha_compare.fp_p) + if (cmp_mode == DFmode) { cmp_code = swap_condition (code); branch_code = NE; @@ -2474,9 +2470,8 @@ alpha_emit_conditional_branch (enum rtx_code code) gcc_unreachable (); } - if (alpha_compare.fp_p) + if (cmp_mode == DFmode) { - cmp_mode = DFmode; if (flag_unsafe_math_optimizations && cmp_code != UNORDERED) { /* When we are not as concerned about non-finite values, and we @@ -2501,8 +2496,6 @@ alpha_emit_conditional_branch (enum rtx_code code) } else { - cmp_mode = DImode; - /* The following optimizations are only for signed compares. */ if (code != LEU && code != LTU && code != GEU && code != GTU) { @@ -2544,36 +2537,38 @@ alpha_emit_conditional_branch (enum rtx_code code) emit_move_insn (tem, gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1)); } - /* Zero the operands. */ - memset (&alpha_compare, 0, sizeof (alpha_compare)); - - /* Return the branch comparison. */ - return gen_rtx_fmt_ee (branch_code, branch_mode, tem, CONST0_RTX (cmp_mode)); + /* Emit the branch instruction. */ + tem = gen_rtx_SET (VOIDmode, pc_rtx, + gen_rtx_IF_THEN_ELSE (VOIDmode, + gen_rtx_fmt_ee (branch_code, + branch_mode, tem, + CONST0_RTX (cmp_mode)), + gen_rtx_LABEL_REF (VOIDmode, + operands[3]), + pc_rtx)); + emit_jump_insn (tem); } /* Certain simplifications can be done to make invalid setcc operations valid. Return the final comparison, or NULL if we can't work. */ -rtx -alpha_emit_setcc (enum rtx_code code) +bool +alpha_emit_setcc (rtx operands[], enum machine_mode cmp_mode) { enum rtx_code cmp_code; - rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1; - int fp_p = alpha_compare.fp_p; + enum rtx_code code = GET_CODE (operands[1]); + rtx op0 = operands[2], op1 = operands[3]; rtx tmp; - /* Zero the operands. */ - memset (&alpha_compare, 0, sizeof (alpha_compare)); - - if (fp_p && GET_MODE (op0) == TFmode) + if (cmp_mode == TFmode) { op0 = alpha_emit_xfloating_compare (&code, op0, op1); op1 = const0_rtx; - fp_p = 0; + cmp_mode = DImode; } - if (fp_p && !TARGET_FIX) - return NULL_RTX; + if (cmp_mode == DFmode && !TARGET_FIX) + return 0; /* The general case: fold the comparison code to the types of compares that we have, choosing the branch as necessary. */ @@ -2584,12 +2579,12 @@ alpha_emit_setcc (enum rtx_code code) case EQ: case LE: case LT: case LEU: case LTU: case UNORDERED: /* We have these compares. */ - if (fp_p) + if (cmp_mode == DFmode) cmp_code = code, code = NE; break; case NE: - if (!fp_p && op1 == const0_rtx) + if (cmp_mode == DImode && op1 == const0_rtx) break; /* FALLTHRU */ @@ -2601,10 +2596,10 @@ alpha_emit_setcc (enum rtx_code code) case GE: case GT: case GEU: case GTU: /* These normally need swapping, but for integer zero we have special patterns that recognize swapped operands. */ - if (!fp_p && op1 == const0_rtx) + if (cmp_mode == DImode && op1 == const0_rtx) break; code = swap_condition (code); - if (fp_p) + if (cmp_mode == DFmode) cmp_code = code, code = NE; tmp = op0, op0 = op1, op1 = tmp; break; @@ -2613,7 +2608,7 @@ alpha_emit_setcc (enum rtx_code code) gcc_unreachable (); } - if (!fp_p) + if (cmp_mode == DImode) { if (!register_operand (op0, DImode)) op0 = force_reg (DImode, op0); @@ -2624,18 +2619,18 @@ alpha_emit_setcc (enum rtx_code code) /* Emit an initial compare instruction, if necessary. */ if (cmp_code != UNKNOWN) { - enum machine_mode mode = fp_p ? DFmode : DImode; - - tmp = gen_reg_rtx (mode); + tmp = gen_reg_rtx (cmp_mode); emit_insn (gen_rtx_SET (VOIDmode, tmp, - gen_rtx_fmt_ee (cmp_code, mode, op0, op1))); + gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1))); - op0 = fp_p ? gen_lowpart (DImode, tmp) : tmp; + op0 = cmp_mode == DImode ? gen_lowpart (DImode, tmp) : tmp; op1 = const0_rtx; } - /* Return the setcc comparison. */ - return gen_rtx_fmt_ee (code, DImode, op0, op1); + /* Emit the setcc instruction. */ + emit_insn (gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_fmt_ee (code, DImode, op0, op1))); + return true; } @@ -2651,20 +2646,17 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode) { enum rtx_code code = GET_CODE (cmp); enum rtx_code cmov_code = NE; - rtx op0 = alpha_compare.op0; - rtx op1 = alpha_compare.op1; - int fp_p = alpha_compare.fp_p; + rtx op0 = XEXP (cmp, 0); + rtx op1 = XEXP (cmp, 1); enum machine_mode cmp_mode = (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0)); - enum machine_mode cmp_op_mode = fp_p ? DFmode : DImode; enum machine_mode cmov_mode = VOIDmode; int local_fast_math = flag_unsafe_math_optimizations; rtx tem; - /* Zero the operands. */ - memset (&alpha_compare, 0, sizeof (alpha_compare)); + gcc_assert (cmp_mode == DFmode || cmp_mode == DImode); - if (fp_p != FLOAT_MODE_P (mode)) + if (FLOAT_MODE_P (cmp_mode) != FLOAT_MODE_P (mode)) { enum rtx_code cmp_code; @@ -2691,7 +2683,7 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode) case GE: case GT: case GEU: case GTU: /* These normally need swapping, but for integer zero we have special patterns that recognize swapped operands. */ - if (!fp_p && op1 == const0_rtx) + if (cmp_mode == DImode && op1 == const0_rtx) cmp_code = code, code = NE; else { @@ -2705,22 +2697,21 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode) gcc_unreachable (); } - tem = gen_reg_rtx (cmp_op_mode); + tem = gen_reg_rtx (cmp_mode); emit_insn (gen_rtx_SET (VOIDmode, tem, - gen_rtx_fmt_ee (cmp_code, cmp_op_mode, + gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1))); - cmp_mode = cmp_op_mode = fp_p ? DImode : DFmode; - op0 = gen_lowpart (cmp_op_mode, tem); - op1 = CONST0_RTX (cmp_op_mode); - fp_p = !fp_p; + cmp_mode = cmp_mode == DImode ? DFmode : DImode; + op0 = gen_lowpart (cmp_mode, tem); + op1 = CONST0_RTX (cmp_mode); local_fast_math = 1; } /* We may be able to use a conditional move directly. This avoids emitting spurious compares. */ if (signed_comparison_operator (cmp, VOIDmode) - && (!fp_p || local_fast_math) + && (cmp_mode == DImode || local_fast_math) && (op0 == CONST0_RTX (cmp_mode) || op1 == CONST0_RTX (cmp_mode))) return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); @@ -2757,7 +2748,7 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode) gcc_unreachable (); } - if (!fp_p) + if (cmp_mode == DImode) { if (!reg_or_0_operand (op0, DImode)) op0 = force_reg (DImode, op0); @@ -2768,12 +2759,12 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode) /* ??? We mark the branch mode to be CCmode to prevent the compare and cmov from being combined, since the compare insn follows IEEE rules that the cmov does not. */ - if (fp_p && !local_fast_math) + if (cmp_mode == DFmode && !local_fast_math) cmov_mode = CCmode; - tem = gen_reg_rtx (cmp_op_mode); - emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_op_mode, op0, op1)); - return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_op_mode)); + tem = gen_reg_rtx (cmp_mode); + emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_mode, op0, op1)); + return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_mode)); } /* Simplify a conditional move of two constants into a setcc with diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index f33e8e63854..ed9bd747f39 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -803,24 +803,6 @@ extern int alpha_memory_latency; #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ function_arg((CUM), (MODE), (TYPE), (NAMED)) -/* Try to output insns to set TARGET equal to the constant C if it can be - done in less than N insns. Do all computations in MODE. Returns the place - where the output has been placed if it can be done and the insns have been - emitted. If it would take more than N insns, zero is returned and no - insns and emitted. */ - -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. Note that we can't use "rtx" here - since it hasn't been defined! */ - -struct alpha_compare -{ - struct rtx_def *op0, *op1; - int fp_p; -}; - -extern struct alpha_compare alpha_compare; - /* Make (or fake) .linkage entry for function call. IS_LOCAL is 0 if name is used in call, 1 if name is used in definition. */ diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 543ed533080..e6a05780bba 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -3963,206 +3963,53 @@ ;; These are the main define_expand's used to make conditional branches ;; and compares. -(define_expand "cmpdf" - [(set (cc0) (compare (match_operand:DF 0 "reg_or_0_operand" "") - (match_operand:DF 1 "reg_or_0_operand" "")))] +(define_expand "cbranchdf4" + [(use (match_operator 0 "alpha_cbranch_operator" + [(match_operand:DF 1 "reg_or_0_operand" "") + (match_operand:DF 2 "reg_or_0_operand" "")])) + (use (match_operand 3 ""))] "TARGET_FP" -{ - alpha_compare.op0 = operands[0]; - alpha_compare.op1 = operands[1]; - alpha_compare.fp_p = 1; - DONE; -}) + { alpha_emit_conditional_branch (operands, DFmode); DONE; }) -(define_expand "cmptf" - [(set (cc0) (compare (match_operand:TF 0 "general_operand" "") - (match_operand:TF 1 "general_operand" "")))] +(define_expand "cbranchtf4" + [(use (match_operator 0 "alpha_cbranch_operator" + [(match_operand:TF 1 "general_operand") + (match_operand:TF 2 "general_operand")])) + (use (match_operand 3 ""))] "TARGET_HAS_XFLOATING_LIBS" -{ - alpha_compare.op0 = operands[0]; - alpha_compare.op1 = operands[1]; - alpha_compare.fp_p = 1; - DONE; -}) - -(define_expand "cmpdi" - [(set (cc0) (compare (match_operand:DI 0 "some_operand" "") - (match_operand:DI 1 "some_operand" "")))] - "" -{ - alpha_compare.op0 = operands[0]; - alpha_compare.op1 = operands[1]; - alpha_compare.fp_p = 0; - DONE; -}) - -(define_expand "beq" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (EQ); }") - -(define_expand "bne" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (NE); }") - -(define_expand "blt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (LT); }") + { alpha_emit_conditional_branch (operands, TFmode); DONE; }) -(define_expand "ble" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (LE); }") - -(define_expand "bgt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] +(define_expand "cbranchdi4" + [(use (match_operator 0 "alpha_cbranch_operator" + [(match_operand:DI 1 "some_operand") + (match_operand:DI 2 "some_operand")])) + (use (match_operand 3 ""))] "" - "{ operands[1] = alpha_emit_conditional_branch (GT); }") + { alpha_emit_conditional_branch (operands, DImode); DONE; }) -(define_expand "bge" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (GE); }") - -(define_expand "bltu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (LTU); }") - -(define_expand "bleu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (LEU); }") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (GTU); }") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (GEU); }") - -(define_expand "bunordered" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (UNORDERED); }") - -(define_expand "bordered" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (ORDERED); }") - -(define_expand "seq" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (EQ)) == NULL_RTX) FAIL; }") - -(define_expand "sne" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (NE)) == NULL_RTX) FAIL; }") - -(define_expand "slt" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (LT)) == NULL_RTX) FAIL; }") - -(define_expand "sle" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (LE)) == NULL_RTX) FAIL; }") - -(define_expand "sgt" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (GT)) == NULL_RTX) FAIL; }") - -(define_expand "sge" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (GE)) == NULL_RTX) FAIL; }") - -(define_expand "sltu" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (LTU)) == NULL_RTX) FAIL; }") - -(define_expand "sleu" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (LEU)) == NULL_RTX) FAIL; }") - -(define_expand "sgtu" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (GTU)) == NULL_RTX) FAIL; }") - -(define_expand "sgeu" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (GEU)) == NULL_RTX) FAIL; }") +(define_expand "cstoredf4" + [(use (match_operator:DI 1 "alpha_cbranch_operator" + [(match_operand:DF 2 "reg_or_0_operand") + (match_operand:DF 3 "reg_or_0_operand")])) + (clobber (match_operand:DI 0 "register_operand"))] + "TARGET_FP" + { if (!alpha_emit_setcc (operands, DFmode)) FAIL; else DONE; }) -(define_expand "sunordered" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (UNORDERED)) == NULL_RTX) FAIL; }") +(define_expand "cstoretf4" + [(use (match_operator:DI 1 "alpha_cbranch_operator" + [(match_operand:TF 2 "general_operand") + (match_operand:TF 3 "general_operand")])) + (clobber (match_operand:DI 0 "register_operand"))] + "TARGET_HAS_XFLOATING_LIBS" + { if (!alpha_emit_setcc (operands, TFmode)) FAIL; else DONE; }) -(define_expand "sordered" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] +(define_expand "cstoredi4" + [(use (match_operator:DI 1 "alpha_cbranch_operator" + [(match_operand:DI 2 "some_operand") + (match_operand:DI 3 "some_operand")])) + (clobber (match_operand:DI 0 "register_operand"))] "" - "{ if ((operands[1] = alpha_emit_setcc (ORDERED)) == NULL_RTX) FAIL; }") + { if (!alpha_emit_setcc (operands, DImode)) FAIL; else DONE; }) ;; These are the main define_expand's used to make conditional moves. @@ -6766,7 +6613,7 @@ rtx loop_label = gen_label_rtx (); rtx want = gen_reg_rtx (Pmode); rtx tmp = gen_reg_rtx (Pmode); - rtx memref; + rtx memref, test; emit_insn (gen_subdi3 (want, stack_pointer_rtx, force_reg (Pmode, operands[1]))); @@ -6775,8 +6622,8 @@ if (!CONST_INT_P (operands[1])) { out_label = gen_label_rtx (); - emit_insn (gen_cmpdi (want, tmp)); - emit_jump_insn (gen_bgeu (out_label)); + test = gen_rtx_GEU (VOIDmode, want, tmp); + emit_jump_insn (gen_cbranchdi4 (test, want, tmp, out_label)); } emit_label (loop_label); @@ -6784,8 +6631,8 @@ MEM_VOLATILE_P (memref) = 1; emit_move_insn (memref, const0_rtx); emit_insn (gen_adddi3 (tmp, tmp, GEN_INT(-8192))); - emit_insn (gen_cmpdi (tmp, want)); - emit_jump_insn (gen_bgtu (loop_label)); + test = gen_rtx_GTU (VOIDmode, tmp, want); + emit_jump_insn (gen_cbranchdi4 (test, tmp, want, loop_label)); memref = gen_rtx_MEM (DImode, want); MEM_VOLATILE_P (memref) = 1; diff --git a/gcc/config/alpha/predicates.md b/gcc/config/alpha/predicates.md index 425134ac820..ec11eaa3d1f 100644 --- a/gcc/config/alpha/predicates.md +++ b/gcc/config/alpha/predicates.md @@ -543,6 +543,12 @@ (and (match_code "reg") (match_operand 0 "register_operand"))) +;; Return 1 if OP is a valid Alpha comparison operator for "cbranch" +;; instructions. +(define_predicate "alpha_cbranch_operator" + (ior (match_operand 0 "ordered_comparison_operator") + (match_code "ordered,unordered"))) + ;; Return 1 if OP is a valid Alpha comparison operator for "cmp" style ;; instructions. (define_predicate "alpha_comparison_operator" diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index 3f81f611f80..1f456b63cd7 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -49,10 +49,6 @@ int arc_cpu_type; cpu (or NULL). */ const char *arc_mangle_cpu; -/* Save the operands last given to a compare for use when we - generate a scc or bcc insn. */ -rtx arc_compare_op0, arc_compare_op1; - /* Name of text, data, and rodata sections used in varasm.c. */ const char *arc_text_section; const char *arc_data_section; @@ -729,21 +725,14 @@ proper_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) /* Misc. utilities. */ -/* X and Y are two things to compare using CODE. Emit the compare insn and - return the rtx for the cc reg in the proper mode. */ +/* X and Y are two things to compare using CODE. Return the rtx + for the cc reg in the proper mode. */ rtx gen_compare_reg (enum rtx_code code, rtx x, rtx y) { enum machine_mode mode = SELECT_CC_MODE (code, x, y); - rtx cc_reg; - - cc_reg = gen_rtx_REG (mode, 61); - - emit_insn (gen_rtx_SET (VOIDmode, cc_reg, - gen_rtx_COMPARE (mode, x, y))); - - return cc_reg; + return gen_rtx_REG (mode, 61); } /* Return 1 if VALUE, a const_double, will fit in a limm (4 byte number). diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h index db6829bc560..4153ad6f6b6 100644 --- a/gcc/config/arc/arc.h +++ b/gcc/config/arc/arc.h @@ -1067,11 +1067,6 @@ do { if ((LOG) != 0) fprintf (FILE, "\t.align %d\n", 1 << (LOG)); } while (0) /* ??? Not defined in tm.texi. */ #define SETJMP_VIA_SAVE_AREA -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. Note that we can't use "rtx" here - since it hasn't been defined! */ -extern struct rtx_def *arc_compare_op0, *arc_compare_op1; - /* ARC function types. */ enum arc_function_type { ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL, diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index b67984babbb..09e47daf1d1 100644 --- a/gcc/config/arc/arc.md +++ b/gcc/config/arc/arc.md @@ -585,29 +585,11 @@ " { enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg - = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), - 61); - - operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); + rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0), + XEXP (operands[1], 1)); + operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx); }") -;(define_expand "movdicc" -; [(set (match_operand:DI 0 "register_operand" "") -; (if_then_else:DI (match_operand 1 "comparison_operator" "") -; (match_operand:DI 2 "nonmemory_operand" "") -; (match_operand:DI 3 "register_operand" "")))] -; "0 /* ??? this would work better if we had cmpdi */" -; " -;{ -; enum rtx_code code = GET_CODE (operands[1]); -; rtx ccreg -; = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), -; 61); -; -; operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); -;}") - (define_expand "movsfcc" [(set (match_operand:SF 0 "register_operand" "") (if_then_else:SF (match_operand 1 "comparison_operator" "") @@ -617,29 +599,11 @@ " { enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg - = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), - 61); - - operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); + rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0), + XEXP (operands[1], 1)); + operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx); }") -;(define_expand "movdfcc" -; [(set (match_operand:DF 0 "register_operand" "") -; (if_then_else:DF (match_operand 1 "comparison_operator" "") -; (match_operand:DF 2 "nonmemory_operand" "") -; (match_operand:DF 3 "register_operand" "")))] -; "0 /* ??? can generate less efficient code if constants involved */" -; " -;{ -; enum rtx_code code = GET_CODE (operands[1]); -; rtx ccreg -; = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), -; 61); -; -; operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); -;}") - (define_insn "*movsicc_insn" [(set (match_operand:SI 0 "register_operand" "=r") (if_then_else:SI (match_operand 1 "comparison_operator" "") @@ -649,32 +613,6 @@ "mov.%d1 %0,%S2" [(set_attr "type" "cmove")]) -; ??? This doesn't properly handle constants. -;(define_insn "*movdicc_insn" -; [(set (match_operand:DI 0 "register_operand" "=r,r") -; (if_then_else:DI (match_operand 1 "comparison_operator" "") -; (match_operand:DI 2 "nonmemory_operand" "r,Ji") -; (match_operand:DI 3 "register_operand" "0,0")))] -; "0" -; "* -;{ -; switch (which_alternative) -; { -; case 0 : -; /* We normally copy the low-numbered register first. However, if -; the first register operand 0 is the same as the second register of -; operand 1, we must copy in the opposite order. */ -; if (REGNO (operands[0]) == REGNO (operands[2]) + 1) -; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\"; -; else -; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; -; case 1 : -; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; -; } -;}" -; [(set_attr "type" "cmove,cmove") -; (set_attr "length" "2,4")]) - (define_insn "*movsfcc_insn" [(set (match_operand:SF 0 "register_operand" "=r,r") (if_then_else:SF (match_operand 1 "comparison_operator" "") @@ -686,30 +624,6 @@ mov.%d1 %0,%2 ; %A2" [(set_attr "type" "cmove,cmove")]) -;(define_insn "*movdfcc_insn" -; [(set (match_operand:DF 0 "register_operand" "=r,r") -; (if_then_else:DF (match_operand 1 "comparison_operator" "") -; (match_operand:DF 2 "nonmemory_operand" "r,E") -; (match_operand:DF 3 "register_operand" "0,0")))] -; "0" -; "* -;{ -; switch (which_alternative) -; { -; case 0 : -; /* We normally copy the low-numbered register first. However, if -; the first register operand 0 is the same as the second register of -; operand 1, we must copy in the opposite order. */ -; if (REGNO (operands[0]) == REGNO (operands[2]) + 1) -; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\"; -; else -; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; -; case 1 : -; return \"mov.%d1 %0,%L2\;mov.%d1 %R0,%H2 ; %A2\"; -; } -;}" -; [(set_attr "type" "cmove,cmove") -; (set_attr "length" "2,4")]) ;; Zero extension instructions. ;; ??? We don't support volatile memrefs here, but I'm not sure why. @@ -1156,22 +1070,6 @@ ;; Compare instructions. ;; This controls RTL generation and register allocation. -;; We generate RTL for comparisons and branches by having the cmpxx -;; patterns store away the operands. Then, the scc and bcc patterns -;; emit RTL for both the compare and the branch. - -(define_expand "cmpsi" - [(set (reg:CC 61) - (compare:CC (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "nonmemory_operand" "")))] - "" - " -{ - arc_compare_op0 = operands[0]; - arc_compare_op1 = operands[1]; - DONE; -}") - ;; ??? We may be able to relax this a bit by adding a new constant 'K' for 0. ;; This assumes sub.f 0,symbol,0 is a valid insn. ;; Note that "sub.f 0,r0,1" is an 8 byte insn. To avoid unnecessarily @@ -1211,96 +1109,25 @@ sub.f 0,%0,%1" [(set_attr "type" "compare,compare,compare")]) -;; Next come the scc insns. - -(define_expand "seq" - [(set (match_operand:SI 0 "register_operand" "=r") - (eq:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1); -}") +;; Next come the scc insn and its expander. -(define_expand "sne" - [(set (match_operand:SI 0 "register_operand" "=r") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sgt" - [(set (match_operand:SI 0 "register_operand" "=r") - (gt:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sle" - [(set (match_operand:SI 0 "register_operand" "=r") - (le:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sge" - [(set (match_operand:SI 0 "register_operand" "=r") - (ge:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "slt" - [(set (match_operand:SI 0 "register_operand" "=r") - (lt:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sgtu" - [(set (match_operand:SI 0 "register_operand" "=r") - (gtu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sleu" - [(set (match_operand:SI 0 "register_operand" "=r") - (leu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sgeu" - [(set (match_operand:SI 0 "register_operand" "=r") - (geu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sltu" - [(set (match_operand:SI 0 "register_operand" "=r") - (ltu:SI (match_dup 1) (const_int 0)))] +(define_expand "cstoresi4" + [(set (match_dup 4) + (match_op_dup 5 + [(match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "nonmemory_operand" "")])) + (set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" + [(match_dup 4) + (const_int 0)]))] "" " { - operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1); + operands[4] = gen_compare_reg (GET_CODE (operands[1]), + operands[2], operands[3]); + operands[5] = gen_rtx_fmt_ee (COMPARE, + GET_MODE (operands[4]), + operands[2], operands[3]); }") (define_insn "*scc_insn" @@ -1332,114 +1159,26 @@ ;; These control RTL generation for conditional jump insns -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (le (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] +(define_expand "cbranchsi4" + [(set (match_dup 4) + (match_op_dup 5 + [(match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" "")])) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" + [(match_dup 4) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" " { - operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1); + operands[4] = gen_compare_reg (GET_CODE (operands[0]), + operands[1], operands[2]); + operands[5] = gen_rtx_fmt_ee (COMPARE, + GET_MODE (operands[4]), + operands[1], operands[2]); }") ;; Now match both normal and inverted jump. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 1d9b4265843..18e009d1368 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -418,10 +418,6 @@ extern FILE * asm_out_file; /* True if we are currently building a constant table. */ int making_const_table; -/* Define the information needed to generate branch insns. This is - stored from the compare operation. */ -rtx arm_compare_op0, arm_compare_op1; - /* The processor for which instructions should be scheduled. */ enum processor_type arm_tune = arm_none; diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index e7bc7a7a2d5..e0430908901 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -124,10 +124,6 @@ extern arm_cc arm_current_cc; extern int arm_target_label; extern int arm_ccfsm_state; extern GTY(()) rtx arm_target_insn; -/* Define the information needed to generate branch insns. This is - stored from the compare operation. */ -extern GTY(()) rtx arm_compare_op0; -extern GTY(()) rtx arm_compare_op1; /* The label of the current constant pool. */ extern rtx pool_vector_label; /* Set to 1 when a return insn is output, this means that the epilogue diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 801865287b7..b18173e1aff 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -6386,8 +6386,16 @@ (match_operand:SI 2 "nonmemory_operand" "")]) (label_ref (match_operand 3 "" "")) (pc)))] - "TARGET_THUMB1" + "TARGET_THUMB1 || TARGET_32BIT" " + if (!TARGET_THUMB1) + { + if (!arm_add_operand (operands[2], SImode)) + operands[2] = force_reg (SImode, operands[2]); + emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2], + operands[3])); + DONE; + } if (thumb1_cmpneg_operand (operands[2], SImode)) { emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2], @@ -6398,6 +6406,43 @@ operands[2] = force_reg (SImode, operands[2]); ") +(define_expand "cbranchsf4" + [(set (pc) (if_then_else + (match_operator 0 "arm_comparison_operator" + [(match_operand:SF 1 "s_register_operand" "") + (match_operand:SF 2 "arm_float_compare_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_32BIT && TARGET_HARD_FLOAT" + "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2], + operands[3])); DONE;" +) + +(define_expand "cbranchdf4" + [(set (pc) (if_then_else + (match_operator 0 "arm_comparison_operator" + [(match_operand:DF 1 "s_register_operand" "") + (match_operand:DF 2 "arm_float_compare_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_32BIT && TARGET_HARD_FLOAT" + "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2], + operands[3])); DONE;" +) + +;; this uses the Cirrus DI compare instruction +(define_expand "cbranchdi4" + [(set (pc) (if_then_else + (match_operator 0 "arm_comparison_operator" + [(match_operand:DI 1 "cirrus_fp_register" "") + (match_operand:DI 2 "cirrus_fp_register" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2], + operands[3])); DONE;" +) + (define_insn "*cbranchsi4_insn" [(set (pc) (if_then_else (match_operator 0 "arm_comparison_operator" @@ -7451,39 +7496,6 @@ ;; Comparison and test insns -(define_expand "cmpsi" - [(match_operand:SI 0 "s_register_operand" "") - (match_operand:SI 1 "arm_add_operand" "")] - "TARGET_32BIT" - "{ - arm_compare_op0 = operands[0]; - arm_compare_op1 = operands[1]; - DONE; - }" -) - -(define_expand "cmpsf" - [(match_operand:SF 0 "s_register_operand" "") - (match_operand:SF 1 "arm_float_compare_operand" "")] - "TARGET_32BIT && TARGET_HARD_FLOAT" - " - arm_compare_op0 = operands[0]; - arm_compare_op1 = operands[1]; - DONE; - " -) - -(define_expand "cmpdf" - [(match_operand:DF 0 "s_register_operand" "") - (match_operand:DF 1 "arm_float_compare_operand" "")] - "TARGET_32BIT && TARGET_HARD_FLOAT" - " - arm_compare_op0 = operands[0]; - arm_compare_op1 = operands[1]; - DONE; - " -) - (define_insn "*arm_cmpsi_insn" [(set (reg:CC CC_REGNUM) (compare:CC (match_operand:SI 0 "s_register_operand" "r,r") @@ -7562,17 +7574,6 @@ (set_attr "cirrus" "compare")] ) -;; Cirrus DI compare instruction -(define_expand "cmpdi" - [(match_operand:DI 0 "cirrus_fp_register" "") - (match_operand:DI 1 "cirrus_fp_register" "")] - "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" - "{ - arm_compare_op0 = operands[0]; - arm_compare_op1 = operands[1]; - DONE; - }") - (define_insn "*cirrus_cmpdi" [(set (reg:CC CC_REGNUM) (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v") @@ -7600,170 +7601,16 @@ ;; Conditional branch insns -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bne" +(define_expand "cbranch_cc" [(set (pc) - (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "" [(match_operand 1 "" "") + (match_operand 2 "" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "ble" - [(set (pc) - (if_then_else (le (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bunordered" - [(set (pc) - (if_then_else (unordered (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, - arm_compare_op1);" -) - -(define_expand "bordered" - [(set (pc) - (if_then_else (ordered (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, - arm_compare_op1);" -) - -(define_expand "bungt" - [(set (pc) - (if_then_else (ungt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bunlt" - [(set (pc) - (if_then_else (unlt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bunge" - [(set (pc) - (if_then_else (unge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bunle" - [(set (pc) - (if_then_else (unle (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);" -) - -;; The following two patterns need two branch instructions, since there is -;; no single instruction that will handle all cases. -(define_expand "buneq" - [(set (pc) - (if_then_else (uneq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bltgt" - [(set (pc) - (if_then_else (ltgt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);" + "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]), + operands[1], operands[2]); + operands[2] = const0_rtx;" ) ;; @@ -7876,141 +7723,16 @@ ; scc insns -(define_expand "seq" - [(set (match_operand:SI 0 "s_register_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sne" - [(set (match_operand:SI 0 "s_register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sgt" - [(set (match_operand:SI 0 "s_register_operand" "") - (gt:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sle" - [(set (match_operand:SI 0 "s_register_operand" "") - (le:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sge" - [(set (match_operand:SI 0 "s_register_operand" "") - (ge:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "slt" - [(set (match_operand:SI 0 "s_register_operand" "") - (lt:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sgtu" - [(set (match_operand:SI 0 "s_register_operand" "") - (gtu:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sleu" - [(set (match_operand:SI 0 "s_register_operand" "") - (leu:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sgeu" +(define_expand "cstore_cc" [(set (match_operand:SI 0 "s_register_operand" "") - (geu:SI (match_dup 1) (const_int 0)))] + (match_operator:SI 1 "" [(match_operand 2 "" "") + (match_operand 3 "" "")]))] "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sltu" - [(set (match_operand:SI 0 "s_register_operand" "") - (ltu:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sunordered" - [(set (match_operand:SI 0 "s_register_operand" "") - (unordered:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, - arm_compare_op1);" -) - -(define_expand "sordered" - [(set (match_operand:SI 0 "s_register_operand" "") - (ordered:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, - arm_compare_op1);" -) - -(define_expand "sungt" - [(set (match_operand:SI 0 "s_register_operand" "") - (ungt:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, - arm_compare_op1);" -) - -(define_expand "sunge" - [(set (match_operand:SI 0 "s_register_operand" "") - (unge:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, - arm_compare_op1);" -) - -(define_expand "sunlt" - [(set (match_operand:SI 0 "s_register_operand" "") - (unlt:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, - arm_compare_op1);" -) - -(define_expand "sunle" - [(set (match_operand:SI 0 "s_register_operand" "") - (unle:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, - arm_compare_op1);" + "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]), + operands[2], operands[3]); + operands[3] = const0_rtx;" ) -;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with -;;; simple ARM instructions. -; -; (define_expand "suneq" -; [(set (match_operand:SI 0 "s_register_operand" "") -; (uneq:SI (match_dup 1) (const_int 0)))] -; "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" -; "gcc_unreachable ();" -; ) -; -; (define_expand "sltgt" -; [(set (match_operand:SI 0 "s_register_operand" "") -; (ltgt:SI (match_dup 1) (const_int 0)))] -; "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" -; "gcc_unreachable ();" -; ) - (define_insn "*mov_scc" [(set (match_operand:SI 0 "s_register_operand" "=r") (match_operator:SI 1 "arm_comparison_operator" @@ -8046,10 +7768,19 @@ (match_operator:SI 1 "arm_comparison_operator" [(match_operand:SI 2 "s_register_operand" "") (match_operand:SI 3 "reg_or_int_operand" "")]))] - "TARGET_THUMB1" + "TARGET_32BIT || TARGET_THUMB1" "{ rtx op3, scratch, scratch2; + if (!TARGET_THUMB1) + { + if (!arm_add_operand (operands[3], SImode)) + operands[3] = force_reg (SImode, operands[3]); + emit_insn (gen_cstore_cc (operands[0], operands[1], + operands[2], operands[3])); + DONE; + } + if (operands[3] == const0_rtx) { switch (GET_CODE (operands[1])) @@ -8170,6 +7901,38 @@ DONE; }") +(define_expand "cstoresf4" + [(set (match_operand:SI 0 "s_register_operand" "") + (match_operator:SI 1 "arm_comparison_operator" + [(match_operand:SF 2 "s_register_operand" "") + (match_operand:SF 3 "arm_float_compare_operand" "")]))] + "TARGET_32BIT && TARGET_HARD_FLOAT" + "emit_insn (gen_cstore_cc (operands[0], operands[1], + operands[2], operands[3])); DONE;" +) + +(define_expand "cstoredf4" + [(set (match_operand:SI 0 "s_register_operand" "") + (match_operator:SI 1 "arm_comparison_operator" + [(match_operand:DF 2 "s_register_operand" "") + (match_operand:DF 3 "arm_float_compare_operand" "")]))] + "TARGET_32BIT && TARGET_HARD_FLOAT" + "emit_insn (gen_cstore_cc (operands[0], operands[1], + operands[2], operands[3])); DONE;" +) + +;; this uses the Cirrus DI compare instruction +(define_expand "cstoredi4" + [(set (match_operand:SI 0 "s_register_operand" "") + (match_operator:SI 1 "arm_comparison_operator" + [(match_operand:DI 2 "cirrus_fp_register" "") + (match_operand:DI 3 "cirrus_fp_register" "")]))] + "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + "emit_insn (gen_cstore_cc (operands[0], operands[1], + operands[2], operands[3])); DONE;" +) + + (define_expand "cstoresi_eq0_thumb1" [(parallel [(set (match_operand:SI 0 "s_register_operand" "") @@ -8250,7 +8013,8 @@ if (code == UNEQ || code == LTGT) FAIL; - ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); + ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0), + XEXP (operands[1], 1)); operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); }" ) @@ -8275,7 +8039,8 @@ || (!arm_float_add_operand (operands[3], SFmode))) operands[3] = force_reg (SFmode, operands[3]); - ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); + ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0), + XEXP (operands[1], 1)); operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); }" ) @@ -8294,7 +8059,8 @@ if (code == UNEQ || code == LTGT) FAIL; - ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); + ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0), + XEXP (operands[1], 1)); operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); }" ) diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index c7d63355d34..b45faf43cbc 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -191,9 +191,13 @@ (define_special_predicate "equality_operator" (match_code "eq,ne")) -;; True for comparisons other than LTGT or UNEQ. +;; True for integer comparisons and, if FP is active, for comparisons +;; other than LTGT or UNEQ. (define_special_predicate "arm_comparison_operator" - (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu,unordered,ordered,unlt,unle,unge,ungt")) + (ior (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu") + (and (match_test "TARGET_32BIT && TARGET_HARD_FLOAT + && (TARGET_FPA || TARGET_VFP)") + (match_code "unordered,ordered,unlt,unle,unge,ungt")))) (define_special_predicate "minmax_operator" (and (match_code "smin,smax,umin,umax") diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h index 44246901b32..f4d2119a998 100644 --- a/gcc/config/avr/avr-protos.h +++ b/gcc/config/avr/avr-protos.h @@ -72,8 +72,8 @@ extern const char *out_movhi_mr_r (rtx insn, rtx op[], int *l); extern const char *out_movsi_r_mr (rtx insn, rtx op[], int *l); extern const char *out_movsi_mr_r (rtx insn, rtx op[], int *l); extern const char *output_movsisf (rtx insn, rtx operands[], int *l); -extern const char *out_tstsi (rtx insn, int *l); -extern const char *out_tsthi (rtx insn, int *l); +extern const char *out_tstsi (rtx insn, rtx src, int *l); +extern const char *out_tsthi (rtx insn, rtx src, int *l); extern const char *ret_cond_branch (rtx x, int len, int reverse); extern const char *ashlqi3_out (rtx insn, rtx operands[], int *len); diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 6bcc8e80372..4811b92637f 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -2915,21 +2915,21 @@ compare_eq_p (rtx insn) /* Output test instruction for HImode. */ const char * -out_tsthi (rtx insn, int *l) +out_tsthi (rtx insn, rtx op, int *l) { if (compare_sign_p (insn)) { if (l) *l = 1; return AS1 (tst,%B0); } - if (reg_unused_after (insn, SET_SRC (PATTERN (insn))) + if (reg_unused_after (insn, op) && compare_eq_p (insn)) { /* Faster than sbiw if we can clobber the operand. */ if (l) *l = 1; return AS2 (or,%A0,%B0); } - if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn)))) + if (test_hard_reg_class (ADDW_REGS, op)) { if (l) *l = 1; return AS2 (sbiw,%0,0); @@ -2943,14 +2943,14 @@ out_tsthi (rtx insn, int *l) /* Output test instruction for SImode. */ const char * -out_tstsi (rtx insn, int *l) +out_tstsi (rtx insn, rtx op, int *l) { if (compare_sign_p (insn)) { if (l) *l = 1; return AS1 (tst,%D0); } - if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn)))) + if (test_hard_reg_class (ADDW_REGS, op)) { if (l) *l = 3; return (AS2 (sbiw,%A0,0) CR_TAB @@ -4367,8 +4367,8 @@ adjust_insn_length (rtx insn, int len) { switch (GET_MODE (op[1])) { - case HImode: out_tsthi (insn,&len); break; - case SImode: out_tstsi (insn,&len); break; + case HImode: out_tsthi (insn, op[1], &len); break; + case SImode: out_tstsi (insn, op[1], &len); break; default: break; } } @@ -5734,6 +5734,21 @@ avr_reorg (void) XEXP (pattern,1) = x; INSN_CODE (next) = -1; } + else if (true_regnum (XEXP (pattern, 0)) >= 0 + && XEXP (pattern, 1) == const0_rtx) + { + /* This is a tst insn, we can reverse it. */ + rtx next = next_real_insn (insn); + rtx pat = PATTERN (next); + rtx src = SET_SRC (pat); + rtx t = XEXP (src,0); + + PUT_CODE (t, swap_condition (GET_CODE (t))); + XEXP (pattern, 1) = XEXP (pattern, 0); + XEXP (pattern, 0) = const0_rtx; + INSN_CODE (next) = -1; + INSN_CODE (insn) = -1; + } else if (true_regnum (XEXP (pattern,0)) >= 0 && GET_CODE (XEXP (pattern,1)) == CONST_INT) { @@ -5753,20 +5768,6 @@ avr_reorg (void) } } } - else if (true_regnum (SET_SRC (pattern)) >= 0) - { - /* This is a tst insn */ - rtx next = next_real_insn (insn); - rtx pat = PATTERN (next); - rtx src = SET_SRC (pat); - rtx t = XEXP (src,0); - - PUT_CODE (t, swap_condition (GET_CODE (t))); - SET_SRC (pattern) = gen_rtx_COMPARE (GET_MODE (SET_SRC (pattern)), const0_rtx, - SET_SRC (pattern)); - INSN_CODE (next) = -1; - INSN_CODE (insn) = -1; - } } } } diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 269e2c5ddb5..86a217dc23c 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -2202,53 +2202,65 @@ ;;<=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=> ;; compare -(define_insn "tstqi" +; Optimize negated tests into reverse compare if overflow is undefined. +(define_insn "*negated_tstqi" [(set (cc0) - (match_operand:QI 0 "register_operand" "r"))] - "" - "tst %0" + (compare (neg:QI (match_operand:QI 0 "register_operand" "r")) + (const_int 0)))] + "(!flag_wrapv && !flag_trapv && flag_strict_overflow)" + "cp __zero_reg__,%0" [(set_attr "cc" "compare") (set_attr "length" "1")]) (define_insn "*reversed_tstqi" [(set (cc0) - (compare (const_int 0) + (compare (const_int 0) (match_operand:QI 0 "register_operand" "r")))] "" "cp __zero_reg__,%0" - [(set_attr "cc" "compare") - (set_attr "length" "1")]) +[(set_attr "cc" "compare") + (set_attr "length" "2")]) -(define_insn "tsthi" +(define_insn "*negated_tsthi" [(set (cc0) - (match_operand:HI 0 "register_operand" "!w,r"))] - "" - "* return out_tsthi (insn,NULL);" -[(set_attr "cc" "compare,compare") - (set_attr "length" "1,2")]) + (compare (neg:HI (match_operand:HI 0 "register_operand" "r")) + (const_int 0)))] + "(!flag_wrapv && !flag_trapv && flag_strict_overflow)" + "cp __zero_reg__,%A0 + cpc __zero_reg__,%B0" +[(set_attr "cc" "compare") + (set_attr "length" "2")]) +;; Leave here the clobber used by the cmphi pattern for simplicity, even +;; though it is unused, because this pattern is synthesized by avr_reorg. (define_insn "*reversed_tsthi" [(set (cc0) (compare (const_int 0) - (match_operand:HI 0 "register_operand" "r")))] + (match_operand:HI 0 "register_operand" "r"))) + (clobber (match_scratch:QI 1 "=X"))] "" "cp __zero_reg__,%A0 cpc __zero_reg__,%B0" [(set_attr "cc" "compare") (set_attr "length" "2")]) -(define_insn "tstsi" +(define_insn "*negated_tstsi" [(set (cc0) - (match_operand:SI 0 "register_operand" "r"))] - "" - "* return out_tstsi (insn,NULL);" + (compare (neg:SI (match_operand:SI 0 "register_operand" "r")) + (const_int 0)))] + "(!flag_wrapv && !flag_trapv && flag_strict_overflow)" + "cp __zero_reg__,%A0 + cpc __zero_reg__,%B0 + cpc __zero_reg__,%C0 + cpc __zero_reg__,%D0" [(set_attr "cc" "compare") (set_attr "length" "4")]) (define_insn "*reversed_tstsi" [(set (cc0) - (compare (const_int 0) - (match_operand:SI 0 "register_operand" "r")))] + (compare (const_int 0) + (match_operand:SI 0 "register_operand" "r"))) + (clobber (match_scratch:QI 1 "=X"))] "" "cp __zero_reg__,%A0 cpc __zero_reg__,%B0 @@ -2258,16 +2270,17 @@ (set_attr "length" "4")]) -(define_insn "cmpqi" +(define_insn "*cmpqi" [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "r,d") - (match_operand:QI 1 "nonmemory_operand" "r,i")))] + (compare (match_operand:QI 0 "register_operand" "r,r,d") + (match_operand:QI 1 "nonmemory_operand" "L,r,i")))] "" "@ + tst %0 cp %0,%1 cpi %0,lo8(%1)" - [(set_attr "cc" "compare,compare") - (set_attr "length" "1,1")]) + [(set_attr "cc" "compare,compare,compare") + (set_attr "length" "1,1,1")]) (define_insn "*cmpqi_sign_extend" [(set (cc0) @@ -2279,19 +2292,22 @@ [(set_attr "cc" "compare") (set_attr "length" "1")]) -(define_insn "cmphi" +(define_insn "*cmphi" [(set (cc0) - (compare (match_operand:HI 0 "register_operand" "r,d,d,r,r") - (match_operand:HI 1 "nonmemory_operand" "r,M,i,M,i"))) - (clobber (match_scratch:QI 2 "=X,X,&d,&d,&d"))] + (compare (match_operand:HI 0 "register_operand" "!w,r,r,d,d,r,r") + (match_operand:HI 1 "nonmemory_operand" "L,L,r,M,i,M,i"))) + (clobber (match_scratch:QI 2 "=X,X,X,X,&d,&d,&d"))] "" "*{ switch (which_alternative) { - case 0: + case 0: case 1: + return out_tsthi (insn, operands[0], NULL); + + case 2: return (AS2 (cp,%A0,%A1) CR_TAB AS2 (cpc,%B0,%B1)); - case 1: + case 3: if (reg_unused_after (insn, operands[0]) && INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 63 && test_hard_reg_class (ADDW_REGS, operands[0])) @@ -2299,7 +2315,7 @@ else return (AS2 (cpi,%0,%1) CR_TAB AS2 (cpc,%B0,__zero_reg__)); - case 2: + case 4: if (reg_unused_after (insn, operands[0])) return (AS2 (subi,%0,lo8(%1)) CR_TAB AS2 (sbci,%B0,hi8(%1))); @@ -2307,12 +2323,12 @@ return (AS2 (ldi, %2,hi8(%1)) CR_TAB AS2 (cpi, %A0,lo8(%1)) CR_TAB AS2 (cpc, %B0,%2)); - case 3: + case 5: return (AS2 (ldi, %2,lo8(%1)) CR_TAB AS2 (cp, %A0,%2) CR_TAB AS2 (cpc, %B0,__zero_reg__)); - case 4: + case 6: return (AS2 (ldi, %2,lo8(%1)) CR_TAB AS2 (cp, %A0,%2) CR_TAB AS2 (ldi, %2,hi8(%1)) CR_TAB @@ -2320,25 +2336,28 @@ } return \"bug\"; }" - [(set_attr "cc" "compare,compare,compare,compare,compare") - (set_attr "length" "2,2,3,3,4")]) + [(set_attr "cc" "compare,compare,compare,compare,compare,compare,compare") + (set_attr "length" "1,2,2,2,3,3,4")]) -(define_insn "cmpsi" +(define_insn "*cmpsi" [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "r,d,d,r,r") - (match_operand:SI 1 "nonmemory_operand" "r,M,i,M,i"))) - (clobber (match_scratch:QI 2 "=X,X,&d,&d,&d"))] + (compare (match_operand:SI 0 "register_operand" "r,r,d,d,r,r") + (match_operand:SI 1 "nonmemory_operand" "L,r,M,i,M,i"))) + (clobber (match_scratch:QI 2 "=X,X,X,&d,&d,&d"))] "" "*{ switch (which_alternative) { case 0: + return out_tstsi (insn, operands[0], NULL); + + case 1: return (AS2 (cp,%A0,%A1) CR_TAB AS2 (cpc,%B0,%B1) CR_TAB AS2 (cpc,%C0,%C1) CR_TAB AS2 (cpc,%D0,%D1)); - case 1: + case 2: if (reg_unused_after (insn, operands[0]) && INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 63 && test_hard_reg_class (ADDW_REGS, operands[0])) @@ -2350,7 +2369,7 @@ AS2 (cpc,%B0,__zero_reg__) CR_TAB AS2 (cpc,%C0,__zero_reg__) CR_TAB AS2 (cpc,%D0,__zero_reg__)); - case 2: + case 3: if (reg_unused_after (insn, operands[0])) return (AS2 (subi,%A0,lo8(%1)) CR_TAB AS2 (sbci,%B0,hi8(%1)) CR_TAB @@ -2364,13 +2383,13 @@ AS2 (cpc, %C0,%2) CR_TAB AS2 (ldi, %2,hhi8(%1)) CR_TAB AS2 (cpc, %D0,%2)); - case 3: + case 4: return (AS2 (ldi,%2,lo8(%1)) CR_TAB AS2 (cp,%A0,%2) CR_TAB AS2 (cpc,%B0,__zero_reg__) CR_TAB AS2 (cpc,%C0,__zero_reg__) CR_TAB AS2 (cpc,%D0,__zero_reg__)); - case 4: + case 5: return (AS2 (ldi, %2,lo8(%1)) CR_TAB AS2 (cp, %A0,%2) CR_TAB AS2 (ldi, %2,hi8(%1)) CR_TAB @@ -2382,113 +2401,53 @@ } return \"bug\"; }" - [(set_attr "cc" "compare,compare,compare,compare,compare") - (set_attr "length" "4,4,7,5,8")]) - -; Optimize negated tests into reverse compare if overflow is undefined. -(define_insn_and_split "negated_tst" - [(set (cc0) - (neg:QISI (match_operand:QISI 0 "register_operand")))] + [(set_attr "cc" "compare,compare,compare,compare,compare,compare") + (set_attr "length" "4,4,4,7,5,8")]) - "(!flag_wrapv && !flag_trapv && flag_strict_overflow)" - "#" - "" - [(set (cc0) - (compare (const_int 0) - (match_dup 0)))] - "") ;; ---------------------------------------------------------------------- ;; JUMP INSTRUCTIONS ;; ---------------------------------------------------------------------- ;; Conditional jump instructions -(define_expand "beq" - [(set (pc) - (if_then_else (eq (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - - - -/**************************************************************** - AVR not have following conditional jumps: LE,LEU,GT,GTU. - Convert them all to proper jumps. -*****************************************************************/ - -(define_expand "ble" - [(set (pc) - (if_then_else (le (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") +(define_expand "cbranchsi4" + [(parallel [(set (cc0) + (compare (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" ""))) + (clobber (match_scratch:QI 4 ""))]) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "") + +(define_expand "cbranchhi4" + [(parallel [(set (cc0) + (compare (match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "nonmemory_operand" ""))) + (clobber (match_scratch:QI 4 ""))]) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "") -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") +(define_expand "cbranchqi4" + [(set (cc0) + (compare (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "nonmemory_operand" ""))) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "") -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") ;; Test a single bit in a QI/HI/SImode register. (define_insn "*sbrx_branch" @@ -2557,7 +2516,8 @@ ;; Convert sign tests to bit 7/15/31 tests that match the above insns. (define_peephole2 - [(set (cc0) (match_operand:QI 0 "register_operand" "")) + [(set (cc0) (compare (match_operand:QI 0 "register_operand" "") + (const_int 0))) (set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2571,7 +2531,8 @@ "") (define_peephole2 - [(set (cc0) (match_operand:QI 0 "register_operand" "")) + [(set (cc0) (compare (match_operand:QI 0 "register_operand" "") + (const_int 0))) (set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2585,7 +2546,9 @@ "") (define_peephole2 - [(set (cc0) (match_operand:HI 0 "register_operand" "")) + [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "") + (const_int 0))) + (clobber (match_operand:HI 2 ""))]) (set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2597,7 +2560,9 @@ "") (define_peephole2 - [(set (cc0) (match_operand:HI 0 "register_operand" "")) + [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "") + (const_int 0))) + (clobber (match_operand:HI 2 ""))]) (set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2609,7 +2574,9 @@ "") (define_peephole2 - [(set (cc0) (match_operand:SI 0 "register_operand" "")) + [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "") + (const_int 0))) + (clobber (match_operand:SI 2 ""))]) (set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2621,7 +2588,9 @@ "operands[2] = GEN_INT (-2147483647 - 1);") (define_peephole2 - [(set (cc0) (match_operand:SI 0 "register_operand" "")) + [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "") + (const_int 0))) + (clobber (match_operand:SI 2 ""))]) (set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2650,6 +2619,11 @@ [(set_attr "type" "branch") (set_attr "cc" "clobber")]) +;; **************************************************************** +;; AVR does not have following conditional jumps: LE,LEU,GT,GTU. +;; Convert them all to proper jumps. +;; ****************************************************************/ + (define_insn "difficult_branch" [(set (pc) (if_then_else (match_operator 1 "difficult_comparison_operator" @@ -3150,7 +3124,9 @@ }") (define_peephole - [(set (cc0) (match_operand:QI 0 "register_operand" "")) + [(set (cc0) + (compare (match_operand:QI 0 "register_operand" "") + (const_int 0))) (set (pc) (if_then_else (eq (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 077d5c544a7..ac237d73bd2 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -67,10 +67,6 @@ struct GTY(()) machine_function int has_loopreg_clobber; }; -/* Test and compare insns in bfin.md store the information needed to - generate branch and scc insns here. */ -rtx bfin_compare_op0, bfin_compare_op1; - /* RTX for condition code flag register and RETS register */ extern GTY(()) rtx bfin_cc_rtx; extern GTY(()) rtx bfin_rets_rtx; @@ -2714,7 +2710,7 @@ rtx bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED) { enum rtx_code code1, code2; - rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1; + rtx op0 = XEXP (cmp, 0), op1 = XEXP (cmp, 1); rtx tem = bfin_cc_rtx; enum rtx_code code = GET_CODE (cmp); @@ -2742,7 +2738,7 @@ bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED) code2 = EQ; break; } - emit_insn (gen_rtx_SET (BImode, tem, + emit_insn (gen_rtx_SET (VOIDmode, tem, gen_rtx_fmt_ee (code1, BImode, op0, op1))); } @@ -4219,17 +4215,17 @@ bfin_optimize_loop (loop_info loop) { /* If loop->iter_reg is a DREG or PREG, we can split it here without scratch register. */ - rtx insn; + rtx insn, test; emit_insn_before (gen_addsi3 (loop->iter_reg, loop->iter_reg, constm1_rtx), loop->loop_end); - emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx), - loop->loop_end); - - insn = emit_jump_insn_before (gen_bne (loop->start_label), + test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx); + insn = emit_jump_insn_before (gen_cbranchsi4 (test, + loop->iter_reg, const0_rtx, + loop->start_label), loop->loop_end); JUMP_LABEL (insn) = loop->start_label; diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h index d97fe8faaf4..352f4b4c208 100644 --- a/gcc/config/bfin/bfin.h +++ b/gcc/config/bfin/bfin.h @@ -1292,7 +1292,6 @@ do { \ #define ASM_OUTPUT_REG_PUSH(FILE, REGNO) fprintf (FILE, "[SP--] = %s;\n", reg_names[REGNO]) #define ASM_OUTPUT_REG_POP(FILE, REGNO) fprintf (FILE, "%s = [SP++];\n", reg_names[REGNO]) -extern struct rtx_def *bfin_compare_op0, *bfin_compare_op1; extern struct rtx_def *bfin_cc_rtx, *bfin_rets_rtx; /* This works for GAS and some other assemblers. */ diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md index 4397b7a139a..755a0d3ced6 100644 --- a/gcc/config/bfin/bfin.md +++ b/gcc/config/bfin/bfin.md @@ -2255,29 +2255,6 @@ ;; Conditional branch patterns ;; The Blackfin has only few condition codes: eq, lt, lte, ltu, leu -;; The only outcome of this pattern is that global variables -;; bfin_compare_op[01] are set for use in bcond patterns. - -(define_expand "cmpbi" - [(set (cc0) (compare (match_operand:BI 0 "register_operand" "") - (match_operand:BI 1 "immediate_operand" "")))] - "" -{ - bfin_compare_op0 = operands[0]; - bfin_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmpsi" - [(set (cc0) (compare (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "reg_or_const_int_operand" "")))] - "" -{ - bfin_compare_op0 = operands[0]; - bfin_compare_op1 = operands[1]; - DONE; -}) - (define_insn "compare_eq" [(set (match_operand:BI 0 "register_operand" "=C,C") (eq:BI (match_operand:SI 1 "register_operand" "d,a") @@ -2326,106 +2303,6 @@ "cc =%1<%2 (iu);" [(set_attr "type" "compare")]) -(define_expand "beq" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1; - operands[1] = bfin_cc_rtx; /* hard register: CC */ - operands[2] = gen_rtx_EQ (BImode, op0, op1); - /* If we have a BImode input, then we already have a compare result, and - do not need to emit another comparison. */ - if (GET_MODE (bfin_compare_op0) == BImode) - { - gcc_assert (bfin_compare_op1 == const0_rtx); - emit_insn (gen_cbranchbi4 (operands[2], op0, op1, operands[0])); - DONE; - } - - operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx); -}) - -(define_expand "bne" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1; - /* If we have a BImode input, then we already have a compare result, and - do not need to emit another comparison. */ - if (GET_MODE (bfin_compare_op0) == BImode) - { - rtx cmp = gen_rtx_NE (BImode, op0, op1); - - gcc_assert (bfin_compare_op1 == const0_rtx); - emit_insn (gen_cbranchbi4 (cmp, op0, op1, operands[0])); - DONE; - } - - operands[1] = bfin_cc_rtx; /* hard register: CC */ - operands[2] = gen_rtx_EQ (BImode, op0, op1); - operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx); -}) - -(define_expand "bgt" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LE (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx); -}) - -(define_expand "bgtu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LEU (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx); -}) - -(define_expand "blt" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LT (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx); -}) - -(define_expand "bltu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LTU (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx); -}) - ;; Same as above, but and CC with the overflow bit generated by the first ;; multiplication. (define_insn "flag_mul_macv2hi_parts_acconly_andcc0" @@ -2490,63 +2367,25 @@ (set_attr "length" "6") (set_attr "seq_insns" "multi")]) -(define_expand "bge" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LT (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx); -}) - -(define_expand "bgeu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LTU (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx); -}) - -(define_expand "ble" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LE (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx); -}) - -(define_expand "bleu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc))) - ] +(define_expand "cbranchsi4" + [(set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "reg_or_const_int_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" { - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LEU (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx); + rtx bi_compare = bfin_gen_compare (operands[0], SImode); + emit_jump_insn (gen_cbranchbi4 (bi_compare, bfin_cc_rtx, CONST0_RTX (BImode), + operands[3])); + DONE; }) (define_insn "cbranchbi4" [(set (pc) (if_then_else - (match_operator 0 "bfin_cbranch_operator" + (match_operator 0 "bfin_bimode_comparison_operator" [(match_operand:BI 1 "register_operand" "C") (match_operand:BI 2 "immediate_operand" "P0")]) (label_ref (match_operand 3 "" "")) @@ -2564,7 +2403,7 @@ (define_insn "cbranch_predicted_taken" [(set (pc) (if_then_else - (match_operator 0 "bfin_cbranch_operator" + (match_operator 0 "bfin_bimode_comparison_operator" [(match_operand:BI 1 "register_operand" "C") (match_operand:BI 2 "immediate_operand" "P0")]) (label_ref (match_operand 3 "" "")) @@ -2580,7 +2419,7 @@ (define_insn "cbranch_with_nops" [(set (pc) (if_then_else - (match_operator 0 "bfin_cbranch_operator" + (match_operator 0 "bfin_bimode_comparison_operator" [(match_operand:BI 1 "register_operand" "C") (match_operand:BI 2 "immediate_operand" "P0")]) (label_ref (match_operand 3 "" "")) @@ -2594,60 +2433,49 @@ [(set_attr "type" "brcc") (set_attr "length" "8")]) -;; setcc insns. */ -(define_expand "seq" - [(set (match_dup 1) (eq:BI (match_dup 2) (match_dup 3))) - (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" -{ - operands[2] = bfin_compare_op0; - operands[3] = bfin_compare_op1; - operands[1] = bfin_cc_rtx; -}) +;; setcc insns. -(define_expand "slt" - [(set (match_dup 1) (lt:BI (match_dup 2) (match_dup 3))) +(define_expand "cstorebi4" + [(set (match_dup 4) + (match_operator:BI 1 "bfin_bimode_comparison_operator" + [(match_operand:BI 2 "register_operand" "") + (match_operand:BI 3 "reg_or_const_int_operand" "")])) (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] + (ne:SI (match_dup 4) (const_int 0)))] "" { - operands[2] = bfin_compare_op0; - operands[3] = bfin_compare_op1; - operands[1] = bfin_cc_rtx; -}) + /* It could be expanded as a movbisi instruction, but the portable + alternative produces better code. */ + if (GET_CODE (operands[1]) == NE) + FAIL; -(define_expand "sle" - [(set (match_dup 1) (le:BI (match_dup 2) (match_dup 3))) - (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" -{ - operands[2] = bfin_compare_op0; - operands[3] = bfin_compare_op1; - operands[1] = bfin_cc_rtx; + operands[4] = bfin_cc_rtx; }) -(define_expand "sltu" - [(set (match_dup 1) (ltu:BI (match_dup 2) (match_dup 3))) - (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] +(define_expand "cstoresi4" + [(set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "reg_or_const_int_operand" "")]))] "" { - operands[2] = bfin_compare_op0; - operands[3] = bfin_compare_op1; - operands[1] = bfin_cc_rtx; -}) + rtx bi_compare, test; -(define_expand "sleu" - [(set (match_dup 1) (leu:BI (match_dup 2) (match_dup 3))) - (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" -{ - operands[2] = bfin_compare_op0; - operands[3] = bfin_compare_op1; - operands[1] = bfin_cc_rtx; + if (!bfin_direct_comparison_operator (operands[1], SImode)) + { + if (!register_operand (operands[3], SImode) + || GET_CODE (operands[1]) == NE) + FAIL; + test = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[1])), + SImode, operands[3], operands[2]); + } + else + test = operands[1]; + + bi_compare = bfin_gen_compare (test, SImode); + gcc_assert (GET_CODE (bi_compare) == NE); + emit_insn (gen_movbisi (operands[0], bfin_cc_rtx)); + DONE; }) (define_insn "nop" @@ -2676,13 +2504,16 @@ "CC = %1;" [(set_attr "length" "2")]) -(define_insn "movbisi" +(define_insn_and_split "movbisi" [(set (match_operand:SI 0 "register_operand" "=d") (ne:SI (match_operand:BI 1 "register_operand" "C") (const_int 0)))] "" - "%0 = CC;" - [(set_attr "length" "2")]) + "#" + "" + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:BI 1 "register_operand" "")))] + "") (define_insn "notbi" [(set (match_operand:BI 0 "register_operand" "=C") diff --git a/gcc/config/bfin/predicates.md b/gcc/config/bfin/predicates.md index 7aac5b0534c..bce725a7009 100644 --- a/gcc/config/bfin/predicates.md +++ b/gcc/config/bfin/predicates.md @@ -172,10 +172,14 @@ && REGNO (op) <= LAST_VIRTUAL_REGISTER)); }) -;; Test for an operator valid in a conditional branch -(define_predicate "bfin_cbranch_operator" +;; Test for an operator valid in a BImode conditional branch +(define_predicate "bfin_bimode_comparison_operator" (match_code "eq,ne")) +;; Test for an operator whose result is accessible with movbisi. +(define_predicate "bfin_direct_comparison_operator" + (match_code "eq,lt,le,leu,ltu")) + ;; The following two are used to compute the addrtype attribute. They return ;; true if passed a memory address usable for a 16-bit load or store using a ;; P or I register, respectively. If neither matches, we know we have a diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c index 2112670de6c..bc634ddbf3e 100644 --- a/gcc/config/cris/cris.c +++ b/gcc/config/cris/cris.c @@ -1431,13 +1431,18 @@ cris_normal_notice_update_cc (rtx exp, rtx insn) if (SET_DEST (exp) == cc0_rtx) { CC_STATUS_INIT; - cc_status.value1 = SET_SRC (exp); - /* Handle flags for the special btstq on one bit. */ - if (GET_CODE (SET_SRC (exp)) == ZERO_EXTRACT - && XEXP (SET_SRC (exp), 1) == const1_rtx) + if (GET_CODE (SET_SRC (exp)) == COMPARE + && XEXP (SET_SRC (exp), 1) == const0_rtx) + cc_status.value1 = XEXP (SET_SRC (exp), 0); + else + cc_status.value1 = SET_SRC (exp); + + /* Handle flags for the special btstq on one bit. */ + if (GET_CODE (cc_status.value1) == ZERO_EXTRACT + && XEXP (cc_status.value1, 1) == const1_rtx) { - if (CONST_INT_P (XEXP (SET_SRC (exp), 0))) + if (CONST_INT_P (XEXP (cc_status.value1, 0))) /* Using cmpq. */ cc_status.flags = CC_INVERTED; else @@ -1445,7 +1450,7 @@ cris_normal_notice_update_cc (rtx exp, rtx insn) cc_status.flags = CC_Z_IN_NOT_N; } - if (GET_CODE (SET_SRC (exp)) == COMPARE) + else if (GET_CODE (SET_SRC (exp)) == COMPARE) { if (!REG_P (XEXP (SET_SRC (exp), 0)) && XEXP (SET_SRC (exp), 1) != const0_rtx) @@ -1855,6 +1860,11 @@ cris_rtx_costs (rtx x, int code, int outer_code, int *total, } return false; + case ZERO_EXTRACT: + if (outer_code != COMPARE) + return false; + /* fall through */ + case ZERO_EXTEND: case SIGN_EXTEND: *total = rtx_cost (XEXP (x, 0), outer_code, speed); return true; diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md index f4b2128ea19..79eb8da3b0d 100644 --- a/gcc/config/cris/cris.md +++ b/gcc/config/cris/cris.md @@ -248,40 +248,16 @@ ;; Test insns. -;; DImode -;; -;; Allow register and offsettable mem operands only; post-increment is -;; not worth the trouble. - -(define_expand "tstdi" - [(set (cc0) (match_operand:DI 0 "nonimmediate_operand"))] - "" -{ - if (TARGET_V32 && MEM_P (operands[0])) - operands[0] = force_reg (DImode, operands[0]); -}) - -(define_insn "*tstdi_non_v32" - [(set (cc0) - (match_operand:DI 0 "nonimmediate_operand" "r,o"))] - "!TARGET_V32" - "test.d %M0\;ax\;test.d %H0") - -(define_insn "*tstdi_v32" - [(set (cc0) - (match_operand:DI 0 "register_operand" "r"))] - "TARGET_V32" - "cmpq 0,%M0\;ax\;cmpq 0,%H0") - ;; No test insns with side-effect on the mem addressing. ;; ;; See note on cmp-insns with side-effects (or lack of them) ;; Normal named test patterns from SI on. -(define_insn "tstsi" +(define_insn "*tstsi" [(set (cc0) - (match_operand:SI 0 "nonimmediate_operand" "r,Q>,m"))] + (compare (match_operand:SI 0 "nonimmediate_operand" "r,Q>,m") + (const_int 0)))] "" { if (which_alternative == 0 && TARGET_V32) @@ -290,15 +266,10 @@ } [(set_attr "slottable" "yes,yes,no")]) -(define_expand "tst" - [(set (cc0) - (match_operand:BW 0 "nonimmediate_operand"))] - "" - "") - (define_insn "*tst_cmp" [(set (cc0) - (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m"))] + (compare (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m") + (const_int 0)))] "cris_cc0_user_requires_cmp (insn)" "@ cmp 0,%0 @@ -308,7 +279,8 @@ (define_insn "*tst_non_cmp" [(set (cc0) - (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m"))] + (compare (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m") + (const_int 0)))] "!cris_cc0_user_requires_cmp (insn)" "@ move %0,%0 @@ -332,24 +304,13 @@ ;; DImode for anything else but a structure/block-mode. Just do the ;; obvious stuff for the straight-forward constraint letters. -(define_expand "cmpdi" - [(set (cc0) - (compare (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "general_operand" "")))] - "" -{ - if (TARGET_V32 && !REG_P (operands[0])) - operands[0] = force_reg (DImode, operands[0]); - if (TARGET_V32 && MEM_P (operands[1])) - operands[1] = force_reg (DImode, operands[1]); -}) - (define_insn "*cmpdi_non_v32" [(set (cc0) - (compare (match_operand:DI 0 "nonimmediate_operand" "r,r,r,r,r,r,o") - (match_operand:DI 1 "general_operand" "Kc,I,P,n,r,o,r")))] + (compare (match_operand:DI 0 "nonimmediate_operand" "rm,r,r,r,r,r,r,o") + (match_operand:DI 1 "general_operand" "M,Kc,I,P,n,r,o,r")))] "!TARGET_V32" "@ + test.d %M0\;ax\;test.d %H0 cmpq %1,%M0\;ax\;cmpq 0,%H0 cmpq %1,%M0\;ax\;cmpq -1,%H0 cmp%e1.%z1 %1,%M0\;ax\;cmpq %H1,%H0 @@ -415,9 +376,9 @@ (set_attr "cc" "rev")]) ;; The "normal" compare patterns, from SI on. Special-cases with zero -;; should not happen. +;; are covered above. -(define_insn "cmpsi" +(define_insn "*cmpsi" [(set (cc0) (compare (match_operand:SI 0 "nonimmediate_operand" "r,r,r, Q>,r,r,m") @@ -434,7 +395,7 @@ [(set_attr "slottable" "yes,yes,yes,yes,no,no,no") (set_attr "cc" "normal,normal,normal,rev,normal,normal,rev")]) -(define_insn "cmp" +(define_insn "*cmp" [(set (cc0) (compare (match_operand:BW 0 "nonimmediate_operand" "r,r, Q>,r,m") (match_operand:BW 1 "general_operand" "r,Q>,r, g,r")))] @@ -457,10 +418,12 @@ ;; extends subregs for lower-size modes. FIXME: Add testcase. (define_insn "*btst" [(set (cc0) - (zero_extract - (match_operand:SI 0 "nonmemory_operand" "r, r,r, r,r, r,Kp") - (match_operand:SI 1 "const_int_operand" "Kc,n,Kc,n,Kc,n,n") - (match_operand:SI 2 "nonmemory_operand" "M, M,Kc,n,r, r,r")))] + (compare + (zero_extract:SI + (match_operand:SI 0 "nonmemory_operand" "r, r,r, r,r, r,Kp") + (match_operand:SI 1 "const_int_operand" "Kc,n,Kc,n,Kc,n,n") + (match_operand:SI 2 "nonmemory_operand" "M, M,Kc,n,r, r,r")) + (const_int 0)))] ;; Either it is a single bit, or consecutive ones starting at 0. ;; The btst ones depend on stuff in NOTICE_UPDATE_CC. "CONST_INT_P (operands[1]) @@ -3550,6 +3513,36 @@ ;; Conditional branches. +(define_expand "cbranch4" + [(set (cc0) (compare + (match_operand:BWD 1 "nonimmediate_operand") + (match_operand:BWD 2 "general_operand"))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" + "") + +(define_expand "cbranchdi4" + [(set (cc0) + (compare (match_operand:DI 1 "nonimmediate_operand" "") + (match_operand:DI 2 "general_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" +{ + if (TARGET_V32 && !REG_P (operands[1])) + operands[1] = force_reg (DImode, operands[1]); + if (TARGET_V32 && MEM_P (operands[2])) + operands[2] = force_reg (DImode, operands[2]); +}) + + ;; We suffer from the same overflow-bit-gets-in-the-way problem as ;; e.g. m68k, so we have to check if overflow bit is set on all "signed" ;; conditions. @@ -3634,6 +3627,31 @@ ;; Set on condition: sCC. +(define_expand "cstoredi4" + [(set (cc0) (compare + (match_operand:DI 2 "nonimmediate_operand") + (match_operand:DI 3 "general_operand"))) + (set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" + [(cc0) (const_int 0)]))] + "" +{ + if (TARGET_V32 && !REG_P (operands[2])) + operands[2] = force_reg (DImode, operands[2]); + if (TARGET_V32 && MEM_P (operands[3])) + operands[3] = force_reg (DImode, operands[3]); +}) + +(define_expand "cstore4" + [(set (cc0) (compare + (match_operand:BWD 2 "nonimmediate_operand") + (match_operand:BWD 3 "general_operand"))) + (set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" + [(cc0) (const_int 0)]))] + "" + "") + ;; Like bCC, we have to check the overflow bit for ;; signed conditions. diff --git a/gcc/config/crx/crx-protos.h b/gcc/config/crx/crx-protos.h index 0be641dd89e..386fab9fe43 100644 --- a/gcc/config/crx/crx-protos.h +++ b/gcc/config/crx/crx-protos.h @@ -62,10 +62,6 @@ extern void crx_print_operand (FILE *, rtx, int); extern void crx_print_operand_address (FILE *, rtx); /* Misc functions called from crx.md. */ -extern rtx crx_expand_compare (enum rtx_code, enum machine_mode); -extern void crx_expand_branch (enum rtx_code, rtx); -extern void crx_expand_scond (enum rtx_code, rtx); - extern void crx_expand_movmem_single (rtx, rtx, rtx, rtx, rtx, unsigned HOST_WIDE_INT *); extern int crx_expand_movmem (rtx, rtx, rtx, rtx); #endif /* RTX_CODE */ diff --git a/gcc/config/crx/crx.c b/gcc/config/crx/crx.c index 6f10afd2e5f..cc3248fb5ee 100644 --- a/gcc/config/crx/crx.c +++ b/gcc/config/crx/crx.c @@ -124,10 +124,6 @@ static enum machine_mode output_memory_reference_mode; /* Table of machine attributes. */ const struct attribute_spec crx_attribute_table[]; -/* Test and compare insns use these globals to generate branch insns. */ -rtx crx_compare_op0 = NULL_RTX; -rtx crx_compare_op1 = NULL_RTX; - /*****************************************************************************/ /* TARGETM FUNCTION PROTOTYPES */ /*****************************************************************************/ @@ -1217,43 +1213,6 @@ crx_expand_movmem (rtx dstbase, rtx srcbase, rtx count_exp, rtx align_exp) return 1; } -rtx -crx_expand_compare (enum rtx_code code, enum machine_mode mode) -{ - rtx op0, op1, cc_reg, ret; - - op0 = crx_compare_op0; - op1 = crx_compare_op1; - - /* Emit the compare that writes into CC_REGNUM) */ - cc_reg = gen_rtx_REG (CCmode, CC_REGNUM); - ret = gen_rtx_COMPARE (CCmode, op0, op1); - emit_insn (gen_rtx_SET (VOIDmode, cc_reg, ret)); - /* debug_rtx (get_last_insn ()); */ - - /* Return the rtx for using the result in CC_REGNUM */ - return gen_rtx_fmt_ee (code, mode, cc_reg, const0_rtx); -} - -void -crx_expand_branch (enum rtx_code code, rtx label) -{ - rtx tmp = crx_expand_compare (code, VOIDmode); - tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, - gen_rtx_LABEL_REF (VOIDmode, label), - pc_rtx); - emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); - /* debug_rtx (get_last_insn ()); */ -} - -void -crx_expand_scond (enum rtx_code code, rtx dest) -{ - rtx tmp = crx_expand_compare (code, GET_MODE (dest)); - emit_move_insn (dest, tmp); - /* debug_rtx (get_last_insn ()); */ -} - static void mpushpop_str (char *stringbuffer, const char *mnemonic, char *mask) { diff --git a/gcc/config/crx/crx.h b/gcc/config/crx/crx.h index 69065f3795b..cac465701bf 100644 --- a/gcc/config/crx/crx.h +++ b/gcc/config/crx/crx.h @@ -520,11 +520,4 @@ struct cumulative_args #define FUNCTION_MODE QImode -/*****************************************************************************/ -/* EXTERNAL DECLARATIONS FOR VARIABLES DEFINED IN CRX.C */ -/*****************************************************************************/ - -extern rtx crx_compare_op0; /* operand 0 for comparisons */ -extern rtx crx_compare_op1; /* operand 1 for comparisons */ - #endif /* ! GCC_CRX_H */ diff --git a/gcc/config/crx/crx.md b/gcc/config/crx/crx.md index b9655544ffc..229e345d32f 100644 --- a/gcc/config/crx/crx.md +++ b/gcc/config/crx/crx.md @@ -63,6 +63,10 @@ (ior (match_code "symbol_ref") (match_operand 0 "register_operand"))) +(define_predicate "cc_reg_operand" + (and (match_code "reg") + (match_test "REGNO (op) == CC_REGNUM"))) + (define_predicate "nosp_reg_operand" (and (match_operand 0 "register_operand") (match_test "REGNO (op) != SP_REGNUM"))) @@ -107,8 +111,6 @@ (define_code_iterator mima_oprnd [smax umax smin umin]) (define_code_attr mimaIsa [(smax "maxs") (umax "maxu") (smin "mins") (umin "minu")]) -(define_code_iterator any_cond [eq ne gt gtu lt ltu ge geu le leu]) - ;; Addition Instructions (define_insn "adddi3" @@ -522,9 +524,21 @@ ;; Compare and Branch Instructions +(define_insn "cbranchcc4" + [(set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:CC 1 "cc_reg_operand" "r") + (match_operand 2 "cst4_operand" "L")]) + (label_ref (match_operand 3 "")) + (pc)))] + "" + "b%d0\t%l3" + [(set_attr "length" "6")] +) + (define_insn "cbranch4" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ordered_comparison_operator" [(match_operand:CRXIM 1 "register_operand" "r") (match_operand:CRXIM 2 "reg_or_cst4_operand" "rL")]) (label_ref (match_operand 3 "" "")) @@ -535,18 +549,18 @@ [(set_attr "length" "6")] ) -;; Compare Instructions -(define_expand "cmp" +;; Scond Instructions + +(define_expand "cstore4" [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:CRXIM 0 "register_operand" "") - (match_operand:CRXIM 1 "nonmemory_operand" "")))] + (compare:CC (match_operand:CRXIM 2 "register_operand" "") + (match_operand:CRXIM 3 "nonmemory_operand" ""))) + (set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" + [(reg:CC CC_REGNUM) (const_int 0)]))] + "" "" - { - crx_compare_op0 = operands[0]; - crx_compare_op1 = operands[1]; - DONE; - } ) (define_insn "cmp_internal" @@ -558,48 +572,9 @@ [(set_attr "length" "2,")] ) -;; Conditional Branch Instructions - -(define_expand "b" - [(set (pc) - (if_then_else (any_cond (reg:CC CC_REGNUM) - (const_int 0)) - (label_ref (match_operand 0 "")) - (pc)))] - "" - { - crx_expand_branch (, operands[0]); - DONE; - } -) - -(define_insn "bCOND_internal" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC CC_REGNUM) - (const_int 0)]) - (label_ref (match_operand 1 "")) - (pc)))] - "" - "b%d0\t%l1" - [(set_attr "length" "6")] -) - -;; Scond Instructions - -(define_expand "s" - [(set (match_operand:SI 0 "register_operand") - (any_cond:SI (reg:CC CC_REGNUM) (const_int 0)))] - "" - { - crx_expand_scond (, operands[0]); - DONE; - } -) - (define_insn "sCOND_internal" [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 1 "comparison_operator" + (match_operator:SI 1 "ordered_comparison_operator" [(reg:CC CC_REGNUM) (const_int 0)]))] "" "s%d1\t%0" diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c index e7f2e3cfd86..5642c548a29 100644 --- a/gcc/config/fr30/fr30.c +++ b/gcc/config/fr30/fr30.c @@ -48,12 +48,6 @@ /*}}}*/ /*{{{ Function Prologues & Epilogues */ -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ - -struct rtx_def * fr30_compare_op0; -struct rtx_def * fr30_compare_op1; - /* The FR30 stack looks like this: Before call After call diff --git a/gcc/config/fr30/fr30.h b/gcc/config/fr30/fr30.h index c1e8e0a9723..b958a678db4 100644 --- a/gcc/config/fr30/fr30.h +++ b/gcc/config/fr30/fr30.h @@ -1106,16 +1106,6 @@ fprintf (STREAM, "\t.word .L%d\n", VALUE) #endif /*}}}*/ -/*{{{ Exported variables */ - -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. Note that we can't use "rtx" here - since it hasn't been defined! */ - -extern struct rtx_def * fr30_compare_op0; -extern struct rtx_def * fr30_compare_op1; - -/*}}}*/ /* Local Variables: */ /* folded-file: t */ diff --git a/gcc/config/fr30/fr30.md b/gcc/config/fr30/fr30.md index a198ea3544d..fa115c4cfa1 100644 --- a/gcc/config/fr30/fr30.md +++ b/gcc/config/fr30/fr30.md @@ -916,23 +916,7 @@ ;;}}} ;;{{{ Comparisons -;; Note, we store the operands in the comparison insns, and use them later -;; when generating the branch or scc operation. - -;; First the routines called by the machine independent part of the compiler -(define_expand "cmpsi" - [(set (reg:CC 16) - (compare:CC (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "nonmemory_operand" "")))] - "" - "{ - fr30_compare_op0 = operands[0]; - fr30_compare_op1 = operands[1]; - DONE; - }" -) - -;; Now, the actual comparisons, generated by the branch and/or scc operations +;; The actual comparisons, generated by the cbranch and/or cstore expanders (define_insn "*cmpsi_internal" [(set (reg:CC 16) @@ -951,165 +935,19 @@ ;; Define_expands called by the machine independent part of the compiler ;; to allocate a new comparison register -(define_expand "beq" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (eq:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bne" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (ne:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "blt" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (lt:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "ble" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (le:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bgt" +(define_expand "cbranchsi4" [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) + (compare:CC (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" ""))) (set (pc) - (if_then_else (gt:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator:CC 0 "ordered_comparison_operator" + [(reg:CC 16) (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bge" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (ge:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bltu" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (ltu:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bleu" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (leu:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bgtu" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (gtu:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" ) -(define_expand "bgeu" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (geu:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) ;; Actual branches. We must allow for the (label_ref) and the (pc) to be ;; swapped. If they are swapped, it reverses the sense of the branch. diff --git a/gcc/config/frv/frv-protos.h b/gcc/config/frv/frv-protos.h index c34d02cf96f..98ada2286a5 100644 --- a/gcc/config/frv/frv-protos.h +++ b/gcc/config/frv/frv-protos.h @@ -81,8 +81,8 @@ extern const char *output_move_single (rtx *, rtx); extern const char *output_move_double (rtx *, rtx); extern const char *output_condmove_single (rtx *, rtx); -extern int frv_emit_cond_branch (enum rtx_code, rtx); -extern int frv_emit_scc (enum rtx_code, rtx); +extern int frv_emit_cond_branch (rtx *); +extern int frv_emit_scc (rtx *); extern rtx frv_split_scc (rtx, rtx, rtx, rtx, HOST_WIDE_INT); extern int frv_emit_cond_move (rtx, rtx, rtx, rtx); extern rtx frv_split_cond_move (rtx *); diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c index 4e8c1b24cf8..e5476523f13 100644 --- a/gcc/config/frv/frv.c +++ b/gcc/config/frv/frv.c @@ -193,11 +193,6 @@ typedef struct int base_offset; } frv_frame_accessor_t; -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ -rtx frv_compare_op0; -rtx frv_compare_op1; - /* Conditional execution support gathered together in one structure. */ typedef struct { @@ -4768,19 +4763,18 @@ frv_emit_comparison (enum rtx_code test, rtx op0, rtx op1) } -/* Emit code for a conditional branch. The comparison operands were previously - stored in frv_compare_op0 and frv_compare_op1. - +/* Emit code for a conditional branch. XXX: I originally wanted to add a clobber of a CCR register to use in conditional execution, but that confuses the rest of the compiler. */ int -frv_emit_cond_branch (enum rtx_code test, rtx label) +frv_emit_cond_branch (rtx operands[]) { rtx test_rtx; rtx label_ref; rtx if_else; - rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1); + enum rtx_code test = GET_CODE (operands[0]); + rtx cc_reg = frv_emit_comparison (test, operands[1], operands[2]); enum machine_mode cc_mode = GET_MODE (cc_reg); /* Branches generate: @@ -4788,7 +4782,7 @@ frv_emit_cond_branch (enum rtx_code test, rtx label) (if_then_else (, , (const_int 0)) (label_ref ) (pc))) */ - label_ref = gen_rtx_LABEL_REF (VOIDmode, label); + label_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]); test_rtx = gen_rtx_fmt_ee (test, cc_mode, cc_reg, const0_rtx); if_else = gen_rtx_IF_THEN_ELSE (cc_mode, test_rtx, label_ref, pc_rtx); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_else)); @@ -4796,23 +4790,23 @@ frv_emit_cond_branch (enum rtx_code test, rtx label) } -/* Emit code to set a gpr to 1/0 based on a comparison. The comparison - operands were previously stored in frv_compare_op0 and frv_compare_op1. */ +/* Emit code to set a gpr to 1/0 based on a comparison. */ int -frv_emit_scc (enum rtx_code test, rtx target) +frv_emit_scc (rtx operands[]) { rtx set; rtx test_rtx; rtx clobber; rtx cr_reg; - rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1); + enum rtx_code test = GET_CODE (operands[1]); + rtx cc_reg = frv_emit_comparison (test, operands[2], operands[3]); /* SCC instructions generate: (parallel [(set (, , (const_int 0)) (clobber ())]) */ test_rtx = gen_rtx_fmt_ee (test, SImode, cc_reg, const0_rtx); - set = gen_rtx_SET (VOIDmode, target, test_rtx); + set = gen_rtx_SET (VOIDmode, operands[0], test_rtx); cr_reg = ((TARGET_ALLOC_CC) ? gen_reg_rtx (CC_CCRmode) @@ -4874,7 +4868,8 @@ frv_emit_cond_move (rtx dest, rtx test_rtx, rtx src1, rtx src2) rtx cr_reg; rtx if_rtx; enum rtx_code test = GET_CODE (test_rtx); - rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1); + rtx cc_reg = frv_emit_comparison (test, + XEXP (test_rtx, 0), XEXP (test_rtx, 1)); enum machine_mode cc_mode = GET_MODE (cc_reg); /* Conditional move instructions generate: diff --git a/gcc/config/frv/frv.h b/gcc/config/frv/frv.h index b6fdca4aa0a..e510de08901 100644 --- a/gcc/config/frv/frv.h +++ b/gcc/config/frv/frv.h @@ -2913,9 +2913,6 @@ enum frv_builtins /* Enable prototypes on the call rtl functions. */ #define MD_CALL_PROTOTYPES 1 -extern GTY(()) rtx frv_compare_op0; /* operand save for */ -extern GTY(()) rtx frv_compare_op1; /* comparison generation */ - #define CPU_UNITS_QUERY 1 #ifdef __FRV_FDPIC__ diff --git a/gcc/config/frv/frv.md b/gcc/config/frv/frv.md index aadf02c4fbd..9315f9b623c 100644 --- a/gcc/config/frv/frv.md +++ b/gcc/config/frv/frv.md @@ -3734,59 +3734,7 @@ ;; :: ;; :::::::::::::::::::: -;; Note, we store the operands in the comparison insns, and use them later -;; when generating the branch or scc operation. - -;; First the routines called by the machine independent part of the compiler -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "integer_register_operand" "") - (match_operand:SI 1 "gpr_or_int10_operand" "")))] - "" - " -{ - frv_compare_op0 = operands[0]; - frv_compare_op1 = operands[1]; - DONE; -}") - -;(define_expand "cmpdi" -; [(set (cc0) -; (compare (match_operand:DI 0 "register_operand" "") -; (match_operand:DI 1 "nonmemory_operand" "")))] -; "" -; " -;{ -; frv_compare_op0 = operands[0]; -; frv_compare_op1 = operands[1]; -; DONE; -;}") - -(define_expand "cmpsf" - [(set (cc0) - (compare (match_operand:SF 0 "fpr_operand" "") - (match_operand:SF 1 "fpr_operand" "")))] - "TARGET_HARD_FLOAT" - " -{ - frv_compare_op0 = operands[0]; - frv_compare_op1 = operands[1]; - DONE; -}") - -(define_expand "cmpdf" - [(set (cc0) - (compare (match_operand:DF 0 "fpr_operand" "") - (match_operand:DF 1 "fpr_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE" - " -{ - frv_compare_op0 = operands[0]; - frv_compare_op1 = operands[1]; - DONE; -}") - -;; Now, the actual comparisons, generated by the branch and/or scc operations +;; The comparisons are generated by the branch and/or scc operations (define_insn "cmpsi_cc" [(set (match_operand:CC 0 "icc_operand" "=t,t") @@ -3847,137 +3795,31 @@ ;; :::::::::::::::::::: ;; Define_expands called by the machine independent part of the compiler -;; to allocate a new comparison register. Each of these named patterns -;; must be present, and they cannot be amalgamated into one pattern. -;; -;; If a fixed condition code register is being used, (as opposed to, say, -;; using cc0), then the expands should look like this: -;; -;; (define_expand "" -;; [(set (reg:CC ) -;; (compare:CC (match_dup 1) -;; (match_dup 2))) -;; (set (pc) -;; (if_then_else (eq:CC (reg:CC ) -;; (const_int 0)) -;; (label_ref (match_operand 0 "" "")) -;; (pc)))] -;; "" -;; "{ -;; operands[1] = frv_compare_op0; -;; operands[2] = frv_compare_op1; -;; }" -;; ) - -(define_expand "beq" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (EQ, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bne" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (NE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "blt" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (LT, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "ble" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (LE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bgt" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (GT, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bge" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (GE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bltu" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (LTU, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bleu" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (LEU, operands[0])) - FAIL; - - DONE; -}") +;; to allocate a new comparison register. -(define_expand "bgtu" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (GTU, operands[0])) - FAIL; +(define_expand "cbranchdf4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:DF 1 "fpr_operand" "") + (match_operand:DF 2 "fpr_operand" "")])) + (use (match_operand 3 ""))] + "TARGET_HARD_FLOAT && TARGET_DOUBLE" + { if (frv_emit_cond_branch (operands)) DONE; gcc_unreachable (); }) - DONE; -}") +(define_expand "cbranchsf4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:SF 1 "fpr_operand" "") + (match_operand:SF 2 "fpr_operand" "")])) + (use (match_operand 3 ""))] + "TARGET_HARD_FLOAT" + { if (frv_emit_cond_branch (operands)) DONE; gcc_unreachable (); }) -(define_expand "bgeu" - [(use (match_operand 0 "" ""))] +(define_expand "cbranchsi4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:SI 1 "integer_register_operand" "") + (match_operand:SI 2 "gpr_or_int10_operand" "")])) + (use (match_operand 3 ""))] "" - " -{ - if (! frv_emit_cond_branch (GEU, operands[0])) - FAIL; - - DONE; -}") + { if (frv_emit_cond_branch (operands)) DONE; gcc_unreachable (); }) ;; Actual branches. We must allow for the (label_ref) and the (pc) to be ;; swapped. If they are swapped, it reverses the sense of the branch. @@ -4142,115 +3984,29 @@ ;; Define_expands called by the machine independent part of the compiler ;; to allocate a new comparison register -(define_expand "seq" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (EQ, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sne" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (NE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "slt" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (LT, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sle" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (LE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sgt" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (GT, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sge" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (GE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sltu" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (LTU, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sleu" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (LEU, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sgtu" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (GTU, operands[0])) - FAIL; - - DONE; -}") +(define_expand "cstoredf4" + [(use (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:DF 2 "fpr_operand") + (match_operand:DF 3 "fpr_operand")])) + (clobber (match_operand:SI 0 "register_operand"))] + "TARGET_HARD_FLOAT && TARGET_DOUBLE" + { if (frv_emit_scc (operands)) DONE; else FAIL; }) -(define_expand "sgeu" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (GEU, operands[0])) - FAIL; +(define_expand "cstoresf4" + [(use (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SF 2 "fpr_operand") + (match_operand:SF 3 "fpr_operand")])) + (clobber (match_operand:SI 0 "register_operand"))] + "TARGET_HARD_FLOAT" + { if (frv_emit_scc (operands)) DONE; else FAIL; }) - DONE; -}") +(define_expand "cstoresi4" + [(use (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SI 2 "integer_register_operand") + (match_operand:SI 3 "gpr_or_int10_operand")])) + (clobber (match_operand:SI 0 "register_operand"))] + "" + { if (frv_emit_scc (operands)) DONE; else FAIL; }) (define_insn "*scc_int" [(set (match_operand:SI 0 "integer_register_operand" "=d") diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h index 2e7b72fe6c4..4a0b64790a7 100644 --- a/gcc/config/h8300/h8300-protos.h +++ b/gcc/config/h8300/h8300-protos.h @@ -44,7 +44,8 @@ extern const char *output_logical_op (enum machine_mode, rtx *); extern unsigned int compute_logical_op_length (enum machine_mode, rtx *); extern int compute_logical_op_cc (enum machine_mode, rtx *); -extern void h8300_expand_branch (enum rtx_code, rtx); +extern void h8300_expand_branch (rtx[]); +extern void h8300_expand_store (rtx[]); extern bool expand_a_shift (enum machine_mode, int, rtx[]); extern int h8300_shift_needs_scratch_p (int, enum machine_mode); extern int expand_a_rotate (rtx[]); diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index 34d1f82687c..9946d28078f 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -1226,6 +1226,11 @@ h8300_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed) *total = 20; return true; + case COMPARE: + if (XEXP (x, 1) == const0_rtx) + *total = 0; + return false; + case AND: if (!h8300_dst_operand (XEXP (x, 0), VOIDmode) || !h8300_src_operand (XEXP (x, 1), VOIDmode)) @@ -3503,16 +3508,42 @@ compute_logical_op_cc (enum machine_mode mode, rtx *operands) /* Expand a conditional branch. */ void -h8300_expand_branch (enum rtx_code code, rtx label) +h8300_expand_branch (rtx operands[]) { + enum rtx_code code = GET_CODE (operands[0]); + rtx op0 = operands[1]; + rtx op1 = operands[2]; + rtx label = operands[3]; rtx tmp; + tmp = gen_rtx_COMPARE (VOIDmode, op0, op1); + emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, tmp)); + tmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx); tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, gen_rtx_LABEL_REF (VOIDmode, label), pc_rtx); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); } + + +/* Expand a conditional store. */ + +void +h8300_expand_store (rtx operands[]) +{ + rtx dest = operands[0]; + enum rtx_code code = GET_CODE (operands[1]); + rtx op0 = operands[2]; + rtx op1 = operands[3]; + rtx tmp; + + tmp = gen_rtx_COMPARE (VOIDmode, op0, op1); + emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, tmp)); + + tmp = gen_rtx_fmt_ee (code, GET_MODE (dest), cc0_rtx, const0_rtx); + emit_insn (gen_rtx_SET (VOIDmode, dest, tmp)); +} /* Shifts. diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index 61f876c8399..c05e8c6966f 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -961,28 +961,33 @@ ;; ---------------------------------------------------------------------- (define_insn "" - [(set (cc0) (zero_extract:HI (match_operand:QI 0 "bit_memory_operand" "r,U") - (const_int 1) - (match_operand 1 "const_int_operand" "n,n")))] + [(set (cc0) (compare + (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "r,U") + (const_int 1) + (match_operand 1 "const_int_operand" "n,n")) + (const_int 0)))] "TARGET_H8300" "btst %Z1,%Y0" [(set_attr "length" "2,4") (set_attr "cc" "set_zn,set_zn")]) (define_insn "" - [(set (cc0) (zero_extract:HI (match_operand:HI 0 "register_operand" "r") - (const_int 1) - (match_operand 1 "const_int_operand" "n")))] + [(set (cc0) (compare + (zero_extract:HI (match_operand:HI 0 "register_operand" "r") + (const_int 1) + (match_operand 1 "const_int_operand" "n")) + (const_int 0)))] "TARGET_H8300" "btst %Z1,%Y0" [(set_attr "length" "2") (set_attr "cc" "set_zn")]) (define_insn_and_split "*tst_extzv_1_n" - [(set (cc0) - (zero_extract:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>") - (const_int 1) - (match_operand 1 "const_int_operand" "n,n,n"))) + [(set (cc0) (compare + (zero_extract:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>") + (const_int 1) + (match_operand 1 "const_int_operand" "n,n,n")) + (const_int 0))) (clobber (match_scratch:QI 2 "=X,X,&r"))] "(TARGET_H8300H || TARGET_H8300S)" "@ @@ -993,18 +998,20 @@ && !OK_FOR_U (operands[0])" [(set (match_dup 2) (match_dup 0)) - (parallel [(set (cc0) (zero_extract:SI (match_dup 2) - (const_int 1) - (match_dup 1))) + (parallel [(set (cc0) (compare (zero_extract:SI (match_dup 2) + (const_int 1) + (match_dup 1)) + (const_int 0))) (clobber (scratch:QI))])] "" [(set_attr "length" "2,8,10") (set_attr "cc" "set_zn,set_zn,set_zn")]) (define_insn "" - [(set (cc0) (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand 1 "const_int_operand" "n")))] + [(set (cc0) (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r") + (const_int 1) + (match_operand 1 "const_int_operand" "n")) + (const_int 0)))] "(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[1]) <= 15" "btst %Z1,%Y0" @@ -1012,10 +1019,10 @@ (set_attr "cc" "set_zn")]) (define_insn_and_split "*tstsi_upper_bit" - [(set (cc0) - (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand 1 "const_int_operand" "n"))) + [(set (cc0) (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r") + (const_int 1) + (match_operand 1 "const_int_operand" "n")) + (const_int 0))) (clobber (match_scratch:SI 2 "=&r"))] "(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[1]) >= 16" @@ -1026,18 +1033,18 @@ (const_int -65536)) (lshiftrt:SI (match_dup 0) (const_int 16)))) - (set (cc0) - (zero_extract:SI (match_dup 2) - (const_int 1) - (match_dup 3)))] + (set (cc0) (compare (zero_extract:SI (match_dup 2) + (const_int 1) + (match_dup 3)) + (const_int 0)))] "operands[3] = GEN_INT (INTVAL (operands[1]) - 16);") (define_insn "*tstsi_variable_bit" - [(set (cc0) - (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (and:SI (match_operand:SI 1 "register_operand" "r") - (const_int 7))))] + [(set (cc0) (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r") + (const_int 1) + (and:SI (match_operand:SI 1 "register_operand" "r") + (const_int 7))) + (const_int 0)))] "TARGET_H8300H || TARGET_H8300S" "btst %w1,%w0" [(set_attr "length" "2") @@ -1045,10 +1052,12 @@ (define_insn_and_split "*tstsi_variable_bit_qi" [(set (cc0) - (zero_extract:SI (zero_extend:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>")) - (const_int 1) - (and:SI (match_operand:SI 1 "register_operand" "r,r,r") - (const_int 7)))) + (compare + (zero_extract:SI (zero_extend:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>")) + (const_int 1) + (and:SI (match_operand:SI 1 "register_operand" "r,r,r") + (const_int 7))) + (const_int 0))) (clobber (match_scratch:QI 2 "=X,X,&r"))] "(TARGET_H8300H || TARGET_H8300S)" "@ @@ -1059,55 +1068,59 @@ && !OK_FOR_U (operands[0])" [(set (match_dup 2) (match_dup 0)) - (parallel [(set (cc0) (zero_extract:SI (zero_extend:SI (match_dup 2)) - (const_int 1) - (and:SI (match_dup 1) - (const_int 7)))) + (parallel [(set (cc0) (compare (zero_extract:SI (zero_extend:SI (match_dup 2)) + (const_int 1) + (and:SI (match_dup 1) + (const_int 7))) + (const_int 0))) (clobber (scratch:QI))])] "" [(set_attr "length" "2,8,10") (set_attr "cc" "set_zn,set_zn,set_zn")]) -(define_insn "tstqi" - [(set (cc0) (match_operand:QI 0 "register_operand" "r"))] +(define_insn "*tstqi" + [(set (cc0) (compare (match_operand:QI 0 "register_operand" "r") + (const_int 0)))] "" "mov.b %X0,%X0" [(set_attr "length" "2") (set_attr "cc" "set_znv")]) -(define_insn "tsthi" - [(set (cc0) (match_operand:HI 0 "register_operand" "r"))] +(define_insn "*tsthi" + [(set (cc0) (compare (match_operand:HI 0 "register_operand" "r") + (const_int 0)))] "" "mov.w %T0,%T0" [(set_attr "length" "2") (set_attr "cc" "set_znv")]) (define_insn "*tsthi_upper" - [(set (cc0) - (and:HI (match_operand:HI 0 "register_operand" "r") - (const_int -256)))] + [(set (cc0) (compare (and:HI (match_operand:HI 0 "register_operand" "r") + (const_int -256)) + (const_int 0)))] "" "mov.b %t0,%t0" [(set_attr "length" "2") (set_attr "cc" "set_znv")]) -(define_insn "tstsi" - [(set (cc0) (match_operand:SI 0 "register_operand" "r"))] +(define_insn "*tstsi" + [(set (cc0) (compare (match_operand:SI 0 "register_operand" "r") + (const_int 0)))] "TARGET_H8300H || TARGET_H8300S" "mov.l %S0,%S0" [(set_attr "length" "2") (set_attr "cc" "set_znv")]) (define_insn "*tstsi_upper" - [(set (cc0) - (and:SI (match_operand:SI 0 "register_operand" "r") - (const_int -65536)))] + [(set (cc0) (compare (and:SI (match_operand:SI 0 "register_operand" "r") + (const_int -65536)) + (const_int 0)))] "" "mov.w %e0,%e0" [(set_attr "length" "2") (set_attr "cc" "set_znv")]) -(define_insn "cmpqi" +(define_insn "*cmpqi" [(set (cc0) (compare (match_operand:QI 0 "h8300_dst_operand" "rQ") (match_operand:QI 1 "h8300_src_operand" "rQi")))] @@ -1116,19 +1129,6 @@ [(set_attr "length_table" "addb") (set_attr "cc" "compare")]) -(define_expand "cmphi" - [(set (cc0) - (compare (match_operand:HI 0 "h8300_dst_operand" "") - (match_operand:HI 1 "h8300_src_operand" "")))] - "" - " -{ - /* Force operand1 into a register if we're compiling - for the H8/300. */ - if (GET_CODE (operands[1]) != REG && TARGET_H8300) - operands[1] = force_reg (HImode, operands[1]); -}") - (define_insn "*cmphi_h8300_znvc" [(set (cc0) (compare (match_operand:HI 0 "register_operand" "r") @@ -2155,55 +2155,37 @@ ;; Conditional jump instructions -(define_expand "ble" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (LE, operands[0]); DONE;") - -(define_expand "bleu" - [(match_operand 0 "" "")] +(define_expand "cbranchqi4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:QI 1 "h8300_dst_operand" "") + (match_operand:QI 2 "h8300_src_operand" "")])) + (use (match_operand 3 ""))] "" - "h8300_expand_branch (LEU, operands[0]); DONE;") + "h8300_expand_branch (operands); DONE;") -(define_expand "bge" - [(match_operand 0 "" "")] +(define_expand "cbranchhi4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:HI 1 "h8300_dst_operand" "") + (match_operand:HI 2 "h8300_src_operand" "")])) + (use (match_operand 3 ""))] "" - "h8300_expand_branch (GE, operands[0]); DONE;") - -(define_expand "bgeu" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (GEU, operands[0]); DONE;") - -(define_expand "blt" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (LT, operands[0]); DONE;") - -(define_expand "bltu" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (LTU, operands[0]); DONE;") - -(define_expand "bgt" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (GT, operands[0]); DONE;") - -(define_expand "bgtu" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (GTU, operands[0]); DONE;") - -(define_expand "beq" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (EQ, operands[0]); DONE;") + " +{ + /* Force operand1 into a register if we're compiling + for the H8/300. */ + if ((GET_CODE (operands[2]) != REG && operands[2] != const0_rtx) + && TARGET_H8300) + operands[2] = force_reg (HImode, operands[2]); + h8300_expand_branch (operands); DONE; +}") -(define_expand "bne" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (NE, operands[0]); DONE;") +(define_expand "cbranchsi4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:SI 1 "h8300_dst_operand" "") + (match_operand:SI 2 "h8300_src_operand" "")])) + (use (match_operand 3 ""))] + "TARGET_H8300H || TARGET_H8300S" + "h8300_expand_branch (operands); DONE;") (define_insn "branch_true" [(set (pc) @@ -3019,8 +3001,8 @@ (clobber (match_operand:QI 3 "register_operand" ""))] "epilogue_completed && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))" - [(set (cc0) - (match_dup 1)) + [(set (cc0) (compare (match_dup 1) + (const_int 0))) (set (pc) (if_then_else (le (cc0) (const_int 0)) (label_ref (match_dup 5)) @@ -3032,8 +3014,8 @@ (clobber (scratch:QI))]) (set (match_dup 1) (plus:QI (match_dup 1) (const_int -1))) - (set (cc0) - (match_dup 1)) + (set (cc0) (compare (match_dup 1) + (const_int 0))) (set (pc) (if_then_else (ne (cc0) (const_int 0)) (label_ref (match_dup 4)) @@ -3052,8 +3034,8 @@ && !find_regno_note (insn, REG_DEAD, REGNO (operands[1]))" [(set (match_dup 3) (match_dup 1)) - (set (cc0) - (match_dup 3)) + (set (cc0) (compare (match_dup 3) + (const_int 0))) (set (pc) (if_then_else (le (cc0) (const_int 0)) (label_ref (match_dup 5)) @@ -3065,8 +3047,8 @@ (clobber (scratch:QI))]) (set (match_dup 3) (plus:QI (match_dup 3) (const_int -1))) - (set (cc0) - (match_dup 3)) + (set (cc0) (compare (match_dup 3) + (const_int 0))) (set (pc) (if_then_else (ne (cc0) (const_int 0)) (label_ref (match_dup 4)) @@ -3413,17 +3395,29 @@ [(set_attr "cc" "none_0hit") (set_attr "length_table" "bitfield")]) -(define_expand "seq" - [(set (match_operand:HI 0 "register_operand" "") - (eq:HI (cc0) (const_int 0)))] +(define_expand "cstoreqi4" + [(use (match_operator 1 "eqne_operator" + [(match_operand:QI 2 "h8300_dst_operand" "") + (match_operand:QI 3 "h8300_src_operand" "")])) + (clobber (match_operand:HI 0 "register_operand"))] "TARGET_H8300SX" - "") + "h8300_expand_store (operands); DONE;") -(define_expand "sne" - [(set (match_operand:HI 0 "register_operand" "") - (ne:HI (cc0) (const_int 0)))] +(define_expand "cstorehi4" + [(use (match_operator 1 "eqne_operator" + [(match_operand:HI 2 "h8300_dst_operand" "") + (match_operand:HI 3 "h8300_src_operand" "")])) + (clobber (match_operand:HI 0 "register_operand"))] "TARGET_H8300SX" - "") + "h8300_expand_store (operands); DONE;") + +(define_expand "cstoresi4" + [(use (match_operator 1 "eqne_operator" + [(match_operand:SI 2 "h8300_dst_operand" "") + (match_operand:SI 3 "h8300_src_operand" "")])) + (clobber (match_operand:HI 0 "register_operand"))] + "TARGET_H8300SX" + "h8300_expand_store (operands); DONE;") (define_insn "*bstzhireg" [(set (match_operand:HI 0 "register_operand" "=r") @@ -3451,13 +3445,7 @@ [(set (cc0) (match_dup 5)) (set (zero_extract:QI (match_dup 0) (const_int 1) (match_dup 1)) (match_op_dup:QI 2 [(cc0) (const_int 0)]))] - " -{ - if (operands[4] == const0_rtx && GET_CODE (operands[3]) == REG) - operands[5] = operands[3]; - else - operands[5] = gen_rtx_COMPARE (VOIDmode, operands[3], operands[4]); -}" + "operands[5] = gen_rtx_COMPARE (VOIDmode, operands[3], operands[4]);" [(set_attr "cc" "set_znv,compare")]) (define_insn "*bstz" @@ -3499,13 +3487,7 @@ (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) (ior:QI (match_dup 4) (match_dup 5)) (match_dup 4)))] - " -{ - if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG) - operands[6] = operands[2]; - else - operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); -}" + "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);" [(set_attr "cc" "set_znv,compare")]) (define_insn "*condbset" @@ -3541,13 +3523,7 @@ (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) (and:QI (match_dup 4) (match_dup 5)) (match_dup 4)))] - " -{ - if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG) - operands[6] = operands[2]; - else - operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); -}" + "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);" [(set_attr "cc" "set_znv,compare")]) (define_insn "*condbclr" @@ -3587,13 +3563,7 @@ (ashift:QI (const_int 1) (match_operand:QI 5 "register_operand" "r,r"))) (match_dup 4)))] - " -{ - if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG) - operands[6] = operands[2]; - else - operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); -}" + "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);" [(set_attr "cc" "set_znv,compare")]) (define_insn "*condbsetreg" @@ -3634,13 +3604,7 @@ (ashift:QI (const_int 1) (match_operand:QI 5 "register_operand" "r,r"))) (match_dup 4)))] - " -{ - if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG) - operands[6] = operands[2]; - else - operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); -}" + "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);" [(set_attr "cc" "set_znv,compare")]) (define_insn "*condbclrreg" @@ -3878,10 +3842,10 @@ "(TARGET_H8300H || TARGET_H8300S)" "#" "&& reload_completed" - [(set (cc0) - (zero_extract:SI (match_dup 1) - (const_int 1) - (const_int 0))) + [(set (cc0) (compare (zero_extract:SI (match_dup 1) + (const_int 1) + (const_int 0)) + (const_int 0))) (set (pc) (if_then_else (eq (cc0) (const_int 0)) @@ -3901,10 +3865,10 @@ "(TARGET_H8300H || TARGET_H8300S)" "#" "&& reload_completed" - [(set (cc0) - (zero_extract:SI (match_dup 1) - (const_int 1) - (const_int 0))) + [(set (cc0) (compare (zero_extract:SI (match_dup 1) + (const_int 1) + (const_int 0)) + (const_int 0))) (set (pc) (if_then_else (ne (cc0) (const_int 0)) @@ -4398,8 +4362,8 @@ "" "#" "" - [(set (cc0) - (match_dup 0)) + [(set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (ge (cc0) (const_int 0)) @@ -4418,8 +4382,8 @@ "" "#" "" - [(set (cc0) - (match_dup 0)) + [(set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (lt (cc0) (const_int 0)) @@ -4852,8 +4816,8 @@ [(set (match_operand:HI 0 "register_operand" "") (plus:HI (match_dup 0) (match_operand 1 "incdec_operand" ""))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_operator 3 "eqne_operator" [(cc0) (const_int 0)]) @@ -4864,8 +4828,8 @@ (unspec:HI [(match_dup 0) (match_dup 1)] UNSPEC_INCDEC)) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -4878,8 +4842,8 @@ [(set (match_operand:SI 0 "register_operand" "") (plus:SI (match_dup 0) (match_operand 1 "incdec_operand" ""))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_operator 3 "eqne_operator" [(cc0) (const_int 0)]) @@ -4890,8 +4854,8 @@ (unspec:SI [(match_dup 0) (match_dup 1)] UNSPEC_INCDEC)) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -4900,9 +4864,10 @@ (define_peephole2 [(parallel [(set (cc0) - (zero_extract:SI (match_operand:QI 0 "register_operand" "") - (const_int 1) - (const_int 7))) + (compare (zero_extract:SI (match_operand:QI 0 "register_operand" "") + (const_int 1) + (const_int 7)) + (const_int 0))) (clobber (scratch:QI))]) (set (pc) (if_then_else (match_operator 1 "eqne_operator" @@ -4910,8 +4875,8 @@ (label_ref (match_operand 2 "" "")) (pc)))] "(TARGET_H8300H || TARGET_H8300S)" - [(set (cc0) - (match_dup 0)) + [(set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5032,6 +4997,45 @@ "operands[3] = gen_lowpart (HImode, operands[0]); operands[4] = gen_lowpart (HImode, operands[1]);") +;; Convert a memory comparison to a move if there is a scratch register. + +(define_peephole2 + [(match_scratch:QI 1 "r") + (set (cc0) + (compare (match_operand:QI 0 "memory_operand" "") + (const_int 0)))] + "" + [(set (match_dup 1) + (match_dup 0)) + (set (cc0) (compare (match_dup 1) + (const_int 0)))] + "") + +(define_peephole2 + [(match_scratch:HI 1 "r") + (set (cc0) + (compare (match_operand:HI 0 "memory_operand" "") + (const_int 0)))] + "(TARGET_H8300H || TARGET_H8300S)" + [(set (match_dup 1) + (match_dup 0)) + (set (cc0) (compare (match_dup 1) + (const_int 0)))] + "") + +(define_peephole2 + [(match_scratch:SI 1 "r") + (set (cc0) + (compare (match_operand:SI 0 "memory_operand" "") + (const_int 0)))] + "(TARGET_H8300H || TARGET_H8300S)" + [(set (match_dup 1) + (match_dup 0)) + (set (cc0) (compare (match_dup 1) + (const_int 0)))] + "") + + ;; (compare (reg:HI) (const_int)) takes 4 bytes, so we try to achieve ;; the equivalent with shorter sequences. Here is the summary. Cases ;; are grouped for each define_peephole2. @@ -5073,13 +5077,14 @@ (label_ref (match_operand 2 "" "")) (pc)))] "(TARGET_H8300H || TARGET_H8300S) + && INTVAL (operands[1]) != 0 && peep2_reg_dead_p (1, operands[0])" [(set (match_dup 0) (unspec:HI [(match_dup 0) (match_dup 4)] UNSPEC_INCDEC)) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5113,8 +5118,8 @@ (ashiftrt:HI (match_dup 0) (match_dup 4))) (clobber (scratch:QI))]) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_dup 2) (label_ref (match_dup 3)) @@ -5148,8 +5153,8 @@ (ashiftrt:HI (match_dup 0) (match_dup 4))) (clobber (scratch:QI))]) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_dup 5) (label_ref (match_dup 3)) @@ -5182,9 +5187,9 @@ (label_ref (match_operand 2 "" "")) (pc)))] "TARGET_H8300H || TARGET_H8300S" - [(set (cc0) - (and:HI (match_dup 0) - (const_int -256))) + [(set (cc0) (compare (and:HI (match_dup 0) + (const_int -256)) + (const_int 0))) (set (pc) (if_then_else (match_dup 1) (label_ref (match_dup 2)) @@ -5211,9 +5216,9 @@ (label_ref (match_operand 2 "" "")) (pc)))] "TARGET_H8300H || TARGET_H8300S" - [(set (cc0) - (and:HI (match_dup 0) - (const_int -256))) + [(set (cc0) (compare (and:HI (match_dup 0) + (const_int -256)) + (const_int 0))) (set (pc) (if_then_else (match_dup 3) (label_ref (match_dup 2)) @@ -5307,13 +5312,14 @@ (label_ref (match_operand 2 "" "")) (pc)))] "(TARGET_H8300H || TARGET_H8300S) + && INTVAL (operands[1]) != 0 && peep2_reg_dead_p (1, operands[0])" [(set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 4)] UNSPEC_INCDEC)) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5348,8 +5354,8 @@ [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5381,13 +5387,14 @@ && ((INTVAL (operands[1]) & 0x00ff) == INTVAL (operands[1]) || (INTVAL (operands[1]) & 0xff00) == INTVAL (operands[1]) || INTVAL (operands[1]) == 0x0000ffff) + && INTVAL (operands[1]) != 0 && INTVAL (operands[1]) != 1 && INTVAL (operands[1]) != 2" [(set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5425,8 +5432,8 @@ (match_dup 4))) (set (match_dup 0) (not:SI (match_dup 0))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5464,8 +5471,8 @@ (unspec:SI [(match_dup 0) (const_int -1)] UNSPEC_INCDEC)) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5507,8 +5514,8 @@ (ashiftrt:SI (match_dup 4) (match_dup 5))) (clobber (scratch:QI))]) - (set (cc0) - (match_dup 4)) + (set (cc0) (compare (match_dup 4) + (const_int 0))) (set (pc) (if_then_else (match_dup 2) (label_ref (match_dup 3)) @@ -5550,8 +5557,8 @@ (ashiftrt:SI (match_dup 4) (match_dup 5))) (clobber (scratch:QI))]) - (set (cc0) - (match_dup 4)) + (set (cc0) (compare (match_dup 4) + (const_int 0))) (set (pc) (if_then_else (match_dup 6) (label_ref (match_dup 3)) @@ -5591,8 +5598,8 @@ (ashiftrt:SI (match_dup 0) (match_dup 4))) (clobber (scratch:QI))]) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_dup 2) (label_ref (match_dup 3)) @@ -5626,8 +5633,8 @@ (ashiftrt:SI (match_dup 0) (match_dup 4))) (clobber (scratch:QI))]) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_dup 5) (label_ref (match_dup 3)) @@ -5672,8 +5679,8 @@ [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 4))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_dup 2) (label_ref (match_dup 3)) @@ -5712,8 +5719,8 @@ [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 4))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_dup 5) (label_ref (match_dup 3)) @@ -5746,9 +5753,9 @@ (label_ref (match_operand 2 "" "")) (pc)))] "TARGET_H8300H || TARGET_H8300S" - [(set (cc0) - (and:SI (match_dup 0) - (const_int -65536))) + [(set (cc0) (compare (and:SI (match_dup 0) + (const_int -65536)) + (const_int 0))) (set (pc) (if_then_else (match_dup 1) (label_ref (match_dup 2)) @@ -5775,9 +5782,9 @@ (label_ref (match_operand 2 "" "")) (pc)))] "TARGET_H8300H || TARGET_H8300S" - [(set (cc0) - (and:SI (match_dup 0) - (const_int -65536))) + [(set (cc0) (compare (and:SI (match_dup 0) + (const_int -65536)) + (const_int 0))) (set (pc) (if_then_else (match_dup 3) (label_ref (match_dup 2)) @@ -5814,6 +5821,7 @@ (label_ref (match_operand 2 "" "")) (pc)))] "(TARGET_H8300H || TARGET_H8300S) + && INTVAL (operands[1]) != 0 && !peep2_reg_dead_p (1, operands[0]) && !same_cmp_following_p (insn)" [(set (match_dup 4) @@ -5822,8 +5830,8 @@ (unspec:SI [(match_dup 4) (match_dup 5)] UNSPEC_INCDEC)) - (set (cc0) - (match_dup 4)) + (set (cc0) (compare (match_dup 4) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5836,8 +5844,8 @@ [(set (match_operand:HI 0 "register_operand" "") (and:HI (match_dup 0) (match_operand:HI 1 "const_int_qi_operand" ""))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_operator 3 "eqne_operator" [(cc0) (const_int 0)]) @@ -5847,8 +5855,8 @@ [(set (match_dup 4) (and:QI (match_dup 4) (match_dup 5))) - (set (cc0) - (match_dup 4)) + (set (cc0) (compare (match_dup 4) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5860,8 +5868,8 @@ [(set (match_operand:SI 0 "register_operand" "") (and:SI (match_dup 0) (match_operand:SI 1 "const_int_qi_operand" ""))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_operator 3 "eqne_operator" [(cc0) (const_int 0)]) @@ -5871,8 +5879,8 @@ [(set (match_dup 4) (and:QI (match_dup 4) (match_dup 5))) - (set (cc0) - (match_dup 4)) + (set (cc0) (compare (match_dup 4) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5884,8 +5892,8 @@ [(set (match_operand:SI 0 "register_operand" "") (and:SI (match_dup 0) (match_operand:SI 1 "const_int_hi_operand" ""))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_operator 3 "eqne_operator" [(cc0) (const_int 0)]) @@ -5895,8 +5903,8 @@ [(set (match_dup 4) (and:HI (match_dup 4) (match_dup 5))) - (set (cc0) - (match_dup 4)) + (set (cc0) (compare (match_dup 4) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5911,8 +5919,8 @@ (set (match_dup 0) (xor:SI (match_dup 0) (match_operand:SI 2 "const_int_qi_operand" ""))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_operator 4 "eqne_operator" [(cc0) (const_int 0)]) @@ -5926,8 +5934,8 @@ (set (match_dup 5) (xor:QI (match_dup 5) (match_dup 7))) - (set (cc0) - (match_dup 5)) + (set (cc0) (compare (match_dup 5) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 4 [(cc0) (const_int 0)]) (label_ref (match_dup 3)) @@ -6088,7 +6096,8 @@ (match_operand 2 "h8300_src_operand" "")))] "TARGET_H8300SX && peep2_reg_dead_p (2, operands[0]) - && !reg_overlap_mentioned_p (operands[0], operands[2])" + && !reg_overlap_mentioned_p (operands[0], operands[2]) + && operands[2] != const0_rtx" [(set (cc0) (compare (match_dup 1) (match_dup 2)))]) diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 803a9da7ca3..9452d2a60ec 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -106,7 +106,7 @@ extern int ix86_match_ccmode (rtx, enum machine_mode); extern rtx ix86_expand_compare (enum rtx_code, rtx *, rtx *); extern int ix86_use_fcomi_compare (enum rtx_code); extern void ix86_expand_branch (enum rtx_code, rtx); -extern int ix86_expand_setcc (enum rtx_code, rtx); +extern void ix86_expand_setcc (enum rtx_code, rtx); extern int ix86_expand_int_movcc (rtx[]); extern int ix86_expand_fp_movcc (rtx[]); extern bool ix86_expand_fp_vcond (rtx[]); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index aefb891ff5b..bb013a144f6 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -14947,15 +14947,12 @@ ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2, emit_label (label); } -int +void ix86_expand_setcc (enum rtx_code code, rtx dest) { rtx ret, tmp, tmpreg, equiv; rtx second_test, bypass_test; - if (GET_MODE (ix86_compare_op0) == (TARGET_64BIT ? TImode : DImode)) - return 0; /* FAIL */ - gcc_assert (GET_MODE (dest) == QImode); ret = ix86_expand_compare (code, &second_test, &bypass_test); @@ -14994,8 +14991,6 @@ ix86_expand_setcc (enum rtx_code code, rtx dest) ix86_compare_op0, ix86_compare_op1); set_unique_reg_note (get_last_insn (), REG_EQUAL, equiv); } - - return 1; /* DONE */ } /* Expand comparison setting or clearing carry flag. Return true when @@ -15143,6 +15138,8 @@ ix86_expand_int_movcc (rtx operands[]) bool sign_bit_compare_p = false;; start_sequence (); + ix86_compare_op0 = XEXP (operands[1], 0); + ix86_compare_op1 = XEXP (operands[1], 1); compare_op = ix86_expand_compare (code, &second_test, &bypass_test); compare_seq = get_insns (); end_sequence (); @@ -15860,6 +15857,8 @@ ix86_expand_fp_movcc (rtx operands[]) enum rtx_code code = GET_CODE (operands[1]); rtx tmp, compare_op, second_test, bypass_test; + ix86_compare_op0 = XEXP (operands[1], 0); + ix86_compare_op1 = XEXP (operands[1], 1); if (TARGET_SSE_MATH && SSE_FLOAT_MODE_P (mode)) { enum machine_mode cmode; @@ -16387,6 +16386,8 @@ ix86_expand_int_addcc (rtx operands[]) bool fpcmp = false; enum machine_mode mode = GET_MODE (operands[0]); + ix86_compare_op0 = XEXP (operands[1], 0); + ix86_compare_op1 = XEXP (operands[1], 1); if (operands[3] != const1_rtx && operands[3] != constm1_rtx) return 0; @@ -28870,13 +28871,14 @@ void ix86_emit_i387_log1p (rtx op0, rtx op1) rtx tmp = gen_reg_rtx (XFmode); rtx tmp2 = gen_reg_rtx (XFmode); + rtx test; emit_insn (gen_absxf2 (tmp, op1)); - emit_insn (gen_cmpxf (tmp, + test = gen_rtx_GE (VOIDmode, tmp, CONST_DOUBLE_FROM_REAL_VALUE ( REAL_VALUE_ATOF ("0.29289321881345247561810596348408353", XFmode), - XFmode))); - emit_jump_insn (gen_bge (label1)); + XFmode)); + emit_jump_insn (gen_cbranchxf4 (test, XEXP (test, 0), XEXP (test, 1), label1)); emit_move_insn (tmp2, standard_80387_constant_rtx (4)); /* fldln2 */ emit_insn (gen_fyl2xp1xf3_i387 (op0, op1, tmp2)); diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 1bb96fd07db..198b59d2e47 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -759,77 +759,183 @@ (include "constraints.md") -;; Compare instructions. +;; Compare and branch/compare and store instructions. -;; All compare insns have expanders that save the operands away without -;; actually generating RTL. The bCOND or sCOND (emitted immediately -;; after the cmp) will actually emit the cmpM. +(define_expand "cbranchti4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:TI 1 "nonimmediate_operand" "") + (match_operand:TI 2 "x86_64_general_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_64BIT" +{ + if (MEM_P (operands[1]) && MEM_P (operands[2])) + operands[1] = force_reg (TImode, operands[1]); + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) -(define_expand "cmpti" +(define_expand "cbranchdi4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:TI 0 "nonimmediate_operand" "") - (match_operand:TI 1 "x86_64_general_operand" "")))] + (compare:CC (match_operand:DI 1 "nonimmediate_operand" "") + (match_operand:DI 2 "x86_64_general_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" +{ + if (MEM_P (operands[1]) && MEM_P (operands[2])) + operands[1] = force_reg (DImode, operands[1]); + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) + +(define_expand "cstoredi4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:DI 2 "nonimmediate_operand" "") + (match_operand:DI 3 "x86_64_general_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] "TARGET_64BIT" { - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (TImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + if (MEM_P (operands[2]) && MEM_P (operands[3])) + operands[2] = force_reg (DImode, operands[2]); + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) -(define_expand "cmpdi" +(define_expand "cbranchsi4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "x86_64_general_operand" "")))] + (compare:CC (match_operand:SI 1 "cmpsi_operand" "") + (match_operand:SI 2 "general_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" { - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (DImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + if (MEM_P (operands[1]) && MEM_P (operands[2])) + operands[1] = force_reg (SImode, operands[1]); + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); DONE; }) -(define_expand "cmpsi" +(define_expand "cstoresi4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:SI 0 "cmpsi_operand" "") - (match_operand:SI 1 "general_operand" "")))] + (compare:CC (match_operand:SI 2 "cmpsi_operand" "") + (match_operand:SI 3 "general_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] "" { - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (SImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + if (MEM_P (operands[2]) && MEM_P (operands[3])) + operands[2] = force_reg (SImode, operands[2]); + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) -(define_expand "cmphi" +(define_expand "cbranchhi4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:HI 0 "nonimmediate_operand" "") - (match_operand:HI 1 "general_operand" "")))] + (compare:CC (match_operand:HI 1 "nonimmediate_operand" "") + (match_operand:HI 2 "general_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" { - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (HImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + if (MEM_P (operands[1]) && MEM_P (operands[2])) + operands[1] = force_reg (HImode, operands[1]); + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); DONE; }) -(define_expand "cmpqi" +(define_expand "cstorehi4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" "")))] - "TARGET_QIMODE_MATH" + (compare:CC (match_operand:HI 2 "nonimmediate_operand" "") + (match_operand:HI 3 "general_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] + "" { - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (QImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + if (MEM_P (operands[2]) && MEM_P (operands[3])) + operands[2] = force_reg (HImode, operands[2]); + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); + DONE; +}) + + +(define_expand "cbranchqi4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:QI 1 "nonimmediate_operand" "") + (match_operand:QI 2 "general_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" +{ + if (MEM_P (operands[1]) && MEM_P (operands[2])) + operands[1] = force_reg (QImode, operands[1]); + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) + + +(define_expand "cstoreqi4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:QI 2 "nonimmediate_operand" "") + (match_operand:QI 3 "general_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] + "" +{ + if (MEM_P (operands[2]) && MEM_P (operands[3])) + operands[2] = force_reg (QImode, operands[2]); + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) + (define_insn "cmpdi_ccno_1_rex64" [(set (reg FLAGS_REG) (compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr") @@ -1078,39 +1184,103 @@ ;; which would allow mix and match FP modes on the compares. Which is what ;; the old patterns did, but with many more of them. -(define_expand "cmpxf" +(define_expand "cbranchxf4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:XF 1 "nonmemory_operand" "") + (match_operand:XF 2 "nonmemory_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_80387" +{ + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) + +(define_expand "cstorexf4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:XF 0 "nonmemory_operand" "") - (match_operand:XF 1 "nonmemory_operand" "")))] + (compare:CC (match_operand:XF 2 "nonmemory_operand" "") + (match_operand:XF 3 "nonmemory_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] "TARGET_80387" { - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) -(define_expand "cmp" +(define_expand "cbranch4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:MODEF 0 "cmp_fp_expander_operand" "") - (match_operand:MODEF 1 "cmp_fp_expander_operand" "")))] + (compare:CC (match_operand:MODEF 1 "cmp_fp_expander_operand" "") + (match_operand:MODEF 2 "cmp_fp_expander_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "TARGET_80387 || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" { - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); DONE; }) -(define_expand "cmpcc" +(define_expand "cstore4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand 0 "flags_reg_operand" "") - (match_operand 1 "general_operand" "")))] + (compare:CC (match_operand:MODEF 2 "cmp_fp_expander_operand" "") + (match_operand:MODEF 3 "cmp_fp_expander_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] + "TARGET_80387 || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" +{ + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); + DONE; +}) + +(define_expand "cbranchcc4" + [(set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(match_operand 1 "flags_reg_operand" "") + (match_operand 2 "const0_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" +{ + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) + +(define_expand "cstorecc4" + [(set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(match_operand 2 "flags_reg_operand" "") + (match_operand 3 "const0_operand" "")]))] "" { - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) + ;; FP compares, step 1: ;; Set the FP condition codes. ;; @@ -14182,18 +14352,6 @@ ;; to avoid partial register stalls. Otherwise do things the setcc+movzx ;; way, which can later delete the movzx if only QImode is needed. -(define_expand "s" - [(set (match_operand:QI 0 "register_operand" "") - (int_cond:QI (reg:CC FLAGS_REG) (const_int 0)))] - "" - "if (ix86_expand_setcc (, operands[0])) DONE; else FAIL;") - -(define_expand "s" - [(set (match_operand:QI 0 "register_operand" "") - (fp_cond:QI (reg:CC FLAGS_REG) (const_int 0)))] - "TARGET_80387 || TARGET_SSE" - "if (ix86_expand_setcc (, operands[0])) DONE; else FAIL;") - (define_insn "*setcc_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") (match_operator:QI 1 "ix86_comparison_operator" @@ -14322,27 +14480,6 @@ ;; Basic conditional jump instructions. ;; We ignore the overflow flag for signed branch instructions. -;; For all bCOND expanders, also expand the compare or test insn that -;; generates reg FLAGS_REG. Generate an equality comparison if `beq' or `bne'. - -(define_expand "b" - [(set (pc) - (if_then_else (int_cond:CC (reg:CC FLAGS_REG) - (const_int 0)) - (label_ref (match_operand 0 "")) - (pc)))] - "" - "ix86_expand_branch (, operands[0]); DONE;") - -(define_expand "b" - [(set (pc) - (if_then_else (fp_cond:CC (reg:CC FLAGS_REG) - (const_int 0)) - (label_ref (match_operand 0 "")) - (pc)))] - "TARGET_80387 || TARGET_SSE_MATH" - "ix86_expand_branch (, operands[0]); DONE;") - (define_insn "*jcc_1" [(set (pc) (if_then_else (match_operator 1 "ix86_comparison_operator" @@ -22004,9 +22141,8 @@ emit_insn (gen_stack_protect_test_si (flags, operands[0], operands[1])); #endif - ix86_compare_op0 = flags; - ix86_compare_op1 = const0_rtx; - emit_jump_insn (gen_beq (operands[2])); + emit_jump_insn (gen_cbranchcc4 (gen_rtx_EQ (VOIDmode, flags, const0_rtx), + flags, const0_rtx, operands[2])); DONE; }) diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h index e3b78641eb8..0859c7f53af 100644 --- a/gcc/config/ia64/ia64-protos.h +++ b/gcc/config/ia64/ia64-protos.h @@ -18,13 +18,6 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ -/* Variables defined in ia64.c. */ - -#ifdef RTX_CODE -extern GTY(()) rtx ia64_compare_op0; -extern GTY(()) rtx ia64_compare_op1; -#endif - /* Functions defined in ia64.c */ extern int bundling_p; @@ -43,7 +36,7 @@ extern void ia64_emit_cond_move (rtx, rtx, rtx); extern int ia64_depz_field_mask (rtx, rtx); extern void ia64_split_tmode_move (rtx[]); extern bool ia64_expand_movxf_movrf (enum machine_mode, rtx[]); -extern rtx ia64_expand_compare (enum rtx_code, enum machine_mode); +extern void ia64_expand_compare (rtx *, rtx *, rtx *); extern void ia64_expand_vecint_cmov (rtx[]); extern bool ia64_expand_vecint_minmax (enum rtx_code, enum machine_mode, rtx[]); extern void ia64_expand_widen_sum (rtx[], bool); diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index acf73c52969..1f433a6fb0f 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -63,11 +63,6 @@ along with GCC; see the file COPYING3. If not see ASM_OUTPUT_LABELREF. */ int ia64_asm_output_label = 0; -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ -struct rtx_def * ia64_compare_op0; -struct rtx_def * ia64_compare_op1; - /* Register names for ia64_expand_prologue. */ static const char * const ia64_reg_numbers[96] = { "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", @@ -1493,28 +1488,28 @@ ia64_expand_movxf_movrf (enum machine_mode mode, rtx operands[]) return false; } -/* Emit comparison instruction if necessary, returning the expression - that holds the compare result in the proper mode. */ +/* Emit comparison instruction if necessary, replacing *EXPR, *OP0, *OP1 + with the expression that holds the compare result (in VOIDmode). */ static GTY(()) rtx cmptf_libfunc; -rtx -ia64_expand_compare (enum rtx_code code, enum machine_mode mode) +void +ia64_expand_compare (rtx *expr, rtx *op0, rtx *op1) { - rtx op0 = ia64_compare_op0, op1 = ia64_compare_op1; + enum rtx_code code = GET_CODE (*expr); rtx cmp; /* If we have a BImode input, then we already have a compare result, and do not need to emit another comparison. */ - if (GET_MODE (op0) == BImode) + if (GET_MODE (*op0) == BImode) { - gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx); - cmp = op0; + gcc_assert ((code == NE || code == EQ) && *op1 == const0_rtx); + cmp = *op0; } /* HPUX TFmode compare requires a library call to _U_Qfcmp, which takes a magic number as its third argument, that indicates what to do. The return value is an integer to be compared against zero. */ - else if (TARGET_HPUX && GET_MODE (op0) == TFmode) + else if (TARGET_HPUX && GET_MODE (*op0) == TFmode) { enum qfcmp_magic { QCMP_INV = 1, /* Raise FP_INVALID on SNaN as a side effect. */ @@ -1527,7 +1522,7 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode) enum rtx_code ncode; rtx ret, insns; - gcc_assert (cmptf_libfunc && GET_MODE (op1) == TFmode); + gcc_assert (cmptf_libfunc && GET_MODE (*op1) == TFmode); switch (code) { /* 1 = equal, 0 = not equal. Equality operators do @@ -1552,7 +1547,7 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode) start_sequence (); ret = emit_library_call_value (cmptf_libfunc, 0, LCT_CONST, DImode, 3, - op0, TFmode, op1, TFmode, + *op0, TFmode, *op1, TFmode, GEN_INT (magic), DImode); cmp = gen_reg_rtx (BImode); emit_insn (gen_rtx_SET (VOIDmode, cmp, @@ -1563,18 +1558,20 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode) end_sequence (); emit_libcall_block (insns, cmp, cmp, - gen_rtx_fmt_ee (code, BImode, op0, op1)); + gen_rtx_fmt_ee (code, BImode, *op0, *op1)); code = NE; } else { cmp = gen_reg_rtx (BImode); emit_insn (gen_rtx_SET (VOIDmode, cmp, - gen_rtx_fmt_ee (code, BImode, op0, op1))); + gen_rtx_fmt_ee (code, BImode, *op0, *op1))); code = NE; } - return gen_rtx_fmt_ee (code, mode, cmp, const0_rtx); + *expr = gen_rtx_fmt_ee (code, VOIDmode, cmp, const0_rtx); + *op0 = cmp; + *op1 = const0_rtx; } /* Generate an integral vector comparison. Return true if the condition has diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md index 26e71f841b5..e5a6d81730c 100644 --- a/gcc/config/ia64/ia64.md +++ b/gcc/config/ia64/ia64.md @@ -409,6 +409,7 @@ (set_attr "speculable2" "no, no, no, no, yes,no,no, no, no, yes,no, no, no, no, no, no, no, no, no")]) (define_mode_iterator MODE [BI QI HI SI DI SF DF XF TI]) +(define_mode_iterator MODE_FOR_CMP [BI SI DI SF DF XF (TF "TARGET_HPUX")]) (define_mode_iterator MODE_FOR_EXTEND [QI HI SI]) (define_mode_attr output_a [ @@ -4759,82 +4760,76 @@ ;; :: ;; :::::::::::::::::::: -(define_expand "cmpbi" - [(set (cc0) - (compare (match_operand:BI 0 "register_operand" "") - (match_operand:BI 1 "const_int_operand" "")))] +(define_expand "cbranchbi4" + [(set (pc) + (if_then_else (match_operator 0 "ia64_cbranch_operator" + [(match_operand:BI 1 "register_operand" "") + (match_operand:BI 2 "const_int_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" -{ - ia64_compare_op0 = operands[0]; - ia64_compare_op1 = operands[1]; - DONE; -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "gr_register_operand" "") - (match_operand:SI 1 "gr_reg_or_8bit_and_adjusted_operand" "")))] +(define_expand "cbranchsi4" + [(set (pc) + (if_then_else (match_operator 0 "ia64_cbranch_operator" + [(match_operand:SI 1 "gr_register_operand" "") + (match_operand:SI 2 "gr_reg_or_8bit_and_adjusted_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" -{ - ia64_compare_op0 = operands[0]; - ia64_compare_op1 = operands[1]; - DONE; -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") -(define_expand "cmpdi" - [(set (cc0) - (compare (match_operand:DI 0 "gr_register_operand" "") - (match_operand:DI 1 "gr_reg_or_8bit_and_adjusted_operand" "")))] +(define_expand "cbranchdi4" + [(set (pc) + (if_then_else (match_operator 0 "ia64_cbranch_operator" + [(match_operand:DI 1 "gr_register_operand" "") + (match_operand:DI 2 "gr_reg_or_8bit_and_adjusted_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" -{ - ia64_compare_op0 = operands[0]; - ia64_compare_op1 = operands[1]; - DONE; -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") -(define_expand "cmpsf" - [(set (cc0) - (compare (match_operand:SF 0 "fr_reg_or_fp01_operand" "") - (match_operand:SF 1 "fr_reg_or_fp01_operand" "")))] +(define_expand "cbranchsf4" + [(set (pc) + (if_then_else (match_operator 0 "ia64_cbranch_operator" + [(match_operand:SF 1 "fr_reg_or_fp01_operand" "") + (match_operand:SF 2 "fr_reg_or_fp01_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" -{ - ia64_compare_op0 = operands[0]; - ia64_compare_op1 = operands[1]; - DONE; -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") -(define_expand "cmpdf" - [(set (cc0) - (compare (match_operand:DF 0 "fr_reg_or_fp01_operand" "") - (match_operand:DF 1 "fr_reg_or_fp01_operand" "")))] +(define_expand "cbranchdf4" + [(set (pc) + (if_then_else (match_operator 0 "ia64_cbranch_operator" + [(match_operand:DF 1 "fr_reg_or_fp01_operand" "") + (match_operand:DF 2 "fr_reg_or_fp01_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" -{ - ia64_compare_op0 = operands[0]; - ia64_compare_op1 = operands[1]; - DONE; -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") -(define_expand "cmpxf" - [(set (cc0) - (compare (match_operand:XF 0 "xfreg_or_fp01_operand" "") - (match_operand:XF 1 "xfreg_or_fp01_operand" "")))] +(define_expand "cbranchxf4" + [(set (pc) + (if_then_else (match_operator 0 "ia64_cbranch_operator" + [(match_operand:XF 1 "xfreg_or_fp01_operand" "") + (match_operand:XF 2 "xfreg_or_fp01_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" -{ - ia64_compare_op0 = operands[0]; - ia64_compare_op1 = operands[1]; - DONE; -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") -(define_expand "cmptf" - [(set (cc0) - (compare (match_operand:TF 0 "gr_register_operand" "") - (match_operand:TF 1 "gr_register_operand" "")))] +(define_expand "cbranchtf4" + [(set (pc) + (if_then_else (match_operator 0 "ia64_cbranch_operator" + [(match_operand:TF 1 "gr_register_operand" "") + (match_operand:TF 2 "gr_register_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "TARGET_HPUX" -{ - ia64_compare_op0 = operands[0]; - ia64_compare_op1 = operands[1]; - DONE; -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + (define_insn "*cmpsi_normal" [(set (match_operand:BI 0 "register_operand" "=c") @@ -4933,102 +4928,6 @@ ;; :: ;; :::::::::::::::::::: -(define_expand "beq" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (EQ, VOIDmode);") - -(define_expand "bne" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (NE, VOIDmode);") - -(define_expand "blt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (LT, VOIDmode);") - -(define_expand "ble" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (LE, VOIDmode);") - -(define_expand "bgt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (GT, VOIDmode);") - -(define_expand "bge" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (GE, VOIDmode);") - -(define_expand "bltu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (LTU, VOIDmode);") - -(define_expand "bleu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (LEU, VOIDmode);") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (GTU, VOIDmode);") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (GEU, VOIDmode);") - -(define_expand "bunordered" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (UNORDERED, VOIDmode);") - -(define_expand "bordered" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (ORDERED, VOIDmode);") - (define_insn "*br_true" [(set (pc) (if_then_else (match_operator 0 "predicate_operator" @@ -5094,65 +4993,61 @@ ;; :: ;; :::::::::::::::::::: -(define_expand "seq" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] +(define_expand "cstorebi4" + [(set (match_operand:DI 0 "gr_register_operand" "") + (match_operator:DI 1 "ia64_cbranch_operator" + [(match_operand:BI 2 "register_operand" "") + (match_operand:BI 3 "const_int_operand" "")]))] "" - "operands[1] = ia64_expand_compare (EQ, DImode);") + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") -(define_expand "sne" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] +(define_expand "cstoresi4" + [(set (match_operand:DI 0 "gr_register_operand" "") + (match_operator:DI 1 "ia64_cbranch_operator" + [(match_operand:SI 2 "gr_register_operand" "") + (match_operand:SI 3 "gr_reg_or_8bit_and_adjusted_operand" "")]))] "" - "operands[1] = ia64_expand_compare (NE, DImode);") + "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);") -(define_expand "slt" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] +(define_expand "cstoredi4" + [(set (match_operand:DI 0 "gr_register_operand" "") + (match_operator:DI 1 "ia64_cbranch_operator" + [(match_operand:DI 2 "gr_register_operand" "") + (match_operand:DI 3 "gr_reg_or_8bit_and_adjusted_operand" "")]))] "" - "operands[1] = ia64_expand_compare (LT, DImode);") + "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);") -(define_expand "sle" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] +(define_expand "cstoresf4" + [(set (match_operand:DI 0 "gr_register_operand" "") + (match_operator:DI 1 "ia64_cbranch_operator" + [(match_operand:SF 2 "fr_reg_or_fp01_operand" "") + (match_operand:SF 3 "fr_reg_or_fp01_operand" "")]))] "" - "operands[1] = ia64_expand_compare (LE, DImode);") + "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);") -(define_expand "sgt" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] +(define_expand "cstoredf4" + [(set (match_operand:DI 0 "gr_register_operand" "") + (match_operator:DI 1 "ia64_cbranch_operator" + [(match_operand:DF 2 "fr_reg_or_fp01_operand" "") + (match_operand:DF 3 "fr_reg_or_fp01_operand" "")]))] "" - "operands[1] = ia64_expand_compare (GT, DImode);") + "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);") -(define_expand "sge" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] +(define_expand "cstorexf4" + [(set (match_operand:DI 0 "gr_register_operand" "") + (match_operator:DI 1 "ia64_cbranch_operator" + [(match_operand:XF 2 "xfreg_or_fp01_operand" "") + (match_operand:XF 3 "xfreg_or_fp01_operand" "")]))] "" - "operands[1] = ia64_expand_compare (GE, DImode);") + "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);") -(define_expand "sltu" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] - "" - "operands[1] = ia64_expand_compare (LTU, DImode);") - -(define_expand "sleu" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] - "" - "operands[1] = ia64_expand_compare (LEU, DImode);") - -(define_expand "sgtu" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] - "" - "operands[1] = ia64_expand_compare (GTU, DImode);") - -(define_expand "sgeu" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] - "" - "operands[1] = ia64_expand_compare (GEU, DImode);") - -(define_expand "sunordered" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] - "" - "operands[1] = ia64_expand_compare (UNORDERED, DImode);") - -(define_expand "sordered" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] - "" - "operands[1] = ia64_expand_compare (ORDERED, DImode);") +(define_expand "cstoretf4" + [(set (match_operand:DI 0 "gr_register_operand" "") + (match_operator:DI 1 "ia64_cbranch_operator" + [(match_operand:TF 2 "gr_register_operand" "") + (match_operand:TF 3 "gr_register_operand" "")]))] + "TARGET_HPUX" + "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);") ;; Don't allow memory as destination here, because cmov/cmov/st is more ;; efficient than mov/mov/cst/cst. @@ -6018,12 +5913,62 @@ "break %0" [(set_attr "itanium_class" "chk_s_i")]) -(define_expand "conditional_trap" - [(trap_if (match_operand 0 "" "") (match_operand 1 "" ""))] +(define_expand "ctrapbi4" + [(trap_if (match_operator 0 "ia64_cbranch_operator" + [(match_operand:BI 1 "register_operand" "") + (match_operand:BI 2 "const_int_operand" "")]) + (match_operand 3 "" ""))] "" -{ - operands[0] = ia64_expand_compare (GET_CODE (operands[0]), VOIDmode); -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + +(define_expand "ctrapsi4" + [(trap_if (match_operator 0 "ia64_cbranch_operator" + [(match_operand:SI 1 "gr_register_operand" "") + (match_operand:SI 2 "gr_reg_or_8bit_and_adjusted_operand" "")]) + (match_operand 3 "" ""))] + "" + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + +(define_expand "ctrapdi4" + [(trap_if (match_operator 0 "ia64_cbranch_operator" + [(match_operand:DI 1 "gr_register_operand" "") + (match_operand:DI 2 "gr_reg_or_8bit_and_adjusted_operand" "")]) + (match_operand 3 "" ""))] + "" + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + +(define_expand "ctrapsf4" + [(trap_if (match_operator 0 "ia64_cbranch_operator" + [(match_operand:SF 1 "fr_reg_or_fp01_operand" "") + (match_operand:SF 2 "fr_reg_or_fp01_operand" "")]) + (match_operand 3 "" ""))] + "" + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + +(define_expand "ctrapdf4" + [(trap_if (match_operator 0 "ia64_cbranch_operator" + [(match_operand:DF 1 "fr_reg_or_fp01_operand" "") + (match_operand:DF 2 "fr_reg_or_fp01_operand" "")]) + (match_operand 3 "" ""))] + "" + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + +(define_expand "ctrapxf4" + [(trap_if (match_operator 0 "ia64_cbranch_operator" + [(match_operand:XF 1 "xfreg_or_fp01_operand" "") + (match_operand:XF 2 "xfreg_or_fp01_operand" "")]) + (match_operand 3 "" ""))] + "" + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + +(define_expand "ctraptf4" + [(trap_if (match_operator 0 "ia64_cbranch_operator" + [(match_operand:TF 1 "gr_register_operand" "") + (match_operand:TF 2 "gr_register_operand" "")]) + (match_operand 3 "" ""))] + "TARGET_HPUX" + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + (define_insn "*conditional_trap" [(trap_if (match_operator 0 "predicate_operator" diff --git a/gcc/config/ia64/predicates.md b/gcc/config/ia64/predicates.md index 5a957490390..1503a0520cb 100644 --- a/gcc/config/ia64/predicates.md +++ b/gcc/config/ia64/predicates.md @@ -536,6 +536,11 @@ (and (match_code "const_double,const_vector") (match_test "op == CONST0_RTX (GET_MODE (op))")))) +;; Return 1 if OP is a valid comparison operator for "cbranch" instructions. +(define_predicate "ia64_cbranch_operator" + (ior (match_operand 0 "ordered_comparison_operator") + (match_code "ordered,unordered"))) + ;; True if this is a comparison operator, which accepts a normal 8-bit ;; signed immediate operand. (define_predicate "normal_comparison_operator" diff --git a/gcc/config/iq2000/iq2000-protos.h b/gcc/config/iq2000/iq2000-protos.h index 094bcbf2f12..a927452d83c 100644 --- a/gcc/config/iq2000/iq2000-protos.h +++ b/gcc/config/iq2000/iq2000-protos.h @@ -41,7 +41,7 @@ extern void print_operand (FILE *, rtx, int); #ifdef RTX_CODE extern rtx gen_int_relational (enum rtx_code, rtx, rtx, rtx, int *); -extern void gen_conditional_branch (rtx *, enum rtx_code); +extern void gen_conditional_branch (rtx *, enum machine_mode); #endif #ifdef TREE_CODE diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c index 3b9e1166b27..28bb7a831fe 100644 --- a/gcc/config/iq2000/iq2000.c +++ b/gcc/config/iq2000/iq2000.c @@ -118,13 +118,6 @@ enum processor_type iq2000_tune; /* Which instruction set architecture to use. */ int iq2000_isa; -/* Cached operands, and operator to compare for use in set/branch/trap - on condition codes. */ -rtx branch_cmp[2]; - -/* What type of branch to use. */ -enum cmp_type branch_type; - /* Local variables. */ /* The next branch instruction is a branch likely, not branch normal. */ @@ -1010,60 +1003,31 @@ gen_int_relational (enum rtx_code test_code, rtx result, rtx cmp0, rtx cmp1, The comparison operands are saved away by cmp{si,di,sf,df}. */ void -gen_conditional_branch (rtx operands[], enum rtx_code test_code) +gen_conditional_branch (rtx operands[], enum machine_mode mode) { - enum cmp_type type = branch_type; - rtx cmp0 = branch_cmp[0]; - rtx cmp1 = branch_cmp[1]; - enum machine_mode mode; + enum rtx_code test_code = GET_CODE (operands[0]); + rtx cmp0 = operands[1]; + rtx cmp1 = operands[2]; rtx reg; int invert; rtx label1, label2; - switch (type) - { - case CMP_SI: - case CMP_DI: - mode = type == CMP_SI ? SImode : DImode; - invert = 0; - reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert); - - if (reg) - { - cmp0 = reg; - cmp1 = const0_rtx; - test_code = NE; - } - else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0) - /* We don't want to build a comparison against a nonzero - constant. */ - cmp1 = force_reg (mode, cmp1); - - break; - - case CMP_SF: - case CMP_DF: - reg = gen_reg_rtx (CCmode); + invert = 0; + reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert); - /* For cmp0 != cmp1, build cmp0 == cmp1, and test for result == 0. */ - emit_insn (gen_rtx_SET (VOIDmode, reg, - gen_rtx_fmt_ee (test_code == NE ? EQ : test_code, - CCmode, cmp0, cmp1))); - - test_code = test_code == NE ? EQ : NE; - mode = CCmode; + if (reg) + { cmp0 = reg; cmp1 = const0_rtx; - invert = 0; - break; - - default: - abort_with_insn (gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1), - "bad test"); + test_code = NE; } + else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0) + /* We don't want to build a comparison against a nonzero + constant. */ + cmp1 = force_reg (mode, cmp1); /* Generate the branch. */ - label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]); + label1 = gen_rtx_LABEL_REF (VOIDmode, operands[3]); label2 = pc_rtx; if (invert) diff --git a/gcc/config/iq2000/iq2000.h b/gcc/config/iq2000/iq2000.h index 30642b2a13f..0664f511bd3 100644 --- a/gcc/config/iq2000/iq2000.h +++ b/gcc/config/iq2000/iq2000.h @@ -1001,13 +1001,6 @@ extern enum processor_type iq2000_tune; /* Which instruction set architecture to use. */ extern int iq2000_isa; -/* Cached operands, and operator to compare for use in set/branch/trap - on condition codes. */ -extern rtx branch_cmp[2]; - -/* What type of branch to use. */ -extern enum cmp_type branch_type; - enum iq2000_builtins { IQ2000_BUILTIN_ADO16, diff --git a/gcc/config/iq2000/iq2000.md b/gcc/config/iq2000/iq2000.md index 919f6a20231..61275f2c671 100644 --- a/gcc/config/iq2000/iq2000.md +++ b/gcc/config/iq2000/iq2000.md @@ -989,63 +989,25 @@ ;; ;; .................... ;; -;; COMPARISONS +;; CONDITIONAL BRANCHES ;; ;; .................... -;; Flow here is rather complex: -;; -;; 1) The cmp{si,di,sf,df} routine is called. It deposits the -;; arguments into the branch_cmp array, and the type into -;; branch_type. No RTL is generated. -;; -;; 2) The appropriate branch define_expand is called, which then -;; creates the appropriate RTL for the comparison and branch. -;; Different CC modes are used, based on what type of branch is -;; done, so that we can constrain things appropriately. There -;; are assumptions in the rest of GCC that break if we fold the -;; operands into the branches for integer operations, and use cc0 -;; for floating point, so we use the fp status register instead. -;; If needed, an appropriate temporary is created to hold the -;; of the integer compare. - -(define_expand "cmpsi" - [(set (cc0) - (compare:CC (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "arith_operand" "")))] +(define_expand "cbranchsi4" + [(set (pc) + (if_then_else + (match_operator:SI 0 "ordered_comparison_operator" + [(match_operand:SI 1 "register_operand") + (match_operand:SI 2 "reg_or_const_operand")]) + (label_ref (match_operand:SI 3 "")) + (pc)))] "" " { - if (operands[0]) /* avoid unused code message */ - { - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_SI; - DONE; - } + gen_conditional_branch (operands, SImode); + DONE; }") -(define_expand "tstsi" - [(set (cc0) - (match_operand:SI 0 "register_operand" ""))] - "" - " -{ - if (operands[0]) /* avoid unused code message */ - { - branch_cmp[0] = operands[0]; - branch_cmp[1] = const0_rtx; - branch_type = CMP_SI; - DONE; - } -}") - -;; -;; .................... -;; -;; CONDITIONAL BRANCHES -;; -;; .................... ;; Conditional branches on comparisons with zero. @@ -1135,166 +1097,6 @@ [(set_attr "type" "branch") (set_attr "mode" "none")]) -(define_expand "beq" - [(set (pc) - (if_then_else (eq:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, EQ); - DONE; - } -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, NE); - DONE; - } -}") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GT); - DONE; - } -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GE); - DONE; - } -}") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LT); - DONE; - } -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (le:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LE); - DONE; - } -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GTU); - DONE; - } -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GEU); - DONE; - } -}") - - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LTU); - DONE; - } -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LEU); - DONE; - } -}") ;; Recognize bbi and bbin instructions. These use two unusual template ;; patterns, %Ax and %Px. %Ax outputs an 'i' if operand `x' is a LABEL_REF @@ -1390,25 +1192,19 @@ ;; ;; .................... -(define_expand "seq" +(define_expand "cstoresi4" [(set (match_operand:SI 0 "register_operand" "=d") - (eq:SI (match_dup 1) - (match_dup 2)))] + (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SI 2 "register_operand") + (match_operand:SI 3 "reg_or_const_operand")]))] "" " { - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (EQ, operands[0], operands[1], operands[2], (int *)0); + gen_int_relational (GET_CODE (operands[1]), operands[0], + operands[2], operands[3], (int *)0); DONE; }") - (define_insn "seq_si_zero" [(set (match_operand:SI 0 "register_operand" "=d") (eq:SI (match_operand:SI 1 "register_operand" "d") @@ -1418,24 +1214,6 @@ [(set_attr "type" "arith") (set_attr "mode" "SI")]) -(define_expand "sne" - [(set (match_operand:SI 0 "register_operand" "=d") - (ne:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (NE, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - (define_insn "sne_si_zero" [(set (match_operand:SI 0 "register_operand" "=d") (ne:SI (match_operand:SI 1 "register_operand" "d") @@ -1445,24 +1223,6 @@ [(set_attr "type" "arith") (set_attr "mode" "SI")]) -(define_expand "sgt" - [(set (match_operand:SI 0 "register_operand" "=d") - (gt:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (GT, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - (define_insn "sgt_si" [(set (match_operand:SI 0 "register_operand" "=d,=d") (gt:SI (match_operand:SI 1 "register_operand" "d,d") @@ -1474,42 +1234,6 @@ [(set_attr "type" "arith,arith") (set_attr "mode" "SI,SI")]) -(define_expand "sge" - [(set (match_operand:SI 0 "register_operand" "=d") - (ge:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (GE, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - -(define_expand "slt" - [(set (match_operand:SI 0 "register_operand" "=d") - (lt:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (LT, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - (define_insn "slt_si" [(set (match_operand:SI 0 "register_operand" "=d,=d") (lt:SI (match_operand:SI 1 "register_operand" "d,d") @@ -1521,24 +1245,6 @@ [(set_attr "type" "arith,arith") (set_attr "mode" "SI,SI")]) -(define_expand "sle" - [(set (match_operand:SI 0 "register_operand" "=d") - (le:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (LE, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - (define_insn "sle_si_const" [(set (match_operand:SI 0 "register_operand" "=d") (le:SI (match_operand:SI 1 "register_operand" "d") @@ -1552,24 +1258,6 @@ [(set_attr "type" "arith") (set_attr "mode" "SI")]) -(define_expand "sgtu" - [(set (match_operand:SI 0 "register_operand" "=d") - (gtu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (GTU, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - (define_insn "sgtu_si" [(set (match_operand:SI 0 "register_operand" "=d") (gtu:SI (match_operand:SI 1 "register_operand" "d") @@ -1588,42 +1276,6 @@ [(set_attr "type" "arith") (set_attr "mode" "SI")]) -(define_expand "sgeu" - [(set (match_operand:SI 0 "register_operand" "=d") - (geu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (GEU, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - -(define_expand "sltu" - [(set (match_operand:SI 0 "register_operand" "=d") - (ltu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (LTU, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - (define_insn "sltu_si" [(set (match_operand:SI 0 "register_operand" "=d,=d") (ltu:SI (match_operand:SI 1 "register_operand" "d,d") @@ -1635,24 +1287,6 @@ [(set_attr "type" "arith,arith") (set_attr "mode" "SI,SI")]) -(define_expand "sleu" - [(set (match_operand:SI 0 "register_operand" "=d") - (leu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (LEU, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - (define_insn "sleu_si_const" [(set (match_operand:SI 0 "register_operand" "=d") (leu:SI (match_operand:SI 1 "register_operand" "d") diff --git a/gcc/config/iq2000/predicates.md b/gcc/config/iq2000/predicates.md index 53471e455ad..f275090309b 100644 --- a/gcc/config/iq2000/predicates.md +++ b/gcc/config/iq2000/predicates.md @@ -41,6 +41,14 @@ return register_operand (op, mode); }) +;; Return 1 if OP is a register or a constant. gen_int_relational +;; takes care of forcing out-of-range constants into a register. + +(define_predicate "reg_or_const_operand" + (ior (match_code "const_int") + (and (match_code "reg,subreg") + (match_operand 0 "register_operand")))) + ;; Return 1 if OP is a integer which fits in 16 bits. (define_predicate "small_int" diff --git a/gcc/config/m32c/cond.md b/gcc/config/m32c/cond.md index 60d83eea6ca..c751070e716 100644 --- a/gcc/config/m32c/cond.md +++ b/gcc/config/m32c/cond.md @@ -58,12 +58,23 @@ [(set (reg:CC FLG_REGNO) (compare (match_dup 1) (match_dup 2))) - (set (pc) (if_then_else (match_dup 4) + (set (pc) (if_then_else (match_op_dup 0 [(reg:CC FLG_REGNO) (const_int 0)]) (label_ref (match_dup 3)) (pc)))] - "operands[4] = m32c_cmp_flg_0 (operands[0]);" + "" ) +(define_insn "bcc_op" + [(set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(reg:CC FLG_REGNO) (const_int 0)]) + (label_ref (match_operand 1 "")) + (pc)))] + "" + "j%c0\t%l1" + [(set_attr "flags" "n")] +) + (define_insn "stzx_16" [(set (match_operand:QI 0 "mrai_operand" "=R0w,R0w,R0w") (if_then_else:QI (eq (reg:CC FLG_REGNO) (const_int 0)) @@ -113,34 +124,6 @@ "* return m32c_output_compare(insn, operands); " [(set_attr "flags" "oszc")]) -(define_expand "cmp" - [(set (reg:CC FLG_REGNO) - (compare (match_operand:QHPSI 0 "mra_operand" "RraSd") - (match_operand:QHPSI 1 "mrai_operand" "RraSdi")))] - "" - "m32c_pend_compare (operands); DONE;") - -(define_insn "b_op" - [(set (pc) - (if_then_else (any_cond (reg:CC FLG_REGNO) - (const_int 0)) - (label_ref (match_operand 0 "")) - (pc)))] - "" - "j\t%l0" - [(set_attr "flags" "n")] -) - -(define_expand "b" - [(set (pc) - (if_then_else (any_cond (reg:CC FLG_REGNO) - (const_int 0)) - (label_ref (match_operand 0 "")) - (pc)))] - "" - "m32c_unpend_compare ();" -) - ;; m32c_conditional_register_usage changes the setcc_gen_code array to ;; point to the _24 variants if needed. @@ -151,51 +134,54 @@ ;; These are the post-split patterns for the conditional sets. -(define_insn "s_op" +(define_insn "scc_op" [(set (match_operand:QI 0 "register_operand" "=Rqi") - (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))] + (match_operator:QI 1 "ordered_comparison_operator" + [(reg:CC FLG_REGNO) (const_int 0)]))] "TARGET_A16 && reload_completed" - "* return m32c_scc_pattern(operands, );") + "* return m32c_scc_pattern(operands, GET_CODE (operands[1]));") -(define_insn "s_24_op" +(define_insn "scc_24_op" [(set (match_operand:HI 0 "mra_operand" "=RhiSd") - (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))] + (match_operator:HI 1 "ordered_comparison_operator" + [(reg:CC FLG_REGNO) (const_int 0)]))] "TARGET_A24 && reload_completed" - "sc\t%0" + "sc%c1\t%0" [(set_attr "flags" "n")] ) -;; These are the pre-split patterns for the conditional sets. Yes, -;; there are a lot of permutations. +;; These are the pre-split patterns for the conditional sets. -(define_insn_and_split "s_" +(define_insn_and_split "cstore4" [(set (match_operand:QI 0 "register_operand" "=Rqi") - (any_cond:QI (match_operand:QHPSI 1 "mra_operand" "RraSd") - (match_operand:QHPSI 2 "mrai_operand" "RraSdi")))] + (match_operator:QI 1 "ordered_comparison_operator" + [(match_operand:QHPSI 2 "mra_operand" "RraSd") + (match_operand:QHPSI 3 "mrai_operand" "RraSdi")]))] "TARGET_A16" "#" "reload_completed" [(set (reg:CC FLG_REGNO) - (compare (match_dup 1) - (match_dup 2))) + (compare (match_dup 2) + (match_dup 3))) (set (match_dup 0) - (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))] + (match_op_dup 1 [(reg:CC FLG_REGNO) (const_int 0)]))] "" [(set_attr "flags" "x")] ) -(define_insn_and_split "s__24" +(define_insn_and_split "cstore4_24" [(set (match_operand:HI 0 "mra_nopp_operand" "=RhiSd") - (any_cond:HI (match_operand:QHPSI 1 "mra_operand" "RraSd") - (match_operand:QHPSI 2 "mrai_operand" "RraSdi")))] + (match_operator:HI 1 "ordered_comparison_operator" + [(match_operand:QHPSI 2 "mra_operand" "RraSd") + (match_operand:QHPSI 3 "mrai_operand" "RraSdi")]))] "TARGET_A24" "#" "reload_completed" [(set (reg:CC FLG_REGNO) - (compare (match_dup 1) - (match_dup 2))) + (compare (match_dup 2) + (match_dup 3))) (set (match_dup 0) - (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))] + (match_op_dup 1 [(reg:CC FLG_REGNO) (const_int 0)]))] "" [(set_attr "flags" "x")] ) @@ -240,21 +226,7 @@ [(set_attr "flags" "x")] ) -;; And these are the expanders, which read the pending compare -;; operands to build a combined insn. - -(define_expand "s" - [(set (match_operand:QI 0 "register_operand" "=Rqi") - (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))] - "TARGET_A16" - "m32c_expand_scc (, operands); DONE;") - -(define_expand "s_24" - [(set (match_operand:HI 0 "mra_nopp_operand" "=RhiSd") - (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))] - "TARGET_A24" - "m32c_expand_scc (, operands); DONE;") - +;; And these are the expanders. (define_expand "movqicc" [(set (match_operand:QI 0 "register_operand" "") diff --git a/gcc/config/m32c/m32c-protos.h b/gcc/config/m32c/m32c-protos.h index 650c918b44a..ef857275c9d 100644 --- a/gcc/config/m32c/m32c-protos.h +++ b/gcc/config/m32c/m32c-protos.h @@ -45,7 +45,6 @@ void m32c_register_pragmas (void); int m32c_regno_ok_for_base_p (int); int m32c_trampoline_alignment (void); int m32c_trampoline_size (void); -void m32c_unpend_compare (void); #if defined(RTX_CODE) && defined(TREE_CODE) @@ -58,7 +57,6 @@ rtx m32c_function_value (const_tree, const_tree); int m32c_cannot_change_mode_class (MM, MM, int); int m32c_class_max_nregs (int, MM); -rtx m32c_cmp_flg_0 (rtx); rtx m32c_eh_return_stackadj_rtx (void); void m32c_emit_eh_epilogue (rtx); int m32c_expand_cmpstr (rtx *); @@ -68,7 +66,6 @@ int m32c_expand_movmemhi (rtx *); int m32c_expand_movstr (rtx *); void m32c_expand_neg_mulpsi3 (rtx *); int m32c_expand_setmemhi (rtx *); -void m32c_expand_scc (int, rtx *); int m32c_extra_constraint_p (rtx, char, const char *); int m32c_extra_constraint_p2 (rtx, char, const char *); int m32c_hard_regno_nregs (int, MM); @@ -86,7 +83,6 @@ int m32c_memory_move_cost (MM, int, int); int m32c_modes_tieable_p (MM, MM); bool m32c_mov_ok (rtx *, MM); char * m32c_output_compare (rtx, rtx *); -void m32c_pend_compare (rtx *); int m32c_preferred_output_reload_class (rtx, int); int m32c_preferred_reload_class (rtx, int); int m32c_prepare_move (rtx *, MM); diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c index d0980dd63a6..17d5dd32ebc 100644 --- a/gcc/config/m32c/m32c.c +++ b/gcc/config/m32c/m32c.c @@ -1746,22 +1746,15 @@ m32c_initialize_trampoline (rtx tramp, rtx function, rtx chainval) static void m32c_init_libfuncs (void) { + /* We do this because the M32C has an HImode operand, but the + M16C has an 8-bit operand. Since gcc looks at the match data + and not the expanded rtl, we have to reset the optab so that + the right modes are found. */ if (TARGET_A24) { - /* We do this because the M32C has an HImode operand, but the - M16C has an 8-bit operand. Since gcc looks at the match data - and not the expanded rtl, we have to reset the array so that - the right modes are found. */ - setcc_gen_code[EQ] = CODE_FOR_seq_24; - setcc_gen_code[NE] = CODE_FOR_sne_24; - setcc_gen_code[GT] = CODE_FOR_sgt_24; - setcc_gen_code[GE] = CODE_FOR_sge_24; - setcc_gen_code[LT] = CODE_FOR_slt_24; - setcc_gen_code[LE] = CODE_FOR_sle_24; - setcc_gen_code[GTU] = CODE_FOR_sgtu_24; - setcc_gen_code[GEU] = CODE_FOR_sgeu_24; - setcc_gen_code[LTU] = CODE_FOR_sltu_24; - setcc_gen_code[LEU] = CODE_FOR_sleu_24; + optab_handler (cstore_optab, QImode)->insn_code = CODE_FOR_cstoreqi4_24; + optab_handler (cstore_optab, HImode)->insn_code = CODE_FOR_cstorehi4_24; + optab_handler (cstore_optab, PSImode)->insn_code = CODE_FOR_cstorepsi4_24; } } @@ -3691,57 +3684,8 @@ m32c_expand_neg_mulpsi3 (rtx * operands) emit_insn (gen_truncsipsi2 (operands[0], temp2)); } -static rtx compare_op0, compare_op1; - -void -m32c_pend_compare (rtx *operands) -{ - compare_op0 = operands[0]; - compare_op1 = operands[1]; -} - -void -m32c_unpend_compare (void) -{ - switch (GET_MODE (compare_op0)) - { - case QImode: - emit_insn (gen_cmpqi_op (compare_op0, compare_op1)); - case HImode: - emit_insn (gen_cmphi_op (compare_op0, compare_op1)); - case PSImode: - emit_insn (gen_cmppsi_op (compare_op0, compare_op1)); - default: - /* Just to silence the "missing case" warnings. */ ; - } -} - -void -m32c_expand_scc (int code, rtx *operands) -{ - enum machine_mode mode = TARGET_A16 ? QImode : HImode; - - emit_insn (gen_rtx_SET (mode, - operands[0], - gen_rtx_fmt_ee (code, - mode, - compare_op0, - compare_op1))); -} - /* Pattern Output Functions */ -/* Returns a (OP (reg:CC FLG_REGNO) (const_int 0)) from some other - match_operand rtx's OP. */ -rtx -m32c_cmp_flg_0 (rtx cmp) -{ - return gen_rtx_fmt_ee (GET_CODE (cmp), - GET_MODE (cmp), - gen_rtx_REG (CCmode, FLG_REGNO), - GEN_INT (0)); -} - int m32c_expand_movcc (rtx *operands) { @@ -3753,22 +3697,17 @@ m32c_expand_movcc (rtx *operands) if (GET_CODE (operands[2]) != CONST_INT || GET_CODE (operands[3]) != CONST_INT) return 1; - emit_insn (gen_cmpqi(XEXP (rel, 0), XEXP (rel, 1))); if (GET_CODE (rel) == NE) { rtx tmp = operands[2]; operands[2] = operands[3]; operands[3] = tmp; + rel = gen_rtx_EQ (GET_MODE (rel), XEXP (rel, 0), XEXP (rel, 1)); } - cmp = gen_rtx_fmt_ee (GET_CODE (rel), - GET_MODE (rel), - compare_op0, - compare_op1); - emit_move_insn (operands[0], gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), - cmp, + rel, operands[2], operands[3])); return 0; diff --git a/gcc/config/m32c/m32c.md b/gcc/config/m32c/m32c.md index 4bc4d05fbf1..da0f8dd23f9 100644 --- a/gcc/config/m32c/m32c.md +++ b/gcc/config/m32c/m32c.md @@ -60,10 +60,7 @@ (define_mode_iterator QHSI [QI HI (SI "TARGET_A24")]) (define_mode_attr bwl [(QI "b") (HI "w") (PSI "l") (SI "l")]) -(define_code_iterator any_cond [eq ne gt ge lt le gtu geu ltu leu]) (define_code_iterator eqne_cond [eq ne]) -(define_code_iterator gl_cond [gt ge lt le gtu geu ltu leu]) - (define_insn "nop" diff --git a/gcc/config/m32r/m32r-protos.h b/gcc/config/m32r/m32r-protos.h index 33a9f9dd01f..04533b9b49e 100644 --- a/gcc/config/m32r/m32r-protos.h +++ b/gcc/config/m32r/m32r-protos.h @@ -38,6 +38,7 @@ extern enum m32r_function_type m32r_compute_function_type (tree); extern int easy_di_const (rtx); extern int easy_df_const (rtx); extern rtx gen_compare (enum rtx_code, rtx, rtx, int); +extern bool gen_cond_store (enum rtx_code, rtx, rtx, rtx); extern rtx gen_split_move_double (rtx *); extern int m32r_address_code (rtx); extern void m32r_initialize_trampoline (rtx, rtx, rtx); diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c index 656c0eae1be..0b5ff6bc6fd 100644 --- a/gcc/config/m32r/m32r.c +++ b/gcc/config/m32r/m32r.c @@ -43,10 +43,6 @@ #include "target-def.h" #include "tm-constrs.h" -/* Save the operands last given to a compare for use when we - generate a scc or bcc insn. */ -rtx m32r_compare_op0, m32r_compare_op1; - /* Array of valid operand punctuation characters. */ char m32r_punct_chars[256]; @@ -864,6 +860,151 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare) return gen_rtx_fmt_ee (branch_code, VOIDmode, cc_reg, CONST0_RTX (CCmode)); } + +bool +gen_cond_store (enum rtx_code code, rtx op0, rtx op1, rtx op2) +{ + enum machine_mode mode = GET_MODE (op0); + + gcc_assert (mode == SImode); + switch (code) + { + case EQ: + if (!register_operand (op1, mode)) + op1 = force_reg (mode, op1); + + if (TARGET_M32RX || TARGET_M32R2) + { + if (!reg_or_zero_operand (op2, mode)) + op2 = force_reg (mode, op2); + + emit_insn (gen_seq_insn_m32rx (op0, op1, op2)); + return true; + } + if (GET_CODE (op2) == CONST_INT && INTVAL (op2) == 0) + { + emit_insn (gen_seq_zero_insn (op0, op1)); + return true; + } + + if (!reg_or_eq_int16_operand (op2, mode)) + op2 = force_reg (mode, op2); + + emit_insn (gen_seq_insn (op0, op1, op2)); + return true; + + case NE: + if (GET_CODE (op2) != CONST_INT + || (INTVAL (op2) != 0 && satisfies_constraint_K (op2))) + { + rtx reg; + + if (reload_completed || reload_in_progress) + return false; + + reg = gen_reg_rtx (SImode); + emit_insn (gen_xorsi3 (reg, op1, op2)); + op1 = reg; + + if (!register_operand (op1, mode)) + op1 = force_reg (mode, op1); + + emit_insn (gen_sne_zero_insn (op0, op1)); + return true; + } + return false; + + case LT: + case GT: + if (code == GT) + { + rtx tmp = op2; + op2 = op1; + op1 = tmp; + code = LT; + } + + if (!register_operand (op1, mode)) + op1 = force_reg (mode, op1); + + if (!reg_or_int16_operand (op2, mode)) + op2 = force_reg (mode, op2); + + emit_insn (gen_slt_insn (op0, op1, op2)); + return true; + + case LTU: + case GTU: + if (code == GTU) + { + rtx tmp = op2; + op2 = op1; + op1 = tmp; + code = LTU; + } + + if (!register_operand (op1, mode)) + op1 = force_reg (mode, op1); + + if (!reg_or_int16_operand (op2, mode)) + op2 = force_reg (mode, op2); + + emit_insn (gen_sltu_insn (op0, op1, op2)); + return true; + + case GE: + case GEU: + if (!register_operand (op1, mode)) + op1 = force_reg (mode, op1); + + if (!reg_or_int16_operand (op2, mode)) + op2 = force_reg (mode, op2); + + if (code == GE) + emit_insn (gen_sge_insn (op0, op1, op2)); + else + emit_insn (gen_sgeu_insn (op0, op1, op2)); + return true; + + case LE: + case LEU: + if (!register_operand (op1, mode)) + op1 = force_reg (mode, op1); + + if (GET_CODE (op2) == CONST_INT) + { + HOST_WIDE_INT value = INTVAL (op2); + if (value >= 2147483647) + { + emit_move_insn (op0, const1_rtx); + return true; + } + + op2 = GEN_INT (value + 1); + if (value < -32768 || value >= 32767) + op2 = force_reg (mode, op2); + + if (code == LEU) + emit_insn (gen_sltu_insn (op0, op1, op2)); + else + emit_insn (gen_slt_insn (op0, op1, op2)); + return true; + } + + if (!register_operand (op2, mode)) + op2 = force_reg (mode, op2); + + if (code == LEU) + emit_insn (gen_sleu_insn (op0, op1, op2)); + else + emit_insn (gen_sle_insn (op0, op1, op2)); + return true; + + default: + gcc_unreachable (); + } +} + /* Split a 2 word move (DI or DF) into component parts. */ @@ -2291,8 +2432,8 @@ m32r_expand_block_move (rtx operands[]) if (bytes > MAX_MOVE_BYTES) { - emit_insn (gen_cmpsi (src_reg, final_src)); - emit_jump_insn (gen_bne (label)); + rtx test = gen_rtx_NE (VOIDmode, src_reg, final_src); + emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label)); } } diff --git a/gcc/config/m32r/m32r.h b/gcc/config/m32r/m32r.h index 9bc0fa98a0a..41dc07abad6 100644 --- a/gcc/config/m32r/m32r.h +++ b/gcc/config/m32r/m32r.h @@ -1495,12 +1495,6 @@ extern char m32r_punct_chars[256]; /* A function address in a call instruction. */ #define FUNCTION_MODE SImode -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. Note that we can't use "rtx" here - since it hasn't been defined! */ -extern struct rtx_def * m32r_compare_op0; -extern struct rtx_def * m32r_compare_op1; - /* M32R function types. */ enum m32r_function_type { diff --git a/gcc/config/m32r/m32r.md b/gcc/config/m32r/m32r.md index d117e1e6928..0c76a044ccc 100644 --- a/gcc/config/m32r/m32r.md +++ b/gcc/config/m32r/m32r.md @@ -1180,18 +1180,6 @@ ;; thus merge the compare and branch into one instruction, so they are ;; preferred. -(define_expand "cmpsi" - [(set (reg:CC 17) - (compare:CC (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "reg_or_cmp_int16_operand" "")))] - "" - " -{ - m32r_compare_op0 = operands[0]; - m32r_compare_op1 = operands[1]; - DONE; -}") - (define_insn "cmp_eqsi_zero_insn" [(set (reg:CC 17) (eq:CC (match_operand:SI 0 "register_operand" "r,r") @@ -1256,114 +1244,20 @@ ;; These control RTL generation for conditional jump insns. -(define_expand "beq" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (EQ, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (NE, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "bgt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (GT, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (LE, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (GE, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "blt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (LT, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (GTU, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (LEU, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (GEU, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "bltu" +(define_expand "cbranchsi4" + ; the comparison is emitted by gen_compare if needed. [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "reg_or_cmp_int16_operand" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] "" " { - operands[1] = gen_compare (LTU, m32r_compare_op0, m32r_compare_op1, FALSE); + operands[0] = gen_compare (GET_CODE (operands[0]), operands[1], operands[2], FALSE); + operands[1] = XEXP (operands[0], 0); + operands[2] = XEXP (operands[0], 1); }") ;; Now match both normal and inverted jump. @@ -1597,40 +1491,21 @@ ;; S operations to set a register to 1/0 based on a comparison -(define_expand "seq" - [(match_operand:SI 0 "register_operand" "")] +(define_expand "cstoresi4" + [(match_operand:SI 0 "register_operand" "") + (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "reg_or_cmp_int16_operand" "")])] "" " { - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) + if (GET_MODE (operands[0]) != SImode) FAIL; - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (TARGET_M32RX || TARGET_M32R2) - { - if (! reg_or_zero_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_seq_insn_m32rx (op0, op1, op2)); - DONE; - } - if (GET_CODE (op2) == CONST_INT && INTVAL (op2) == 0) - { - emit_insn (gen_seq_zero_insn (op0, op1)); - DONE; - } - - if (! reg_or_eq_int16_operand (op2, mode)) - op2 = force_reg (mode, op2); + if (!gen_cond_store (GET_CODE (operands[1]), + operands[0], operands[2], operands[3])) + FAIL; - emit_insn (gen_seq_insn (op0, op1, op2)); DONE; }") @@ -1739,41 +1614,6 @@ end_sequence (); }") -(define_expand "sne" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (GET_CODE (op2) != CONST_INT - || (INTVAL (op2) != 0 && satisfies_constraint_K (op2))) - { - rtx reg; - - if (reload_completed || reload_in_progress) - FAIL; - - reg = gen_reg_rtx (SImode); - emit_insn (gen_xorsi3 (reg, op1, op2)); - op1 = reg; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - emit_insn (gen_sne_zero_insn (op0, op1)); - DONE; - } - else - FAIL; -}") - (define_insn "sne_zero_insn" [(set (match_operand:SI 0 "register_operand" "=r") (ne:SI (match_operand:SI 1 "register_operand" "r") @@ -1801,29 +1641,6 @@ (ne:SI (reg:CC 17) (const_int 0)))] "") -(define_expand "slt" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (! reg_or_int16_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_slt_insn (op0, op1, op2)); - DONE; -}") - (define_insn "slt_insn" [(set (match_operand:SI 0 "register_operand" "=r,r") (lt:SI (match_operand:SI 1 "register_operand" "r,r") @@ -1847,46 +1664,6 @@ (ne:SI (reg:CC 17) (const_int 0)))] "") -(define_expand "sle" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (GET_CODE (op2) == CONST_INT) - { - HOST_WIDE_INT value = INTVAL (op2); - if (value >= 2147483647) - { - emit_move_insn (op0, const1_rtx); - DONE; - } - - op2 = GEN_INT (value+1); - if (value < -32768 || value >= 32767) - op2 = force_reg (mode, op2); - - emit_insn (gen_slt_insn (op0, op1, op2)); - DONE; - } - - if (! register_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_sle_insn (op0, op1, op2)); - DONE; -}") - (define_insn "sle_insn" [(set (match_operand:SI 0 "register_operand" "=r") (le:SI (match_operand:SI 1 "register_operand" "r") @@ -1933,52 +1710,6 @@ (neg:SI (match_dup 0)))] "") -(define_expand "sgt" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (! register_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_slt_insn (op0, op2, op1)); - DONE; -}") - -(define_expand "sge" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (! reg_or_int16_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_sge_insn (op0, op1, op2)); - DONE; -}") - (define_insn "sge_insn" [(set (match_operand:SI 0 "register_operand" "=r,r") (ge:SI (match_operand:SI 1 "register_operand" "r,r") @@ -2025,29 +1756,6 @@ (neg:SI (match_dup 0)))] "") -(define_expand "sltu" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (! reg_or_int16_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_sltu_insn (op0, op1, op2)); - DONE; -}") - (define_insn "sltu_insn" [(set (match_operand:SI 0 "register_operand" "=r,r") (ltu:SI (match_operand:SI 1 "register_operand" "r,r") @@ -2071,43 +1779,6 @@ (ne:SI (reg:CC 17) (const_int 0)))] "") -(define_expand "sleu" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (GET_CODE (op2) == CONST_INT) - { - HOST_WIDE_INT value = INTVAL (op2); - if (value >= 2147483647) - { - emit_move_insn (op0, const1_rtx); - DONE; - } - - op2 = GEN_INT (value+1); - if (value < 0 || value >= 32767) - op2 = force_reg (mode, op2); - - emit_insn (gen_sltu_insn (op0, op1, op2)); - DONE; - } - - if (! register_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_sleu_insn (op0, op1, op2)); - DONE; -}") - (define_insn "sleu_insn" [(set (match_operand:SI 0 "register_operand" "=r") (leu:SI (match_operand:SI 1 "register_operand" "r") @@ -2154,52 +1825,6 @@ (neg:SI (match_dup 0)))] "") -(define_expand "sgtu" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (! register_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_sltu_insn (op0, op2, op1)); - DONE; -}") - -(define_expand "sgeu" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (! reg_or_int16_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_sgeu_insn (op0, op1, op2)); - DONE; -}") - (define_insn "sgeu_insn" [(set (match_operand:SI 0 "register_operand" "=r,r") (geu:SI (match_operand:SI 1 "register_operand" "r,r") @@ -2546,8 +2171,8 @@ FAIL; /* Generate the comparison that will set the carry flag. */ - operands[1] = gen_compare (GET_CODE (operands[1]), m32r_compare_op0, - m32r_compare_op1, TRUE); + operands[1] = gen_compare (GET_CODE (operands[1]), XEXP (operands[1], 0), + XEXP (operands[1], 1), TRUE); /* See other movsicc pattern below for reason why. */ emit_insn (gen_blockage ()); diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c index 10bc7a0e66e..024e55de476 100644 --- a/gcc/config/m68hc11/m68hc11.c +++ b/gcc/config/m68hc11/m68hc11.c @@ -141,10 +141,6 @@ int m68hc11_sp_correction; int m68hc11_addr_mode; int m68hc11_mov_addr_mode; - -/* Comparison operands saved by the "tstxx" and "cmpxx" expand patterns. */ -rtx m68hc11_compare_op0; -rtx m68hc11_compare_op1; const struct processor_costs *m68hc11_cost; @@ -3877,7 +3873,11 @@ m68hc11_notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED) { cc_status.flags = 0; cc_status.value1 = XEXP (exp, 0); - cc_status.value2 = XEXP (exp, 1); + if (GET_CODE (XEXP (exp, 1)) == COMPARE + && XEXP (XEXP (exp, 1), 1) == CONST0_RTX (GET_MODE (XEXP (XEXP (exp, 1), 0)))) + cc_status.value2 = XEXP (XEXP (exp, 1), 0); + else + cc_status.value2 = XEXP (exp, 1); } else { @@ -5355,6 +5355,7 @@ m68hc11_rtx_costs_1 (rtx x, enum rtx_code code, case COMPARE: case ABS: case ZERO_EXTEND: + case ZERO_EXTRACT: total = extra_cost + rtx_cost (XEXP (x, 0), code, !optimize_size); if (mode == QImode) { @@ -5405,6 +5406,10 @@ m68hc11_rtx_costs (rtx x, int code, int outer_code, int *total, *total = 0; return true; + case ZERO_EXTRACT: + if (outer_code != COMPARE) + return false; + case ROTATE: case ROTATERT: case ASHIFT: diff --git a/gcc/config/m68hc11/m68hc11.h b/gcc/config/m68hc11/m68hc11.h index 35176592601..29d998dbf89 100644 --- a/gcc/config/m68hc11/m68hc11.h +++ b/gcc/config/m68hc11/m68hc11.h @@ -1498,8 +1498,6 @@ extern int current_function_interrupt; extern int current_function_trap; extern int current_function_far; -extern GTY(()) rtx m68hc11_compare_op0; -extern GTY(()) rtx m68hc11_compare_op1; extern GTY(()) rtx m68hc11_soft_tmp_reg; extern GTY(()) rtx ix_reg; extern GTY(()) rtx iy_reg; diff --git a/gcc/config/m68hc11/m68hc11.md b/gcc/config/m68hc11/m68hc11.md index 0d40278cebb..f4ff3ebbb4c 100644 --- a/gcc/config/m68hc11/m68hc11.md +++ b/gcc/config/m68hc11/m68hc11.md @@ -162,31 +162,11 @@ ;; An offsetable memory operand should be ok. The 'tst_operand' and ;; 'cmp_operand' predicates take care of this rule. ;; -(define_expand "tstsi" - [(set (cc0) - (match_operand:SI 0 "tst_operand" ""))] - "" - " -{ - m68hc11_compare_op0 = operands[0]; - m68hc11_compare_op1 = const0_rtx; - DONE; -}") - -(define_expand "tsthi" - [(set (cc0) - (match_operand:HI 0 "tst_operand" ""))] - "" - " -{ - m68hc11_compare_op0 = operands[0]; - m68hc11_compare_op1 = const0_rtx; - DONE; -}") (define_insn "tsthi_1" [(set (cc0) - (match_operand:HI 0 "tst_operand" "dx,*y"))] + (compare (match_operand:HI 0 "tst_operand" "dx,*y") + (const_int 0)))] "" "* { @@ -196,34 +176,26 @@ return \"cp%0\\t#0\"; }") -(define_expand "tstqi" - [(set (cc0) - (match_operand:QI 0 "tst_operand" ""))] - "" - " -{ - m68hc11_compare_op0 = operands[0]; - m68hc11_compare_op1 = const0_rtx; - DONE; -}") - ;; ;; Split pattern for (tst:QI) on an address register. ;; (define_split [(set (cc0) - (match_operand:QI 0 "hard_addr_reg_operand" ""))] + (compare (match_operand:QI 0 "hard_addr_reg_operand" "") + (const_int 0)))] "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode" [(parallel [(set (reg:HI D_REGNUM) (match_dup 1)) (set (match_dup 1) (reg:HI D_REGNUM))]) - (set (cc0) (reg:QI D_REGNUM)) + (set (cc0) (compare (reg:QI D_REGNUM) + (const_int 0))) (parallel [(set (reg:HI D_REGNUM) (match_dup 1)) (set (match_dup 1) (reg:HI D_REGNUM))])] "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));") (define_insn "tstqi_1" [(set (cc0) - (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))] + (compare (match_operand:QI 0 "tst_operand" "m,d,*A,!u") + (const_int 0)))] "" "* { @@ -252,8 +224,8 @@ ;; after Z register replacement. ;; (define_insn_and_split "tstqi_z_used" - [(set (cc0) - (match_operand:QI 0 "tst_operand" "m")) + [(set (cc0) (compare (match_operand:QI 0 "tst_operand" "m") + (const_int 0))) (use (match_operand:HI 1 "hard_reg_operand" "dxy")) (use (reg:HI SOFT_Z_REGNUM))] "" @@ -261,7 +233,8 @@ "z_replacement_completed == 2" [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1)) (set (match_dup 1) (match_dup 2)) - (set (cc0) (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))] "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);") @@ -270,21 +243,6 @@ ;;- Compare ;;-------------------------------------------------------------------- -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "tst_operand" "") - (match_operand:SI 1 "cmp_operand" "")))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[0] = force_reg (SImode, operands[0]); - - m68hc11_compare_op0 = operands[0]; - m68hc11_compare_op1 = operands[1]; - DONE; -}") - ;; ;; Comparison of a hard register with another one is provided because ;; it helps GCC to avoid to spill a pseudo hard register. @@ -316,21 +274,6 @@ (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))] "") -(define_expand "cmphi" - [(set (cc0) - (compare (match_operand:HI 0 "tst_operand" "") - (match_operand:HI 1 "cmp_operand" "")))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[0] = force_reg (HImode, operands[0]); - - m68hc11_compare_op0 = operands[0]; - m68hc11_compare_op1 = operands[1]; - DONE; -}") - (define_insn "cmphi_1_hc12" [(set (cc0) (compare (match_operand:HI 0 "tst_operand" @@ -419,25 +362,11 @@ operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM); operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));") -(define_expand "cmpqi" - [(set (cc0) - (compare (match_operand:QI 0 "tst_operand" "") - (match_operand:QI 1 "cmp_operand" "")))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[0] = force_reg (QImode, operands[0]); - - m68hc11_compare_op0 = operands[0]; - m68hc11_compare_op1 = operands[1]; - DONE; -}") - (define_insn "bitcmpqi" [(set (cc0) - (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u") - (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")))] + (compare (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u") + (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")) + (const_int 0)))] "" "@ bitb\\t%b1 @@ -448,8 +377,9 @@ (define_split /* "bitcmpqi" */ [(set (cc0) - (and:QI (match_operand:QI 0 "tst_operand" "") - (match_operand:QI 1 "hard_addr_reg_operand" "")))] + (compare (and:QI (match_operand:QI 0 "tst_operand" "") + (match_operand:QI 1 "hard_addr_reg_operand" "")) + (const_int 0)))] "z_replacement_completed == 2" [(set (match_dup 3) (match_dup 2)) (set (cc0) (and:QI (match_dup 0) (match_dup 4)))] @@ -459,8 +389,9 @@ (define_insn_and_split "bitcmpqi_z_used" [(set (cc0) - (and:QI (match_operand:QI 0 "tst_operand" "d,m") - (match_operand:QI 1 "cmp_operand" "m,d"))) + (compare (and:QI (match_operand:QI 0 "tst_operand" "d,m") + (match_operand:QI 1 "cmp_operand" "m,d")) + (const_int 0))) (use (match_operand:HI 2 "hard_reg_operand" "xy,xy")) (use (reg:HI SOFT_Z_REGNUM))] "" @@ -474,8 +405,9 @@ (define_insn "bitcmphi" [(set (cc0) - (and:HI (match_operand:HI 0 "tst_operand" "d") - (match_operand:HI 1 "const_int_operand" "i")))] + (compare (and:HI (match_operand:HI 0 "tst_operand" "d") + (match_operand:HI 1 "const_int_operand" "i")) + (const_int 0)))] "(INTVAL (operands[1]) & 0x0ff) == 0 || (INTVAL (operands[1]) & 0x0ff00) == 0" "* @@ -488,9 +420,10 @@ (define_insn "bitcmpqi_12" [(set (cc0) - (zero_extract (match_operand:HI 0 "tst_operand" "d") - (match_operand:HI 1 "const_int_operand" "i") - (match_operand:HI 2 "const_int_operand" "i")))] + (compare (zero_extract:HI (match_operand:HI 0 "tst_operand" "d") + (match_operand:HI 1 "const_int_operand" "i") + (match_operand:HI 2 "const_int_operand" "i")) + (const_int 0)))] "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8 || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16) && (unsigned) INTVAL (operands[2]) >= 8)" @@ -6134,155 +6067,66 @@ "" "bra\\t%l0") -(define_expand "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - m68hc11_expand_compare_and_branch (EQ, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); - DONE; -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - m68hc11_expand_compare_and_branch (NE, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); - DONE; -}") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) +(define_expand "cbranchsi4" + [(set (cc0) + (compare (match_operand:SI 1 "tst_operand" "") + (match_operand:SI 2 "cmp_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] "" " { - m68hc11_expand_compare_and_branch (GT, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); - DONE; -}") + if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM) + operands[1] = force_reg (SImode, operands[1]); -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - m68hc11_expand_compare_and_branch (GTU, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); + m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1], + operands[2], operands[3]); DONE; }") -(define_expand "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - m68hc11_expand_compare_and_branch (LT, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); - DONE; -}") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) +(define_expand "cbranchhi4" + [(set (cc0) + (compare (match_operand:HI 1 "tst_operand" "") + (match_operand:HI 2 "cmp_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] "" " { - m68hc11_expand_compare_and_branch (LTU, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); - DONE; -}") + if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM) + operands[1] = force_reg (HImode, operands[1]); -(define_expand "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - m68hc11_expand_compare_and_branch (GE, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); + m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1], + operands[2], operands[3]); DONE; }") -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) +(define_expand "cbranchqi4" + [(set (cc0) + (compare (match_operand:QI 1 "tst_operand" "") + (match_operand:QI 2 "cmp_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] "" " { - m68hc11_expand_compare_and_branch (GEU, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); - DONE; -}") + if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM) + operands[1] = force_reg (QImode, operands[1]); -(define_expand "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - m68hc11_expand_compare_and_branch (LE, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); + m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1], + operands[2], operands[3]); DONE; }") -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - m68hc11_expand_compare_and_branch (LEU, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); - DONE; -}") ;; ;; Test and branch instructions for 68HC12 for EQ and NE. @@ -7091,11 +6935,14 @@ (plus:HI (match_dup 0) (match_operand:HI 1 "const_int_operand" ""))) (set (cc0) - (match_operand:QI 2 "memory_operand" ""))] + (compare (match_operand:QI 2 "memory_operand" "") + (const_int 0)))] "TARGET_AUTO_INC_DEC && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1) && reg_mentioned_p (operands[0], operands[2])" - [(set (cc0) (match_dup 3))] + [(set (cc0) + (compare (match_dup 3) + (const_int 0)))] "if (INTVAL (operands[1]) == 1) operands[3] = gen_rtx_MEM (QImode, gen_rtx_PRE_INC (HImode, operands[0])); @@ -7326,7 +7173,8 @@ (match_operand:HI 1 "hard_reg_operand" "")) (set (match_dup 1) (plus:HI (match_dup 1) (match_operand:HI 2 "const_int_operand" ""))) - (set (cc0) (match_dup 0))] + (set (cc0) (compare (match_dup 0) + (const_int 0)))] "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])" [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2))) (set (cc0) (compare (match_dup 1) (match_dup 2)))] @@ -7339,7 +7187,8 @@ (plus:HI (match_dup 2) (match_operand:HI 3 "const_int_operand" ""))) (set (match_operand:HI 4 "memory_operand" "") (match_dup 2)) - (set (cc0) (match_operand:HI 5 "hard_reg_operand" ""))] + (set (cc0) (compare (match_operand:HI 5 "hard_reg_operand" "") + (const_int 0)))] "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2]) && !reg_mentioned_p (operands[2], operands[4]) diff --git a/gcc/config/m68k/constraints.md b/gcc/config/m68k/constraints.md index 592112a155b..8be423788d6 100644 --- a/gcc/config/m68k/constraints.md +++ b/gcc/config/m68k/constraints.md @@ -78,6 +78,11 @@ (and (match_code "const_double") (match_test "!(TARGET_68881 && standard_68881_constant_p (op))"))) +(define_constraint "H" + "Defines a real zero constant." + (and (match_code "const_double") + (match_test "op == CONST0_RTX (GET_MODE (op))"))) + (define_constraint "S" "Used for operands that satisfy 'm' when -mpcrel is in effect." (and (match_code "mem") diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index d3734efd9cf..1b5c83bb414 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -152,11 +152,6 @@ static bool m68k_return_in_memory (const_tree, const_tree); /* Specify the identification number of the library being built */ const char *m68k_library_id_string = "_current_shared_library_a5_offset_"; - -/* Nonzero if the last compare/test insn had FP operands. The - sCC expanders peek at this to determine what to do for the - 68060, which has no fsCC instructions. */ -int m68k_last_compare_had_fp_operands; /* Initialize the GCC target structure. */ @@ -1024,10 +1019,10 @@ m68k_expand_prologue (void) emit_move_insn (gen_rtx_REG (Pmode, D0_REG), limit); limit = gen_rtx_REG (Pmode, D0_REG); } - emit_insn (gen_cmpsi (stack_pointer_rtx, limit)); - emit_insn (gen_conditional_trap (gen_rtx_LTU (VOIDmode, - cc0_rtx, const0_rtx), - const1_rtx)); + emit_insn (gen_ctrapsi4 (gen_rtx_LTU (VOIDmode, + stack_pointer_rtx, limit), + stack_pointer_rtx, limit, + const1_rtx)); } fsize_with_regs = current_frame.size; @@ -1110,12 +1105,11 @@ m68k_expand_prologue (void) if (crtl->limit_stack) { if (REG_P (stack_limit_rtx)) - { - emit_insn (gen_cmpsi (stack_pointer_rtx, stack_limit_rtx)); - emit_insn (gen_conditional_trap (gen_rtx_LTU (VOIDmode, - cc0_rtx, const0_rtx), - const1_rtx)); - } + emit_insn (gen_ctrapsi4 (gen_rtx_LTU (VOIDmode, stack_pointer_rtx, + stack_limit_rtx), + stack_pointer_rtx, stack_limit_rtx, + const1_rtx)); + else if (GET_CODE (stack_limit_rtx) != SYMBOL_REF) warning (0, "stack limit expression is not supported"); } @@ -2418,6 +2412,11 @@ m68k_rtx_costs (rtx x, int code, int outer_code, int *total, *total = COSTS_N_INSNS (43); /* div.l */ return true; + case ZERO_EXTRACT: + if (outer_code == COMPARE) + *total = 0; + return false; + default: return false; } diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h index 875667dc428..ec0b35bdc1b 100644 --- a/gcc/config/m68k/m68k.h +++ b/gcc/config/m68k/m68k.h @@ -1060,7 +1060,6 @@ enum m68k_function_kind /* Variables in m68k.c; see there for details. */ extern const char *m68k_library_id_string; -extern int m68k_last_compare_had_fp_operands; extern enum target_device m68k_cpu; extern enum uarch_type m68k_tune; extern enum fpu_type m68k_fpu; diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index 68442fd5746..33058fa08b8 100644 --- a/gcc/config/m68k/m68k.md +++ b/gcc/config/m68k/m68k.md @@ -300,17 +300,10 @@ ;; (set (cc0) (const_int foo)) has no mode information. Such insns will ;; be folded while optimizing anyway. -(define_expand "tstdi" - [(parallel [(set (cc0) - (match_operand:DI 0 "nonimmediate_operand" "")) - (clobber (match_scratch:SI 1 "")) - (clobber (match_scratch:DI 2 ""))])] - "" - "m68k_last_compare_had_fp_operands = 0;") - -(define_insn "" +(define_insn "tstdi" [(set (cc0) - (match_operand:DI 0 "nonimmediate_operand" "am,d")) + (compare (match_operand:DI 0 "nonimmediate_operand" "am,d") + (const_int 0))) (clobber (match_scratch:SI 1 "=X,d")) (clobber (match_scratch:DI 2 "=d,X"))] "" @@ -339,17 +332,12 @@ return "sub%.l %1,%1\;tst%.l %R0\;subx%.l %1,%0"; }) -(define_expand "tstsi" - [(set (cc0) - (match_operand:SI 0 "nonimmediate_operand" ""))] - "" - "m68k_last_compare_had_fp_operands = 0;") - ;; If you think that the 68020 does not support tstl a0, ;; reread page B-167 of the 68020 manual more carefully. (define_insn "*tstsi_internal_68020_cf" [(set (cc0) - (match_operand:SI 0 "nonimmediate_operand" "rm"))] + (compare (match_operand:SI 0 "nonimmediate_operand" "rm") + (const_int 0)))] "TARGET_68020 || TARGET_COLDFIRE" "tst%.l %0" [(set_attr "type" "tst_l")]) @@ -357,7 +345,8 @@ ;; On an address reg, cmpw may replace cmpl. (define_insn "*tstsi_internal" [(set (cc0) - (match_operand:SI 0 "nonimmediate_operand" "dm,r"))] + (compare (match_operand:SI 0 "nonimmediate_operand" "dm,r") + (const_int 0)))] "!(TARGET_68020 || TARGET_COLDFIRE)" "@ tst%.l %0 @@ -366,43 +355,26 @@ ;; This can't use an address register, because comparisons ;; with address registers as second operand always test the whole word. -(define_expand "tsthi" - [(set (cc0) - (match_operand:HI 0 "nonimmediate_operand" ""))] - "" - "m68k_last_compare_had_fp_operands = 0;") - (define_insn "*tsthi_internal" [(set (cc0) - (match_operand:HI 0 "nonimmediate_operand" "dm"))] + (compare (match_operand:HI 0 "nonimmediate_operand" "dm") + (const_int 0)))] "" "tst%.w %0" [(set_attr "type" "tst")]) -(define_expand "tstqi" - [(set (cc0) - (match_operand:QI 0 "nonimmediate_operand" ""))] - "" - "m68k_last_compare_had_fp_operands = 0;") - (define_insn "*tstqi_internal" [(set (cc0) - (match_operand:QI 0 "nonimmediate_operand" "dm"))] + (compare (match_operand:QI 0 "nonimmediate_operand" "dm") + (const_int 0)))] "" "tst%.b %0" [(set_attr "type" "tst")]) -(define_expand "tst" - [(set (cc0) - (match_operand:FP 0 "general_operand" ""))] - "TARGET_HARD_FLOAT" -{ - m68k_last_compare_had_fp_operands = 1; -}) - (define_insn "tst_68881" [(set (cc0) - (match_operand:FP 0 "general_operand" "fm"))] + (compare (match_operand:FP 0 "general_operand" "fm") + (match_operand:FP 1 "const0_operand" "H")))] "TARGET_68881" { cc_status.flags = CC_IN_68881; @@ -414,7 +386,8 @@ (define_insn "tst_cf" [(set (cc0) - (match_operand:FP 0 "general_operand" "fU"))] + (compare (match_operand:FP 0 "general_operand" "fU") + (match_operand:FP 1 "const0_operand" "H")))] "TARGET_COLDFIRE_FPU" { cc_status.flags = CC_IN_68881; @@ -427,20 +400,11 @@ ;; compare instructions. -(define_expand "cmpdi" - [(parallel - [(set (cc0) - (compare (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "general_operand" ""))) - (clobber (match_scratch:DI 2 ""))])] - "" - "m68k_last_compare_had_fp_operands = 0;") - -(define_insn "" - [(set (cc0) - (compare (match_operand:DI 1 "nonimmediate_operand" "0,d") - (match_operand:DI 2 "general_operand" "d,0"))) - (clobber (match_scratch:DI 0 "=d,d"))] +(define_insn "*cmpdi_internal" + [(set (cc0) + (compare (match_operand:DI 1 "nonimmediate_operand" "0,d") + (match_operand:DI 2 "general_operand" "d,0"))) + (clobber (match_scratch:DI 0 "=d,d"))] "" { if (rtx_equal_p (operands[0], operands[1])) @@ -452,15 +416,71 @@ } }) -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:SI 1 "general_operand" "")))] +(define_insn "cmpdi" + [(set (cc0) + (compare (match_operand:DI 0 "nonimmediate_operand") + (match_operand:DI 1 "general_operand"))) + (clobber (match_scratch:DI 2))] + "" + "") + + +(define_expand "cbranchdi4" + [(set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:DI 1 "nonimmediate_operand") + (match_operand:DI 2 "general_operand")]) + (label_ref (match_operand 3 "")) + (pc)))] "" { - m68k_last_compare_had_fp_operands = 0; + if (operands[2] == const0_rtx) + emit_insn (gen_tstdi (operands[1])); + else + emit_insn (gen_cmpdi (operands[1], operands[2])); + operands[1] = cc0_rtx; + operands[2] = const0_rtx; +}) + +(define_expand "cstoredi4" + [(set (match_operand:QI 0 "register_operand") + (match_operator:QI 1 "ordered_comparison_operator" + [(match_operand:DI 2 "nonimmediate_operand") + (match_operand:DI 3 "general_operand")]))] + "" +{ + if (operands[3] == const0_rtx) + emit_insn (gen_tstdi (operands[2])); + else + emit_insn (gen_cmpdi (operands[2], operands[3])); + operands[2] = cc0_rtx; + operands[3] = const0_rtx; }) + +(define_expand "cbranchsi4" + [(set (cc0) + (compare (match_operand:SI 1 "nonimmediate_operand" "") + (match_operand:SI 2 "general_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "")) + (pc)))] + "" + "") + +(define_expand "cstoresi4" + [(set (cc0) + (compare (match_operand:SI 2 "nonimmediate_operand" "") + (match_operand:SI 3 "general_operand" ""))) + (set (match_operand:QI 0 "register_operand") + (match_operator:QI 1 "ordered_comparison_operator" + [(cc0) (const_int 0)]))] + "" + "") + + ;; A composite of the cmp, cmpa, cmpi & cmpm m68000 op codes. (define_insn "" [(set (cc0) @@ -500,12 +520,27 @@ } [(set_attr "type" "cmp_l")]) -(define_expand "cmphi" +(define_expand "cbranchhi4" [(set (cc0) - (compare (match_operand:HI 0 "nonimmediate_src_operand" "") - (match_operand:HI 1 "general_src_operand" "")))] - "!TARGET_COLDFIRE" - "m68k_last_compare_had_fp_operands = 0;") + (compare (match_operand:HI 1 "nonimmediate_src_operand" "") + (match_operand:HI 2 "m68k_subword_comparison_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "")) + (pc)))] + "" + "") + +(define_expand "cstorehi4" + [(set (cc0) + (compare (match_operand:HI 2 "nonimmediate_operand" "") + (match_operand:HI 3 "m68k_subword_comparison_operand" ""))) + (set (match_operand:QI 0 "register_operand") + (match_operator:QI 1 "ordered_comparison_operator" + [(cc0) (const_int 0)]))] + "" + "") (define_insn "" [(set (cc0) @@ -524,12 +559,27 @@ return "cmp%.w %d1,%d0"; }) -(define_expand "cmpqi" +(define_expand "cbranchqi4" [(set (cc0) - (compare (match_operand:QI 0 "nonimmediate_src_operand" "") - (match_operand:QI 1 "general_src_operand" "")))] - "!TARGET_COLDFIRE" - "m68k_last_compare_had_fp_operands = 0;") + (compare (match_operand:QI 1 "nonimmediate_src_operand" "") + (match_operand:QI 2 "m68k_subword_comparison_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "")) + (pc)))] + "" + "") + +(define_expand "cstoreqi4" + [(set (cc0) + (compare (match_operand:QI 2 "nonimmediate_src_operand" "") + (match_operand:QI 3 "m68k_subword_comparison_operand" ""))) + (set (match_operand:QI 0 "register_operand") + (match_operator:QI 1 "ordered_comparison_operator" + [(cc0) (const_int 0)]))] + "" + "") (define_insn "" [(set (cc0) @@ -548,12 +598,28 @@ return "cmp%.b %d1,%d0"; }) -(define_expand "cmp" +(define_expand "cbranch4" [(set (cc0) - (compare (match_operand:FP 0 "register_operand" "") - (match_operand:FP 1 "fp_src_operand" "")))] + (compare (match_operand:FP 1 "register_operand" "") + (match_operand:FP 2 "fp_src_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "")) + (pc)))] "TARGET_HARD_FLOAT" - "m68k_last_compare_had_fp_operands = 1;") + "") + +(define_expand "cstore4" + [(set (cc0) + (compare (match_operand:FP 2 "register_operand" "") + (match_operand:FP 3 "fp_src_operand" ""))) + (set (match_operand:QI 0 "register_operand") + (match_operator:QI 1 "m68k_cstore_comparison_operator" + [(cc0) (const_int 0)]))] + "TARGET_HARD_FLOAT && !(TUNE_68060 || TARGET_COLDFIRE_FPU)" + "if (TARGET_COLDFIRE && operands[2] != const0_rtx) + FAIL;") (define_insn "*cmp_68881" [(set (cc0) @@ -588,10 +654,13 @@ ;; from a MEM at a constant bit position if we can't use this as a constraint. (define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "memory_src_operand" "oS") - (const_int 1) - (minus:SI (const_int 7) - (match_operand:SI 1 "general_operand" "di"))))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:QI 0 "memory_src_operand" "oS") + (const_int 1) + (minus:SI (const_int 7) + (match_operand:SI 1 "general_operand" "di"))) + (const_int 0)))] "!TARGET_COLDFIRE" { return output_btst (operands, operands[1], operands[0], insn, 7); @@ -601,20 +670,26 @@ ;; has been deleted. (define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o") - (const_int 1) - (minus:SI (const_int 7) - (match_operand:SI 1 "general_operand" "d"))))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o") + (const_int 1) + (minus:SI (const_int 7) + (match_operand:SI 1 "general_operand" "d"))) + (const_int 0)))] "TARGET_COLDFIRE" { return output_btst (operands, operands[1], operands[0], insn, 7); }) (define_insn "" - [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d") - (const_int 1) - (minus:SI (const_int 31) - (match_operand:SI 1 "general_operand" "di"))))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d") + (const_int 1) + (minus:SI (const_int 31) + (match_operand:SI 1 "general_operand" "di"))) + (const_int 0)))] "" { return output_btst (operands, operands[1], operands[0], insn, 31); @@ -625,24 +700,30 @@ ;; are automatically masked to 3 or 5 bits. (define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o") - (const_int 1) - (minus:SI (const_int 7) - (and:SI - (match_operand:SI 1 "register_operand" "d") - (const_int 7)))))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o") + (const_int 1) + (minus:SI (const_int 7) + (and:SI + (match_operand:SI 1 "register_operand" "d") + (const_int 7)))) + (const_int 0)))] "" { return output_btst (operands, operands[1], operands[0], insn, 7); }) (define_insn "" - [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d") - (const_int 1) - (minus:SI (const_int 31) - (and:SI - (match_operand:SI 1 "register_operand" "d") - (const_int 31)))))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d") + (const_int 1) + (minus:SI (const_int 31) + (and:SI + (match_operand:SI 1 "register_operand" "d") + (const_int 31)))) + (const_int 0)))] "" { return output_btst (operands, operands[1], operands[0], insn, 31); @@ -651,9 +732,12 @@ ;; Nonoffsettable mem refs are ok in this one pattern ;; since we don't try to adjust them. (define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m") - (const_int 1) - (match_operand:SI 1 "const_int_operand" "n")))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "n")) + (const_int 0)))] "(unsigned) INTVAL (operands[1]) < 8 && !TARGET_COLDFIRE" { operands[1] = GEN_INT (7 - INTVAL (operands[1])); @@ -661,9 +745,12 @@ }) (define_insn "" - [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "do") - (const_int 1) - (match_operand:SI 1 "const_int_operand" "n")))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "do") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "n")) + (const_int 0)))] "!TARGET_COLDFIRE" { if (GET_CODE (operands[0]) == MEM) @@ -681,9 +768,12 @@ ;; The 'o' has been replaced with 'Q'. (define_insn "" - [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "dQ") - (const_int 1) - (match_operand:SI 1 "const_int_operand" "n")))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "dQ") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "n")) + (const_int 0)))] "TARGET_COLDFIRE" { if (GET_CODE (operands[0]) == MEM) @@ -5751,9 +5841,10 @@ (define_insn "" [(set (cc0) - (zero_extract:SI (match_operand:QI 0 "memory_operand" "o") - (match_operand:SI 1 "const_int_operand" "n") - (match_operand:SI 2 "general_operand" "dn")))] + (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o") + (match_operand:SI 1 "const_int_operand" "n") + (match_operand:SI 2 "general_operand" "dn")) + (const_int 0)))] "TARGET_68020 && TARGET_BITFIELD" { if (operands[1] == const1_rtx @@ -5776,9 +5867,10 @@ ;;; now handle the register cases (define_insn "" [(set (cc0) - (zero_extract:SI (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "const_int_operand" "n") - (match_operand:SI 2 "general_operand" "dn")))] + (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d") + (match_operand:SI 1 "const_int_operand" "n") + (match_operand:SI 2 "general_operand" "dn")) + (const_int 0)))] "TARGET_68020 && TARGET_BITFIELD" { if (operands[1] == const1_rtx @@ -5798,7 +5890,7 @@ (define_insn "scc0_di" [(set (match_operand:QI 0 "nonimmediate_operand" "=dm") - (match_operator 1 "valid_dbcc_comparison_p" + (match_operator 1 "ordered_comparison_operator" [(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))] "! TARGET_COLDFIRE" { @@ -5807,7 +5899,7 @@ (define_insn "scc0_di_5200" [(set (match_operand:QI 0 "nonimmediate_operand" "=d") - (match_operator 1 "valid_dbcc_comparison_p" + (match_operator 1 "ordered_comparison_operator" [(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))] "TARGET_COLDFIRE" { @@ -5816,7 +5908,7 @@ (define_insn "scc_di" [(set (match_operand:QI 0 "nonimmediate_operand" "=dm,dm") - (match_operator 1 "valid_dbcc_comparison_p" + (match_operator 1 "ordered_comparison_operator" [(match_operand:DI 2 "general_operand" "ro,r") (match_operand:DI 3 "general_operand" "r,ro")]))] "! TARGET_COLDFIRE" @@ -5826,7 +5918,7 @@ (define_insn "scc_di_5200" [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d") - (match_operator 1 "valid_dbcc_comparison_p" + (match_operator 1 "ordered_comparison_operator" [(match_operand:DI 2 "general_operand" "ro,r") (match_operand:DI 3 "general_operand" "r,ro")]))] "TARGET_COLDFIRE" @@ -5838,19 +5930,6 @@ ;; memory, but we cannot allow it to be in memory in case the address ;; needs to be reloaded. -(define_expand "seq" - [(set (match_operand:QI 0 "register_operand" "") - (eq:QI (cc0) (const_int 0)))] - "" -{ - if ((TUNE_68060 || TARGET_COLDFIRE_FPU) - && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}) - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (eq:QI (cc0) (const_int 0)))] @@ -5860,19 +5939,6 @@ OUTPUT_JUMP ("seq %0", "fseq %0", "seq %0"); }) -(define_expand "sne" - [(set (match_operand:QI 0 "register_operand" "") - (ne:QI (cc0) (const_int 0)))] - "" -{ - if ((TUNE_68060 || TARGET_COLDFIRE_FPU) - && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}) - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (ne:QI (cc0) (const_int 0)))] @@ -5882,19 +5948,6 @@ OUTPUT_JUMP ("sne %0", "fsne %0", "sne %0"); }) -(define_expand "sgt" - [(set (match_operand:QI 0 "register_operand" "") - (gt:QI (cc0) (const_int 0)))] - "" -{ - if ((TUNE_68060 || TARGET_COLDFIRE_FPU) - && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}) - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (gt:QI (cc0) (const_int 0)))] @@ -5904,12 +5957,6 @@ OUTPUT_JUMP ("sgt %0", "fsgt %0", 0); }) -(define_expand "sgtu" - [(set (match_operand:QI 0 "register_operand" "") - (gtu:QI (cc0) (const_int 0)))] - "" - "") - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (gtu:QI (cc0) (const_int 0)))] @@ -5919,19 +5966,6 @@ return "shi %0"; }) -(define_expand "slt" - [(set (match_operand:QI 0 "register_operand" "") - (lt:QI (cc0) (const_int 0)))] - "" -{ - if ((TUNE_68060 || TARGET_COLDFIRE_FPU) - && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}) - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (lt:QI (cc0) (const_int 0)))] @@ -5941,12 +5975,6 @@ OUTPUT_JUMP ("slt %0", "fslt %0", "smi %0"); }) -(define_expand "sltu" - [(set (match_operand:QI 0 "register_operand" "") - (ltu:QI (cc0) (const_int 0)))] - "" - "") - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (ltu:QI (cc0) (const_int 0)))] @@ -5956,19 +5984,6 @@ return "scs %0"; }) -(define_expand "sge" - [(set (match_operand:QI 0 "register_operand" "") - (ge:QI (cc0) (const_int 0)))] - "" -{ - if ((TUNE_68060 || TARGET_COLDFIRE_FPU) - && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}) - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (ge:QI (cc0) (const_int 0)))] @@ -5978,12 +5993,6 @@ OUTPUT_JUMP ("sge %0", "fsge %0", "spl %0"); }) -(define_expand "sgeu" - [(set (match_operand:QI 0 "register_operand" "") - (geu:QI (cc0) (const_int 0)))] - "" - "") - (define_insn "*scc" [(set (match_operand:QI 0 "register_operand" "=d") (geu:QI (cc0) (const_int 0)))] @@ -5994,19 +6003,6 @@ } [(set_attr "type" "scc")]) -(define_expand "sle" - [(set (match_operand:QI 0 "register_operand" "") - (le:QI (cc0) (const_int 0)))] - "" -{ - if ((TUNE_68060 || TARGET_COLDFIRE_FPU) - && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}) - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (le:QI (cc0) (const_int 0)))] @@ -6016,12 +6012,6 @@ OUTPUT_JUMP ("sle %0", "fsle %0", 0); }) -(define_expand "sleu" - [(set (match_operand:QI 0 "register_operand" "") - (leu:QI (cc0) (const_int 0)))] - "" - "") - (define_insn "*sls" [(set (match_operand:QI 0 "register_operand" "=d") (leu:QI (cc0) (const_int 0)))] @@ -6032,15 +6022,6 @@ } [(set_attr "type" "scc")]) -(define_expand "sordered" - [(set (match_operand:QI 0 "register_operand" "") - (ordered:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*sordered_1" [(set (match_operand:QI 0 "register_operand" "=d") (ordered:QI (cc0) (const_int 0)))] @@ -6050,15 +6031,6 @@ return "fsor %0"; }) -(define_expand "sunordered" - [(set (match_operand:QI 0 "register_operand" "") - (unordered:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*sunordered_1" [(set (match_operand:QI 0 "register_operand" "=d") (unordered:QI (cc0) (const_int 0)))] @@ -6068,15 +6040,6 @@ return "fsun %0"; }) -(define_expand "suneq" - [(set (match_operand:QI 0 "register_operand" "") - (uneq:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*suneq_1" [(set (match_operand:QI 0 "register_operand" "=d") (uneq:QI (cc0) (const_int 0)))] @@ -6086,15 +6049,6 @@ return "fsueq %0"; }) -(define_expand "sunge" - [(set (match_operand:QI 0 "register_operand" "") - (unge:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*sunge_1" [(set (match_operand:QI 0 "register_operand" "=d") (unge:QI (cc0) (const_int 0)))] @@ -6104,15 +6058,6 @@ return "fsuge %0"; }) -(define_expand "sungt" - [(set (match_operand:QI 0 "register_operand" "") - (ungt:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*sungt_1" [(set (match_operand:QI 0 "register_operand" "=d") (ungt:QI (cc0) (const_int 0)))] @@ -6122,15 +6067,6 @@ return "fsugt %0"; }) -(define_expand "sunle" - [(set (match_operand:QI 0 "register_operand" "") - (unle:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*sunle_1" [(set (match_operand:QI 0 "register_operand" "=d") (unle:QI (cc0) (const_int 0)))] @@ -6140,15 +6076,6 @@ return "fsule %0"; }) -(define_expand "sunlt" - [(set (match_operand:QI 0 "register_operand" "") - (unlt:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*sunlt_1" [(set (match_operand:QI 0 "register_operand" "=d") (unlt:QI (cc0) (const_int 0)))] @@ -6158,15 +6085,6 @@ return "fsult %0"; }) -(define_expand "sltgt" - [(set (match_operand:QI 0 "register_operand" "") - (ltgt:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*sltgt_1" [(set (match_operand:QI 0 "register_operand" "=d") (ltgt:QI (cc0) (const_int 0)))] @@ -7758,23 +7676,54 @@ "trap #7" [(set_attr "type" "trap")]) -(define_expand "conditional_trap" - [(trap_if (match_operator 0 "valid_dbcc_comparison_p" +(define_expand "ctrapdi4" + [(trap_if (match_operator 0 "ordered_comparison_operator" [(cc0) (const_int 0)]) - (match_operand:SI 1 "const_int_operand" "I"))] + (match_operand:SI 3 "const1_operand" ""))] "TARGET_68020" { - if (m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } + if (operands[2] == const0_rtx) + emit_insn (gen_tstdi (operands[1])); + else + emit_insn (gen_cmpdi (operands[1], operands[2])); + operands[1] = cc0_rtx; + operands[2] = const0_rtx; }) +(define_expand "ctrapsi4" + [(set (cc0) + (compare (match_operand:SI 1 "nonimmediate_operand" "") + (match_operand:SI 2 "general_operand" ""))) + (trap_if (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:SI 3 "const1_operand" ""))] + "TARGET_68020" + "") + +(define_expand "ctraphi4" + [(set (cc0) + (compare (match_operand:HI 1 "nonimmediate_src_operand" "") + (match_operand:HI 2 "general_src_operand" ""))) + (trap_if (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:SI 3 "const1_operand" ""))] + "TARGET_68020" + "") + +(define_expand "ctrapqi4" + [(set (cc0) + (compare (match_operand:QI 1 "nonimmediate_src_operand" "") + (match_operand:QI 2 "general_src_operand" ""))) + (trap_if (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:SI 3 "const1_operand" ""))] + "TARGET_68020" + "") + (define_insn "*conditional_trap" - [(trap_if (match_operator 0 "valid_dbcc_comparison_p" + [(trap_if (match_operator 0 "ordered_comparison_operator" [(cc0) (const_int 0)]) - (match_operand:SI 1 "const_int_operand" "I"))] + (match_operand:SI 1 "const1_operand" "I"))] "TARGET_68020 && ! flags_in_68881 ()" { switch (GET_CODE (operands[0])) diff --git a/gcc/config/m68k/predicates.md b/gcc/config/m68k/predicates.md index b43e55b8972..417989f6d6c 100644 --- a/gcc/config/m68k/predicates.md +++ b/gcc/config/m68k/predicates.md @@ -124,6 +124,11 @@ (and (match_code "eq,ne,gtu,ltu,geu,leu,gt,lt,ge,le") (match_test "valid_dbcc_comparison_p_2 (op, mode)"))) +(define_predicate "m68k_cstore_comparison_operator" + (if_then_else (match_test "TARGET_68881") + (match_operand 0 "comparison_operator") + (match_operand 0 "ordered_comparison_operator"))) + ;; Check for sign_extend or zero_extend. Used for bit-count operands. (define_predicate "extend_operator" @@ -193,6 +198,24 @@ (and (match_code "mem") (match_test "GET_CODE (XEXP (op, 0)) == PRE_DEC"))) +;; A zero constant. +(define_predicate "const0_operand" + (and (match_code "const_int,const_double,const_vector") + (match_test "op == CONST0_RTX (mode)"))) + +;; A one constant (operand for conditional_trap). +(define_predicate "const1_operand" + (and (match_code "const_int") + (match_test "op == const1_rtx"))) + +;; A valid operand for a HImode or QImode conditional operation. +;; ColdFire has tst patterns, but not cmp patterns. +(define_predicate "m68k_subword_comparison_operand" + (if_then_else (match_test "TARGET_COLDFIRE") + (and (match_code "const_int") + (match_test "op == const0_rtx")) + (match_operand 0 "general_src_operand"))) + ;; An operand for movsi_const0 pattern. (define_predicate "movsi_const0_operand" (and (match_operand 0 "nonimmediate_operand") diff --git a/gcc/config/mcore/mcore-protos.h b/gcc/config/mcore/mcore-protos.h index 93c7c11e766..331cf7191d7 100644 --- a/gcc/config/mcore/mcore-protos.h +++ b/gcc/config/mcore/mcore-protos.h @@ -46,21 +46,17 @@ extern rtx mcore_function_value (const_tree, const_tree); #ifdef RTX_CODE -extern GTY(()) rtx arch_compare_op0; -extern GTY(()) rtx arch_compare_op1; - extern const char * mcore_output_bclri (rtx, int); extern const char * mcore_output_bseti (rtx, int); extern const char * mcore_output_cmov (rtx *, int, const char *); extern char * mcore_output_call (rtx *, int); extern int mcore_is_dead (rtx, rtx); extern int mcore_expand_insv (rtx *); -extern int mcore_modify_comparison (RTX_CODE); extern bool mcore_expand_block_move (rtx *); extern const char * mcore_output_andn (rtx, rtx *); extern void mcore_print_operand_address (FILE *, rtx); extern void mcore_print_operand (FILE *, rtx, int); -extern rtx mcore_gen_compare_reg (RTX_CODE); +extern bool mcore_gen_compare (RTX_CODE, rtx, rtx); extern int mcore_symbolic_address_p (rtx); extern bool mcore_r15_operand_p (rtx); extern enum reg_class mcore_secondary_reload_class (enum reg_class, enum machine_mode, rtx); diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c index 24cc9406ed7..472bb75562a 100644 --- a/gcc/config/mcore/mcore.c +++ b/gcc/config/mcore/mcore.c @@ -57,11 +57,6 @@ long mcore_current_compilation_timestamp = 0; /* Global variables for machine-dependent things. */ -/* Saved operands from the last compare to use when we generate an scc - or bcc insn. */ -rtx arch_compare_op0; -rtx arch_compare_op1; - /* Provides the class number of the smallest class containing reg number. */ const int regno_reg_class[FIRST_PSEUDO_REGISTER] = @@ -519,26 +514,36 @@ mcore_rtx_costs (rtx x, int code, int outer_code, int * total, } } -/* Check to see if a comparison against a constant can be made more efficient - by incrementing/decrementing the constant to get one that is more efficient - to load. */ +/* Prepare the operands for a comparison. Return whether the branch/setcc + should reverse the operands. */ -int -mcore_modify_comparison (enum rtx_code code) +bool +mcore_gen_compare (enum rtx_code code, rtx op0, rtx op1) { - rtx op1 = arch_compare_op1; - + rtx cc_reg = gen_rtx_REG (CCmode, CC_REG); + bool invert; + if (GET_CODE (op1) == CONST_INT) { HOST_WIDE_INT val = INTVAL (op1); switch (code) { + case GTU: + /* Unsigned > 0 is the same as != 0; everything else is converted + below to LEU (reversed cmphs). */ + if (val == 0) + code = NE; + break; + + /* Check whether (LE A imm) can become (LT A imm + 1), + or (GT A imm) can become (GE A imm + 1). */ + case GT: case LE: if (CONST_OK_FOR_J (val + 1)) { - arch_compare_op1 = GEN_INT (val + 1); - return 1; + op1 = GEN_INT (val + 1); + code = code == LE ? LT : GE; } break; @@ -546,28 +551,18 @@ mcore_modify_comparison (enum rtx_code code) break; } } - - return 0; -} - -/* Prepare the operands for a comparison. */ - -rtx -mcore_gen_compare_reg (enum rtx_code code) -{ - rtx op0 = arch_compare_op0; - rtx op1 = arch_compare_op1; - rtx cc_reg = gen_rtx_REG (CCmode, CC_REG); - + if (CONSTANT_P (op1) && GET_CODE (op1) != CONST_INT) op1 = force_reg (SImode, op1); /* cmpnei: 0-31 (K immediate) cmplti: 1-32 (J immediate, 0 using btsti x,31). */ + invert = false; switch (code) { case EQ: /* Use inverted condition, cmpne. */ code = NE; + invert = true; /* Drop through. */ case NE: /* Use normal condition, cmpne. */ @@ -577,6 +572,7 @@ mcore_gen_compare_reg (enum rtx_code code) case LE: /* Use inverted condition, reversed cmplt. */ code = GT; + invert = true; /* Drop through. */ case GT: /* Use normal condition, reversed cmplt. */ @@ -586,6 +582,7 @@ mcore_gen_compare_reg (enum rtx_code code) case GE: /* Use inverted condition, cmplt. */ code = LT; + invert = true; /* Drop through. */ case LT: /* Use normal condition, cmplt. */ @@ -597,13 +594,10 @@ mcore_gen_compare_reg (enum rtx_code code) break; case GTU: /* Use inverted condition, cmple. */ - /* Unsigned > 0 is the same as != 0, but we need to invert the - condition, so we want to set code = EQ. This cannot be done - however, as the mcore does not support such a test. Instead - we cope with this case in the "bgtu" pattern itself so we - should never reach this point. */ + /* We coped with unsigned > 0 above. */ gcc_assert (GET_CODE (op1) != CONST_INT || INTVAL (op1) != 0); code = LEU; + invert = true; /* Drop through. */ case LEU: /* Use normal condition, reversed cmphs. */ @@ -613,6 +607,7 @@ mcore_gen_compare_reg (enum rtx_code code) case LTU: /* Use inverted condition, cmphs. */ code = GEU; + invert = true; /* Drop through. */ case GEU: /* Use normal condition, cmphs. */ @@ -624,9 +619,10 @@ mcore_gen_compare_reg (enum rtx_code code) break; } - emit_insn (gen_rtx_SET (VOIDmode, cc_reg, gen_rtx_fmt_ee (code, CCmode, op0, op1))); - - return cc_reg; + emit_insn (gen_rtx_SET (VOIDmode, + cc_reg, + gen_rtx_fmt_ee (code, CCmode, op0, op1))); + return invert; } int diff --git a/gcc/config/mcore/mcore.md b/gcc/config/mcore/mcore.md index 74906993e20..65b91588fc2 100644 --- a/gcc/config/mcore/mcore.md +++ b/gcc/config/mcore/mcore.md @@ -303,22 +303,6 @@ "" "cmphs %1,%0") -;; We save the compare operands in the cmpxx patterns and use them when -;; we generate the branch. - -;; We accept constants here, in case we can modify them to ones which -;; are more efficient to load. E.g. change 'x <= 62' to 'x < 63'. - -(define_expand "cmpsi" - [(set (reg:CC 17) (compare:CC (match_operand:SI 0 "mcore_compare_operand" "") - (match_operand:SI 1 "nonmemory_operand" "")))] - "" - " -{ arch_compare_op0 = operands[0]; - arch_compare_op1 = operands[1]; - DONE; -}") - ;; ------------------------------------------------------------------------- ;; Logical operations ;; ------------------------------------------------------------------------- @@ -1479,6 +1463,10 @@ ;; Define the real conditional branch instructions. ;; ------------------------------------------------------------------------ +;; At top-level, condition test are eq/ne, because we +;; are comparing against the condition register (which +;; has the result of the true relational test + (define_insn "branch_true" [(set (pc) (if_then_else (ne (reg:CC 17) (const_int 0)) (label_ref (match_operand 0 "" "")) @@ -1513,189 +1501,28 @@ ;; Conditional branch insns -;; At top-level, condition test are eq/ne, because we -;; are comparing against the condition register (which -;; has the result of the true relational test - -; There is no beq compare, so we reverse the branch arms. - -(define_expand "beq" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (EQ); -}") - -(define_expand "bne" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (NE); -}") - -; check whether (GT A imm) can become (LE A imm) with the branch reversed. -; if so, emit a (LT A imm + 1) in place of the (LE A imm). BRC - -(define_expand "bgt" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (mcore_modify_comparison (LE)) - { - emit_jump_insn (gen_reverse_blt (operands[0])); - DONE; - } - operands[1] = mcore_gen_compare_reg (GT); -}") - -; There is no ble compare, so we reverse the branch arms. -; reversed the condition and branch arms for ble -- the check_dbra_loop() -; transformation assumes that ble uses a branch-true with the label as -; as the target. BRC - -; check whether (LE A imm) can become (LT A imm + 1). - -(define_expand "ble" - [(set (pc) (if_then_else (eq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (mcore_modify_comparison (LE)) - { - emit_jump_insn (gen_blt (operands[0])); - DONE; - } - operands[1] = mcore_gen_compare_reg (LE); -}") - -; make generating a reversed blt simple -(define_expand "reverse_blt" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (LT); -}") - -(define_expand "blt" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (LT); -}") - -; There is no bge compare, so we reverse the branch arms. - -(define_expand "bge" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (GE); -}") - -; There is no gtu compare, so we reverse the branch arms - -;(define_expand "bgtu" -; [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) -; (pc) -; (label_ref (match_operand 0 "" ""))))] -; "" -; " -;{ -; if (GET_CODE (arch_compare_op1) == CONST_INT -; && INTVAL (arch_compare_op1) == 0) -; operands[1] = mcore_gen_compare_reg (NE); -; else -; { if (mcore_modify_comparison (GTU)) -; { -; emit_jump_insn (gen_bgeu (operands[0])); -; DONE; -; } -; operands[1] = mcore_gen_compare_reg (LEU); -; } -;}") - -(define_expand "bgtu" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - " -{ - if (GET_CODE (arch_compare_op1) == CONST_INT - && INTVAL (arch_compare_op1) == 0) - { - /* The inverse of '> 0' for an unsigned test is - '== 0' but we do not have such an instruction available. - Instead we must reverse the branch (back to the normal - ordering) and test '!= 0'. */ - - operands[1] = mcore_gen_compare_reg (NE); - - emit_jump_insn (gen_rtx_SET (VOIDmode, - pc_rtx, - gen_rtx_IF_THEN_ELSE (VOIDmode, - gen_rtx_NE (VOIDmode, - operands[1], - const0_rtx), - gen_rtx_LABEL_REF (VOIDmode,operands[0]), - pc_rtx))); - DONE; - } - operands[1] = mcore_gen_compare_reg (GTU); -}") - - -(define_expand "bleu" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] +(define_expand "cbranchsi4" + [(set (pc) + (if_then_else (match_operator:SI 0 "ordered_comparison_operator" + [(match_operand:SI 1 "mcore_compare_operand") + (match_operand:SI 2 "nonmemory_operand")]) + (label_ref (match_operand 3 "")) + (pc)))] "" " { - operands[1] = mcore_gen_compare_reg (LEU); -}") + bool invert; + invert = mcore_gen_compare (GET_CODE (operands[0]), + operands[1], operands[2]); -; There is no bltu compare, so we reverse the branch arms -(define_expand "bltu" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (LTU); + if (invert) + emit_jump_insn (gen_branch_false (operands[3])); + else + emit_jump_insn (gen_branch_true (operands[3])); + DONE; }") -(define_expand "bgeu" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (GEU); -}") ;; ------------------------------------------------------------------------ ;; Jump and linkage insns @@ -1853,118 +1680,23 @@ (set (match_dup 0) (eq:SI (reg:CC 17) (const_int 0)))]) -(define_expand "seq" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (NE); -}") - -(define_expand "sne" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (NE); -}") - -(define_expand "slt" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (LT); -}") - -; make generating a LT with the comparison reversed easy. BRC -(define_expand "reverse_slt" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (LT); -}") - -(define_expand "sge" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (LT); -}") - -; check whether (GT A imm) can become (LE A imm) with the comparison -; reversed. if so, emit a (LT A imm + 1) in place of the (LE A imm). BRC - -(define_expand "sgt" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - if (mcore_modify_comparison (LE)) - { - emit_insn (gen_reverse_slt (operands[0])); - DONE; - } - - operands[1] = mcore_gen_compare_reg (GT); -}") - -(define_expand "sle" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] - "" - " -{ - if (mcore_modify_comparison (LE)) - { - emit_insn (gen_slt (operands[0])); - DONE; - } - operands[1] = mcore_gen_compare_reg (GT); -}") - -(define_expand "sltu" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (GEU); -}") - -(define_expand "sgeu" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (GEU); -}") - -(define_expand "sgtu" +(define_expand "cstoresi4" [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] + (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SI 2 "mcore_compare_operand" "") + (match_operand:SI 3 "nonmemory_operand" "")]))] "" " { - operands[1] = mcore_gen_compare_reg (LEU); -}") + bool invert; + invert = mcore_gen_compare (GET_CODE (operands[1]), + operands[2], operands[3]); -(define_expand "sleu" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (LEU); + if (invert) + emit_insn (gen_mvcv (operands[0])); + else + emit_insn (gen_mvc (operands[0])); + DONE; }") (define_insn "incscc" @@ -3308,7 +3040,7 @@ rtx loop_label = gen_label_rtx (); rtx step = gen_reg_rtx (Pmode); rtx tmp = gen_reg_rtx (Pmode); - rtx memref; + rtx test, memref; #if 1 emit_insn (gen_movsi (tmp, operands[1])); @@ -3317,8 +3049,8 @@ if (GET_CODE (operands[1]) != CONST_INT) { out_label = gen_label_rtx (); - emit_insn (gen_cmpsi (step, tmp)); /* quick out */ - emit_jump_insn (gen_bgeu (out_label)); + test = gen_rtx_GEU (VOIDmode, step, tmp); /* quick out */ + emit_jump_insn (gen_cbranchsi4 (test, step, tmp, out_label)); } /* Run a loop that steps it incrementally. */ @@ -3332,8 +3064,8 @@ emit_insn(gen_subsi3(tmp, tmp, step)); /* Loop condition -- going back up. */ - emit_insn (gen_cmpsi (step, tmp)); - emit_jump_insn (gen_bltu (loop_label)); + test = gen_rtx_LTU (VOIDmode, step, tmp); + emit_jump_insn (gen_cbranchsi4 (test, step, tmp, loop_label)); if (out_label) emit_label (out_label); diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index b95461a4c4f..f2c67b84908 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -222,11 +222,11 @@ extern void mips_split_doubleword_move (rtx, rtx); extern const char *mips_output_move (rtx, rtx); extern void mips_restore_gp (rtx); #ifdef RTX_CODE -extern bool mips_expand_scc (enum rtx_code, rtx); -extern void mips_expand_conditional_branch (rtx *, enum rtx_code); +extern void mips_expand_scc (rtx *); +extern void mips_expand_conditional_branch (rtx *); extern void mips_expand_vcondv2sf (rtx, rtx, rtx, enum rtx_code, rtx, rtx); extern void mips_expand_conditional_move (rtx *); -extern void mips_expand_conditional_trap (enum rtx_code); +extern void mips_expand_conditional_trap (rtx); #endif extern bool mips_use_pic_fn_addr_reg_p (const_rtx); extern rtx mips_expand_call (enum mips_call_type, rtx, rtx, rtx, rtx, bool); diff --git a/gcc/config/mips/mips-ps-3d.md b/gcc/config/mips/mips-ps-3d.md index d4efe4cbf79..98932d85b11 100644 --- a/gcc/config/mips/mips-ps-3d.md +++ b/gcc/config/mips/mips-ps-3d.md @@ -58,7 +58,7 @@ MOVZ.PS. MOVT.PS and MOVF.PS depend on two CC values and move each item independently. */ - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) + if (GET_MODE_CLASS (GET_MODE (XEXP (operands[1], 0))) != MODE_INT) FAIL; mips_expand_conditional_move (operands); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 32c898bcf83..9d712d2f096 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -448,9 +448,6 @@ static int set_noat; normal branch. */ static bool mips_branch_likely; -/* The operands passed to the last cmpMM expander. */ -rtx cmp_operands[2]; - /* The current instruction-set architecture. */ enum processor_type mips_arch; const struct mips_cpu_info *mips_arch_info; @@ -4221,8 +4218,8 @@ mips_reversed_fp_cond (enum rtx_code *code) } /* Convert a comparison into something that can be used in a branch or - conditional move. cmp_operands[0] and cmp_operands[1] are the values - being compared and *CODE is the code used to compare them. + conditional move. On entry, *OP0 and *OP1 are the values being + compared and *CODE is the code used to compare them. Update *CODE, *OP0 and *OP1 so that they describe the final comparison. If NEED_EQ_NE_P, then only EQ or NE comparisons against zero are possible, @@ -4235,42 +4232,38 @@ mips_reversed_fp_cond (enum rtx_code *code) static void mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p) { - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) == MODE_INT) + rtx cmp_op0 = *op0; + rtx cmp_op1 = *op1; + + if (GET_MODE_CLASS (GET_MODE (*op0)) == MODE_INT) { - if (!need_eq_ne_p && cmp_operands[1] == const0_rtx) - { - *op0 = cmp_operands[0]; - *op1 = cmp_operands[1]; - } + if (!need_eq_ne_p && *op1 == const0_rtx) + ; else if (*code == EQ || *code == NE) { if (need_eq_ne_p) { - *op0 = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]); + *op0 = mips_zero_if_equal (cmp_op0, cmp_op1); *op1 = const0_rtx; } else - { - *op0 = cmp_operands[0]; - *op1 = force_reg (GET_MODE (*op0), cmp_operands[1]); - } + *op1 = force_reg (GET_MODE (cmp_op0), cmp_op1); } else { /* The comparison needs a separate scc instruction. Store the result of the scc in *OP0 and compare it against zero. */ bool invert = false; - *op0 = gen_reg_rtx (GET_MODE (cmp_operands[0])); - mips_emit_int_order_test (*code, &invert, *op0, - cmp_operands[0], cmp_operands[1]); + *op0 = gen_reg_rtx (GET_MODE (cmp_op0)); + mips_emit_int_order_test (*code, &invert, *op0, cmp_op0, cmp_op1); *code = (invert ? EQ : NE); *op1 = const0_rtx; } } - else if (ALL_FIXED_POINT_MODE_P (GET_MODE (cmp_operands[0]))) + else if (ALL_FIXED_POINT_MODE_P (GET_MODE (cmp_op0))) { *op0 = gen_rtx_REG (CCDSPmode, CCDSP_CC_REGNUM); - mips_emit_binary (*code, *op0, cmp_operands[0], cmp_operands[1]); + mips_emit_binary (*code, *op0, cmp_op0, cmp_op1); *code = NE; *op1 = const0_rtx; } @@ -4290,49 +4283,55 @@ mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p) ? gen_reg_rtx (CCmode) : gen_rtx_REG (CCmode, FPSW_REGNUM)); *op1 = const0_rtx; - mips_emit_binary (cmp_code, *op0, cmp_operands[0], cmp_operands[1]); + mips_emit_binary (cmp_code, *op0, cmp_op0, cmp_op1); } } -/* Try comparing cmp_operands[0] and cmp_operands[1] using rtl code CODE. - Store the result in TARGET and return true if successful. +/* Try performing the comparison in OPERANDS[1], whose arms are OPERANDS[2] + and OPERAND[3]. Store the result in OPERANDS[0]. - On 64-bit targets, TARGET may be narrower than cmp_operands[0]. */ + On 64-bit targets, the mode of the comparison and target will always be + SImode, thus possibly narrower than that of the comparison's operands. */ -bool -mips_expand_scc (enum rtx_code code, rtx target) +void +mips_expand_scc (rtx operands[]) { - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) - return false; + rtx target = operands[0]; + enum rtx_code code = GET_CODE (operands[1]); + rtx op0 = operands[2]; + rtx op1 = operands[3]; + + gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT); if (code == EQ || code == NE) { if (ISA_HAS_SEQ_SNE - && reg_imm10_operand (cmp_operands[1], GET_MODE (cmp_operands[1]))) - mips_emit_binary (code, target, cmp_operands[0], cmp_operands[1]); + && reg_imm10_operand (op1, GET_MODE (op1))) + mips_emit_binary (code, target, op0, op1); else { - rtx zie = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]); + rtx zie = mips_zero_if_equal (op0, op1); mips_emit_binary (code, target, zie, const0_rtx); } } else - mips_emit_int_order_test (code, 0, target, - cmp_operands[0], cmp_operands[1]); - return true; + mips_emit_int_order_test (code, 0, target, op0, op1); } -/* Compare cmp_operands[0] with cmp_operands[1] using comparison code - CODE and jump to OPERANDS[0] if the condition holds. */ +/* Compare OPERANDS[1] with OPERANDS[2] using comparison code + CODE and jump to OPERANDS[3] if the condition holds. */ void -mips_expand_conditional_branch (rtx *operands, enum rtx_code code) +mips_expand_conditional_branch (rtx *operands) { - rtx op0, op1, condition; + enum rtx_code code = GET_CODE (operands[0]); + rtx op0 = operands[1]; + rtx op1 = operands[2]; + rtx condition; mips_emit_compare (&code, &op0, &op1, TARGET_MIPS16); condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1); - emit_jump_insn (gen_condjump (condition, operands[0])); + emit_jump_insn (gen_condjump (condition, operands[3])); } /* Implement: @@ -4359,35 +4358,36 @@ mips_expand_vcondv2sf (rtx dest, rtx true_src, rtx false_src, cmp_result)); } -/* Compare cmp_operands[0] with cmp_operands[1] using the code of - OPERANDS[1]. Move OPERANDS[2] into OPERANDS[0] if the condition - holds, otherwise move OPERANDS[3] into OPERANDS[0]. */ +/* Perform the comparison in OPERANDS[1]. Move OPERANDS[2] into OPERANDS[0] + if the condition holds, otherwise move OPERANDS[3] into OPERANDS[0]. */ void mips_expand_conditional_move (rtx *operands) { - enum rtx_code code; - rtx cond, op0, op1; + rtx cond; + enum rtx_code code = GET_CODE (operands[1]); + rtx op0 = XEXP (operands[1], 0); + rtx op1 = XEXP (operands[1], 1); - code = GET_CODE (operands[1]); mips_emit_compare (&code, &op0, &op1, true); - cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1), + cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); emit_insn (gen_rtx_SET (VOIDmode, operands[0], gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), cond, operands[2], operands[3]))); } -/* Compare cmp_operands[0] with cmp_operands[1] using rtl code CODE, - then trap if the condition holds. */ +/* Perform the comparison in COMPARISON, then trap if the condition holds. */ void -mips_expand_conditional_trap (enum rtx_code code) +mips_expand_conditional_trap (rtx comparison) { rtx op0, op1; enum machine_mode mode; + enum rtx_code code; /* MIPS conditional trap instructions don't have GT or LE flavors, so we must swap the operands and convert to LT and GE respectively. */ + code = GET_CODE (comparison); switch (code) { case GT: @@ -4395,17 +4395,17 @@ mips_expand_conditional_trap (enum rtx_code code) case GTU: case LEU: code = swap_condition (code); - op0 = cmp_operands[1]; - op1 = cmp_operands[0]; + op0 = XEXP (comparison, 1); + op1 = XEXP (comparison, 0); break; default: - op0 = cmp_operands[0]; - op1 = cmp_operands[1]; + op0 = XEXP (comparison, 0); + op1 = XEXP (comparison, 1); break; } - mode = GET_MODE (cmp_operands[0]); + mode = GET_MODE (XEXP (comparison, 0)); op0 = force_reg (mode, op0); if (!arith_operand (op1, mode)) op1 = force_reg (mode, op1); @@ -6396,7 +6396,7 @@ static void mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length, HOST_WIDE_INT bytes_per_iter) { - rtx label, src_reg, dest_reg, final_src; + rtx label, src_reg, dest_reg, final_src, test; HOST_WIDE_INT leftover; leftover = length % bytes_per_iter; @@ -6423,11 +6423,11 @@ mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length, mips_emit_move (dest_reg, plus_constant (dest_reg, bytes_per_iter)); /* Emit the loop condition. */ + test = gen_rtx_NE (VOIDmode, src_reg, final_src); if (Pmode == DImode) - emit_insn (gen_cmpdi (src_reg, final_src)); + emit_jump_insn (gen_cbranchdi4 (test, src_reg, final_src, label)); else - emit_insn (gen_cmpsi (src_reg, final_src)); - emit_jump_insn (gen_bne (label)); + emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label)); /* Mop up any left-over bytes. */ if (leftover) diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 5c68688ccce..301a26ec1ad 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -3432,7 +3432,6 @@ extern int mips_dbx_regno[]; extern int mips_dwarf_regno[]; extern bool mips_split_p[]; extern bool mips_split_hi_p[]; -extern GTY(()) rtx cmp_operands[2]; extern enum processor_type mips_arch; /* which cpu to codegen for */ extern enum processor_type mips_tune; /* which cpu to schedule for */ extern int mips_isa; /* architectural level */ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 95ba6ba2620..713bd834730 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -791,11 +791,6 @@ (DF "ISA_HAS_FP4 && TARGET_FLOAT64") (V2SF "TARGET_SB1")]) -;; This code iterator allows all branch instructions to be generated from -;; a single define_expand template. -(define_code_iterator any_cond [unordered ordered unlt unge uneq ltgt unle ungt - eq ne gt ge lt le gtu geu ltu leu]) - ;; This code iterator allows signed and unsigned widening multiplications ;; to use the same template. (define_code_iterator any_extend [sign_extend zero_extend]) @@ -994,19 +989,15 @@ } [(set_attr "type" "trap")]) -(define_expand "conditional_trap" +(define_expand "ctrap4" [(trap_if (match_operator 0 "comparison_operator" - [(match_dup 2) (match_dup 3)]) - (match_operand 1 "const_int_operand"))] + [(match_operand:GPR 1 "reg_or_0_operand") + (match_operand:GPR 2 "arith_operand")]) + (match_operand 3 "const_0_operand"))] "ISA_HAS_COND_TRAP" { - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) == MODE_INT - && operands[1] == const0_rtx) - { - mips_expand_conditional_trap (GET_CODE (operands[0])); - DONE; - } - FAIL; + mips_expand_conditional_trap (operands[0]); + DONE; }) (define_insn "*conditional_trap" @@ -3243,6 +3234,7 @@ rtx reg3 = gen_reg_rtx (SImode); rtx label1 = gen_label_rtx (); rtx label2 = gen_label_rtx (); + rtx test; REAL_VALUE_TYPE offset; real_2expN (&offset, 31, DFmode); @@ -3252,8 +3244,8 @@ mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); do_pending_stack_adjust (); - emit_insn (gen_cmpdf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); + test = gen_rtx_GE (VOIDmode, operands[1], reg1); + emit_jump_insn (gen_cbranchdf4 (test, operands[1], reg1, label1)); emit_insn (gen_fix_truncdfsi2 (operands[0], operands[1])); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, @@ -3288,6 +3280,7 @@ rtx reg3 = gen_reg_rtx (DImode); rtx label1 = gen_label_rtx (); rtx label2 = gen_label_rtx (); + rtx test; REAL_VALUE_TYPE offset; real_2expN (&offset, 63, DFmode); @@ -3295,8 +3288,8 @@ mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); do_pending_stack_adjust (); - emit_insn (gen_cmpdf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); + test = gen_rtx_GE (VOIDmode, operands[1], reg1); + emit_jump_insn (gen_cbranchdf4 (test, operands[1], reg1, label1)); emit_insn (gen_fix_truncdfdi2 (operands[0], operands[1])); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, @@ -3330,6 +3323,7 @@ rtx reg3 = gen_reg_rtx (SImode); rtx label1 = gen_label_rtx (); rtx label2 = gen_label_rtx (); + rtx test; REAL_VALUE_TYPE offset; real_2expN (&offset, 31, SFmode); @@ -3337,8 +3331,8 @@ mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); do_pending_stack_adjust (); - emit_insn (gen_cmpsf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); + test = gen_rtx_GE (VOIDmode, operands[1], reg1); + emit_jump_insn (gen_cbranchsf4 (test, operands[1], reg1, label1)); emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1])); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, @@ -3372,6 +3366,7 @@ rtx reg3 = gen_reg_rtx (DImode); rtx label1 = gen_label_rtx (); rtx label2 = gen_label_rtx (); + rtx test; REAL_VALUE_TYPE offset; real_2expN (&offset, 63, SFmode); @@ -3379,8 +3374,8 @@ mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); do_pending_stack_adjust (); - emit_insn (gen_cmpsf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); + test = gen_rtx_GE (VOIDmode, operands[1], reg1); + emit_jump_insn (gen_cbranchsf4 (test, operands[1], reg1, label1)); emit_insn (gen_fix_truncsfdi2 (operands[0], operands[1])); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, @@ -5011,50 +5006,6 @@ ;; ;; .................... ;; -;; COMPARISONS -;; -;; .................... - -;; Flow here is rather complex: -;; -;; 1) The cmp{si,di,sf,df} routine is called. It deposits the arguments -;; into cmp_operands[] but generates no RTL. -;; -;; 2) The appropriate branch define_expand is called, which then -;; creates the appropriate RTL for the comparison and branch. -;; Different CC modes are used, based on what type of branch is -;; done, so that we can constrain things appropriately. There -;; are assumptions in the rest of GCC that break if we fold the -;; operands into the branches for integer operations, and use cc0 -;; for floating point, so we use the fp status register instead. -;; If needed, an appropriate temporary is created to hold the -;; of the integer compare. - -(define_expand "cmp" - [(set (cc0) - (compare:CC (match_operand:GPR 0 "register_operand") - (match_operand:GPR 1 "nonmemory_operand")))] - "" -{ - cmp_operands[0] = operands[0]; - cmp_operands[1] = operands[1]; - DONE; -}) - -(define_expand "cmp" - [(set (cc0) - (compare:CC (match_operand:SCALARF 0 "register_operand") - (match_operand:SCALARF 1 "register_operand")))] - "" -{ - cmp_operands[0] = operands[0]; - cmp_operands[1] = operands[1]; - DONE; -}) - -;; -;; .................... -;; ;; CONDITIONAL BRANCHES ;; ;; .................... @@ -5189,15 +5140,29 @@ [(set_attr "type" "branch") (set_attr "mode" "none")]) -(define_expand "b" +(define_expand "cbranch4" [(set (pc) - (if_then_else (any_cond:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "")) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:GPR 1 "register_operand") + (match_operand:GPR 2 "nonmemory_operand")]) + (label_ref (match_operand 3 "")) (pc)))] "" { - mips_expand_conditional_branch (operands, ); + mips_expand_conditional_branch (operands); + DONE; +}) + +(define_expand "cbranch4" + [(set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:SCALARF 1 "register_operand") + (match_operand:SCALARF 2 "register_operand")]) + (label_ref (match_operand 3 "")) + (pc)))] + "" +{ + mips_expand_conditional_branch (operands); DONE; }) @@ -5261,12 +5226,16 @@ ;; Destination is always set in SI mode. -(define_expand "seq" +(define_expand "cstore4" [(set (match_operand:SI 0 "register_operand") - (eq:SI (match_dup 1) - (match_dup 2)))] + (match_operator:SI 1 "mips_cstore_operator" + [(match_operand:GPR 2 "register_operand") + (match_operand:GPR 3 "nonmemory_operand")]))] "" - { if (mips_expand_scc (EQ, operands[0])) DONE; else FAIL; }) +{ + mips_expand_scc (operands); + DONE; +}) (define_insn "*seq_zero_" [(set (match_operand:GPR2 0 "register_operand" "=d") @@ -5299,16 +5268,6 @@ [(set_attr "type" "slt") (set_attr "mode" "")]) -;; "sne" uses sltu instructions in which the first operand is $0. -;; This isn't possible in mips16 code. - -(define_expand "sne" - [(set (match_operand:SI 0 "register_operand") - (ne:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_MIPS16" - { if (mips_expand_scc (NE, operands[0])) DONE; else FAIL; }) - (define_insn "*sne_zero_" [(set (match_operand:GPR2 0 "register_operand" "=d") (ne:GPR2 (match_operand:GPR 1 "register_operand" "d") @@ -5331,13 +5290,6 @@ [(set_attr "type" "slt") (set_attr "mode" "")]) -(define_expand "sgt" - [(set (match_operand:SI 0 "register_operand") - (any_gt:SI (match_dup 1) - (match_dup 2)))] - "" - { if (mips_expand_scc (, operands[0])) DONE; else FAIL; }) - (define_insn "*sgt_" [(set (match_operand:GPR2 0 "register_operand" "=d") (any_gt:GPR2 (match_operand:GPR 1 "register_operand" "d") @@ -5356,13 +5308,6 @@ [(set_attr "type" "slt") (set_attr "mode" "")]) -(define_expand "sge" - [(set (match_operand:SI 0 "register_operand") - (any_ge:SI (match_dup 1) - (match_dup 2)))] - "" - { if (mips_expand_scc (, operands[0])) DONE; else FAIL; }) - (define_insn "*sge_" [(set (match_operand:GPR2 0 "register_operand" "=d") (any_ge:GPR2 (match_operand:GPR 1 "register_operand" "d") @@ -5372,13 +5317,6 @@ [(set_attr "type" "slt") (set_attr "mode" "")]) -(define_expand "slt" - [(set (match_operand:SI 0 "register_operand") - (any_lt:SI (match_dup 1) - (match_dup 2)))] - "" - { if (mips_expand_scc (, operands[0])) DONE; else FAIL; }) - (define_insn "*slt_" [(set (match_operand:GPR2 0 "register_operand" "=d") (any_lt:GPR2 (match_operand:GPR 1 "register_operand" "d") @@ -5402,13 +5340,6 @@ (const_int 4) (const_int 8))])]) -(define_expand "sle" - [(set (match_operand:SI 0 "register_operand") - (any_le:SI (match_dup 1) - (match_dup 2)))] - "" - { if (mips_expand_scc (, operands[0])) DONE; else FAIL; }) - (define_insn "*sle_" [(set (match_operand:GPR2 0 "register_operand" "=d") (any_le:GPR2 (match_operand:GPR 1 "register_operand" "d") diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md index aaebdded674..d32eaf13f8e 100644 --- a/gcc/config/mips/predicates.md +++ b/gcc/config/mips/predicates.md @@ -285,6 +285,12 @@ (define_predicate "order_operator" (match_code "lt,ltu,le,leu,ge,geu,gt,gtu")) +;; For NE, cstore uses sltu instructions in which the first operand is $0. +;; This isn't possible in mips16 code. + +(define_predicate "mips_cstore_operator" + (ior (match_code "eq,gt,gtu,ge,geu,lt,ltu,le,leu") + (and (match_code "ne") (match_test "!TARGET_MIPS16")))) (define_predicate "small_data_pattern" (and (match_code "set,parallel,unspec,unspec_volatile,prefetch") diff --git a/gcc/config/mmix/mmix-protos.h b/gcc/config/mmix/mmix-protos.h index d71064aa6d7..d294d8ff0ed 100644 --- a/gcc/config/mmix/mmix-protos.h +++ b/gcc/config/mmix/mmix-protos.h @@ -96,7 +96,6 @@ extern void mmix_setup_frame_addresses (void); /* Needs to be ifdef:d for sake of enum rtx_code. */ extern enum machine_mode mmix_select_cc_mode (enum rtx_code, rtx, rtx); extern void mmix_canonicalize_comparison (enum rtx_code *, rtx *, rtx *); -extern int mmix_valid_comparison (enum rtx_code, enum machine_mode, rtx); extern rtx mmix_gen_compare_reg (enum rtx_code, rtx, rtx); #endif diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c index ceed8dbb6db..6ced05c04dc 100644 --- a/gcc/config/mmix/mmix.c +++ b/gcc/config/mmix/mmix.c @@ -2359,70 +2359,14 @@ mmix_shiftable_wyde_value (unsigned HOST_WIDEST_INT value) return 1; } -/* Returns zero if code and mode is not a valid condition from a - compare-type insn. Nonzero if it is. The parameter op, if non-NULL, - is the comparison of mode is CC-somethingmode. */ - -int -mmix_valid_comparison (RTX_CODE code, enum machine_mode mode, rtx op) -{ - if (mode == VOIDmode && op != NULL_RTX) - mode = GET_MODE (op); - - /* We don't care to look at these, they should always be valid. */ - if (mode == CCmode || mode == CC_UNSmode || mode == DImode) - return 1; - - if ((mode == CC_FPmode || mode == DFmode) - && (code == GT || code == LT)) - return 1; - - if ((mode == CC_FPEQmode || mode == DFmode) - && (code == EQ || code == NE)) - return 1; - - if ((mode == CC_FUNmode || mode == DFmode) - && (code == ORDERED || code == UNORDERED)) - return 1; - - return 0; -} - -/* X and Y are two things to compare using CODE. Emit a compare insn if - possible and return the rtx for the cc-reg in the proper mode, or - NULL_RTX if this is not a valid comparison. */ +/* X and Y are two things to compare using CODE. Return the rtx for + the cc-reg in the proper mode. */ rtx mmix_gen_compare_reg (RTX_CODE code, rtx x, rtx y) { enum machine_mode ccmode = SELECT_CC_MODE (code, x, y); - rtx cc_reg; - - /* FIXME: Do we get constants here? Of double mode? */ - enum machine_mode mode - = GET_MODE (x) == VOIDmode - ? GET_MODE (y) - : GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT ? DFmode : DImode; - - if (! mmix_valid_comparison (code, mode, x)) - return NULL_RTX; - - cc_reg = gen_reg_rtx (ccmode); - - /* FIXME: Can we avoid emitting a compare insn here? */ - if (! REG_P (x) && ! REG_P (y)) - x = force_reg (mode, x); - - /* If it's not quite right yet, put y in a register. */ - if (! REG_P (y) - && (GET_CODE (y) != CONST_INT - || ! CONST_OK_FOR_LETTER_P (INTVAL (y), 'I'))) - y = force_reg (mode, y); - - emit_insn (gen_rtx_SET (VOIDmode, cc_reg, - gen_rtx_COMPARE (ccmode, x, y))); - - return cc_reg; + return gen_reg_rtx (ccmode); } /* Local (static) helper functions. */ diff --git a/gcc/config/mmix/mmix.h b/gcc/config/mmix/mmix.h index a7fb6e5884e..5a0582df26b 100644 --- a/gcc/config/mmix/mmix.h +++ b/gcc/config/mmix/mmix.h @@ -81,11 +81,6 @@ along with GCC; see the file COPYING3. If not see #define MMIX_FUNCTION_ARG_SIZE(MODE, TYPE) \ ((MODE) != BLKmode ? GET_MODE_SIZE (MODE) : int_size_in_bytes (TYPE)) -/* Declarations for helper variables that are not tied to a particular - target macro. */ -extern GTY(()) rtx mmix_compare_op0; -extern GTY(()) rtx mmix_compare_op1; - /* Per-function machine data. This is normally an opaque type just defined and used in the tm.c file, but we need to see the definition in mmix.md too. */ diff --git a/gcc/config/mmix/mmix.md b/gcc/config/mmix/mmix.md index aa878af0f82..44263e47f64 100644 --- a/gcc/config/mmix/mmix.md +++ b/gcc/config/mmix/mmix.md @@ -440,30 +440,6 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2") "" "NOR %0,%1,0") -;; Since we don't have cc0, we do what is recommended in the manual; -;; store away the operands for use in the branch, scc or movcc insn. -(define_expand "cmpdi" - [(match_operand:DI 0 "register_operand" "") - (match_operand:DI 1 "mmix_reg_or_8bit_operand" "")] - "" - " -{ - mmix_compare_op0 = operands[0]; - mmix_compare_op1 = operands[1]; - DONE; -}") - -(define_expand "cmpdf" - [(match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "register_operand" "")] - "" - " -{ - mmix_compare_op0 = operands[0]; - mmix_compare_op1 = operands[1]; - DONE; -}") - ;; When the user-patterns expand, the resulting insns will match the ;; patterns below. @@ -474,7 +450,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2") ;; unsigned, so that has to be done another way. ;; FIXME: Perhaps a peep2 changing CCcode to a new code, that ;; gets folded here. -(define_insn "*cmpcc_folded" +(define_insn "*cmpdi_folded" [(set (match_operand:CC 0 "register_operand" "=r") (compare:CC (match_operand:DI 1 "register_operand" "r") @@ -485,7 +461,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2") && REGNO (operands[1]) == REGNO (operands[0])" "%% folded: cmp %0,%1,0") -(define_insn "*cmpcc" +(define_insn "*cmps" [(set (match_operand:CC 0 "register_operand" "=r") (compare:CC (match_operand:DI 1 "register_operand" "r") @@ -724,7 +700,8 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2") ;; 0 to use in movdfcc. (define_expand "movdfcc" - [(set (match_operand:DF 0 "register_operand" "") + [(set (match_dup 4) (match_dup 5)) + (set (match_operand:DF 0 "register_operand" "") (if_then_else:DF (match_operand 1 "comparison_operator" "") (match_operand:DF 2 "mmix_reg_or_0_operand" "") @@ -733,15 +710,20 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2") " { enum rtx_code code = GET_CODE (operands[1]); - rtx cc_reg = mmix_gen_compare_reg (code, mmix_compare_op0, - mmix_compare_op1); - if (cc_reg == NULL_RTX) + if (code == LE || code == GE) FAIL; - operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx); + + operands[4] = mmix_gen_compare_reg (code, XEXP (operands[1], 0), + XEXP (operands[1], 1)); + operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]), + XEXP (operands[1], 0), + XEXP (operands[1], 1)); + operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx); }") (define_expand "movdicc" - [(set (match_operand:DI 0 "register_operand" "") + [(set (match_dup 4) (match_dup 5)) + (set (match_operand:DI 0 "register_operand" "") (if_then_else:DI (match_operand 1 "comparison_operator" "") (match_operand:DI 2 "mmix_reg_or_8bit_operand" "") @@ -750,11 +732,15 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2") " { enum rtx_code code = GET_CODE (operands[1]); - rtx cc_reg = mmix_gen_compare_reg (code, mmix_compare_op0, - mmix_compare_op1); - if (cc_reg == NULL_RTX) + if (code == LE || code == GE) FAIL; - operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx); + + operands[4] = mmix_gen_compare_reg (code, XEXP (operands[1], 0), + XEXP (operands[1], 1)); + operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]), + XEXP (operands[1], 0), + XEXP (operands[1], 1)); + operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx); }") ;; FIXME: Is this the right way to do "folding" of CCmode -> DImode? @@ -854,175 +840,65 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2") CS%d2 %0,%3,%1 ZS%d2 %0,%3,%1") -;; FIXME: scc patterns will probably help, I just skip them +;; FIXME: scc insns will probably help, I just skip them ;; right now. Revisit. -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (EQ, mmix_compare_op0, mmix_compare_op1); -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] +(define_expand "cbranchdi4" + [(set (match_dup 4) + (match_op_dup 5 + [(match_operand:DI 1 "register_operand" "") + (match_operand:DI 2 "mmix_reg_or_8bit_operand" "")])) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" + [(match_dup 4) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" " { - operands[1] - = mmix_gen_compare_reg (NE, mmix_compare_op0, mmix_compare_op1); + operands[4] = mmix_gen_compare_reg (GET_CODE (operands[0]), + operands[1], operands[2]); + operands[5] = gen_rtx_fmt_ee (COMPARE, + GET_MODE (operands[4]), + operands[1], operands[2]); }") -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] +(define_expand "cbranchdf4" + [(set (match_dup 4) + (match_op_dup 5 + [(match_operand:DF 1 "register_operand" "") + (match_operand:DF 2 "register_operand" "")])) + (set (pc) + (if_then_else + (match_operator 0 "float_comparison_operator" + [(match_dup 4) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" " { - operands[1] - = mmix_gen_compare_reg (GT, mmix_compare_op0, mmix_compare_op1); -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (le (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (LE, mmix_compare_op0, mmix_compare_op1); - /* The head comment of optabs.c:can_compare_p says we're required to implement this, so we have to clean up the mess here. */ - if (operands[1] == NULL_RTX) + if (GET_CODE (operands[0]) == LE || GET_CODE (operands[0]) == GE) { - /* FIXME: Watch out for sharing/unsharing of rtx:es. */ - emit_jump_insn ((*bcc_gen_fctn[(int) LT]) (operands[0])); - emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (operands[0])); + enum rtx_code ltgt_code = GET_CODE (operands[0]) == LE ? LT : GT; + emit_cmp_and_jump_insns (operands[1], operands[2], ltgt_code, NULL_RTX, + DFmode, 0, operands[3]); + emit_cmp_and_jump_insns (operands[1], operands[2], EQ, NULL_RTX, + DFmode, 0, operands[3]); DONE; } -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (GE, mmix_compare_op0, mmix_compare_op1); - /* The head comment of optabs.c:can_compare_p says we're required to - implement this, so we have to clean up the mess here. */ - if (operands[1] == NULL_RTX) - { - /* FIXME: Watch out for sharing/unsharing of rtx:es. */ - emit_jump_insn ((*bcc_gen_fctn[(int) GT]) (operands[0])); - emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (operands[0])); - DONE; - } + operands[4] = mmix_gen_compare_reg (GET_CODE (operands[0]), + operands[1], operands[2]); + operands[5] = gen_rtx_fmt_ee (COMPARE, + GET_MODE (operands[4]), + operands[1], operands[2]); }") -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (LT, mmix_compare_op0, mmix_compare_op1); -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (GTU, mmix_compare_op0, mmix_compare_op1); -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (LEU, mmix_compare_op0, mmix_compare_op1); -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (GEU, mmix_compare_op0, mmix_compare_op1); -}") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (LTU, mmix_compare_op0, mmix_compare_op1); -}") - -(define_expand "bunordered" - [(set (pc) - (if_then_else (unordered (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (UNORDERED, mmix_compare_op0, mmix_compare_op1); - - if (operands[1] == NULL_RTX) - FAIL; -}") - -(define_expand "bordered" - [(set (pc) - (if_then_else (ordered (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (ORDERED, mmix_compare_op0, mmix_compare_op1); -}") ;; FIXME: we can emit an unordered-or-*not*-equal compare in one insn, but ;; there's no RTL code for it. Maybe revisit in future. diff --git a/gcc/config/mmix/predicates.md b/gcc/config/mmix/predicates.md index 5c5792e1f6b..b5773b87aee 100644 --- a/gcc/config/mmix/predicates.md +++ b/gcc/config/mmix/predicates.md @@ -17,6 +17,11 @@ ;; along with GCC; see the file COPYING3. If not see ;; . +;; Return 1 if OP is a valid comparison operator for "cbranch" instructions. +;; LE and GE are further lowered by the cbranchdf4 pattern. +(define_predicate "float_comparison_operator" + (match_code "ne, eq, le, ge, lt, gt, ordered, unordered")) + ;; True if this is a foldable comparison operator ;; - one where a the result of (compare:CC (reg) (const_int 0)) can be ;; replaced by (reg). */ diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c index ceb77e862c2..47fd5cbf933 100644 --- a/gcc/config/mn10300/mn10300.c +++ b/gcc/config/mn10300/mn10300.c @@ -2030,7 +2030,7 @@ mn10300_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed ATTRI { case CONST_INT: /* Zeros are extremely cheap. */ - if (INTVAL (x) == 0 && outer_code == SET) + if (INTVAL (x) == 0 && (outer_code == SET || outer_code == COMPARE)) *total = 0; /* If it fits in 8 bits, then it's still relatively cheap. */ else if (INT_8_BITS (INTVAL (x))) @@ -2059,6 +2059,12 @@ mn10300_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed ATTRI *total = 8; return true; + case ZERO_EXTRACT: + /* This is cheap, we can use btst. */ + if (outer_code == COMPARE) + *total = 0; + return false; + /* ??? This probably needs more work. */ case MOD: case DIV: diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md index 35b0e589cb5..a2b6296912f 100644 --- a/gcc/config/mn10300/mn10300.md +++ b/gcc/config/mn10300/mn10300.md @@ -826,34 +826,34 @@ ;; TEST INSTRUCTIONS ;; ---------------------------------------------------------------------- -;; Go ahead and define tstsi so we can eliminate redundant tst insns -;; when we start trying to optimize this port. -(define_insn "tstsi" - [(set (cc0) (match_operand:SI 0 "register_operand" "dax"))] - "" - "* return output_tst (operands[0], insn);" - [(set_attr "cc" "set_znv")]) - -(define_insn "" - [(set (cc0) (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx,!a")))] +(define_insn "*tst_extqisi_am33" + [(set (cc0) (compare + (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx,!a")) + (const_int 0)))] "TARGET_AM33" "* return output_tst (operands[0], insn);" [(set_attr "cc" "set_znv")]) -(define_insn "" - [(set (cc0) (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx")))] +(define_insn "*tst_extqisi" + [(set (cc0) (compare + (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx")) + (const_int 0)))] "" "* return output_tst (operands[0], insn);" [(set_attr "cc" "set_znv")]) -(define_insn "" - [(set (cc0) (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx,!a")))] +(define_insn "*tst_exthisi_am33" + [(set (cc0) (compare + (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx,!a")) + (const_int 0)))] "TARGET_AM33" "* return output_tst (operands[0], insn);" [(set_attr "cc" "set_znv")]) -(define_insn "" - [(set (cc0) (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx")))] +(define_insn "*tst_exthisi" + [(set (cc0) (compare + (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx")) + (const_int 0)))] "" "* return output_tst (operands[0], insn);" [(set_attr "cc" "set_znv")]) @@ -874,17 +874,22 @@ ;; possibly satisfied, so just mark the alternative with a `!', so ;; that it is not considered by reload. -(define_insn "cmpsi" +(define_insn "*cmpsi" [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "!*d*a*x,dax") - (match_operand:SI 1 "nonmemory_operand" "*0,daxi")))] + (compare (match_operand:SI 0 "register_operand" "!*d*a*x,dax,dax") + (match_operand:SI 1 "nonmemory_operand" "*0,I,daxi")))] "" - "@ - btst 0,d0 - cmp %1,%0" - [(set_attr "cc" "compare,compare")]) + "* +{ + if (which_alternative == 0) + return \"btst 0,d0\"; + if (which_alternative == 1) + return output_tst (operands[0], insn); + return \"cmp %1,%0\"; +}" + [(set_attr "cc" "compare,set_znv,compare")]) -(define_insn "cmpsf" +(define_insn "*cmpsf" [(set (cc0) (compare (match_operand:SF 0 "register_operand" "f,f") (match_operand:SF 1 "nonmemory_operand" "f,F")))] @@ -1510,9 +1515,10 @@ (define_insn "" [(set (cc0) - (zero_extract:SI (match_operand:SI 0 "register_operand" "dx") - (match_operand 1 "const_int_operand" "") - (match_operand 2 "const_int_operand" "")))] + (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "dx") + (match_operand 1 "const_int_operand" "") + (match_operand 2 "const_int_operand" "")) + (const_int 0)))] "" "* { @@ -1537,9 +1543,10 @@ (define_insn "" [(set (cc0) - (zero_extract:SI (match_operand:QI 0 "general_operand" "R,dx") - (match_operand 1 "const_int_operand" "") - (match_operand 2 "const_int_operand" "")))] + (compare (zero_extract:SI (match_operand:QI 0 "general_operand" "R,dx") + (match_operand 1 "const_int_operand" "") + (match_operand 2 "const_int_operand" "")) + (const_int 0)))] "mask_ok_for_mem_btst (INTVAL (operands[1]), INTVAL (operands[2]))" "* { @@ -1581,17 +1588,19 @@ [(set_attr "cc" "clobber")]) (define_insn "" - [(set (cc0) (and:SI (match_operand:SI 0 "register_operand" "dx") - (match_operand:SI 1 "const_int_operand" "")))] + [(set (cc0) (compare (and:SI (match_operand:SI 0 "register_operand" "dx") + (match_operand:SI 1 "const_int_operand" "")) + (const_int 0)))] "" "btst %1,%0" [(set_attr "cc" "clobber")]) (define_insn "" [(set (cc0) - (and:SI - (subreg:SI (match_operand:QI 0 "general_operand" "R,dx") 0) - (match_operand:SI 1 "const_8bit_operand" "")))] + (compare (and:SI + (subreg:SI (match_operand:QI 0 "general_operand" "R,dx") 0) + (match_operand:SI 1 "const_8bit_operand" "")) + (const_int 0)))] "" "@ btst %U1,%A0 @@ -1603,97 +1612,34 @@ ;; JUMP INSTRUCTIONS ;; ---------------------------------------------------------------------- -;; Conditional jump instructions - -(define_expand "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] +(define_expand "cbranchsi4" + [(set (cc0) + (compare (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" ""))) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" "") -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" +(define_expand "cbranchsf4" + [(set (cc0) + (compare (match_operand:SF 1 "register_operand" "") + (match_operand:SF 2 "nonmemory_operand" ""))) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_AM33_2" "") -(define_expand "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") -(define_expand "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") +;; Conditional jump instructions (define_insn "" [(set (pc) @@ -1774,11 +1720,13 @@ rtx table = gen_reg_rtx (SImode); rtx index = gen_reg_rtx (SImode); rtx addr = gen_reg_rtx (Pmode); + rtx test; emit_move_insn (table, gen_rtx_LABEL_REF (VOIDmode, operands[3])); emit_move_insn (index, plus_constant (operands[0], - INTVAL (operands[1]))); - emit_insn (gen_cmpsi (index, operands[2])); - emit_jump_insn (gen_bgtu (operands[4])); + test = gen_rtx_fmt_ee (GTU, VOIDmode, index, operands[2]); + emit_jump_insn (gen_cbranchsi4 (test, index, operands[2], operands[4])); + emit_move_insn (index, gen_rtx_ASHIFT (SImode, index, const2_rtx)); emit_move_insn (addr, gen_rtx_MEM (SImode, gen_rtx_PLUS (SImode, table, index))); @@ -2518,7 +2466,8 @@ ;; This will work on the mn10200 because we can check the ZX flag ;; if the comparison is in HImode. (define_peephole - [(set (cc0) (match_operand:SI 0 "register_operand" "dx")) + [(set (cc0) (compare (match_operand:SI 0 "register_operand" "dx") + (const_int 0))) (set (pc) (if_then_else (ge (cc0) (const_int 0)) (match_operand 1 "" "") (pc)))] @@ -2527,7 +2476,8 @@ [(set_attr "cc" "clobber")]) (define_peephole - [(set (cc0) (match_operand:SI 0 "register_operand" "dx")) + [(set (cc0) (compare (match_operand:SI 0 "register_operand" "dx") + (const_int 0))) (set (pc) (if_then_else (lt (cc0) (const_int 0)) (match_operand 1 "" "") (pc)))] @@ -2536,7 +2486,8 @@ [(set_attr "cc" "clobber")]) (define_peephole - [(set (cc0) (match_operand:SI 0 "register_operand" "dx")) + [(set (cc0) (compare (match_operand:SI 0 "register_operand" "dx") + (const_int 0))) (set (pc) (if_then_else (ge (cc0) (const_int 0)) (pc) (match_operand 1 "" "")))] @@ -2545,7 +2496,8 @@ [(set_attr "cc" "clobber")]) (define_peephole - [(set (cc0) (match_operand:SI 0 "register_operand" "dx")) + [(set (cc0) (compare (match_operand:SI 0 "register_operand" "dx") + (const_int 0))) (set (pc) (if_then_else (lt (cc0) (const_int 0)) (pc) (match_operand 1 "" "")))] diff --git a/gcc/config/pa/pa-protos.h b/gcc/config/pa/pa-protos.h index 3cd1f8580bc..526081acd52 100644 --- a/gcc/config/pa/pa-protos.h +++ b/gcc/config/pa/pa-protos.h @@ -56,7 +56,6 @@ extern void output_arg_descriptor (rtx); extern void output_global_address (FILE *, rtx, int); extern void print_operand (FILE *, rtx, int); extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx); -extern struct rtx_def *gen_cmp_fp (enum rtx_code, rtx, rtx); extern void hppa_encode_label (rtx); extern int arith11_operand (rtx, enum machine_mode); extern int adddi3_operand (rtx, enum machine_mode); @@ -96,7 +95,7 @@ extern int fmpyaddoperands (rtx *); extern int fmpysuboperands (rtx *); extern int call_operand_address (rtx, enum machine_mode); extern int ior_operand (rtx, enum machine_mode); -extern void emit_bcond_fp (enum rtx_code, rtx); +extern void emit_bcond_fp (rtx[]); extern int emit_move_sequence (rtx *, enum machine_mode, rtx); extern int emit_hpdiv_const (rtx *, int); extern int is_function_label_plus_const (rtx); diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 80f5fe90bc2..882fac1aad4 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -165,11 +165,6 @@ static GTY(()) section *som_readonly_data_section; static GTY(()) section *som_one_only_readonly_data_section; static GTY(()) section *som_one_only_data_section; -/* Save the operands last given to a compare for use when we - generate a scc or bcc insn. */ -rtx hppa_compare_op0, hppa_compare_op1; -enum cmp_type hppa_branch_type; - /* Which cpu we are scheduling for. */ enum processor_type pa_cpu = TARGET_SCHED_DEFAULT; @@ -4383,6 +4378,19 @@ return_addr_rtx (int count, rtx frameaddr) rtx saved_rp; rtx ins; + /* Instruction stream at the normal return address for the export stub: + + 0x4bc23fd1 | stub+8: ldw -18(sr0,sp),rp + 0x004010a1 | stub+12: ldsid (sr0,rp),r1 + 0x00011820 | stub+16: mtsp r1,sr0 + 0xe0400002 | stub+20: be,n 0(sr0,rp) + + 0xe0400002 must be specified as -532676606 so that it won't be + rejected as an invalid immediate operand on 64-bit hosts. */ + + HOST_WIDE_INT insns[4] = {0x4bc23fd1, 0x004010a1, 0x00011820, -532676606}; + int i; + if (count != 0) return NULL_RTX; @@ -4391,6 +4399,9 @@ return_addr_rtx (int count, rtx frameaddr) if (TARGET_64BIT || TARGET_NO_SPACE_REGS) return rp; + /* If there is no export stub then just use the value saved from + the return pointer register. */ + saved_rp = gen_reg_rtx (Pmode); emit_move_insn (saved_rp, rp); @@ -4402,37 +4413,15 @@ return_addr_rtx (int count, rtx frameaddr) label = gen_label_rtx (); /* Check the instruction stream at the normal return address for the - export stub: - - 0x4bc23fd1 | stub+8: ldw -18(sr0,sp),rp - 0x004010a1 | stub+12: ldsid (sr0,rp),r1 - 0x00011820 | stub+16: mtsp r1,sr0 - 0xe0400002 | stub+20: be,n 0(sr0,rp) + export stub. If it is an export stub, than our return address is + really in -24[frameaddr]. */ - If it is an export stub, than our return address is really in - -24[frameaddr]. */ - - emit_cmp_insn (gen_rtx_MEM (SImode, ins), GEN_INT (0x4bc23fd1), NE, - NULL_RTX, SImode, 1); - emit_jump_insn (gen_bne (label)); - - emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 4)), - GEN_INT (0x004010a1), NE, NULL_RTX, SImode, 1); - emit_jump_insn (gen_bne (label)); - - emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 8)), - GEN_INT (0x00011820), NE, NULL_RTX, SImode, 1); - emit_jump_insn (gen_bne (label)); - - /* 0xe0400002 must be specified as -532676606 so that it won't be - rejected as an invalid immediate operand on 64-bit hosts. */ - emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 12)), - GEN_INT (-532676606), NE, NULL_RTX, SImode, 1); - - /* If there is no export stub then just use the value saved from - the return pointer register. */ - - emit_jump_insn (gen_bne (label)); + for (i = 0; i < 3; i++) + { + rtx op0 = gen_rtx_MEM (SImode, plus_constant (ins, i * 4)); + rtx op1 = GEN_INT (insns[i]); + emit_cmp_and_jump_insns (op0, op1, NE, NULL, SImode, 0, label); + } /* Here we know that our return address points to an export stub. We don't want to return the address of the export stub, @@ -4446,30 +4435,32 @@ return_addr_rtx (int count, rtx frameaddr) -24)))); emit_label (label); + return saved_rp; } void -emit_bcond_fp (enum rtx_code code, rtx operand0) +emit_bcond_fp (rtx operands[]) { + enum rtx_code code = GET_CODE (operands[0]); + rtx operand0 = operands[1]; + rtx operand1 = operands[2]; + rtx label = operands[3]; + + emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (CCFPmode, 0), + gen_rtx_fmt_ee (code, CCFPmode, operand0, operand1))); + emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, gen_rtx_IF_THEN_ELSE (VOIDmode, - gen_rtx_fmt_ee (code, + gen_rtx_fmt_ee (NE, VOIDmode, gen_rtx_REG (CCFPmode, 0), const0_rtx), - gen_rtx_LABEL_REF (VOIDmode, operand0), + gen_rtx_LABEL_REF (VOIDmode, label), pc_rtx))); } -rtx -gen_cmp_fp (enum rtx_code code, rtx operand0, rtx operand1) -{ - return gen_rtx_SET (VOIDmode, gen_rtx_REG (CCFPmode, 0), - gen_rtx_fmt_ee (code, CCFPmode, operand0, operand1)); -} - /* Adjust the cost of a scheduling dependency. Return the new cost of a dependency LINK or INSN on DEP_INSN. COST is the current cost. */ diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index 303bdd341df..576916f5b7b 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -21,14 +21,6 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ -enum cmp_type /* comparison type */ -{ - CMP_SI, /* compare integers */ - CMP_SF, /* compare single precision floats */ - CMP_DF, /* compare double precision floats */ - CMP_MAX /* max comparison type */ -}; - /* For long call handling. */ extern unsigned long total_code_bytes; @@ -755,10 +747,6 @@ struct hppa_args {int words, nargs_prototype, incoming, indirect; }; ? PARM_BOUNDARY : MAX_PARM_BOUNDARY) -extern GTY(()) rtx hppa_compare_op0; -extern GTY(()) rtx hppa_compare_op1; -extern enum cmp_type hppa_branch_type; - /* On HPPA, we emit profiling code as rtl via PROFILE_HOOK rather than as assembly via FUNCTION_PROFILER. Just output a local label. We can't use the function label because the GAS SOM target can't diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index b845182d592..1f5a69b9352 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -653,64 +653,6 @@ ;; Compare instructions. ;; This controls RTL generation and register allocation. -;; We generate RTL for comparisons and branches by having the cmpxx -;; patterns store away the operands. Then, the scc and bcc patterns -;; emit RTL for both the compare and the branch. -;; - -(define_expand "cmpdi" - [(set (reg:CC 0) - (compare:CC (match_operand:DI 0 "reg_or_0_operand" "") - (match_operand:DI 1 "register_operand" "")))] - "TARGET_64BIT" - - " -{ - hppa_compare_op0 = operands[0]; - hppa_compare_op1 = operands[1]; - hppa_branch_type = CMP_SI; - DONE; -}") - -(define_expand "cmpsi" - [(set (reg:CC 0) - (compare:CC (match_operand:SI 0 "reg_or_0_operand" "") - (match_operand:SI 1 "arith5_operand" "")))] - "" - " -{ - hppa_compare_op0 = operands[0]; - hppa_compare_op1 = operands[1]; - hppa_branch_type = CMP_SI; - DONE; -}") - -(define_expand "cmpsf" - [(set (reg:CCFP 0) - (compare:CCFP (match_operand:SF 0 "reg_or_0_operand" "") - (match_operand:SF 1 "reg_or_0_operand" "")))] - "! TARGET_SOFT_FLOAT" - " -{ - hppa_compare_op0 = operands[0]; - hppa_compare_op1 = operands[1]; - hppa_branch_type = CMP_SF; - DONE; -}") - -(define_expand "cmpdf" - [(set (reg:CCFP 0) - (compare:CCFP (match_operand:DF 0 "reg_or_0_operand" "") - (match_operand:DF 1 "reg_or_0_operand" "")))] - "! TARGET_SOFT_FLOAT" - " -{ - hppa_compare_op0 = operands[0]; - hppa_compare_op1 = operands[1]; - hppa_branch_type = CMP_DF; - DONE; -}") - (define_insn "" [(set (reg:CCFP 0) (match_operator:CCFP 2 "comparison_operator" @@ -767,143 +709,13 @@ ;; scc insns. -(define_expand "seq" - [(set (match_operand:SI 0 "register_operand" "") - (eq:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - /* set up operands from compare. */ - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; - /* fall through and generate default code */ -}") - -(define_expand "sne" - [(set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "slt" - [(set (match_operand:SI 0 "register_operand" "") - (lt:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sgt" - [(set (match_operand:SI 0 "register_operand" "") - (gt:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sle" - [(set (match_operand:SI 0 "register_operand" "") - (le:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sge" - [(set (match_operand:SI 0 "register_operand" "") - (ge:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sltu" - [(set (match_operand:SI 0 "register_operand" "") - (ltu:SI (match_dup 1) - (match_dup 2)))] +(define_expand "cstoresi4" + [(set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SI 2 "reg_or_0_operand" "") + (match_operand:SI 3 "arith5_operand" "")]))] "!TARGET_64BIT" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sgtu" - [(set (match_operand:SI 0 "register_operand" "") - (gtu:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sleu" - [(set (match_operand:SI 0 "register_operand" "") - (leu:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sgeu" - [(set (match_operand:SI 0 "register_operand" "") - (geu:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") + "") ;; Instruction canonicalization puts immediate operands second, which ;; is the reverse of what we want. @@ -1346,28 +1158,15 @@ (define_expand "movsicc" [(set (match_operand:SI 0 "register_operand" "") (if_then_else:SI - (match_operator 1 "comparison_operator" - [(match_dup 4) - (match_dup 5)]) + (match_operand 1 "comparison_operator" "") (match_operand:SI 2 "reg_or_cint_move_operand" "") (match_operand:SI 3 "reg_or_cint_move_operand" "")))] "" " { - enum rtx_code code = GET_CODE (operands[1]); - - if (hppa_branch_type != CMP_SI) + if (GET_MODE (XEXP (operands[1], 0)) != SImode + || GET_MODE (XEXP (operands[1], 0)) != GET_MODE (XEXP (operands[1], 1))) FAIL; - - if (GET_MODE (hppa_compare_op0) != GET_MODE (hppa_compare_op1) - || GET_MODE (hppa_compare_op0) != GET_MODE (operands[0])) - FAIL; - - /* operands[1] is currently the result of compare_from_rtx. We want to - emit a compare of the original operands. */ - operands[1] = gen_rtx_fmt_ee (code, SImode, hppa_compare_op0, hppa_compare_op1); - operands[4] = hppa_compare_op0; - operands[5] = hppa_compare_op1; }") ;; We used to accept any register for op1. @@ -1419,28 +1218,15 @@ (define_expand "movdicc" [(set (match_operand:DI 0 "register_operand" "") (if_then_else:DI - (match_operator 1 "comparison_operator" - [(match_dup 4) - (match_dup 5)]) + (match_operand 1 "comparison_operator" "") (match_operand:DI 2 "reg_or_cint_move_operand" "") (match_operand:DI 3 "reg_or_cint_move_operand" "")))] "TARGET_64BIT" " { - enum rtx_code code = GET_CODE (operands[1]); - - if (hppa_branch_type != CMP_SI) + if (GET_MODE (XEXP (operands[1], 0)) != DImode + || GET_MODE (XEXP (operands[1], 0)) != GET_MODE (XEXP (operands[1], 1))) FAIL; - - if (GET_MODE (hppa_compare_op0) != GET_MODE (hppa_compare_op1) - || GET_MODE (hppa_compare_op0) != GET_MODE (operands[0])) - FAIL; - - /* operands[1] is currently the result of compare_from_rtx. We want to - emit a compare of the original operands. */ - operands[1] = gen_rtx_fmt_ee (code, DImode, hppa_compare_op0, hppa_compare_op1); - operands[4] = hppa_compare_op0; - operands[5] = hppa_compare_op1; }") ; We need the first constraint alternative in order to avoid @@ -1486,289 +1272,52 @@ ;; Conditional Branches -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (EQ, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - /* set up operands from compare. */ - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; - /* fall through and generate default code */ -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (NE, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bgt" +(define_expand "cbranchdi4" [(set (pc) - (if_then_else (gt (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:DI 1 "reg_or_0_operand" "") + (match_operand:DI 2 "register_operand" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (GT, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (LT, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (GE, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (le (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (LE, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bltgt" - [(set (pc) - (if_then_else (ltgt (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (LTGT, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; -}") - -(define_expand "bunle" - [(set (pc) - (if_then_else (unle (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (UNLE, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; -}") - -(define_expand "bunlt" - [(set (pc) - (if_then_else (unlt (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (UNLT, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; -}") - -(define_expand "bunge" - [(set (pc) - (if_then_else (unge (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (UNGE, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; -}") + "TARGET_64BIT" + "") -(define_expand "bungt" +(define_expand "cbranchsi4" [(set (pc) - (if_then_else (ungt (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:SI 1 "reg_or_0_operand" "") + (match_operand:SI 2 "arith5_operand" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] "" - " -{ - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (UNGT, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; -}") + "") -(define_expand "buneq" +(define_expand "cbranchsf4" [(set (pc) - (if_then_else (uneq (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:SF 1 "reg_or_0_operand" "") + (match_operand:SF 2 "reg_or_0_operand" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] "" " { - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (UNEQ, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); + emit_bcond_fp (operands); DONE; }") -(define_expand "bunordered" - [(set (pc) - (if_then_else (unordered (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (UNORDERED, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; -}") -(define_expand "bordered" +(define_expand "cbranchdf4" [(set (pc) - (if_then_else (ordered (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:DF 1 "reg_or_0_operand" "") + (match_operand:DF 2 "reg_or_0_operand" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] "" " { - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (ORDERED, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); + emit_bcond_fp (operands); DONE; }") @@ -7527,8 +7076,10 @@ then be worthwhile to split the casesi patterns to improve scheduling. However, it's not clear that all this extra complexity is worth the effort. */ - emit_insn (gen_cmpsi (operands[0], operands[2])); - emit_jump_insn (gen_bgtu (operands[4])); + { + rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[2]); + emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], operands[4])); + } if (TARGET_BIG_SWITCH) { diff --git a/gcc/config/pdp11/pdp11-protos.h b/gcc/config/pdp11/pdp11-protos.h index f493fbc8ab1..1ed272e5081 100644 --- a/gcc/config/pdp11/pdp11-protos.h +++ b/gcc/config/pdp11/pdp11-protos.h @@ -33,9 +33,9 @@ extern void output_addr_const_pdp11 (FILE *, rtx); extern const char *output_move_double (rtx *); extern const char *output_move_quad (rtx *); extern const char *output_block_move (rtx *); +extern const char *output_jump (enum rtx_code, int, int); extern void print_operand_address (FILE *, rtx); extern int register_move_cost (enum reg_class, enum reg_class); #endif /* RTX_CODE */ extern void output_ascii (FILE *, const char *, int); -extern const char *output_jump (const char *, const char *, int); diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c index 6e8941d75e9..8f2d78fe555 100644 --- a/gcc/config/pdp11/pdp11.c +++ b/gcc/config/pdp11/pdp11.c @@ -1170,11 +1170,27 @@ pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total, } const char * -output_jump (const char *pos, const char *neg, int length) +output_jump (enum rtx_code code, int inv, int length) { static int x = 0; static char buf[1000]; + const char *pos, *neg; + + switch (code) + { + case EQ: pos = "beq", neg = "bne"; break; + case NE: pos = "bne", neg = "beq"; break; + case GT: pos = "bgt", neg = "ble"; break; + case GTU: pos = "bhi", neg = "blos"; break; + case LT: pos = "blt", neg = "bge"; break; + case LTU: pos = "blo", neg = "bhis"; break; + case GE: pos = "bge", neg = "blt"; break; + case GEU: pos = "bhis", neg = "blo"; break; + case LE: pos = "ble", neg = "bgt"; break; + case LEU: pos = "blos", neg = "bhi"; break; + default: gcc_unreachable (); + } #if 0 /* currently we don't need this, because the tstdf and cmpdf @@ -1190,14 +1206,13 @@ output_jump (const char *pos, const char *neg, int length) { case 1: - strcpy(buf, pos); - strcat(buf, " %l0"); + sprintf(buf, "%s %%l1", inv ? neg : pos); return buf; case 3: - sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x); + sprintf(buf, "%s JMP_%d\n\tjmp %%l1\nJMP_%d:", inv ? pos : neg, x, x); x++; diff --git a/gcc/config/pdp11/pdp11.h b/gcc/config/pdp11/pdp11.h index 9dbb41eb7c1..437e2b81e2e 100644 --- a/gcc/config/pdp11/pdp11.h +++ b/gcc/config/pdp11/pdp11.h @@ -1031,6 +1031,9 @@ JMP FUNCTION 0x0058 0x0000 <- FUNCTION #define OPTIMIZATION_OPTIONS(LEVEL,SIZE) \ { \ + flag_finite_math_only = 0; \ + flag_trapping_math = 0; \ + flag_signaling_nans = 0; \ if (LEVEL >= 3) \ { \ flag_omit_frame_pointer = 1; \ diff --git a/gcc/config/pdp11/pdp11.md b/gcc/config/pdp11/pdp11.md index d5d4396b1c6..64d57e056b3 100644 --- a/gcc/config/pdp11/pdp11.md +++ b/gcc/config/pdp11/pdp11.md @@ -19,6 +19,11 @@ ;; along with GCC; see the file COPYING3. If not see ;; . +;; Match CONST_DOUBLE zero for tstd/tstf. +(define_predicate "register_or_const0_operand" + (ior (match_operand 0 "register_operand") + (match_test "op == CONST0_RTX (GET_MODE (op))"))) + ;; HI is 16 bit ;; QI is 8 bit @@ -81,141 +86,50 @@ ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0) ;; compare -(define_insn "cmpdf" +(define_insn "*cmpdf" [(set (cc0) - (compare (match_operand:DF 0 "general_operand" "fR,Q,F") - (match_operand:DF 1 "register_operand" "a,a,a")))] + (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,Q,F") + (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a,a")))] "TARGET_FPU" "* { cc_status.flags = CC_IN_FPU; - return \"{cmpd|cmpf} %0, %1\;cfcc\"; -}" - [(set_attr "length" "2,3,6")]) - -;; a bit of brain damage, maybe inline later - -;; problem is - gcc seems to NEED SImode because -;; of the cmp weirdness - maybe change gcc to handle this? - -(define_expand "cmpsi" - [(set (reg:SI 0) - (match_operand:SI 0 "general_operand" "g")) - (set (reg:SI 2) - (match_operand:SI 1 "general_operand" "g")) - (parallel [(set (cc0) - (compare (reg:SI 0) - (reg:SI 2))) - (clobber (reg:SI 0))])] - "0" ;; disable for test - "") - -;; check for next insn for branch code - does this still -;; work in gcc 2.* ? - -(define_insn "" - [(set (cc0) - (compare (reg:SI 0) - (reg:SI 2))) - (clobber (reg:SI 0))] - "" - "* -{ - rtx br_insn = NEXT_INSN (insn); - RTX_CODE br_code; - - gcc_assert (GET_CODE (br_insn) == JUMP_INSN); - br_code = GET_CODE (XEXP (XEXP (PATTERN (br_insn), 1), 0)); - - switch(br_code) - { - case GEU: - case LTU: - case GTU: - case LEU: - - return \"jsr pc, ___ucmpsi\;cmp $1,r0\"; - - case GE: - case LT: - case GT: - case LE: - case EQ: - case NE: - - return \"jsr pc, ___cmpsi\;tst r0\"; - - default: - - gcc_unreachable (); - } + if (which_alternative == 0 || which_alternative == 2) + return \"{tstd|tstf} %0, %1\;cfcc\"; + else + return \"{cmpd|cmpf} %0, %1\;cfcc\"; }" - [(set_attr "length" "4")]) + [(set_attr "length" "2,2,3,3,6")]) - -(define_insn "cmphi" +(define_insn "*cmphi" [(set (cc0) - (compare (match_operand:HI 0 "general_operand" "rR,rR,Qi,Qi") - (match_operand:HI 1 "general_operand" "rR,Qi,rR,Qi")))] + (compare (match_operand:HI 0 "general_operand" "rR,rR,rR,Q,Qi,Qi") + (match_operand:HI 1 "general_operand" "N,rR,Qi,N,rR,Qi")))] "" - "cmp %0,%1" - [(set_attr "length" "1,2,2,3")]) - -(define_insn "cmpqi" + "@ + tst %0 + cmp %0,%1 + cmp %0,%1 + tst %0 + cmp %0,%1 + cmp %0,%1" + [(set_attr "length" "1,1,2,2,2,3")]) + +(define_insn "*cmpqi" [(set (cc0) - (compare (match_operand:QI 0 "general_operand" "rR,rR,Qi,Qi") - (match_operand:QI 1 "general_operand" "rR,Qi,rR,Qi")))] + (compare (match_operand:QI 0 "general_operand" "rR,rR,rR,Q,Qi,Qi") + (match_operand:QI 1 "general_operand" "N,rR,Qi,N,rR,Qi")))] "" - "cmpb %0,%1" - [(set_attr "length" "1,2,2,3")]) + "@ + tstb %0 + cmpb %0,%1 + cmpb %0,%1 + tstb %0 + cmpb %0,%1 + cmpb %0,%1" + [(set_attr "length" "1,1,2,2,2,3")]) -;; We have to have this because cse can optimize the previous pattern -;; into this one. - -(define_insn "tstdf" - [(set (cc0) - (match_operand:DF 0 "general_operand" "fR,Q"))] - "TARGET_FPU" - "* -{ - cc_status.flags = CC_IN_FPU; - return \"{tstd|tstf} %0\;cfcc\"; -}" - [(set_attr "length" "2,3")]) - - -(define_expand "tstsi" - [(set (reg:SI 0) - (match_operand:SI 0 "general_operand" "g")) - (parallel [(set (cc0) - (reg:SI 0)) - (clobber (reg:SI 0))])] - "0" ;; disable for test - "") - -(define_insn "" - [(set (cc0) - (reg:SI 0)) - (clobber (reg:SI 0))] - "" - "jsr pc, ___tstsi\;tst r0" - [(set_attr "length" "3")]) - - -(define_insn "tsthi" - [(set (cc0) - (match_operand:HI 0 "general_operand" "rR,Q"))] - "" - "tst %0" - [(set_attr "length" "1,2")]) - -(define_insn "tstqi" - [(set (cc0) - (match_operand:QI 0 "general_operand" "rR,Q"))] - "" - "tstb %0" - [(set_attr "length" "1,2")]) - ;; sob instruction - we need an assembler which can make this instruction ;; valid under _all_ circumstances! @@ -264,353 +178,81 @@ ;; These control RTL generation for conditional jump insns ;; and match them for register allocation. -;; problem with too short jump distance! we need an assembler which can -;; make this valid for all jump distances! -;; e.g. gas! - -;; these must be changed to check for CC_IN_FCCR if float is to be -;; enabled - -(define_insn "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_jump(\"beq\", \"bne\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - - -(define_insn "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_jump(\"bgt\", \"ble\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) +(define_expand "cbranchdf4" + [(set (cc0) + (compare (match_operand:DF 1 "general_operand") + (match_operand:DF 2 "general_operand"))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] "" - "* return output_jump(\"bhi\", \"blos\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) + "") -(define_insn "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) +(define_expand "cbranchhi4" + [(set (cc0) + (compare (match_operand:HI 1 "general_operand") + (match_operand:HI 2 "general_operand"))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] "" - "* return output_jump(\"blt\", \"bge\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - + "") -(define_insn "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) +(define_expand "cbranchqi4" + [(set (cc0) + (compare (match_operand:QI 1 "general_operand") + (match_operand:QI 2 "general_operand"))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] "" - "* return output_jump(\"blo\", \"bhis\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) + "") -(define_insn "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_jump(\"bge\", \"blt\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) +;; problem with too short jump distance! we need an assembler which can +;; make this valid for all jump distances! +;; e.g. gas! -(define_insn "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_jump(\"bhis\", \"blo\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) +;; these must be changed to check for CC_IN_FCCR if float is to be +;; enabled -(define_insn "ble" +(define_insn "*branch" [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 1 "" "")) (pc)))] "" - "* return output_jump(\"ble\", \"bgt\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) + "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));" + [(set (attr "length") (if_then_else (ior (le (minus (match_dup 1) (pc)) (const_int -128)) - (ge (minus (match_dup 0) + (ge (minus (match_dup 1) (pc)) (const_int 128))) (const_int 3) (const_int 1)))]) -(define_insn "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_jump(\"blos\", \"bhi\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - ;; These match inverted jump insns for register allocation. -(define_insn "" +(define_insn "*branch_inverted" [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) (pc) - (label_ref (match_operand 0 "" ""))))] + (label_ref (match_operand 1 "" ""))))] "" - "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) + "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));" + [(set (attr "length") (if_then_else (ior (le (minus (match_dup 1) (pc)) (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"beq\", \"bne\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"ble\", \"bgt\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"blos\", \"bhi\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"bge\", \"blt\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"bhis\", \"blo\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"blt\", \"bge\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"blo\", \"bhis\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"bgt\", \"ble\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"bhi\", \"blos\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) + (ge (minus (match_dup 1) (pc)) (const_int 128))) (const_int 3) diff --git a/gcc/config/picochip/picochip.md b/gcc/config/picochip/picochip.md index 657629c96fa..02f0f14850d 100644 --- a/gcc/config/picochip/picochip.md +++ b/gcc/config/picochip/picochip.md @@ -551,7 +551,7 @@ (define_insn_and_split "cbranchhi4" [(set (pc) (if_then_else - (match_operator:CC 0 "comparison_operator" + (match_operator:CC 0 "ordered_comparison_operator" [(match_operand:HI 1 "register_operand" "r") (match_operand:HI 2 "picochip_comparison_operand" "ri")]) (label_ref (match_operand 3 "" "")) @@ -2524,117 +2524,6 @@ (set_attr "type" "picoAlu,picoAlu") (set_attr "longConstant" "false,true")]) -;; cmphi - This needs to be defined, to ensure that the conditional -;; move works properly (because the if-cvt code uses this pattern to -;; build the conditional move, even though normally we use cbranch to -;; directly generate the instructions). - -(define_expand "cmphi" - [(match_operand:HI 0 "general_operand" "g") - (match_operand:HI 1 "general_operand" "g")] - "" - "DONE;") - -;;============================================================================ -;; Branch patterns - needed for conditional moves. This is because -;; they result in the bcc_gen_fctn array being initialised with the -;; code to define_expand the following, and this in turn means that -;; when noce_emit_cmove is called, the correct pattern can be -;; generated, based upon the assumed presence of the following. The -;; following are never actually used, because the earlier cbranch -;; patterns take precendence. -;;============================================================================ - -(define_expand "bne" - [(set (pc) - (if_then_else - (ne (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "beq" - [(set (pc) - (if_then_else - (eq (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "blt" - [(set (pc) - (if_then_else - (lt (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "bge" - [(set (pc) - (if_then_else - (ge (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "bgeu" - [(set (pc) - (if_then_else - (geu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "bltu" - [(set (pc) - (if_then_else - (ltu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "ble" - [(set (pc) - (if_then_else - (le (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "bgt" - [(set (pc) - (if_then_else - (gt (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "bleu" - [(set (pc) - (if_then_else - (leu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "bgtu" - [(set (pc) - (if_then_else - (gtu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - ;;============================================================================ ;; Scheduling, including delay slot scheduling. ;;============================================================================ diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index af80ef46b6f..dbf78734b17 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -830,6 +830,11 @@ GET_MODE (XEXP (op, 0))), 1")))) +(define_predicate "rs6000_cbranch_operator" + (if_then_else (match_test "TARGET_HARD_FLOAT && !TARGET_FPRS") + (match_operand 0 "ordered_comparison_operator") + (match_operand 0 "comparison_operator"))) + ;; Return 1 if OP is a comparison operation that is valid for an SCC insn -- ;; it must be a positive comparison. (define_predicate "scc_comparison_operator" @@ -842,11 +847,6 @@ (and (match_operand 0 "branch_comparison_operator") (match_code "eq,lt,gt,ltu,gtu,unordered"))) -;; Return 1 is OP is a comparison operation that is valid for a trap insn. -(define_predicate "trap_comparison_operator" - (and (match_operand 0 "comparison_operator") - (match_code "eq,ne,le,lt,ge,gt,leu,ltu,geu,gtu"))) - ;; Return 1 if OP is a load multiple operation, known to be a PARALLEL. (define_predicate "load_multiple_operation" (match_code "parallel") diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 4b8f5220a51..f40adabd00a 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -81,8 +81,8 @@ extern void print_operand_address (FILE *, rtx); extern bool rs6000_output_addr_const_extra (FILE *, rtx); extern enum rtx_code rs6000_reverse_condition (enum machine_mode, enum rtx_code); -extern void rs6000_emit_sCOND (enum rtx_code, rtx); -extern void rs6000_emit_cbranch (enum rtx_code, rtx); +extern void rs6000_emit_sCOND (enum machine_mode, rtx[]); +extern void rs6000_emit_cbranch (enum machine_mode, rtx[]); extern char * output_cbranch (rtx, const char *, int, rtx); extern char * output_e500_flip_gt_bit (rtx, rtx); extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 8e24769816d..2d34b14f63f 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -190,11 +190,6 @@ int rs6000_darwin64_abi; /* Set to nonzero once AIX common-mode calls have been defined. */ static GTY(()) int common_mode_defined; -/* Save information from a "cmpxx" operation until the branch or scc is - emitted. */ -rtx rs6000_compare_op0, rs6000_compare_op1; -int rs6000_compare_fp_p; - /* Label number of label created for -mrelocatable, to call to so we can get the address of the GOT section */ int rs6000_pic_labelno; @@ -752,7 +747,7 @@ struct processor_costs power6_cost = { static bool rs6000_function_ok_for_sibcall (tree, tree); static const char *rs6000_invalid_within_doloop (const_rtx); -static rtx rs6000_generate_compare (enum rtx_code); +static rtx rs6000_generate_compare (rtx, enum machine_mode); static void rs6000_emit_stack_tie (void); static void rs6000_frame_related (rtx, rtx, HOST_WIDE_INT, rtx, rtx); static bool spe_func_has_64bit_regs_p (void); @@ -12788,21 +12783,24 @@ rs6000_reverse_condition (enum machine_mode mode, enum rtx_code code) represents the result of the compare. */ static rtx -rs6000_generate_compare (enum rtx_code code) +rs6000_generate_compare (rtx cmp, enum machine_mode mode) { enum machine_mode comp_mode; rtx compare_result; + enum rtx_code code = GET_CODE (cmp); + rtx op0 = XEXP (cmp, 0); + rtx op1 = XEXP (cmp, 1); - if (rs6000_compare_fp_p) + if (FLOAT_MODE_P (mode)) comp_mode = CCFPmode; else if (code == GTU || code == LTU || code == GEU || code == LEU) comp_mode = CCUNSmode; else if ((code == EQ || code == NE) - && GET_CODE (rs6000_compare_op0) == SUBREG - && GET_CODE (rs6000_compare_op1) == SUBREG - && SUBREG_PROMOTED_UNSIGNED_P (rs6000_compare_op0) - && SUBREG_PROMOTED_UNSIGNED_P (rs6000_compare_op1)) + && GET_CODE (op0) == SUBREG + && GET_CODE (op1) == SUBREG + && SUBREG_PROMOTED_UNSIGNED_P (op0) + && SUBREG_PROMOTED_UNSIGNED_P (op1)) /* These are unsigned values, perhaps there will be a later ordering compare that can be shared with this one. Unfortunately we cannot detect the signedness of the operands @@ -12816,13 +12814,13 @@ rs6000_generate_compare (enum rtx_code code) /* E500 FP compare instructions on the GPRs. Yuck! */ if ((!TARGET_FPRS && TARGET_HARD_FLOAT) - && rs6000_compare_fp_p) + && FLOAT_MODE_P (mode)) { rtx cmp, or_result, compare_result2; - enum machine_mode op_mode = GET_MODE (rs6000_compare_op0); + enum machine_mode op_mode = GET_MODE (op0); if (op_mode == VOIDmode) - op_mode = GET_MODE (rs6000_compare_op1); + op_mode = GET_MODE (op1); /* The E500 FP compare instructions toggle the GT bit (CR bit 1) only. This explains the following mess. */ @@ -12834,26 +12832,20 @@ rs6000_generate_compare (enum rtx_code code) { case SFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstsfeq_gpr (compare_result, op0, op1) + : gen_cmpsfeq_gpr (compare_result, op0, op1); break; case DFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstdfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpdfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstdfeq_gpr (compare_result, op0, op1) + : gen_cmpdfeq_gpr (compare_result, op0, op1); break; case TFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tsttfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmptfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tsttfeq_gpr (compare_result, op0, op1) + : gen_cmptfeq_gpr (compare_result, op0, op1); break; default: @@ -12866,26 +12858,20 @@ rs6000_generate_compare (enum rtx_code code) { case SFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstsfgt_gpr (compare_result, op0, op1) + : gen_cmpsfgt_gpr (compare_result, op0, op1); break; case DFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstdfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpdfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstdfgt_gpr (compare_result, op0, op1) + : gen_cmpdfgt_gpr (compare_result, op0, op1); break; case TFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tsttfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmptfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tsttfgt_gpr (compare_result, op0, op1) + : gen_cmptfgt_gpr (compare_result, op0, op1); break; default: @@ -12898,26 +12884,20 @@ rs6000_generate_compare (enum rtx_code code) { case SFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstsflt_gpr (compare_result, op0, op1) + : gen_cmpsflt_gpr (compare_result, op0, op1); break; case DFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstdflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpdflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstdflt_gpr (compare_result, op0, op1) + : gen_cmpdflt_gpr (compare_result, op0, op1); break; case TFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tsttflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmptflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tsttflt_gpr (compare_result, op0, op1) + : gen_cmptflt_gpr (compare_result, op0, op1); break; default: @@ -12949,26 +12929,20 @@ rs6000_generate_compare (enum rtx_code code) { case SFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstsfeq_gpr (compare_result2, op0, op1) + : gen_cmpsfeq_gpr (compare_result2, op0, op1); break; case DFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstdfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpdfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstdfeq_gpr (compare_result2, op0, op1) + : gen_cmpdfeq_gpr (compare_result2, op0, op1); break; case TFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tsttfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmptfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tsttfeq_gpr (compare_result2, op0, op1) + : gen_cmptfeq_gpr (compare_result2, op0, op1); break; default: @@ -12998,16 +12972,14 @@ rs6000_generate_compare (enum rtx_code code) /* Generate XLC-compatible TFmode compare as PARALLEL with extra CLOBBERs to match cmptf_internal2 pattern. */ if (comp_mode == CCFPmode && TARGET_XL_COMPAT - && GET_MODE (rs6000_compare_op0) == TFmode + && GET_MODE (op0) == TFmode && !TARGET_IEEEQUAD && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128) emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (9, gen_rtx_SET (VOIDmode, compare_result, - gen_rtx_COMPARE (comp_mode, - rs6000_compare_op0, - rs6000_compare_op1)), + gen_rtx_COMPARE (comp_mode, op0, op1)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)), @@ -13016,29 +12988,25 @@ rs6000_generate_compare (enum rtx_code code) gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode))))); - else if (GET_CODE (rs6000_compare_op1) == UNSPEC - && XINT (rs6000_compare_op1, 1) == UNSPEC_SP_TEST) + else if (GET_CODE (op1) == UNSPEC + && XINT (op1, 1) == UNSPEC_SP_TEST) { - rtx op1 = XVECEXP (rs6000_compare_op1, 0, 0); + rtx op1 = XVECEXP (op1, 0, 0); comp_mode = CCEQmode; compare_result = gen_reg_rtx (CCEQmode); if (TARGET_64BIT) - emit_insn (gen_stack_protect_testdi (compare_result, - rs6000_compare_op0, op1)); + emit_insn (gen_stack_protect_testdi (compare_result, op0, op1)); else - emit_insn (gen_stack_protect_testsi (compare_result, - rs6000_compare_op0, op1)); + emit_insn (gen_stack_protect_testsi (compare_result, op0, op1)); } else emit_insn (gen_rtx_SET (VOIDmode, compare_result, - gen_rtx_COMPARE (comp_mode, - rs6000_compare_op0, - rs6000_compare_op1))); + gen_rtx_COMPARE (comp_mode, op0, op1))); } /* Some kinds of FP comparisons need an OR operation; under flag_finite_math_only we don't bother. */ - if (rs6000_compare_fp_p + if (FLOAT_MODE_P (mode) && !flag_finite_math_only && !(TARGET_HARD_FLOAT && !TARGET_FPRS) && (code == LE || code == GE @@ -13081,16 +13049,17 @@ rs6000_generate_compare (enum rtx_code code) /* Emit the RTL for an sCOND pattern. */ void -rs6000_emit_sCOND (enum rtx_code code, rtx result) +rs6000_emit_sCOND (enum machine_mode mode, rtx operands[]) { rtx condition_rtx; enum machine_mode op_mode; enum rtx_code cond_code; + rtx result = operands[0]; - condition_rtx = rs6000_generate_compare (code); + condition_rtx = rs6000_generate_compare (operands[1], mode); cond_code = GET_CODE (condition_rtx); - if (rs6000_compare_fp_p + if (FLOAT_MODE_P (mode) && !TARGET_FPRS && TARGET_HARD_FLOAT) { rtx t; @@ -13125,11 +13094,11 @@ rs6000_emit_sCOND (enum rtx_code code, rtx result) condition_rtx = gen_rtx_EQ (VOIDmode, not_result, const0_rtx); } - op_mode = GET_MODE (rs6000_compare_op0); + op_mode = GET_MODE (XEXP (operands[1], 0)); if (op_mode == VOIDmode) - op_mode = GET_MODE (rs6000_compare_op1); + op_mode = GET_MODE (XEXP (operands[1], 1)); - if (TARGET_POWERPC64 && (op_mode == DImode || rs6000_compare_fp_p)) + if (TARGET_POWERPC64 && (op_mode == DImode || FLOAT_MODE_P (mode))) { PUT_MODE (condition_rtx, DImode); convert_move (result, condition_rtx, 0); @@ -13144,12 +13113,12 @@ rs6000_emit_sCOND (enum rtx_code code, rtx result) /* Emit a branch of kind CODE to location LOC. */ void -rs6000_emit_cbranch (enum rtx_code code, rtx loc) +rs6000_emit_cbranch (enum machine_mode mode, rtx operands[]) { rtx condition_rtx, loc_ref; - condition_rtx = rs6000_generate_compare (code); - loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc); + condition_rtx = rs6000_generate_compare (operands[0], mode); + loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx, loc_ref, pc_rtx))); @@ -13595,8 +13564,8 @@ int rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) { enum rtx_code code = GET_CODE (op); - rtx op0 = rs6000_compare_op0; - rtx op1 = rs6000_compare_op1; + rtx op0 = XEXP (op, 0); + rtx op1 = XEXP (op, 1); REAL_VALUE_TYPE c1; enum machine_mode compare_mode = GET_MODE (op0); enum machine_mode result_mode = GET_MODE (dest); @@ -13616,7 +13585,7 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) /* First, work out if the hardware can do this at all, or if it's too slow.... */ - if (! rs6000_compare_fp_p) + if (!FLOAT_MODE_P (compare_mode)) { if (TARGET_ISEL) return rs6000_emit_int_cmove (dest, op, true_cond, false_cond); @@ -13781,13 +13750,13 @@ rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) rtx condition_rtx, cr; /* All isel implementations thus far are 32-bits. */ - if (GET_MODE (rs6000_compare_op0) != SImode) + if (GET_MODE (XEXP (op, 0)) != SImode) return 0; /* We still have to do the compare, because isel doesn't do a compare, it just looks at the CRx bits set by a previous compare instruction. */ - condition_rtx = rs6000_generate_compare (GET_CODE (op)); + condition_rtx = rs6000_generate_compare (op, SImode); cr = XEXP (condition_rtx, 0); if (GET_MODE (cr) == CCmode) diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index f11ea1fe249..e65bf5d95df 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1986,12 +1986,6 @@ do { \ /* Given a condition code and a mode, return the inverse condition. */ #define REVERSE_CONDITION(CODE, MODE) rs6000_reverse_condition (MODE, CODE) -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ - -extern GTY(()) rtx rs6000_compare_op0; -extern GTY(()) rtx rs6000_compare_op1; -extern int rs6000_compare_fp_p; /* Control the assembler format that we output. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index cc37d911dbb..9d4a96051b7 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -11897,262 +11897,90 @@ ;; signed & unsigned, and one type of branch. ;; ;; Start with the DEFINE_EXPANDs to generate the rtl for compares, scc -;; insns, and branches. We store the operands of compares until we see -;; how it is used. -(define_expand "cmp" - [(set (cc0) - (compare (match_operand:GPR 0 "gpc_reg_operand" "") - (match_operand:GPR 1 "reg_or_short_operand" "")))] +;; insns, and branches. + +(define_expand "cbranch4" + [(use (match_operator 0 "rs6000_cbranch_operator" + [(match_operand:GPR 1 "gpc_reg_operand" "") + (match_operand:GPR 2 "reg_or_short_operand" "")])) + (use (match_operand 3 ""))] "" " { - /* Take care of the possibility that operands[1] might be negative but + /* Take care of the possibility that operands[2] might be negative but this might be a logical operation. That insn doesn't exist. */ - if (GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) < 0) - operands[1] = force_reg (mode, operands[1]); - - rs6000_compare_op0 = operands[0]; - rs6000_compare_op1 = operands[1]; - rs6000_compare_fp_p = 0; - DONE; -}") + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) < 0) + { + operands[2] = force_reg (mode, operands[2]); + operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]), + GET_MODE (operands[0]), + operands[1], operands[2]); + } -(define_expand "cmp" - [(set (cc0) (compare (match_operand:FP 0 "gpc_reg_operand" "") - (match_operand:FP 1 "gpc_reg_operand" "")))] - "" - " -{ - rs6000_compare_op0 = operands[0]; - rs6000_compare_op1 = operands[1]; - rs6000_compare_fp_p = 1; + rs6000_emit_cbranch (mode, operands); DONE; }") -(define_expand "beq" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (EQ, operands[0]); DONE; }") - -(define_expand "bne" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (NE, operands[0]); DONE; }") - -(define_expand "bge" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (GE, operands[0]); DONE; }") - -(define_expand "bgt" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (GT, operands[0]); DONE; }") - -(define_expand "ble" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (LE, operands[0]); DONE; }") - -(define_expand "blt" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (LT, operands[0]); DONE; }") - -(define_expand "bgeu" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (GEU, operands[0]); DONE; }") - -(define_expand "bgtu" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (GTU, operands[0]); DONE; }") - -(define_expand "bleu" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (LEU, operands[0]); DONE; }") - -(define_expand "bltu" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (LTU, operands[0]); DONE; }") - -(define_expand "bunordered" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (UNORDERED, operands[0]); DONE; }") - -(define_expand "bordered" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (ORDERED, operands[0]); DONE; }") - -(define_expand "buneq" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (UNEQ, operands[0]); DONE; }") - -(define_expand "bunge" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (UNGE, operands[0]); DONE; }") - -(define_expand "bungt" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (UNGT, operands[0]); DONE; }") - -(define_expand "bunle" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (UNLE, operands[0]); DONE; }") - -(define_expand "bunlt" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (UNLT, operands[0]); DONE; }") - -(define_expand "bltgt" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (LTGT, operands[0]); DONE; }") - -;; For SNE, we would prefer that the xor/abs sequence be used for integers. -;; For SEQ, likewise, except that comparisons with zero should be done -;; with an scc insns. However, due to the order that combine see the -;; resulting insns, we must, in fact, allow SEQ for integers. Fail in -;; the cases we don't want to handle. -(define_expand "seq" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "" - "{ rs6000_emit_sCOND (EQ, operands[0]); DONE; }") - -(define_expand "sne" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] +(define_expand "cbranch4" + [(use (match_operator 0 "rs6000_cbranch_operator" + [(match_operand:FP 1 "gpc_reg_operand" "") + (match_operand:FP 2 "gpc_reg_operand" "")])) + (use (match_operand 3 ""))] "" " { - if (! rs6000_compare_fp_p) - FAIL; - - rs6000_emit_sCOND (NE, operands[0]); + rs6000_emit_cbranch (mode, operands); DONE; }") -;; A >= 0 is best done the portable way for A an integer. -(define_expand "sge" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] +(define_expand "cstore4" + [(use (match_operator 1 "rs6000_cbranch_operator" + [(match_operand:GPR 2 "gpc_reg_operand" "") + (match_operand:GPR 3 "reg_or_short_operand" "")])) + (clobber (match_operand:SI 0 "register_operand"))] "" " { - if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx) - FAIL; - - rs6000_emit_sCOND (GE, operands[0]); - DONE; -}") + /* Take care of the possibility that operands[3] might be negative but + this might be a logical operation. That insn doesn't exist. */ + if (GET_CODE (operands[3]) == CONST_INT + && INTVAL (operands[3]) < 0) + { + operands[3] = force_reg (mode, operands[3]); + operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), + GET_MODE (operands[1]), + operands[2], operands[3]); + } -;; A > 0 is best done using the portable sequence, so fail in that case. -(define_expand "sgt" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "" - " -{ - if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx) + /* For SNE, we would prefer that the xor/abs sequence be used for integers. + For SEQ, likewise, except that comparisons with zero should be done + with an scc insns. However, due to the order that combine see the + resulting insns, we must, in fact, allow SEQ for integers. Fail in + the cases we don't want to handle or are best handled by portable + code. */ + if (GET_CODE (operands[1]) == NE) FAIL; - - rs6000_emit_sCOND (GT, operands[0]); - DONE; -}") - -;; A <= 0 is best done the portable way for A an integer. -(define_expand "sle" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "" - " -{ - if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx) + if ((GET_CODE (operands[1]) == LT || GET_CODE (operands[1]) == LE + || GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE) + && operands[3] == const0_rtx) FAIL; - - rs6000_emit_sCOND (LE, operands[0]); + rs6000_emit_sCOND (mode, operands); DONE; }") -;; A < 0 is best done in the portable way for A an integer. -(define_expand "slt" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] +(define_expand "cstore4" + [(use (match_operator 1 "rs6000_cbranch_operator" + [(match_operand:FP 2 "gpc_reg_operand" "") + (match_operand:FP 3 "gpc_reg_operand" "")])) + (clobber (match_operand:SI 0 "register_operand"))] "" " { - if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx) - FAIL; - - rs6000_emit_sCOND (LT, operands[0]); + rs6000_emit_sCOND (mode, operands); DONE; }") -(define_expand "sgeu" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "" - "{ rs6000_emit_sCOND (GEU, operands[0]); DONE; }") - -(define_expand "sgtu" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "" - "{ rs6000_emit_sCOND (GTU, operands[0]); DONE; }") - -(define_expand "sleu" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "" - "{ rs6000_emit_sCOND (LEU, operands[0]); DONE; }") - -(define_expand "sltu" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "" - "{ rs6000_emit_sCOND (LTU, operands[0]); DONE; }") - -(define_expand "sunordered" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (UNORDERED, operands[0]); DONE; }") - -(define_expand "sordered" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (ORDERED, operands[0]); DONE; }") - -(define_expand "suneq" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (UNEQ, operands[0]); DONE; }") - -(define_expand "sunge" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (UNGE, operands[0]); DONE; }") - -(define_expand "sungt" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (UNGT, operands[0]); DONE; }") - -(define_expand "sunle" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (UNLE, operands[0]); DONE; }") - -(define_expand "sunlt" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (UNLT, operands[0]); DONE; }") - -(define_expand "sltgt" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (LTGT, operands[0]); DONE; }") (define_expand "stack_protect_set" [(match_operand 0 "memory_operand" "") @@ -12195,16 +12023,16 @@ (match_operand 2 "" "")] "" { + rtx test, op0, op1; #ifdef TARGET_THREAD_SSP_OFFSET rtx tlsreg = gen_rtx_REG (Pmode, TARGET_64BIT ? 13 : 2); rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET)); operands[1] = gen_rtx_MEM (Pmode, addr); #endif - rs6000_compare_op0 = operands[0]; - rs6000_compare_op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, operands[1]), - UNSPEC_SP_TEST); - rs6000_compare_fp_p = 0; - emit_jump_insn (gen_beq (operands[2])); + op0 = operands[0]; + op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, operands[1]), UNSPEC_SP_TEST); + test = gen_rtx_EQ (VOIDmode, op0, op1); + emit_jump_insn (gen_cbranchsi4 (test, op0, op1, operands[2])); DONE; }) @@ -14775,17 +14603,16 @@ "{t 31,0,0|trap}" [(set_attr "type" "trap")]) -(define_expand "conditional_trap" - [(trap_if (match_operator 0 "trap_comparison_operator" - [(match_dup 2) (match_dup 3)]) - (match_operand 1 "const_int_operand" ""))] +(define_expand "ctrap4" + [(trap_if (match_operator 0 "ordered_comparison_operator" + [(match_operand:GPR 1 "register_operand") + (match_operand:GPR 2 "reg_or_short_operand")]) + (match_operand 3 "zero_constant" ""))] "" - "if (rs6000_compare_fp_p || operands[1] != const0_rtx) FAIL; - operands[2] = rs6000_compare_op0; - operands[3] = rs6000_compare_op1;") + "") (define_insn "" - [(trap_if (match_operator 0 "trap_comparison_operator" + [(trap_if (match_operator 0 "ordered_comparison_operator" [(match_operand:GPR 1 "register_operand" "r") (match_operand:GPR 2 "reg_or_short_operand" "rI")]) (const_int 0))] diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md index bb8fdf261d5..d09c9b3e161 100644 --- a/gcc/config/s390/predicates.md +++ b/gcc/config/s390/predicates.md @@ -189,6 +189,14 @@ return (s390_compare_and_branch_condition_mask (op) >= 0); }) +;; Return nonzero if OP is a valid comparison operator for the +;; cstore expanders -- respectively cstorecc4 and integer cstore. +(define_predicate "s390_eqne_operator" + (match_code "eq, ne")) + +(define_predicate "s390_scond_operator" + (match_code "ltu, gtu, leu, geu")) + ;; Return nonzero if OP is a valid comparison operator ;; for an ALC condition. diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index e2ed4a0d407..17891c6492f 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -223,11 +223,6 @@ struct processor_costs z10_cost = extern int reload_completed; -/* Save information from a "cmpxx" operation until the branch or scc is - emitted. A pair of a MODE_CC register and a const0_rtx if a compare - has been emitted already. */ -rtx s390_compare_op0, s390_compare_op1; - /* Structure used to hold the components of a S/390 memory address. A legitimate address on S/390 is of the general form @@ -7747,15 +7742,11 @@ s390_emit_prologue (void) rtx t = gen_rtx_AND (Pmode, stack_pointer_rtx, GEN_INT (stack_check_mask)); if (TARGET_64BIT) - gen_cmpdi (t, const0_rtx); + emit_insn (gen_ctrapdi4 (gen_rtx_EQ (VOIDmode, t, const0_rtx), + t, const0_rtx, const0_rtx)); else - gen_cmpsi (t, const0_rtx); - - emit_insn (gen_conditional_trap (gen_rtx_EQ (CCmode, - gen_rtx_REG (CCmode, - CC_REGNUM), - const0_rtx), - const0_rtx)); + emit_insn (gen_ctrapsi4 (gen_rtx_EQ (VOIDmode, t, const0_rtx), + t, const0_rtx, const0_rtx)); } } diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 2b4d7ce72ca..b2541857170 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -803,12 +803,6 @@ do { \ #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \ s390_canonicalize_comparison (&(CODE), &(OP0), &(OP1)) -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. Note that we can't use "rtx" here - since it hasn't been defined! */ -extern struct rtx_def *s390_compare_op0, *s390_compare_op1; - - /* Relative costs of operations. */ /* On s390, copy between fprs and gprs is expensive. */ diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index c3d181f0aac..7c9a2b28100 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -354,13 +354,6 @@ (define_mode_iterator INT [(DI "TARGET_64BIT") SI HI QI]) (define_mode_iterator INTALL [TI DI SI HI QI]) -;; This iterator allows to unify all 'bCOND' expander patterns. -(define_code_iterator COMPARE [eq ne gt gtu lt ltu ge geu le leu unordered - ordered uneq unlt ungt unle unge ltgt]) - -;; This iterator allows to unify all 'sCOND' patterns. -(define_code_iterator SCOND [ltu gtu leu geu]) - ;; This iterator allows some 'ashift' and 'lshiftrt' pattern to be defined from ;; the same template. (define_code_iterator SHIFT [ashift lshiftrt]) @@ -493,39 +486,6 @@ ;;- Compare instructions. ;; -(define_expand "cmp" - [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:GPR 0 "register_operand" "") - (match_operand:GPR 1 "general_operand" "")))] - "" -{ - s390_compare_op0 = operands[0]; - s390_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmp" - [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:FP 0 "register_operand" "") - (match_operand:FP 1 "general_operand" "")))] - "TARGET_HARD_FLOAT" -{ - s390_compare_op0 = operands[0]; - s390_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmpcc" - [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand 0 "cc_reg_operand" "") - (match_operand 1 "general_operand" "")))] - "" -{ - s390_compare_op0 = operands[0]; - s390_compare_op1 = operands[1]; - DONE; -}) - ; Test-under-Mask instructions (define_insn "*tmqi_mem" @@ -3812,9 +3772,9 @@ TD -> DI convert afterwards. */ emit_insn (gen_extendddtd2 (temp, operands[1])); temp = force_reg (TDmode, temp); - emit_insn (gen_cmptd (temp, - CONST_DOUBLE_FROM_REAL_VALUE (cmp, TDmode))); - emit_jump_insn (gen_blt (label1)); + emit_cmp_and_jump_insns (temp, + CONST_DOUBLE_FROM_REAL_VALUE (cmp, TDmode), + LT, NULL_RTX, VOIDmode, 0, label1); emit_insn (gen_subtd3 (temp, temp, CONST_DOUBLE_FROM_REAL_VALUE (sub, TDmode))); emit_insn (gen_fix_trunctddi2_dfp (operands[0], temp, GEN_INT (11))); @@ -3840,9 +3800,9 @@ decimal_real_from_string (&cmp, "9223372036854775808.0"); /* 2^63 */ decimal_real_from_string (&sub, "18446744073709551616.0"); /* 2^64 */ - emit_insn (gen_cmptd (operands[1], - CONST_DOUBLE_FROM_REAL_VALUE (cmp, TDmode))); - emit_jump_insn (gen_blt (label1)); + emit_cmp_and_jump_insns (operands[1], + CONST_DOUBLE_FROM_REAL_VALUE (cmp, TDmode), + LT, NULL_RTX, VOIDmode, 0, label1); emit_insn (gen_subtd3 (temp, operands[1], CONST_DOUBLE_FROM_REAL_VALUE (sub, TDmode))); emit_insn (gen_fix_trunctddi2_dfp (operands[0], temp, GEN_INT (11))); @@ -3873,9 +3833,9 @@ real_2expN (&cmp, GET_MODE_BITSIZE(mode) - 1, mode); real_2expN (&sub, GET_MODE_BITSIZE(mode), mode); - emit_insn (gen_cmp (operands[1], - CONST_DOUBLE_FROM_REAL_VALUE (cmp, mode))); - emit_jump_insn (gen_blt (label1)); + emit_cmp_and_jump_insns (operands[1], + CONST_DOUBLE_FROM_REAL_VALUE (cmp, mode), + LT, NULL_RTX, VOIDmode, 0, label1); emit_insn (gen_sub3 (temp, operands[1], CONST_DOUBLE_FROM_REAL_VALUE (sub, mode))); emit_insn (gen_fix_trunc2_bfp (operands[0], temp, @@ -5074,7 +5034,7 @@ (match_operand:GPR 3 "const_int_operand" "")] "TARGET_CPU_ZARCH" "if (!s390_expand_addcc (GET_CODE (operands[1]), - s390_compare_op0, s390_compare_op1, + XEXP (operands[1], 0), XEXP (operands[1], 1), operands[0], operands[2], operands[3])) FAIL; DONE;") @@ -5114,31 +5074,29 @@ "") -(define_expand "s" +(define_expand "cstore4" [(set (match_operand:SI 0 "register_operand" "") - (SCOND (match_dup 0) - (match_dup 0)))] + (match_operator:SI 1 "s390_scond_operator" + [(match_operand:GPR 2 "register_operand" "") + (match_operand:GPR 3 "general_operand" "")]))] "TARGET_CPU_ZARCH" - "if (!s390_expand_addcc (, s390_compare_op0, s390_compare_op1, + "if (!s390_expand_addcc (GET_CODE (operands[1]), operands[2], operands[3], operands[0], const0_rtx, const1_rtx)) FAIL; DONE;") -(define_expand "seq" +(define_expand "cstorecc4" [(parallel - [(set (match_operand:SI 0 "register_operand" "=d") - (match_dup 1)) - (clobber (reg:CC CC_REGNUM))]) - (parallel - [(set (match_dup 0) (xor:SI (match_dup 0) (const_int 1))) + [(set (match_operand:SI 0 "register_operand" "") + (match_operator:SI 1 "s390_eqne_operator" + [(match_operand:CCZ1 2 "register_operand") + (match_operand 3 "const0_operand")])) (clobber (reg:CC CC_REGNUM))])] "" -{ - if (GET_MODE (s390_compare_op0) != CCZ1mode) - FAIL; - operands[1] = s390_emit_compare (NE, s390_compare_op0, s390_compare_op1); - PUT_MODE (operands[1], SImode); -}) + "emit_insn (gen_sne (operands[0], operands[2])); + if (GET_CODE (operands[1]) == EQ) + emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx)); + DONE;") -(define_insn_and_split "*sne" +(define_insn_and_split "sne" [(set (match_operand:SI 0 "register_operand" "=d") (ne:SI (match_operand:CCZ1 1 "register_operand" "0") (const_int 0))) @@ -5566,8 +5524,8 @@ operands[1] = make_safe_from (operands[1], operands[0]); emit_move_insn (operands[0], const0_rtx); - emit_insn (gen_cmpsi (operands[1], operands[2])); - emit_jump_insn (gen_bltu (label1)); + emit_cmp_and_jump_insns (operands[1], operands[2], LT, NULL_RTX, + SImode, 1, label1); emit_move_insn (operands[0], const1_rtx); emit_label (label1); } @@ -5598,12 +5556,12 @@ operands[2] = make_safe_from (operands[2], operands[0]); emit_move_insn (operands[0], const0_rtx); - emit_insn (gen_cmpsi (operands[2], operands[1])); - emit_jump_insn (gen_bgtu (label3)); - emit_insn (gen_cmpsi (operands[2], const0_rtx)); - emit_jump_insn (gen_blt (label2)); - emit_insn (gen_cmpsi (operands[2], const1_rtx)); - emit_jump_insn (gen_beq (label1)); + emit_cmp_and_jump_insns (operands[2], operands[1], GT, NULL_RTX, + SImode, 1, label3); + emit_cmp_and_jump_insns (operands[2], const0_rtx, LT, NULL_RTX, + SImode, 0, label2); + emit_cmp_and_jump_insns (operands[2], const1_rtx, EQ, NULL_RTX, + SImode, 0, label1); emit_insn (gen_zero_extendsidi2 (operands[3], operands[1])); insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3], operands[2])); @@ -5652,8 +5610,8 @@ operands[1] = make_safe_from (operands[1], operands[0]); emit_move_insn (operands[0], operands[1]); - emit_insn (gen_cmpsi (operands[0], operands[2])); - emit_jump_insn (gen_bltu (label1)); + emit_cmp_and_jump_insns (operands[0], operands[2], LT, NULL_RTX, + SImode, 1, label1); emit_insn (gen_abssi2 (operands[0], operands[2])); emit_insn (gen_addsi3 (operands[0], operands[0], operands[1])); emit_label (label1); @@ -5685,12 +5643,12 @@ operands[2] = make_safe_from (operands[2], operands[0]); emit_move_insn(operands[0], operands[1]); - emit_insn (gen_cmpsi (operands[2], operands[1])); - emit_jump_insn (gen_bgtu (label3)); - emit_insn (gen_cmpsi (operands[2], const0_rtx)); - emit_jump_insn (gen_blt (label2)); - emit_insn (gen_cmpsi (operands[2], const1_rtx)); - emit_jump_insn (gen_beq (label1)); + emit_cmp_and_jump_insns (operands[2], operands[1], GT, NULL_RTX, + SImode, 1, label3); + emit_cmp_and_jump_insns (operands[2], const0_rtx, LT, NULL_RTX, + SImode, 0, label2); + emit_cmp_and_jump_insns (operands[2], const1_rtx, EQ, NULL_RTX, + SImode, 0, label1); emit_insn (gen_zero_extendsidi2 (operands[3], operands[1])); insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3], operands[2])); @@ -7359,15 +7317,42 @@ ;; Branch instruction patterns. ;; -(define_expand "b" +(define_expand "cbranch4" [(set (pc) - (if_then_else (COMPARE (match_operand 0 "" "") - (const_int 0)) - (match_dup 0) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:GPR 1 "register_operand" "") + (match_operand:GPR 2 "general_operand" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] "" - "s390_emit_jump (operands[0], - s390_emit_compare (, s390_compare_op0, s390_compare_op1)); DONE;") + "s390_emit_jump (operands[3], + s390_emit_compare (GET_CODE (operands[0]), operands[1], operands[2])); + DONE;") + +(define_expand "cbranch4" + [(set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:FP 1 "register_operand" "") + (match_operand:FP 2 "general_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_HARD_FLOAT" + "s390_emit_jump (operands[3], + s390_emit_compare (GET_CODE (operands[0]), operands[1], operands[2])); + DONE;") + +(define_expand "cbranchcc4" + [(set (pc) + (if_then_else (match_operator 0 "s390_eqne_operator" + [(match_operand 1 "cc_reg_operand" "") + (match_operand 2 "const0_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_HARD_FLOAT" + "s390_emit_jump (operands[3], + s390_emit_compare (GET_CODE (operands[0]), operands[1], operands[2])); + DONE;") + ;; @@ -7506,18 +7491,36 @@ [(set_attr "op_type" "RI") (set_attr "type" "branch")]) -(define_expand "conditional_trap" - [(trap_if (match_operand 0 "comparison_operator" "") - (match_operand 1 "general_operand" ""))] +(define_expand "ctrap4" + [(trap_if (match_operator 0 "comparison_operator" + [(match_operand:GPR 1 "register_operand" "") + (match_operand:GPR 2 "general_operand" "")]) + (match_operand 3 "const0_operand" ""))] "" -{ - if (operands[1] != const0_rtx) FAIL; - operands[0] = s390_emit_compare (GET_CODE (operands[0]), - s390_compare_op0, s390_compare_op1); -}) + { + rtx cond = s390_emit_compare (GET_CODE (operands[0]), + operands[1], operands[2]); + emit_insn (gen_condtrap (cond, XEXP (cond, 0))); + DONE; + }) + +(define_expand "ctrap4" + [(trap_if (match_operator 0 "comparison_operator" + [(match_operand:FP 1 "register_operand" "") + (match_operand:FP 2 "general_operand" "")]) + (match_operand 3 "const0_operand" ""))] + "" + { + rtx cond = s390_emit_compare (GET_CODE (operands[0]), + operands[1], operands[2]); + emit_insn (gen_condtrap (cond, XEXP (cond, 0))); + DONE; + }) -(define_insn "*trap" - [(trap_if (match_operator 0 "s390_comparison" [(reg CC_REGNUM) (const_int 0)]) +(define_insn "condtrap" + [(trap_if (match_operator 0 "s390_comparison" + [(match_operand 1 "cc_reg_operand" "c") + (const_int 0)]) (const_int 0))] "" "j%C0\t.+2"; @@ -8665,6 +8668,7 @@ (match_operand 2 "" "")] "" { + rtx cc_reg, test; #ifdef TARGET_THREAD_SSP_OFFSET operands[1] = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), @@ -8675,9 +8679,9 @@ else emit_insn (gen_stack_protect_testsi (operands[0], operands[1])); - s390_compare_op0 = gen_rtx_REG (CCZmode, CC_REGNUM); - s390_compare_op1 = const0_rtx; - emit_jump_insn (gen_beq (operands[2])); + cc_reg = gen_rtx_REG (CCZmode, CC_REGNUM); + test = gen_rtx_EQ (VOIDmode, cc_reg, const0_rtx); + emit_jump_insn (gen_cbranchcc4 (test, cc_reg, const0_rtx, operands[2])); DONE; }) diff --git a/gcc/config/score/score-conv.h b/gcc/config/score/score-conv.h index 67855da895e..e042dc1b7d3 100644 --- a/gcc/config/score/score-conv.h +++ b/gcc/config/score/score-conv.h @@ -22,11 +22,6 @@ extern int target_flags; -/* Define the information needed to generate branch insns. This is - stored from the compare operation. */ -extern GTY(()) rtx cmp_op0; -extern GTY(()) rtx cmp_op1; - #define GP_REG_FIRST 0U #define GP_REG_LAST 31U #define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1U) diff --git a/gcc/config/score/score-protos.h b/gcc/config/score/score-protos.h index d6739b8cf4c..204dc1876a4 100644 --- a/gcc/config/score/score-protos.h +++ b/gcc/config/score/score-protos.h @@ -25,7 +25,6 @@ enum score_mem_unit {SCORE_BYTE = 0, SCORE_HWORD = 1, SCORE_WORD = 2}; #define SCORE_ALIGN_UNIT(V, UNIT) !(V & ((1 << UNIT) - 1)) -extern void score_gen_cmp (enum machine_mode mode); extern void score_prologue (void); extern void score_epilogue (int sibcall_p); extern void score_call (rtx *ops, bool sib); diff --git a/gcc/config/score/score.c b/gcc/config/score/score.c index 2ac3021bf5e..e517eeb6608 100644 --- a/gcc/config/score/score.c +++ b/gcc/config/score/score.c @@ -117,7 +117,6 @@ #define TARGET_ADDRESS_COST score_address_cost struct extern_list *extern_head = 0; -rtx cmp_op0, cmp_op1; /* default 0 = NO_REGS */ enum reg_class score_char_to_class[256]; @@ -698,17 +697,6 @@ score_epilogue (int sibcall_p) gcc_unreachable (); } -void -score_gen_cmp (enum machine_mode mode) -{ - if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D) - return score7_gen_cmp (mode); - else if (TARGET_SCORE3) - return score3_gen_cmp (mode); - - gcc_unreachable (); -} - /* Call and sibcall pattern all need call this function. */ void score_call (rtx *ops, bool sib) @@ -1118,7 +1106,7 @@ score_block_move_loop (rtx dst, rtx src, HOST_WIDE_INT length) HOST_WIDE_INT loop_mov_bytes; HOST_WIDE_INT iteration = 0; HOST_WIDE_INT head_length = 0, leftover; - rtx label, src_reg, dst_reg, final_dst; + rtx label, src_reg, dst_reg, final_dst, test; bool gen_loop_head = (src_align < BITS_PER_WORD || dst_align < BITS_PER_WORD); @@ -1158,8 +1146,8 @@ score_block_move_loop (rtx dst, rtx src, HOST_WIDE_INT length) score_block_move_loop_body (dst_reg, dst_align, src_reg, src_align, loop_mov_bytes); - emit_insn (gen_cmpsi (dst_reg, final_dst)); - emit_jump_insn (gen_bne (label)); + test = gen_rtx_NE (VOIDmode, dst_reg, final_dst); + emit_jump_insn (gen_cbranchsi4 (test, dst_reg, final_dst, label)); score_block_move_loop_foot (dst_reg, dst_align, src_reg, src_align, leftover); diff --git a/gcc/config/score/score.md b/gcc/config/score/score.md index e616c57aa7e..b426e14e0ac 100644 --- a/gcc/config/score/score.md +++ b/gcc/config/score/score.md @@ -2175,6 +2175,20 @@ (set_attr "length" "4,4") (set_attr "mode" "SI")]) +(define_expand "cbranchsi4" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_operand:SI 1 "score_register_operand" "") + (match_operand:SI 2 "arith_operand" ""))) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" + [(reg:CC CC_REGNUM) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" + "") + (define_insn "cbrancheqz" [(set (pc) (if_then_else (eq (match_operand:SI 0 "score_register_operand" "d") @@ -2259,16 +2273,6 @@ (const_int 4) (const_int 6)))]) -(define_expand "cmpsi" - [(match_operand:SI 0 "score_register_operand") - (match_operand:SI 1 "arith_operand")] - "" -{ - cmp_op0 = operands[0]; - cmp_op1 = operands[1]; - DONE; -}) - (define_insn "cmpsi_nz_score7" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (match_operand:SI 0 "register_operand" "d,e,d") @@ -2375,106 +2379,6 @@ (set_attr "up_c" "yes") (set_attr "mode" "SI")]) -(define_expand "beq" - [(set (pc) - (if_then_else (eq (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "ble" - [(set (pc) - (if_then_else (le (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - (define_insn "*branch_n_score7" [(set (pc) (if_then_else diff --git a/gcc/config/score/score3.c b/gcc/config/score/score3.c index 9e41452c03d..3ddc3b8c798 100644 --- a/gcc/config/score/score3.c +++ b/gcc/config/score/score3.c @@ -54,9 +54,6 @@ #define BITSET_P(VALUE, BIT) (((VALUE) & (1L << (BIT))) != 0) #define INS_BUF_SZ 128 -/* Define the information needed to generate branch insns. This is - stored from the compare operation. */ -extern rtx cmp_op0, cmp_op1; extern enum reg_class score_char_to_class[256]; static int score3_sdata_max; @@ -1647,13 +1644,6 @@ score3_epilogue (int sibcall_p) emit_jump_insn (gen_return_internal_score3 (gen_rtx_REG (Pmode, RA_REGNUM))); } -void -score3_gen_cmp (enum machine_mode mode) -{ - emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM), - gen_rtx_COMPARE (mode, cmp_op0, cmp_op1))); -} - /* Return true if X is a symbolic constant that can be calculated in the same way as a bare symbol. If it is, store the type of the symbol in *SYMBOL_TYPE. */ @@ -1692,7 +1682,8 @@ score3_movsicc (rtx *ops) mode = score3_select_cc_mode (GET_CODE (ops[1]), ops[2], ops[3]); emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM), - gen_rtx_COMPARE (mode, cmp_op0, cmp_op1))); + gen_rtx_COMPARE (mode, XEXP (ops[1], 0), + XEXP (ops[1], 1)))); } /* Call and sibcall pattern all need call this function. */ diff --git a/gcc/config/score/score3.h b/gcc/config/score/score3.h index c46a8e694d9..d718d12e8d9 100644 --- a/gcc/config/score/score3.h +++ b/gcc/config/score/score3.h @@ -138,7 +138,6 @@ extern enum machine_mode score3_select_cc_mode (enum rtx_code op, rtx x, rtx y); extern void score3_prologue (void); extern void score3_epilogue (int sibcall_p); -extern void score3_gen_cmp (enum machine_mode mode); extern void score3_call (rtx *ops, bool sib); extern void score3_call_value (rtx *ops, bool sib); extern void score3_movsicc (rtx *ops); diff --git a/gcc/config/score/score7.c b/gcc/config/score/score7.c index dc532764edd..661cae73bd3 100644 --- a/gcc/config/score/score7.c +++ b/gcc/config/score/score7.c @@ -54,9 +54,6 @@ #define BITSET_P(VALUE, BIT) (((VALUE) & (1L << (BIT))) != 0) #define INS_BUF_SZ 128 -/* Define the information needed to generate branch insns. This is - stored from the compare operation. */ -extern rtx cmp_op0, cmp_op1; extern enum reg_class score_char_to_class[256]; static int score7_sdata_max; @@ -1531,13 +1528,6 @@ score7_epilogue (int sibcall_p) emit_jump_insn (gen_return_internal_score7 (gen_rtx_REG (Pmode, RA_REGNUM))); } -void -score7_gen_cmp (enum machine_mode mode) -{ - emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM), - gen_rtx_COMPARE (mode, cmp_op0, cmp_op1))); -} - /* Return true if X is a symbolic constant that can be calculated in the same way as a bare symbol. If it is, store the type of the symbol in *SYMBOL_TYPE. */ @@ -1576,7 +1566,8 @@ score7_movsicc (rtx *ops) mode = score7_select_cc_mode (GET_CODE (ops[1]), ops[2], ops[3]); emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM), - gen_rtx_COMPARE (mode, cmp_op0, cmp_op1))); + gen_rtx_COMPARE (mode, XEXP (ops[1], 0), + XEXP (ops[1], 1)))); } /* Call and sibcall pattern all need call this function. */ diff --git a/gcc/config/score/score7.h b/gcc/config/score/score7.h index e2033c74498..0c0a3b20f8e 100644 --- a/gcc/config/score/score7.h +++ b/gcc/config/score/score7.h @@ -139,7 +139,6 @@ extern enum machine_mode score7_select_cc_mode (enum rtx_code op, rtx y); extern void score7_prologue (void); extern void score7_epilogue (int sibcall_p); -extern void score7_gen_cmp (enum machine_mode mode); extern void score7_call (rtx *ops, bool sib); extern void score7_call_value (rtx *ops, bool sib); extern void score7_movsicc (rtx *ops); diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md index da9962c9984..ea924d830f5 100644 --- a/gcc/config/sh/predicates.md +++ b/gcc/config/sh/predicates.md @@ -552,6 +552,17 @@ (and (match_code "minus,div") (match_test "GET_MODE (op) == mode"))) +;; UNORDERED is only supported on SHMEDIA. + +(define_predicate "sh_float_comparison_operator" + (ior (match_operand 0 "ordered_comparison_operator") + (and (match_test "TARGET_SHMEDIA") + (match_code "unordered")))) + +(define_predicate "shmedia_cbranch_comparison_operator" + (ior (match_operand 0 "equality_comparison_operator") + (match_operand 0 "greater_comparison_operator"))) + ;; TODO: Add a comment here. (define_predicate "sh_const_vec" diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index a484b9c5d05..0c89f17b15d 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -41,7 +41,6 @@ enum sh_function_kind { extern rtx sh_fsca_sf2int (void); extern rtx sh_fsca_df2int (void); extern rtx sh_fsca_int2sf (void); -extern struct rtx_def *prepare_scc_operands (enum rtx_code); /* Declare functions defined in sh.c and used in templates. */ @@ -72,7 +71,10 @@ extern enum rtx_code prepare_cbranch_operands (rtx *, enum machine_mode mode, enum rtx_code comparison); extern void expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int); extern bool expand_cbranchdi4 (rtx *operands, enum rtx_code comparison); -extern void from_compare (rtx *, int); +extern void sh_emit_scc_to_t (enum rtx_code, rtx, rtx); +extern rtx sh_emit_cheap_store_flag (enum machine_mode, enum rtx_code, rtx, rtx); +extern void sh_emit_compare_and_branch (rtx *, enum machine_mode); +extern void sh_emit_compare_and_set (rtx *, enum machine_mode); extern int shift_insns_rtx (rtx); extern void gen_ashift (int, int, rtx); extern void gen_ashift_hi (int, int, rtx); @@ -117,7 +119,7 @@ extern int sh_insn_length_adjustment (rtx); extern int sh_can_redirect_branch (rtx, rtx); extern void sh_expand_unop_v2sf (enum rtx_code, rtx, rtx); extern void sh_expand_binop_v2sf (enum rtx_code, rtx, rtx, rtx); -extern int sh_expand_t_scc (enum rtx_code code, rtx target); +extern int sh_expand_t_scc (rtx *); extern rtx sh_gen_truncate (enum machine_mode, rtx, int); extern bool sh_vector_mode_supported_p (enum machine_mode); #endif /* RTX_CODE */ diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index d23a45a2289..e25cd42e871 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -105,12 +105,6 @@ static int skip_cycles = 0; and returned from sh_reorder2. */ static short cached_can_issue_more; -/* Saved operands from the last compare to use when we generate an scc - or bcc insn. */ - -rtx sh_compare_op0; -rtx sh_compare_op1; - /* Provides the class number of the smallest class containing reg number. */ @@ -1677,10 +1671,26 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison) return true; } +/* Emit INSN, possibly in a PARALLEL with an USE of fpscr for SH4. */ + +static void +sh_emit_set_t_insn (rtx insn, enum machine_mode mode) +{ + if ((TARGET_SH4 || TARGET_SH2A) && GET_MODE_CLASS (mode) == MODE_FLOAT) + { + insn = gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, insn, + gen_rtx_USE (VOIDmode, get_fpscr_rtx ()))); + (mode == SFmode ? emit_sf_insn : emit_df_insn) (insn); + } + else + emit_insn (insn); +} + /* Prepare the operands for an scc instruction; make sure that the - compare has been done. */ -rtx -prepare_scc_operands (enum rtx_code code) + compare has been done and the result is in T_REG. */ +void +sh_emit_scc_to_t (enum rtx_code code, rtx op0, rtx op1) { rtx t_reg = gen_rtx_REG (SImode, T_REG); enum rtx_code oldcode = code; @@ -1709,77 +1719,222 @@ prepare_scc_operands (enum rtx_code code) } if (code != oldcode) { - rtx tmp = sh_compare_op0; - sh_compare_op0 = sh_compare_op1; - sh_compare_op1 = tmp; + rtx tmp = op0; + op0 = op1; + op1 = tmp; } - mode = GET_MODE (sh_compare_op0); + mode = GET_MODE (op0); if (mode == VOIDmode) - mode = GET_MODE (sh_compare_op1); + mode = GET_MODE (op1); - sh_compare_op0 = force_reg (mode, sh_compare_op0); + op0 = force_reg (mode, op0); if ((code != EQ && code != NE - && (sh_compare_op1 != const0_rtx + && (op1 != const0_rtx || code == GTU || code == GEU || code == LTU || code == LEU)) - || (mode == DImode && sh_compare_op1 != const0_rtx) + || (mode == DImode && op1 != const0_rtx) || (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT)) - sh_compare_op1 = force_reg (mode, sh_compare_op1); + op1 = force_reg (mode, op1); - if ((TARGET_SH4 || TARGET_SH2A) && GET_MODE_CLASS (mode) == MODE_FLOAT) - (mode == SFmode ? emit_sf_insn : emit_df_insn) - (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, - gen_rtx_SET (VOIDmode, t_reg, - gen_rtx_fmt_ee (code, SImode, - sh_compare_op0, sh_compare_op1)), - gen_rtx_USE (VOIDmode, get_fpscr_rtx ())))); - else - emit_insn (gen_rtx_SET (VOIDmode, t_reg, - gen_rtx_fmt_ee (code, SImode, - sh_compare_op0, sh_compare_op1))); + sh_emit_set_t_insn (gen_rtx_SET (VOIDmode, t_reg, + gen_rtx_fmt_ee (code, SImode, op0, op1)), + mode); +} - return t_reg; +rtx +sh_emit_cheap_store_flag (enum machine_mode mode, enum rtx_code code, + rtx op0, rtx op1) +{ + rtx target = gen_reg_rtx (SImode); + rtx tmp; + + gcc_assert (TARGET_SHMEDIA); + switch (code) + { + case EQ: + case GT: + case LT: + case UNORDERED: + case GTU: + case LTU: + tmp = gen_rtx_fmt_ee (code, SImode, op0, op1); + emit_insn (gen_cstore4_media (target, tmp, op0, op1)); + code = NE; + break; + + case NE: + case GE: + case LE: + case ORDERED: + case GEU: + case LEU: + tmp = gen_rtx_fmt_ee (reverse_condition (code), mode, op0, op1); + emit_insn (gen_cstore4_media (target, tmp, op0, op1)); + code = EQ; + break; + + case UNEQ: + case UNGE: + case UNGT: + case UNLE: + case UNLT: + case LTGT: + return NULL_RTX; + + default: + gcc_unreachable (); + } + + if (mode == DImode) + { + rtx t2 = gen_reg_rtx (DImode); + emit_insn (gen_extendsidi2 (t2, target)); + target = t2; + } + + return gen_rtx_fmt_ee (code, VOIDmode, target, const0_rtx); } /* Called from the md file, set up the operands of a compare instruction. */ void -from_compare (rtx *operands, int code) +sh_emit_compare_and_branch (rtx *operands, enum machine_mode mode) { - enum machine_mode mode = GET_MODE (sh_compare_op0); - rtx insn; - if (mode == VOIDmode) - mode = GET_MODE (sh_compare_op1); - if (code != EQ - || mode == DImode - || (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT)) + enum rtx_code code = GET_CODE (operands[0]); + enum rtx_code branch_code; + rtx op0 = operands[1]; + rtx op1 = operands[2]; + rtx insn, tem; + bool need_ccmpeq = false; + + if (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT) { - /* Force args into regs, since we can't use constants here. */ - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx - || code == GTU || code == GEU - || (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT)) - sh_compare_op1 = force_reg (mode, sh_compare_op1); + op0 = force_reg (mode, op0); + op1 = force_reg (mode, op1); } - if (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT && code == GE) + else { - from_compare (operands, GT); - insn = gen_ieee_ccmpeqsf_t (sh_compare_op0, sh_compare_op1); + if (code != EQ || mode == DImode) + { + /* Force args into regs, since we can't use constants here. */ + op0 = force_reg (mode, op0); + if (op1 != const0_rtx || code == GTU || code == GEU) + op1 = force_reg (mode, op1); + } } + + if (GET_MODE_CLASS (mode) == MODE_FLOAT) + { + if (code == LT + || (code == LE && TARGET_IEEE && TARGET_SH2E) + || (code == GE && !(TARGET_IEEE && TARGET_SH2E))) + { + tem = op0, op0 = op1, op1 = tem; + code = swap_condition (code); + } + + /* GE becomes fcmp/gt+fcmp/eq, for SH2E and TARGET_IEEE only. */ + if (code == GE) + { + gcc_assert (TARGET_IEEE && TARGET_SH2E); + need_ccmpeq = true; + code = GT; + } + + /* Now we can have EQ, NE, GT, LE. NE and LE are then transformed + to EQ/GT respectively. */ + gcc_assert (code == EQ || code == GT || code == NE || code == LE); + } + + switch (code) + { + case EQ: + case GT: + case GE: + case GTU: + case GEU: + branch_code = code; + break; + case NE: + case LT: + case LE: + case LTU: + case LEU: + branch_code = reverse_condition (code); + break; + default: + gcc_unreachable (); + } + + insn = gen_rtx_SET (VOIDmode, + gen_rtx_REG (SImode, T_REG), + gen_rtx_fmt_ee (branch_code, SImode, op0, op1)); + + sh_emit_set_t_insn (insn, mode); + if (need_ccmpeq) + sh_emit_set_t_insn (gen_ieee_ccmpeqsf_t (op0, op1), mode); + + if (branch_code == code) + emit_jump_insn (gen_branch_true (operands[3])); else - insn = gen_rtx_SET (VOIDmode, - gen_rtx_REG (SImode, T_REG), - gen_rtx_fmt_ee ((enum rtx_code) code, SImode, - sh_compare_op0, sh_compare_op1)); - if ((TARGET_SH4 || TARGET_SH2A) && GET_MODE_CLASS (mode) == MODE_FLOAT) + emit_jump_insn (gen_branch_false (operands[3])); +} + +void +sh_emit_compare_and_set (rtx *operands, enum machine_mode mode) +{ + enum rtx_code code = GET_CODE (operands[1]); + rtx op0 = operands[2]; + rtx op1 = operands[3]; + rtx lab = NULL_RTX; + bool invert = false; + rtx tem; + + op0 = force_reg (mode, op0); + if ((code != EQ && code != NE + && (op1 != const0_rtx + || code == GTU || code == GEU || code == LTU || code == LEU)) + || (mode == DImode && op1 != const0_rtx) + || (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT)) + op1 = force_reg (mode, op1); + + if (GET_MODE_CLASS (mode) == MODE_FLOAT) { - insn = gen_rtx_PARALLEL (VOIDmode, - gen_rtvec (2, insn, - gen_rtx_USE (VOIDmode, get_fpscr_rtx ()))); - (mode == SFmode ? emit_sf_insn : emit_df_insn) (insn); + if (code == LT || code == LE) + { + code = swap_condition (code); + tem = op0, op0 = op1, op1 = tem; + } + if (code == GE) + { + if (TARGET_IEEE) + { + lab = gen_label_rtx (); + sh_emit_scc_to_t (EQ, op0, op1); + emit_jump_insn (gen_branch_true (lab)); + code = GT; + } + else + { + code = LT; + invert = true; + } + } } + + if (code == NE) + { + code = EQ; + invert = true; + } + + sh_emit_scc_to_t (code, op0, op1); + if (lab) + emit_label (lab); + if (invert) + emit_insn (gen_movnegt (operands[0])); else - emit_insn (insn); + emit_move_insn (operands[0], gen_rtx_REG (SImode, T_REG)); } /* Functions to output assembly code. */ @@ -10782,17 +10937,21 @@ sh_get_pr_initial_val (void) } int -sh_expand_t_scc (enum rtx_code code, rtx target) +sh_expand_t_scc (rtx operands[]) { + enum rtx_code code = GET_CODE (operands[1]); + rtx target = operands[0]; + rtx op0 = operands[2]; + rtx op1 = operands[3]; rtx result = target; HOST_WIDE_INT val; - if (GET_CODE (sh_compare_op0) != REG || REGNO (sh_compare_op0) != T_REG - || GET_CODE (sh_compare_op1) != CONST_INT) + if (GET_CODE (op0) != REG || REGNO (op0) != T_REG + || GET_CODE (op1) != CONST_INT) return 0; if (GET_CODE (result) != REG) result = gen_reg_rtx (SImode); - val = INTVAL (sh_compare_op1); + val = INTVAL (op1); if ((code == EQ && val == 1) || (code == NE && val == 0)) emit_insn (gen_movt (result)); else if (TARGET_SH2A && ((code == EQ && val == 0) diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index dc6a7ab6b82..ffd0db08225 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -646,8 +646,15 @@ (label_ref (match_operand 3 "" "")) (pc))) (clobber (reg:SI T_REG))] - "TARGET_CBRANCHDI4" - "expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1); DONE;") + "" + "if (TARGET_SHMEDIA) + emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1], + operands[2], operands[3])); + else if (TARGET_CBRANCHDI4) + expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1); + else + sh_emit_compare_and_branch (operands, SImode); + DONE;") ;; ------------------------------------------------------------------------- ;; SImode unsigned integer comparisons @@ -676,23 +683,6 @@ "cmp/hi %1,%0" [(set_attr "type" "mt_group")]) -;; We save the compare operands in the cmpxx patterns and use them when -;; we generate the branch. - -(define_expand "cmpsi" - [(set (reg:SI T_REG) - (compare (match_operand:SI 0 "cmpsi_operand" "") - (match_operand:SI 1 "arith_operand" "")))] - "TARGET_SH1 || TARGET_SHMEDIA" - " -{ - if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == T_REG - && GET_CODE (operands[1]) != CONST_INT) - operands[0] = copy_to_mode_reg (SImode, operands[0]); - sh_compare_op0 = operands[0]; - sh_compare_op1 = operands[1]; - DONE; -}") ;; ------------------------------------------------------------------------- ;; DImode compare and branch @@ -713,29 +703,45 @@ (pc))) (clobber (match_dup 4)) (clobber (reg:SI T_REG))] - "TARGET_CBRANCHDI4" + "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA" " { enum rtx_code comparison; - if (TARGET_EXPAND_CBRANCHDI4) + if (TARGET_SHMEDIA) + { + emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1], + operands[2], operands[3])); + DONE; + } + + else if (!TARGET_CBRANCHDI4) { - if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE)) - DONE; + sh_emit_compare_and_branch (operands, DImode); + DONE; + } + + else + { + if (TARGET_EXPAND_CBRANCHDI4) + { + if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE)) + DONE; + } + comparison = prepare_cbranch_operands (operands, DImode, + LAST_AND_UNUSED_RTX_CODE); + if (comparison != GET_CODE (operands[0])) + operands[0] + = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]); + operands[4] = gen_rtx_SCRATCH (SImode); } - comparison = prepare_cbranch_operands (operands, DImode, - LAST_AND_UNUSED_RTX_CODE); - if (comparison != GET_CODE (operands[0])) - operands[0] - = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]); - operands[4] = gen_rtx_SCRATCH (SImode); }") (define_insn_and_split "cbranchdi4_i" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(match_operand:DI 1 "arith_operand" "r,r") - (match_operand:DI 2 "arith_operand" "rN,i")]) + (match_operand:DI 2 "arith_operand" "rN,I08")]) (label_ref (match_operand 3 "" "")) (pc))) (clobber (match_scratch:SI 4 "=X,&r")) @@ -907,20 +913,6 @@ "cmpgtu %1,r63,%0" [(set_attr "type" "cmp_media")]) -;; We save the compare operands in the cmpxx patterns and use them when -;; we generate the branch. - -(define_expand "cmpdi" - [(set (reg:SI T_REG) - (compare (match_operand:DI 0 "arith_operand" "") - (match_operand:DI 1 "arith_operand" "")))] - "TARGET_SH2 || TARGET_SHMEDIA" - " -{ - sh_compare_op0 = operands[0]; - sh_compare_op1 = operands[1]; - DONE; -}") ;; ------------------------------------------------------------------------- ;; Conditional move instructions ;; ------------------------------------------------------------------------- @@ -988,92 +980,20 @@ " { if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) - && GET_MODE (sh_compare_op0) == DImode - && sh_compare_op1 == const0_rtx) - operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode, - sh_compare_op0, sh_compare_op1); + && GET_MODE (XEXP (operands[1], 0)) == DImode + && XEXP (operands[1], 1) == const0_rtx) + ; else { - rtx tmp; - if (!can_create_pseudo_p ()) FAIL; - tmp = gen_reg_rtx (DImode); - - switch (GET_CODE (operands[1])) - { - case EQ: - emit_insn (gen_seq (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case NE: - emit_insn (gen_seq (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case GT: - emit_insn (gen_sgt (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case LT: - emit_insn (gen_slt (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case GE: - emit_insn (gen_slt (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case LE: - emit_insn (gen_sgt (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case GTU: - emit_insn (gen_sgtu (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case LTU: - emit_insn (gen_sltu (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case GEU: - emit_insn (gen_sltu (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case LEU: - emit_insn (gen_sgtu (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case UNORDERED: - emit_insn (gen_sunordered (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case ORDERED: - emit_insn (gen_sunordered (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case UNEQ: - case UNGE: - case UNGT: - case UNLE: - case UNLT: - case LTGT: - FAIL; - - default: - gcc_unreachable (); - } + operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]), + GET_CODE (operands[1]), + XEXP (operands[1], 0), + XEXP (operands[1], 1)); + if (!operands[1]) + FAIL; } }") @@ -1268,24 +1188,26 @@ " { if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) - && GET_MODE (sh_compare_op0) == SImode + && GET_MODE (XEXP (operands[1], 0)) == SImode && (TARGET_SHMEDIA - || (REG_P (sh_compare_op0) && REGNO (sh_compare_op0) == T_REG)) - && sh_compare_op1 == const0_rtx) - operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode, - sh_compare_op0, sh_compare_op1); + || (REG_P (XEXP (operands[1], 0)) + && REGNO (XEXP (operands[1], 0)) == T_REG)) + && XEXP (operands[1], 1) == const0_rtx) + ; + else if (TARGET_PRETEND_CMOVE) { enum rtx_code code = GET_CODE (operands[1]); enum rtx_code new_code = code; - rtx tmp; + rtx op0 = XEXP (operands[1], 0); + rtx op1 = XEXP (operands[1], 1); if (! currently_expanding_to_rtl) FAIL; switch (code) { case LT: case LE: case LEU: case LTU: - if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) != MODE_INT) + if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT) break; case NE: new_code = reverse_condition (code); @@ -1295,92 +1217,21 @@ default: FAIL; } - tmp = prepare_scc_operands (new_code); + sh_emit_scc_to_t (new_code, op0, op1); operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode, - tmp, const0_rtx); + gen_rtx_REG (SImode, T_REG), const0_rtx); } else { - rtx tmp; - if (!can_create_pseudo_p ()) FAIL; - tmp = gen_reg_rtx (SImode); - - switch (GET_CODE (operands[1])) - { - case EQ: - emit_insn (gen_seq (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case NE: - emit_insn (gen_seq (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case GT: - emit_insn (gen_sgt (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case LT: - emit_insn (gen_slt (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case GE: - emit_insn (gen_slt (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case LE: - emit_insn (gen_sgt (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case GTU: - emit_insn (gen_sgtu (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case LTU: - emit_insn (gen_sltu (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case GEU: - emit_insn (gen_sltu (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case LEU: - emit_insn (gen_sgtu (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case UNORDERED: - emit_insn (gen_sunordered (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case ORDERED: - emit_insn (gen_sunordered (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case UNEQ: - case UNGE: - case UNGT: - case UNLE: - case UNLT: - case LTGT: - FAIL; - - default: - abort (); - } + operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]), + GET_CODE (operands[1]), + XEXP (operands[1], 0), + XEXP (operands[1], 1)); + if (!operands[1]) + FAIL; } }") @@ -1887,8 +1738,9 @@ implemented by comparing with the divisor. */ if (operands[1] == const1_rtx && currently_expanding_to_rtl) { - emit_insn (gen_cmpsi (operands[1], operands[2])); - emit_insn (gen_sgeu (operands[0])); + rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]); + emit_insn (gen_cstoresi4 (operands[0], test, + operands[1], operands[2])); DONE; } else if (operands[2] == const0_rtx) @@ -6877,14 +6729,83 @@ label: ;; Conditional branch insns -(define_expand "beq_media" +(define_expand "cbranchint4_media" + [(set (pc) + (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator" + [(match_operand 1 "" "") + (match_operand 2 "" "")]) + (match_operand 3 "" "") + (pc)))] + "TARGET_SHMEDIA" + " +{ + enum machine_mode mode = GET_MODE (operands[1]); + if (mode == VOIDmode) + mode = GET_MODE (operands[2]); + if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE) + { + operands[1] = force_reg (mode, operands[1]); + if (CONSTANT_P (operands[2]) + && (! satisfies_constraint_I06 (operands[2]))) + operands[2] = force_reg (mode, operands[2]); + } + else + { + if (operands[1] != const0_rtx) + operands[1] = force_reg (mode, operands[1]); + if (operands[2] != const0_rtx) + operands[2] = force_reg (mode, operands[2]); + } + switch (GET_CODE (operands[0])) + { + case LEU: + case LE: + case LTU: + case LT: + operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])), + VOIDmode, operands[2], operands[1]); + operands[1] = XEXP (operands[0], 0); + operands[2] = XEXP (operands[0], 1); + break; + default: + operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]), + VOIDmode, operands[1], operands[2]); + break; + } + operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]); +}") + +(define_expand "cbranchfp4_media" [(set (pc) - (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r") - (match_operand:DI 2 "arith_operand" "r,I06")) - (match_operand 0 "" "") + (if_then_else (match_operator 0 "sh_float_comparison_operator" + [(match_operand 1 "" "") + (match_operand 2 "" "")]) + (match_operand 3 "" "") (pc)))] "TARGET_SHMEDIA" - "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") + " +{ + /* hack to generate same code. */ + rtx tmp_di = GET_CODE (operands[0]) == UNORDERED ? NULL : gen_reg_rtx (DImode); + rtx tmp = gen_reg_rtx (SImode); + rtx cmp; + if (GET_CODE (operands[0]) == NE) + cmp = gen_rtx_EQ (SImode, operands[1], operands[2]); + else + cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode, + operands[1], operands[2]); + + emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2])); + if (tmp_di) emit_insn (gen_extendsidi2 (tmp_di, tmp)); else tmp_di = tmp; + + if (GET_CODE (cmp) == GET_CODE (operands[0])) + operands[0] = gen_rtx_NE (VOIDmode, tmp_di, const0_rtx); + else + operands[0] = gen_rtx_EQ (VOIDmode, tmp_di, const0_rtx); + operands[1] = tmp_di; + operands[2] = const0_rtx; + operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]); +}") (define_insn "*beq_media_i" [(set (pc) @@ -6912,51 +6833,6 @@ label: b%o3i%' %1, %2, %0%>" [(set_attr "type" "cbranch_media")]) -(define_expand "bne_media" - [(set (pc) - (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r") - (match_operand:DI 2 "arith_operand" "r,I06")) - (match_operand 0 "" "") - (pc)))] - "TARGET_SHMEDIA" - "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") - -(define_expand "bgt_media" - [(set (pc) - (if_then_else (gt (match_operand:DI 1 "arith_reg_or_0_operand" "") - (match_operand:DI 2 "arith_reg_or_0_operand" "")) - (match_operand 0 "" "") - (pc)))] - "TARGET_SHMEDIA" - "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") - -(define_expand "bge_media" - [(set (pc) - (if_then_else (ge (match_operand:DI 1 "arith_reg_or_0_operand" "") - (match_operand:DI 2 "arith_reg_or_0_operand" "")) - (match_operand 0 "" "") - (pc)))] - "TARGET_SHMEDIA" - "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") - -(define_expand "bgtu_media" - [(set (pc) - (if_then_else (gtu (match_operand:DI 1 "arith_reg_or_0_operand" "") - (match_operand:DI 2 "arith_reg_or_0_operand" "")) - (match_operand 0 "" "") - (pc)))] - "TARGET_SHMEDIA" - "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") - -(define_expand "bgeu_media" - [(set (pc) - (if_then_else (geu (match_operand:DI 1 "arith_reg_or_0_operand" "") - (match_operand:DI 2 "arith_reg_or_0_operand" "")) - (match_operand 0 "" "") - (pc)))] - "TARGET_SHMEDIA" - "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") - (define_insn "*bgt_media_i" [(set (pc) (if_then_else (match_operator 3 "greater_comparison_operator" @@ -7003,421 +6879,84 @@ label: "b%o3%' %N2, %N1, %0%>" [(set_attr "type" "cbranch_media")]) -(define_expand "beq" +;; combiner splitter for test-and-branch on single bit in register. This +;; is endian dependent because the non-paradoxical subreg looks different +;; on big endian. +(define_split [(set (pc) - (if_then_else (ne (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" + (if_then_else + (match_operator 3 "equality_comparison_operator" + [(subreg:SI (zero_extract:DI (subreg:DI (match_operand:SI 1 + "extend_reg_operand" "") + 0) + (const_int 1) + (match_operand 2 + "const_int_operand" "")) 0) + (const_int 0)]) + (match_operand 0 "target_operand" "") + (pc))) + (clobber (match_operand:SI 4 "arith_reg_dest" ""))] + "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN" + [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5))) + (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))] + " { - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (mode != DImode && mode != SImode) - { - rtx tmp = gen_reg_rtx (DImode); - - emit_insn (gen_seq (tmp)); - emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx)); - DONE; - } - - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (CONSTANT_P (sh_compare_op1) - && (! satisfies_constraint_I06 (sh_compare_op1))) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_beq_media (operands[0], - sh_compare_op0, sh_compare_op1)); - DONE; - } - - from_compare (operands, EQ); + operands[5] = GEN_INT (31 - INTVAL (operands[2])); + operands[6] = (GET_CODE (operands[3]) == EQ + ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx) + : gen_rtx_GT (VOIDmode, const0_rtx, operands[4])); }") -(define_expand "bne" - [(set (pc) - (if_then_else (eq (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" +; operand 0 is the loop count pseudo register +; operand 1 is the number of loop iterations or 0 if it is unknown +; operand 2 is the maximum number of loop iterations +; operand 3 is the number of levels of enclosed loops +; operand 4 is the label to jump to at the top of the loop + +(define_expand "doloop_end" + [(parallel [(set (pc) (if_then_else + (ne:SI (match_operand:SI 0 "" "") + (const_int 1)) + (label_ref (match_operand 4 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) (const_int -1))) + (clobber (reg:SI T_REG))])] + "TARGET_SH2" " { - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (mode != DImode && mode != SImode) - { - rtx tmp = gen_reg_rtx (DImode); - - emit_insn (gen_seq (tmp)); - emit_jump_insn (gen_beq_media (operands[0], tmp, const0_rtx)); - DONE; - } - - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (CONSTANT_P (sh_compare_op1) - && (! satisfies_constraint_I06 (sh_compare_op1))) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bne_media (operands[0], - sh_compare_op0, sh_compare_op1)); - DONE; - } - - from_compare (operands, EQ); -}") + if (GET_MODE (operands[0]) != SImode) + FAIL; +} +") -(define_expand "bgt" +(define_insn_and_split "doloop_end_split" [(set (pc) - (if_then_else (ne (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] + (if_then_else (ne:SI (match_operand:SI 0 "arith_reg_dest" "+r") + (const_int 1)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus (match_dup 0) (const_int -1))) + (clobber (reg:SI T_REG))] + "TARGET_SH2" + "#" "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (mode != DImode && mode != SImode) - { - rtx tmp = gen_reg_rtx (DImode); - - emit_insn (gen_sgt (tmp)); - emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx)); - DONE; - } + [(parallel [(set (reg:SI T_REG) + (eq:SI (match_operand:SI 0 "arith_reg_dest" "+r") + (const_int 1))) + (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]) + (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc)))] +"" + [(set_attr "type" "cbranch")]) - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bgt_media (operands[0], - sh_compare_op0, sh_compare_op1)); - DONE; - } - - from_compare (operands, GT); -}") - -(define_expand "blt" - [(set (pc) - (if_then_else (eq (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (mode != DImode && mode != SImode) - { - rtx tmp = gen_reg_rtx (DImode); - - emit_insn (gen_slt (tmp)); - emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx)); - DONE; - } - - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bgt_media (operands[0], - sh_compare_op1, sh_compare_op0)); - DONE; - } - - if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT) - { - rtx tmp = sh_compare_op0; - sh_compare_op0 = sh_compare_op1; - sh_compare_op1 = tmp; - emit_insn (gen_bgt (operands[0])); - DONE; - } - from_compare (operands, GE); -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (eq (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (mode != DImode && mode != SImode) - { - rtx tmp = gen_reg_rtx (DImode); - - emit_insn (gen_sle (tmp)); - emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx)); - DONE; - } - - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bge_media (operands[0], - sh_compare_op1, sh_compare_op0)); - DONE; - } - - if (TARGET_SH2E - && TARGET_IEEE - && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT) - { - rtx tmp = sh_compare_op0; - sh_compare_op0 = sh_compare_op1; - sh_compare_op1 = tmp; - emit_insn (gen_bge (operands[0])); - DONE; - } - from_compare (operands, GT); -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (ne (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (mode != DImode && mode != SImode) - { - rtx tmp = gen_reg_rtx (DImode); - - emit_insn (gen_sge (tmp)); - emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx)); - DONE; - } - - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bge_media (operands[0], - sh_compare_op0, sh_compare_op1)); - DONE; - } - - if (TARGET_SH2E - && ! TARGET_IEEE - && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT) - { - rtx tmp = sh_compare_op0; - sh_compare_op0 = sh_compare_op1; - sh_compare_op1 = tmp; - emit_insn (gen_ble (operands[0])); - DONE; - } - from_compare (operands, GE); -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (ne (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bgtu_media (operands[0], - sh_compare_op0, sh_compare_op1)); - DONE; - } - - from_compare (operands, GTU); -}") - -(define_expand "bltu" - [(set (pc) - (if_then_else (eq (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bgtu_media (operands[0], - sh_compare_op1, sh_compare_op0)); - DONE; - } - - from_compare (operands, GEU); -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (ne (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bgeu_media (operands[0], - sh_compare_op0, sh_compare_op1)); - DONE; - } - - from_compare (operands, GEU); -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (eq (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bgeu_media (operands[0], - sh_compare_op1, sh_compare_op0)); - DONE; - } - - from_compare (operands, GTU); -}") - -(define_expand "bunordered" - [(set (match_dup 1) (unordered:SI (match_dup 2) (match_dup 3))) - (set (pc) - (if_then_else (ne (match_dup 1) (const_int 0)) - (match_operand 0 "" "") - (pc)))] - "TARGET_SHMEDIA" - " -{ - operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]); - operands[1] = gen_reg_rtx (SImode); - operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1); -}") - -;; combiner splitter for test-and-branch on single bit in register. This -;; is endian dependent because the non-paradoxical subreg looks different -;; on big endian. -(define_split - [(set (pc) - (if_then_else - (match_operator 3 "equality_comparison_operator" - [(subreg:SI (zero_extract:DI (subreg:DI (match_operand:SI 1 - "extend_reg_operand" "") - 0) - (const_int 1) - (match_operand 2 - "const_int_operand" "")) 0) - (const_int 0)]) - (match_operand 0 "target_operand" "") - (pc))) - (clobber (match_operand:SI 4 "arith_reg_dest" ""))] - "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN" - [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5))) - (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))] - - " -{ - operands[5] = GEN_INT (31 - INTVAL (operands[2])); - operands[6] = (GET_CODE (operands[3]) == EQ - ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx) - : gen_rtx_GT (VOIDmode, const0_rtx, operands[4])); -}") - -; operand 0 is the loop count pseudo register -; operand 1 is the number of loop iterations or 0 if it is unknown -; operand 2 is the maximum number of loop iterations -; operand 3 is the number of levels of enclosed loops -; operand 4 is the label to jump to at the top of the loop - -(define_expand "doloop_end" - [(parallel [(set (pc) (if_then_else - (ne:SI (match_operand:SI 0 "" "") - (const_int 1)) - (label_ref (match_operand 4 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) (const_int -1))) - (clobber (reg:SI T_REG))])] - "TARGET_SH2" - " -{ - if (GET_MODE (operands[0]) != SImode) - FAIL; -} -") - -(define_insn_and_split "doloop_end_split" - [(set (pc) - (if_then_else (ne:SI (match_operand:SI 0 "arith_reg_dest" "+r") - (const_int 1)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus (match_dup 0) (const_int -1))) - (clobber (reg:SI T_REG))] - "TARGET_SH2" - "#" - "" - [(parallel [(set (reg:SI T_REG) - (eq:SI (match_operand:SI 0 "arith_reg_dest" "+r") - (const_int 1))) - (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]) - (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc)))] -"" - [(set_attr "type" "cbranch")]) - - -;; ------------------------------------------------------------------------ -;; Jump and linkage insns -;; ------------------------------------------------------------------------ + +;; ------------------------------------------------------------------------ +;; Jump and linkage insns +;; ------------------------------------------------------------------------ (define_insn "jump_compact" [(set (pc) @@ -9120,15 +8659,17 @@ mov.l\\t1f,r0\\n\\ rtx reg3 = gen_reg_rtx (Pmode); rtx reg4 = gen_reg_rtx (Pmode); rtx reg5 = gen_reg_rtx (Pmode); - rtx load; + rtx load, test; operands[0] = convert_modes (DImode, SImode, operands[0], 0); operands[1] = convert_modes (DImode, SImode, operands[1], 0); operands[2] = convert_modes (DImode, SImode, operands[2], 1); - emit_jump_insn (gen_bgt_media (operands[4], operands[1], operands[0])); + test = gen_rtx_GT (VOIDmode, operands[1], operands[0]); + emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0], operands[4])); emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1])); - emit_jump_insn (gen_bgtu_media (operands[4], reg, operands[2])); + test = gen_rtx_GTU (VOIDmode, reg, operands[2]); + emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4])); emit_insn (gen_casesi_shift_media (reg2, reg, operands[3])); emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF (Pmode, operands[3]))); @@ -9580,536 +9121,133 @@ mov.l\\t1f,r0\\n\\ "movrt\\t%0" [(set_attr "type" "arith")]) -(define_expand "seq" - [(set (match_operand:SI 0 "arith_reg_dest" "") - (match_dup 1))] - "" - " -{ - if (TARGET_SHMEDIA) - { - rtx reg; - - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - if (GET_MODE_SIZE (GET_MODE (operands[0])) <= 4) - { - if (GET_MODE (operands[0]) != SImode) - operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0); - - switch (GET_MODE (sh_compare_op0)) - { - case SImode: - emit_insn (gen_cmpeqsi_media (operands[0], - sh_compare_op0, sh_compare_op1)); - break; - - case DImode: - emit_insn (gen_cmpeqdi_media (operands[0], - sh_compare_op0, sh_compare_op1)); - break; - - case SFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpeqsf_media (operands[0], - sh_compare_op0, sh_compare_op1)); - break; - - case DFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpeqdf_media (operands[0], - sh_compare_op0, sh_compare_op1)); - break; - - default: - FAIL; - } - DONE; - } - - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - - switch (GET_MODE (sh_compare_op0)) - { - case SImode: - emit_insn (gen_cmpeqsi_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - case DImode: - emit_insn (gen_cmpeqdi_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - case SFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpeqsf_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - case DFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpeqdf_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - default: - FAIL; - } - - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); - - DONE; - } - if (sh_expand_t_scc (EQ, operands[0])) - DONE; - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (EQ); -}") - -(define_expand "slt" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (match_dup 1))] - "" +(define_expand "cstore4_media" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "sh_float_comparison_operator" + [(match_operand 2 "logical_operand" "") + (match_operand 3 "cmp_operand" "")]))] + "TARGET_SHMEDIA" " { - if (TARGET_SHMEDIA) + enum machine_mode mode = GET_MODE (operands[2]); + enum rtx_code code = GET_CODE (operands[1]); + bool invert, swap; + if (mode == VOIDmode) + mode = GET_MODE (operands[3]); + if (operands[2] == const0_rtx) { - rtx reg; - - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - - switch (GET_MODE (sh_compare_op0)) - { - case SImode: - emit_insn (gen_cmpgtsi_media (reg, - sh_compare_op1, sh_compare_op0)); - break; - - case DImode: - emit_insn (gen_cmpgtdi_media (reg, - sh_compare_op1, sh_compare_op0)); - break; - - case SFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgtsf_media (reg, - sh_compare_op1, sh_compare_op0)); - break; - - case DFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgtdf_media (reg, - sh_compare_op1, sh_compare_op0)); - break; - - default: - FAIL; - } - - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); - - DONE; + if (code == EQ || code == NE) + operands[2] = operands[3], operands[3] = const0_rtx; } - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (LT); -}") - -(define_expand "sle" - [(match_operand:SI 0 "arith_reg_operand" "")] - "" - " -{ - rtx tmp = sh_compare_op0; + else + operands[2] = force_reg (mode, operands[2]); + if (operands[3] != const0_rtx) + operands[3] = force_reg (mode, operands[3]); - if (TARGET_SHMEDIA) + switch (code) { - rtx reg; - - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - - switch (GET_MODE (sh_compare_op0)) - { - case SImode: - { - tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode); - - emit_insn (gen_cmpgtsi_media (tmp, - sh_compare_op0, sh_compare_op1)); - emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); - break; - } - - case DImode: - { - tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode); - - emit_insn (gen_cmpgtdi_media (tmp, - sh_compare_op0, sh_compare_op1)); - emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); - break; - } - - case SFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgesf_media (reg, - sh_compare_op1, sh_compare_op0)); - break; + case GEU: + case GE: + swap = invert = !FLOAT_MODE_P (mode); + break; - case DFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgedf_media (reg, - sh_compare_op1, sh_compare_op0)); - break; + case LEU: + case LE: + swap = FLOAT_MODE_P (mode), invert = !swap; + break; - default: - FAIL; - } + case LTU: + case LT: + swap = true, invert = false; + break; - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); + case GTU: + case GT: + case EQ: + case UNORDERED: + swap = invert = false; + break; - DONE; - } + case NE: + swap = invert = true; + break; - sh_compare_op0 = sh_compare_op1; - sh_compare_op1 = tmp; - emit_insn (gen_sge (operands[0])); - DONE; -}") + default: + gcc_unreachable (); + } -(define_expand "sgt" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (match_dup 1))] - "" - " -{ - if (TARGET_SHMEDIA) + if (swap) { - rtx reg; - - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () ? - gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - - switch (GET_MODE (sh_compare_op0)) - { - case SImode: - emit_insn (gen_cmpgtsi_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - case DImode: - emit_insn (gen_cmpgtdi_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - case SFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgtsf_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - case DFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgtdf_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - default: - FAIL; - } - - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); - - DONE; + rtx tem = operands[2]; + operands[2] = operands[3]; + operands[3] = tem; + code = swap_condition (code); } - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (GT); -}") -(define_expand "sge" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (match_dup 1))] - "" - " -{ - if (TARGET_SHMEDIA) + if (invert) { - rtx reg; - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if ((mode) == VOIDmode) - mode = GET_MODE (sh_compare_op1); - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - - switch (mode) - { - case SImode: - { - rtx tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode); - - emit_insn (gen_cmpgtsi_media (tmp, - sh_compare_op1, sh_compare_op0)); - emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); - break; - } - - case DImode: - { - rtx tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode); - - emit_insn (gen_cmpgtdi_media (tmp, - sh_compare_op1, sh_compare_op0)); - emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); - break; - } - - case SFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgesf_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - case DFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgedf_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - default: - FAIL; - } - - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); - - DONE; + rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0]; + code = reverse_condition (code); + operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]); + emit_insn (gen_cstore4_media (tem, operands[1], + operands[2], operands[3])); + code = EQ; + operands[2] = tem; + operands[3] = const0_rtx; } - if (! currently_expanding_to_rtl) - FAIL; - if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT) - { - if (TARGET_IEEE) - { - rtx lab = gen_label_rtx (); - prepare_scc_operands (EQ); - emit_jump_insn (gen_branch_true (lab)); - prepare_scc_operands (GT); - emit_label (lab); - emit_insn (gen_movt (operands[0])); - } - else - emit_insn (gen_movnegt (operands[0], prepare_scc_operands (LT))); - DONE; - } - operands[1] = prepare_scc_operands (GE); + operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]); }") -(define_expand "sgtu" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (match_dup 1))] - "" - " -{ - if (TARGET_SHMEDIA) +(define_expand "cstoresi4" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "comparison_operator" + [(match_operand:SI 2 "cmpsi_operand" "") + (match_operand:SI 3 "arith_operand" "")]))] + "TARGET_SH1 || TARGET_SHMEDIA" + "if (TARGET_SHMEDIA) { - rtx reg; - - reg = operands[0]; - if (GET_MODE (operands[0]) == DImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - - emit_insn (gen_cmpgtudi_media (reg, - sh_compare_op0, sh_compare_op1)); - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); - + emit_insn (gen_cstore4_media (operands[0], operands[1], + operands[2], operands[3])); DONE; } - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (GTU); -}") -(define_expand "sltu" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (match_dup 1))] - "" - " -{ - if (TARGET_SHMEDIA) - { - rtx reg; - - reg = operands[0]; - if (GET_MODE (operands[0]) == DImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - - emit_insn (gen_cmpgtudi_media (reg, - sh_compare_op1, sh_compare_op0)); - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); + if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) + && sh_expand_t_scc (operands)) + DONE; - DONE; - } - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (LTU); -}") + if (! currently_expanding_to_rtl) + FAIL; + + sh_emit_compare_and_set (operands, SImode); + DONE; +") -(define_expand "sleu" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (match_dup 1))] - "" - " -{ - if (TARGET_SHMEDIA) +(define_expand "cstoredi4" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "comparison_operator" + [(match_operand:DI 2 "arith_operand" "") + (match_operand:DI 3 "arith_operand" "")]))] + "TARGET_SH2 || TARGET_SHMEDIA" + "if (TARGET_SHMEDIA) { - rtx tmp, reg; - - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - - tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode); - - emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1)); - emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); - + emit_insn (gen_cstore4_media (operands[0], operands[1], + operands[2], operands[3])); DONE; } - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (LEU); -}") - -(define_expand "sgeu" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (match_dup 1))] - "" - " -{ - if (TARGET_SHMEDIA) - { - rtx tmp, reg; - - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - tmp = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (SImode); + if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) + && sh_expand_t_scc (operands)) + DONE; - emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0)); - emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); + if (! currently_expanding_to_rtl) + FAIL; + + sh_emit_compare_and_set (operands, DImode); + DONE; +") - DONE; - } - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (GEU); -}") ;; sne moves the complement of the T reg to DEST like this: ;; cmp/eq ... @@ -10119,81 +9257,20 @@ mov.l\\t1f,r0\\n\\ ;; not require r0 and further, the -1 may be CSE-ed or lifted out of a ;; loop. -(define_expand "sne" - [(set (match_dup 2) (const_int -1)) - (parallel [(set (match_operand:SI 0 "arith_reg_operand" "") - (neg:SI (plus:SI (match_dup 1) - (match_dup 2)))) +(define_expand "movnegt" + [(set (match_dup 1) (const_int -1)) + (parallel [(set (match_operand:SI 0 "" "") + (neg:SI (plus:SI (reg:SI T_REG) + (match_dup 1)))) (set (reg:SI T_REG) - (ne:SI (ior:SI (match_dup 1) (match_dup 2)) + (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1)) (const_int 0)))])] "" " { - if (TARGET_SHMEDIA) - { - rtx tmp, reg; - - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - if (! TARGET_SHMEDIA_FPU - && GET_MODE (sh_compare_op0) != DImode - && GET_MODE (sh_compare_op0) != SImode) - FAIL; - - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - - tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode); - - emit_insn (gen_seq (tmp)); - emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); - - DONE; - } - - if (sh_expand_t_scc (NE, operands[0])) - DONE; - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (EQ); - operands[2] = gen_reg_rtx (SImode); -}") - -(define_expand "sunordered" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (unordered:SI (match_dup 1) (match_dup 2)))] - "TARGET_SHMEDIA_FPU" - " -{ - operands[1] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - operands[2] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1); + operands[1] = gen_reg_rtx (SImode); }") -;; Use the same trick for FP sle / sge - -;; Apart from the constant use and the T setting, this is like movt, -;; except that it uses the logically negated value of T, i.e. -;; operand[0] := T ? 0 : 1. -(define_expand "movnegt" - [(set (match_dup 2) (const_int -1)) - (parallel [(set (match_operand 0 "" "") - (neg:SI (plus:SI (match_dup 1) - (match_dup 2)))) - (set (reg:SI T_REG) - (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2)) - (const_int 0)))])] - "TARGET_SH1" - "operands[2] = gen_reg_rtx (SImode);") ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1. ;; This prevents a regression that occurred when we switched from xor to @@ -10208,6 +9285,47 @@ mov.l\\t1f,r0\\n\\ (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))] "") +(define_expand "cstoresf4" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "sh_float_comparison_operator" + [(match_operand:SF 2 "arith_operand" "") + (match_operand:SF 3 "arith_operand" "")]))] + "TARGET_SH2E || TARGET_SHMEDIA_FPU" + "if (TARGET_SHMEDIA) + { + emit_insn (gen_cstore4_media (operands[0], operands[1], + operands[2], operands[3])); + DONE; + } + + if (! currently_expanding_to_rtl) + FAIL; + + sh_emit_compare_and_set (operands, SFmode); + DONE; +") + +(define_expand "cstoredf4" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "sh_float_comparison_operator" + [(match_operand:DF 2 "arith_operand" "") + (match_operand:DF 3 "arith_operand" "")]))] + "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" + "if (TARGET_SHMEDIA) + { + emit_insn (gen_cstore4_media (operands[0], operands[1], + operands[2], operands[3])); + DONE; + } + + if (! currently_expanding_to_rtl) + FAIL; + + sh_emit_compare_and_set (operands, DFmode); + DONE; +") + + ;; ------------------------------------------------------------------------- ;; Instructions to cope with inline literal tables ;; ------------------------------------------------------------------------- @@ -10986,15 +10104,21 @@ mov.l\\t1f,r0\\n\\ "fcmpun.s %1, %2, %0" [(set_attr "type" "fcmp_media")]) -(define_expand "cmpsf" - [(set (reg:SI T_REG) - (compare (match_operand:SF 0 "arith_operand" "") - (match_operand:SF 1 "arith_operand" "")))] +(define_expand "cbranchsf4" + [(set (pc) + (if_then_else (match_operator 0 "sh_float_comparison_operator" + [(match_operand:SF 1 "arith_operand" "") + (match_operand:SF 2 "arith_operand" "")]) + (match_operand 3 "" "") + (pc)))] "TARGET_SH2E || TARGET_SHMEDIA_FPU" " { - sh_compare_op0 = operands[0]; - sh_compare_op1 = operands[1]; + if (TARGET_SHMEDIA) + emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2], + operands[3])); + else + sh_emit_compare_and_branch (operands, SFmode); DONE; }") @@ -11484,18 +10608,25 @@ mov.l\\t1f,r0\\n\\ "fcmpun.d %1,%2,%0" [(set_attr "type" "fcmp_media")]) -(define_expand "cmpdf" - [(set (reg:SI T_REG) - (compare (match_operand:DF 0 "arith_operand" "") - (match_operand:DF 1 "arith_operand" "")))] +(define_expand "cbranchdf4" + [(set (pc) + (if_then_else (match_operator 0 "sh_float_comparison_operator" + [(match_operand:DF 1 "arith_operand" "") + (match_operand:DF 2 "arith_operand" "")]) + (match_operand 3 "" "") + (pc)))] "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" " { - sh_compare_op0 = operands[0]; - sh_compare_op1 = operands[1]; + if (TARGET_SHMEDIA) + emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2], + operands[3])); + else + sh_emit_compare_and_branch (operands, DFmode); DONE; }") + (define_expand "negdf2" [(set (match_operand:DF 0 "arith_reg_operand" "") (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))] @@ -14144,15 +13275,21 @@ mov.l\\t1f,r0\\n\\ if (TARGET_SHMEDIA) { rtx tmp = gen_reg_rtx (GET_MODE (operands[0])); + rtx test; + test = gen_rtx_NE (VOIDmode, tmp, const0_rtx); if (TARGET_SHMEDIA64) - emit_insn (gen_stack_protect_test_di_media (tmp, operands[0], - operands[1])); + { + emit_insn (gen_stack_protect_test_di_media (tmp, operands[0], + operands[1])); + emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2])); + } else - emit_insn (gen_stack_protect_test_si_media (tmp, operands[0], - operands[1])); - - emit_jump_insn (gen_bne_media (operands[2], tmp, const0_rtx)); + { + emit_insn (gen_stack_protect_test_si_media (tmp, operands[0], + operands[1])); + emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2])); + } } else { diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h index 40ac75e130c..fd388dd8139 100644 --- a/gcc/config/sparc/sparc-protos.h +++ b/gcc/config/sparc/sparc-protos.h @@ -54,16 +54,14 @@ extern void sparc_output_scratch_registers (FILE *); #ifdef RTX_CODE extern enum machine_mode select_cc_mode (enum rtx_code, rtx, rtx); /* Define the function that build the compare insn for scc and bcc. */ -extern rtx gen_compare_reg (enum rtx_code code); -extern rtx gen_compare_operator (enum rtx_code code); -extern enum rtx_code sparc_emit_float_lib_cmp (rtx, rtx, enum rtx_code); +extern rtx gen_compare_reg (rtx cmp); +extern rtx sparc_emit_float_lib_cmp (rtx, rtx, enum rtx_code); extern void sparc_emit_floatunsdi (rtx [2], enum machine_mode); extern void sparc_emit_fixunsdi (rtx [2], enum machine_mode); extern void emit_tfmode_binop (enum rtx_code, rtx *); extern void emit_tfmode_unop (enum rtx_code, rtx *); extern void emit_tfmode_cvt (enum rtx_code, rtx *); /* This function handles all v9 scc insns */ -extern int gen_v9_scc (enum rtx_code, rtx *); extern void sparc_initialize_trampoline (rtx, rtx, rtx); extern void sparc64_initialize_trampoline (rtx, rtx, rtx); extern bool legitimate_constant_p (rtx); @@ -86,7 +84,8 @@ extern const char *output_return (rtx); extern const char *output_sibcall (rtx, rtx); extern const char *output_v8plus_shift (rtx *, rtx, const char *); extern const char *output_v9branch (rtx, rtx, int, int, int, int, rtx); -extern void emit_v9_brxx_insn (enum rtx_code, rtx, rtx); +extern bool emit_scc_insn (rtx []); +extern void emit_conditional_branch_insn (rtx []); extern void print_operand (FILE *, rtx, int); extern int mems_ok_for_ldd_peep (rtx, rtx, rtx); extern int arith_double_4096_operand (rtx, enum machine_mode); diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index ab2b57bbcd9..330c2c06981 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -280,10 +280,6 @@ static GTY(()) alias_set_type sparc_sr_alias_set; /* The alias set for the structure return value. */ static GTY(()) alias_set_type struct_value_alias_set; -/* Save the operands last given to a compare for use when we - generate a scc or bcc insn. */ -rtx sparc_compare_op0, sparc_compare_op1; - /* Vector to say how input registers are mapped to output registers. HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to eliminate it. You must use -fomit-frame-pointer to get that. */ @@ -2005,19 +2001,18 @@ select_cc_mode (enum rtx_code op, rtx x, rtx y ATTRIBUTE_UNUSED) } } -/* Emit the compare insn and return the CC reg for a CODE comparison. */ +/* Emit the compare insn and return the CC reg for a CODE comparison + with operands X and Y. */ -rtx -gen_compare_reg (enum rtx_code code) +static rtx +gen_compare_reg_1 (enum rtx_code code, rtx x, rtx y) { enum machine_mode mode; - rtx x, y, cc_reg; + rtx cc_reg; - if (GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) == MODE_CC) - return sparc_compare_op0; + if (GET_MODE_CLASS (GET_MODE (x)) == MODE_CC) + return x; - x = sparc_compare_op0; - y = sparc_compare_op1; mode = SELECT_CC_MODE (code, x, y); /* ??? We don't have movcc patterns so we cannot generate pseudo regs for the @@ -2073,26 +2068,19 @@ gen_compare_reg (enum rtx_code code) return cc_reg; } -/* Same as above but return the whole compare operator. */ + +/* Emit the compare insn and return the CC reg for the comparison in CMP. */ rtx -gen_compare_operator (enum rtx_code code) +gen_compare_reg (rtx cmp) { - rtx cc_reg; - - if (GET_MODE (sparc_compare_op0) == TFmode && !TARGET_HARD_QUAD) - code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, code); - - cc_reg = gen_compare_reg (code); - return gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); + return gen_compare_reg_1 (GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1)); } /* This function is used for v9 only. + DEST is the target of the Scc insn. CODE is the code for an Scc's comparison. - OPERANDS[0] is the target of the Scc insn. - OPERANDS[1] is the value we compare against const0_rtx (which hasn't - been generated yet). + X and Y are the values we compare. This function is needed to turn @@ -2106,53 +2094,50 @@ gen_compare_operator (enum rtx_code code) IE: The instruction recognizer needs to see the mode of the comparison to find the right instruction. We could use "gt:DI" right in the - define_expand, but leaving it out allows us to handle DI, SI, etc. + define_expand, but leaving it out allows us to handle DI, SI, etc. */ - We refer to the global sparc compare operands sparc_compare_op0 and - sparc_compare_op1. */ - -int -gen_v9_scc (enum rtx_code compare_code, register rtx *operands) +static int +gen_v9_scc (rtx dest, enum rtx_code compare_code, rtx x, rtx y) { if (! TARGET_ARCH64 - && (GET_MODE (sparc_compare_op0) == DImode - || GET_MODE (operands[0]) == DImode)) + && (GET_MODE (x) == DImode + || GET_MODE (dest) == DImode)) return 0; /* Try to use the movrCC insns. */ if (TARGET_ARCH64 - && GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) == MODE_INT - && sparc_compare_op1 == const0_rtx + && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT + && y == const0_rtx && v9_regcmp_p (compare_code)) { - rtx op0 = sparc_compare_op0; + rtx op0 = x; rtx temp; /* Special case for op0 != 0. This can be done with one instruction if - operands[0] == sparc_compare_op0. */ + dest == x. */ if (compare_code == NE - && GET_MODE (operands[0]) == DImode - && rtx_equal_p (op0, operands[0])) + && GET_MODE (dest) == DImode + && rtx_equal_p (op0, dest)) { - emit_insn (gen_rtx_SET (VOIDmode, operands[0], + emit_insn (gen_rtx_SET (VOIDmode, dest, gen_rtx_IF_THEN_ELSE (DImode, gen_rtx_fmt_ee (compare_code, DImode, op0, const0_rtx), const1_rtx, - operands[0]))); + dest))); return 1; } - if (reg_overlap_mentioned_p (operands[0], op0)) + if (reg_overlap_mentioned_p (dest, op0)) { - /* Handle the case where operands[0] == sparc_compare_op0. + /* Handle the case where dest == x. We "early clobber" the result. */ - op0 = gen_reg_rtx (GET_MODE (sparc_compare_op0)); - emit_move_insn (op0, sparc_compare_op0); + op0 = gen_reg_rtx (GET_MODE (x)); + emit_move_insn (op0, x); } - emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx)); + emit_insn (gen_rtx_SET (VOIDmode, dest, const0_rtx)); if (GET_MODE (op0) != DImode) { temp = gen_reg_rtx (DImode); @@ -2160,47 +2145,137 @@ gen_v9_scc (enum rtx_code compare_code, register rtx *operands) } else temp = op0; - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), + emit_insn (gen_rtx_SET (VOIDmode, dest, + gen_rtx_IF_THEN_ELSE (GET_MODE (dest), gen_rtx_fmt_ee (compare_code, DImode, temp, const0_rtx), const1_rtx, - operands[0]))); + dest))); return 1; } else { - operands[1] = gen_compare_reg (compare_code); + x = gen_compare_reg_1 (compare_code, x, y); + y = const0_rtx; - switch (GET_MODE (operands[1])) - { - case CCmode : - case CCXmode : - case CCFPEmode : - case CCFPmode : - break; - default : - gcc_unreachable (); - } - emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx)); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), + gcc_assert (GET_MODE (x) != CC_NOOVmode + && GET_MODE (x) != CCX_NOOVmode); + + emit_insn (gen_rtx_SET (VOIDmode, dest, const0_rtx)); + emit_insn (gen_rtx_SET (VOIDmode, dest, + gen_rtx_IF_THEN_ELSE (GET_MODE (dest), gen_rtx_fmt_ee (compare_code, - GET_MODE (operands[1]), - operands[1], const0_rtx), - const1_rtx, operands[0]))); + GET_MODE (x), x, y), + const1_rtx, dest))); return 1; } } + +/* Emit an scc insn. For seq, sne, sgeu, and sltu, we can do this + without jumps using the addx/subx instructions. */ + +bool +emit_scc_insn (rtx operands[]) +{ + rtx tem; + rtx x; + rtx y; + enum rtx_code code; + + /* The quad-word fp compare library routines all return nonzero to indicate + true, which is different from the equivalent libgcc routines, so we must + handle them specially here. */ + if (GET_MODE (operands[2]) == TFmode && ! TARGET_HARD_QUAD) + { + operands[1] = sparc_emit_float_lib_cmp (operands[2], operands[3], + GET_CODE (operands[1])); + operands[2] = XEXP (operands[1], 0); + operands[3] = XEXP (operands[1], 1); + } + + code = GET_CODE (operands[1]); + x = operands[2]; + y = operands[3]; + + /* For seq/sne on v9 we use the same code as v8 (the addx/subx method has + more applications). The exception to this is "reg != 0" which can + be done in one instruction on v9 (so we do it). */ + if (code == EQ) + { + if (GET_MODE (x) == SImode) + { + rtx pat = gen_seqsi_special (operands[0], x, y); + emit_insn (pat); + return true; + } + else if (GET_MODE (x) == DImode) + { + rtx pat = gen_seqdi_special (operands[0], x, y); + emit_insn (pat); + return true; + } + } + + if (code == NE) + { + if (GET_MODE (x) == SImode) + { + rtx pat = gen_snesi_special (operands[0], x, y); + emit_insn (pat); + return true; + } + else if (GET_MODE (x) == DImode) + { + rtx pat = gen_snedi_special (operands[0], x, y); + emit_insn (pat); + return true; + } + } + + /* For the rest, on v9 we can use conditional moves. */ + + if (TARGET_V9) + { + if (gen_v9_scc (operands[0], code, x, y)) + return true; + } + + /* We can do LTU and GEU using the addx/subx instructions too. And + for GTU/LEU, if both operands are registers swap them and fall + back to the easy case. */ + if (code == GTU || code == LEU) + { + if ((GET_CODE (x) == REG || GET_CODE (x) == SUBREG) + && (GET_CODE (y) == REG || GET_CODE (y) == SUBREG)) + { + tem = x; + x = y; + y = tem; + code = swap_condition (code); + } + } + + if (code == LTU || code == GEU) + { + emit_insn (gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_fmt_ee (code, SImode, + gen_compare_reg_1 (code, x, y), + const0_rtx))); + return true; + } + + /* Nope, do branches. */ + return false; +} + /* Emit a conditional jump insn for the v9 architecture using comparison code CODE and jump target LABEL. This function exists to take advantage of the v9 brxx insns. */ -void +static void emit_v9_brxx_insn (enum rtx_code code, rtx op0, rtx label) { - gcc_assert (GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) != MODE_CC); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, gen_rtx_IF_THEN_ELSE (VOIDmode, @@ -2210,6 +2285,37 @@ emit_v9_brxx_insn (enum rtx_code code, rtx op0, rtx label) pc_rtx))); } +void +emit_conditional_branch_insn (rtx operands[]) +{ + /* The quad-word fp compare library routines all return nonzero to indicate + true, which is different from the equivalent libgcc routines, so we must + handle them specially here. */ + if (GET_MODE (operands[1]) == TFmode && ! TARGET_HARD_QUAD) + { + operands[0] = sparc_emit_float_lib_cmp (operands[1], operands[2], + GET_CODE (operands[0])); + operands[1] = XEXP (operands[0], 0); + operands[2] = XEXP (operands[0], 1); + } + + if (TARGET_ARCH64 && operands[2] == const0_rtx + && GET_CODE (operands[1]) == REG + && GET_MODE (operands[1]) == DImode) + { + emit_v9_brxx_insn (GET_CODE (operands[0]), operands[1], operands[3]); + return; + } + + operands[1] = gen_compare_reg (operands[0]); + operands[2] = const0_rtx; + operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]), VOIDmode, + operands[1], operands[2]); + emit_jump_insn (gen_cbranchcc4 (operands[0], operands[1], operands[2], + operands[3])); +} + + /* Generate a DFmode part of a hard TFmode register. REG is the TFmode hard register, LOW is 1 for the low 64bit of the register and 0 otherwise. @@ -6116,7 +6222,7 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul, values as arguments instead of the TFmode registers themselves, that's why we cannot call emit_float_lib_cmp. */ -enum rtx_code +rtx sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison) { const char *qpfunc; @@ -6207,32 +6313,24 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison) switch (comparison) { default: - new_comparison = NE; - emit_cmp_insn (result, const0_rtx, new_comparison, NULL_RTX, mode, 0); - break; + return gen_rtx_NE (VOIDmode, result, const0_rtx); case ORDERED: case UNORDERED: new_comparison = (comparison == UNORDERED ? EQ : NE); - emit_cmp_insn (result, GEN_INT(3), new_comparison, NULL_RTX, mode, 0); - break; + return gen_rtx_fmt_ee (new_comparison, VOIDmode, result, GEN_INT(3)); case UNGT: case UNGE: new_comparison = (comparison == UNGT ? GT : NE); - emit_cmp_insn (result, const1_rtx, new_comparison, NULL_RTX, mode, 0); - break; + return gen_rtx_fmt_ee (new_comparison, VOIDmode, result, const1_rtx); case UNLE: - new_comparison = NE; - emit_cmp_insn (result, const2_rtx, new_comparison, NULL_RTX, mode, 0); - break; + return gen_rtx_NE (VOIDmode, result, const2_rtx); case UNLT: tem = gen_reg_rtx (mode); if (TARGET_ARCH32) emit_insn (gen_andsi3 (tem, result, const1_rtx)); else emit_insn (gen_anddi3 (tem, result, const1_rtx)); - new_comparison = NE; - emit_cmp_insn (tem, const0_rtx, new_comparison, NULL_RTX, mode, 0); - break; + return gen_rtx_NE (VOIDmode, tem, const0_rtx); case UNEQ: case LTGT: tem = gen_reg_rtx (mode); @@ -6246,11 +6344,10 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison) else emit_insn (gen_anddi3 (tem2, tem, const2_rtx)); new_comparison = (comparison == UNEQ ? EQ : NE); - emit_cmp_insn (tem2, const0_rtx, new_comparison, NULL_RTX, mode, 0); - break; + return gen_rtx_fmt_ee (new_comparison, VOIDmode, tem2, const0_rtx); } - return new_comparison; + gcc_unreachable (); } /* Generate an unsigned DImode to FP conversion. This is the same code @@ -9021,15 +9118,12 @@ sparc_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval) gen_rtx_AND (SImode, gen_rtx_NOT (SImode, mask), res))); - sparc_compare_op0 = resv; - sparc_compare_op1 = val; - cc = gen_compare_reg (NE); - + cc = gen_compare_reg_1 (NE, resv, val); emit_insn (gen_rtx_SET (VOIDmode, val, resv)); - sparc_compare_op0 = cc; - sparc_compare_op1 = const0_rtx; - emit_jump_insn (gen_bne (loop_label)); + /* Use cbranchcc4 to separate the compare and branch! */ + emit_jump_insn (gen_cbranchcc4 (gen_rtx_NE (VOIDmode, cc, const0_rtx), + cc, const0_rtx, loop_label)); emit_label (end_label); diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index d21900135e2..280036224be 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -1558,12 +1558,6 @@ function_arg_padding ((MODE), (TYPE)) && (GET_MODE_ALIGNMENT (MODE) == 128 \ || ((TYPE) && TYPE_ALIGN (TYPE) == 128))) \ ? 128 : PARM_BOUNDARY) - -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ - -extern GTY(()) rtx sparc_compare_op0; -extern GTY(()) rtx sparc_compare_op1; /* Generate the special assembly code needed to tell the assembler whatever diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 4fae329cd9a..9e35910f4db 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -76,6 +76,18 @@ (UNSPECV_LDSTUB 10) ]) + +(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) +(define_mode_iterator I [QI HI SI DI]) +(define_mode_iterator F [SF DF TF]) + +;; We don't define V1SI because SI should work just fine. +(define_mode_iterator V32 [SF V2HI V4QI]) +(define_mode_iterator V32I [SI V2HI V4QI]) + +(define_mode_iterator V64 [DF V2SI V4HI V8QI]) +(define_mode_iterator V64I [DI V2SI V4HI V8QI]) + ;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this ;; a second register class, EXTRA_FP_REGS, exists for the v9 chip. The name ;; is a bit of a misnomer as it covers all 64 fp regs. The corresponding @@ -340,84 +352,11 @@ ;; Compare instructions. -;; We generate RTL for comparisons and branches by having the cmpxx -;; patterns store away the operands. Then, the scc and bcc patterns -;; emit RTL for both the compare and the branch. -;; -;; We do this because we want to generate different code for an sne and -;; seq insn. In those cases, if the second operand of the compare is not -;; const0_rtx, we want to compute the xor of the two operands and test -;; it against zero. -;; -;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match -;; the patterns. Finally, we have the DEFINE_SPLITs for some of the scc -;; insns that actually require more than one machine instruction. - -(define_expand "cmpsi" - [(set (reg:CC 100) - (compare:CC (match_operand:SI 0 "compare_operand" "") - (match_operand:SI 1 "arith_operand" "")))] - "" -{ - if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx) - operands[0] = force_reg (SImode, operands[0]); - - sparc_compare_op0 = operands[0]; - sparc_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmpdi" - [(set (reg:CCX 100) - (compare:CCX (match_operand:DI 0 "compare_operand" "") - (match_operand:DI 1 "arith_operand" "")))] - "TARGET_ARCH64" -{ - if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx) - operands[0] = force_reg (DImode, operands[0]); - - sparc_compare_op0 = operands[0]; - sparc_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmpsf" - ;; The 96 here isn't ever used by anyone. - [(set (reg:CCFP 96) - (compare:CCFP (match_operand:SF 0 "register_operand" "") - (match_operand:SF 1 "register_operand" "")))] - "TARGET_FPU" -{ - sparc_compare_op0 = operands[0]; - sparc_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmpdf" - ;; The 96 here isn't ever used by anyone. - [(set (reg:CCFP 96) - (compare:CCFP (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "register_operand" "")))] - "TARGET_FPU" -{ - sparc_compare_op0 = operands[0]; - sparc_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmptf" - ;; The 96 here isn't ever used by anyone. - [(set (reg:CCFP 96) - (compare:CCFP (match_operand:TF 0 "register_operand" "") - (match_operand:TF 1 "register_operand" "")))] - "TARGET_FPU" -{ - sparc_compare_op0 = operands[0]; - sparc_compare_op1 = operands[1]; - DONE; -}) +;; These are just the DEFINE_INSNs to match the patterns and the +;; DEFINE_SPLITs for some of the scc insns that actually require +;; more than one machine instruction. DEFINE_EXPANDs are further down. -;; Now the compare DEFINE_INSNs. +;; The compare DEFINE_INSNs. (define_insn "*cmpsi_insn" [(set (reg:CC 100) @@ -509,12 +448,41 @@ } [(set_attr "type" "fpcmp")]) -;; Next come the scc insns. For seq, sne, sgeu, and sltu, we can do this -;; without jumps using the addx/subx instructions. For seq/sne on v9 we use -;; the same code as v8 (the addx/subx method has more applications). The -;; exception to this is "reg != 0" which can be done in one instruction on v9 -;; (so we do it). For the rest, on v9 we use conditional moves; on v8, we do -;; branches. +;; Next come the scc insns. + +(define_expand "cstoresi4" + [(use (match_operator 1 "comparison_operator" + [(match_operand:SI 2 "compare_operand" "") + (match_operand:SI 3 "arith_operand" "")])) + (clobber (match_operand:SI 0 "register_operand"))] + "" +{ + if (GET_CODE (operands[2]) == ZERO_EXTRACT && operands[3] != const0_rtx) + operands[2] = force_reg (SImode, operands[2]); + if (emit_scc_insn (operands)) DONE; else FAIL; +}) + +(define_expand "cstoredi4" + [(use (match_operator 1 "comparison_operator" + [(match_operand:DI 2 "compare_operand" "") + (match_operand:DI 3 "arith_operand" "")])) + (clobber (match_operand:SI 0 "register_operand"))] + "TARGET_ARCH64" +{ + if (GET_CODE (operands[2]) == ZERO_EXTRACT && operands[3] != const0_rtx) + operands[2] = force_reg (DImode, operands[2]); + if (emit_scc_insn (operands)) DONE; else FAIL; +}) + +(define_expand "cstore4" + [(use (match_operator 1 "comparison_operator" + [(match_operand:F 2 "register_operand" "") + (match_operand:F 3 "register_operand" "")])) + (clobber (match_operand:SI 0 "register_operand"))] + "TARGET_FPU" + { if (emit_scc_insn (operands)) DONE; else FAIL; }) + + ;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they ;; generate addcc/subcc instructions. @@ -533,8 +501,8 @@ [(set (match_dup 3) (xor:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) - (set (match_operand:DI 0 "register_operand" "") - (eq:DI (match_dup 3) (const_int 0)))] + (set (match_operand:SI 0 "register_operand" "") + (eq:SI (match_dup 3) (const_int 0)))] "TARGET_ARCH64" { operands[3] = gen_reg_rtx (DImode); }) @@ -552,338 +520,11 @@ [(set (match_dup 3) (xor:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) - (set (match_operand:DI 0 "register_operand" "") - (ne:DI (match_dup 3) (const_int 0)))] - "TARGET_ARCH64" - { operands[3] = gen_reg_rtx (DImode); }) - -(define_expand "seqdi_special_trunc" - [(set (match_dup 3) - (xor:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" ""))) - (set (match_operand:SI 0 "register_operand" "") - (eq:SI (match_dup 3) (const_int 0)))] - "TARGET_ARCH64" - { operands[3] = gen_reg_rtx (DImode); }) - -(define_expand "snedi_special_trunc" - [(set (match_dup 3) - (xor:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" ""))) (set (match_operand:SI 0 "register_operand" "") (ne:SI (match_dup 3) (const_int 0)))] "TARGET_ARCH64" { operands[3] = gen_reg_rtx (DImode); }) -(define_expand "seqsi_special_extend" - [(set (match_dup 3) - (xor:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" ""))) - (parallel [(set (match_operand:DI 0 "register_operand" "") - (eq:DI (match_dup 3) (const_int 0))) - (clobber (reg:CC 100))])] - "TARGET_ARCH64" - { operands[3] = gen_reg_rtx (SImode); }) - -(define_expand "snesi_special_extend" - [(set (match_dup 3) - (xor:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" ""))) - (parallel [(set (match_operand:DI 0 "register_operand" "") - (ne:DI (match_dup 3) (const_int 0))) - (clobber (reg:CC 100))])] - "TARGET_ARCH64" - { operands[3] = gen_reg_rtx (SImode); }) - -;; ??? v9: Operand 0 needs a mode, so SImode was chosen. -;; However, the code handles both SImode and DImode. -(define_expand "seq" - [(set (match_operand:SI 0 "int_register_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == SImode) - { - rtx pat; - - if (GET_MODE (operands[0]) == SImode) - pat = gen_seqsi_special (operands[0], sparc_compare_op0, - sparc_compare_op1); - else if (! TARGET_ARCH64) - FAIL; - else - pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0, - sparc_compare_op1); - emit_insn (pat); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == DImode) - { - rtx pat; - - if (! TARGET_ARCH64) - FAIL; - else if (GET_MODE (operands[0]) == SImode) - pat = gen_seqdi_special_trunc (operands[0], sparc_compare_op0, - sparc_compare_op1); - else - pat = gen_seqdi_special (operands[0], sparc_compare_op0, - sparc_compare_op1); - emit_insn (pat); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ); - gcc_assert (code == NE); - emit_insn (gen_sne (operands[0])); - DONE; - } - else if (TARGET_V9) - { - if (gen_v9_scc (EQ, operands)) - DONE; - /* fall through */ - } - FAIL; -}) - -;; ??? v9: Operand 0 needs a mode, so SImode was chosen. -;; However, the code handles both SImode and DImode. -(define_expand "sne" - [(set (match_operand:SI 0 "int_register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == SImode) - { - rtx pat; - - if (GET_MODE (operands[0]) == SImode) - pat = gen_snesi_special (operands[0], sparc_compare_op0, - sparc_compare_op1); - else if (! TARGET_ARCH64) - FAIL; - else - pat = gen_snesi_special_extend (operands[0], sparc_compare_op0, - sparc_compare_op1); - emit_insn (pat); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == DImode) - { - rtx pat; - - if (! TARGET_ARCH64) - FAIL; - else if (GET_MODE (operands[0]) == SImode) - pat = gen_snedi_special_trunc (operands[0], sparc_compare_op0, - sparc_compare_op1); - else - pat = gen_snedi_special (operands[0], sparc_compare_op0, - sparc_compare_op1); - emit_insn (pat); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE); - gcc_assert (code == NE); - emit_insn (gen_sne (operands[0])); - DONE; - } - else if (TARGET_V9) - { - if (gen_v9_scc (NE, operands)) - DONE; - /* fall through */ - } - FAIL; -}) - -(define_expand "sgt" - [(set (match_operand:SI 0 "int_register_operand" "") - (gt:SI (match_dup 1) (const_int 0)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT); - gcc_assert (code == NE); - emit_insn (gen_sne (operands[0])); - DONE; - } - else if (TARGET_V9) - { - if (gen_v9_scc (GT, operands)) - DONE; - /* fall through */ - } - FAIL; -}) - -(define_expand "slt" - [(set (match_operand:SI 0 "int_register_operand" "") - (lt:SI (match_dup 1) (const_int 0)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT); - gcc_assert (code == NE); - emit_insn (gen_sne (operands[0])); - DONE; - } - else if (TARGET_V9) - { - if (gen_v9_scc (LT, operands)) - DONE; - /* fall through */ - } - FAIL; -}) - -(define_expand "sge" - [(set (match_operand:SI 0 "int_register_operand" "") - (ge:SI (match_dup 1) (const_int 0)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE); - gcc_assert (code == NE); - emit_insn (gen_sne (operands[0])); - DONE; - } - else if (TARGET_V9) - { - if (gen_v9_scc (GE, operands)) - DONE; - /* fall through */ - } - FAIL; -}) - -(define_expand "sle" - [(set (match_operand:SI 0 "int_register_operand" "") - (le:SI (match_dup 1) (const_int 0)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE); - gcc_assert (code == NE); - emit_insn (gen_sne (operands[0])); - DONE; - } - else if (TARGET_V9) - { - if (gen_v9_scc (LE, operands)) - DONE; - /* fall through */ - } - FAIL; -}) - -(define_expand "sgtu" - [(set (match_operand:SI 0 "int_register_operand" "") - (gtu:SI (match_dup 1) (const_int 0)))] - "" -{ - if (! TARGET_V9) - { - rtx tem, pat; - - /* We can do ltu easily, so if both operands are registers, swap them and - do a LTU. */ - if ((GET_CODE (sparc_compare_op0) == REG - || GET_CODE (sparc_compare_op0) == SUBREG) - && (GET_CODE (sparc_compare_op1) == REG - || GET_CODE (sparc_compare_op1) == SUBREG)) - { - tem = sparc_compare_op0; - sparc_compare_op0 = sparc_compare_op1; - sparc_compare_op1 = tem; - pat = gen_sltu (operands[0]); - if (pat == NULL_RTX) - FAIL; - emit_insn (pat); - DONE; - } - } - else - { - if (gen_v9_scc (GTU, operands)) - DONE; - } - FAIL; -}) - -(define_expand "sltu" - [(set (match_operand:SI 0 "int_register_operand" "") - (ltu:SI (match_dup 1) (const_int 0)))] - "" -{ - if (TARGET_V9) - { - if (gen_v9_scc (LTU, operands)) - DONE; - } - operands[1] = gen_compare_reg (LTU); -}) - -(define_expand "sgeu" - [(set (match_operand:SI 0 "int_register_operand" "") - (geu:SI (match_dup 1) (const_int 0)))] - "" -{ - if (TARGET_V9) - { - if (gen_v9_scc (GEU, operands)) - DONE; - } - operands[1] = gen_compare_reg (GEU); -}) - -(define_expand "sleu" - [(set (match_operand:SI 0 "int_register_operand" "") - (leu:SI (match_dup 1) (const_int 0)))] - "" -{ - if (! TARGET_V9) - { - rtx tem, pat; - - /* We can do geu easily, so if both operands are registers, swap them and - do a GEU. */ - if ((GET_CODE (sparc_compare_op0) == REG - || GET_CODE (sparc_compare_op0) == SUBREG) - && (GET_CODE (sparc_compare_op1) == REG - || GET_CODE (sparc_compare_op1) == SUBREG)) - { - tem = sparc_compare_op0; - sparc_compare_op0 = sparc_compare_op1; - sparc_compare_op1 = tem; - pat = gen_sgeu (operands[0]); - if (pat == NULL_RTX) - FAIL; - emit_insn (pat); - DONE; - } - } - else - { - if (gen_v9_scc (LEU, operands)) - DONE; - } - FAIL; -}) ;; Now the DEFINE_INSNs for the scc cases. @@ -1275,344 +916,51 @@ ;; These control RTL generation for conditional jump insns -;; The quad-word fp compare library routines all return nonzero to indicate -;; true, which is different from the equivalent libgcc routines, so we must -;; handle them specially here. - -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode) - { - emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (EQ); -}) - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode) - { - emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (NE); -}) - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode) - { - emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (GT); -}) - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = gen_compare_reg (GTU); -}) - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode) - { - emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (LT); -}) - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = gen_compare_reg (LTU); -}) - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode) - { - emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (GE); -}) - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = gen_compare_reg (GEU); -}) - -(define_expand "ble" +(define_expand "cbranchcc4" [(set (pc) - (if_then_else (le (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand 1 "compare_operand" "") + (match_operand 2 "const_zero_operand" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] "" -{ - if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode) - { - emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (LE); -}) - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = gen_compare_reg (LEU); -}) - -(define_expand "bunordered" - [(set (pc) - (if_then_else (unordered (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNORDERED); - gcc_assert (code == EQ); - emit_jump_insn (gen_beq (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (UNORDERED); -}) - -(define_expand "bordered" - [(set (pc) - (if_then_else (ordered (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (ORDERED); -}) - -(define_expand "bungt" - [(set (pc) - (if_then_else (ungt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT); - gcc_assert (code == GT); - emit_jump_insn (gen_bgt (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (UNGT); -}) + "") -(define_expand "bunlt" - [(set (pc) - (if_then_else (unlt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] +(define_expand "cbranchsi4" + [(use (match_operator 0 "comparison_operator" + [(match_operand:SI 1 "compare_operand" "") + (match_operand:SI 2 "arith_operand" "")])) + (use (match_operand 3 ""))] "" { - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (UNLT); + if (GET_CODE (operands[1]) == ZERO_EXTRACT && operands[2] != const0_rtx) + operands[1] = force_reg (SImode, operands[1]); + emit_conditional_branch_insn (operands); + DONE; }) -(define_expand "buneq" - [(set (pc) - (if_then_else (uneq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" +(define_expand "cbranchdi4" + [(use (match_operator 0 "comparison_operator" + [(match_operand:DI 1 "compare_operand" "") + (match_operand:DI 2 "arith_operand" "")])) + (use (match_operand 3 ""))] + "TARGET_ARCH64" { - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ); - gcc_assert (code == EQ); - emit_jump_insn (gen_beq (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (UNEQ); + if (GET_CODE (operands[1]) == ZERO_EXTRACT && operands[2] != const0_rtx) + operands[1] = force_reg (DImode, operands[1]); + emit_conditional_branch_insn (operands); + DONE; }) -(define_expand "bunge" - [(set (pc) - (if_then_else (unge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (UNGE); -}) +(define_expand "cbranch4" + [(use (match_operator 0 "comparison_operator" + [(match_operand:F 1 "register_operand" "") + (match_operand:F 2 "register_operand" "")])) + (use (match_operand 3 ""))] + "TARGET_FPU" + { emit_conditional_branch_insn (operands); DONE; }) -(define_expand "bunle" - [(set (pc) - (if_then_else (unle (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (UNLE); -}) -(define_expand "bltgt" - [(set (pc) - (if_then_else (ltgt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LTGT); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (LTGT); -}) - ;; Now match both normal and inverted jump. ;; XXX fpcmp nop braindamage @@ -1755,8 +1103,6 @@ (set_attr "branch_type" "reg")]) -(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) - ;; Load in operand 0 the (absolute) address of operand 1, which is a symbolic ;; value subject to a PC-relative relocation. Operand 2 is a helper function ;; that adds the PC value at the call point to operand 0. @@ -2393,9 +1739,6 @@ ;; Floating point and vector move instructions -;; We don't define V1SI because SI should work just fine. -(define_mode_iterator V32 [SF V2HI V4QI]) - ;; Yes, you guessed it right, the former movsf expander. (define_expand "mov" [(set (match_operand:V32 0 "nonimmediate_operand" "") @@ -2530,8 +1873,6 @@ [(set (match_dup 0) (high:SF (match_dup 1))) (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))]) -(define_mode_iterator V64 [DF V2SI V4HI V8QI]) - ;; Yes, you again guessed it right, the former movdf expander. (define_expand "mov" [(set (match_operand:V64 0 "nonimmediate_operand" "") @@ -3073,8 +2414,6 @@ ;; 3 contains the constant if one is present, but we handle either for ;; generality (sparc.c puts a constant in operand 2). -(define_mode_iterator I [QI HI SI DI]) - (define_expand "movcc" [(set (match_operand:I 0 "register_operand" "") (if_then_else:I (match_operand 1 "comparison_operator" "") @@ -3083,21 +2422,27 @@ "TARGET_V9 && !(mode == DImode && TARGET_ARCH32)" { enum rtx_code code = GET_CODE (operands[1]); + rtx cc_reg; - if (GET_MODE (sparc_compare_op0) == DImode + if (GET_MODE (XEXP (operands[1], 0)) == DImode && ! TARGET_ARCH64) FAIL; - if (sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode + if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD) + operands[1] + = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1), + GET_CODE (operands[1])); + + if (XEXP (operands[1], 1) == const0_rtx + && GET_CODE (XEXP (operands[1], 0)) == REG + && GET_MODE (XEXP (operands[1], 0)) == DImode && v9_regcmp_p (code)) - operands[1] = gen_rtx_fmt_ee (code, DImode, sparc_compare_op0, const0_rtx); + cc_reg = XEXP (operands[1], 0); else - operands[1] = gen_compare_operator (code); -}) + cc_reg = gen_compare_reg (operands[1]); -(define_mode_iterator F [SF DF TF]) + operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); +}) (define_expand "movcc" [(set (match_operand:F 0 "register_operand" "") @@ -3107,18 +2452,26 @@ "TARGET_V9 && TARGET_FPU" { enum rtx_code code = GET_CODE (operands[1]); + rtx cc_reg; - if (GET_MODE (sparc_compare_op0) == DImode + if (GET_MODE (XEXP (operands[1], 0)) == DImode && ! TARGET_ARCH64) FAIL; - if (sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode + if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD) + operands[1] + = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1), + GET_CODE (operands[1])); + + if (XEXP (operands[1], 1) == const0_rtx + && GET_CODE (XEXP (operands[1], 0)) == REG + && GET_MODE (XEXP (operands[1], 0)) == DImode && v9_regcmp_p (code)) - operands[1] = gen_rtx_fmt_ee (code, DImode, sparc_compare_op0, const0_rtx); + cc_reg = XEXP (operands[1], 0); else - operands[1] = gen_compare_operator (code); + cc_reg = gen_compare_reg (operands[1]); + + operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); }) ;; Conditional move define_insns @@ -5133,9 +4486,6 @@ ;; We define DImode `and' so with DImode `not' we can get ;; DImode `andn'. Other combinations are possible. -(define_mode_iterator V64I [DI V2SI V4HI V8QI]) -(define_mode_iterator V32I [SI V2HI V4QI]) - (define_expand "and3" [(set (match_operand:V64I 0 "register_operand" "") (and:V64I (match_operand:V64I 1 "arith_double_operand" "") @@ -7434,14 +6784,28 @@ "ta\t5" [(set_attr "type" "trap")]) -(define_expand "conditional_trap" - [(trap_if (match_operator 0 "noov_compare_operator" [(match_dup 2) (match_dup 3)]) - (match_operand:SI 1 "arith_operand" ""))] +(define_expand "ctrapsi4" + [(trap_if (match_operator 0 "noov_compare_operator" + [(match_operand:SI 1 "compare_operand" "") + (match_operand:SI 2 "arith_operand" "")]) + (match_operand 3 ""))] "" - "operands[2] = gen_compare_reg (GET_CODE (operands[0])); - if (GET_MODE (operands[2]) != CCmode && GET_MODE (operands[2]) != CCXmode) + "operands[1] = gen_compare_reg (operands[0]); + if (GET_MODE (operands[1]) != CCmode && GET_MODE (operands[1]) != CCXmode) FAIL; - operands[3] = const0_rtx;") + operands[2] = const0_rtx;") + +(define_expand "ctrapdi4" + [(trap_if (match_operator 0 "noov_compare_operator" + [(match_operand:DI 1 "compare_operand" "") + (match_operand:DI 2 "arith_operand" "")]) + (match_operand 3 ""))] + "TARGET_ARCH64" + "operands[1] = gen_compare_reg (operands[0]); + if (GET_MODE (operands[1]) != CCmode && GET_MODE (operands[1]) != CCXmode) + FAIL; + operands[2] = const0_rtx;") + (define_insn "" [(trap_if (match_operator 0 "noov_compare_operator" [(reg:CC 100) (const_int 0)]) @@ -8071,6 +7435,7 @@ (match_operand 2 "" "")] "" { + rtx result, test; #ifdef TARGET_THREAD_SSP_OFFSET rtx tlsreg = gen_rtx_REG (Pmode, 7); rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET)); @@ -8078,18 +7443,18 @@ #endif if (TARGET_ARCH64) { - rtx temp = gen_reg_rtx (Pmode); - emit_insn (gen_stack_protect_testdi (temp, operands[0], operands[1])); - sparc_compare_op0 = temp; - sparc_compare_op1 = const0_rtx; + result = gen_reg_rtx (Pmode); + emit_insn (gen_stack_protect_testdi (result, operands[0], operands[1])); + test = gen_rtx_EQ (VOIDmode, result, const0_rtx); + emit_jump_insn (gen_cbranchdi4 (test, result, const0_rtx, operands[2])); } else { emit_insn (gen_stack_protect_testsi (operands[0], operands[1])); - sparc_compare_op0 = gen_rtx_REG (CCmode, SPARC_ICC_REG); - sparc_compare_op1 = const0_rtx; + result = gen_rtx_REG (CCmode, SPARC_ICC_REG); + test = gen_rtx_EQ (VOIDmode, result, const0_rtx); + emit_jump_insn (gen_cbranchcc4 (test, result, const0_rtx, operands[2])); } - emit_jump_insn (gen_beq (operands[2])); DONE; }) diff --git a/gcc/config/spu/spu-protos.h b/gcc/config/spu/spu-protos.h index 06e02ba0b48..3e2600b996b 100644 --- a/gcc/config/spu/spu-protos.h +++ b/gcc/config/spu/spu-protos.h @@ -28,8 +28,7 @@ extern int valid_subreg (rtx op); extern void spu_expand_extv (rtx * ops, int unsignedp); extern void spu_expand_insv (rtx * ops); extern int spu_expand_block_move (rtx * ops); -extern void spu_emit_branch_or_set (int is_set, enum rtx_code code, - rtx * operands); +extern void spu_emit_branch_or_set (int is_set, rtx cmp, rtx * operands); extern int spu_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx); extern HOST_WIDE_INT const_double_to_hwint (rtx x); extern rtx hwint_to_const_double (enum machine_mode mode, HOST_WIDE_INT v); diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c index bb73622f9d5..f73bb217605 100644 --- a/gcc/config/spu/spu.c +++ b/gcc/config/spu/spu.c @@ -212,7 +212,6 @@ static void asm_file_start (void); static unsigned int spu_section_type_flags (tree, const char *, int); extern const char *reg_names[]; -rtx spu_compare_op0, spu_compare_op1; /* Which instruction set architecture to use. */ int spu_arch; @@ -844,42 +843,44 @@ int spu_comp_icode[12][3] = { WORD_MODE, we can generate better code in most cases if we do it ourselves. */ void -spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[]) +spu_emit_branch_or_set (int is_set, rtx cmp, rtx operands[]) { int reverse_compare = 0; int reverse_test = 0; rtx compare_result, eq_result; rtx comp_rtx, eq_rtx; - rtx target = operands[0]; enum machine_mode comp_mode; enum machine_mode op_mode; enum spu_comp_code scode, eq_code; enum insn_code ior_code; + enum rtx_code code = GET_CODE (cmp); + rtx op0 = XEXP (cmp, 0); + rtx op1 = XEXP (cmp, 1); int index; int eq_test = 0; - /* When spu_compare_op1 is a CONST_INT change (X >= C) to (X > C-1), + /* When op1 is a CONST_INT change (X >= C) to (X > C-1), and so on, to keep the constant in operand 1. */ - if (GET_CODE (spu_compare_op1) == CONST_INT) + if (GET_CODE (op1) == CONST_INT) { - HOST_WIDE_INT val = INTVAL (spu_compare_op1) - 1; - if (trunc_int_for_mode (val, GET_MODE (spu_compare_op0)) == val) + HOST_WIDE_INT val = INTVAL (op1) - 1; + if (trunc_int_for_mode (val, GET_MODE (op0)) == val) switch (code) { case GE: - spu_compare_op1 = GEN_INT (val); + op1 = GEN_INT (val); code = GT; break; case LT: - spu_compare_op1 = GEN_INT (val); + op1 = GEN_INT (val); code = LE; break; case GEU: - spu_compare_op1 = GEN_INT (val); + op1 = GEN_INT (val); code = GTU; break; case LTU: - spu_compare_op1 = GEN_INT (val); + op1 = GEN_INT (val); code = LEU; break; default: @@ -888,7 +889,7 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[]) } comp_mode = SImode; - op_mode = GET_MODE (spu_compare_op0); + op_mode = GET_MODE (op0); switch (code) { @@ -1012,18 +1013,18 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[]) abort (); } - if (GET_MODE (spu_compare_op1) == DFmode + if (GET_MODE (op1) == DFmode && (scode != SPU_GT && scode != SPU_EQ)) abort (); - if (is_set == 0 && spu_compare_op1 == const0_rtx - && (GET_MODE (spu_compare_op0) == SImode - || GET_MODE (spu_compare_op0) == HImode) && scode == SPU_EQ) + if (is_set == 0 && op1 == const0_rtx + && (GET_MODE (op0) == SImode + || GET_MODE (op0) == HImode) && scode == SPU_EQ) { /* Don't need to set a register with the result when we are comparing against zero and branching. */ reverse_test = !reverse_test; - compare_result = spu_compare_op0; + compare_result = op0; } else { @@ -1031,23 +1032,22 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[]) if (reverse_compare) { - rtx t = spu_compare_op1; - spu_compare_op1 = spu_compare_op0; - spu_compare_op0 = t; + rtx t = op1; + op1 = op0; + op0 = t; } if (spu_comp_icode[index][scode] == 0) abort (); if (!(*insn_data[spu_comp_icode[index][scode]].operand[1].predicate) - (spu_compare_op0, op_mode)) - spu_compare_op0 = force_reg (op_mode, spu_compare_op0); + (op0, op_mode)) + op0 = force_reg (op_mode, op0); if (!(*insn_data[spu_comp_icode[index][scode]].operand[2].predicate) - (spu_compare_op1, op_mode)) - spu_compare_op1 = force_reg (op_mode, spu_compare_op1); + (op1, op_mode)) + op1 = force_reg (op_mode, op1); comp_rtx = GEN_FCN (spu_comp_icode[index][scode]) (compare_result, - spu_compare_op0, - spu_compare_op1); + op0, op1); if (comp_rtx == 0) abort (); emit_insn (comp_rtx); @@ -1056,8 +1056,7 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[]) { eq_result = gen_reg_rtx (comp_mode); eq_rtx = GEN_FCN (spu_comp_icode[index][eq_code]) (eq_result, - spu_compare_op0, - spu_compare_op1); + op0, op1); if (eq_rtx == 0) abort (); emit_insn (eq_rtx); @@ -1088,13 +1087,14 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[]) else bcomp = gen_rtx_NE (comp_mode, compare_result, const0_rtx); - loc_ref = gen_rtx_LABEL_REF (VOIDmode, target); + loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp, loc_ref, pc_rtx))); } else if (is_set == 2) { + rtx target = operands[0]; int compare_size = GET_MODE_BITSIZE (comp_mode); int target_size = GET_MODE_BITSIZE (GET_MODE (target)); enum machine_mode mode = mode_for_size (target_size, MODE_INT, 0); @@ -1129,6 +1129,7 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[]) } else { + rtx target = operands[0]; if (reverse_test) emit_insn (gen_rtx_SET (VOIDmode, compare_result, gen_rtx_NOT (comp_mode, compare_result))); diff --git a/gcc/config/spu/spu.h b/gcc/config/spu/spu.h index ed92715cd01..ddd464ac579 100644 --- a/gcc/config/spu/spu.h +++ b/gcc/config/spu/spu.h @@ -606,11 +606,6 @@ targetm.resolve_overloaded_builtin = spu_resolve_overloaded_builtin; \ } \ } while (0) -/* These are set by the cmp patterns and used while expanding - conditional branches. */ -extern GTY(()) rtx spu_compare_op0; -extern GTY(()) rtx spu_compare_op1; - /* Builtins. */ diff --git a/gcc/config/spu/spu.md b/gcc/config/spu/spu.md index bd6936fd9e3..db42db16111 100644 --- a/gcc/config/spu/spu.md +++ b/gcc/config/spu/spu.md @@ -3657,57 +3657,6 @@ selb\t%0,%4,%0,%3" [(set_attr "type" "br")]) -;; Compare insns are next. Note that the spu has two types of compares, -;; signed & unsigned, and one type of branch. -;; -;; Start with the DEFINE_EXPANDs to generate the rtl for compares, scc -;; insns, and branches. We store the operands of compares until we see -;; how it is used. - -(define_expand "cmp" - [(set (cc0) - (compare (match_operand:VQHSI 0 "spu_reg_operand" "") - (match_operand:VQHSI 1 "spu_nonmem_operand" "")))] - "" - { - spu_compare_op0 = operands[0]; - spu_compare_op1 = operands[1]; - DONE; - }) - -(define_expand "cmp" - [(set (cc0) - (compare (match_operand:DTI 0 "spu_reg_operand" "") - (match_operand:DTI 1 "spu_reg_operand" "")))] - "" - { - spu_compare_op0 = operands[0]; - spu_compare_op1 = operands[1]; - DONE; - }) - -(define_expand "cmp" - [(set (cc0) - (compare (match_operand:VSF 0 "spu_reg_operand" "") - (match_operand:VSF 1 "spu_reg_operand" "")))] - "" - { - spu_compare_op0 = operands[0]; - spu_compare_op1 = operands[1]; - DONE; - }) - -(define_expand "cmpdf" - [(set (cc0) - (compare (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "register_operand" "")))] - "" - "{ - spu_compare_op0 = operands[0]; - spu_compare_op1 = operands[1]; - DONE; -}") - ;; vector conditional compare patterns (define_expand "vcond" [(set (match_operand:VCMP 0 "spu_reg_operand" "=r") @@ -3746,108 +3695,72 @@ selb\t%0,%4,%0,%3" ;; branch on condition -(define_expand "beq" - [(use (match_operand 0 "" ""))] - "" - { spu_emit_branch_or_set (0, EQ, operands); DONE; }) - -(define_expand "bne" - [(use (match_operand 0 "" ""))] - "" - { spu_emit_branch_or_set (0, NE, operands); DONE; }) - -(define_expand "bge" - [(use (match_operand 0 "" ""))] - "" - { spu_emit_branch_or_set (0, GE, operands); DONE; }) - -(define_expand "bgt" - [(use (match_operand 0 "" ""))] - "" - { spu_emit_branch_or_set (0, GT, operands); DONE; }) - -(define_expand "ble" - [(use (match_operand 0 "" ""))] - "" - { spu_emit_branch_or_set (0, LE, operands); DONE; }) - -(define_expand "blt" - [(use (match_operand 0 "" ""))] +(define_expand "cbranch4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:VQHSI 1 "spu_reg_operand" "") + (match_operand:VQHSI 2 "spu_nonmem_operand" "")])) + (use (match_operand 3 ""))] "" - { spu_emit_branch_or_set (0, LT, operands); DONE; }) + { spu_emit_branch_or_set (0, operands[0], operands); DONE; }) -(define_expand "bgeu" - [(use (match_operand 0 "" ""))] +(define_expand "cbranch4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:DTI 1 "spu_reg_operand" "") + (match_operand:DTI 2 "spu_reg_operand" "")])) + (use (match_operand 3 ""))] "" - { spu_emit_branch_or_set (0, GEU, operands); DONE; }) + { spu_emit_branch_or_set (0, operands[0], operands); DONE; }) -(define_expand "bgtu" - [(use (match_operand 0 "" ""))] +(define_expand "cbranch4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:VSF 1 "spu_reg_operand" "") + (match_operand:VSF 2 "spu_reg_operand" "")])) + (use (match_operand 3 ""))] "" - { spu_emit_branch_or_set (0, GTU, operands); DONE; }) + { spu_emit_branch_or_set (0, operands[0], operands); DONE; }) -(define_expand "bleu" - [(use (match_operand 0 "" ""))] +(define_expand "cbranchdf4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:DF 1 "spu_reg_operand" "") + (match_operand:DF 2 "spu_reg_operand" "")])) + (use (match_operand 3 ""))] "" - { spu_emit_branch_or_set (0, LEU, operands); DONE; }) - -(define_expand "bltu" - [(use (match_operand 0 "" ""))] - "" - { spu_emit_branch_or_set (0, LTU, operands); DONE; }) + { spu_emit_branch_or_set (0, operands[0], operands); DONE; }) ;; set on condition -(define_expand "seq" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] - "" - { spu_emit_branch_or_set (1, EQ, operands); DONE; }) - -(define_expand "sne" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] - "" - { spu_emit_branch_or_set (1, NE, operands); DONE; }) - -(define_expand "sgt" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] - "" - { spu_emit_branch_or_set (1, GT, operands); DONE; }) - -(define_expand "slt" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] - "" - { spu_emit_branch_or_set (1, LT, operands); DONE; }) - -(define_expand "sge" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] - "" - { spu_emit_branch_or_set (1, GE, operands); DONE; }) - -(define_expand "sle" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] - "" - { spu_emit_branch_or_set (1, LE, operands); DONE; }) - -(define_expand "sgtu" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] +(define_expand "cstore4" + [(use (match_operator 1 "ordered_comparison_operator" + [(match_operand:VQHSI 2 "spu_reg_operand" "") + (match_operand:VQHSI 3 "spu_nonmem_operand" "")])) + (clobber (match_operand:SI 0 "spu_reg_operand"))] "" - { spu_emit_branch_or_set (1, GTU, operands); DONE; }) + { spu_emit_branch_or_set (1, operands[1], operands); DONE; }) -(define_expand "sltu" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] +(define_expand "cstore4" + [(use (match_operator 1 "ordered_comparison_operator" + [(match_operand:DTI 2 "spu_reg_operand" "") + (match_operand:DTI 3 "spu_reg_operand" "")])) + (clobber (match_operand:SI 0 "spu_reg_operand"))] "" - { spu_emit_branch_or_set (1, LTU, operands); DONE; }) + { spu_emit_branch_or_set (1, operands[1], operands); DONE; }) -(define_expand "sgeu" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] +(define_expand "cstore4" + [(use (match_operator 1 "ordered_comparison_operator" + [(match_operand:VSF 2 "spu_reg_operand" "") + (match_operand:VSF 3 "spu_reg_operand" "")])) + (clobber (match_operand:SI 0 "spu_reg_operand"))] "" - { spu_emit_branch_or_set (1, GEU, operands); DONE; }) + { spu_emit_branch_or_set (1, operands[1], operands); DONE; }) -(define_expand "sleu" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] +(define_expand "cstoredf4" + [(use (match_operator 1 "ordered_comparison_operator" + [(match_operand:DF 2 "spu_reg_operand" "") + (match_operand:DF 3 "spu_reg_operand" "")])) + (clobber (match_operand:SI 0 "spu_reg_operand"))] "" - { spu_emit_branch_or_set (1, LEU, operands); DONE; }) + { spu_emit_branch_or_set (1, operands[1], operands); DONE; }) ;; conditional move @@ -3863,12 +3776,12 @@ selb\t%0,%4,%0,%3" (define_expand "movcc" [(set (match_operand:ALL 0 "spu_reg_operand" "") - (if_then_else:ALL (match_operand 1 "comparison_operator" "") + (if_then_else:ALL (match_operand 1 "ordered_comparison_operator" "") (match_operand:ALL 2 "spu_reg_operand" "") (match_operand:ALL 3 "spu_reg_operand" "")))] "" { - spu_emit_branch_or_set(2, GET_CODE(operands[1]), operands); + spu_emit_branch_or_set(2, operands[1], operands); DONE; }) diff --git a/gcc/config/stormy16/stormy16-protos.h b/gcc/config/stormy16/stormy16-protos.h index 58cff8a26e9..bde411b4e3a 100644 --- a/gcc/config/stormy16/stormy16-protos.h +++ b/gcc/config/stormy16/stormy16-protos.h @@ -48,7 +48,7 @@ extern rtx xstormy16_function_value (const_tree, const_tree); #endif #ifdef RTX_CODE -extern void xstormy16_emit_cbranch (enum rtx_code, rtx); +extern void xstormy16_emit_cbranch (enum rtx_code, rtx, rtx, rtx); extern char *xstormy16_output_cbranch_hi (rtx, const char *, int, rtx); extern char *xstormy16_output_cbranch_si (rtx, const char *, int, rtx); extern int xstormy16_mode_dependent_address_p (rtx); diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c index eefc58f0847..4d04cae95d9 100644 --- a/gcc/config/stormy16/stormy16.c +++ b/gcc/config/stormy16/stormy16.c @@ -61,11 +61,6 @@ static bool xstormy16_rtx_costs (rtx, int, int, int *, bool); static int xstormy16_address_cost (rtx, bool); static bool xstormy16_return_in_memory (const_tree, const_tree); -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ -struct rtx_def * xstormy16_compare_op0; -struct rtx_def * xstormy16_compare_op1; - static GTY(()) section *bss100_section; /* Compute a (partial) cost for rtx X. Return true if the complete @@ -139,10 +134,8 @@ xstormy16_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED) /* Emit a branch of kind CODE to location LOC. */ void -xstormy16_emit_cbranch (enum rtx_code code, rtx loc) +xstormy16_emit_cbranch (enum rtx_code code, rtx op0, rtx op1, rtx loc) { - rtx op0 = xstormy16_compare_op0; - rtx op1 = xstormy16_compare_op1; rtx condition_rtx, loc_ref, branch, cy_clobber; rtvec vec; enum machine_mode mode; @@ -159,10 +152,10 @@ xstormy16_emit_cbranch (enum rtx_code code, rtx loc) if (gt_p) lab = gen_label_rtx (); - xstormy16_emit_cbranch (unsigned_p ? LTU : LT, gt_p ? lab : loc); + xstormy16_emit_cbranch (unsigned_p ? LTU : LT, op0, op1, gt_p ? lab : loc); /* This should be generated as a comparison against the temporary created by the previous insn, but reload can't handle that. */ - xstormy16_emit_cbranch (gt_p ? NE : EQ, loc); + xstormy16_emit_cbranch (gt_p ? NE : EQ, op0, op1, loc); if (gt_p) emit_label (lab); return; @@ -171,6 +164,7 @@ xstormy16_emit_cbranch (enum rtx_code code, rtx loc) && (code == NE || code == EQ) && op1 != const0_rtx) { + rtx op0_word, op1_word; rtx lab = NULL_RTX; int num_words = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; int i; @@ -180,17 +174,17 @@ xstormy16_emit_cbranch (enum rtx_code code, rtx loc) for (i = 0; i < num_words - 1; i++) { - xstormy16_compare_op0 = simplify_gen_subreg (word_mode, op0, mode, - i * UNITS_PER_WORD); - xstormy16_compare_op1 = simplify_gen_subreg (word_mode, op1, mode, - i * UNITS_PER_WORD); - xstormy16_emit_cbranch (NE, code == EQ ? lab : loc); + op0_word = simplify_gen_subreg (word_mode, op0, mode, + i * UNITS_PER_WORD); + op1_word = simplify_gen_subreg (word_mode, op1, mode, + i * UNITS_PER_WORD); + xstormy16_emit_cbranch (NE, op0_word, op1_word, code == EQ ? lab : loc); } - xstormy16_compare_op0 = simplify_gen_subreg (word_mode, op0, mode, - i * UNITS_PER_WORD); - xstormy16_compare_op1 = simplify_gen_subreg (word_mode, op1, mode, - i * UNITS_PER_WORD); - xstormy16_emit_cbranch (code, loc); + op0_word = simplify_gen_subreg (word_mode, op0, mode, + i * UNITS_PER_WORD); + op1_word = simplify_gen_subreg (word_mode, op1, mode, + i * UNITS_PER_WORD); + xstormy16_emit_cbranch (code, op0_word, op1_word, loc); if (code == EQ) emit_label (lab); diff --git a/gcc/config/stormy16/stormy16.h b/gcc/config/stormy16/stormy16.h index 675b94d9949..d626edf6e50 100644 --- a/gcc/config/stormy16/stormy16.h +++ b/gcc/config/stormy16/stormy16.h @@ -801,11 +801,4 @@ do { \ is responsible for updating the value of MORE (typically by (MORE)--). */ /* #define MD_SCHED_VARIABLE_ISSUE (FILE, VERBOSE, INSN, MORE) */ - -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. Note that we can't use "rtx" here - since it hasn't been defined! */ - -extern struct rtx_def *xstormy16_compare_op0, *xstormy16_compare_op1; - /* End of xstormy16.h */ diff --git a/gcc/config/stormy16/stormy16.md b/gcc/config/stormy16/stormy16.md index 43e454804a1..9c86d43e627 100644 --- a/gcc/config/stormy16/stormy16.md +++ b/gcc/config/stormy16/stormy16.md @@ -736,40 +736,7 @@ operands[0], operands[2], operands[3]);" [(set_attr "length" "6,10") (set_attr "psw_operand" "clobber,clobber")]) - -;; :::::::::::::::::::: -;; :: -;; :: Comparisons -;; :: -;; :::::::::::::::::::: - -;; Note, we store the operands in the comparison insns, and use them later -;; when generating the branch or scc operation. - -;; First the routines called by the machine independent part of the compiler -(define_expand "cmphi" - [(set (cc0) - (compare (match_operand:HI 0 "register_operand" "") - (match_operand:HI 1 "nonmemory_operand" "")))] - "" - { - xstormy16_compare_op0 = operands[0]; - xstormy16_compare_op1 = operands[1]; - DONE; - }) -; There are no real SImode comparisons, but some can be emulated -; by performing a SImode subtract and looking at the condition flags. -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "nonmemory_operand" "")))] - "" - { - xstormy16_compare_op0 = operands[0]; - xstormy16_compare_op1 = operands[1]; - DONE; - }) ;; :::::::::::::::::::: ;; :: @@ -777,55 +744,35 @@ ;; :: ;; :::::::::::::::::::: -(define_expand "beq" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (EQ, operands[0]); DONE; }) - -(define_expand "bne" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (NE, operands[0]); DONE; }) - -(define_expand "bge" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (GE, operands[0]); DONE; }) - -(define_expand "bgt" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (GT, operands[0]); DONE; }) - -(define_expand "ble" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (LE, operands[0]); DONE; }) - -(define_expand "blt" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (LT, operands[0]); DONE; }) - -(define_expand "bgeu" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (GEU, operands[0]); DONE; }) - -(define_expand "bgtu" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (GTU, operands[0]); DONE; }) - -(define_expand "bleu" - [(use (match_operand 0 "" ""))] +(define_expand "cbranchhi4" + [(set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "nonmemory_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc))) + (clobber (reg:BI CARRY_REG))] "" - { xstormy16_emit_cbranch (LEU, operands[0]); DONE; }) + { + xstormy16_emit_cbranch (GET_CODE (operands[0]), operands[1], operands[2], + operands[3]); + DONE; +}) -(define_expand "bltu" - [(use (match_operand 0 "" ""))] +(define_expand "cbranchsi4" + [(set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc))) + (clobber (reg:BI CARRY_REG))] "" - { xstormy16_emit_cbranch (LTU, operands[0]); DONE; }) + { + xstormy16_emit_cbranch (GET_CODE (operands[0]), operands[1], operands[2], + operands[3]); + DONE; +}) (define_insn "cbranchhi" [(set (pc) diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c index a562202538b..f9e8a7dd8b0 100644 --- a/gcc/config/v850/v850.c +++ b/gcc/config/v850/v850.c @@ -464,6 +464,11 @@ v850_rtx_costs (rtx x, *total = 20; return true; + case ZERO_EXTRACT: + if (outer_code == COMPARE) + *total = 0; + return false; + default: return false; } diff --git a/gcc/config/v850/v850.md b/gcc/config/v850/v850.md index dad3cdd885b..69c8d881f89 100644 --- a/gcc/config/v850/v850.md +++ b/gcc/config/v850/v850.md @@ -227,9 +227,11 @@ ;; ---------------------------------------------------------------------- (define_insn "*v850_tst1" - [(set (cc0) (zero_extract:SI (match_operand:QI 0 "memory_operand" "m") - (const_int 1) - (match_operand:QI 1 "const_int_operand" "n")))] + [(set (cc0) + (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m") + (const_int 1) + (match_operand:QI 1 "const_int_operand" "n")) + (const_int 0)))] "" "tst1 %1,%0" [(set_attr "length" "4") @@ -237,37 +239,52 @@ ;; This replaces ld.b;sar;andi with tst1;setf nz. -;; ??? The zero_extract sets the Z bit to the opposite of what one would -;; expect. This perhaps should be wrapped in a (eq: X (const_int 0)). - (define_split [(set (match_operand:SI 0 "register_operand" "") - (zero_extract:SI (match_operand:QI 1 "memory_operand" "") - (const_int 1) - (match_operand 2 "const_int_operand" "")))] - "" - [(set (cc0) (zero_extract:SI (match_dup 1) - (const_int 1) - (match_dup 2))) + (compare (zero_extract:SI (match_operand:QI 1 "memory_operand" "") + (const_int 1) + (match_operand 2 "const_int_operand" "")) + (const_int 0)))] + "" + [(set (cc0) (compare (zero_extract:SI (match_dup 1) + (const_int 1) + (match_dup 2)) + (const_int 0))) (set (match_dup 0) (ne:SI (cc0) (const_int 0)))]) -(define_insn "tstsi" - [(set (cc0) (match_operand:SI 0 "register_operand" "r"))] - "" - "cmp %.,%0" - [(set_attr "length" "2") - (set_attr "cc" "set_znv")]) +(define_expand "cbranchsi4" + [(set (cc0) + (compare (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "reg_or_int5_operand" ""))) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "") + +(define_expand "cstoresi4" + [(set (cc0) + (compare (match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "reg_or_int5_operand" ""))) + (set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" [(cc0) + (const_int 0)]))] + "") -(define_insn "cmpsi" +(define_insn "*cmpsi" [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "r,r") - (match_operand:SI 1 "reg_or_int5_operand" "r,J")))] + (compare (match_operand:SI 0 "register_operand" "r,r,r") + (match_operand:SI 1 "reg_or_int5_operand" "r,I,J")))] "" "@ cmp %1,%0 + cmp %.,%0 cmp %1,%0" - [(set_attr "length" "2,2") - (set_attr "cc" "compare")]) + [(set_attr "length" "2,2,2") + (set_attr "cc" "compare,set_znv,compare")]) + ;; ---------------------------------------------------------------------- ;; ADD INSTRUCTIONS @@ -688,110 +705,25 @@ ;; Scc INSTRUCTIONS ;; ----------------------------------------------------------------- -(define_insn "sle" - [(set (match_operand:SI 0 "register_operand" "=r") - (le:SI (cc0) (const_int 0)))] - "" - "* -{ - if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) - return 0; - - return \"setf le,%0\"; -}" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "sleu" - [(set (match_operand:SI 0 "register_operand" "=r") - (leu:SI (cc0) (const_int 0)))] - "" - "setf nh,%0" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "sge" - [(set (match_operand:SI 0 "register_operand" "=r") - (ge:SI (cc0) (const_int 0)))] - "" - "* -{ - if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) - return 0; - - return \"setf ge,%0\"; -}" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "sgeu" +(define_insn "*setcc" [(set (match_operand:SI 0 "register_operand" "=r") - (geu:SI (cc0) (const_int 0)))] - "" - "setf nl,%0" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "slt" - [(set (match_operand:SI 0 "register_operand" "=r") - (lt:SI (cc0) (const_int 0)))] - "" - "* -{ - if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) - return 0; - - return \"setf lt,%0\"; -}" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "sltu" - [(set (match_operand:SI 0 "register_operand" "=r") - (ltu:SI (cc0) (const_int 0)))] - "" - "setf l,%0" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "sgt" - [(set (match_operand:SI 0 "register_operand" "=r") - (gt:SI (cc0) (const_int 0)))] + (match_operator:SI 1 "comparison_operator" + [(cc0) (const_int 0)]))] "" "* { - if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) + if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 + && (GET_CODE (operands[1]) == GT + || GET_CODE (operands[1]) == GE + || GET_CODE (operands[1]) == LE + || GET_CODE (operands[1]) == LT)) return 0; - return \"setf gt,%0\"; + return \"setf %c1,%0\"; }" [(set_attr "length" "4") (set_attr "cc" "none_0hit")]) -(define_insn "sgtu" - [(set (match_operand:SI 0 "register_operand" "=r") - (gtu:SI (cc0) (const_int 0)))] - "" - "setf h,%0" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "seq" - [(set (match_operand:SI 0 "register_operand" "=r") - (eq:SI (cc0) (const_int 0)))] - "" - "setf z,%0" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "sne" - [(set (match_operand:SI 0 "register_operand" "=r") - (ne:SI (cc0) (const_int 0)))] - "" - "setf nz,%0" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - ;; ---------------------------------------------------------------------- ;; CONDITIONAL MOVE INSTRUCTIONS ;; ---------------------------------------------------------------------- @@ -800,25 +732,15 @@ ;; hide the fact that this instruction uses cc0. We do so by including the ;; compare instruction inside it. -;; ??? This is very ugly. The right way to do this is to modify cmpsi so -;; that it doesn't emit RTL, and then modify the bcc/scc patterns so that -;; they emit RTL for the compare instruction. Unfortunately, this requires -;; lots of changes that will be hard to sanitize. So for now, cmpsi still -;; emits RTL, and I get the compare operands here from the previous insn. - (define_expand "movsicc" [(set (match_operand:SI 0 "register_operand" "=r") (if_then_else:SI - (match_operator 1 "comparison_operator" - [(match_dup 4) (match_dup 5)]) + (match_operand 1 "comparison_operator") (match_operand:SI 2 "reg_or_const_operand" "rJ") (match_operand:SI 3 "reg_or_const_operand" "rI")))] "TARGET_V850E" " { - rtx insn = get_last_insn_anywhere (); - rtx src; - if ( (GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT)) { @@ -845,28 +767,6 @@ if (GET_CODE (operands[3]) != REG) operands[3] = copy_to_mode_reg (SImode, operands[3]); } - gcc_assert (GET_CODE (insn) == INSN - && GET_CODE (PATTERN (insn)) == SET - && SET_DEST (PATTERN (insn)) == cc0_rtx); - - src = SET_SRC (PATTERN (insn)); - - switch (GET_CODE (src)) - { - case COMPARE: - operands[4] = XEXP (src, 0); - operands[5] = XEXP (src, 1); - break; - - case REG: - case SUBREG: - operands[4] = src; - operands[5] = const0_rtx; - break; - - default: - gcc_unreachable (); - } }") ;; ??? Clobbering the condition codes is overkill. @@ -1037,96 +937,6 @@ ;; Conditional jump instructions -(define_expand "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - (define_insn "*branch_normal" [(set (pc) (if_then_else (match_operator 1 "comparison_operator" @@ -1241,14 +1051,16 @@ { rtx reg = gen_reg_rtx (SImode); rtx tableaddress = gen_reg_rtx (SImode); + rtx test; rtx mem; /* Subtract the lower bound from the index. */ emit_insn (gen_subsi3 (reg, operands[0], operands[1])); - /* Compare the result against the number of table entries. */ - emit_insn (gen_cmpsi (reg, operands[2])); - /* Branch to the default label if out of range of the table. */ - emit_jump_insn (gen_bgtu (operands[4])); + + /* Compare the result against the number of table entries; + branch to the default label if out of range of the table. */ + test = gen_rtx_fmt_ee (GTU, VOIDmode, reg, operands[2]); + emit_jump_insn (gen_cbranchsi4 (test, reg, operands[2], operands[4])); /* Shift index for the table array access. */ emit_insn (gen_ashlsi3 (reg, reg, GEN_INT (TARGET_BIG_SWITCH ? 2 : 1))); diff --git a/gcc/config/vax/vax-protos.h b/gcc/config/vax/vax-protos.h index 9b43d4f86e9..c038b300d91 100644 --- a/gcc/config/vax/vax-protos.h +++ b/gcc/config/vax/vax-protos.h @@ -26,6 +26,7 @@ extern bool legitimate_address_p (enum machine_mode, rtx, bool); extern bool vax_mode_dependent_address_p (rtx); #ifdef RTX_CODE +extern const char *cond_name (rtx); extern bool adjacent_operands_p (rtx, rtx, enum machine_mode); extern const char *rev_cond_name (rtx); extern void print_operand_address (FILE *, rtx); @@ -35,7 +36,6 @@ extern void vax_expand_addsub_di_operands (rtx *, enum rtx_code); extern const char * vax_output_int_move (rtx, rtx *, enum machine_mode); extern const char * vax_output_int_add (rtx, rtx *, enum machine_mode); extern const char * vax_output_int_subtract (rtx, rtx *, enum machine_mode); -extern const char * vax_output_conditional_branch (enum rtx_code); extern const char * vax_output_movmemsi (rtx, rtx *); #endif /* RTX_CODE */ diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c index e91696947e6..cd66bb4e2d7 100644 --- a/gcc/config/vax/vax.c +++ b/gcc/config/vax/vax.c @@ -428,6 +428,8 @@ print_operand (FILE *file, rtx x, int code) fputc (ASM_DOUBLE_CHAR, file); else if (code == '|') fputs (REGISTER_PREFIX, file); + else if (code == 'c') + fputs (cond_name (x), file); else if (code == 'C') fputs (rev_cond_name (x), file); else if (code == 'D' && CONST_INT_P (x) && INTVAL (x) < 0) @@ -480,6 +482,37 @@ print_operand (FILE *file, rtx x, int code) } const char * +cond_name (rtx op) +{ + switch (GET_CODE (op)) + { + case NE: + return "neq"; + case EQ: + return "eql"; + case GE: + return "geq"; + case GT: + return "gtr"; + case LE: + return "leq"; + case LT: + return "lss"; + case GEU: + return "gequ"; + case GTU: + return "gtru"; + case LEU: + return "lequ"; + case LTU: + return "lssu"; + + default: + gcc_unreachable (); + } +} + +const char * rev_cond_name (rtx op) { switch (GET_CODE (op)) @@ -1516,27 +1549,6 @@ vax_output_int_subtract (rtx insn, rtx *operands, enum machine_mode mode) } } -/* Output a conditional branch. */ -const char * -vax_output_conditional_branch (enum rtx_code code) -{ - switch (code) - { - case EQ: return "jeql %l0"; - case NE: return "jneq %l0"; - case GT: return "jgtr %l0"; - case LT: return "jlss %l0"; - case GTU: return "jgtru %l0"; - case LTU: return "jlssu %l0"; - case GE: return "jgeq %l0"; - case LE: return "jleq %l0"; - case GEU: return "jgequ %l0"; - case LEU: return "jlequ %l0"; - default: - gcc_unreachable (); - } -} - /* True if X is an rtx for a constant that is a valid address. */ bool diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h index 997029e0f62..7fa2fbb870e 100644 --- a/gcc/config/vax/vax.h +++ b/gcc/config/vax/vax.h @@ -802,6 +802,7 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES }; VAX operand formatting codes: letter print + c direct branch condition C reverse branch condition D 64-bit immediate operand B the low 8 bits of the complement of a constant operand diff --git a/gcc/config/vax/vax.md b/gcc/config/vax/vax.md index da3ca48e90b..649f17e36ba 100644 --- a/gcc/config/vax/vax.md +++ b/gcc/config/vax/vax.md @@ -58,30 +58,16 @@ (include "constraints.md") (include "predicates.md") -;; We don't want to allow a constant operand for test insns because -;; (set (cc0) (const_int foo)) has no mode information. Such insns will -;; be folded while optimizing anyway. - -(define_insn "tst" - [(set (cc0) - (match_operand:VAXint 0 "nonimmediate_operand" "nrmT"))] - "" - "tst %0") - -(define_insn "tst" +(define_insn "*cmp" [(set (cc0) - (match_operand:VAXfp 0 "general_operand" "gF"))] + (compare (match_operand:VAXint 0 "nonimmediate_operand" "nrmT,nrmT") + (match_operand:VAXint 1 "general_operand" "I,nrmT")))] "" - "tst %0") - -(define_insn "cmp" - [(set (cc0) - (compare (match_operand:VAXint 0 "nonimmediate_operand" "nrmT") - (match_operand:VAXint 1 "general_operand" "nrmT")))] - "" - "cmp %0,%1") + "@ + tst %0 + cmp %0,%1") -(define_insn "cmp" +(define_insn "*cmp" [(set (cc0) (compare (match_operand:VAXfp 0 "general_operand" "gF,gF") (match_operand:VAXfp 1 "general_operand" "G,gF")))] @@ -92,8 +78,9 @@ (define_insn "*bit" [(set (cc0) - (and:VAXint (match_operand:VAXint 0 "general_operand" "nrmT") - (match_operand:VAXint 1 "general_operand" "nrmT")))] + (compare (and:VAXint (match_operand:VAXint 0 "general_operand" "nrmT") + (match_operand:VAXint 1 "general_operand" "nrmT")) + (const_int 0)))] "" "bit %0,%1") @@ -1078,21 +1065,45 @@ "jbr %l0") ;; Conditional jumps -(define_code_iterator any_cond [eq ne gt lt gtu ltu ge le geu leu]) -(define_insn "b" +(define_expand "cbranch4" + [(set (cc0) + (compare (match_operand:VAXint 1 "nonimmediate_operand" "") + (match_operand:VAXint 2 "general_operand" ""))) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "") + +(define_expand "cbranch4" + [(set (cc0) + (compare (match_operand:VAXfp 1 "general_operand" "") + (match_operand:VAXfp 2 "general_operand" ""))) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "") + +(define_insn "*branch" [(set (pc) - (if_then_else (any_cond (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) + (const_int 0)]) + (label_ref (match_operand 1 "" "")) (pc)))] "" - "* return vax_output_conditional_branch ();") + "j%c0 %l1") ;; Recognize reversed jumps. -(define_insn "" +(define_insn "*branch_reversed" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ordered_comparison_operator" [(cc0) (const_int 0)]) (pc) @@ -1452,6 +1463,8 @@ (match_operand 4 "" "")] "" { + rtx test; + /* i = index - minimum_bound; But only if the lower bound is not already zero. */ if (operands[1] != const0_rtx) @@ -1463,9 +1476,9 @@ operands[0] = index; } - /* if (i > (maximum_bound - minimum_bound + 1) goto default; */ - emit_insn (gen_cmpsi (operands[0], operands[2])); - emit_jump_insn (gen_bgtu (operands[4])); + /* if (i > (maximum_bound - minimum_bound + 1)) goto default; */ + test = gen_rtx_fmt_ee (GTU, VOIDmode, operands[0], operands[2]); + emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], operands[4])); /* casesi (i, 0, table); */ emit_jump_insn (gen_casesi1 (operands[0], operands[2], operands[3])); diff --git a/gcc/config/xtensa/predicates.md b/gcc/config/xtensa/predicates.md index 2cb2a7d1757..27f058de796 100644 --- a/gcc/config/xtensa/predicates.md +++ b/gcc/config/xtensa/predicates.md @@ -167,6 +167,9 @@ (define_predicate "boolean_operator" (match_code "eq,ne")) +(define_predicate "xtensa_cstoresi_operator" + (match_code "eq,ne,gt,ge,lt,le")) + (define_predicate "tls_symbol_operand" (and (match_code "symbol_ref") (match_test "SYMBOL_REF_TLS_MODEL (op) != 0"))) diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h index 5f8cd74fe36..76f10179c75 100644 --- a/gcc/config/xtensa/xtensa-protos.h +++ b/gcc/config/xtensa/xtensa-protos.h @@ -39,9 +39,9 @@ extern int smalloffset_mem_p (rtx); extern int constantpool_address_p (rtx); extern int constantpool_mem_p (rtx); extern void xtensa_extend_reg (rtx, rtx); -extern void xtensa_expand_conditional_branch (rtx *, enum rtx_code); +extern void xtensa_expand_conditional_branch (rtx *, enum machine_mode); extern int xtensa_expand_conditional_move (rtx *, int); -extern int xtensa_expand_scc (rtx *); +extern int xtensa_expand_scc (rtx *, enum machine_mode); extern int xtensa_expand_block_move (rtx *); extern void xtensa_split_operand_pair (rtx *, enum machine_mode); extern int xtensa_emit_move_sequence (rtx *, enum machine_mode); diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index 50467b4602c..35e399f54b4 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -71,13 +71,6 @@ enum internal_test ITEST_MAX }; -/* Cached operands, and operator to compare for use in set/branch on - condition codes. */ -rtx branch_cmp[2]; - -/* what type of branch to use */ -enum cmp_type branch_type; - /* Array giving truth value on whether or not a given hard register can support a given mode. */ char xtensa_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER]; @@ -128,7 +121,7 @@ const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER] = static enum internal_test map_test_to_internal_test (enum rtx_code); static rtx gen_int_relational (enum rtx_code, rtx, rtx, int *); static rtx gen_float_relational (enum rtx_code, rtx, rtx); -static rtx gen_conditional_move (rtx); +static rtx gen_conditional_move (enum rtx_code, enum machine_mode, rtx, rtx); static rtx fixup_subreg_mem (rtx); static struct machine_function * xtensa_init_machine_status (void); static rtx xtensa_legitimize_tls_address (rtx); @@ -712,27 +705,27 @@ gen_float_relational (enum rtx_code test_code, /* relational test (EQ, etc) */ void -xtensa_expand_conditional_branch (rtx *operands, enum rtx_code test_code) +xtensa_expand_conditional_branch (rtx *operands, enum machine_mode mode) { - enum cmp_type type = branch_type; - rtx cmp0 = branch_cmp[0]; - rtx cmp1 = branch_cmp[1]; + enum rtx_code test_code = GET_CODE (operands[0]); + rtx cmp0 = operands[1]; + rtx cmp1 = operands[2]; rtx cmp; int invert; rtx label1, label2; - switch (type) + switch (mode) { - case CMP_DF: + case DFmode: default: fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1)); - case CMP_SI: + case SImode: invert = FALSE; cmp = gen_int_relational (test_code, cmp0, cmp1, &invert); break; - case CMP_SF: + case SFmode: if (!TARGET_HARD_FLOAT) fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1)); @@ -743,7 +736,7 @@ xtensa_expand_conditional_branch (rtx *operands, enum rtx_code test_code) /* Generate the branch. */ - label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]); + label1 = gen_rtx_LABEL_REF (VOIDmode, operands[3]); label2 = pc_rtx; if (invert) @@ -760,14 +753,13 @@ xtensa_expand_conditional_branch (rtx *operands, enum rtx_code test_code) static rtx -gen_conditional_move (rtx cmp) +gen_conditional_move (enum rtx_code code, enum machine_mode mode, + rtx op0, rtx op1) { - enum rtx_code code = GET_CODE (cmp); - rtx op0 = branch_cmp[0]; - rtx op1 = branch_cmp[1]; - - if (branch_type == CMP_SI) + if (mode == SImode) { + rtx cmp; + /* Jump optimization calls get_condition() which canonicalizes comparisons like (GE x ) to (GT x ). Transform those comparisons back to GE, since that is the @@ -825,7 +817,7 @@ gen_conditional_move (rtx cmp) return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); } - if (TARGET_HARD_FLOAT && (branch_type == CMP_SF)) + if (TARGET_HARD_FLOAT && mode == SFmode) return gen_float_relational (code, op0, op1); return 0; @@ -835,36 +827,39 @@ gen_conditional_move (rtx cmp) int xtensa_expand_conditional_move (rtx *operands, int isflt) { - rtx cmp; + rtx dest = operands[0]; + rtx cmp = operands[1]; + enum machine_mode cmp_mode = GET_MODE (XEXP (cmp, 0)); rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx); - if (!(cmp = gen_conditional_move (operands[1]))) + if (!(cmp = gen_conditional_move (GET_CODE (cmp), cmp_mode, + XEXP (cmp, 0), XEXP (cmp, 1)))) return 0; if (isflt) - gen_fn = (branch_type == CMP_SI + gen_fn = (cmp_mode == SImode ? gen_movsfcc_internal0 : gen_movsfcc_internal1); else - gen_fn = (branch_type == CMP_SI + gen_fn = (cmp_mode == SImode ? gen_movsicc_internal0 : gen_movsicc_internal1); - emit_insn (gen_fn (operands[0], XEXP (cmp, 0), - operands[2], operands[3], cmp)); + emit_insn (gen_fn (dest, XEXP (cmp, 0), operands[2], operands[3], cmp)); return 1; } int -xtensa_expand_scc (rtx *operands) +xtensa_expand_scc (rtx operands[4], enum machine_mode cmp_mode) { rtx dest = operands[0]; - rtx cmp = operands[1]; + rtx cmp; rtx one_tmp, zero_tmp; rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx); - if (!(cmp = gen_conditional_move (cmp))) + if (!(cmp = gen_conditional_move (GET_CODE (operands[1]), cmp_mode, + operands[2], operands[3]))) return 0; one_tmp = gen_reg_rtx (SImode); @@ -872,7 +867,7 @@ xtensa_expand_scc (rtx *operands) emit_insn (gen_movsi (one_tmp, const_true_rtx)); emit_insn (gen_movsi (zero_tmp, const0_rtx)); - gen_fn = (branch_type == CMP_SI + gen_fn = (cmp_mode == SImode ? gen_movsicc_internal0 : gen_movsicc_internal1); emit_insn (gen_fn (dest, XEXP (cmp, 0), one_tmp, zero_tmp, cmp)); diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h index 73f68ef315f..c01a778bf2b 100644 --- a/gcc/config/xtensa/xtensa.h +++ b/gcc/config/xtensa/xtensa.h @@ -27,17 +27,6 @@ extern int optimize; /* External variables defined in xtensa.c. */ -/* comparison type */ -enum cmp_type { - CMP_SI, /* four byte integers */ - CMP_DI, /* eight byte integers */ - CMP_SF, /* single precision floats */ - CMP_DF, /* double precision floats */ - CMP_MAX /* max comparison type */ -}; - -extern struct rtx_def * branch_cmp[2]; /* operands for compare */ -extern enum cmp_type branch_type; /* what type of branch to use */ extern unsigned xtensa_current_frame_size; /* Macros used in the machine description to select various Xtensa diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 63c5db5b476..13883f1d5ca 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -64,15 +64,6 @@ (define_code_attr minmax [(smin "min") (umin "minu") (smax "max") (umax "maxu")]) -;; This code iterator allows all branch instructions to be generated from -;; a single define_expand template. -(define_code_iterator any_cond [eq ne gt ge lt le gtu geu ltu leu - uneq ltgt ungt unge unlt unle - unordered ordered]) - -;; This code iterator is for setting a register from a comparison. -(define_code_iterator any_scc [eq ne gt ge lt le]) - ;; This code iterator is for floating-point comparisons. (define_code_iterator any_scc_sf [eq lt le uneq unlt unle unordered]) (define_code_attr scc_sf [(eq "oeq") (lt "olt") (le "ole") @@ -1131,44 +1122,27 @@ ;; Comparisons. -;; Handle comparisons by stashing away the operands and then using that -;; information in the subsequent conditional branch. +;; Conditional branches. -(define_expand "cmpsi" - [(set (cc0) - (compare:CC (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "nonmemory_operand" "")))] +(define_expand "cbranchsi4" + [(match_operator 0 "comparison_operator" + [(match_operand:SI 1 "register_operand") + (match_operand:SI 2 "nonmemory_operand")]) + (match_operand 3 "")] "" { - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_SI; + xtensa_expand_conditional_branch (operands, SImode); DONE; }) -(define_expand "cmpsf" - [(set (cc0) - (compare:CC (match_operand:SF 0 "register_operand" "") - (match_operand:SF 1 "register_operand" "")))] +(define_expand "cbranchsf4" + [(match_operator 0 "comparison_operator" + [(match_operand:SF 1 "register_operand") + (match_operand:SF 2 "register_operand")]) + (match_operand 3 "")] "TARGET_HARD_FLOAT" { - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_SF; - DONE; -}) - - -;; Conditional branches. - -(define_expand "b" - [(set (pc) - (if_then_else (any_cond (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - xtensa_expand_conditional_branch (operands, ); + xtensa_expand_conditional_branch (operands, SFmode); DONE; }) @@ -1353,18 +1327,31 @@ ;; Setting a register from a comparison. -(define_expand "s" - [(set (match_operand:SI 0 "register_operand" "") - (any_scc:SI (match_dup 1) - (match_dup 2)))] +(define_expand "cstoresi4" + [(match_operand:SI 0 "register_operand") + (match_operator 1 "xtensa_cstoresi_operator" + [(match_operand:SI 2 "register_operand") + (match_operand:SI 3 "nonmemory_operand")])] "" { - operands[1] = gen_rtx_ (SImode, branch_cmp[0], branch_cmp[1]); - if (!xtensa_expand_scc (operands)) + if (!xtensa_expand_scc (operands, SImode)) FAIL; DONE; }) +(define_expand "cstoresf4" + [(match_operand:SI 0 "register_operand") + (match_operator:SI 1 "comparison_operator" + [(match_operand:SF 2 "register_operand") + (match_operand:SF 3 "register_operand")])] + "TARGET_HARD_FLOAT" +{ + if (!xtensa_expand_scc (operands, SFmode)) + FAIL; + DONE; +}) + + ;; Conditional moves. diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index b966c27a880..f91d6e12480 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -4236,30 +4236,6 @@ the operand to that mode before generating the instruction. @item @samp{one_cmpl@var{m}2} Store the bitwise-complement of operand 1 into operand 0. -@cindex @code{cmp@var{m}} instruction pattern -@item @samp{cmp@var{m}} -Compare operand 0 and operand 1, and set the condition codes. -The RTL pattern should look like this: - -@smallexample -(set (cc0) (compare (match_operand:@var{m} 0 @dots{}) - (match_operand:@var{m} 1 @dots{}))) -@end smallexample - -@cindex @code{tst@var{m}} instruction pattern -@item @samp{tst@var{m}} -Compare operand 0 against zero, and set the condition codes. -The RTL pattern should look like this: - -@smallexample -(set (cc0) (match_operand:@var{m} 0 @dots{})) -@end smallexample - -@samp{tst@var{m}} patterns should not be defined for machines that do -not use @code{(cc0)}. Doing so would confuse the optimizer since it -would no longer be clear which @code{set} operations were comparisons. -The @samp{cmp@var{m}} patterns should be used instead. - @cindex @code{movmem@var{m}} instruction pattern @item @samp{movmem@var{m}} Block move instruction. The destination and source blocks of memory @@ -4522,16 +4498,14 @@ move operand 2 or (operands 2 + operand 3) into operand 0 according to the comparison in operand 1. If the comparison is true, operand 2 is moved into operand 0, otherwise (operand 2 + operand 3) is moved. -@cindex @code{s@var{cond}} instruction pattern -@item @samp{s@var{cond}} -Store zero or nonzero in the operand according to the condition codes. -Value stored is nonzero iff the condition @var{cond} is true. -@var{cond} is the name of a comparison operation expression code, such -as @code{eq}, @code{lt} or @code{leu}. - -You specify the mode that the operand must have when you write the -@code{match_operand} expression. The compiler automatically sees -which mode you have used and supplies an operand of that mode. +@cindex @code{cstore@var{mode}4} instruction pattern +@item @samp{cstore@var{mode}4} +Store zero or nonzero in operand 0 according to whether a comparison +is true. Operand 1 is a comparison operator. Operand 2 and operand 3 +are the first and second operand of the comparison, respectively. +You specify the mode that operand 0 must have when you write the +@code{match_operand} expression. The compiler automatically sees which +mode you have used and supplies an operand of that mode. The value stored for a true condition must have 1 as its low bit, or else must be negative. Otherwise the instruction is not suitable and @@ -4548,33 +4522,11 @@ integer comparisons, it is best to omit these patterns. If these operations are omitted, the compiler will usually generate code that copies the constant one to the target and branches around an assignment of zero to the target. If this code is more efficient than -the potential instructions used for the @samp{s@var{cond}} pattern +the potential instructions used for the @samp{cstore@var{mode}4} pattern followed by those required to convert the result into a 1 or a zero in -@code{SImode}, you should omit the @samp{s@var{cond}} operations from +@code{SImode}, you should omit the @samp{cstore@var{mode}4} operations from the machine description. -@cindex @code{b@var{cond}} instruction pattern -@item @samp{b@var{cond}} -Conditional branch instruction. Operand 0 is a @code{label_ref} that -refers to the label to jump to. Jump if the condition codes meet -condition @var{cond}. - -Some machines do not follow the model assumed here where a comparison -instruction is followed by a conditional branch instruction. In that -case, the @samp{cmp@var{m}} (and @samp{tst@var{m}}) patterns should -simply store the operands away and generate all the required insns in a -@code{define_expand} (@pxref{Expander Definitions}) for the conditional -branch operations. All calls to expand @samp{b@var{cond}} patterns are -immediately preceded by calls to expand either a @samp{cmp@var{m}} -pattern or a @samp{tst@var{m}} pattern. - -Machines that use a pseudo register for the condition code value, or -where the mode used for the comparison depends on the condition being -tested, should also use the above mechanism. @xref{Jump Patterns}. - -The above discussion also applies to the @samp{mov@var{mode}cc} and -@samp{s@var{cond}} patterns. - @cindex @code{cbranch@var{mode}4} instruction pattern @item @samp{cbranch@var{mode}4} Conditional branch instruction combined with a compare instruction. @@ -5025,18 +4977,20 @@ This pattern, if defined, signals an error, typically by causing some kind of signal to be raised. Among other places, it is used by the Java front end to signal `invalid array index' exceptions. -@cindex @code{conditional_trap} instruction pattern -@item @samp{conditional_trap} +@cindex @code{ctrap@var{MM}4} instruction pattern +@item @samp{ctrap@var{MM}4} Conditional trap instruction. Operand 0 is a piece of RTL which -performs a comparison. Operand 1 is the trap code, an integer. +performs a comparison, and operands 1 and 2 are the arms of the +comparison. Operand 3 is the trap code, an integer. -A typical @code{conditional_trap} pattern looks like +A typical @code{ctrap} pattern looks like @smallexample -(define_insn "conditional_trap" +(define_insn "ctrapsi4" [(trap_if (match_operator 0 "trap_operator" - [(cc0) (const_int 0)]) - (match_operand 1 "const_int_operand" "i"))] + [(match_operand 1 "register_operand") + (match_operand 2 "immediate_operand")]) + (match_operand 3 "const_int_operand" "i"))] "" "@dots{}") @end smallexample @@ -5092,14 +5046,16 @@ operation and all memory operations after the atomic operation occur after the atomic operation. For targets where the success or failure of the compare-and-swap -operation is available via the status flags, it is possible -to avoid a separate compare operation and issue the subsequent -setcc or branch immediately after the compare-and-swap. To this -end, GCC will look for a @code{MODE_CC} set in the output of -@code{sync_compare_and_swap@var{mode}}; if the machine description -includes such a set, the target should also define a special @code{cmpcc} -instruction. GCC will then be able to take the destination of the -@code{MODE_CC} set and use it as the first operand of @code{cmpcc}. +operation is available via the status flags, it is possible to +avoid a separate compare operation and issue the subsequent +branch or store-flag operation immediately after the compare-and-swap. +To this end, GCC will look for a @code{MODE_CC} set in the +output of @code{sync_compare_and_swap@var{mode}}; if the machine +description includes such a set, the target should also define special +@code{cbranchcc4} and/or @code{cstorecc4} instructions. GCC will then +be able to take the destination of the @code{MODE_CC} set and pass it +to the @code{cbranchcc4} or @code{cstorecc4} pattern as the first +operand of the comparison (the second will be @code{(const_int 0)}). @cindex @code{sync_add@var{mode}} instruction pattern @cindex @code{sync_sub@var{mode}} instruction pattern @@ -5275,48 +5231,6 @@ constant value. @cindex Dependent Patterns @cindex Interdependence of Patterns -Every machine description must have a named pattern for each of the -conditional branch names @samp{b@var{cond}}. The recognition template -must always have the form - -@smallexample -(set (pc) - (if_then_else (@var{cond} (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc))) -@end smallexample - -@noindent -In addition, every machine description must have an anonymous pattern -for each of the possible reverse-conditional branches. Their templates -look like - -@smallexample -(set (pc) - (if_then_else (@var{cond} (cc0) (const_int 0)) - (pc) - (label_ref (match_operand 0 "" "")))) -@end smallexample - -@noindent -They are necessary because jump optimization can turn direct-conditional -branches into reverse-conditional branches. - -It is often convenient to use the @code{match_operator} construct to -reduce the number of patterns that must be specified for branches. For -example, - -@smallexample -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] - "@var{condition}" - "@dots{}") -@end smallexample - In some cases machines support instructions identical except for the machine mode of one or more operands. For example, there may be ``sign-extend halfword'' and ``sign-extend byte'' instructions whose @@ -5357,113 +5271,38 @@ generating the appropriate machine instruction. @cindex jump instruction patterns @cindex defining jump instruction patterns -For most machines, GCC assumes that the machine has a condition code. -A comparison insn sets the condition code, recording the results of both -signed and unsigned comparison of the given operands. A separate branch -insn tests the condition code and branches or not according its value. -The branch insns come in distinct signed and unsigned flavors. Many -common machines, such as the VAX, the 68000 and the 32000, work this -way. - -Some machines have distinct signed and unsigned compare instructions, and -only one set of conditional branch instructions. The easiest way to handle -these machines is to treat them just like the others until the final stage -where assembly code is written. At this time, when outputting code for the -compare instruction, peek ahead at the following branch using -@code{next_cc0_user (insn)}. (The variable @code{insn} refers to the insn -being output, in the output-writing code in an instruction pattern.) If -the RTL says that is an unsigned branch, output an unsigned compare; -otherwise output a signed compare. When the branch itself is output, you -can treat signed and unsigned branches identically. - -The reason you can do this is that GCC always generates a pair of -consecutive RTL insns, possibly separated by @code{note} insns, one to -set the condition code and one to test it, and keeps the pair inviolate -until the end. - -To go with this technique, you must define the machine-description macro -@code{NOTICE_UPDATE_CC} to do @code{CC_STATUS_INIT}; in other words, no -compare instruction is superfluous. - -Some machines have compare-and-branch instructions and no condition code. -A similar technique works for them. When it is time to ``output'' a -compare instruction, record its operands in two static variables. When -outputting the branch-on-condition-code instruction that follows, actually -output a compare-and-branch instruction that uses the remembered operands. - -It also works to define patterns for compare-and-branch instructions. -In optimizing compilation, the pair of compare and branch instructions -will be combined according to these patterns. But this does not happen -if optimization is not requested. So you must use one of the solutions -above in addition to any special patterns you define. - -In many RISC machines, most instructions do not affect the condition -code and there may not even be a separate condition code register. On -these machines, the restriction that the definition and use of the -condition code be adjacent insns is not necessary and can prevent -important optimizations. For example, on the IBM RS/6000, there is a -delay for taken branches unless the condition code register is set three -instructions earlier than the conditional branch. The instruction -scheduler cannot perform this optimization if it is not permitted to -separate the definition and use of the condition code register. - -On these machines, do not use @code{(cc0)}, but instead use a register -to represent the condition code. If there is a specific condition code -register in the machine, use a hard register. If the condition code or -comparison result can be placed in any general register, or if there are -multiple condition registers, use a pseudo register. - -@findex prev_cc0_setter -@findex next_cc0_user -On some machines, the type of branch instruction generated may depend on -the way the condition code was produced; for example, on the 68k and -SPARC, setting the condition code directly from an add or subtract -instruction does not clear the overflow bit the way that a test -instruction does, so a different branch instruction must be used for -some conditional branches. For machines that use @code{(cc0)}, the set -and use of the condition code must be adjacent (separated only by -@code{note} insns) allowing flags in @code{cc_status} to be used. -(@xref{Condition Code}.) Also, the comparison and branch insns can be -located from each other by using the functions @code{prev_cc0_setter} -and @code{next_cc0_user}. - -However, this is not true on machines that do not use @code{(cc0)}. On -those machines, no assumptions can be made about the adjacency of the -compare and branch insns and the above methods cannot be used. Instead, -we use the machine mode of the condition code register to record -different formats of the condition code register. - -Registers used to store the condition code value should have a mode that -is in class @code{MODE_CC}. Normally, it will be @code{CCmode}. If -additional modes are required (as for the add example mentioned above in -the SPARC), define them in @file{@var{machine}-modes.def} -(@pxref{Condition Code}). Also define @code{SELECT_CC_MODE} to choose -a mode given an operand of a compare. - -If it is known during RTL generation that a different mode will be -required (for example, if the machine has separate compare instructions -for signed and unsigned quantities, like most IBM processors), they can -be specified at that time. - -If the cases that require different modes would be made by instruction -combination, the macro @code{SELECT_CC_MODE} determines which machine -mode should be used for the comparison result. The patterns should be -written using that mode. To support the case of the add on the SPARC -discussed above, we have the pattern - -@smallexample -(define_insn "" - [(set (reg:CC_NOOV 0) - (compare:CC_NOOV - (plus:SI (match_operand:SI 0 "register_operand" "%r") - (match_operand:SI 1 "arith_operand" "rI")) - (const_int 0)))] - "" - "@dots{}") -@end smallexample - -The @code{SELECT_CC_MODE} macro on the SPARC returns @code{CC_NOOVmode} -for comparisons whose argument is a @code{plus}. +GCC does not assume anything about how the machine realizes jumps. +The machine description should define a single pattern, usually +a @code{define_expand}, which expands to all the required insns. + +Usually, this would be a comparison insn to set the condition code +and a separate branch insn testing the condition code and branching +or not according to its value. For many machines, however, +separating compares and branches is limiting, which is why the +more flexible approach with one @code{define_expand} is used in GCC. +The machine description becomes clearer for architectures that +have compare-and-branch instructions but no condition code. It also +works better when different sets of comparison operators are supported +by different kinds of conditional branches (e.g. integer vs. floating-point), +or by conditional branches with respect to conditional stores. + +Two separate insns are always used if the machine description represents +a condition code register using the legacy RTL expression @code{(cc0)}, +and on most machines that use a separate condition code register +(@pxref{Condition Code}). For machines that use @code{(cc0)}, in +fact, the set and use of the condition code must be separate and +adjacent@footnote{@code{note} insns can separate them, though.}, thus +allowing flags in @code{cc_status} to be used (@pxref{Condition Code}) and +so that the comparison and branch insns could be located from each other +by using the functions @code{prev_cc0_setter} and @code{next_cc0_user}. + +Even in this case having a single entry point for conditional branches +is advantageous, because it handles equally well the case where a single +comparison instruction records the results of both signed and unsigned +comparison of the given operands (with the branch insns coming in distinct +signed and unsigned flavors) as in the x86 or SPARC, and the case where +there are distinct signed and unsigned compare instructions and only +one set of conditional branch instructions as in the PowerPC. @end ifset @ifset INTERNALS @@ -5625,13 +5464,9 @@ the operations as far as possible. For instance, @cindex @code{compare}, canonicalization of @item For the @code{compare} operator, a constant is always the second operand -on machines where @code{cc0} is used (@pxref{Jump Patterns}). On other -machines, there are rare cases where the compiler might want to construct -a @code{compare} with a constant as the first operand. However, these -cases are not common enough for it to be worthwhile to provide a pattern -matching a constant as the first operand unless the machine actually has -such an instruction. +if the first argument is a condition code register or @code{(cc0)}. +@item An operand of @code{neg}, @code{not}, @code{mult}, @code{plus}, or @code{minus} is made the first operand under the same conditions as above. @@ -5699,11 +5534,6 @@ the form (plus:@var{m} (plus:@var{m} @var{x} @var{y}) @var{constant}) @end smallexample -@item -On machines that do not use @code{cc0}, -@code{(compare @var{x} (const_int 0))} will be converted to -@var{x}. - @cindex @code{zero_extract}, canonicalization of @cindex @code{sign_extract}, canonicalization of @item diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 4c9b16279b5..05e04761bc4 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -5724,8 +5724,47 @@ or target-specific sections. @section Condition Code Status @cindex condition code status -@c prevent bad page break with this line -This describes the condition code status. +The macros in this section can be split in two families, according to the +two ways of representing condition codes in GCC. + +The first representation is the so called @code{(cc0)} representation +(@pxref{Jump Patterns}), where all instructions can have an implicit +clobber of the condition codes. The second is the condition code +register representation, which provides better schedulability for +architectures that do have a condition code register, but on which +most instructions do not affect it. The latter category includes +most RISC machines. + +The implicit clobbering poses a strong restriction on the placement of +the definition and use of the condition code, which need to be in adjacent +insns for machines using @code{(cc0)}. This can prevent important +optimizations on some machines. For example, on the IBM RS/6000, there +is a delay for taken branches unless the condition code register is set +three instructions earlier than the conditional branch. The instruction +scheduler cannot perform this optimization if it is not permitted to +separate the definition and use of the condition code register. + +For this reason, it is possible and suggested to use a register to +represent the condition code for new ports. If there is a specific +condition code register in the machine, use a hard register. If the +condition code or comparison result can be placed in any general register, +or if there are multiple condition registers, use a pseudo register. +Registers used to store the condition code value will usually have a mode +that is in class @code{MODE_CC}. + +Alternatively, you can use @code{BImode} if the comparison operator is +specified already in the compare instruction. In this case, you are not +interested in most macros in this section. + +@menu +* CC0 Condition Codes:: Old style representation of condition codes. +* MODE_CC Condition Codes:: Modern representation of condition codes. +* Cond. Exec. Macros:: Macros to control conditional execution. +@end menu + +@node CC0 Condition Codes +@subsection Representation of condition codes using @code{(cc0)} +@findex cc0 @findex cc_status The file @file{conditions.h} defines a variable @code{cc_status} to @@ -5791,12 +5830,45 @@ that looks at an attribute (@pxref{Insn Attributes}) named, for example, two places, the @file{md} file and in @code{NOTICE_UPDATE_CC}. @end defmac +@node MODE_CC Condition Codes +@subsection Representation of condition codes using registers +@findex CCmode +@findex MODE_CC + @defmac SELECT_CC_MODE (@var{op}, @var{x}, @var{y}) -Returns a mode from class @code{MODE_CC} to be used when comparison -operation code @var{op} is applied to rtx @var{x} and @var{y}. For -example, on the SPARC, @code{SELECT_CC_MODE} is defined as (see -@pxref{Jump Patterns} for a description of the reason for this -definition) +On many machines, the condition code may be produced by other instructions +than compares, for example the branch can use directly the condition +code set by a subtract instruction. However, on some machines +when the condition code is set this way some bits (such as the overflow +bit) are not set in the same way as a test instruction, so that a different +branch instruction must be used for some conditional branches. When +this happens, use the machine mode of the condition code register to +record different formats of the condition code register. Modes can +also be used to record which compare instruction (e.g. a signed or an +unsigned comparison) produced the condition codes. + +If other modes than @code{CCmode} are required, add them to +@file{@var{machine}-modes.def} and define @code{SELECT_CC_MODE} to choose +a mode given an operand of a compare. This is needed because the modes +have to be chosen not only during RTL generation but also, for example, +by instruction combination. The result of @code{SELECT_CC_MODE} should +be consistent with the mode used in the patterns; for example to support +the case of the add on the SPARC discussed above, we have the pattern + +@smallexample +(define_insn "" + [(set (reg:CC_NOOV 0) + (compare:CC_NOOV + (plus:SI (match_operand:SI 0 "register_operand" "%r") + (match_operand:SI 1 "arith_operand" "rI")) + (const_int 0)))] + "" + "@dots{}") +@end smallexample + +@noindent +together with a @code{SELECT_CC_MODE} that returns @code{CC_NOOVmode} +for comparisons whose argument is a @code{plus}: @smallexample #define SELECT_CC_MODE(OP,X,Y) \ @@ -5807,6 +5879,10 @@ definition) ? CC_NOOVmode : CCmode)) @end smallexample +Another reason to use modes is to retain information on which operands +were used by the comparison; see @code{REVERSIBLE_CC_MODE} later in +this section. + You should define this macro if and only if you define extra CC modes in @file{@var{machine}-modes.def}. @end defmac @@ -5863,20 +5939,6 @@ like: @end smallexample @end defmac -@defmac REVERSE_CONDEXEC_PREDICATES_P (@var{op1}, @var{op2}) -A C expression that returns true if the conditional execution predicate -@var{op1}, a comparison operation, is the inverse of @var{op2} and vice -versa. Define this to return 0 if the target has conditional execution -predicates that cannot be reversed safely. There is no need to validate -that the arguments of op1 and op2 are the same, this is done separately. -If no expansion is specified, this macro is defined as follows: - -@smallexample -#define REVERSE_CONDEXEC_PREDICATES_P (x, y) \ - (GET_CODE ((x)) == reversed_comparison_code ((y), NULL)) -@end smallexample -@end defmac - @deftypefn {Target Hook} bool TARGET_FIXED_CONDITION_CODE_REGS (unsigned int *, unsigned int *) On targets which do not use @code{(cc0)}, and which use a hard register rather than a pseudo-register to hold condition codes, the @@ -5905,6 +5967,29 @@ same. If they are, it returns that mode. If they are different, it returns @code{VOIDmode}. @end deftypefn +@node Cond. Exec. Macros +@subsection Macros to control conditional execution +@findex conditional execution +@findex predication + +There is one macro that may need to be defined for targets +supporting conditional execution, independent of how they +represent conditional branches. + +@defmac REVERSE_CONDEXEC_PREDICATES_P (@var{op1}, @var{op2}) +A C expression that returns true if the conditional execution predicate +@var{op1}, a comparison operation, is the inverse of @var{op2} and vice +versa. Define this to return 0 if the target has conditional execution +predicates that cannot be reversed safely. There is no need to validate +that the arguments of op1 and op2 are the same, this is done separately. +If no expansion is specified, this macro is defined as follows: + +@smallexample +#define REVERSE_CONDEXEC_PREDICATES_P (x, y) \ + (GET_CODE ((x)) == reversed_comparison_code ((y), NULL)) +@end smallexample +@end defmac + @node Costs @section Describing Relative Costs of Operations @cindex costs of instructions diff --git a/gcc/dojump.c b/gcc/dojump.c index 36430851393..76f62c62eba 100644 --- a/gcc/dojump.c +++ b/gcc/dojump.c @@ -756,64 +756,6 @@ do_jump_by_parts_equality (tree exp, rtx if_false_label, rtx if_true_label) if_true_label); } -/* Generate code for a comparison of OP0 and OP1 with rtx code CODE. - MODE is the machine mode of the comparison, not of the result. - (including code to compute the values to be compared) and set CC0 - according to the result. The decision as to signed or unsigned - comparison must be made by the caller. - - We force a stack adjustment unless there are currently - things pushed on the stack that aren't yet used. - - If MODE is BLKmode, SIZE is an RTX giving the size of the objects being - compared. */ - -rtx -compare_from_rtx (rtx op0, rtx op1, enum rtx_code code, int unsignedp, - enum machine_mode mode, rtx size) -{ - rtx tem; - - /* If one operand is constant, make it the second one. Only do this - if the other operand is not constant as well. */ - - if (swap_commutative_operands_p (op0, op1)) - { - tem = op0; - op0 = op1; - op1 = tem; - code = swap_condition (code); - } - - do_pending_stack_adjust (); - - code = unsignedp ? unsigned_condition (code) : code; - tem = simplify_relational_operation (code, VOIDmode, mode, op0, op1); - if (tem) - { - if (CONSTANT_P (tem)) - return tem; - - if (COMPARISON_P (tem)) - { - code = GET_CODE (tem); - op0 = XEXP (tem, 0); - op1 = XEXP (tem, 1); - mode = GET_MODE (op0); - unsignedp = (code == GTU || code == LTU - || code == GEU || code == LEU); - } - } - - emit_cmp_insn (op0, op1, code, size, mode, unsignedp); - -#if HAVE_cc0 - return gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx); -#else - return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); -#endif -} - /* Like do_compare_and_jump but expects the values to compare as two rtx's. The decision as to signed or unsigned comparison must be made by the caller. diff --git a/gcc/expmed.c b/gcc/expmed.c index d0c1621cc5e..16f7415b549 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -5207,8 +5207,9 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1, enum insn_code icode; enum machine_mode compare_mode; enum machine_mode target_mode = GET_MODE (target); + enum mode_class mclass; rtx tem; - rtx last = get_last_insn (); + rtx last; rtx pattern, comparison; if (unsignedp) @@ -5342,117 +5343,41 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1, return op0; } - icode = setcc_gen_code[(int) code]; - - if (icode != CODE_FOR_nothing) - { - insn_operand_predicate_fn pred; - - /* We think we may be able to do this with a scc insn. Emit the - comparison and then the scc insn. */ - - do_pending_stack_adjust (); - last = get_last_insn (); - - comparison - = compare_from_rtx (op0, op1, code, unsignedp, mode, NULL_RTX); - if (CONSTANT_P (comparison)) - { - switch (GET_CODE (comparison)) - { - case CONST_INT: - if (comparison == const0_rtx) - return const0_rtx; - break; - -#ifdef FLOAT_STORE_FLAG_VALUE - case CONST_DOUBLE: - if (comparison == CONST0_RTX (GET_MODE (comparison))) - return const0_rtx; - break; -#endif - default: - gcc_unreachable (); - } - - if (normalizep == 1) - return const1_rtx; - if (normalizep == -1) - return constm1_rtx; - return const_true_rtx; - } - - /* The code of COMPARISON may not match CODE if compare_from_rtx - decided to swap its operands and reverse the original code. - - We know that compare_from_rtx returns either a CONST_INT or - a new comparison code, so it is safe to just extract the - code from COMPARISON. */ - code = GET_CODE (comparison); - - /* Get a reference to the target in the proper mode for this insn. */ - compare_mode = insn_data[(int) icode].operand[0].mode; - subtarget = target; - pred = insn_data[(int) icode].operand[0].predicate; - if (optimize || ! (*pred) (subtarget, compare_mode)) - subtarget = gen_reg_rtx (compare_mode); - - pattern = GEN_FCN (icode) (subtarget); - if (pattern) - { - emit_insn (pattern); - return emit_store_flag_1 (target, subtarget, compare_mode, - normalizep); - } - } - else + mclass = GET_MODE_CLASS (mode); + for (compare_mode = mode; compare_mode != VOIDmode; + compare_mode = GET_MODE_WIDER_MODE (compare_mode)) { - /* We don't have an scc insn, so try a cstore insn. */ - - for (compare_mode = mode; compare_mode != VOIDmode; - compare_mode = GET_MODE_WIDER_MODE (compare_mode)) - { - icode = optab_handler (cstore_optab, compare_mode)->insn_code; - if (icode != CODE_FOR_nothing) - break; - } - - if (icode != CODE_FOR_nothing) + enum machine_mode optab_mode = mclass == MODE_CC ? CCmode : compare_mode; + icode = optab_handler (cstore_optab, optab_mode)->insn_code; + if (icode != CODE_FOR_nothing) { + rtx x, y; enum machine_mode result_mode = insn_data[(int) icode].operand[0].mode; - rtx cstore_op0 = op0; - rtx cstore_op1 = op1; do_pending_stack_adjust (); last = get_last_insn (); - if (compare_mode != mode) + x = prepare_operand (icode, op0, 2, mode, compare_mode, unsignedp); + y = prepare_operand (icode, op1, 3, mode, compare_mode, unsignedp); + comparison = gen_rtx_fmt_ee (code, result_mode, x, y); + if (!x || !y + || !insn_data[icode].operand[2].predicate + (x, insn_data[icode].operand[2].mode) + || !insn_data[icode].operand[3].predicate + (y, insn_data[icode].operand[3].mode) + || !insn_data[icode].operand[1].predicate (comparison, VOIDmode)) { - cstore_op0 = convert_modes (compare_mode, mode, cstore_op0, - unsignedp); - cstore_op1 = convert_modes (compare_mode, mode, cstore_op1, - unsignedp); + delete_insns_since (last); + continue; } - - if (!insn_data[(int) icode].operand[2].predicate (cstore_op0, - compare_mode)) - cstore_op0 = copy_to_mode_reg (compare_mode, cstore_op0); - if (!insn_data[(int) icode].operand[3].predicate (cstore_op1, - compare_mode)) - cstore_op1 = copy_to_mode_reg (compare_mode, cstore_op1); - - comparison = gen_rtx_fmt_ee (code, result_mode, cstore_op0, - cstore_op1); subtarget = target; - if (optimize || !(insn_data[(int) icode].operand[0].predicate (subtarget, result_mode))) subtarget = gen_reg_rtx (result_mode); - pattern = GEN_FCN (icode) (subtarget, comparison, cstore_op0, - cstore_op1); + pattern = GEN_FCN (icode) (subtarget, comparison, x, y); if (pattern) { @@ -5460,10 +5385,13 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1, return emit_store_flag_1 (target, subtarget, result_mode, normalizep); } + + delete_insns_since (last); + break; } } - delete_insns_since (last); + last = get_last_insn (); /* If optimizing, use different pseudo registers for each insn, instead of reusing the same pseudo. This leads to better CSE, but slows diff --git a/gcc/expr.h b/gcc/expr.h index e3c38370bf2..64794834771 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -298,6 +298,9 @@ extern rtx expand_simple_unop (enum machine_mode, enum rtx_code, rtx, rtx, perform the operation described by CODE and MODE. */ extern int have_insn_for (enum rtx_code, enum machine_mode); +extern rtx prepare_operand (int, rtx, int, enum machine_mode, enum machine_mode, + int); + /* Emit code to make a call to a constant function or a library call. */ extern void emit_libcall_block (rtx, rtx, rtx, rtx); @@ -573,9 +576,6 @@ extern void jumpif (tree, rtx); the result is zero, or IF_TRUE_LABEL if the result is one. */ extern void do_jump (tree, rtx, rtx); -/* Generate rtl to compare two rtx's, will call emit_cmp_insn. */ -extern rtx compare_from_rtx (rtx, rtx, enum rtx_code, int, enum machine_mode, - rtx); extern void do_compare_rtx_and_jump (rtx, rtx, enum rtx_code, int, enum machine_mode, rtx, rtx, rtx); diff --git a/gcc/final.c b/gcc/final.c index 551b3a0e8b0..30ccc852991 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -2320,9 +2320,13 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, && GET_CODE (SET_DEST (set)) == CC0 && insn != last_ignored_compare) { + rtx src1, src2; if (GET_CODE (SET_SRC (set)) == SUBREG) SET_SRC (set) = alter_subreg (&SET_SRC (set)); - else if (GET_CODE (SET_SRC (set)) == COMPARE) + + src1 = SET_SRC (set); + src2 = NULL_RTX; + if (GET_CODE (SET_SRC (set)) == COMPARE) { if (GET_CODE (XEXP (SET_SRC (set), 0)) == SUBREG) XEXP (SET_SRC (set), 0) @@ -2330,11 +2334,18 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, if (GET_CODE (XEXP (SET_SRC (set), 1)) == SUBREG) XEXP (SET_SRC (set), 1) = alter_subreg (&XEXP (SET_SRC (set), 1)); + if (XEXP (SET_SRC (set), 1) + == CONST0_RTX (GET_MODE (XEXP (SET_SRC (set), 0)))) + src2 = XEXP (SET_SRC (set), 0); } if ((cc_status.value1 != 0 - && rtx_equal_p (SET_SRC (set), cc_status.value1)) + && rtx_equal_p (src1, cc_status.value1)) || (cc_status.value2 != 0 - && rtx_equal_p (SET_SRC (set), cc_status.value2))) + && rtx_equal_p (src1, cc_status.value2)) + || (src2 != 0 && cc_status.value1 != 0 + && rtx_equal_p (src2, cc_status.value1)) + || (src2 != 0 && cc_status.value2 != 0 + && rtx_equal_p (src2, cc_status.value2))) { /* Don't delete insn if it has an addressing side-effect. */ if (! FIND_REG_INC_NOTE (insn, NULL_RTX) @@ -2348,9 +2359,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, } } } -#endif -#ifdef HAVE_cc0 /* If this is a conditional branch, maybe modify it if the cc's are in a nonstandard state so that it accomplishes the same thing that it would diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 8e13d1ccdf4..f8cbf9549f8 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -198,15 +198,12 @@ static const char * const optabs[] = "optab_handler (movstrict_optab, $A)->insn_code = CODE_FOR_$(movstrict$a$)", "optab_handler (movmisalign_optab, $A)->insn_code = CODE_FOR_$(movmisalign$a$)", "optab_handler (storent_optab, $A)->insn_code = CODE_FOR_$(storent$a$)", - "optab_handler (cmp_optab, $A)->insn_code = CODE_FOR_$(cmp$a$)", - "optab_handler (tst_optab, $A)->insn_code = CODE_FOR_$(tst$a$)", "optab_handler (addcc_optab, $A)->insn_code = CODE_FOR_$(add$acc$)", - "bcc_gen_fctn[$C] = gen_$(b$c$)", - "setcc_gen_code[$C] = CODE_FOR_$(s$c$)", "movcc_gen_code[$A] = CODE_FOR_$(mov$acc$)", "optab_handler (cbranch_optab, $A)->insn_code = CODE_FOR_$(cbranch$a4$)", "optab_handler (cmov_optab, $A)->insn_code = CODE_FOR_$(cmov$a6$)", "optab_handler (cstore_optab, $A)->insn_code = CODE_FOR_$(cstore$a4$)", + "optab_handler (ctrap_optab, $A)->insn_code = CODE_FOR_$(ctrap$a4$)", "optab_handler (push_optab, $A)->insn_code = CODE_FOR_$(push$a1$)", "reload_in_optab[$A] = CODE_FOR_$(reload_in$a$)", "reload_out_optab[$A] = CODE_FOR_$(reload_out$a$)", diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index fc3cbd65f61..a4324a59b9f 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -62,9 +62,6 @@ #ifndef HAVE_trap #define HAVE_trap 0 #endif -#ifndef HAVE_conditional_trap -#define HAVE_conditional_trap 0 -#endif #ifndef MAX_CONDITIONAL_EXECUTE #define MAX_CONDITIONAL_EXECUTE \ @@ -3043,7 +3040,8 @@ find_if_header (basic_block test_bb, int pass) && cond_exec_find_if_block (&ce_info)) goto success; - if (HAVE_trap && HAVE_conditional_trap + if (HAVE_trap + && optab_handler (ctrap_optab, word_mode)->insn_code != CODE_FOR_nothing && find_cond_trap (test_bb, then_edge, else_edge)) goto success; diff --git a/gcc/optabs.c b/gcc/optabs.c index c59d7ecf717..970f1501700 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -79,17 +79,6 @@ struct convert_optab convert_optab_table[COI_MAX]; /* Contains the optab used for each rtx code. */ optab code_to_optab[NUM_RTX_CODE + 1]; -/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...) - gives the gen_function to make a branch to test that condition. */ - -rtxfun bcc_gen_fctn[NUM_RTX_CODE]; - -/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...) - gives the insn code to make a store-condition insn - to test that condition. */ - -enum insn_code setcc_gen_code[NUM_RTX_CODE]; - #ifdef HAVE_conditional_move /* Indexed by the machine mode, gives the insn code to make a conditional move insn. This is not indexed by the rtx-code like bcc_gen_fctn and @@ -105,23 +94,13 @@ enum insn_code movcc_gen_code[NUM_MACHINE_MODES]; enum insn_code vcond_gen_code[NUM_MACHINE_MODES]; enum insn_code vcondu_gen_code[NUM_MACHINE_MODES]; -/* The insn generating function can not take an rtx_code argument. - TRAP_RTX is used as an rtx argument. Its code is replaced with - the code to be used in the trap insn and all other fields are ignored. */ -static GTY(()) rtx trap_rtx; - -static void prepare_float_lib_cmp (rtx *, rtx *, enum rtx_code *, - enum machine_mode *, int *); +static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *, + enum machine_mode *); static rtx expand_unop_direct (enum machine_mode, optab, rtx, rtx, int); /* Debug facility for use in GDB. */ void debug_optab_libfuncs (void); -#ifndef HAVE_conditional_trap -#define HAVE_conditional_trap 0 -#define gen_conditional_trap(a,b) (gcc_unreachable (), NULL_RTX) -#endif - /* Prefixes for the current version of decimal floating point (BID vs. DPD) */ #if ENABLE_DECIMAL_BID_FORMAT #define DECIMAL_PREFIX "bid_" @@ -2295,12 +2274,12 @@ sign_expand_binop (enum machine_mode mode, optab uoptab, optab soptab, if (temp || methods == OPTAB_WIDEN) return temp; - /* Use the right width lib call if that exists. */ + /* Use the right width libcall if that exists. */ temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB); if (temp || methods == OPTAB_LIB) return temp; - /* Must widen and use a lib call, use either signed or unsigned. */ + /* Must widen and use a libcall, use either signed or unsigned. */ temp = expand_binop (mode, &wide_soptab, op0, op1, target, unsignedp, methods); if (temp != 0) @@ -3985,16 +3964,6 @@ can_compare_p (enum rtx_code code, enum machine_mode mode, { int icode; - if (optab_handler (cmp_optab, mode)->insn_code != CODE_FOR_nothing) - { - if (purpose == ccp_jump) - return bcc_gen_fctn[(int) code] != NULL; - else if (purpose == ccp_store_flag) - return setcc_gen_code[(int) code] != CODE_FOR_nothing; - else - /* There's only one cmov entry point, and it's allowed to fail. */ - return 1; - } if (purpose == ccp_jump && (icode = optab_handler (cbranch_optab, mode)->insn_code) != CODE_FOR_nothing && insn_data[icode].operand[0].predicate (test, mode)) @@ -4020,7 +3989,7 @@ can_compare_p (enum rtx_code code, enum machine_mode mode, *PMODE is the mode of the inputs (in case they are const_int). *PUNSIGNEDP nonzero says that the operands are unsigned; - this matters if they need to be widened. + this matters if they need to be widened (as given by METHODS). If they have mode BLKmode, then SIZE specifies the size of both operands. @@ -4033,14 +4002,18 @@ can_compare_p (enum rtx_code code, enum machine_mode mode, comparisons must have already been folded. */ static void -prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size, - enum machine_mode *pmode, int *punsignedp, - enum can_compare_purpose purpose) +prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, + int unsignedp, enum optab_methods methods, + rtx *ptest, enum machine_mode *pmode) { enum machine_mode mode = *pmode; - rtx x = *px, y = *py; - int unsignedp = *punsignedp; - rtx libfunc; + rtx libfunc, test; + enum machine_mode cmp_mode; + enum mode_class mclass; + + /* The other methods are not needed. */ + gcc_assert (methods == OPTAB_DIRECT || methods == OPTAB_WIDEN + || methods == OPTAB_LIB_WIDEN); #ifdef HAVE_cc0 /* Make sure if we have a canonical comparison. The RTL @@ -4052,12 +4025,14 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size, /* Don't let both operands fail to indicate the mode. */ if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode) x = force_reg (mode, x); + if (mode == VOIDmode) + mode = GET_MODE (x) != VOIDmode ? GET_MODE (x) : GET_MODE (y); /* Handle all BLKmode compares. */ if (mode == BLKmode) { - enum machine_mode cmp_mode, result_mode; + enum machine_mode result_mode; enum insn_code cmp_code; tree length_type; rtx libfunc; @@ -4093,12 +4068,14 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size, size = convert_to_mode (cmp_mode, size, 1); emit_insn (GEN_FCN (cmp_code) (result, x, y, size, opalign)); - *px = result; - *py = const0_rtx; - *pmode = result_mode; + *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, result, const0_rtx); + *pmode = result_mode; return; } + if (methods != OPTAB_LIB && methods != OPTAB_LIB_WIDEN) + goto fail; + /* Otherwise call a library function, memcmp. */ libfunc = memcmp_libfunc; length_type = sizetype; @@ -4112,8 +4089,8 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size, XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, size, cmp_mode); - *px = result; - *py = const0_rtx; + + *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, result, const0_rtx); *pmode = result_mode; return; } @@ -4128,22 +4105,58 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size, y = force_reg (mode, y); } - *px = x; - *py = y; if (GET_MODE_CLASS (mode) == MODE_CC) { - gcc_assert (can_compare_p (*pcomparison, CCmode, purpose)); + gcc_assert (can_compare_p (comparison, CCmode, ccp_jump)); + *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, x, y); return; } - else if (can_compare_p (*pcomparison, mode, purpose)) - return; - /* Handle a lib call just for the mode we are using. */ - libfunc = optab_libfunc (cmp_optab, mode); - if (libfunc && !SCALAR_FLOAT_MODE_P (mode)) + mclass = GET_MODE_CLASS (mode); + test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y); + cmp_mode = mode; + do + { + enum insn_code icode; + icode = optab_handler (cbranch_optab, cmp_mode)->insn_code; + if (icode != CODE_FOR_nothing + && insn_data[icode].operand[0].predicate (test, VOIDmode)) + { + rtx last = get_last_insn (); + rtx op0 = prepare_operand (icode, x, 1, mode, cmp_mode, unsignedp); + rtx op1 = prepare_operand (icode, y, 2, mode, cmp_mode, unsignedp); + if (op0 && op1 + && insn_data[icode].operand[1].predicate + (op0, insn_data[icode].operand[1].mode) + && insn_data[icode].operand[2].predicate + (op1, insn_data[icode].operand[2].mode)) + { + XEXP (test, 0) = op0; + XEXP (test, 1) = op1; + *ptest = test; + *pmode = cmp_mode; + return; + } + delete_insns_since (last); + } + + if (methods == OPTAB_DIRECT || !CLASS_HAS_WIDER_MODES_P (mclass)) + break; + cmp_mode = GET_MODE_WIDER_MODE (cmp_mode); + } + while (cmp_mode != VOIDmode); + + if (methods != OPTAB_LIB_WIDEN) + goto fail; + + if (!SCALAR_FLOAT_MODE_P (mode)) { rtx result; + /* Handle a libcall just for the mode we are using. */ + libfunc = optab_libfunc (cmp_optab, mode); + gcc_assert (libfunc); + /* If we want unsigned, and this mode has a distinct unsigned comparison routine, use that. */ if (unsignedp) @@ -4165,22 +4178,28 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size, case. For unsigned comparisons always compare against 1 after biasing the unbiased result by adding 1. This gives us a way to represent LTU. */ - *px = result; - *pmode = word_mode; - *py = const1_rtx; + x = result; + y = const1_rtx; if (!TARGET_LIB_INT_CMP_BIASED) { - if (*punsignedp) - *px = plus_constant (result, 1); + if (unsignedp) + x = plus_constant (result, 1); else - *py = const0_rtx; + y = const0_rtx; } - return; + + *pmode = word_mode; + prepare_cmp_insn (x, y, comparison, NULL_RTX, unsignedp, methods, + ptest, pmode); } + else + prepare_float_lib_cmp (x, y, comparison, ptest, pmode); - gcc_assert (SCALAR_FLOAT_MODE_P (mode)); - prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp); + return; + + fail: + *ptest = NULL_RTX; } /* Before emitting an insn with code ICODE, make sure that X, which is going @@ -4188,7 +4207,7 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size, WIDER_MODE (UNSIGNEDP determines whether it is an unsigned conversion), and that it is accepted by the operand predicate. Return the new value. */ -static rtx +rtx prepare_operand (int icode, rtx x, int opnum, enum machine_mode mode, enum machine_mode wider_mode, int unsignedp) { @@ -4207,71 +4226,22 @@ prepare_operand (int icode, rtx x, int opnum, enum machine_mode mode, } /* Subroutine of emit_cmp_and_jump_insns; this function is called when we know - we can do the comparison. - The arguments are the same as for emit_cmp_and_jump_insns; but LABEL may - be NULL_RTX which indicates that only a comparison is to be generated. */ + we can do the branch. */ static void -emit_cmp_and_jump_insn_1 (rtx x, rtx y, enum machine_mode mode, - enum rtx_code comparison, int unsignedp, rtx label) +emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label) { - rtx test = gen_rtx_fmt_ee (comparison, mode, x, y); - enum mode_class mclass = GET_MODE_CLASS (mode); - enum machine_mode wider_mode = mode; - - /* Try combined insns first. */ - do - { - enum machine_mode optab_mode = mclass == MODE_CC ? CCmode : wider_mode; - enum insn_code icode; - PUT_MODE (test, wider_mode); - - if (label) - { - icode = optab_handler (cbranch_optab, optab_mode)->insn_code; - - if (icode != CODE_FOR_nothing - && insn_data[icode].operand[0].predicate (test, wider_mode)) - { - x = prepare_operand (icode, x, 1, mode, wider_mode, unsignedp); - y = prepare_operand (icode, y, 2, mode, wider_mode, unsignedp); - emit_jump_insn (GEN_FCN (icode) (test, x, y, label)); - return; - } - } - - /* Handle some compares against zero. */ - icode = optab_handler (tst_optab, optab_mode)->insn_code; - if (y == CONST0_RTX (mode) && icode != CODE_FOR_nothing) - { - x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp); - emit_insn (GEN_FCN (icode) (x)); - if (label) - emit_jump_insn (bcc_gen_fctn[(int) comparison] (label)); - return; - } - - /* Handle compares for which there is a directly suitable insn. */ - - icode = optab_handler (cmp_optab, optab_mode)->insn_code; - if (icode != CODE_FOR_nothing) - { - x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp); - y = prepare_operand (icode, y, 1, mode, wider_mode, unsignedp); - emit_insn (GEN_FCN (icode) (x, y)); - if (label) - emit_jump_insn (bcc_gen_fctn[(int) comparison] (label)); - return; - } - - if (!CLASS_HAS_WIDER_MODES_P (mclass)) - break; + enum machine_mode optab_mode; + enum mode_class mclass; + enum insn_code icode; - wider_mode = GET_MODE_WIDER_MODE (wider_mode); - } - while (wider_mode != VOIDmode); + mclass = GET_MODE_CLASS (mode); + optab_mode = (mclass == MODE_CC) ? CCmode : mode; + icode = optab_handler (cbranch_optab, optab_mode)->insn_code; - gcc_unreachable (); + gcc_assert (icode != CODE_FOR_nothing); + gcc_assert (insn_data[icode].operand[0].predicate (test, VOIDmode)); + emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0), XEXP (test, 1), label)); } /* Generate code to compare X with Y so that the condition codes are @@ -4280,32 +4250,27 @@ emit_cmp_and_jump_insn_1 (rtx x, rtx y, enum machine_mode mode, ensure that the comparison RTL has the canonical form. UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they - need to be widened by emit_cmp_insn. UNSIGNEDP is also used to select - the proper branch condition code. + need to be widened. UNSIGNEDP is also used to select the proper + branch condition code. If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y. MODE is the mode of the inputs (in case they are const_int). - COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). It will - be passed unchanged to emit_cmp_insn, then potentially converted into an - unsigned variant based on UNSIGNEDP to select a proper jump instruction. */ + COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). + It will be potentially converted into an unsigned variant based on + UNSIGNEDP to select a proper jump instruction. */ void emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size, enum machine_mode mode, int unsignedp, rtx label) { rtx op0 = x, op1 = y; + rtx test; /* Swap operands and condition to ensure canonical RTL. */ if (swap_commutative_operands_p (x, y)) { - /* If we're not emitting a branch, callers are required to pass - operands in an order conforming to canonical RTL. We relax this - for commutative comparisons so callers using EQ don't need to do - swapping by hand. */ - gcc_assert (label || (comparison == swap_condition (comparison))); - op0 = y, op1 = x; comparison = swap_condition (comparison); } @@ -4320,32 +4285,21 @@ emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size, if (unsignedp) comparison = unsigned_condition (comparison); - prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp, - ccp_jump); - emit_cmp_and_jump_insn_1 (op0, op1, mode, comparison, unsignedp, label); + prepare_cmp_insn (op0, op1, comparison, size, unsignedp, OPTAB_LIB_WIDEN, + &test, &mode); + emit_cmp_and_jump_insn_1 (test, mode, label); } -/* Like emit_cmp_and_jump_insns, but generate only the comparison. */ - -void -emit_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, - enum machine_mode mode, int unsignedp) -{ - emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, 0); -} /* Emit a library call comparison between floating point X and Y. COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */ static void -prepare_float_lib_cmp (rtx *px, rtx *py, enum rtx_code *pcomparison, - enum machine_mode *pmode, int *punsignedp) +prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison, + rtx *ptest, enum machine_mode *pmode) { - enum rtx_code comparison = *pcomparison; enum rtx_code swapped = swap_condition (comparison); enum rtx_code reversed = reverse_condition_maybe_unordered (comparison); - rtx x = *px; - rtx y = *py; enum machine_mode orig_mode = GET_MODE (x); enum machine_mode mode, cmp_mode; rtx value, target, insns, equiv; @@ -4455,11 +4409,8 @@ prepare_float_lib_cmp (rtx *px, rtx *py, enum rtx_code *pcomparison, || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison)) comparison = reversed_p ? EQ : NE; - *px = target; - *py = const0_rtx; + *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, target, const0_rtx); *pmode = cmp_mode; - *pcomparison = comparison; - *punsignedp = 0; } /* Generate code to indirectly jump to a location given in the rtx LOC. */ @@ -4559,27 +4510,38 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1, (op3, insn_data[icode].operand[3].mode)) op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3); - /* Everything should now be in the suitable form, so emit the compare insn - and then the conditional move. */ + /* Everything should now be in the suitable form. */ - comparison - = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX); + code = unsignedp ? unsigned_condition (code) : code; + comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1); - /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)? */ /* We can get const0_rtx or const_true_rtx in some circumstances. Just return NULL and let the caller figure out how best to deal with this situation. */ - if (GET_CODE (comparison) != code) + if (!COMPARISON_P (comparison)) return NULL_RTX; - insn = GEN_FCN (icode) (subtarget, comparison, op2, op3); + do_pending_stack_adjust (); + start_sequence (); + prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1), + GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN, + &comparison, &cmode); + if (!comparison) + insn = NULL_RTX; + else + insn = GEN_FCN (icode) (subtarget, comparison, op2, op3); /* If that failed, then give up. */ if (insn == 0) - return 0; + { + end_sequence (); + return 0; + } emit_insn (insn); - + insn = get_insns (); + end_sequence (); + emit_insn (insn); if (subtarget != target) convert_move (target, subtarget, 0); @@ -4687,27 +4649,38 @@ emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1, (op3, insn_data[icode].operand[3].mode)) op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3); - /* Everything should now be in the suitable form, so emit the compare insn - and then the conditional move. */ + /* Everything should now be in the suitable form. */ - comparison - = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX); + code = unsignedp ? unsigned_condition (code) : code; + comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1); - /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)? */ /* We can get const0_rtx or const_true_rtx in some circumstances. Just return NULL and let the caller figure out how best to deal with this situation. */ - if (GET_CODE (comparison) != code) + if (!COMPARISON_P (comparison)) return NULL_RTX; - insn = GEN_FCN (icode) (subtarget, comparison, op2, op3); + do_pending_stack_adjust (); + start_sequence (); + prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1), + GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN, + &comparison, &cmode); + if (!comparison) + insn = NULL_RTX; + else + insn = GEN_FCN (icode) (subtarget, comparison, op2, op3); /* If that failed, then give up. */ if (insn == 0) - return 0; + { + end_sequence (); + return 0; + } emit_insn (insn); - + insn = get_insns (); + end_sequence (); + emit_insn (insn); if (subtarget != target) convert_move (target, subtarget, 0); @@ -6155,9 +6128,6 @@ init_optabs (void) libfunc_hash = htab_create_ggc (10, hash_libfunc, eq_libfunc, NULL); /* Start by initializing all tables to contain CODE_FOR_nothing. */ - for (i = 0; i < NUM_RTX_CODE; i++) - setcc_gen_code[i] = CODE_FOR_nothing; - #ifdef HAVE_conditional_move for (i = 0; i < NUM_MACHINE_MODES; i++) movcc_gen_code[i] = CODE_FOR_nothing; @@ -6235,12 +6205,16 @@ init_optabs (void) have_insn_for. */ init_optab (mov_optab, SET); init_optab (movstrict_optab, STRICT_LOW_PART); - init_optab (cmp_optab, COMPARE); + init_optab (cbranch_optab, COMPARE); + + init_optab (cmov_optab, UNKNOWN); + init_optab (cstore_optab, UNKNOWN); + init_optab (ctrap_optab, UNKNOWN); init_optab (storent_optab, UNKNOWN); + init_optab (cmp_optab, UNKNOWN); init_optab (ucmp_optab, UNKNOWN); - init_optab (tst_optab, UNKNOWN); init_optab (eq_optab, EQ); init_optab (ne_optab, NE); @@ -6296,9 +6270,6 @@ init_optabs (void) init_optab (isinf_optab, UNKNOWN); init_optab (strlen_optab, UNKNOWN); - init_optab (cbranch_optab, UNKNOWN); - init_optab (cmov_optab, UNKNOWN); - init_optab (cstore_optab, UNKNOWN); init_optab (push_optab, UNKNOWN); init_optab (reduc_smax_optab, UNKNOWN); @@ -6648,9 +6619,6 @@ init_optabs (void) gcov_flush_libfunc = init_one_libfunc ("__gcov_flush"); - if (HAVE_conditional_trap) - trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX); - /* Allow the target to add more libcalls or rename some, etc. */ targetm.init_libfuncs (); @@ -6714,43 +6682,45 @@ debug_optab_libfuncs (void) CODE. Return 0 on failure. */ rtx -gen_cond_trap (enum rtx_code code ATTRIBUTE_UNUSED, rtx op1, - rtx op2 ATTRIBUTE_UNUSED, rtx tcode ATTRIBUTE_UNUSED) +gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode) { enum machine_mode mode = GET_MODE (op1); enum insn_code icode; rtx insn; - - if (!HAVE_conditional_trap) - return 0; + rtx trap_rtx; if (mode == VOIDmode) return 0; - icode = optab_handler (cmp_optab, mode)->insn_code; + icode = optab_handler (ctrap_optab, mode)->insn_code; if (icode == CODE_FOR_nothing) return 0; + /* Some targets only accept a zero trap code. */ + if (insn_data[icode].operand[3].predicate + && !insn_data[icode].operand[3].predicate (tcode, VOIDmode)) + return 0; + + do_pending_stack_adjust (); start_sequence (); - op1 = prepare_operand (icode, op1, 0, mode, mode, 0); - op2 = prepare_operand (icode, op2, 1, mode, mode, 0); - if (!op1 || !op2) + prepare_cmp_insn (op1, op2, code, NULL_RTX, false, OPTAB_DIRECT, + &trap_rtx, &mode); + if (!trap_rtx) + insn = NULL_RTX; + else + insn = GEN_FCN (icode) (trap_rtx, XEXP (trap_rtx, 0), XEXP (trap_rtx, 1), + tcode); + + /* If that failed, then give up. */ + if (insn == 0) { end_sequence (); return 0; } - emit_insn (GEN_FCN (icode) (op1, op2)); - PUT_CODE (trap_rtx, code); - gcc_assert (HAVE_conditional_trap); - insn = gen_conditional_trap (trap_rtx, tcode); - if (insn) - { - emit_insn (insn); - insn = get_insns (); - } + emit_insn (insn); + insn = get_insns (); end_sequence (); - return insn; } @@ -7023,9 +6993,9 @@ expand_bool_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target) emit_insn (seq); if (cc_reg) - return emit_store_flag (target, EQ, cc_reg, const0_rtx, VOIDmode, 0, 1); + return emit_store_flag_force (target, EQ, cc_reg, const0_rtx, VOIDmode, 0, 1); else - return emit_store_flag (target, EQ, subtarget, old_val, VOIDmode, 1, 1); + return emit_store_flag_force (target, EQ, subtarget, old_val, VOIDmode, 1, 1); } /* This is a helper function for the other atomic operations. This function diff --git a/gcc/optabs.h b/gcc/optabs.h index a518dc6ab86..f4ddfa1480b 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -36,8 +36,7 @@ along with GCC; see the file COPYING3. If not see The `lib_call' slot is the name of the library function that can be used to perform the operation. - A few optabs, such as move_optab and cmp_optab, are used - by special code. */ + A few optabs, such as move_optab, are used by special code. */ struct optab_handlers { @@ -271,12 +270,9 @@ enum optab_index /* Test for infinite value */ OTI_isinf, - /* Compare insn; two operands. */ + /* Compare insn; two operands. Used only for libcalls. */ OTI_cmp, - /* Used only for libcalls for unsigned comparisons. */ OTI_ucmp, - /* tst insn; compare one operand against 0 */ - OTI_tst, /* Floating point comparison optabs - used primarily for libfuncs */ OTI_eq, @@ -290,10 +286,11 @@ enum optab_index /* String length */ OTI_strlen, - /* Combined compare & jump/store flags/move operations. */ + /* Combined compare & jump/move/store flags/trap operations. */ OTI_cbranch, OTI_cmov, OTI_cstore, + OTI_ctrap, /* Push instruction. */ OTI_push, @@ -484,7 +481,6 @@ extern struct optab optab_table[OTI_MAX]; #define cmp_optab (&optab_table[OTI_cmp]) #define ucmp_optab (&optab_table[OTI_ucmp]) -#define tst_optab (&optab_table[OTI_tst]) #define eq_optab (&optab_table[OTI_eq]) #define ne_optab (&optab_table[OTI_ne]) @@ -499,6 +495,8 @@ extern struct optab optab_table[OTI_MAX]; #define cbranch_optab (&optab_table[OTI_cbranch]) #define cmov_optab (&optab_table[OTI_cmov]) #define cstore_optab (&optab_table[OTI_cstore]) +#define ctrap_optab (&optab_table[OTI_ctrap]) + #define push_optab (&optab_table[OTI_push]) #define addcc_optab (&optab_table[OTI_addcc]) @@ -605,17 +603,6 @@ extern optab code_to_optab[NUM_RTX_CODE + 1]; typedef rtx (*rtxfun) (rtx); -/* Indexed by the rtx-code for a conditional (e.g. EQ, LT,...) - gives the gen_function to make a branch to test that condition. */ - -extern rtxfun bcc_gen_fctn[NUM_RTX_CODE]; - -/* Indexed by the rtx-code for a conditional (e.g. EQ, LT,...) - gives the insn code to make a store-condition insn - to test that condition. */ - -extern enum insn_code setcc_gen_code[NUM_RTX_CODE]; - #ifdef HAVE_conditional_move /* Indexed by the machine mode, gives the insn code to make a conditional move insn. */ @@ -723,10 +710,6 @@ extern rtx expand_copysign (rtx, rtx, rtx); extern void emit_unop_insn (int, rtx, rtx, enum rtx_code); extern bool maybe_emit_unop_insn (int, rtx, rtx, enum rtx_code); -/* Emit one rtl insn to compare two rtx's. */ -extern void emit_cmp_insn (rtx, rtx, enum rtx_code, rtx, enum machine_mode, - int); - /* An extra flag to control optab_for_tree_code's behavior. This is needed to distinguish between machines with a vector shift that takes a scalar for the shift amount vs. machines that take a vector for the shift amount. */ diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index e2b1673a8dd..667b5b5c898 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -1739,18 +1739,6 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, break; case COMPARE: -#ifdef HAVE_cc0 - /* Convert (compare FOO (const_int 0)) to FOO unless we aren't - using cc0, in which case we want to leave it as a COMPARE - so we can distinguish it from a register-register-copy. - - In IEEE floating point, x-0 is not the same as x. */ - if (!(HONOR_SIGNED_ZEROS (mode) - && HONOR_SIGN_DEPENDENT_ROUNDING (mode)) - && trueop1 == CONST0_RTX (mode)) - return op0; -#endif - /* Convert (compare (gt (flags) 0) (lt (flags) 0)) to (flags). */ if (((GET_CODE (op0) == GT && GET_CODE (op1) == LT) || (GET_CODE (op0) == GTU && GET_CODE (op1) == LTU)) @@ -3815,8 +3803,8 @@ simplify_relational_operation (enum rtx_code code, enum machine_mode mode, /* If op0 is a compare, extract the comparison arguments from it. */ if (GET_CODE (op0) == COMPARE && op1 == const0_rtx) - return simplify_relational_operation (code, mode, VOIDmode, - XEXP (op0, 0), XEXP (op0, 1)); + return simplify_gen_relational (code, mode, VOIDmode, + XEXP (op0, 0), XEXP (op0, 1)); if (GET_MODE_CLASS (cmp_mode) == MODE_CC || CC0_P (op0)) -- 2.11.0