* final.c (final_scan_insn): CalL CC_STATUS_INIT unconditionally. * config/arm/arm.c (thumb1_code): New variable. (arm_override_options): Set it. (thumb1_final_prescan_insn): Keep track of condition code status. (arm_adjust_cost): For Thumb, try to keep cc-setting insns next to jumps that depend on them. * config/arm/arm.h (thumb1_code): Declare variable. (struct machine_function): Guard with #ifndef GENERATOR_FILE. Add members thumb1_cc_insn, thumb1_cc_op0, thumb1_cc_op1 and thumb1_cc_mode. (CC_STATUS_INIT): New macro. * config/arm/constraints.md (Pc): New constraint. * config/arm/predicates.md (noov_comparison_operator): New predicate. * config/arm/arm.md (is_thumb1): New define_attr. (conds): Set default to "clob" when generating Thumb1 code. (thumb1_bicsi3): Renamed from bicsi3. All uses changed. Condition code are set. Use two-operand assembly syntax. (thumb1_subsi3_insn): Condition codes are set. Now a properly named pattern. (thumb1_andsi3_insn, thumb1_iorsi3_insn, thumb1_xorsi3_insn): Condition codes are set. Use two-operand assembly syntax. (zero_extendhisi splitter): Remove constraints. (thumb1_movsi_insn, thumb1_movhi_insn, thumb1_movqi_insn, thumb1_movhf, thumb1_movsf_insn): Set conds attribute as appropriate. (cbranchsi4_insn): Use condition code status from struct machine_function to determine whether the comparison can be eliminated. Discourage the alternative using high registers. (movsi_cbranchsi4, andsi3_cbranch, orrsi3_cbranch_scratch, orrsi3_cbranch, xorsi3_cbranch_scratch, xorsi3_cbranch, bicsi3_cbranch_scratch, bicsi3_cbranch, subsi3_cbranch_scratch, subsi3_cbranch): Delete. (movsi_cbranchsi4 peepholes): Rewrite to generate a sequence of one subtract and one cbranch insn. Index: final.c =================================================================== --- final.c (revision 161824) +++ final.c (working copy) @@ -2044,9 +2044,7 @@ final_scan_insn (rtx insn, FILE *file, i #endif } } -#ifdef HAVE_cc0 CC_STATUS_INIT; -#endif if (!DECL_IGNORED_P (current_function_decl) && LABEL_NAME (insn)) debug_hooks->label (insn); Index: config/arm/arm.c =================================================================== --- config/arm/arm.c (revision 161831) +++ config/arm/arm.c (working copy) @@ -685,6 +685,9 @@ int arm_tune_cortex_a9 = 0; /* Nonzero if generating Thumb instructions. */ int thumb_code = 0; +/* Nonzero if generating Thumb-1 instructions. */ +int thumb1_code = 0; + /* Nonzero if we should define __THUMB_INTERWORK__ in the preprocessor. XXX This is a bit of a hack, it's intended to help work around @@ -716,6 +719,7 @@ static enum arm_pcs arm_pcs_default; int arm_ccfsm_state; /* arm_current_cc is also used for Thumb-2 cond_exec blocks. */ enum arm_cond_code arm_current_cc; + rtx arm_target_insn; int arm_target_label; /* The number of conditionally executed insns, including the current insn. */ @@ -1570,7 +1574,8 @@ arm_override_options (void) arm_ld_sched = (tune_flags & FL_LDSCHED) != 0; arm_tune_strongarm = (tune_flags & FL_STRONG) != 0; - thumb_code = (TARGET_ARM == 0); + thumb_code = TARGET_ARM == 0; + thumb1_code = TARGET_THUMB1 != 0; arm_tune_wbuf = (tune_flags & FL_WBUF) != 0; arm_tune_xscale = (tune_flags & FL_XSCALE) != 0; arm_arch_iwmmxt = (insn_flags & FL_IWMMXT) != 0; @@ -7658,12 +7663,26 @@ arm_address_cost (rtx x, bool speed ATTR { return TARGET_32BIT ? arm_arm_address_cost (x) : arm_thumb_address_cost (x); } - +/* This function implements the target macro TARGET_SCHED_ADJUST_COST. + It corrects the value of COST based on the relationship between + INSN and DEP through the dependence LINK. It returns the new + value. */ + static int arm_adjust_cost (rtx insn, rtx link, rtx dep, int cost) { rtx i_pat, d_pat; + /* When generating Thumb-1 code, we want to place flag-setting operations + close to a conditional branch which depends on them, so that we can + omit the comparison. */ + if (TARGET_THUMB1 + && REG_NOTE_KIND (link) == 0 + && recog_memoized (insn) == CODE_FOR_cbranchsi4_insn + && recog_memoized (dep) >= 0 + && get_attr_conds (dep) == CONDS_SET) + return 0; + /* Some true dependencies can have a higher cost depending on precisely how certain input operands are used. */ if (arm_tune_xscale @@ -19449,14 +19468,45 @@ thumb_exit (FILE *f, int reg_containing_ /* Return to caller. */ asm_fprintf (f, "\tbx\t%r\n", reg_containing_return_addr); } - +/* Scan INSN just before assembler is output for it. + For Thumb-1, we track the status of the condition codes; this + information is used in the cbranchsi4_insn pattern. */ void thumb1_final_prescan_insn (rtx insn) { if (flag_print_asm_name) asm_fprintf (asm_out_file, "%@ 0x%04x\n", INSN_ADDRESSES (INSN_UID (insn))); + /* Don't overwrite the previous setter when we get to a cbranch. */ + if (INSN_CODE (insn) != CODE_FOR_cbranchsi4_insn) + { + enum attr_conds conds; + + if (cfun->machine->thumb1_cc_insn) + { + if (modified_in_p (cfun->machine->thumb1_cc_op0, insn) + || modified_in_p (cfun->machine->thumb1_cc_op1, insn)) + CC_STATUS_INIT; + } + conds = get_attr_conds (insn); + if (conds == CONDS_SET) + { + rtx set = single_set (insn); + cfun->machine->thumb1_cc_insn = insn; + cfun->machine->thumb1_cc_op0 = SET_DEST (set); + cfun->machine->thumb1_cc_op1 = const0_rtx; + cfun->machine->thumb1_cc_mode = CC_NOOVmode; + if (INSN_CODE (insn) == CODE_FOR_thumb1_subsi3_insn) + { + rtx src1 = XEXP (SET_SRC (set), 1); + if (src1 == const0_rtx) + cfun->machine->thumb1_cc_mode = CCmode; + } + } + else if (conds != CONDS_NOCOND) + cfun->machine->thumb1_cc_insn = NULL_RTX; + } } int Index: config/arm/arm.h =================================================================== --- config/arm/arm.h (revision 161824) +++ config/arm/arm.h (working copy) @@ -406,9 +406,12 @@ extern int arm_arch7em; /* Nonzero if this chip can benefit from load scheduling. */ extern int arm_ld_sched; -/* Nonzero if generating thumb code. */ +/* Nonzero if generating Thumb code, either Thumb-1 or Thumb-2. */ extern int thumb_code; +/* Nonzero if generating Thumb-1 code. */ +extern int thumb1_code; + /* Nonzero if this chip is a StrongARM. */ extern int arm_tune_strongarm; @@ -1587,6 +1590,7 @@ typedef struct GTY(()) arm_stack_offsets } arm_stack_offsets; +#ifndef GENERATOR_FILE /* A C structure for machine-specific, per-function data. This is added to the cfun structure. */ typedef struct GTY(()) machine_function @@ -1617,8 +1621,16 @@ typedef struct GTY(()) machine_function /* Set to 1 when a return insn is output, this means that the epilogue is not needed. */ int return_used_this_function; + /* When outputting Thumb-1 code, record the last insn that provides + information about condition codes, and the comparison operands. */ + rtx thumb1_cc_insn; + rtx thumb1_cc_op0; + rtx thumb1_cc_op1; + /* Also record the CC mode that is supported. */ + enum machine_mode thumb1_cc_mode; } machine_function; +#endif /* As in the machine_function, a global set of call-via labels, for code that is in text_section. */ @@ -2250,6 +2262,9 @@ extern int making_const_table; #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1) #define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1) +#define CC_STATUS_INIT \ + do { cfun->machine->thumb1_cc_insn = NULL_RTX; } while (0) + #undef ASM_APP_OFF #define ASM_APP_OFF (TARGET_THUMB1 ? "\t.code\t16\n" : \ TARGET_THUMB2 ? "\t.thumb\n" : "") Index: config/arm/constraints.md =================================================================== --- config/arm/constraints.md (revision 161824) +++ config/arm/constraints.md (working copy) @@ -148,6 +148,11 @@ (define_constraint "Pb" (match_test "TARGET_THUMB1 && ival >= -262 && ival <= 262 && (ival > 255 || ival < -255)"))) +(define_constraint "Pc" + "@internal In Thumb-1 state a constant in the range 0 to 7" + (and (match_code "const_int") + (match_test "TARGET_THUMB1 && ival >= 0 && ival <= 7"))) + (define_constraint "Ps" "@internal In Thumb-2 state a constant in the range -255 to +255" (and (match_code "const_int") Index: config/arm/predicates.md =================================================================== --- config/arm/predicates.md (revision 161824) +++ config/arm/predicates.md (working copy) @@ -235,6 +235,9 @@ (define_special_predicate "arm_compariso (define_special_predicate "lt_ge_comparison_operator" (match_code "lt,ge")) +(define_special_predicate "noov_comparison_operator" + (match_code "lt,ge,eq,ne")) + (define_special_predicate "minmax_operator" (and (match_code "smin,smax,umin,umax") (match_test "mode == GET_MODE (op)"))) Index: config/arm/arm.md =================================================================== --- config/arm/arm.md (revision 161831) +++ config/arm/arm.md (working copy) @@ -151,6 +151,9 @@ (define_attr "is_thumb" "no,yes" (const ; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6. (define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6"))) +; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code. +(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code"))) + ;; Operand number of an input operand that is shifted. Zero if the ;; given instruction does not shift one of its input operands. (define_attr "shift" "" (const_int 0)) @@ -339,7 +342,9 @@ (define_attr "neon_type" ; output of this insn (define_attr "conds" "use,set,clob,unconditional,nocond" - (if_then_else (eq_attr "type" "call") + (if_then_else + (ior (eq_attr "is_thumb1" "yes") + (eq_attr "type" "call")) (const_string "clob") (if_then_else (eq_attr "neon_type" "none") (const_string "nocond") @@ -1077,14 +1082,14 @@ (define_expand "subsi3" " ) -(define_insn "*thumb1_subsi3_insn" +(define_insn "thumb1_subsi3_insn" [(set (match_operand:SI 0 "register_operand" "=l") (minus:SI (match_operand:SI 1 "register_operand" "l") - (match_operand:SI 2 "register_operand" "l")))] + (match_operand:SI 2 "reg_or_int_operand" "lPc")))] "TARGET_THUMB1" "sub\\t%0, %1, %2" - [(set_attr "length" "2")] -) + [(set_attr "length" "2") + (set_attr "conds" "set")]) ; ??? Check Thumb-2 split length (define_insn_and_split "*arm_subsi3_insn" @@ -1959,7 +1964,7 @@ (define_expand "andsi3" operands[2] = force_reg (SImode, GEN_INT (~INTVAL (operands[2]))); - emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1])); + emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1])); DONE; } @@ -2020,9 +2025,9 @@ (define_insn "*thumb1_andsi3_insn" (and:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "register_operand" "l")))] "TARGET_THUMB1" - "and\\t%0, %0, %2" - [(set_attr "length" "2")] -) + "and\\t%0, %2" + [(set_attr "length" "2") + (set_attr "conds" "set")]) (define_insn "*andsi3_compare0" [(set (reg:CC_NOOV CC_REGNUM) @@ -2561,14 +2566,14 @@ (define_insn "andsi_notsi_si" [(set_attr "predicable" "yes")] ) -(define_insn "bicsi3" +(define_insn "thumb1_bicsi3" [(set (match_operand:SI 0 "register_operand" "=l") (and:SI (not:SI (match_operand:SI 1 "register_operand" "l")) (match_operand:SI 2 "register_operand" "0")))] "TARGET_THUMB1" - "bic\\t%0, %0, %1" - [(set_attr "length" "2")] -) + "bic\\t%0, %1" + [(set_attr "length" "2") + (set_attr "conds" "set")]) (define_insn "andsi_not_shiftsi_si" [(set (match_operand:SI 0 "s_register_operand" "=r") @@ -2703,14 +2708,14 @@ (define_insn_and_split "*arm_iorsi3" (set_attr "predicable" "yes")] ) -(define_insn "*thumb1_iorsi3" +(define_insn "*thumb1_iorsi3_insn" [(set (match_operand:SI 0 "register_operand" "=l") (ior:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "register_operand" "l")))] "TARGET_THUMB1" - "orr\\t%0, %0, %2" - [(set_attr "length" "2")] -) + "orr\\t%0, %2" + [(set_attr "length" "2") + (set_attr "conds" "set")]) (define_peephole2 [(match_scratch:SI 3 "r") @@ -2827,14 +2832,14 @@ (define_insn "*arm_xorsi3" [(set_attr "predicable" "yes")] ) -(define_insn "*thumb1_xorsi3" +(define_insn "*thumb1_xorsi3_insn" [(set (match_operand:SI 0 "register_operand" "=l") (xor:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "register_operand" "l")))] "TARGET_THUMB1" - "eor\\t%0, %0, %2" - [(set_attr "length" "2")] -) + "eor\\t%0, %2" + [(set_attr "length" "2") + (set_attr "conds" "set")]) (define_insn "*xorsi3_compare0" [(set (reg:CC_NOOV CC_REGNUM) @@ -3261,8 +3266,8 @@ (define_insn "*thumb1_ashlsi3" (match_operand:SI 2 "nonmemory_operand" "N,l")))] "TARGET_THUMB1" "lsl\\t%0, %1, %2" - [(set_attr "length" "2")] -) + [(set_attr "length" "2") + (set_attr "conds" "set")]) (define_expand "ashrdi3" [(set (match_operand:DI 0 "s_register_operand" "") @@ -3317,8 +3322,8 @@ (define_insn "*thumb1_ashrsi3" (match_operand:SI 2 "nonmemory_operand" "N,l")))] "TARGET_THUMB1" "asr\\t%0, %1, %2" - [(set_attr "length" "2")] -) + [(set_attr "length" "2") + (set_attr "conds" "set")]) (define_expand "lshrdi3" [(set (match_operand:DI 0 "s_register_operand" "") @@ -3376,8 +3381,8 @@ (define_insn "*thumb1_lshrsi3" (match_operand:SI 2 "nonmemory_operand" "N,l")))] "TARGET_THUMB1" "lsr\\t%0, %1, %2" - [(set_attr "length" "2")] -) + [(set_attr "length" "2") + (set_attr "conds" "set")]) (define_expand "rotlsi3" [(set (match_operand:SI 0 "s_register_operand" "") @@ -4026,7 +4031,7 @@ (define_expand "zero_extendhisi2" (define_split [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:HI 1 "register_operand" "l,m")))] + (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] "!TARGET_THUMB2 && !arm_arch6" [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))] @@ -5062,8 +5067,8 @@ (define_insn "*thumb1_movsi_insn" mov\\t%0, %1" [(set_attr "length" "2,2,4,4,2,2,2,2,2") (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*") - (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")] -) + (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*") + (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")]) (define_split [(set (match_operand:SI 0 "register_operand" "") @@ -5578,8 +5583,8 @@ (define_insn "*thumb1_movhi_insn" return \"ldrh %0, %1\"; }" [(set_attr "length" "2,4,2,2,2,2") - (set_attr "type" "*,load1,store1,*,*,*")] -) + (set_attr "type" "*,load1,store1,*,*,*") + (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")]) (define_expand "movhi_bytes" @@ -5812,8 +5817,8 @@ (define_insn "*thumb1_movqi_insn" mov\\t%0, %1" [(set_attr "length" "2") (set_attr "type" "*,load1,store1,*,*,*") - (set_attr "pool_range" "*,32,*,*,*,*")] -) + (set_attr "pool_range" "*,32,*,*,*,*") + (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")]) ;; HFmode moves (define_expand "movhf" @@ -5913,8 +5918,8 @@ (define_insn "*thumb1_movhf" " [(set_attr "length" "2") (set_attr "type" "*,load1,store1,*,*") - (set_attr "pool_range" "*,1020,*,*,*")] -) + (set_attr "pool_range" "*,1020,*,*,*") + (set_attr "conds" "clob,nocond,nocond,nocond,nocond")]) (define_expand "movsf" [(set (match_operand:SF 0 "general_operand" "") @@ -5989,7 +5994,8 @@ (define_insn "*thumb1_movsf_insn" mov\\t%0, %1" [(set_attr "length" "2") (set_attr "type" "*,load1,store1,load1,store1,*,*") - (set_attr "pool_range" "*,*,*,1020,*,*,*")] + (set_attr "pool_range" "*,*,*,1020,*,*,*") + (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")] ) (define_expand "movdf" @@ -6624,26 +6630,38 @@ (define_expand "cbranchdi4" (define_insn "cbranchsi4_insn" [(set (pc) (if_then_else (match_operator 0 "arm_comparison_operator" - [(match_operand:SI 1 "s_register_operand" "l,*h") + [(match_operand:SI 1 "s_register_operand" "l,?l*h") (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")]) (label_ref (match_operand 3 "" "")) (pc)))] "TARGET_THUMB1" - "* - rtx t = prev_nonnote_insn (insn); - if (t != NULL_RTX - && INSN_P (t) - && INSN_CODE (t) == CODE_FOR_cbranchsi4_insn) +{ + rtx t = cfun->machine->thumb1_cc_insn; + if (t != NULL_RTX) { - t = XEXP (SET_SRC (PATTERN (t)), 0); - if (!rtx_equal_p (XEXP (t, 0), operands[1]) - || !rtx_equal_p (XEXP (t, 1), operands[2])) + if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1]) + || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2])) + t = NULL_RTX; + if (cfun->machine->thumb1_cc_mode == CC_NOOVmode) + { + if (!noov_comparison_operator (operands[0], VOIDmode)) + t = NULL_RTX; + } + else if (cfun->machine->thumb1_cc_mode != CCmode) t = NULL_RTX; } - else - t = NULL_RTX; if (t == NULL_RTX) - output_asm_insn (\"cmp\\t%1, %2\", operands); + { + output_asm_insn ("cmp\t%1, %2", operands); + cfun->machine->thumb1_cc_insn = insn; + cfun->machine->thumb1_cc_op0 = operands[1]; + cfun->machine->thumb1_cc_op1 = operands[2]; + cfun->machine->thumb1_cc_mode = CCmode; + } + else + /* Ensure we emit the right type of condition code on the jump. */ + XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode, + CC_REGNUM); switch (get_attr_length (insn)) { @@ -6651,7 +6669,7 @@ (define_insn "cbranchsi4_insn" case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; } - " +} [(set (attr "far_jump") (if_then_else (eq_attr "length" "8") @@ -6705,69 +6723,8 @@ (define_insn "cbranchsi4_scratch" (const_int 8))))] ) -(define_insn "*movsi_cbranchsi4" - [(set (pc) - (if_then_else - (match_operator 3 "arm_comparison_operator" - [(match_operand:SI 1 "s_register_operand" "0,l,l,l") - (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc))) - (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m") - (match_dup 1))] - "TARGET_THUMB1" - "*{ - if (which_alternative == 0) - output_asm_insn (\"cmp\t%0, #0\", operands); - else if (which_alternative == 1) - output_asm_insn (\"sub\t%0, %1, #0\", operands); - else - { - output_asm_insn (\"cmp\t%1, #0\", operands); - if (which_alternative == 2) - output_asm_insn (\"mov\t%0, %1\", operands); - else - output_asm_insn (\"str\t%1, %0\", operands); - } - switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0)) - { - case 4: return \"b%d3\\t%l2\"; - case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\"; - default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\"; - } - }" - [(set (attr "far_jump") - (if_then_else - (ior (and (gt (symbol_ref ("which_alternative")) - (const_int 1)) - (eq_attr "length" "8")) - (eq_attr "length" "10")) - (const_string "yes") - (const_string "no"))) - (set (attr "length") - (if_then_else - (le (symbol_ref ("which_alternative")) - (const_int 1)) - (if_then_else - (and (ge (minus (match_dup 2) (pc)) (const_int -250)) - (le (minus (match_dup 2) (pc)) (const_int 256))) - (const_int 4) - (if_then_else - (and (ge (minus (match_dup 2) (pc)) (const_int -2040)) - (le (minus (match_dup 2) (pc)) (const_int 2048))) - (const_int 6) - (const_int 8))) - (if_then_else - (and (ge (minus (match_dup 2) (pc)) (const_int -248)) - (le (minus (match_dup 2) (pc)) (const_int 256))) - (const_int 6) - (if_then_else - (and (ge (minus (match_dup 2) (pc)) (const_int -2038)) - (le (minus (match_dup 2) (pc)) (const_int 2048))) - (const_int 8) - (const_int 10)))))] -) - +;; Two peepholes to generate subtract of 0 instead of a move if the +;; condition codes will be useful. (define_peephole2 [(set (match_operand:SI 0 "low_register_operand" "") (match_operand:SI 1 "low_register_operand" "")) @@ -6777,14 +6734,12 @@ (define_peephole2 (label_ref (match_operand 3 "" "")) (pc)))] "TARGET_THUMB1" - [(parallel - [(set (pc) - (if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)]) + [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0))) + (set (pc) + (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)]) (label_ref (match_dup 3)) - (pc))) - (set (match_dup 0) (match_dup 1))])] - "" -) + (pc)))] + "") ;; Sigh! This variant shouldn't be needed, but combine often fails to ;; merge cases like this because the op1 is a hard register in @@ -6798,14 +6753,12 @@ (define_peephole2 (label_ref (match_operand 3 "" "")) (pc)))] "TARGET_THUMB1" - [(parallel - [(set (pc) - (if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)]) + [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0))) + (set (pc) + (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)]) (label_ref (match_dup 3)) - (pc))) - (set (match_dup 0) (match_dup 1))])] - "" -) + (pc)))] + "") (define_insn "*negated_cbranchsi4" [(set (pc) @@ -6929,7 +6882,7 @@ (define_insn "*tlobits_cbranch" (const_int 6) (const_int 8))))] ) - + (define_insn "*tstsi3_cbranch" [(set (pc) (if_then_else @@ -6967,390 +6920,6 @@ (define_insn "*tstsi3_cbranch" (const_int 8))))] ) -(define_insn "*andsi3_cbranch" - [(set (pc) - (if_then_else - (match_operator 5 "equality_operator" - [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1") - (match_operand:SI 3 "s_register_operand" "l,l,l,l")) - (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc))) - (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") - (and:SI (match_dup 2) (match_dup 3))) - (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] - "TARGET_THUMB1" - "* - { - if (which_alternative == 0) - output_asm_insn (\"and\\t%0, %3\", operands); - else if (which_alternative == 1) - { - output_asm_insn (\"and\\t%1, %3\", operands); - output_asm_insn (\"mov\\t%0, %1\", operands); - } - else - { - output_asm_insn (\"and\\t%1, %3\", operands); - output_asm_insn (\"str\\t%1, %0\", operands); - } - - switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) - { - case 4: return \"b%d5\\t%l4\"; - case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; - default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; - } - }" - [(set (attr "far_jump") - (if_then_else - (ior (and (eq (symbol_ref ("which_alternative")) - (const_int 0)) - (eq_attr "length" "8")) - (eq_attr "length" "10")) - (const_string "yes") - (const_string "no"))) - (set (attr "length") - (if_then_else - (eq (symbol_ref ("which_alternative")) - (const_int 0)) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -250)) - (le (minus (match_dup 4) (pc)) (const_int 256))) - (const_int 4) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) - (le (minus (match_dup 4) (pc)) (const_int 2048))) - (const_int 6) - (const_int 8))) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -248)) - (le (minus (match_dup 4) (pc)) (const_int 256))) - (const_int 6) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) - (le (minus (match_dup 4) (pc)) (const_int 2048))) - (const_int 8) - (const_int 10)))))] -) - -(define_insn "*orrsi3_cbranch_scratch" - [(set (pc) - (if_then_else - (match_operator 4 "equality_operator" - [(ior:SI (match_operand:SI 1 "s_register_operand" "%0") - (match_operand:SI 2 "s_register_operand" "l")) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc))) - (clobber (match_scratch:SI 0 "=l"))] - "TARGET_THUMB1" - "* - { - output_asm_insn (\"orr\\t%0, %2\", operands); - switch (get_attr_length (insn)) - { - case 4: return \"b%d4\\t%l3\"; - case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; - default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; - } - }" - [(set (attr "far_jump") - (if_then_else - (eq_attr "length" "8") - (const_string "yes") - (const_string "no"))) - (set (attr "length") - (if_then_else - (and (ge (minus (match_dup 3) (pc)) (const_int -250)) - (le (minus (match_dup 3) (pc)) (const_int 256))) - (const_int 4) - (if_then_else - (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) - (le (minus (match_dup 3) (pc)) (const_int 2048))) - (const_int 6) - (const_int 8))))] -) - -(define_insn "*orrsi3_cbranch" - [(set (pc) - (if_then_else - (match_operator 5 "equality_operator" - [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1") - (match_operand:SI 3 "s_register_operand" "l,l,l,l")) - (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc))) - (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") - (ior:SI (match_dup 2) (match_dup 3))) - (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] - "TARGET_THUMB1" - "* - { - if (which_alternative == 0) - output_asm_insn (\"orr\\t%0, %3\", operands); - else if (which_alternative == 1) - { - output_asm_insn (\"orr\\t%1, %3\", operands); - output_asm_insn (\"mov\\t%0, %1\", operands); - } - else - { - output_asm_insn (\"orr\\t%1, %3\", operands); - output_asm_insn (\"str\\t%1, %0\", operands); - } - - switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) - { - case 4: return \"b%d5\\t%l4\"; - case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; - default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; - } - }" - [(set (attr "far_jump") - (if_then_else - (ior (and (eq (symbol_ref ("which_alternative")) - (const_int 0)) - (eq_attr "length" "8")) - (eq_attr "length" "10")) - (const_string "yes") - (const_string "no"))) - (set (attr "length") - (if_then_else - (eq (symbol_ref ("which_alternative")) - (const_int 0)) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -250)) - (le (minus (match_dup 4) (pc)) (const_int 256))) - (const_int 4) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) - (le (minus (match_dup 4) (pc)) (const_int 2048))) - (const_int 6) - (const_int 8))) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -248)) - (le (minus (match_dup 4) (pc)) (const_int 256))) - (const_int 6) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) - (le (minus (match_dup 4) (pc)) (const_int 2048))) - (const_int 8) - (const_int 10)))))] -) - -(define_insn "*xorsi3_cbranch_scratch" - [(set (pc) - (if_then_else - (match_operator 4 "equality_operator" - [(xor:SI (match_operand:SI 1 "s_register_operand" "%0") - (match_operand:SI 2 "s_register_operand" "l")) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc))) - (clobber (match_scratch:SI 0 "=l"))] - "TARGET_THUMB1" - "* - { - output_asm_insn (\"eor\\t%0, %2\", operands); - switch (get_attr_length (insn)) - { - case 4: return \"b%d4\\t%l3\"; - case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; - default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; - } - }" - [(set (attr "far_jump") - (if_then_else - (eq_attr "length" "8") - (const_string "yes") - (const_string "no"))) - (set (attr "length") - (if_then_else - (and (ge (minus (match_dup 3) (pc)) (const_int -250)) - (le (minus (match_dup 3) (pc)) (const_int 256))) - (const_int 4) - (if_then_else - (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) - (le (minus (match_dup 3) (pc)) (const_int 2048))) - (const_int 6) - (const_int 8))))] -) - -(define_insn "*xorsi3_cbranch" - [(set (pc) - (if_then_else - (match_operator 5 "equality_operator" - [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1") - (match_operand:SI 3 "s_register_operand" "l,l,l,l")) - (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc))) - (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") - (xor:SI (match_dup 2) (match_dup 3))) - (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] - "TARGET_THUMB1" - "* - { - if (which_alternative == 0) - output_asm_insn (\"eor\\t%0, %3\", operands); - else if (which_alternative == 1) - { - output_asm_insn (\"eor\\t%1, %3\", operands); - output_asm_insn (\"mov\\t%0, %1\", operands); - } - else - { - output_asm_insn (\"eor\\t%1, %3\", operands); - output_asm_insn (\"str\\t%1, %0\", operands); - } - - switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) - { - case 4: return \"b%d5\\t%l4\"; - case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; - default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; - } - }" - [(set (attr "far_jump") - (if_then_else - (ior (and (eq (symbol_ref ("which_alternative")) - (const_int 0)) - (eq_attr "length" "8")) - (eq_attr "length" "10")) - (const_string "yes") - (const_string "no"))) - (set (attr "length") - (if_then_else - (eq (symbol_ref ("which_alternative")) - (const_int 0)) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -250)) - (le (minus (match_dup 4) (pc)) (const_int 256))) - (const_int 4) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) - (le (minus (match_dup 4) (pc)) (const_int 2048))) - (const_int 6) - (const_int 8))) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -248)) - (le (minus (match_dup 4) (pc)) (const_int 256))) - (const_int 6) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) - (le (minus (match_dup 4) (pc)) (const_int 2048))) - (const_int 8) - (const_int 10)))))] -) - -(define_insn "*bicsi3_cbranch_scratch" - [(set (pc) - (if_then_else - (match_operator 4 "equality_operator" - [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l")) - (match_operand:SI 1 "s_register_operand" "0")) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc))) - (clobber (match_scratch:SI 0 "=l"))] - "TARGET_THUMB1" - "* - { - output_asm_insn (\"bic\\t%0, %2\", operands); - switch (get_attr_length (insn)) - { - case 4: return \"b%d4\\t%l3\"; - case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; - default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; - } - }" - [(set (attr "far_jump") - (if_then_else - (eq_attr "length" "8") - (const_string "yes") - (const_string "no"))) - (set (attr "length") - (if_then_else - (and (ge (minus (match_dup 3) (pc)) (const_int -250)) - (le (minus (match_dup 3) (pc)) (const_int 256))) - (const_int 4) - (if_then_else - (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) - (le (minus (match_dup 3) (pc)) (const_int 2048))) - (const_int 6) - (const_int 8))))] -) - -(define_insn "*bicsi3_cbranch" - [(set (pc) - (if_then_else - (match_operator 5 "equality_operator" - [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l")) - (match_operand:SI 2 "s_register_operand" "0,1,1,1,1")) - (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc))) - (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m") - (and:SI (not:SI (match_dup 3)) (match_dup 2))) - (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))] - "TARGET_THUMB1" - "* - { - if (which_alternative == 0) - output_asm_insn (\"bic\\t%0, %3\", operands); - else if (which_alternative <= 2) - { - output_asm_insn (\"bic\\t%1, %3\", operands); - /* It's ok if OP0 is a lo-reg, even though the mov will set the - conditions again, since we're only testing for equality. */ - output_asm_insn (\"mov\\t%0, %1\", operands); - } - else - { - output_asm_insn (\"bic\\t%1, %3\", operands); - output_asm_insn (\"str\\t%1, %0\", operands); - } - - switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) - { - case 4: return \"b%d5\\t%l4\"; - case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; - default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; - } - }" - [(set (attr "far_jump") - (if_then_else - (ior (and (eq (symbol_ref ("which_alternative")) - (const_int 0)) - (eq_attr "length" "8")) - (eq_attr "length" "10")) - (const_string "yes") - (const_string "no"))) - (set (attr "length") - (if_then_else - (eq (symbol_ref ("which_alternative")) - (const_int 0)) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -250)) - (le (minus (match_dup 4) (pc)) (const_int 256))) - (const_int 4) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) - (le (minus (match_dup 4) (pc)) (const_int 2048))) - (const_int 6) - (const_int 8))) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -248)) - (le (minus (match_dup 4) (pc)) (const_int 256))) - (const_int 6) - (if_then_else - (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) - (le (minus (match_dup 4) (pc)) (const_int 2048))) - (const_int 8) - (const_int 10)))))] -) - (define_insn "*cbranchne_decr1" [(set (pc) (if_then_else (match_operator 3 "equality_operator" @@ -7603,126 +7172,6 @@ (define_insn "*addsi3_cbranch_scratch" (const_int 8))))] ) -(define_insn "*subsi3_cbranch" - [(set (pc) - (if_then_else - (match_operator 4 "arm_comparison_operator" - [(minus:SI - (match_operand:SI 2 "s_register_operand" "l,l,1,l") - (match_operand:SI 3 "s_register_operand" "l,l,l,l")) - (const_int 0)]) - (label_ref (match_operand 5 "" "")) - (pc))) - (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") - (minus:SI (match_dup 2) (match_dup 3))) - (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] - "TARGET_THUMB1 - && (GET_CODE (operands[4]) == EQ - || GET_CODE (operands[4]) == NE - || GET_CODE (operands[4]) == GE - || GET_CODE (operands[4]) == LT)" - "* - { - if (which_alternative == 0) - output_asm_insn (\"sub\\t%0, %2, %3\", operands); - else if (which_alternative == 1) - { - /* We must provide an alternative for a hi reg because reload - cannot handle output reloads on a jump instruction, but we - can't subtract into that. Fortunately a mov from lo to hi - does not clobber the condition codes. */ - output_asm_insn (\"sub\\t%1, %2, %3\", operands); - output_asm_insn (\"mov\\t%0, %1\", operands); - } - else - { - /* Similarly, but the target is memory. */ - output_asm_insn (\"sub\\t%1, %2, %3\", operands); - output_asm_insn (\"str\\t%1, %0\", operands); - } - - switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0)) - { - case 4: - return \"b%d4\\t%l5\"; - case 6: - return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\"; - default: - return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\"; - } - } - " - [(set (attr "far_jump") - (if_then_else - (ior (and (eq (symbol_ref ("which_alternative")) - (const_int 0)) - (eq_attr "length" "8")) - (eq_attr "length" "10")) - (const_string "yes") - (const_string "no"))) - (set (attr "length") - (if_then_else - (eq (symbol_ref ("which_alternative")) - (const_int 0)) - (if_then_else - (and (ge (minus (match_dup 5) (pc)) (const_int -250)) - (le (minus (match_dup 5) (pc)) (const_int 256))) - (const_int 4) - (if_then_else - (and (ge (minus (match_dup 5) (pc)) (const_int -2040)) - (le (minus (match_dup 5) (pc)) (const_int 2048))) - (const_int 6) - (const_int 8))) - (if_then_else - (and (ge (minus (match_dup 5) (pc)) (const_int -248)) - (le (minus (match_dup 5) (pc)) (const_int 256))) - (const_int 6) - (if_then_else - (and (ge (minus (match_dup 5) (pc)) (const_int -2038)) - (le (minus (match_dup 5) (pc)) (const_int 2048))) - (const_int 8) - (const_int 10)))))] -) - -(define_insn "*subsi3_cbranch_scratch" - [(set (pc) - (if_then_else - (match_operator 0 "arm_comparison_operator" - [(minus:SI (match_operand:SI 1 "register_operand" "l") - (match_operand:SI 2 "nonmemory_operand" "l")) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "TARGET_THUMB1 - && (GET_CODE (operands[0]) == EQ - || GET_CODE (operands[0]) == NE - || GET_CODE (operands[0]) == GE - || GET_CODE (operands[0]) == LT)" - "* - output_asm_insn (\"cmp\\t%1, %2\", operands); - switch (get_attr_length (insn)) - { - case 4: return \"b%d0\\t%l3\"; - case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; - default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; - } - " - [(set (attr "far_jump") - (if_then_else - (eq_attr "length" "8") - (const_string "yes") - (const_string "no"))) - (set (attr "length") - (if_then_else - (and (ge (minus (match_dup 3) (pc)) (const_int -250)) - (le (minus (match_dup 3) (pc)) (const_int 256))) - (const_int 4) - (if_then_else - (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) - (le (minus (match_dup 3) (pc)) (const_int 2048))) - (const_int 6) - (const_int 8))))] -) ;; Comparison and test insns