arm.h (TARGET_HAVE_CBZ): Define.
authorThomas Preud'homme <thomas.preudhomme@arm.com>
Wed, 13 Jul 2016 10:54:12 +0000 (10:54 +0000)
committerThomas Preud'homme <thopre01@gcc.gnu.org>
Wed, 13 Jul 2016 10:54:12 +0000 (10:54 +0000)
2016-07-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>

    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
gcc/config/arm/arm.h
gcc/config/arm/arm.md
gcc/config/arm/thumb1.md
gcc/doc/sourcebuild.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/cbz.c [new file with mode: 0644]
gcc/testsuite/lib/target-supports.exp

index 3f7e7f10bd08df80e5e885c859c36251eb5230cb..f05d2b1924612bf01d43ecdb7a328db3e303a834 100644 (file)
@@ -1,3 +1,15 @@
+2016-07-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       * 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  <thomas.preudhomme@arm.com>
 
        * config/arm/arm.h (TARGET_HAVE_MOVT): Include ARMv8-M as having MOVT.
index 6a0f64537f8e5d0d913d082cb919ae6cbd2100ec..317885cf7197b6755c4d9b5717afe61662626786 100644 (file)
@@ -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)
index 8727c6df16ea95007dfcdb3249a8467ede3d72ac..820471556efbac6b35d46a03fb763cbd30bea30f 100644 (file)
 
 ;; 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")]
 )
index b317f1b0637e02f105f10efb18270f4a35801c7c..cd98de7dcb40de483a9f93c0674bd216f4b0c56a 100644 (file)
   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"
index b437c1711321194467dc4d6867f18655cc8b3272..24b65da8c58030622e12b1175a8034a5e37ac5bf 100644 (file)
@@ -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
index d1204e73e8df4a944727cf950059ade5dab0d0d0..239d55e7458c9d01653b54441c27e81810b92b62 100644 (file)
@@ -1,3 +1,9 @@
+2016-07-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       * 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  <thomas.preudhomme@arm.com>
 
        * 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 (file)
index 0000000..5d3de63
--- /dev/null
@@ -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 } } */
index e6a117022f8f16e61fabfd40dbf5dd7eb0da2bbc..b9909ada734c08a46af886b5190be9ea92fd98e5 100644 (file)
@@ -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 { } {