summarylogtreecommitdiffstats
path: root/bz85638.patch
blob: 9ed00e836d3c534c081f5ad1267e0be21a55afaf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
--- gcc/bb-reorder.c	(revision 259642)
+++ gcc/bb-reorder.c	(working copy)
@@ -117,6 +117,7 @@ 
 #include "fibonacci_heap.h"
 #include "stringpool.h"
 #include "attribs.h"
+#include "common/common-target.h"
 
 /* The number of rounds.  In most cases there will only be 4 rounds, but
    when partitioning hot and cold basic blocks into separate sections of
@@ -1408,17 +1409,95 @@ get_uncond_jump_length (void)
   return length;
 }
 
+/* Create a forwarder block to OLD_BB starting with NEW_LABEL and in the
+   other partition wrt OLD_BB.  */
+
+static basic_block
+create_forwarder_block (rtx_code_label *new_label, basic_block old_bb)
+{
+  /* Put the new label and a jump in the new basic block.  */
+  rtx_insn *label = emit_label (new_label);
+  rtx_code_label *old_label = block_label (old_bb);
+  rtx_insn *jump = emit_jump_insn (targetm.gen_jump (old_label));
+  JUMP_LABEL (jump) = old_label;
+
+  /* Create the new basic block and put it in last position.  */
+  basic_block last_bb = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb;
+  basic_block new_bb = create_basic_block (label, jump, last_bb);
+  new_bb->aux = last_bb->aux;
+  new_bb->count = old_bb->count;
+  last_bb->aux = new_bb;
+
+  emit_barrier_after_bb (new_bb);
+
+  make_single_succ_edge (new_bb, old_bb, 0);
+
+  /* Make sure the new basic block is in the other partition.  */
+  unsigned new_partition = BB_PARTITION (old_bb);
+  new_partition ^= BB_HOT_PARTITION | BB_COLD_PARTITION;
+  BB_SET_PARTITION (new_bb, new_partition);
+
+  return new_bb;
+}
+
+/* The common landing pad in block OLD_BB has edges from both partitions.
+   Add a new landing pad that will just jump to the old one and split the
+   edges so that no EH edge crosses partitions.  */
+
+static void
+sjlj_fix_up_crossing_landing_pad (basic_block old_bb)
+{
+  const unsigned lp_len = cfun->eh->lp_array->length ();
+  edge_iterator ei;
+  edge e;
+
+  /* Generate the new common landing-pad label.  */
+  rtx_code_label *new_label = gen_label_rtx ();
+  LABEL_PRESERVE_P (new_label) = 1;
+
+  /* Create the forwarder block.  */
+  basic_block new_bb = create_forwarder_block (new_label, old_bb);
+
+  /* Create the map from old to new lp index and initialize it.  */
+  unsigned *index_map = (unsigned *) alloca (lp_len * sizeof (unsigned));
+  memset (index_map, 0, lp_len * sizeof (unsigned));
+
+  /* Fix up the edges.  */
+  for (ei = ei_start (old_bb->preds); (e = ei_safe_edge (ei)) != NULL; )
+    if (e->src != new_bb && BB_PARTITION (e->src) == BB_PARTITION (new_bb))
+      {
+	rtx_insn *insn = BB_END (e->src);
+	rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+
+	gcc_assert (note != NULL);
+	const unsigned old_index = INTVAL (XEXP (note, 0));
+
+	/* Generate the new landing-pad structure.  */
+	if (index_map[old_index] == 0)
+	  {
+	    eh_landing_pad old_lp = (*cfun->eh->lp_array)[old_index];
+	    eh_landing_pad new_lp = gen_eh_landing_pad (old_lp->region);
+	    new_lp->post_landing_pad = old_lp->post_landing_pad;
+	    new_lp->landing_pad = new_label;
+	    index_map[old_index] = new_lp->index;
+	  }
+	XEXP (note, 0) = GEN_INT (index_map[old_index]);
+
+	/* Adjust the edge to the new destination.  */
+	redirect_edge_succ (e, new_bb);
+      }
+    else
+      ei_next (&ei);
+}
+
 /* The landing pad OLD_LP, in block OLD_BB, has edges from both partitions.
    Add a new landing pad that will just jump to the old one and split the
    edges so that no EH edge crosses partitions.  */
 
 static void
-fix_up_crossing_landing_pad (eh_landing_pad old_lp, basic_block old_bb)
+dw2_fix_up_crossing_landing_pad (eh_landing_pad old_lp, basic_block old_bb)
 {
   eh_landing_pad new_lp;
-  basic_block new_bb, last_bb;
-  rtx_insn *jump;
-  unsigned new_partition;
   edge_iterator ei;
   edge e;
 
@@ -1428,32 +1507,12 @@ fix_up_crossing_landing_pad (eh_landing_
   new_lp->landing_pad = gen_label_rtx ();
   LABEL_PRESERVE_P (new_lp->landing_pad) = 1;
 
-  /* Put appropriate instructions in new bb.  */
-  rtx_code_label *new_label = emit_label (new_lp->landing_pad);
-
-  rtx_code_label *old_label = block_label (old_bb);
-  jump = emit_jump_insn (targetm.gen_jump (old_label));
-  JUMP_LABEL (jump) = old_label;
-
-  /* Create new basic block to be dest for lp.  */
-  last_bb = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb;
-  new_bb = create_basic_block (new_label, jump, last_bb);
-  new_bb->aux = last_bb->aux;
-  new_bb->count = old_bb->count;
-  last_bb->aux = new_bb;
-
-  emit_barrier_after_bb (new_bb);
-
-  make_single_succ_edge (new_bb, old_bb, 0);
-
-  /* Make sure new bb is in the other partition.  */
-  new_partition = BB_PARTITION (old_bb);
-  new_partition ^= BB_HOT_PARTITION | BB_COLD_PARTITION;
-  BB_SET_PARTITION (new_bb, new_partition);
+  /* Create the forwarder block.  */
+  basic_block new_bb = create_forwarder_block (new_lp->landing_pad, old_bb);
 
   /* Fix up the edges.  */
   for (ei = ei_start (old_bb->preds); (e = ei_safe_edge (ei)) != NULL; )
-    if (e->src != new_bb && BB_PARTITION (e->src) == new_partition)
+    if (e->src != new_bb && BB_PARTITION (e->src) == BB_PARTITION (new_bb))
       {
 	rtx_insn *insn = BB_END (e->src);
 	rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
@@ -1651,9 +1710,11 @@ find_rarely_executed_basic_blocks_and_cr
 
   /* The format of .gcc_except_table does not allow landing pads to
      be in a different partition as the throw.  Fix this by either
-     moving or duplicating the landing pads.  */
+     moving the landing pads or inserting forwarder landing pads.  */
   if (cfun->eh->lp_array)
     {
+      const bool sjlj
+	= (targetm_common.except_unwind_info (&global_options) == UI_SJLJ);
       unsigned i;
       eh_landing_pad lp;
 
@@ -1685,13 +1746,18 @@ find_rarely_executed_basic_blocks_and_cr
 	      which ^= BB_HOT_PARTITION | BB_COLD_PARTITION;
 	      BB_SET_PARTITION (bb, which);
 	    }
+	  else if (sjlj)
+	    sjlj_fix_up_crossing_landing_pad (bb);
 	  else
-	    fix_up_crossing_landing_pad (lp, bb);
+	    dw2_fix_up_crossing_landing_pad (lp, bb);
+
+	  /* There is a single, common landing pad in SJLJ mode.  */
+	  if (sjlj)
+	    break;
 	}
     }
 
   /* Mark every edge that crosses between sections.  */
-
   FOR_EACH_BB_FN (bb, cfun)
     FOR_EACH_EDGE (e, ei, bb->succs)
       {