From patchwork Fri Jul 16 23:46:29 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Add TST to RX From: DJ Delorie X-Patchwork-Id: 59128 Message-Id: <201007162346.o6GNkTMl028163@greed.delorie.com> To: Paolo Bonzini Cc: gcc-patches@gcc.gnu.org, nickc@redhat.com Date: Fri, 16 Jul 2010 19:46:29 -0400 That was not quite subtle enough to make my brain explode, but it does make for a more straight-forward patch... Index: predicates.md =================================================================== --- predicates.md (revision 162264) +++ predicates.md (working copy) @@ -42,12 +42,19 @@ if (CONST_INT_P (op)) return IN_RANGE (INTVAL (op), 0, 31); return true; } ) +(define_predicate "rx_constshift_operand" + (match_code "const_int") + { + return IN_RANGE (INTVAL (op), 0, 31); + } +) + ;; Check that the operand is suitable as the source operand ;; for a logic or arithmeitc instruction. Registers, integers ;; and a restricted subset of memory addresses are allowed. (define_predicate "rx_source_operand" (match_code "const_int,const_double,const,symbol_ref,label_ref,reg,mem") Index: rx.md =================================================================== --- rx.md (revision 162264) +++ rx.md (working copy) @@ -21,12 +21,15 @@ ;; This code iterator allows all branch instructions to ;; be generated from a single define_expand template. (define_code_iterator most_cond [eq ne gt ge lt le gtu geu ltu leu unordered ordered ]) +;; Likewise, but only the ones that use Z or S. +(define_code_iterator zs_cond [eq ne gtu geu ltu leu ]) + ;; This code iterator is used for sign- and zero- extensions. (define_mode_iterator small_int_modes [(HI "") (QI "")]) ;; We do not handle DFmode here because it is either ;; the same as SFmode, or if -m64bit-doubles is active ;; then all operations on doubles have to be handled by @@ -154,25 +157,25 @@ ;; allow the comparison to be moved away from the jump before the reload ;; pass has completed. That would be problematical because reload can ;; generate ADDSI3 instructions which would corrupt the PSW flags. (define_expand "cbranchsi4" [(set (pc) - (if_then_else (match_operator:SI 0 "comparison_operator" - [(match_operand:SI 1 "register_operand") - (match_operand:SI 2 "rx_source_operand")]) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:SI 1 "register_operand") + (match_operand:SI 2 "rx_source_operand")]) (label_ref (match_operand 3 "")) (pc))) ] "" "" ) (define_insn_and_split "*cbranchsi4_" [(set (pc) - (if_then_else (most_cond:SI (match_operand:SI 0 "register_operand" "r") + (if_then_else (most_cond (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "rx_source_operand" "riQ")) (label_ref (match_operand 2 "" "")) (pc))) ] "" "#" @@ -186,28 +189,123 @@ emit_jump_insn (gen_conditional_branch (operands[2], gen_rtx_fmt_ee (, CCmode, gen_rtx_REG (CCmode, CC_REG), const0_rtx))); " ) +;; ----------------------------------------------------------------------------- +;; These two are the canonical TST/branch insns. However, GCC +;; generates a wide variety of tst-like patterns, we catch those +;; below. +(define_insn_and_split "*tstbranchsi4_" + [(set (pc) + (if_then_else (zs_cond (and:SI (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "rx_source_operand" "riQ")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc))) + ] + "" + "#" + "reload_completed" + [(const_int 0)] + " + emit_insn (gen_tstsi (operands[0], operands[1])); + + emit_jump_insn (gen_conditional_branch (operands[2], + gen_rtx_fmt_ee (, CCmode, + gen_rtx_REG (CCmode, CC_REG), const0_rtx))); + " +) + +;; Inverse of above +(define_insn_and_split "*tstbranchsi4_" + [(set (pc) + (if_then_else (zs_cond (and:SI (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "rx_source_operand" "riQ")) + (const_int 0)) + (pc) + (label_ref (match_operand 2 "" "")))) + ] + "" + "#" + "reload_completed" + [(const_int 0)] + " + emit_insn (gen_tstsi (operands[0], operands[1])); + + emit_jump_insn (gen_conditional_branch (operands[2], + gen_rtx_fmt_ee (reverse_condition (), CCmode, + gen_rtx_REG (CCmode, CC_REG), const0_rtx))); + " +) + +;; Various other ways that GCC codes "var & const" + +(define_insn_and_split "*tstbranchsi4m_eq" + [(set (pc) + (if_then_else (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") + (match_operand 1 "rx_constshift_operand" "i") + (match_operand 2 "rx_constshift_operand" "i")) + (const_int 0)) + (label_ref (match_operand 3 "" "")) + (pc))) + ] + "" + "#" + "" + [(set (pc) + (if_then_else (eq (and:SI (match_dup 0) + (match_dup 4)) + (const_int 0)) + (label_ref (match_dup 3)) + (pc))) + ] + "operands[4] = GEN_INT (((1 << INTVAL (operands[1]))-1) << INTVAL (operands[2]));" +) + +(define_insn_and_split "*tstbranchsi4m_ne" + [(set (pc) + (if_then_else (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") + (match_operand 1 "rx_constshift_operand" "i") + (match_operand 2 "rx_constshift_operand" "i")) + (const_int 0)) + (label_ref (match_operand 3 "" "")) + (pc))) + ] + "" + "#" + "" + [(set (pc) + (if_then_else (ne (and:SI (match_dup 0) + (match_dup 4)) + (const_int 0)) + (label_ref (match_dup 3)) + (pc))) + ] + "operands[4] = GEN_INT (((1 << INTVAL (operands[1]))-1) << INTVAL (operands[2]));" +) + +;; ----------------------------------------------------------------------------- + (define_expand "cbranchsf4" [(set (pc) - (if_then_else (match_operator:SF 0 "comparison_operator" - [(match_operand:SF 1 "register_operand") - (match_operand:SF 2 "rx_source_operand")]) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:SF 1 "register_operand") + (match_operand:SF 2 "rx_source_operand")]) (label_ref (match_operand 3 "")) (pc))) ] "ALLOW_RX_FPU_INSNS" "" ) (define_insn_and_split "*cbranchsf4_" [(set (pc) - (if_then_else (most_cond:SF (match_operand:SF 0 "register_operand" "r") - (match_operand:SF 1 "rx_source_operand" "rFiQ")) + (if_then_else (most_cond (match_operand:SF 0 "register_operand" "r") + (match_operand:SF 1 "rx_source_operand" "rFiQ")) (label_ref (match_operand 2 "" "")) (pc))) ] "ALLOW_RX_FPU_INSNS" "#" "&& reload_completed"