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 combine_tests: proc(first,last);
40
41 dcl first ptr,
42 last ptr;
43
44 dcl (s1,s2,stop_ptr,r1,r2,o1,o2) ptr;
45 dcl (just_combined,is_next,is_target) bit(1) aligned;
46 dcl (opcode1,opcode2) bit(9) aligned;
47 dcl cfo(2) fixed bin(6);
48 dcl wo(2) fixed bin(18);
49 dcl based_bs bit(36) aligned based;
50 dcl mask bit(36) aligned auto;
51
52 dcl declare_temporary entry(bit(36) aligned,fixed bin(31),fixed bin(15),ptr) returns(ptr);
53 dcl generate_constant entry(bit(*) aligned,fixed bin) returns(ptr);
54 dcl create_operator entry(bit(9) aligned,fixed bin(15)) returns(ptr);
55 dcl create_reference entry(ptr) returns(ptr);
56 dcl share_expression entry(ptr) returns(ptr);
57 dcl adjust_ref_count entry(ptr,fixed bin);
58 dcl free_node entry(ptr);
59
60 dcl (divide,mod,null,substr) builtin;
61
62 %include cgsystem;
63 %include boundary;
64 %include op_codes;
65 %include nodes;
66 %include label;
67 %include list;
68 %include symbol;
69 %include reference;
70 %include operator;
71 %include statement;
72 %include mask;
73
74 just_combined = "0"b;
75 stop_ptr = first;
76
77 do s2 = last repeat s1 while (s2 ^= stop_ptr);
78 s1 = s2 -> statement.back;
79
80 if s2 -> statement.labels = null
81 then do;
82 o2 = s2 -> statement.root;
83 opcode2 = o2 -> operator.op_code;
84
85 if just_combined
86 then r2 = o2 -> operand(2) -> operand(2);
87 else do;
88 if opcode2 ^= jump_true & opcode2 ^= jump_false
89 then goto next;
90 r2 = o2 -> operand(2);
91 if ^ candidate(r2)
92 then goto next;
93 end;
94
95 o1 = s1 -> statement.root;
96 r1 = o1 -> operand(2);
97 opcode1 = o1 -> operator.op_code;
98
99 if opcode1 = jump_true | opcode1 = jump_false
100 then if candidate(r1)
101 then if same_word(r1,r2)
102 then do;
103 is_target = o1 -> operand(1) = o2 -> operand(1);
104 is_next = "0"b;
105 if o1 -> operand(1) -> node.type = label_node
106 then if o1 -> operand(1) -> label.statement = s2 -> statement.next
107 then is_next = "1"b;
108
109 if just_combined
110 then do;
111 if opcode1 = jump_true
112 & ((opcode2 = jump_true & is_target) | (opcode2 = jump_false & is_next))
113 | opcode1 = jump_false
114 & ((opcode2 = jump_if_eq & is_next) | (opcode2 = jump_if_ne & is_target))
115 then do;
116 call continue_combining;
117 go to step;
118 end;
119 end;
120
121 else do;
122 if opcode1 = jump_true
123 then if opcode2 = jump_true
124 then if is_target
125 then do;
126 call combine(jump_true,2);
127 go to step;
128 end;
129 else;
130 else if is_next
131 then do;
132 call combine(jump_false,2);
133 go to step;
134 end;
135 else;
136 else if opcode2 = jump_true
137 then if is_next
138 then do;
139 call combine(jump_if_eq,3);
140 go to step;
141 end;
142 else;
143 else if is_target
144 then do;
145 call combine(jump_if_ne,3);
146 go to step;
147 end;
148 end;
149 end;
150 end;
151
152 next: just_combined = "0"b;
153 step:
154 end;
155
156 return;
157
158
159 candidate: proc(p) returns(bit(1) aligned);
160
161 dcl p ptr;
162
163 if p -> node.type = reference_node
164 then if p -> reference.c_length = 1
165 then if p -> reference.symbol -> symbol.packed
166 then if ^ p -> reference.fo_in_qual & ^ p -> reference.padded_ref & ^ p -> reference.aligned_ref
167 then if p -> reference.units = 0 | p -> reference.units = word_
168 | p -> reference.offset = null | p -> reference.modword_in_offset
169 then return("1"b);
170
171 return("0"b);
172
173 end;
174
175
176 same_word: proc(p1,p2) returns(bit(1) aligned);
177
178 dcl (p1,p2) ptr;
179
180 dcl (r(2),adam(2),a) ptr;
181 dcl i fixed bin;
182
183 r(1) = p1;
184 r(2) = p2;
185
186 if r(1) -> reference.offset = r(2) -> reference.offset
187 & r(1) -> reference.qualifier = r(2) -> reference.qualifier
188 then do;
189 do i = 1 to 2;
190 wo(i) = divide(r(i) -> reference.c_offset,units_per_word(r(i) -> reference.units),18,0);
191 cfo(i) = mod(r(i) -> reference.c_offset * convert_offset(r(i) -> reference.units), bits_per_word);
192 if cfo(i) ^= 0
193 then if r(i) -> reference.c_offset < 0
194 then wo(i) = wo(i) - 1;
195
196 do a = r(i) -> reference.symbol repeat a -> symbol.father
197 while (a -> symbol.father ^= null);
198 end;
199 adam(i) = a;
200 end;
201
202 if wo(1) = wo(2) & adam(1) = adam(2)
203 then return("1"b);
204 end;
205
206 return("0"b);
207
208 end;
209
210
211 continue_combining: proc;
212
213 dcl p ptr;
214
215 mask = o2 -> operand(2) -> operand(3) -> reference.symbol -> symbol.initial -> based_bs;
216 substr(mask,cfo(1)+1,1) = "1"b;
217 p = generate_constant(mask,1);
218 o2 -> operand(2) -> operand(3) = p;
219 if o2 -> operator.number = 3
220 then o2 -> operand(3) = p;
221
222 call merge_and_unthread;
223
224 just_combined = "1"b;
225
226 end;
227
228
229 combine: proc(op_code,num);
230
231 dcl op_code bit(9) aligned,
232 num fixed bin(15);
233
234 dcl (a,p,r,m) ptr;
235
236 if num ^= 2
237 then do;
238 p = create_operator(op_code,num);
239 p -> operand(1) = o2 -> operand(1);
240 call free_node(o2);
241 o2 = p;
242 end;
243 else ;
244
245 r = create_reference(null);
246 r -> reference = r2 -> reference;
247 if ^ r -> reference.shared
248 then do;
249 r -> reference.ref_count = 1;
250 if r -> reference.qualifier ^= null
251 then r -> reference.qualifier = share_expression((r -> reference.qualifier));
252 if r -> reference.offset ^= null
253 then r -> reference.offset = share_expression((r -> reference.offset));
254 call adjust_ref_count(r2,-1);
255 end;
256
257 r -> reference.c_length = bits_per_word;
258
259 if r -> reference.units ^= 0 & r -> reference.units < word_
260 then do;
261 r -> reference.units = word_;
262 r -> reference.c_offset = wo(2);
263 r -> reference.modword_in_offset = "0"b;
264 end;
265
266 a = create_operator(and_bits,3);
267 a -> operand(2) = r;
268 a -> operand(1) = declare_temporary(bit_mask|aligned_mask,(bits_per_word),0,null);
269
270 mask = (36)"0"b;
271 substr(mask,cfo(1)+1,1) = "1"b;
272 substr(mask,cfo(2)+1,1) = "1"b;
273 p = generate_constant(mask,1);
274 a -> operand(3) = p;
275
276 o2 -> operand(2) = a;
277 if num > 2
278 then o2 -> operand(3) = p;
279
280 call merge_and_unthread;
281
282 just_combined = "1"b;
283
284 end;
285
286
287 merge_and_unthread: proc;
288
289
290
291
292 s1 -> statement.root = o2;
293 call free_node(s2);
294
295 call decrement_target_expression((o1 -> operand(1)));
296 if ^ o1 -> operand(2) -> reference.shared
297 then call adjust_ref_count((o1 -> operand(2)), -1);
298 call free_node(o1);
299
300 end;
301
302
303 decrement_target_expression: proc(pt);
304
305 dcl (p,pt,s,vector,l) ptr;
306 dcl i fixed bin;
307
308
309
310
311
312 p = pt;
313
314 if p -> node.type = label_node
315 then do;
316 s = p -> label.statement;
317 s -> statement.reference_count = s -> statement.reference_count - 1;
318 return;
319 end;
320
321 if p -> node.type = reference_node
322 then if p -> reference.symbol ^= null
323 then if p -> reference.symbol -> node.type = label_node
324 then do;
325 l = p -> reference.symbol;
326 vector = l -> label.statement;
327
328 s = vector -> element(p -> reference.c_offset + 1);
329 s -> statement.reference_count = s -> statement.reference_count - 1;
330 end;
331
332 call adjust_ref_count(p,-1);
333
334 end;
335
336 end;