From patchwork Thu Jun 24 22:52:28 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [ARM] Improve optimization to transform TST into LSLS Date: Thu, 24 Jun 2010 12:52:28 -0000 From: Richard Earnshaw X-Patchwork-Id: 56867 Message-Id: <4C23E1AC.5070602@buzzard.freeserve.co.uk> To: GCC Patches We recently added a pattern to the Thumb2 machine description to try to transform TST reg, # (1 << n) into LSLS reg, #(31-n). Subsequent discussions on another patch led me to realize that this patch could probably be done a better way. Experimentation bears this out: the following patch saves a further 0.1% when compiling CSiBE. This version of the patch uses a peephole2 rather than a combine pattern to spot the optimization. This has two benefits: 1) The pattern will not be used if there's no scratch available (probably better, since tst only costs 2 bytes, but spilling can often cost significantly more). 2) It gives rise to further optimization opportunities, such as if-conversion, that the other patch did not support. Tested on arm-eabi and committed to trunk. R. 2010-06-24 Richard Earnshaw * thumb2.md (thumb2_tlobits_cbranch): Delete. (peephole2 to convert zero_extract/compare of single bit to lshift/compare): New. diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md index 7045d14..3985183 100644 --- a/gcc/config/arm/thumb2.md +++ b/gcc/config/arm/thumb2.md @@ -1509,88 +1509,31 @@ (set_attr "predicable" "yes")] ) -(define_insn "*thumb2_tlobits_cbranch" - [(set (pc) - (if_then_else - (match_operator 0 "equality_operator" - [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l,h,h") - (match_operand:SI 2 "const_int_operand" "i,Pu,i") - (const_int 0)) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc))) - (clobber (match_scratch:SI 4 "=l,X,r")) - (clobber (reg:CC CC_REGNUM))] - "TARGET_THUMB2" - "* - { - if (which_alternative == 0) - { - rtx op[3]; - op[0] = operands[4]; - op[1] = operands[1]; - op[2] = GEN_INT (32 - INTVAL (operands[2])); - - output_asm_insn (\"lsls\\t%0, %1, %2\", op); - 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%=:\"; - } - } - else - { - rtx op[3]; - - if (which_alternative == 1) - { - op[0] = operands[1]; - op[1] = GEN_INT ((1 << INTVAL (operands[2])) - 1); - output_asm_insn (\"tst\\t%0, %1\", op); - } - else - { - op[0] = operands[4]; - op[1] = operands[1]; - op[2] = GEN_INT (32 - INTVAL (operands[2])); - output_asm_insn (\"lsls\\t%0, %1, %2\", op); - } +(define_peephole2 + [(set (match_operand:CC_NOOV 0 "cc_register" "") + (compare:CC_NOOV (zero_extract:SI + (match_operand:SI 1 "low_register_operand" "") + (const_int 1) + (match_operand:SI 2 "const_int_operand" "")) + (const_int 0))) + (match_scratch:SI 3 "l") + (set (pc) + (if_then_else (match_operator:CC_NOOV 4 "equality_operator" + [(match_dup 0) (const_int 0)]) + (match_operand 5 "" "") + (match_operand 6 "" "")))] + "TARGET_THUMB2 + && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)" + [(parallel [(set (match_dup 0) + (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2)) + (const_int 0))) + (clobber (match_dup 3))]) + (set (pc) + (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)]) + (match_dup 5) (match_dup 6)))] + " + operands[2] = GEN_INT (31 - INTVAL (operands[2])); + operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE, + VOIDmode, operands[0], const0_rtx); + ") - switch (get_attr_length (insn)) - { - case 6: return \"b%d0\\t%l3\"; - case 8: 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 - (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) - (le (minus (match_dup 3) (pc)) (const_int 2048))) - (const_string "no") - (const_string "yes"))) - (set (attr "length") - (if_then_else - (eq (symbol_ref ("which_alternative")) - (const_int 0)) - (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))) - (if_then_else - (and (ge (minus (match_dup 3) (pc)) (const_int -250)) - (le (minus (match_dup 3) (pc)) (const_int 256))) - (const_int 6) - (if_then_else - (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) - (le (minus (match_dup 3) (pc)) (const_int 2048))) - (const_int 8) - (const_int 10)))))] -)