On 1/28/20 10:35 AM, Kyrill Tkachov wrote:
Hi Stam,

On 1/8/20 3:18 PM, Stam Markianos-Wright wrote:

On 12/10/19 5:03 PM, Kyrill Tkachov wrote:
Hi Stam,

On 11/15/19 5:26 PM, Stam Markianos-Wright wrote:
Pinging with more correct maintainers this time :)

Also would need to backport to gcc7,8,9, but need to get this approved
first!

Sorry for the delay.
Same here now! Sorry totally forget about this in the lead up to Xmas!

Done the changes marked below and also removed the unnecessary extra #defines
from the test.


This is ok with a nit on the testcase...


diff --git a/gcc/testsuite/gcc.target/arm/pr91816.c b/gcc/testsuite/gcc.target/arm/pr91816.c
new file mode 100644
index 0000000000000000000000000000000000000000..757c897e9c0db32709227b3fdf1b4a8033428232
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr91816.c
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv7-a -mthumb -mfpu=vfpv3-d16" }  */
+int printf(const char *, ...);
+

I think this needs a couple of effective target checks like arm_hard_vfp_ok and arm_thumb2_ok. See other tests in gcc.target/arm that add -mthumb to the options.

Hmm, looking back at this now, is there any reason why it can't just be:

/* { dg-do compile } */
/* { dg-require-effective-target arm_thumb2_ok } */
/* { dg-additional-options "-mthumb" }  */

were we don't override the march or fpu options at all, but just use `require-effective-target arm_thumb2_ok` to make sure that thumb2 is supported?

The attached new diff does just that.

Cheers :)

Stam.


Thanks,
Kyrill


diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 7c4b1003844..8895becc639 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -576,4 +576,6 @@ void arm_parse_option_features (sbitmap, const 
cpu_arch_option *,
 
 void arm_initialize_isa (sbitmap, const enum isa_feature *);
 
+const char * arm_gen_far_branch (rtx *, int, const char * , const char *);
+
 #endif /* ! GCC_ARM_PROTOS_H */
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 07231d722b9..ee5de169f3e 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -32626,6 +32626,40 @@ arm_run_selftests (void)
 }
 } /* Namespace selftest.  */
 
+
+/* Generate code to enable conditional branches in functions over 1 MiB.
+   Parameters are:
+     operands: is the operands list of the asm insn (see arm_cond_branch or
+       arm_cond_branch_reversed).
+     pos_label: is an index into the operands array where operands[pos_label] 
is
+       the asm label of the final jump destination.
+     dest: is a string which is used to generate the asm label of the 
intermediate
+       destination
+   branch_format: is a string denoting the intermediate branch format, e.g.
+     "beq", "bne", etc.  */
+
+const char *
+arm_gen_far_branch (rtx * operands, int pos_label, const char * dest,
+                   const char * branch_format)
+{
+  rtx_code_label * tmp_label = gen_label_rtx ();
+  char label_buf[256];
+  char buffer[128];
+  ASM_GENERATE_INTERNAL_LABEL (label_buf, dest , \
+                       CODE_LABEL_NUMBER (tmp_label));
+  const char *label_ptr = arm_strip_name_encoding (label_buf);
+  rtx dest_label = operands[pos_label];
+  operands[pos_label] = tmp_label;
+
+  snprintf (buffer, sizeof (buffer), "%s%s", branch_format , label_ptr);
+  output_asm_insn (buffer, operands);
+
+  snprintf (buffer, sizeof (buffer), "b\t%%l0%d\n%s:", pos_label, label_ptr);
+  operands[pos_label] = dest_label;
+  output_asm_insn (buffer, operands);
+  return "";
+}
+
 #undef TARGET_RUN_TARGET_SELFTESTS
 #define TARGET_RUN_TARGET_SELFTESTS selftest::arm_run_selftests
 #endif /* CHECKING_P */
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index f89a2d412df..fb1d4547e5c 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -7546,9 +7546,15 @@
 ;; And for backward branches we have 
 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
 ;;
+;; In 16-bit Thumb these ranges are:
 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
 
+;; In 32-bit Thumb these ranges are:
+;; For a 'b'       +/- 16MB is not checked for.
+;; For a 'b<cond>' pos_range = 1048574,  neg_range = -1048576  giving
+;; (-1048568 -> 1048576).
+
 (define_expand "cbranchsi4"
   [(set (pc) (if_then_else
              (match_operator 0 "expandable_comparison_operator"
@@ -7721,23 +7727,50 @@
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   "TARGET_32BIT"
-  "*
-  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
+  {
+    if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
     {
       arm_ccfsm_state += 2;
-      return \"\";
+      return "";
     }
-  return \"b%d1\\t%l0\";
-  "
+    switch (get_attr_length (insn))
+      {
+       case 2: /* Thumb2 16-bit b{cond}.  */
+       case 4: /* Thumb2 32-bit b{cond} or A32 b{cond}.  */
+         return "b%d1\t%l0";
+         break;
+
+       /* Thumb2 b{cond} out of range.  Use 16-bit b{cond} and
+          unconditional branch b.  */
+       default: return arm_gen_far_branch (operands, 0, "Lbcond", "b%D1\t");
+      }
+  }
   [(set_attr "conds" "use")
    (set_attr "type" "branch")
    (set (attr "length")
-       (if_then_else
-          (and (match_test "TARGET_THUMB2")
-               (and (ge (minus (match_dup 0) (pc)) (const_int -250))
-                    (le (minus (match_dup 0) (pc)) (const_int 256))))
-          (const_int 2)
-          (const_int 4)))]
+    (if_then_else (match_test "!TARGET_THUMB2")
+
+      ;;Target is not Thumb2, therefore is A32.  Generate b{cond}.
+      (const_int 4)
+
+      ;; Check if target is within 16-bit Thumb2 b{cond} range.
+      (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -250))
+                        (le (minus (match_dup 0) (pc)) (const_int 256)))
+
+       ;; Target is Thumb2, within narrow range.
+       ;; Generate b{cond}.
+       (const_int 2)
+
+       ;; Check if target is within 32-bit Thumb2 b{cond} range.
+       (if_then_else (and (ge (minus (match_dup 0) (pc))(const_int -1048568))
+                          (le (minus (match_dup 0) (pc)) (const_int 1048576)))
+
+         ;; Target is Thumb2, within wide range.
+         ;; Generate b{cond}
+         (const_int 4)
+         ;; Target is Thumb2, out of range.
+         ;; Generate narrow b{cond} and unconditional branch b.
+         (const_int 6)))))]
 )
 
 (define_insn "*arm_cond_branch_reversed"
@@ -7747,23 +7780,50 @@
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
   "TARGET_32BIT"
-  "*
-  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
+  {
+    if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
     {
       arm_ccfsm_state += 2;
-      return \"\";
+      return "";
     }
-  return \"b%D1\\t%l0\";
-  "
+    switch (get_attr_length (insn))
+      {
+       case 2: /* Thumb2 16-bit b{cond}.  */
+       case 4: /* Thumb2 32-bit b{cond} or A32 b{cond}.  */
+         return "b%D1\t%l0";
+         break;
+
+       /* Thumb2 b{cond} out of range.  Use 16-bit b{cond} and
+          unconditional branch b.  */
+       default: return arm_gen_far_branch (operands, 0, "Lbcond", "b%d1\t");
+      }
+  }
   [(set_attr "conds" "use")
    (set_attr "type" "branch")
    (set (attr "length")
-       (if_then_else
-          (and (match_test "TARGET_THUMB2")
-               (and (ge (minus (match_dup 0) (pc)) (const_int -250))
-                    (le (minus (match_dup 0) (pc)) (const_int 256))))
-          (const_int 2)
-          (const_int 4)))]
+    (if_then_else (match_test "!TARGET_THUMB2")
+
+      ;;Target is not Thumb2, therefore is A32.  Generate b{cond}.
+      (const_int 4)
+
+      ;; Check if target is within 16-bit Thumb2 b{cond} range.
+      (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -250))
+                        (le (minus (match_dup 0) (pc)) (const_int 256)))
+
+       ;; Target is Thumb2, within narrow range.
+       ;; Generate b{cond}.
+       (const_int 2)
+
+       ;; Check if target is within 32-bit Thumb2 b{cond} range.
+       (if_then_else (and (ge (minus (match_dup 0) (pc))(const_int -1048568))
+                          (le (minus (match_dup 0) (pc)) (const_int 1048576)))
+
+         ;; Target is Thumb2, within wide range.
+         ;; Generate b{cond}.
+         (const_int 4)
+         ;; Target is Thumb2, out of range.
+         ;; Generate narrow b{cond} and unconditional branch b.
+         (const_int 6)))))]
 )
 
 
diff --git a/gcc/testsuite/gcc.target/arm/pr91816.c 
b/gcc/testsuite/gcc.target/arm/pr91816.c
new file mode 100644
index 00000000000..1fa382d12ea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr91816.c
@@ -0,0 +1,62 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-additional-options "-mthumb" }  */
+
+int printf(const char *, ...);
+
+#define HW0    printf("Hello World!\n");
+#define HW1    HW0 HW0 HW0 HW0 HW0 HW0 HW0 HW0 HW0 HW0
+#define HW2    HW1 HW1 HW1 HW1 HW1 HW1 HW1 HW1 HW1 HW1
+#define HW3    HW2 HW2 HW2 HW2 HW2 HW2 HW2 HW2 HW2 HW2
+#define HW4    HW3 HW3 HW3 HW3 HW3 HW3 HW3 HW3 HW3 HW3
+#define HW5    HW4 HW4 HW4 HW4 HW4 HW4 HW4 HW4 HW4 HW4
+
+__attribute__((noinline,noclone)) void f1 (int a)
+{
+  if (a) { HW0 }
+}
+
+__attribute__((noinline,noclone)) void f2 (int a)
+{
+  if (a) { HW3 }
+}
+
+
+__attribute__((noinline,noclone)) void f3 (int a)
+{
+  if (a) { HW5 }
+}
+
+__attribute__((noinline,noclone)) void f4 (int a)
+{
+  if (a == 1) { HW0 }
+}
+
+__attribute__((noinline,noclone)) void f5 (int a)
+{
+  if (a == 1) { HW3 }
+}
+
+
+__attribute__((noinline,noclone)) void f6 (int a)
+{
+  if (a == 1) { HW5 }
+}
+
+
+int main(void)
+{
+       f1(0);
+       f2(0);
+       f3(0);
+       f4(0);
+       f5(0);
+       f6(0);
+       return 0;
+}
+
+
+/* { dg-final { scan-assembler-times "beq\\t.L\[0-9\]" 2 } } */
+/* { dg-final { scan-assembler-times "beq\\t.Lbcond\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "bne\\t.L\[0-9\]" 2 } } */
+/* { dg-final { scan-assembler-times "bne\\t.Lbcond\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "b\\t.L\[0-9\]" 2 } } */

Reply via email to