Bug Summary

File:src/of_cprop.c
Warning:line 799, column 30
Dereference of null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name of_cprop.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/kfp/aldor/aldor/aldor/src -fcoverage-compilation-dir=/home/kfp/aldor/aldor/aldor/src -resource-dir /usr/local/lib/clang/18 -D PACKAGE_NAME="aldor" -D PACKAGE_TARNAME="aldor" -D PACKAGE_VERSION="1.4.0" -D PACKAGE_STRING="aldor 1.4.0" -D PACKAGE_BUGREPORT="aldor@xinutec.org" -D PACKAGE_URL="" -D PACKAGE="aldor" -D VERSION="1.4.0" -D YYTEXT_POINTER=1 -D HAVE_STDIO_H=1 -D HAVE_STDLIB_H=1 -D HAVE_STRING_H=1 -D HAVE_INTTYPES_H=1 -D HAVE_STDINT_H=1 -D HAVE_STRINGS_H=1 -D HAVE_SYS_STAT_H=1 -D HAVE_SYS_TYPES_H=1 -D HAVE_UNISTD_H=1 -D STDC_HEADERS=1 -D HAVE_LIBREADLINE=1 -D HAVE_READLINE_READLINE_H=1 -D HAVE_READLINE_HISTORY=1 -D HAVE_READLINE_HISTORY_H=1 -D USE_GLOOP_SHELL=1 -D GENERATOR_COROUTINES=0 -D HAVE_DLFCN_H=1 -D LT_OBJDIR=".libs/" -I . -D VCSVERSION="2c53e759f1e00e345f8b172e7139debda72fda13" -internal-isystem /usr/local/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-empty-body -Wno-enum-compare -Wno-missing-field-initializers -Wno-unused -Wno-unused-parameter -Wno-error=format -Wno-error=type-limits -Wno-error=strict-aliasing -Wno-sign-compare -Wno-error=shift-negative-value -Wno-error=clobbered -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2026-01-15-223856-845667-1 -x c of_cprop.c
1/*****************************************************************************
2 *
3 * of_cprop.c: Copy Propagation
4 *
5 * Copyright (c) 1990-2007 Aldor Software Organization Ltd (Aldor.org).
6 *
7 ****************************************************************************/
8/***************************************************************************
9 *
10 * Copy propagation optimization
11 *
12 * (Refer. to 'Aho, Sethi, Ullman: "Compilers: Principles, Techinques,
13 * and Tools", Addison Wesley)
14 *
15 * The implementation of this optimization is really close to the
16 * algorithm used for UD chains (see top of usedef.c file)
17 * The main differences are:
18 *
19 * - VarCopiesVect[i] is the list of all the copies where (Loc i) is
20 * lhs or rhs (in usedef is only lhs)
21 * - Sets Gen and Kill are build in a slightly different way.
22 * - During phase (3), instead of attaching definitions on each usage,
23 * copy propagation is performed. Each usage of (Loc i) such that there
24 * is a unique copy in its reachingDefs list is substitued with the rhs
25 * of the copy.
26 *
27 * Implementation notes:
28 *
29 * - Once the dflow analysis has been performed, cpCopyPropagate is called.
30 * For each block, cpCopyPropagate0 is called on the corresponding foam
31 * tree. The algorithm try to substitute an usage skipping all the
32 * intermediate copies.
33 * Consider, in example, the following sequence:
34 * (L1 := L0), (L2 := L1), (L3 := L2), foo(L3)
35 * In this case, the rightmost occurrence of L3 is initially replaced
36 * by L2; in the second step L2 is replaced by L1, finally with L0.
37 * Therefore foo(L3) will become foo(L0).
38 *
39 *************************************************************************
40 *
41 * DEFINITIONS
42 *
43 * For the current implementation:
44 * - a TMPVAR is a Loc or a Par.
45 * - a IMMEDIATE is SInt, Char, Bool, Byte, etc. (see cpIsImmediate)
46 * - a DEFinition is a Def or a Set stmt. of kind:
47 * (DEF TMPVAR expr)
48 * or
49 * (DEF (Values ...) expr)
50 *
51 * - CopyableCast is of the form (Cast type TMPVAR)
52 *
53 * - a COPY is a stmt. of kind:
54 * (DEF TMPVAR TMPVAR)
55 * or
56 * (DEF TMPVAR (Cast type TMPVAR))
57 * or
58 * (DEF TMPVAR IMMEDIATE)
59 * or
60 * (DEF TMPVAR (Cast type IMMEDIATE))
61 *
62 *
63 *************************************************************************/
64
65#include "debug.h"
66#include "dflow.h"
67#include "flog.h"
68#include "of_cprop.h"
69#include "of_peep.h"
70#include "of_util.h"
71#include "optfoam.h"
72#include "optinfo.h"
73#include "opttools.h"
74#include "store.h"
75#include "bigint.h"
76
77/****************************************************************************
78 * :: Macros
79 ****************************************************************************/
80
81# define cpIsTmpVar(var)(((var)->hdr.tag) == FOAM_Loc || ((var)->hdr.tag) == FOAM_Par
)
(foamTag(var)((var)->hdr.tag) == FOAM_Loc || foamTag(var)((var)->hdr.tag) == FOAM_Par)
82
83# define cpIsTmpVarOrValues(foam)((((foam)->hdr.tag) == FOAM_Loc || ((foam)->hdr.tag) ==
FOAM_Par) || ((foam)->hdr.tag)==FOAM_Values)
(cpIsTmpVar(foam)(((foam)->hdr.tag) == FOAM_Loc || ((foam)->hdr.tag) == FOAM_Par
)
|| \
84 foamTag(foam)((foam)->hdr.tag)==FOAM_Values)
85
86# define cpIsSpecialCast(foam)((foam)->foamCast.type == FOAM_SFlo) ((foam)->foamCast.type == FOAM_SFlo)
87
88# define cpIsCopyableCast(foam)(((foam)->hdr.tag)==FOAM_Cast && !((foam)->foamCast
.type == FOAM_SFlo) && ((((foam->foamCast.expr)->
hdr.tag) == FOAM_Loc || ((foam->foamCast.expr)->hdr.tag
) == FOAM_Par) || cpIsImmediate(foam->foamCast.expr)))
(foamTag(foam)((foam)->hdr.tag)==FOAM_Cast && \
89 !cpIsSpecialCast(foam)((foam)->foamCast.type == FOAM_SFlo) && \
90 (cpIsTmpVar(foam->foamCast.expr)(((foam->foamCast.expr)->hdr.tag) == FOAM_Loc || ((foam
->foamCast.expr)->hdr.tag) == FOAM_Par)
|| \
91 cpIsImmediate(foam->foamCast.expr)))
92
93# define cpIsCopy(foam)(cpIsDef(foam) && cpDefIsCopy(foam)) (cpIsDef(foam) && cpDefIsCopy(foam))
94
95
96#define cpDF_CUTOFF200 200 /* Max no dataflow iterations to converge. */
97
98# define cpDefNo(foam)((foam)->foamGen.hdr.info.defNo) ((foam)->foamGen.hdr.info.defNo)
99
100 /* given a (Loc) or a (Par), assign to varno the index in the varDefsVect */
101# define cpGetVarNo(varno, foamVar)if (((foamVar)->hdr.tag) == FOAM_Par) (varno) = (foamVar)->
foamPar.index + cpInfo.nLocals; else (varno) = (foamVar)->
foamLoc.index;
\
102 if (foamTag(foamVar)((foamVar)->hdr.tag) == FOAM_Par) \
103 (varno) = (foamVar)->foamPar.index + cpInfo.nLocals;\
104 else \
105 (varno) = (foamVar)->foamLoc.index;
106
107/****************************************************************************
108 * :: Debug
109 ****************************************************************************/
110
111Bool cpDfDebug = false((int) 0);
112Bool cpDebug = false((int) 0);
113
114#define cpDfDEBUGif (!cpDfDebug) { } else afprintf DEBUG_IF(cpDf)if (!cpDfDebug) { } else afprintf
115#define cpDEBUGif (!cpDebug) { } else afprintf DEBUG_IF(cp)if (!cpDebug) { } else afprintf
116
117/****************************************************************************
118 * :: Global Data Structures
119 ****************************************************************************/
120
121typedef struct {
122 FoamList * varCopiesVect;
123 int nParams;
124 int nLocals;
125 int nCopies;
126
127 int nPropagated;
128
129 BitvClass bitvClass;
130} CpInfo;
131
132static CpInfo cpInfo;
133static Bool cpFirstTime;
134
135/* maybe a bitmap ? */
136typedef enum { CP_Lhs, CP_Rhs, CP_CEnv } CpFlagState;
137
138/****************************************************************************
139 *
140 * :: Local prototypes
141 *
142 ****************************************************************************/
143
144localstatic Foam cpProg (Foam);
145
146localstatic void cpFlog0 (FlowGraph);
147
148localstatic void cpVarCopiesVectBuild (Foam);
149localstatic void cpVarCopiesVectUpdate (Foam);
150localstatic void cpVarCopiesVectFree (void);
151extern void cpVarCopiesVectPrint (void);
152
153localstatic Bool cpIsDef (Foam);
154localstatic Bool cpDefIsCopy (Foam);
155localstatic Bool cpIsImmediate (Foam);
156localstatic Foam cpRhsVarFrCopy (Foam);
157
158localstatic void cpFillGenKill (FlowGraph, BBlock);
159localstatic void cpSetKillCopies (Bitv, Foam, int, Bool);
160
161localstatic void cpCopyPropagate (FlowGraph);
162localstatic Foam cpCopyPropagate0 (Foam, Bitv, CpFlagState);
163
164localstatic void cpProgInit (Foam);
165localstatic void cpProgFini (void);
166
167localstatic void acFoldAssignments (FlowGraph);
168
169
170/****************************************************************************
171 *
172 * :: External entry points
173 *
174 ****************************************************************************/
175
176void
177cpropUnit(Foam foam, Bool isFirst)
178{
179 Foam defs, def;
180 int i;
181
182 assert(foamTag(foam) == FOAM_Unit)do { if (!(((foam)->hdr.tag) == FOAM_Unit)) _do_assert(("foamTag(foam) == FOAM_Unit"
),"of_cprop.c",182); } while (0)
;
183
184 cpFirstTime = isFirst;
185
186 defs = foam->foamUnit.defs;
187
188 for (i = 0; i < foamArgc(defs)((defs)->hdr.argc); i++) {
189
190 def = defs->foamDDef.argv[i];
191
192 assert(foamTag(def) == FOAM_Def)do { if (!(((def)->hdr.tag) == FOAM_Def)) _do_assert(("foamTag(def) == FOAM_Def"
),"of_cprop.c",192); } while (0)
;
193 if (foamTag(def->foamDef.rhs)((def->foamDef.rhs)->hdr.tag) != FOAM_Prog)
194 continue;
195
196 def->foamDef.rhs = cpProg(def->foamDef.rhs);
197
198 if (DEBUG(cpDf)cpDfDebug) {
199 if (cpInfo.nCopies) {
200 fprintf(dbOut, "------ New prog: -----\n");
201 foamPrintDb(def->foamDef.rhs);
202 }
203 }
204
205 /* flogFree(flog); !! no flogFree, write it */
206 }
207}
208
209/* Given a flow graph, perform copy propagation on it.
210 * NOTE: Assumes that flog comes from a Prog.
211 */
212Bool
213cpFlog(FlowGraph flog)
214{
215 Bool result = false((int) 0);
216
217 Foam prog = flog->prog;
218
219 assert(foamTag(prog) == FOAM_Prog)do { if (!(((prog)->hdr.tag) == FOAM_Prog)) _do_assert(("foamTag(prog) == FOAM_Prog"
),"of_cprop.c",219); } while (0)
;
1
Assuming field 'tag' is not equal to FOAM_Prog
2
Taking true branch
3
Loop condition is false. Exiting loop
220
221 cpProgInit(prog);
222
223 if (cpInfo.nLocals + cpInfo.nParams == 0) {
4
Assuming the condition is false
5
Taking false branch
224 cpProgFini();
225 return false((int) 0);
226 }
227
228 flogIter(flog, bb, {{ { int _i; BBlock bb; for (_i = 0; _i < ((flog)->blocks
->pos); _i++) { bb = bbufBlockFn((flog)->blocks,_i); if
(!bb) continue; { { cpVarCopiesVectBuild(bb->code); }; };
} }; }
6
Assuming '_i' is >= field 'pos'
7
Loop condition is false. Execution continues on line 232
229 cpVarCopiesVectBuild(bb->code);{ { int _i; BBlock bb; for (_i = 0; _i < ((flog)->blocks
->pos); _i++) { bb = bbufBlockFn((flog)->blocks,_i); if
(!bb) continue; { { cpVarCopiesVectBuild(bb->code); }; };
} }; }
230 }){ { int _i; BBlock bb; for (_i = 0; _i < ((flog)->blocks
->pos); _i++) { bb = bbufBlockFn((flog)->blocks,_i); if
(!bb) continue; { { cpVarCopiesVectBuild(bb->code); }; };
} }; }
;
231
232 if (cpInfo.nCopies) {
8
Assuming field 'nCopies' is not equal to 0
9
Taking true branch
233 flogReuse(flog, FLOG_UniqueExit);
234 cpFlog0(flog);
10
Calling 'cpFlog0'
235 }
236
237 cpProgFini();
238
239 result = cpInfo.nPropagated > 0;
240
241 return result;
242}
243
244/****************************************************************************
245 *
246 * :: cpProg
247 *
248 ****************************************************************************/
249
250localstatic Foam
251cpProg(Foam foam)
252{
253 FlowGraph flog;
254 Foam newProg;
255
256 assert(foamTag(foam) == FOAM_Prog)do { if (!(((foam)->hdr.tag) == FOAM_Prog)) _do_assert(("foamTag(foam) == FOAM_Prog"
),"of_cprop.c",256); } while (0)
;
257
258 if (!optIsCPropPending(foam)(((foam)->hdr.info.opt)->optMask & (1 << 0))) return foam;
259 if (!cpFirstTime)
260 optResetCPropPending(foam)(((foam)->hdr.info.opt)->optMask &= ~(1 << 0)
)
;
261
262 cpProgInit(foam);
263
264 if (cpInfo.nLocals + cpInfo.nParams == 0) {
265 cpProgFini();
266 return foam;
267 }
268
269 cpVarCopiesVectBuild(foam->foamProg.body);
270
271 if (cpInfo.nCopies == 0)
272 return foam;
273
274 flog = flogFrProg(foam, FLOG_UniqueExit);
275
276 cpFlog0(flog);
277
278 newProg = flogToProg(flog);
279
280 if (cpInfo.nPropagated > 0) {
281 optSetPeepPending(newProg)(((newProg)->hdr.info.opt)->optMask |= (1 << 4));
282 optSetJFlowPending(newProg)(((newProg)->hdr.info.opt)->optMask |= (1 << 1));
283 optSetCsePending(newProg)(((newProg)->hdr.info.opt)->optMask |= (1 << 2));
284 /* newProg = peepProg(newProg); */
285 }
286
287 cpProgFini();
288
289 return newProg;
290}
291
292/*
293 * Apply copy propagation to flog
294 */
295localstatic void
296cpFlog0(FlowGraph flog)
297{
298 BBlock bb;
299 int i, k;
300
301 if (false((int) 0))
11
Taking false branch
302 acFoldAssignments(flog);
303
304 flogBitvClass(flog)((flog)->bitvClass) = bitvClassCreate(cpInfo.nCopies);
305 cpInfo.bitvClass = flogBitvClass(flog)((flog)->bitvClass);
306
307 for (i = 0; i < flogBlockC(flog)((flog)->blocks->pos); i++) {
12
Assuming 'i' is >= field 'pos'
13
Loop condition is false. Execution continues on line 313
308 bb = flogBlock(flog, i)bbufBlockFn((flog)->blocks,i);
309 if (!bb || bb->dfinfo) continue;
310 dflowNewBlockInfo(bb, cpInfo.nCopies, cpFillGenKill);
311 }
312
313 i = dflowFwdIterate(flog, DFLOW_Intersection, cpDF_CUTOFF200, &k, NULL((void*)0));
314
315 if (DEBUG(cpDf)cpDfDebug) {
14
Assuming 'cpDfDebug' is 0
15
Taking false branch
316 fprintf(dbOut, i == 0 ? "Converged" : "Did not converge");
317 fprintf(dbOut, " after %d iterations\n", k);
318 flogPrint(dbOut, flog, true1);
319 }
320
321 if (i != 0) return;
16
Assuming 'i' is equal to 0
17
Taking false branch
322
323 cpCopyPropagate(flog);
18
Calling 'cpCopyPropagate'
324
325 dflowFreeGraphInfo(flog);
326}
327
328/****************************************************************************
329 *
330 * :: Local function
331 *
332 ****************************************************************************/
333
334
335/* Assign a progressive number to each copy, and add it to varCopiesVect
336 * in the entries corresponding to the lhs and the rhs.
337 * This info will be used in the dflow analysis.
338 */
339localstatic void
340cpVarCopiesVectBuild(Foam seq)
341{
342 Foam stmt;
343 int i;
344
345 assert(foamTag(seq) == FOAM_Seq)do { if (!(((seq)->hdr.tag) == FOAM_Seq)) _do_assert(("foamTag(seq) == FOAM_Seq"
),"of_cprop.c",345); } while (0)
;
346
347 for (i = 0; i < foamArgc(seq)((seq)->hdr.argc); i++) {
348 stmt = foamArgv(seq)((seq)->foamGen.argv)[i].code;
349
350 if (cpIsCopy(stmt)(cpIsDef(stmt) && cpDefIsCopy(stmt))) {
351 cpDefNo(stmt)((stmt)->foamGen.hdr.info.defNo) = cpInfo.nCopies++;
352 cpVarCopiesVectUpdate(stmt);
353 }
354 }
355
356 if (DEBUG(cpDf)cpDfDebug) {
357 cpVarCopiesVectPrint();
358 }
359
360 return;
361}
362
363localstatic void
364cpVarCopiesVectUpdate(Foam def)
365{
366 Foam lhs = def->foamDef.lhs;
367 Foam rhs;
368 int varNo;
369
370 assert(foamTag(lhs) == FOAM_Loc || foamTag(lhs) == FOAM_Par)do { if (!(((lhs)->hdr.tag) == FOAM_Loc || ((lhs)->hdr.
tag) == FOAM_Par)) _do_assert(("foamTag(lhs) == FOAM_Loc || foamTag(lhs) == FOAM_Par"
),"of_cprop.c",370); } while (0)
;
371
372 cpGetVarNo(varNo, lhs)if (((lhs)->hdr.tag) == FOAM_Par) (varNo) = (lhs)->foamPar
.index + cpInfo.nLocals; else (varNo) = (lhs)->foamLoc.index
;
;
373
374 assert(varNo < cpInfo.nLocals + cpInfo.nParams)do { if (!(varNo < cpInfo.nLocals + cpInfo.nParams)) _do_assert
(("varNo < cpInfo.nLocals + cpInfo.nParams"),"of_cprop.c",
374); } while (0)
;
375
376 cpInfo.varCopiesVect[varNo] = listCons(Foam)(Foam_listPointer->Cons)
377 (foamCopy(def), cpInfo.varCopiesVect[varNo]);
378
379 cpInfo.nCopies += 1;
380
381 rhs = cpRhsVarFrCopy(def);
382
383 if (!rhs)
384 return;
385
386 cpGetVarNo(varNo, rhs)if (((rhs)->hdr.tag) == FOAM_Par) (varNo) = (rhs)->foamPar
.index + cpInfo.nLocals; else (varNo) = (rhs)->foamLoc.index
;
;
387
388 assert(varNo < cpInfo.nLocals + cpInfo.nParams)do { if (!(varNo < cpInfo.nLocals + cpInfo.nParams)) _do_assert
(("varNo < cpInfo.nLocals + cpInfo.nParams"),"of_cprop.c",
388); } while (0)
;
389
390 cpInfo.varCopiesVect[varNo] = listCons(Foam)(Foam_listPointer->Cons)
391 (foamCopy(def), cpInfo.varCopiesVect[varNo]);
392}
393
394localstatic void
395cpVarCopiesVectFree()
396{
397 int i, totVars = cpInfo.nLocals + cpInfo.nParams;
398
399 if (!cpInfo.varCopiesVect) return;
400
401 for (i = 0; i < totVars; i++)
402 listFreeDeeply(Foam)(Foam_listPointer->FreeDeeply)(cpInfo.varCopiesVect[i], foamFree);
403
404 stoFree(cpInfo.varCopiesVect);
405}
406
407void
408cpVarCopiesVectPrint()
409{
410 FoamList fl;
411 int nLoc = cpInfo.nLocals;
412 int nPar = cpInfo.nParams;
413 int i;
414
415 fprintf(dbOut, "**** varCopiesVect ****\n");
416
417 for (i = 0; i < nLoc; i++) {
418 if (!cpInfo.varCopiesVect[i]) continue;
419 fprintf(dbOut, "Loc %d:", i);
420 for (fl = cpInfo.varCopiesVect[i]; fl ; fl = cdr(fl)((fl)->rest))
421 foamPrintDb(car(fl)((fl)->first));
422 }
423 for (i = 0; i < nPar; i++) {
424 if (!cpInfo.varCopiesVect[i + nLoc]) continue;
425 fprintf(dbOut, "Par %d:", i);
426 for (fl = cpInfo.varCopiesVect[i + nLoc]; fl ; fl = cdr(fl)((fl)->rest))
427 foamPrintDb(car(fl)((fl)->first));
428 }
429}
430
431/****************************************************************************
432 *
433 * :: Utility
434 *
435 ****************************************************************************/
436
437localstatic Bool
438cpIsDef(Foam foam)
439{
440 Foam lhs;
441
442 if (foamTag(foam)((foam)->hdr.tag) != FOAM_Def &&
443 foamTag(foam)((foam)->hdr.tag) != FOAM_Set)
444 return false((int) 0);
445
446 lhs = foam->foamDef.lhs;
447
448 if (!cpIsTmpVarOrValues(lhs)((((lhs)->hdr.tag) == FOAM_Loc || ((lhs)->hdr.tag) == FOAM_Par
) || ((lhs)->hdr.tag)==FOAM_Values)
)
449 return false((int) 0);
450
451 return true1;
452}
453
454localstatic Bool
455cpDefIsCopy(Foam foam)
456{
457 Foam rhs;
458
459 assert(foamTag(foam) == FOAM_Def || foamTag(foam) == FOAM_Set)do { if (!(((foam)->hdr.tag) == FOAM_Def || ((foam)->hdr
.tag) == FOAM_Set)) _do_assert(("foamTag(foam) == FOAM_Def || foamTag(foam) == FOAM_Set"
),"of_cprop.c",459); } while (0)
;
460
461 if (foamTag(foam->foamDef.lhs)((foam->foamDef.lhs)->hdr.tag) == FOAM_Values)
462 return false((int) 0);
463
464 rhs = foam->foamDef.rhs;
465
466 if (foamTag(rhs)((rhs)->hdr.tag) != FOAM_Loc &&
467 foamTag(rhs)((rhs)->hdr.tag) != FOAM_Par &&
468#if 1
469 foamTag(rhs)((rhs)->hdr.tag) != FOAM_Clos &&
470#endif
471 !cpIsImmediate(rhs) &&
472 !cpIsCopyableCast(rhs)(((rhs)->hdr.tag)==FOAM_Cast && !((rhs)->foamCast
.type == FOAM_SFlo) && ((((rhs->foamCast.expr)->
hdr.tag) == FOAM_Loc || ((rhs->foamCast.expr)->hdr.tag)
== FOAM_Par) || cpIsImmediate(rhs->foamCast.expr)))
)
473 return false((int) 0);
474
475 return true1;
476}
477
478/* FOAM is generally the rhs of a definition.
479 * Returns true if FOAM is an immediate data or a cast of it
480 *
481 * Note: DFlo, BInt, Rec, Arr, Prog and Clos are not immediate data.
482 * Roughly speaking, an immediate data is a data such that a foam expr
483 * like:
484 * (Seq (Set Loc0 DATA) (use Loc0) (use Loc0))
485 * is semantically equivalent to:
486 * (Seq (use DATA) (use DATA))
487 * Note: RRFmt is considered immediate, as are Type* and SizeOf* bcalls.
488 */
489localstatic Bool
490cpIsImmediate(Foam foam)
491{
492 Bool result = false((int) 0);
493
494 while (foamTag(foam)((foam)->hdr.tag) == FOAM_Cast)
495 foam = foam->foamCast.expr;
496
497 if (foamTag(foam)((foam)->hdr.tag) == FOAM_BInt) {
498 result = bintIsZero(foam->foamBInt.BIntData) ||
499 bintEQ(foam->foamBInt.BIntData, bint1);
500 }
501 else if (foamTag(foam)((foam)->hdr.tag) == FOAM_BCall) {
502 /*
503 * We want to fold RawRepSize and Type* calls
504 * into RRFmt instructions (their primary use).
505 * This allows RRFmt values to be examined in
506 * detail: for example, RRFmts whose arguments
507 * do not refer to locs, lex or globs ought to
508 * be lifted to the start of progs and units.
509 * (see of_rrfmt for more details).
510 *
511 * Note that SizeOf* and Type* calls correspond to
512 * integer values which can be computed cheaply.
513 * Also, while RawRepSize values must be computed
514 * at runtime, they are constant and relatively
515 * cheap to compute.
516 */
517 FoamBValTag tag = foam->foamBCall.op;
518
519 switch (tag) {
520 case FOAM_BVal_RawRepSize: result = true1;break;
521#if 0
522 case FOAM_BVal_SizeOfInt8: /* Fall through */
523 case FOAM_BVal_SizeOfInt16: /* Fall through */
524 case FOAM_BVal_SizeOfInt32: /* Fall through */
525 case FOAM_BVal_SizeOfInt64: /* Fall through */
526 case FOAM_BVal_SizeOfInt128: /* Fall through */
527#endif
528 case FOAM_BVal_SizeOfNil: /* Fall through */
529 case FOAM_BVal_SizeOfChar: /* Fall through */
530 case FOAM_BVal_SizeOfBool: /* Fall through */
531 case FOAM_BVal_SizeOfByte: /* Fall through */
532 case FOAM_BVal_SizeOfHInt: /* Fall through */
533 case FOAM_BVal_SizeOfSInt: /* Fall through */
534 case FOAM_BVal_SizeOfBInt: /* Fall through */
535 case FOAM_BVal_SizeOfSFlo: /* Fall through */
536 case FOAM_BVal_SizeOfDFlo: /* Fall through */
537 case FOAM_BVal_SizeOfWord: /* Fall through */
538 case FOAM_BVal_SizeOfClos: /* Fall through */
539 case FOAM_BVal_SizeOfPtr: /* Fall through */
540 case FOAM_BVal_SizeOfRec: /* Fall through */
541 case FOAM_BVal_SizeOfArr: /* Fall through */
542 case FOAM_BVal_SizeOfTR: result = true1; break;
543
544#if 0
545 case FOAM_BVal_TypeInt8: /* Fall through */
546 case FOAM_BVal_TypeInt16: /* Fall through */
547 case FOAM_BVal_TypeInt32: /* Fall through */
548 case FOAM_BVal_TypeInt64: /* Fall through */
549 case FOAM_BVal_TypeInt128: /* Fall through */
550#endif
551 case FOAM_BVal_TypeNil: /* Fall through */
552 case FOAM_BVal_TypeChar: /* Fall through */
553 case FOAM_BVal_TypeBool: /* Fall through */
554 case FOAM_BVal_TypeByte: /* Fall through */
555 case FOAM_BVal_TypeHInt: /* Fall through */
556 case FOAM_BVal_TypeSInt: /* Fall through */
557 case FOAM_BVal_TypeBInt: /* Fall through */
558 case FOAM_BVal_TypeSFlo: /* Fall through */
559 case FOAM_BVal_TypeDFlo: /* Fall through */
560 case FOAM_BVal_TypeWord: /* Fall through */
561 case FOAM_BVal_TypeClos: /* Fall through */
562 case FOAM_BVal_TypePtr: /* Fall through */
563 case FOAM_BVal_TypeRec: /* Fall through */
564 case FOAM_BVal_TypeArr: /* Fall through */
565 case FOAM_BVal_TypeTR: result = true1; break;
566 default: result = false((int) 0); break;
567 }
568 }
569 else {
570 result = (foamTag(foam)((foam)->hdr.tag) == FOAM_SInt ||
571 foamTag(foam)((foam)->hdr.tag) == FOAM_Char ||
572 foamTag(foam)((foam)->hdr.tag) == FOAM_Bool ||
573 foamTag(foam)((foam)->hdr.tag) == FOAM_Byte ||
574 foamTag(foam)((foam)->hdr.tag) == FOAM_HInt ||
575 foamTag(foam)((foam)->hdr.tag) == FOAM_SFlo ||
576 foamTag(foam)((foam)->hdr.tag) == FOAM_Nil ||
577 foamTag(foam)((foam)->hdr.tag) == FOAM_RRFmt ||
578 foamTag(foam)((foam)->hdr.tag) == FOAM_Env);
579 }
580
581 return result;
582}
583
584/* Given a copy, returns NULL if the rhs is not a (casted) tmpvar,
585 * the tmpvar elsewhere.
586 */
587localstatic Foam
588cpRhsVarFrCopy(Foam copy)
589{
590 Foam rhs;
591
592 if (cpIsTmpVar(copy)(((copy)->hdr.tag) == FOAM_Loc || ((copy)->hdr.tag) == FOAM_Par
)
)
46
Assuming field 'tag' is equal to FOAM_Loc
593 return copy->foamDef.rhs;
47
Returning pointer, which participates in a condition later
594
595 rhs = copy->foamDef.rhs;
596
597 if (foamTag(rhs)((rhs)->hdr.tag) == FOAM_Cast)
598 rhs = rhs->foamCast.expr;
599
600 if (cpIsTmpVar(rhs)(((rhs)->hdr.tag) == FOAM_Loc || ((rhs)->hdr.tag) == FOAM_Par
)
)
601 return rhs;
602
603 return NULL((void*)0);
604}
605/****************************************************************************
606 *
607 * :: Build Gen and Kill sets
608 *
609 ****************************************************************************/
610
611localstatic void
612cpFillGenKill(FlowGraph flog, BBlock bb)
613{
614 Foam seq = bb->code, stmt;
615 int defNo, i;
616 BitvClass class = cpInfo.bitvClass;
617
618 assert(class == bbBitvClass(bb))do { if (!(class == ((((bb)->graph)->bitvClass)))) _do_assert
(("class == bbBitvClass(bb)"),"of_cprop.c",618); } while (0)
;
619
620 /*
621 * Clear the vectors.
622 */
623 bitvClearAll(class, dfFwdGen(bb)((bb)->dfinfo->gen));
624 bitvClearAll(class, dfFwdKill(bb, int0)((bb)->dfinfo->exit[((int) 0)].kill));
625
626 for (i = 0; i < foamArgc(seq)((seq)->hdr.argc); i++) {
627 stmt = foamArgv(seq)((seq)->foamGen.argv)[i].code;
628
629 if (!cpIsDef(stmt))
630 continue;
631
632 defNo = cpDefNo(stmt)((stmt)->foamGen.hdr.info.defNo);
633
634 cpSetKillCopies(dfFwdKill(bb, int0)((bb)->dfinfo->exit[((int) 0)].kill), stmt, defNo, true1);
635
636 if (cpDefIsCopy(stmt)) {
637 /* Set gen bit for the corresponding def */
638 bitvSet(class, dfFwdGen(bb)((bb)->dfinfo->gen), defNo);
639 /* Unkill, needed because we use (IN \/ Gen) - Kill */
640 bitvClear(class, dfFwdKill(bb, int0)((bb)->dfinfo->exit[((int) 0)].kill), defNo);
641 }
642
643 }
644}
645
646localstatic void
647cpSetKillCopies(Bitv statev, Foam def, int defNo, Bool bit)
648{
649 int varNo, n, var, nVars;
650 FoamList defs;
651 Foam lhs = def->foamDef.lhs;
652 Foam * lhsVarVect;
653 BitvClass class = cpInfo.bitvClass;
654
655 assert(cpIsTmpVarOrValues(lhs))do { if (!(((((lhs)->hdr.tag) == FOAM_Loc || ((lhs)->hdr
.tag) == FOAM_Par) || ((lhs)->hdr.tag)==FOAM_Values))) _do_assert
(("cpIsTmpVarOrValues(lhs)"),"of_cprop.c",655); } while (0)
;
656
657 if (foamTag(lhs)((lhs)->hdr.tag) == FOAM_Values) {
658 nVars = foamArgc(lhs)((lhs)->hdr.argc);
659 lhsVarVect = lhs->foamValues.argv;
660 }
661 else {
662 nVars = 1;
663 lhsVarVect = &lhs;
664 }
665
666 for (var = 0; var < nVars; var++) {
667
668 lhs = lhsVarVect[var];
669
670 if (!cpIsTmpVar(lhs)(((lhs)->hdr.tag) == FOAM_Loc || ((lhs)->hdr.tag) == FOAM_Par
)
)
671 continue;
672
673 cpGetVarNo(varNo, lhs)if (((lhs)->hdr.tag) == FOAM_Par) (varNo) = (lhs)->foamPar
.index + cpInfo.nLocals; else (varNo) = (lhs)->foamLoc.index
;
;
674
675 defs = cpInfo.varCopiesVect[varNo];
676
677 for ( ; defs ; defs = cdr(defs)((defs)->rest)) {
678 n = cpDefNo(car(defs))((((defs)->first))->foamGen.hdr.info.defNo);
679 if (bit)
680 bitvSet(class, statev, n);
681 else
682 bitvClear(class, statev, n);
683 }
684 }
685
686 return;
687}
688
689/****************************************************************************
690 *
691 * :: Foam traversal and copy propagation
692 *
693 ****************************************************************************/
694
695localstatic void
696cpCopyPropagate(FlowGraph flog)
697{
698 BBlock bb;
699 int i;
700
701 for (i = 0; i < flogBlockC(flog)((flog)->blocks->pos); i++) {
19
Assuming 'i' is < field 'pos'
20
Loop condition is true. Entering loop body
702 bb = flogBlock(flog, i)bbufBlockFn((flog)->blocks,i);
703 if (!bb) continue;
21
Assuming 'bb' is non-null
704 if (bbEntryC(bb)((bb)->entries->pos) == 0 && !bb->isblock0) continue;
22
Taking false branch
23
Assuming field 'pos' is not equal to 0
705
706 bb->code = cpCopyPropagate0(bb->code, dfFwdIn(bb)((bb)->dfinfo->in), CP_Rhs);
24
Calling 'cpCopyPropagate0'
707
708 if (DEBUG(cpDf)cpDfDebug) {
709 foamPrintDb(bb->code);
710 }
711 }
712}
713
714localstatic Foam
715cpCopyPropagate0(Foam foam, Bitv dfin, CpFlagState cpState)
716{
717 Foam newFoam = foam;
718 Bool isDef = false((int) 0);
719
720 if (otIsDef(foam)(((foam)->hdr.tag) == FOAM_Set || ((foam)->hdr.tag) == FOAM_Def
)
) {
25
Assuming field 'tag' is not equal to FOAM_Set
26
Assuming field 'tag' is not equal to FOAM_Def
27
Taking false branch
721 Foam lhs, rhs;
722 isDef = cpDefIsCopy(foam);
723
724 foam->foamDef.rhs = cpCopyPropagate0(foam->foamDef.rhs, dfin,
725 CP_Rhs);
726 foam->foamDef.lhs = cpCopyPropagate0(foam->foamDef.lhs, dfin,
727 CP_Lhs);
728
729 lhs = foam->foamDef.lhs;
730 rhs = foam->foamDef.rhs;
731
732 /* Remove (Set (Loc n) (Loc n)) that might appear
733 * after a propagation. */
734
735 if (foamTag(lhs)((lhs)->hdr.tag) == foamTag(rhs)((rhs)->hdr.tag) &&
736 cpIsTmpVar(lhs)(((lhs)->hdr.tag) == FOAM_Loc || ((lhs)->hdr.tag) == FOAM_Par
)
&&
737 lhs->foamLoc.index == rhs->foamLoc.index) {
738
739 foamFree(foam);
740 return foamNewNOp()foamNew(FOAM_NOp, (int) 0);
741 }
742 }
743 else if (foamTag(foam)((foam)->hdr.tag) == FOAM_CEnv) {
28
Assuming field 'tag' is not equal to FOAM_CEnv
744 Foam clos = cpCopyPropagate0(foam->foamCEnv.env, dfin, CP_CEnv);
745 /* Should check that clos->env is a constant */
746 if (foamTag(clos)((clos)->hdr.tag) == FOAM_Clos)
747 return clos->foamClos.env;
748 return foam;
749 }
750 else if (foamTag(foam)((foam)->hdr.tag) == FOAM_Values && cpState == CP_Lhs)
29
Taking false branch
30
Assuming field 'tag' is not equal to FOAM_Values
751 return foam;
752 else foamIter(foam, arg, *arg = cpCopyPropagate0(*arg, dfin, CP_Rhs); ){ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv
)+_i; { *arg = cpCopyPropagate0(*arg, dfin, CP_Rhs);; }; } } }
; }
;
31
Assuming '_i' is >= field 'argc'
32
Loop condition is false. Execution continues on line 755
753
754
755 switch (foamTag(foam)((foam)->hdr.tag)) {
33
Control jumps to 'case FOAM_Loc:' at line 756
756 case FOAM_Loc:
757 case FOAM_Par: {
758 int defNo, varNo, index;
759 FoamList defs;
760 Foam def, copy, lhs, rhsVar;
761 Bool unique, foundLoop = false((int) 0);
762 AInt castType = FOAM_Nil;
763
764 if (cpState
33.1
'cpState' is not equal to CP_Lhs
== CP_Lhs) break;
765
766 while (!foundLoop
33.2
'foundLoop' is 0
&& foam) {
34
Loop condition is true. Entering loop body
767 copy = NULL((void*)0);
768
769 cpGetVarNo(varNo, foam)if (((foam)->hdr.tag) == FOAM_Par) (varNo) = (foam)->foamPar
.index + cpInfo.nLocals; else (varNo) = (foam)->foamLoc.index
;
;
35
Taking false branch
770 index = foam->foamLoc.index;
771
772 /* Look which copies are alive at this point */
773 defs = cpInfo.varCopiesVect[varNo];
774
775 for (unique = true1; defs && unique; defs = cdr(defs)((defs)->rest)) {
36
Assuming 'defs' is non-null
37
Loop condition is true. Entering loop body
43
Assuming 'defs' is null
776 def = car(defs)((defs)->first);
777 defNo = cpDefNo(def)((def)->foamGen.hdr.info.defNo);
778 lhs = def->foamDef.lhs;
779
780 /* Still alive ? */
781 if (!bitvTest(cpInfo.bitvClass, dfin, defNo))
38
Assuming the condition is false
782 continue;
783
784 /* Is the same lhs ? */
785 if (index == lhs->foamLoc.index &&
39
Assuming 'index' is equal to field 'index'
41
Taking true branch
786 foamTag(lhs)((lhs)->hdr.tag) == foamTag(foam)((foam)->hdr.tag)) {
40
Assuming '' is equal to ''
787 if (copy
41.1
'copy' is null
) unique = false((int) 0);
42
Taking false branch
788 copy = def;
789 }
790 }
791
792 /* Found a unique copy ? */
793 if (!copy
43.1
'copy' is non-null
|| !unique
43.2
'unique' is 1
) break;
44
Taking false branch
794
795 rhsVar = cpRhsVarFrCopy(copy);
45
Calling 'cpRhsVarFrCopy'
48
Returning from 'cpRhsVarFrCopy'
796 if (cpState
48.1
'cpState' is not equal to CP_CEnv
!= CP_CEnv && rhsVar
&& foamTag(rhsVar)((rhsVar)->hdr.tag) == FOAM_Clos)
49
Assuming 'rhsVar' is null
50
Assuming pointer value is null
797 break;
798
799 if (cpState
50.1
'cpState' is not equal to CP_CEnv
!= CP_CEnv && foamTag(copy->foamDef.rhs)((copy->foamDef.rhs)->hdr.tag) == FOAM_Clos)
51
Dereference of null pointer
800 break;
801
802 if (foamTag(copy->foamDef.rhs)((copy->foamDef.rhs)->hdr.tag) == FOAM_Cast &&
803 castType == FOAM_Nil)
804 castType = copy->foamDef.rhs->foamCast.type;
805
806 /* It's a loop? (Set (Loc 0) (Loc 0)) is a loop. */
807 if (rhsVar && index == rhsVar->foamLoc.index &&
808 foamTag(foam)((foam)->hdr.tag) == foamTag(rhsVar)((rhsVar)->hdr.tag))
809 foundLoop = true1;
810
811 /* Is the unique copy/definition reaching this point.
812 * Substitution can be performed.
813 */
814
815 /* foamFree(foam); */
816
817 newFoam = foamCopy(copy->foamDef.rhs);
818 cpInfo.nPropagated += 1;
819
820 cpDEBUGif (!cpDebug) { } else afprintf(dbOut, "CPROP>> Copy propagated ---\n");
821
822 foam = rhsVar; /* Will be NULL if rhs is IMMEDIATE */
823 }
824
825
826 /* "castType" is used to handle situations like:
827 * l6 -> (Cast Word l5)
828 * l5 -> (Cast SInt l3)
829 * In this case l6 should be substitued by (Cast Word l3).
830 * "castType" keeps trace of the first cast type.
831 */
832
833 if (castType != FOAM_Nil)
834 newFoam = foamNewCast(castType, newFoam)foamNew(FOAM_Cast, 2, castType, newFoam);
835
836
837 break;
838 }
839
840 case FOAM_Set:
841 case FOAM_Def: {
842 Foam lhs = foam->foamDef.lhs;
843 int defNo;
844
845 /* Update the IN vector */
846
847 if (!cpIsTmpVarOrValues(lhs)((((lhs)->hdr.tag) == FOAM_Loc || ((lhs)->hdr.tag) == FOAM_Par
) || ((lhs)->hdr.tag)==FOAM_Values)
)
848 break;
849
850 defNo = cpDefNo(foam)((foam)->foamGen.hdr.info.defNo);
851 cpSetKillCopies(dfin, foam, defNo, false((int) 0));
852
853 /*
854 * !!NB: cpDefIsCopy can return garbage if propogation
855 * has happened
856 */
857 if (isDef)
858 /* Set bit for the corresponding def */
859 bitvSet(cpInfo.bitvClass, dfin, defNo);
860
861 break;
862 }
863
864 default:
865 break;
866 }
867
868 return newFoam;
869}
870
871
872/****************************************************************************
873 *
874 * :: cpProgInit and cpProgFini
875 *
876 ****************************************************************************/
877
878localstatic void
879cpProgInit(Foam prog)
880{
881 int nLoc = foamDDeclArgc(prog->foamProg.locals)(((prog->foamProg.locals)->hdr.argc) - (1));
882 int nPar = foamDDeclArgc(prog->foamProg.params)(((prog->foamProg.params)->hdr.argc) - (1));
883 int i;
884
885 assert(foamTag(prog) == FOAM_Prog)do { if (!(((prog)->hdr.tag) == FOAM_Prog)) _do_assert(("foamTag(prog) == FOAM_Prog"
),"of_cprop.c",885); } while (0)
;
886
887 cpInfo.nLocals = nLoc;
888 cpInfo.nParams = nPar;
889 cpInfo.nCopies = 0;
890 cpInfo.nPropagated = 0;
891 cpInfo.varCopiesVect = (FoamList *) 0;
892
893 if (nLoc + nPar == 0)
894 return;
895
896 cpInfo.varCopiesVect =
897 (FoamList *) stoAlloc(OB_Other0, (nLoc + nPar) * sizeof(FoamList));
898
899 for (i = 0; i < nLoc + nPar; i++)
900 cpInfo.varCopiesVect[i] = listNil(Foam)((FoamList) 0);
901
902
903}
904
905localstatic void
906cpProgFini()
907{
908 cpVarCopiesVectFree();
909 return;
910}
911
912/****************************************************************************
913 *
914 * :: acFlog --- Collect assignments into BB
915 *
916 ****************************************************************************/
917
918static BitvClass acBitClass;
919static Bitv acMarkBits;
920localstatic Bool acIsCandidate (BBlock);
921localstatic BBlock acMergeWithSuccessor (FlowGraph, int);
922localstatic void acFoldBlock(FlowGraph flog, int label);
923
924localstatic void
925acFoldAssignments(FlowGraph flog)
926{
927 Bitv candidates;
928 BBlock bb;
929 int i, sz;
930 sz = flogBlockC(flog)((flog)->blocks->pos);
931 acBitClass = bitvClassCreate(sz);
932 candidates = bitvNew(acBitClass);
933 acMarkBits = bitvNew(acBitClass);
934 bitvClearAll(acBitClass, candidates);
935 bitvClearAll(acBitClass, acMarkBits);
936
937 for (i=0; i<sz; i++) {
938 bb = flogBlock(flog, i)bbufBlockFn((flog)->blocks,i);
939 if (!bb) continue;
940 if (acIsCandidate(bb))
941 bitvSet(acBitClass, candidates, i);
942 }
943
944 acFoldBlock(flog, flog->block0->label);
945 bitvClassDestroy(acBitClass);
946}
947
948localstatic void
949acFoldBlock(FlowGraph flog, int label)
950{
951 BBlock bb = flogBlock(flog, label)bbufBlockFn((flog)->blocks,label);
952 int i;
953
954 /* Depth first, post-order ensures that the
955 * target blocks should already be merged
956 * before the parent looks at them
957 */
958 if (!bb) return;
959 if (label >= bitvClassSize(acBitClass)((acBitClass)->nbits))
960 return;
961 if (bitvTest(acBitClass, acMarkBits, label))
962 return;
963
964 bitvSet(acBitClass, acMarkBits, label);
965
966 for (i=0; i<bbExitC(bb)((bb)->exits->pos); i++)
967 acFoldBlock(flog, bbExit(bb, i)((bb)->exits->argv[i])->label);
968
969 if (bbExitC(bb)((bb)->exits->pos) != 1)
970 return;
971
972 if (acIsCandidate(bbExit(bb,int0)((bb)->exits->argv[((int) 0)])))
973 bb = acMergeWithSuccessor(flog, label);
974}
975
976localstatic Bool
977acIsCandidate(BBlock bb)
978{
979 Foam seq = bb->code;
980 int i;
981
982 if (bbExitC(bb)((bb)->exits->pos) != 1)
983 return false((int) 0);
984 for (i=0; i<foamArgc(seq)((seq)->hdr.argc) - 1; i++) {
985 Foam foam = seq->foamSeq.argv[i];
986
987 if (!otIsDef(foam)(((foam)->hdr.tag) == FOAM_Set || ((foam)->hdr.tag) == FOAM_Def
)
) return false((int) 0);
988 if (!otIsLocalVar(foam->foamSet.lhs)(((foam->foamSet.lhs)->hdr.tag) == FOAM_Loc || ((foam->
foamSet.lhs)->hdr.tag) == FOAM_Par)
)
989 return false((int) 0);
990 foam = foam->foamSet.rhs;
991 otDereferenceCast(foam)while (((foam)->hdr.tag) == FOAM_Cast) foam = foam->foamCast
.expr;
;
992 if (!otIsLocalVar(foam)(((foam)->hdr.tag) == FOAM_Loc || ((foam)->hdr.tag) == FOAM_Par
)
)
993 return false((int) 0);
994 }
995
996 return true1;
997}
998
999localstatic BBlock
1000acMergeWithSuccessor(FlowGraph flog, int label)
1001{
1002 BBlock thisBB, nextBB, newBB;
1003 Foam new;
1004 int i, j;
1005
1006 thisBB = flogBlock(flog, label)bbufBlockFn((flog)->blocks,label);
1007 nextBB = bbExit(thisBB, int0)((thisBB)->exits->argv[((int) 0)]);
1008 if (thisBB == nextBB)
1009 return thisBB;
1010
1011 new = foamNew(FOAM_Seq, foamArgc(thisBB->code)((thisBB->code)->hdr.argc) + foamArgc(nextBB->code)((nextBB->code)->hdr.argc) - 1);
1012 for (i=0; i<foamArgc(thisBB->code)((thisBB->code)->hdr.argc) - 1 ; i++)
1013 new->foamSeq.argv[i] = foamCopy(thisBB->code->foamSeq.argv[i]);
1014 for (j = 0; j<foamArgc(nextBB->code)((nextBB->code)->hdr.argc); i++, j++)
1015 new->foamSeq.argv[i] = foamCopy(nextBB->code->foamSeq.argv[j]);
1016
1017 i = flogReserveLabel(flog)bbufReserve1((flog)->blocks);
1018 newBB = bbNew(new, i);
1019 flogSetBlock(flog, i, newBB)((flog)->fixedEntries = ((int) 0), bbufSetBlockFn((flog)->
blocks,i,newBB), (newBB)->graph = (flog))
;
1020 bbufNeed(newBB->exits, 1);
1021 bbSetExitC(newBB, 1)((newBB)->exits->pos = (1));
1022 bbSetExit(newBB, int0, bbExit(nextBB, int0))((newBB)->graph->fixedEntries = ((int) 0), (newBB)->
exits->argv[((int) 0)] = (((nextBB)->exits->argv[((int
) 0)])))
;
1023#if 0
1024 fprintf(dbOut, "merging: %d with %d -> %d\n", label, nextBB->label, newBB->label);
1025 foamPrintDb(thisBB->code);
1026 foamPrintDb(nextBB->code);
1027#endif
1028 if (flog->block0 == thisBB) {
1029 flog->block0 = newBB;
1030 newBB->isblock0 = true1;
1031 thisBB->isblock0 = false((int) 0);
1032 }
1033 for (i=0; i<flogBlockC(flog)((flog)->blocks->pos); i++) {
1034 BBlock bb = flogBlock(flog, i)bbufBlockFn((flog)->blocks,i);
1035 if (!bb) continue;
1036 for (j=0; j<bbExitC(bb)((bb)->exits->pos); j++) {
1037 if (bbExit(bb, j)((bb)->exits->argv[j]) == thisBB)
1038 bbSetExit(bb, j, newBB)((bb)->graph->fixedEntries = ((int) 0), (bb)->exits->
argv[j] = (newBB))
;
1039 }
1040 }
1041 flogKillBlock(flog, label)((flog)->blocks->argv[label] = 0);
1042
1043 return newBB;
1044}
1045
1046