From patchwork Thu Jul 15 13:24:47 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: ARM patch: New cbranchqi, cbranchhi patterns for Thumb-1 Date: Thu, 15 Jul 2010 03:24:47 -0000 From: Bernd Schmidt X-Patchwork-Id: 58983 Message-Id: <4C3F0C1F.6020901@codesourcery.com> To: GCC Patches Cc: Richard Earnshaw On Thumb-1, comparisons of integer values smaller than a word can be done by shifting the value to the left. This patch adds a new macroized pattern, cbranch4_insn, which is used for QImode and HImode, and does exactly that. Effects: - lsl r2, r1, #24 - lsr r2, r2, #24 - cmp r2, #0 + lsl r1, #24 bne .L195 This uses the neat trick of putting a matching constraint on a match_scratch. An earlier version (with slightly more stupid code) was regression tested on qemu/arm-linux with my usual set of three flags. This version generates identical code as the tested one for all my testcases. Ok if retest passes? Bernd * config/arm/arm.md (QHI): New define_mode_iterator. (cbranch4_insn): New pattern. Index: config/arm/arm.md =================================================================== --- config/arm/arm.md (revision 162146) +++ config/arm/arm.md (working copy) @@ -393,6 +393,9 @@ (define_mode_iterator ANY64 [DI DF V8QI ;; The integer modes up to word size (define_mode_iterator QHSI [QI HI SI]) +;; The integer modes below word size +(define_mode_iterator QHI [QI HI]) + ;;--------------------------------------------------------------------------- ;; Predicates @@ -6686,6 +6689,43 @@ (define_insn "cbranchsi4_insn" (const_int 8))))] ) +(define_mode_attr mode_lshift [(QI "24") (HI "16")]) + +(define_insn "cbranch4_insn" + [(set (pc) (if_then_else + (match_operator 0 "arm_comparison_operator" + [(match_operand:QHI 1 "s_register_operand" "l") + (const_int 0)]) + (label_ref (match_operand 2 "" "")) + (pc))) + (clobber (match_scratch:QHI 3 "=1"))] + "TARGET_THUMB1" +{ + output_asm_insn ("lsl\t%1, #", operands); + + switch (get_attr_length (insn)) + { + case 4: return "b%d0\t%l2"; + case 6: return "b%D0\t.LCB%=\;b\t%l2\t%@long jump\n.LCB%=:"; + default: return "b%D0\t.LCB%=\;bl\t%l2\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 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))))]) + (define_insn "cbranchsi4_scratch" [(set (pc) (if_then_else (match_operator 4 "arm_comparison_operator"