From 5ce15300a0ef85a37fb9d90299ab73b994b67fca Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Wed, 13 Jul 2016 10:54:12 +0000 Subject: [PATCH] arm.h (TARGET_HAVE_CBZ): Define. 2016-07-13 Thomas Preud'homme gcc/ * config/arm/arm.h (TARGET_HAVE_CBZ): Define. (TARGET_IDIV): Set for all Thumb targets provided they have hardware divide feature. * config/arm/arm.md (divsi3): New unpredicable alternative for ARMv8-M Baseline. Make initial alternative TARGET_32BIT only. (udivsi3): Likewise. * config/arm/thumb1.md (thumb1_cbz): New define_insn. * doc/sourcebuild.texi (arm_thumb1_cbz_ok): Document new effective target. gcc/testsuite/ * lib/target-supports.exp (check_effective_target_arm_thumb1_cbz_ok): Add new arm_thumb1_cbz_ok effective target. * gcc.target/arm/cbz.c: New test. From-SVN: r238289 --- gcc/ChangeLog | 12 ++++ gcc/config/arm/arm.h | 5 +- gcc/config/arm/arm.md | 26 ++++---- gcc/config/arm/thumb1.md | 85 +++++++++++++++++++++++++++ gcc/doc/sourcebuild.texi | 4 ++ gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/gcc.target/arm/cbz.c | 12 ++++ gcc/testsuite/lib/target-supports.exp | 17 ++++++ 8 files changed, 156 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/cbz.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3f7e7f10bd0..f05d2b19246 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2016-07-13 Thomas Preud'homme + + * config/arm/arm.h (TARGET_HAVE_CBZ): Define. + (TARGET_IDIV): Set for all Thumb targets provided they have hardware + divide feature. + * config/arm/arm.md (divsi3): New unpredicable alternative for ARMv8-M + Baseline. Make initial alternative TARGET_32BIT only. + (udivsi3): Likewise. + * config/arm/thumb1.md (thumb1_cbz): New define_insn. + * doc/sourcebuild.texi (arm_thumb1_cbz_ok): Document new effective + target. + 2016-07-13 Thomas Preud'homme * config/arm/arm.h (TARGET_HAVE_MOVT): Include ARMv8-M as having MOVT. diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 6a0f64537f8..317885cf719 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -266,9 +266,12 @@ extern void (*arm_lang_output_object_attributes_hook)(void); /* Nonzero if this chip provides the MOVW and MOVT instructions. */ #define TARGET_HAVE_MOVT (arm_arch_thumb2 || arm_arch8) +/* Nonzero if this chip provides the CBZ and CBNZ instructions. */ +#define TARGET_HAVE_CBZ (arm_arch_thumb2 || arm_arch8) + /* Nonzero if integer division instructions supported. */ #define TARGET_IDIV ((TARGET_ARM && arm_arch_arm_hwdiv) \ - || (TARGET_THUMB2 && arm_arch_thumb_hwdiv)) + || (TARGET_THUMB && arm_arch_thumb_hwdiv)) /* Nonzero if disallow volatile memory access in IT block. */ #define TARGET_NO_VOLATILE_CE (arm_arch_no_volatile_ce) diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 8727c6df16e..820471556ef 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -4330,23 +4330,29 @@ ;; Division instructions (define_insn "divsi3" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (div:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "s_register_operand" "r")))] + [(set (match_operand:SI 0 "s_register_operand" "=r,r") + (div:SI (match_operand:SI 1 "s_register_operand" "r,r") + (match_operand:SI 2 "s_register_operand" "r,r")))] "TARGET_IDIV" - "sdiv%?\t%0, %1, %2" - [(set_attr "predicable" "yes") + "@ + sdiv%?\t%0, %1, %2 + sdiv\t%0, %1, %2" + [(set_attr "arch" "32,v8mb") + (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no") (set_attr "type" "sdiv")] ) (define_insn "udivsi3" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (udiv:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "s_register_operand" "r")))] + [(set (match_operand:SI 0 "s_register_operand" "=r,r") + (udiv:SI (match_operand:SI 1 "s_register_operand" "r,r") + (match_operand:SI 2 "s_register_operand" "r,r")))] "TARGET_IDIV" - "udiv%?\t%0, %1, %2" - [(set_attr "predicable" "yes") + "@ + udiv%?\t%0, %1, %2 + udiv\t%0, %1, %2" + [(set_attr "arch" "32,v8mb") + (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no") (set_attr "type" "udiv")] ) diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md index b317f1b0637..cd98de7dcb4 100644 --- a/gcc/config/arm/thumb1.md +++ b/gcc/config/arm/thumb1.md @@ -974,6 +974,91 @@ DONE; }) +;; A pattern for the CB(N)Z instruction added in ARMv8-M Baseline profile, +;; adapted from cbranchsi4_insn. Modifying cbranchsi4_insn instead leads to +;; code generation difference for ARMv6-M because the minimum length of the +;; instruction becomes 2 even for ARMv6-M due to a limitation in genattrtab's +;; handling of PC in the length condition. +(define_insn "thumb1_cbz" + [(set (pc) (if_then_else + (match_operator 0 "equality_operator" + [(match_operand:SI 1 "s_register_operand" "l") + (const_int 0)]) + (label_ref (match_operand 2 "" "")) + (pc)))] + "TARGET_THUMB1 && TARGET_HAVE_CBZ" +{ + if (get_attr_length (insn) == 2) + { + if (GET_CODE (operands[0]) == EQ) + return "cbz\t%1, %l2"; + else + return "cbnz\t%1, %l2"; + } + else + { + rtx t = cfun->machine->thumb1_cc_insn; + if (t != NULL_RTX) + { + 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; + } + if (t == NULL_RTX) + { + output_asm_insn ("cmp\t%1, #0", 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)) + { + case 4: return "b%d0\t%l2"; + case 6: return "b%D0\t.LCB%=;b\t%l2\t%@long jump\n.LCB%=:"; + case 8: return "b%D0\t.LCB%=;bl\t%l2\t%@far jump\n.LCB%=:"; + default: gcc_unreachable (); + } + } +} + [(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 2)) + (le (minus (match_dup 2) (pc)) (const_int 128))) + (const_int 2) + (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))))) + (set (attr "type") + (if_then_else + (eq_attr "length" "2") + (const_string "branch") + (const_string "multiple")))] +) + (define_insn "cbranchsi4_insn" [(set (pc) (if_then_else (match_operator 0 "arm_comparison_operator" diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index b437c171132..24b65da8c58 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -1618,6 +1618,10 @@ ARM target prefers @code{LDRD} and @code{STRD} instructions over ARM target generates Thumb-1 code for @code{-mthumb} with @code{MOVW} and @code{MOVT} instructions available. +@item arm_thumb1_cbz_ok +ARM target generates Thumb-1 code for @code{-mthumb} with +@code{CBZ} and @code{CBNZ} instructions available. + @end table @subsubsection AArch64-specific attributes diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d1204e73e8d..239d55e7458 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-07-13 Thomas Preud'homme + + * lib/target-supports.exp (check_effective_target_arm_thumb1_cbz_ok): + Add new arm_thumb1_cbz_ok effective target. + * gcc.target/arm/cbz.c: New test. + 2016-07-13 Thomas Preud'homme * lib/target-supports.exp (check_effective_target_arm_thumb1_movt_ok): diff --git a/gcc/testsuite/gcc.target/arm/cbz.c b/gcc/testsuite/gcc.target/arm/cbz.c new file mode 100644 index 00000000000..5d3de638777 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/cbz.c @@ -0,0 +1,12 @@ +/* { dg-do compile {target { arm_thumb2 || arm_thumb1_cbz_ok } } } */ +/* { dg-options "-O2" } */ + +int +foo (int a, int *b) +{ + if (a) + *b = 1; + return 0; +} + +/* { dg-final { scan-assembler-times "cbz\\tr\\d" 1 } } */ diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index e6a117022f8..b9909ada734 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -3502,6 +3502,23 @@ proc check_effective_target_arm_thumb1_movt_ok {} { } } +# Return 1 if this is an ARM target where -mthumb causes Thumb-1 to be +# used and CBZ and CBNZ instructions are available. + +proc check_effective_target_arm_thumb1_cbz_ok {} { + if [check_effective_target_arm_thumb1_ok] { + return [check_no_compiler_messages arm_movt object { + int + foo (void) + { + asm ("cbz r0, 2f\n2:"); + } + } "-mthumb"] + } else { + return 0 + } +} + # Return 1 if this compilation turns on string_ops_prefer_neon on. proc check_effective_target_arm_tune_string_ops_prefer_neon { } { -- 2.30.2