This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][AARCH64]Fix for branch offsets over 1 MiB


Conditional branches have a maximum range of [-1048576, 1048572]. Any destination further away can not be reached by these. To be able to have conditional branches in very large functions, we invert the condition and change the destination to jump over an unconditional branch to the original, far away, destination.

gcc/ChangeLog:
2015-08-07  Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
            Andre Vieira  <andre.simoesdiasvieira@arm.com>

        * config/aarch64/aarch64.md (*condjump): Handle functions > 1
        Mib.
        (*cb<optab><mode>1): Idem.
        (*tb<optab><mode>1): Idem.
        (*cb<optab><mode>1): Idem.
        * config/aarch64/iterators.md (inv_cb): New code attribute.
        (inv_tb): Idem.
        * config/aarch64/aarch64.c (aarch64_gen_far_branch): New.
        * config/aarch64/aarch64-protos.h (aarch64_gen_far_branch): New.

gcc/testsuite/ChangeLog:
2015-08-07  Andre Vieira  <andre.simoesdiasvieira@arm.com>

        * gcc.target/aarch64/long-branch.c: New test.
From 9759c5a50c44b0421c7911014e63a6222dd9017d Mon Sep 17 00:00:00 2001
From: Andre Simoes Dias Vieira <andsim01@arm.com>
Date: Fri, 14 Aug 2015 10:21:57 +0100
Subject: [PATCH] fix for far branches

---
 gcc/config/aarch64/aarch64-protos.h            |   1 +
 gcc/config/aarch64/aarch64.c                   |  23 +
 gcc/config/aarch64/aarch64.md                  |  89 +++-
 gcc/config/aarch64/iterators.md                |   6 +
 gcc/testsuite/gcc.target/aarch64/long_branch.c | 565 +++++++++++++++++++++++++
 5 files changed, 669 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/long_branch.c

diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 32b5d0958a6e0b2356874736f858f007fe68cdda..87a26deb6a0dbf13e25275baeebec21a37a42f41 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -316,6 +316,7 @@ unsigned aarch64_trampoline_size (void);
 void aarch64_asm_output_labelref (FILE *, const char *);
 void aarch64_cpu_cpp_builtins (cpp_reader *);
 void aarch64_elf_asm_named_section (const char *, unsigned, tree);
+const char * aarch64_gen_far_branch (rtx *, int, const char *, const char *);
 void aarch64_err_no_fpadvsimd (machine_mode, const char *);
 void aarch64_expand_epilogue (bool);
 void aarch64_expand_mov_immediate (rtx, rtx);
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 7159f5aca5df97f154b3e654f60af9136354f335..3b491a232d81892b6511bad84e4174d939fa1be7 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -587,6 +587,29 @@ static const char * const aarch64_condition_codes[] =
   "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
 };
 
+/* Generate code to enable conditional branches in functions over 1 MiB.  */
+const char *
+aarch64_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 = targetm.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%%l%d\n%s:", pos_label, label_ptr);
+    operands[pos_label] = dest_label;
+    output_asm_insn (buffer, operands);
+    return "";
+}
+
 void
 aarch64_err_no_fpadvsimd (machine_mode mode, const char *msg)
 {
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 35255e91a95cdf20d52270470202f7499ba46bb2..74f6e3ec4bdcd076c2ad6d1431102aa50dfb5068 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -181,6 +181,13 @@
 	     (const_string "no")
 	] (const_string "yes")))
 
+;; Attribute that specifies whether we are dealing with a branch to a
+;; label that is far away, i.e. further away than the maximum/minimum
+;; representable in a signed 21-bits number.
+;; 0 :=: no
+;; 1 :=: yes
+(define_attr "far_branch" "" (const_int 0))
+
 ;; -------------------------------------------------------------------
 ;; Pipeline descriptions and scheduling
 ;; -------------------------------------------------------------------
@@ -308,8 +315,23 @@
 			   (label_ref (match_operand 2 "" ""))
 			   (pc)))]
   ""
-  "b%m0\\t%l2"
-  [(set_attr "type" "branch")]
+  {
+    if (get_attr_length (insn) == 8)
+      return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
+    else
+      return  "b%m0\\t%l2";
+  }
+  [(set_attr "type" "branch")
+   (set (attr "length")
+	(if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
+			   (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
+		      (const_int 4)
+		      (const_int 8)))
+   (set (attr "far_branch")
+	(if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
+			   (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
+		      (const_int 0)
+		      (const_int 1)))]
 )
 
 (define_expand "casesi"
@@ -488,9 +510,23 @@
 			   (label_ref (match_operand 1 "" ""))
 			   (pc)))]
   ""
-  "<cbz>\\t%<w>0, %l1"
-  [(set_attr "type" "branch")]
-
+  {
+    if (get_attr_length (insn) == 8)
+      return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
+    else
+      return "<cbz>\\t%<w>0, %l1";
+  }
+  [(set_attr "type" "branch")
+   (set (attr "length")
+	(if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
+			   (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
+		      (const_int 4)
+		      (const_int 8)))
+   (set (attr "far_branch")
+	(if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
+			   (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
+		      (const_int 0)
+		      (const_int 1)))]
 )
 
 (define_insn "*tb<optab><mode>1"
@@ -506,8 +542,14 @@
   {
     if (get_attr_length (insn) == 8)
       {
-	operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
-	return "tst\t%<w>0, %1\;<bcond>\t%l2";
+	if (get_attr_far_branch (insn) == 1)
+	  return aarch64_gen_far_branch (operands, 2, "Ltb",
+					 "<inv_tb>\\t%<w>0, %1, ");
+	else
+	  {
+	    operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
+	    return "tst\t%<w>0, %1\;<bcond>\t%l2";
+	  }
       }
     else
       return "<tbz>\t%<w>0, %1, %l2";
@@ -517,7 +559,13 @@
 	(if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
 			   (lt (minus (match_dup 2) (pc)) (const_int 32764)))
 		      (const_int 4)
-		      (const_int 8)))]
+		      (const_int 8)))
+   (set (attr "far_branch")
+	(if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
+			   (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
+		      (const_int 0)
+		      (const_int 1)))]
+
 )
 
 (define_insn "*cb<optab><mode>1"
@@ -530,12 +578,18 @@
   {
     if (get_attr_length (insn) == 8)
       {
-	char buf[64];
-	uint64_t val = ((uint64_t ) 1)
-			<< (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
-	sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
-	output_asm_insn (buf, operands);
-	return "<bcond>\t%l1";
+	if (get_attr_far_branch (insn) == 1)
+	  return aarch64_gen_far_branch (operands, 1, "Ltb",
+					 "<inv_tb>\\t%<w>0, <sizem1>, ");
+	else
+	  {
+	    char buf[64];
+	    uint64_t val = ((uint64_t) 1)
+		<< (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
+	    sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
+	    output_asm_insn (buf, operands);
+	    return "<bcond>\t%l1";
+	  }
       }
     else
       return "<tbz>\t%<w>0, <sizem1>, %l1";
@@ -545,7 +599,12 @@
 	(if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
 			   (lt (minus (match_dup 1) (pc)) (const_int 32764)))
 		      (const_int 4)
-		      (const_int 8)))]
+		      (const_int 8)))
+   (set (attr "far_branch")
+	(if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
+			   (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
+		      (const_int 0)
+		      (const_int 1)))]
 )
 
 ;; -------------------------------------------------------------------
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 5d7966d7adf49a1824ddc41cd34b04c6f179b09a..8b245c351f11960267d242892fcddb68b1542ddb 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -820,9 +820,15 @@
 ;; Emit cbz/cbnz depending on comparison type.
 (define_code_attr cbz [(eq "cbz") (ne "cbnz") (lt "cbnz") (ge "cbz")])
 
+;; Emit inverted cbz/cbnz depending on comparison type.
+(define_code_attr inv_cb [(eq "cbnz") (ne "cbz") (lt "cbz") (ge "cbnz")])
+
 ;; Emit tbz/tbnz depending on comparison type.
 (define_code_attr tbz [(eq "tbz") (ne "tbnz") (lt "tbnz") (ge "tbz")])
 
+;; Emit inverted tbz/tbnz depending on comparison type.
+(define_code_attr inv_tb [(eq "tbnz") (ne "tbz") (lt "tbz") (ge "tbnz")])
+
 ;; Max/min attributes.
 (define_code_attr maxmin [(smax "max")
 			  (smin "min")
diff --git a/gcc/testsuite/gcc.target/aarch64/long_branch.c b/gcc/testsuite/gcc.target/aarch64/long_branch.c
new file mode 100644
index 0000000000000000000000000000000000000000..37aed8823d3a3634be2462d0c18a9301c59ec97d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/long_branch.c
@@ -0,0 +1,565 @@
+/* { dg-do assemble } */
+/* { dg-timeout-factor 2.0 } */
+/* { dg-options "-O1 -fno-reorder-blocks -fno-tree-cselim --save-temps" } */
+
+
+__attribute__((noinline, noclone)) int
+restore (int a, int b)
+{
+  return a * b;
+}
+
+__attribute__((noinline, noclone)) void
+do_nothing (int *input)
+{
+  *input = restore (*input, 1);
+  return;
+}
+
+#define CASE_ENTRY(n) \
+  case n: \
+    sum = sum / (n + 1); \
+    sum = restore (sum, n + 1); \
+    if (sum == (n + addend)) \
+      break;\
+    sum = sum / (n + 2); \
+    sum = restore (sum, n + 2); \
+    sum = sum / (n + 3); \
+    sum = restore (sum, n + 3); \
+    sum = sum / (n + 4); \
+    sum = restore (sum, n + 4); \
+    sum = sum / (n + 5); \
+    sum = restore (sum, n + 5); \
+    sum = sum / (n + 6); \
+    sum = restore (sum, n + 6); \
+    sum = sum / (n + 7); \
+    sum = restore (sum, n + 7); \
+    sum = sum / (n + 8); \
+    sum = restore (sum, n + 8); \
+    sum = sum / (n + 9); \
+    sum = restore (sum, n + 9); \
+    sum = sum / (n + 10); \
+    sum = restore (sum, n + 10); \
+    sum = sum / (n + 11); \
+    sum = restore (sum, n + 11); \
+    sum = sum / (n + 12); \
+    sum = restore (sum, n + 12); \
+    sum = sum / (n + 13); \
+    sum = restore (sum, n + 13); \
+    sum = sum / (n + 14); \
+    sum = restore (sum, n + 14); \
+    sum = sum / (n + 15); \
+    sum = restore (sum, n + 15); \
+    sum = sum / (n + 16); \
+    sum = restore (sum, n + 16); \
+    sum = sum / (n + 17); \
+    sum = restore (sum, n + 17); \
+    sum = sum / (n + 18); \
+    sum = restore (sum, n + 18); \
+    sum = sum / (n + 19); \
+    sum = restore (sum, n + 19); \
+    sum = sum / (n + 20); \
+    sum = restore (sum, n + 20); \
+    sum = sum / (n + 21); \
+    sum = restore (sum, n + 21); \
+    sum = sum / (n + 22); \
+    sum = restore (sum, n + 22); \
+    sum = sum / (n + 23); \
+    sum = restore (sum, n + 23); \
+    sum = sum / (n + 24); \
+    sum = restore (sum, n + 24); \
+    sum = sum / (n + 25); \
+    sum = restore (sum, n + 25); \
+    sum = sum / (n + 26); \
+    sum = restore (sum, n + 26); \
+    sum = sum / (n + 27); \
+    sum = restore (sum, n + 27); \
+    sum = sum / (n + 28); \
+    sum = restore (sum, n + 28); \
+    sum = sum / (n + 29); \
+    sum = restore (sum, n + 29); \
+    sum = sum / (n + 30); \
+    sum = restore (sum, n + 30); \
+    sum = sum / (n + 31); \
+    sum = restore (sum, n + 31); \
+    sum = sum / (n + 32); \
+    sum = restore (sum, n + 32); \
+    sum = sum / (n + 33); \
+    sum = restore (sum, n + 33); \
+    sum = sum / (n + 34); \
+    sum = restore (sum, n + 34); \
+    sum = sum / (n + 35); \
+    sum = restore (sum, n + 35); \
+    sum = sum / (n + 36); \
+    sum = restore (sum, n + 36); \
+    sum = sum / (n + 37); \
+    sum = restore (sum, n + 37); \
+    sum = sum / (n + 38); \
+    sum = restore (sum, n + 38); \
+    sum = sum / (n + 39); \
+    sum = restore (sum, n + 39); \
+    sum = sum / (n + 40); \
+    sum = restore (sum, n + 40); \
+    sum = sum / (n + 41); \
+    sum = restore (sum, n + 41); \
+    sum = sum / (n + 42); \
+    sum = restore (sum, n + 42); \
+    sum = sum / (n + 43); \
+    sum = restore (sum, n + 43); \
+    sum = sum / (n + 44); \
+    sum = restore (sum, n + 44); \
+    sum = sum / (n + 45); \
+    sum = restore (sum, n + 45); \
+    sum = sum / (n + 46); \
+    sum = restore (sum, n + 46); \
+    sum = sum / (n + 47); \
+    sum = restore (sum, n + 47); \
+    sum = sum / (n + 48); \
+    sum = restore (sum, n + 48); \
+    sum = sum / (n + 49); \
+    sum = restore (sum, n + 49); \
+    sum = sum / (n + 50); \
+    sum = restore (sum, n + 50); \
+    sum = sum / (n + 51); \
+    sum = restore (sum, n + 51); \
+    sum = sum / (n + 52); \
+    sum = restore (sum, n + 52); \
+    sum = sum / (n + 53); \
+    sum = restore (sum, n + 53); \
+    sum = sum / (n + 54); \
+    sum = restore (sum, n + 54); \
+    sum = sum / (n + 55); \
+    sum = restore (sum, n + 55); \
+    sum = sum / (n + 56); \
+    sum = restore (sum, n + 56); \
+    sum = sum / (n + 57); \
+    sum = restore (sum, n + 57); \
+    sum = sum / (n + 58); \
+    sum = restore (sum, n + 58); \
+    sum = sum / (n + 59); \
+    sum = restore (sum, n + 59); \
+    sum = sum / (n + 60); \
+    sum = restore (sum, n + 60); \
+    sum = sum / (n + 61); \
+    sum = restore (sum, n + 61); \
+    sum = sum / (n + 62); \
+    sum = restore (sum, n + 62); \
+    sum = sum / (n + 63); \
+    sum = restore (sum, n + 63); \
+    sum = sum / (n + 64); \
+    sum = restore (sum, n + 64); \
+    sum = sum / (n + 65); \
+    sum = restore (sum, n + 65); \
+    sum = sum / (n + 66); \
+    sum = restore (sum, n + 66); \
+    sum = sum / (n + 67); \
+    sum = restore (sum, n + 67); \
+    sum = sum / (n + 68); \
+    sum = restore (sum, n + 68); \
+    sum = sum / (n + 69); \
+    sum = restore (sum, n + 69); \
+    sum = sum / (n + 70); \
+    sum = restore (sum, n + 70); \
+    sum = sum / (n + 71); \
+    sum = restore (sum, n + 71); \
+    sum = sum / (n + 72); \
+    sum = restore (sum, n + 72); \
+    sum = sum / (n + 73); \
+    sum = restore (sum, n + 73); \
+    sum = sum / (n + 74); \
+    sum = restore (sum, n + 74); \
+    sum = sum / (n + 75); \
+    sum = restore (sum, n + 75); \
+    sum = sum / (n + 76); \
+    sum = restore (sum, n + 76); \
+    sum = sum / (n + 77); \
+    sum = restore (sum, n + 77); \
+    sum = sum / (n + 78); \
+    sum = restore (sum, n + 78); \
+    sum = sum / (n + 79); \
+    sum = restore (sum, n + 79); \
+    sum = sum / (n + 80); \
+    sum = restore (sum, n + 80); \
+    sum = sum / (n + 81); \
+    sum = restore (sum, n + 81); \
+    sum = sum / (n + 82); \
+    sum = restore (sum, n + 82); \
+    sum = sum / (n + 83); \
+    sum = restore (sum, n + 83); \
+    sum = sum / (n + 84); \
+    sum = restore (sum, n + 84); \
+    sum = sum / (n + 85); \
+    sum = restore (sum, n + 85); \
+    sum = sum / (n + 86); \
+    sum = restore (sum, n + 86); \
+    sum = sum / (n + 87); \
+    sum = restore (sum, n + 87); \
+    sum = sum / (n + 88); \
+    sum = restore (sum, n + 88); \
+    sum = sum / (n + 89); \
+    sum = restore (sum, n + 89); \
+    sum = sum / (n + 90); \
+    sum = restore (sum, n + 90); \
+    sum = sum / (n + 91); \
+    sum = restore (sum, n + 91); \
+    sum = sum / (n + 92); \
+    sum = restore (sum, n + 92); \
+    sum = sum / (n + 93); \
+    sum = restore (sum, n + 93); \
+    sum = sum / (n + 94); \
+    sum = restore (sum, n + 94); \
+    sum = sum / (n + 95); \
+    sum = restore (sum, n + 95); \
+    sum = sum / (n + 96); \
+    sum = restore (sum, n + 96); \
+    sum = sum / (n + 97); \
+    sum = restore (sum, n + 97); \
+    sum = sum / (n + 98); \
+    sum = restore (sum, n + 98); \
+    sum = sum / (n + 99); \
+    sum = restore (sum, n + 99); \
+    sum = sum / (n + 100); \
+    sum = restore (sum, n + 100); \
+    sum = sum / (n + 101); \
+    sum = restore (sum, n + 101); \
+    sum = sum / (n + 102); \
+    sum = restore (sum, n + 102); \
+    sum = sum / (n + 103); \
+    sum = restore (sum, n + 103); \
+    sum = sum / (n + 104); \
+    sum = restore (sum, n + 104); \
+    sum = sum / (n + 105); \
+    sum = restore (sum, n + 105); \
+    sum = sum / (n + 106); \
+    sum = restore (sum, n + 106); \
+    sum = sum / (n + 107); \
+    sum = restore (sum, n + 107); \
+    sum = sum / (n + 108); \
+    sum = restore (sum, n + 108); \
+    sum = sum / (n + 109); \
+    sum = restore (sum, n + 109); \
+    sum = sum / (n + 110); \
+    sum = restore (sum, n + 110); \
+    sum = sum / (n + 111); \
+    sum = restore (sum, n + 111); \
+    sum = sum / (n + 112); \
+    sum = restore (sum, n + 112); \
+    sum = sum / (n + 113); \
+    sum = restore (sum, n + 113); \
+    sum = sum / (n + 114); \
+    sum = restore (sum, n + 114); \
+    sum = sum / (n + 115); \
+    sum = restore (sum, n + 115); \
+    sum = sum / (n + 116); \
+    sum = restore (sum, n + 116); \
+    sum = sum / (n + 117); \
+    sum = restore (sum, n + 117); \
+    sum = sum / (n + 118); \
+    sum = restore (sum, n + 118); \
+    sum = sum / (n + 119); \
+    sum = restore (sum, n + 119); \
+    sum = sum / (n + 120); \
+    sum = restore (sum, n + 120); \
+    sum = sum / (n + 121); \
+    sum = restore (sum, n + 121); \
+    sum = sum / (n + 122); \
+    sum = restore (sum, n + 122); \
+    sum = sum / (n + 123); \
+    sum = restore (sum, n + 123); \
+    sum = sum / (n + 124); \
+    sum = restore (sum, n + 124); \
+    sum = sum / (n + 125); \
+    sum = restore (sum, n + 125); \
+    sum = sum / (n + 126); \
+    sum = restore (sum, n + 126); \
+    sum = sum / (n + 127); \
+    sum = restore (sum, n + 127); \
+    sum = sum / (n + 128); \
+    sum = restore (sum, n + 128); \
+    sum = sum / (n + 129); \
+    sum = restore (sum, n + 129); \
+    sum = sum / (n + 130); \
+    sum = restore (sum, n + 130); \
+    sum = sum / (n + 131); \
+    sum = restore (sum, n + 131); \
+    sum = sum / (n + 132); \
+    sum = restore (sum, n + 132); \
+    sum = sum / (n + 133); \
+    sum = restore (sum, n + 133); \
+    sum = sum / (n + 134); \
+    sum = restore (sum, n + 134); \
+    sum = sum / (n + 135); \
+    sum = restore (sum, n + 135); \
+    sum = sum / (n + 136); \
+    sum = restore (sum, n + 136); \
+    sum = sum / (n + 137); \
+    sum = restore (sum, n + 137); \
+    sum = sum / (n + 138); \
+    sum = restore (sum, n + 138); \
+    sum = sum / (n + 139); \
+    sum = restore (sum, n + 139); \
+    sum = sum / (n + 140); \
+    sum = restore (sum, n + 140); \
+    sum = sum / (n + 141); \
+    sum = restore (sum, n + 141); \
+    sum = sum / (n + 142); \
+    sum = restore (sum, n + 142); \
+    sum = sum / (n + 143); \
+    sum = restore (sum, n + 143); \
+    sum = sum / (n + 144); \
+    sum = restore (sum, n + 144); \
+    sum = sum / (n + 145); \
+    sum = restore (sum, n + 145); \
+    sum = sum / (n + 146); \
+    sum = restore (sum, n + 146); \
+    sum = sum / (n + 147); \
+    sum = restore (sum, n + 147); \
+    sum = sum / (n + 148); \
+    sum = restore (sum, n + 148); \
+    sum = sum / (n + 149); \
+    sum = restore (sum, n + 149); \
+    sum = sum / (n + 150); \
+    sum = restore (sum, n + 150); \
+    break;
+
+__attribute__((noinline, noclone)) long long
+test_and_branch (int selector, int addend, int cond)
+{
+  long long sum = selector + 1;
+
+  if (selector > 200)
+    {
+start0:
+      return sum - 1;
+start1:
+      return sum + 1;
+start2:
+      return sum;
+start3:
+      return sum - 2;
+    }
+  else
+    {
+      switch (selector)
+	{
+	  CASE_ENTRY (1)
+	  CASE_ENTRY (2)
+	  CASE_ENTRY (3)
+	  CASE_ENTRY (4)
+	  CASE_ENTRY (5)
+	  CASE_ENTRY (6)
+	  CASE_ENTRY (7)
+	  CASE_ENTRY (8)
+	  CASE_ENTRY (9)
+	  CASE_ENTRY (10)
+	  CASE_ENTRY (11)
+	  CASE_ENTRY (12)
+	  CASE_ENTRY (13)
+	  CASE_ENTRY (14)
+	  CASE_ENTRY (15)
+	  CASE_ENTRY (16)
+	  CASE_ENTRY (17)
+	  CASE_ENTRY (18)
+	  CASE_ENTRY (19)
+	  CASE_ENTRY (20)
+	  CASE_ENTRY (21)
+	  CASE_ENTRY (22)
+	  CASE_ENTRY (23)
+	  CASE_ENTRY (24)
+	  CASE_ENTRY (25)
+	  CASE_ENTRY (26)
+	  CASE_ENTRY (27)
+	  CASE_ENTRY (28)
+	  CASE_ENTRY (29)
+	  CASE_ENTRY (30)
+	  CASE_ENTRY (31)
+	  CASE_ENTRY (32)
+	  CASE_ENTRY (33)
+	  CASE_ENTRY (34)
+	  CASE_ENTRY (35)
+	  CASE_ENTRY (36)
+	  CASE_ENTRY (37)
+	  CASE_ENTRY (38)
+	  CASE_ENTRY (39)
+	  CASE_ENTRY (40)
+	  CASE_ENTRY (41)
+	  CASE_ENTRY (42)
+	  CASE_ENTRY (43)
+	  CASE_ENTRY (44)
+	  CASE_ENTRY (45)
+	  CASE_ENTRY (46)
+	  CASE_ENTRY (47)
+	  CASE_ENTRY (48)
+	  CASE_ENTRY (49)
+	  CASE_ENTRY (50)
+	  CASE_ENTRY (51)
+	  CASE_ENTRY (52)
+	  CASE_ENTRY (53)
+	  CASE_ENTRY (54)
+	  CASE_ENTRY (55)
+	  CASE_ENTRY (56)
+	  CASE_ENTRY (57)
+	  CASE_ENTRY (58)
+	  CASE_ENTRY (59)
+	  CASE_ENTRY (60)
+	  CASE_ENTRY (61)
+	  CASE_ENTRY (62)
+	  CASE_ENTRY (63)
+	  CASE_ENTRY (64)
+	  CASE_ENTRY (65)
+	  CASE_ENTRY (66)
+	  CASE_ENTRY (67)
+	  CASE_ENTRY (68)
+	  CASE_ENTRY (69)
+	  CASE_ENTRY (70)
+	  CASE_ENTRY (71)
+	  CASE_ENTRY (72)
+	  CASE_ENTRY (73)
+	  CASE_ENTRY (74)
+	  CASE_ENTRY (75)
+	  CASE_ENTRY (76)
+	  CASE_ENTRY (77)
+	  CASE_ENTRY (78)
+	  CASE_ENTRY (79)
+	  CASE_ENTRY (80)
+	  CASE_ENTRY (81)
+	  CASE_ENTRY (82)
+	  CASE_ENTRY (83)
+	  CASE_ENTRY (84)
+	  CASE_ENTRY (85)
+	  CASE_ENTRY (86)
+	  CASE_ENTRY (87)
+	  CASE_ENTRY (88)
+	  CASE_ENTRY (89)
+	  CASE_ENTRY (90)
+	  CASE_ENTRY (91)
+	  CASE_ENTRY (92)
+	  CASE_ENTRY (93)
+	  CASE_ENTRY (94)
+	  CASE_ENTRY (95)
+	  CASE_ENTRY (96)
+	  CASE_ENTRY (97)
+	  CASE_ENTRY (98)
+	  CASE_ENTRY (99)
+	  CASE_ENTRY (100)
+	  CASE_ENTRY (101)
+	  CASE_ENTRY (102)
+	  CASE_ENTRY (103)
+	  CASE_ENTRY (104)
+	  CASE_ENTRY (105)
+	  CASE_ENTRY (106)
+	  CASE_ENTRY (107)
+	  CASE_ENTRY (108)
+	  CASE_ENTRY (109)
+	  CASE_ENTRY (110)
+	  CASE_ENTRY (111)
+	  CASE_ENTRY (112)
+	  CASE_ENTRY (113)
+	  CASE_ENTRY (114)
+	  CASE_ENTRY (115)
+	  CASE_ENTRY (116)
+	  CASE_ENTRY (117)
+	  CASE_ENTRY (118)
+	  CASE_ENTRY (119)
+	  CASE_ENTRY (120)
+	  CASE_ENTRY (121)
+	  CASE_ENTRY (122)
+	  CASE_ENTRY (123)
+	  CASE_ENTRY (124)
+	  CASE_ENTRY (125)
+	  CASE_ENTRY (126)
+	  CASE_ENTRY (127)
+	  CASE_ENTRY (128)
+	  CASE_ENTRY (129)
+	  CASE_ENTRY (130)
+	  CASE_ENTRY (131)
+	  CASE_ENTRY (132)
+	  CASE_ENTRY (133)
+	  CASE_ENTRY (134)
+	  CASE_ENTRY (135)
+	  CASE_ENTRY (136)
+	  CASE_ENTRY (137)
+	  CASE_ENTRY (138)
+	  CASE_ENTRY (139)
+	  CASE_ENTRY (140)
+	  CASE_ENTRY (141)
+	  CASE_ENTRY (142)
+	  CASE_ENTRY (143)
+	  CASE_ENTRY (144)
+	  CASE_ENTRY (145)
+	  CASE_ENTRY (146)
+	  CASE_ENTRY (147)
+	  CASE_ENTRY (148)
+	  CASE_ENTRY (149)
+	  CASE_ENTRY (150)
+	  CASE_ENTRY (151)
+	  CASE_ENTRY (152)
+	  CASE_ENTRY (153)
+	  CASE_ENTRY (154)
+	  CASE_ENTRY (155)
+	  CASE_ENTRY (156)
+	  CASE_ENTRY (157)
+	  CASE_ENTRY (158)
+	  CASE_ENTRY (159)
+	  CASE_ENTRY (160)
+	  CASE_ENTRY (161)
+	  CASE_ENTRY (162)
+	  CASE_ENTRY (163)
+	  CASE_ENTRY (164)
+	  CASE_ENTRY (165)
+	  CASE_ENTRY (166)
+	  CASE_ENTRY (167)
+	  CASE_ENTRY (168)
+	  CASE_ENTRY (169)
+	  CASE_ENTRY (170)
+	  CASE_ENTRY (171)
+	  CASE_ENTRY (172)
+	  CASE_ENTRY (173)
+	  CASE_ENTRY (174)
+	  CASE_ENTRY (175)
+	  CASE_ENTRY (176)
+	  CASE_ENTRY (177)
+	  CASE_ENTRY (178)
+	  CASE_ENTRY (179)
+	  CASE_ENTRY (180)
+	  CASE_ENTRY (181)
+	  CASE_ENTRY (182)
+	  CASE_ENTRY (183)
+	  CASE_ENTRY (184)
+	  CASE_ENTRY (185)
+	  CASE_ENTRY (186)
+	  CASE_ENTRY (187)
+	  CASE_ENTRY (188)
+	  CASE_ENTRY (189)
+	  CASE_ENTRY (190)
+	  CASE_ENTRY (191)
+	  CASE_ENTRY (192)
+	  CASE_ENTRY (193)
+	  CASE_ENTRY (194)
+	  CASE_ENTRY (195)
+	  CASE_ENTRY (196)
+	  CASE_ENTRY (197)
+	  CASE_ENTRY (198)
+	  CASE_ENTRY (199)
+	  CASE_ENTRY (200)
+	}
+
+      do_nothing ((int *)&sum);
+
+      if (cond == 0)
+	goto start0;
+      else if (cond < 0)
+	goto start1;
+      else if ((cond & 0x010) != 0)
+	goto start2;
+      else if (cond >= 14)
+	goto start3;
+
+    }
+
+  return -1;
+}
+
+/* { dg-final { scan-assembler "Lbcond" } } */
+/* { dg-final { scan-assembler "Lcb" } } */
+/* { dg-final { scan-assembler "Ltb" } } */
-- 
1.9.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]