From: Bernd Schmidt Date: Mon, 2 Aug 2010 09:51:39 +0000 (+0000) Subject: final.c (final_scan_insn): Call CC_STATUS_INIT unconditionally. X-Git-Tag: releases/gcc-4.6.0~5290 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=906668bb6f8c3f1eb4046dec89e9664554481eaa;p=thirdparty%2Fgcc.git final.c (final_scan_insn): Call CC_STATUS_INIT unconditionally. * 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 (Pd): 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. From-SVN: r162813 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 31348a411b08..fb365750c465 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -3,6 +3,40 @@ * postreload.c (reload_cse_simplify_operands): Take attribute enabled into account. + * 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 (Pd): 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. + 2010-08-02 Ramana Radhakrishnan * config/arm/arm.c (COSTS_N_INSNS): Remove definition. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 23bc81023c06..d22ded39b33f 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -687,6 +687,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 @@ -718,6 +721,7 @@ 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. */ @@ -1572,7 +1576,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; @@ -7682,12 +7687,26 @@ arm_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED) { 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 @@ -19474,14 +19493,45 @@ thumb_exit (FILE *f, int reg_containing_return_addr) /* 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 diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 8c6d249a837c..e90f1d3cbdd4 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -412,9 +412,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; @@ -1593,6 +1596,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 @@ -1623,8 +1627,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. */ @@ -2259,6 +2271,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" : "") diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 885d6ed81cba..097defd07425 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -151,6 +151,9 @@ ; 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 @@ ; 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") @@ -1080,14 +1085,14 @@ " ) -(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" "lPd")))] "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" @@ -1962,7 +1967,7 @@ 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; } @@ -2023,9 +2028,9 @@ (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) @@ -2564,14 +2569,14 @@ [(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") @@ -2706,14 +2711,14 @@ (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") @@ -2830,14 +2835,14 @@ [(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) @@ -3264,8 +3269,8 @@ (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" "") @@ -3320,8 +3325,8 @@ (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" "") @@ -3379,8 +3384,8 @@ (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" "") @@ -4029,7 +4034,7 @@ (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)))] @@ -5086,8 +5091,8 @@ 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" "") @@ -5635,8 +5640,8 @@ 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" @@ -5869,8 +5874,8 @@ 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" @@ -5970,8 +5975,8 @@ " [(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" "") @@ -6046,7 +6051,8 @@ 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" @@ -6681,26 +6687,38 @@ (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)) { @@ -6708,7 +6726,7 @@ 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") @@ -6762,69 +6780,8 @@ (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" "")) @@ -6834,14 +6791,12 @@ (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 @@ -6855,14 +6810,12 @@ (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) @@ -6986,7 +6939,7 @@ (const_int 6) (const_int 8))))] ) - + (define_insn "*tstsi3_cbranch" [(set (pc) (if_then_else @@ -7024,390 +6977,6 @@ (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" @@ -7660,126 +7229,6 @@ (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 diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md index ee6b6256b323..9ee681ca0728 100644 --- a/gcc/config/arm/constraints.md +++ b/gcc/config/arm/constraints.md @@ -30,7 +30,7 @@ ;; The following multi-letter normal constraints have been used: ;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy, Di -;; in Thumb-1 state: Pa, Pb, Pc +;; in Thumb-1 state: Pa, Pb, Pc, Pd ;; in Thumb-2 state: Ps, Pt, Pu, Pv, Pw, Px ;; The following memory constraints have been used: @@ -154,6 +154,11 @@ (match_test "TARGET_THUMB1 && ival > 1020 && ival <= 1275"))) +(define_constraint "Pd" + "@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") diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index f53c54fa110e..89dcb29a2508 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -235,6 +235,9 @@ (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)"))) diff --git a/gcc/final.c b/gcc/final.c index c35ed7b75a57..f1cff3409ade 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -99,8 +99,8 @@ along with GCC; see the file COPYING3. If not see #include "sdbout.h" #endif -/* If we aren't using cc0, CC_STATUS_INIT shouldn't exist. So define a - null default for it to save conditionalization later. */ +/* Most ports that aren't using cc0 don't need to define CC_STATUS_INIT. + So define a null default for it to save conditionalization later. */ #ifndef CC_STATUS_INIT #define CC_STATUS_INIT #endif @@ -2039,9 +2039,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, #endif } } -#ifdef HAVE_cc0 CC_STATUS_INIT; -#endif if (!DECL_IGNORED_P (current_function_decl) && LABEL_NAME (insn)) debug_hooks->label (insn);