Trailing-Edge
-
PDP-10 Archives
-
FORTRAN-10_V7wLink_Feb83
-
graph.bli
There are 12 other files named graph.bli in the archive. Click here to see a list.
!THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
! OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
!COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1972, 1983
!AUTHOR NORMA ABEL/DCE/SJW/JNG/AHM/EGM
MODULE GRAPH(RESERVE(0,1,2,3),SREG=#17,VREG=#15,FREG=#16,DREGS=4)=
BEGIN
! REQUIRES FIRST, TABLES, OPTMAC/LIST
GLOBAL BIND GRAPHV = 7^24 + 0^18 + #1164; ! Version Date: 16-Feb-82
%(
***** Begin Revision History *****
108 ----- ----- FIX RETURNING OF OPTIMIZERS WORDS
FOR SUBSUMPTION
109 ----- ----- REMOVE BOGUS CALL TO LOKEXIT FOR TERMINATION
LABEL OF AN INNER DO IN GRAPH
110 ----- ----- DELETE BAD RETURN ON NULL LOOP IN DOCOLLAPSE
111 ----- ----- CHANGE ERROR MESSAGES AND MAKE GRAPH SPACE
DYNAMIC
112 ----- ----- DO ERROR MESSAGES CORRECTLY
113 ----- ----- CORRECT ERROR STUFF AND FIX GLOBAL REFS
114 ----- ----- SAVSPACE THE UNIQUE VALUES LIST
115 ----- ----- DELETE CODE THAT CARES ABOUT MAKING
LABELS "ASSIGNED" TO PARMATERS OF
CALLS SUCCESSORS OF THE CALL
116 ----- ----- FIX DO DEPTH ABALYSIS TREE WALK NOT TO
NEED A STACK
***** Begin Version 4B *****
117 327 16688 DISCONTINUE OPTIMIZATION FOR CASES WHERE
POSTDOMINATORS ARE NOT ALL COMPUTED, (DCE)
118 330 17150 MAKE SURE THAT ENTRY STATEMENTS ARE NEVER
CONSIDERED INACCESSIBLE CODE!
119 333 17045 FIX ASSIGNED GO TO STATEMENTS WITHIN DO LOOPS.
LOOP MUST NOT BE OPTIMIZED!, (DCE)
120 361 18451 FIX JUMP TO LABEL OF INNER DO LOOP, (DCE)
121 372 18314 FIX DOCOLLAPSE TO RETURN SPACE CORRECTLY, (DCE)
122 374 ----- FIX MIS-SPELLING (IOBRAHCH), (DCE)
***** Begin Version 5 *****
123 VER5 ----- GRAPH ERR= FOR OPEN & CLOSE, (SJW)
124 443 QA656 WARNING + STOP OPT IF DISCOVER ILLEGAL DO
NESTING IN LNKEXTND IN HOOKUP, (SJW)
***** Begin Version 5A *****
125 535 21809 INNACCESSIBLE CODE WITH ZERO LINE NUMBER!
126 565 21810 EXTENDED RANGE DO LOOP IMPROPERLY GRAPHED, (DCE)
127 576 22798 GIVE LINE NUMBER CORRECTLY WHEN LOOP DETECTED
***** Begin Version 5B *****
128 637 24802 DO NOT DISCONTINUE OPTIMIZATION WHEN INFINITE
LOOP DETECTED. INSTEAD, FIX THE GRAPH SO ALL
STATEMENTS ARE ASSIGNED POSTDOMINATORS.
FIX INACCESSIBLE CODE FINDER TO CHECK FOR
ZERO PREDOMINATORS., (JNG)
129 716 26409 MARK LOOPS AS INELIGIBLE FOR GLOBAL REGISTER
OPTIMIZATIONS IF THEY CONTAIN LABELS WHICH CAN
BE REACHED DIRECTLY ON RETURN FROM SUBROUTINES, (DCE)
***** Begin Version 6 *****
130 1052 EGM 9-Feb-81 --------
Correct edit 361 for correct optimization of a transfer
out of an inner do, to main, to outer do terminus path.
131 1063 DCE 23-Apr-81 QAR5631
Add error detection for jumps into loops with no exits.
132 1066 EGM 12-May-81 Q10-05202
Do not use ISN in error messages if not pertinent.
134 1112 DCE 17-Jul-81 QAR5631
More work to get the local label counts right for nested loops
with inner references to outer labels.
Should make edit 1063 much more stable.
135 1125 DCE 24-Sep-81 -----
Once again for edit 1063. This time remove edit 443 which has
been found to be both unnecessary, and wrong! Also fix up two
more places where the local label count could become incorrect.
These deal mainly with nested DO loop situations.
136 1136 AHM 9-Oct-81 Q20-01652,Q20-01656
Make GRAPH know about END= and ERR= for some I/O statements.
And turn the SELECT into a CASE.
137 1137 DCE 20-Oct-81 -----
Prevent looping optimizer for inaccessible DO stmnt with jumps
into loop.
138 1140 DCE 21-Oct-81 -----
Same as 137, but for nested loops with only the inner loop having
entrances.
***** Begin Version 6A *****
139 1150 DCE 16-Feb-82 20-17292
Handle programs with ASSIGN statements properly.
Avoid unjustified error messages.
1164 EGM 12-Jul-82
Prevent loop in (the) SWAMP caused by incorrect information being
setup for LOKEXIT. In particular, for certain nested loops, allow
LOKEXIT to correctly determine it has a branch back into an inner
loop, instead of thinking it has an exit. This change brings the
code in line with the comments at the end of GRAPH.
***** End Revision History *****
)%
SWITCHES NOLIST;
REQUIRE FIRST.BLI;
REQUIRE TABLES.BLI;
SWITCHES LIST;
REQUIRE OPTMAC.BLI;
EXTERNAL TOP,BOTTOM,ISN;
FORWARD ASSLOOKER;
OWN P,PA,PB,PREV,PC;
OWN PO,P1,P2,P3,HEAD,TAIL;
MAP PHAZ2 PA:PB:PC:P:PREV;
EXTERNAL TBLSEARCH,CORMAN,ASIPTR;
FORWARD LOKEXIT;
MAP BASE TOP;
EXTERNAL QQ,LOOP;
OWN OLDHEAD,DISCONFLG; ![637]
MAP PHAZ2 QQ;
EXTERNAL EXITNO;
OWN EXITLST;
OWN LLLNO,LLL,EPTR;
MAP PHAZ2 PO:P1:P2:P3:HEAD:TAIL;
OWN T; ![637]
EXTERNAL RGRAPH,FGRAPH;
MAP PHAZ2 P:PA;
MAP PHAZ2 OLDHEAD;
EXTERNAL LEND;
!************************************
!*******************************
ROUTINE LNKREV(X,Q)=
BEGIN
REGISTER PHAZ2 GP:T;
MAP PHAZ2 Q;
!X IS THE PREDECESSOR OF Q
T_.Q[PREDPTR];
GP_GETGRAPHELM;
GP[CESLNK]_.T;
Q[PREDPTR]_.GP;
GP[CESSOR]_.X;
END;
!**********************************
ROUTINE LNKFWD(X,Q)=
BEGIN
MAP PHAZ2 Q;
REGISTER PHAZ2 GP:T;
!X IS THE SUCCESSOR FO Q
T_.Q[SUCPTR];
GP_GETGRAPHELM;
GP[CESLNK]_.T;
Q[SUCPTR]_.GP;
GP[CESSOR]_.X;
END;
!FOR EACH LABEL THAT IS ENCOUNTERED AS A BRANCH THE
!ROUTINE LOKEXIT IS CALLED. THIS ROUTINE EXAMINES THE LLL (LOCAL
!LABEL LIST) AND EXITLST (EXIT LABEL LIST), ETC. TO
!DETERMINE THE NATURE OF THE BRANCH. THE ROUTINE RETURNS
! 0 LOCAL LABEL, BRANCH WITHIN GRAPH OF CURRENT DO
! 1 EXIT, BOTTOM IS THE DESTINATION
! 2 IT IS A JUMP BACK TO A LABEL IN A NESTED DO
! PREVIOUSLY PROCESSED AND WILL BE CONSIDERED
! AS AN EXTENDED RANGE .PA[SNEXTND] IS THE DESTINATION
MACRO LNKBOT=
BEGIN
IF .P NEQ .LEND THEN
BEGIN
LNKFWD(.LEND,.P);
LNKREV(.P,.LEND);
END;
END$;
!
!NOTE: SXENTND POINTS TO THE DO DEPH ANALYSIS TREE SO WE NEED AN INDEIRECT
MACRO LNKEXTND =
BEGIN
PA_.PA[SNEXTND];
! DON'T ALLOW NODE TO BE ITS OWN PREDECESSOR: ONLY HAPPENS WHEN
! LOKEXIT RETURNS 2 => A LABEL ON EXTLST FOR THIS LOOP IS CONTAINED
! IN A LOOP WHICH IS CONTAINED IN THIS LOOP, IE, AN EXTENDED
! RANGE IS POSSIBLE. IF PREDPTR WOULD GET LOOPED, THE DO MUST CONTAIN
! AN ILLEGAL NEST, EG:
! DO 10 J = 1,10
! K = I + J
! IF (K+A .EQ. 0) GO TO 10
! DO 10 L = 1,5
!10 M = K + I + L + F
! Remove edit 443 - it had problems which are resolved elsewhere.
![1125]
![1125] IF .P EQL .PA [DOSRC]
![1125] THEN BEGIN
![1125] EXTERNAL CSTMNT, ISN, OPTERR, E140;
![1125] MAP BASE CSTMNT;
![1125] CSTMNT _ .PA [DOSRC]; !POINT TO ENCLOSING DO
![1125] ISN _ .CSTMNT [SRCISN]; !GET STATEMENT # FOR WARNING
![1125] OPTERR (E140); !ILLEGAL DO NESTING - OPT DISCONTINUED
![1125] END;
LNKFWD(.PA[DOSRC],.P);
LNKREV(.P,.PA[DOSRC]);
END$;
MACRO IOBRANCH=
BEGIN
IF .P[IOERR] NEQ 0 THEN
BEGIN
PA_.P[IOERR];
HOOKUP(.PA);
END;
IF .P[IOEND] NEQ 0 THEN
BEGIN
PA_.P[IOEND];
HOOKUP(.PA);
END;
%1136% PREV=.P
END$;
!***************************************
!
ROUTINE HOOKUP(PA)=
!TO SHORTEN CODE THIS ROUTINE WAS CREATED TO CALL LOKEXIT TO
!DETERMINE THE NATURE OF A BRANCH AND LINK IT INTO THE GRAPH
!CORRECTLY
BEGIN
MAP BASE PA;
CASE LOKEXIT(.PA) OF SET
BEGIN
LNKREV(.P,.PA[SNHDR]);
LNKFWD(.PA[SNHDR],.P);
END;
LNKBOT;
LNKEXTND
TES;
END;
![637] Delete ABSGOCHK routine
ROUTINE GRAPH=
BEGIN
!BUILD THE PROGRAM GRAPH FOR EACH INDIVIDUAL STATEMENT.
!P POINTS TO THE CURRENT STATEMENT. PREV POINTS TO THE
!PREVIOUS STATEMENT OR IS ZERO IF THE PREVIOUS STATEMENT
!WAS AN ABSOLUTE BRANCH.
MACRO INFLOOP=
IF .PA EQL .P[SRCLBL] THEN OPTERR(E100)$;
%1136% MACRO OTHERS=PREV_.P$; ! Action for non-branch statements
EXTERNAL ENTRY,OPTERR,LOOP,LEND;
IF .PREV NEQ 0 THEN
BEGIN
LNKREV(.PREV,.P); LNKFWD(.P,.PREV);
END;
![1136] Create the CASE statement below from a vary large, slow SELECT
![1136] Also, make all I/O use IOBRANCH macro
CASE .P[SRCID] OF SET
!ASGNID:
OTHERS;
!ASSIID:
OTHERS;
!CALLID:
BEGIN !CALL STATEMENT
!NEED TO CHECK FOR LABELS AS PARAMETERS AND ASSIGN-ED VARIABLES
!
IF .P[CALLIST] NEQ 0 THEN
BEGIN
LOCAL ARGUMENTLIST AG;
AG_.P[CALLIST];
INCR I FROM 1 TO .AG[ARGCOUNT] DO
BEGIN
PA_.AG[.I,ARGNPTR];
IF .PA[OPRCLS] EQL LABOP THEN
BEGIN !LABEL AS PARAMETER
HOOKUP(.PA);
P[LABLARGS]_1;
END;
END; !INCR LOOP ON PARAMETERS
END; !PARAMETERS AT ALL
PREV_.P;
END; !CALL STATEMENT
!CONTID:
OTHERS;
!DOID:
BEGIN !DO STATEMENT
!NOTE THAT THIS IS AN INNER DO (ALREADY PROCESSED
!WE ADJUST PREV AND P TO START THE GRAPHING PROCESS
!UP AGAIN AT THE STATEMENT AFTER THE DO.
!THERE IS ONE OTHER THING TO DO:
!1. IF A PREVIOUS LOOP HAD A BRANCH OUT TO A LABEL
! WE MUST SEE IF THE LABEL IS DEFINED HEREIN (IN THE
! CURRENT LOOP AND LINK THEM UP.
!1 FIRST. IF THERE ARE OPTIMIZERS WORDS TO GO WITH THIS LOOP
IF .P[SRCOPT] NEQ 0 THEN
BEGIN
!IF THERE WERE EXITS FROM THIS LOOP THEY
!ARE IN A LINKED LIST FROM EXTLST
IF .P[EXTLST] NEQ 0 THEN
BEGIN
!EXAMINE THE LABELS ON THE LINKED LIST
!AND SEE IF THEY ARE IN LLL (LOCAL LABEL
!LIST.
PC_.P[EXTLST];
WHILE .PC NEQ 0 DO
BEGIN
%[1112]% LOCAL SAVLREFCNT; ! So that HOOKUP won't change it!
PA_.PC[LEFTP];
%[1112]% SAVLREFCNT_.PA[LREFCNT];
HOOKUP(.PA);
%[1112]% PA[LREFCNT]_.SAVLREFCNT;
!LOOK AT NEXT ITEM OM LINKED LIST
PC_.PC[RIGHTP];
END;
END; !EXTLST IS ZERO
END;
P_.P[DOLBL]; !TERMINATION LABEL
P_.P[SNHDR]; !TERMINATION STATEMENT
PREV_.P;
END;
!ENTRID:
BEGIN !ENTRY, SUBROUTINE OR FUNCTION STATEMENT
!THIS SHOULD BE AN ENTRY, WE ARE IN THE "MAIN" PROGRAM
LNKFWD(.P,.TOP);
LNKREV(.TOP,.P);
PREV_.P;
END;
!COMNSUB:
OTHERS;
!GOTOID:
BEGIN !UNCONDITIONAL GO TO
PA_.P[GOTOLBL];
INFLOOP;
HOOKUP(.PA);
PREV_0;
END;
!AGOID:
BEGIN !ASSIGNED GO TO
ENTRY_.P[SRCISN];
!TURN OFF GLOBAL REGISTER ALLOCATION
! FOR THIS LOOP ONLY.
TOP[HASRTRN]_1;
IF .P[GOTOLIST] EQL 0 THEN !OPTIONAL LIST IS NOT PRESENT
BEGIN !YOU LOSE
!PICK UP LIST THAT IS
ASSLOOKER(.P[AGOTOLBL]);!LINKED OFF
!ASIPTR. THROUGH ALL
!ASSIGN STATEMENTS
!BY PHASE 1.
!INTERPRETATION OF **THE STANDARD**
!IF WE HAVE HAD TO BUILD THE LIST, WE
!WILL (BY DEFINITION) GO TO A LABEL ON
!THE LIST. THAT MAKES THIS AN ABSOLUTE
!BRANCH AND IT WILL BE TREATED A SUCH
IF .P[GOTONUM] EQL 0 THEN
(P[GOTOLIST]_0; OPTERR(E62));
PREV_0;
END;
!OPTIONAL LIST IN NODE
!HURRAY!
DECR I FROM .P[GOTONUM]-1 TO 0 DO
BEGIN
PA_@(.P[GOTOLIST]+.I); !SAME AS COMPUTED GO TO
INFLOOP;
HOOKUP(.PA);
!THIS IS NOT AN ABSOLUTE BRANCH
PREV_.P;
END;
END; !ASSIGNED GO TO
!CGOID:
BEGIN !COMPUTED GO TO
!A COMPUTED GOTO IS NOT AN ABSOLUTE BRANCH, SINCE IF THE
!INDEX IS OUT OF RANGE CONTROL IS TRANSFERRED TO THE NEXT
!STATEMENT.
DECR I FROM .P[GOTONUM]-1 TO 0 DO
BEGIN
PA_@(.P[GOTOLIST]+.I); !PA BOUND TO BASE
INFLOOP;
HOOKUP(.PA);
END;
PREV_.P;
END; !COMPUTED GO TO
!IFAID:
BEGIN !ARITHMETIC IF
PA_.P[AIFLESS];
INFLOOP;
HOOKUP(.PA);
PA_.P[AIFEQL];
INFLOOP;
HOOKUP(.PA);
PA_.P[AIFGTR];
INFLOOP;
HOOKUP(.PA);
%[637]% PREV_0;
END; !ARITHMETIC IF
!IFLID:
BEGIN !LOGICAL IF
!ONLY TRICKY CASE
!FIRST GET THE OPTIMIZERS CORE FOR THE STATEMENT
PC_.P; !SAVE P
P_.P[LIFSTATE];
NAME<LEFT>_5;
P[SRCOPT]_CORMAN();
P[SUCPTR]_FGRAPH[0];
P[PREDPTR]_RGRAPH[0];
P_.PC; !RESTORE P
!THE IF STATEMENT BECOMES THE PREDECOESSOR OF LIFSTATE
LNKREV(.P,.P[LIFSTATE]);
!LIFSTATE BECOMES THE SUCCESSOR OF THE IF STATEMENT
LNKFWD(.P[LIFSTATE],.P);
!NOW THE TRICKY PART
! THE SUCCESSOR OF LIFSTATE
! **NOTE IT IS NOT THE NEXT STATEMENT IF LIFSTATE IS A BRANCH
!
PREV_0;
PC_.P; !SAVE P
P_.P[LIFSTATE]; !TRICK GRAPH
GRAPH();
!
!IF PREV IS NOT ZERO NOW IT WAS NOT A BRANCH STATEMENT
!
P_.PC; !RESTORE P
IF .PREV NEQ 0 THEN
BEGIN
!
!LIFSTATE IS A PREDECESSOR OF THE NEXT STATEMENT
LNKREV(.P[LIFSTATE],.P[SRCLINK]);
!
!THE NEXT STATEMENT IS A SUCCESSOR OF LIFSTATE
!
LNKFWD(.P[SRCLINK],.P[LIFSTATE]);
END ELSE P[TRUEISBR]_1;
!
PREV_.P;
END;
!RETUID:
BEGIN !RETURN STATEMENT
LNKBOT;
%[637]% PREV_0;
TOP[HASRTRN]_1;
END;
!STOPID:
BEGIN !STOP STATEMENT
LNKBOT;
%[637]% PREV_0;
END;
!READID:
IOBRANCH;
!WRITID:
IOBRANCH;
!DECOID:
%1136% IOBRANCH;
!ENCOID:
%1136% IOBRANCH;
!REREDID:
%1136% IOBRANCH;
!FINDID:
%1136% IOBRANCH;
!CLOSID:
IOBRANCH;
!INPUID:
%1136% IOBRANCH; ! OPTERR();
!OUTPID:
%1136% IOBRANCH; ! OPTERR();
!BACKID:
%1136% IOBRANCH;
!BKFILID:
%1136% IOBRANCH;
!REWDID:
%1136% IOBRANCH;
!SKFILID:
%1136% IOBRANCH;
!SKRECID:
%1136% IOBRANCH;
!UNLODID:
%1136% IOBRANCH;
!RELSID:
%1136% IOBRANCH; ! OPTERR();
!ENDFID:
%1136% IOBRANCH;
!ENDID:
OTHERS;
!PAUSID:
OTHERS;
!OPENID:
IOBRANCH;
!SFNID:
OTHERS;
!FORMID:
OTHERS;
!BLTID:
OTHERS;
!REGMASK:
OTHERS;
TES;
!THIS ALL DOES NOT CATCH BRANCHES BACK OR CONNECT WITH
!INNER (MORE INNER, NOT NECESSARILY INNERMOST) LOOPS.
!TO DO THIS WE MUST LOOK AT THE LABEL OF THE STATEMENT, IF ANY,
!AND SEE IF THERE WAS A REFERENCE PREVIOUSLY MADE FROM THE
!*INSIDE*. SNEXTND IS A LABEL TABLE FIELD WHICH IS SET TO LOO
!IN MAKLLL AND UPDATED IN DOCOLLAPSE SO THAT IT POINTS TO
!THE OUTERMOST LOOP OF ANY NEST WHUCH CONTAINS THE LABEL IN QUESTION.
IF .P[SRCLBL] NEQ 0 THEN
BEGIN
PA_.P[SRCLBL];
![716] IF THIS LABEL CAN BE REACHED ON RETURN FROM SUBROUTINES
![716] THEN WE MUST MARK THE LOOP FOR NO GLOBAL REGISTER ALLOCATION
%[716]% IF .PA[SNRFS] NEQ 0 THEN TOP[HASRTRN]_1;
IF .PA[SNEXTND] NEQ 0 AND
.PA[SNEXTND] NEQ .LOOP AND
.PA[SNREFNO] NEQ 1 THEN
LNKEXTND;
END;
END;
FORWARD LOKENTRANCE,MAKLLL;
GLOBAL ROUTINE GPHBLD =
BEGIN
!BUILD THE FORWARD AND REVERSE GRAPHS FOR THE PROGRAM
!TOP IS FIRST STATEMENT
!BOTTOM IS LAST STATEMENT
!
EXTERNAL ISN,MOVLAB,LOOP;
EXTERNAL LEND,LOCELMIO,P2SKSTMNT,BACKST,SAVSPACE,CSTMNT;
%[637]% MAP BASE TOP:T:CSTMNT:LEND;
P_.TOP;
!GET OPTIMIZERS SPECIAL 5 WORDS PER STATEMENT FOR EACH STATEMENT
!GET OPTIMIZERS WORDS FOR THIS STATEMENT (THE DO)
CSTMNT_.P;
ISN_.CSTMNT[SRCISN];
NAME<LEFT>_5;
P[SRCOPT]_CORMAN();
P[SUCPTR]_FGRAPH[0];
P[PREDPTR]_RGRAPH[0];
P_.P[SRCLINK];
!NO NEED TO RETRY THE ONE WE JUST DID
!NOW GET THEM FOR THE STATEMENT IN THE LOOP
WHILE .P NEQ .BOTTOM DO
BEGIN
IF .P[SRCID] NEQ DOID AND .P[SRCOPT] EQL 0 THEN
BEGIN
CSTMNT_.P;
NAME<LEFT>_5;
P[SRCOPT]_CORMAN();
P[SUCPTR]_FGRAPH[0];
P[PREDPTR]_RGRAPH[0];
END ELSE
IF .P[SRCID] EQL DOID THEN
BEGIN
T_.P[DOLBL];
P_PREV_.T[SNHDR];
!P WILL BE ADJUSTED IN THE STATEMNT AFTER THE NEXT END
END;
P_.P[SRCLINK];
END;
MAKLLL(); !COLLECT LOCAL LABLES
!IF THIS IS REALLY A LOOP (I.E. NOT THE MAIN PROGRAM) THEN
!MAKE LEND A PREDECESSOR OF TOP.
!THIS IS TO HANDLE THE CASE ILLUSTRATED BY THE EXAMPLE:
! DO 10 -------
! = A
! .
! .
! .
! A =
! 10
!IF IT WERE NOT DONE THE DEFINITION POINT OF A AT ITS USE WOULD
!INDICATE THAT A WAS A REGION CONSTANT
IF .LOOP NEQ 0 THEN LNKREV(.LEND,.TOP);
!START THE GRAPH WITH THE STATEMENT AFTER THE DO LOOP
CSTMNT_PREV_.TOP;
P_.TOP[SRCLINK];
EXITNO_0; !INITIALIZE EXITNO
EPTR_0;
DO
BEGIN
CSTMNT_.P;
ISN_.CSTMNT[SRCISN];
GRAPH();
P_.P[SRCLINK];
END UNTIL .P EQL .BOTTOM;
!IF THIS ISNT A MAIN PROGRAM AN THERE WERE LOOP EXITS
!GO FIND THE ENTRANCES
%[1063]% IF .LOOP NEQ 0 THEN
BEGIN
%[1063]% IF .EXITNO NEQ 0 THEN TOP[HASEXIT]_1;
LOKENTRANCE(); !COLLECT LOOP ENTRANCES
END;
!LEND STILL POINTS TO THE UNIQUE CONTINUE THAT GOES WITH THIS LOOP
!SAVE THE EXITLST INFO IN THE OPTINFO FIELD OF THIS CONTINUE
LEND[OPTINFO]_.EPTR;
END; !GRAPHBUILDER ROUTINE
ROUTINE ASSLOOKER(VAR)=
!*****
!OBSCENITY IS IN THE EYE OF THE BEHOLDER
!*****
!IT STANDS FOR ASSIGN LOOKER
BEGIN
EXTERNAL OPTERR;
!LOOK AT LINKED LIST OF ASSIGN STATEMENTS
!VAR IS SYMBOL TABLE POINTER FOR ASSIGNED VARIABLE
!P IS STATEMENT POINTER
!FOR EACH MATCH ENCOUNTERER
!P IS PREDECESSOR OF *LABELED* STATEMENT
! *LABELED* STATEMENT IS PREDECESSOR OF STMT
MAP BASE PB;
MAP BASE VAR;
OWN BASE EXPR:CNT;
!SET A FLAG ON THE STATEMENT SO WE WILL
!REMOVE THE LIST LATER. REMOVINF THE LIST GIVES BETTER
!CODE.
P[NOLBLLST]_1;
PB_.ASIPTR<LEFT>; !PICK UP GLOBAL POINTER
!FIRST GO THROUGH THE LIST AND COUNT THE &'%$ LABELS
P[GOTONUM]_0;
WHILE .PB NEQ 0 DO
BEGIN
IF .VAR EQL .PB[ASISYM] THEN
P[GOTONUM]_.P[GOTONUM]+1 !UP COUNT
ELSE
!SPECIAL *TRY HARDER* FOR ARRAY REFERENCES
BEGIN
IF .VAR[OPRCLS] EQL ARRAYREF THEN
BEGIN
EXPR_.PB[ASISYM];
IF .EXPR[OPRCLS] EQL ARRAYREF THEN
IF .VAR[ARG1PTR] EQL .EXPR[ARG1PTR] THEN
!USE THIS ONE
P[GOTONUM]_.P[GOTONUM]+1; !UP COUNT
END;
END;
PB_.PB[ASILINK];
END;
!NOW WE KNOW HOW MANY THERE ARE. IF NONE GENERATE ERROR AND QUIT
IF .P[GOTONUM] EQL 0 THEN
BEGIN
OPTERR(E62);
RETURN;
END;
!RESET PB. GET CORE FOR LIST
PB_.ASIPTR<LEFT>;
NAME<LEFT>_.P[GOTONUM];
P[GOTOLIST]_CORMAN();
CNT_0;
WHILE .PB NEQ 0 DO
BEGIN
IF .VAR EQL .PB[ASISYM] THEN
BEGIN
!BUILD OPTIONAL LIST PROGRAMMER DID NOT PROVIDE
(.P[GOTOLIST]+.CNT)<RIGHT>_.PB[ASILBL];
CNT_.CNT+1;
END
ELSE
!SPECIAL *TRY HARDER* FOR ARRAY REFERENCES
BEGIN
IF .VAR[OPRCLS] EQL ARRAYREF THEN
BEGIN
EXPR_.PB[ASISYM];
IF .EXPR[OPRCLS] EQL ARRAYREF THEN
IF .VAR[ARG1PTR] EQL .EXPR[ARG1PTR] THEN
!USE THIS ONE
BEGIN
!BUILD OPTIONAL LIST PROGRAMMER DID NOT PROVIDE
(.P[GOTOLIST]+.CNT)<RIGHT>_.PB[ASILBL];
CNT_.CNT+1;
END;
END;
END;
PB_.PB[ASILINK];
END;
END;
GLOBAL ROUTINE DOCOLLAPSE=
BEGIN
EXTERNAL LABTBL,SAVSPACE,OPTERR,LENTRY;
EXTERNAL BASE UNIQVAL;
MAP BASE T;
!CREATE A COLLAPSED DO NODE
! SUCCESSOR OF DO (IN GRAPH) IS
! STATEMENT FOLLOWING TERMINATION
! PLUS ALL OTHER EXITS
MAP PHAZ2 TOP:PB:BOTTOM;
TOP[PREDPTR]_RGRAPH[0]; !REINITIALIZE GRAPH POINTERS. PREDPTR WILL BE
TOP[SUCPTR]_FGRAPH[0]; ! FILLED BY GPHBLD FOR OUTER LOOP
TOP[LEVEL]_0; !INITIALIZE OTHER FIELDS
TOP[BUSY]_0;
TOP[PREDOM]_0;
TOP[POSTDOM]_0;
TOP[ACC]_0;
!MAKE A NEW BOTTOM.
!IT WILL BE LEND FOR THE PURPOSES OF COLLAPSING THE DO TO
!A SINGLE NODE
BOTTOM_.LEND;
!STEP THRU EXITLST BUILDING GRAPH
!FIRST GET OPTIMIZERS WORDS FOR BOTTOM IF THEY ARENT ALREADY THERER
IF .BOTTOM[SRCOPT] EQL 0 THEN
BEGIN
NAME<LEFT>_5;
BOTTOM[SRCOPT]_CORMAN();
END;
!AT ANY REATE REINITIALIZE THE GRAPHING FOR IT
BOTTOM[SUCPTR]_FGRAPH[0];
BOTTOM[PREDPTR]_RGRAPH[0];
!ZERO OTHER FIELDS
BOTTOM[BUSY]_BOTTOM[LEVEL]_BOTTOM[PREDOM]_BOTTOM[POSTDOM]_0;
BOTTOM[ACC]_0;
!HOOK TOP TO BOTTOM
LNKREV(.TOP,.BOTTOM);
LNKFWD(.BOTTOM,.TOP);
!PUT THE EXITLST INTO THE FIELD EXTLST
IF .EXITNO NEQ 0 THEN
TOP[EXTLST]_.EPTR;
!SAVE DOCHNGL FOR GLOBAL REGISTER ALLOCATION
!IN THE UNIQUE LABEL TABLE ENTRY THAT GOES WITH TOP
P_.TOP[DOLBL];
P[SNSTATUS]_.TOP[DOCHNGL];
!NOW GIVE BACK THE OPTIMIZERS WORDS FOR THE STATEMENTS IN THE
!LOOP. NOT FOR TOP OR BOTTOM, HOWEVER.
%[1164]% !ALSO UPDATE THE SNEXTND FIELD OF THE LABEL
%[1164]% !TABLE ENTRIES FOR ANY INNER LOOPS TO POINT TO
%[1164]% !THE OUTER-MORE LOOP WE ARE NOW COLLAPSING.
P_.TOP[SRCLINK];
WHILE .P NEQ .BOTTOM DO
BEGIN
IF .P[SRCOPT] NEQ 0 THEN
BEGIN
!GIVE BACK GRAPH ELEMENTS TOO
RELSGRAPHELM(P);
SAVSPACE(4,.P[SRCOPT]);
!DO NOT ALLOW ASSIGNED GO TO LISTS TO BE GIVEN
! BACK BY MORE THAN ONE DO LOOP! CLEAN UP TOO.
P[SRCOPT]_0;
!CHECK FOR ASSIGNED GO TO STATEMENTS AND
!LOGICAL IF STATEMENTS WHERE WE CAN CLEAN HOUSE
! FOR AN ASSIGNED GO TO STATEMENT, DELETE THE
! OPTIMIZER BUILT LIST
IF .P[SRCID] EQL AGOID AND .P[NOLBLLST] THEN
BEGIN
SAVSPACE(.P[GOTONUM]-1,.P[GOTOLIST]);
P[GOTONUM]_P[GOTOLIST]_0;
END
ELSE
IF .P[SRCID] EQL IFLID THEN
BEGIN
PC_.P[LIFSTATE];
IF .PC[SRCOPT] NEQ 0 THEN
BEGIN
RELSGRAPHELM(PC);
SAVSPACE(4,.PC[SRCOPT]);
PC[SRCOPT]_0;
IF .PC[SRCID] EQL AGOID AND
.PC[NOLBLLST] THEN
BEGIN
SAVSPACE(.PC[GOTONUM]-1,
.PC[GOTOLIST]);
PC[GOTONUM]_PC[GOTOLIST]_0;
END
END
END
END;
%[1164]% !Now walk any inner DOs
%[1164]% IF .P[SRCID] EQL DOID THEN
%[1164]% BEGIN
%[1164]% PB_.P[DOLBL]; !Get terminus node of inner loop
%[1164]% PB_.PB[SNHDR];
%[1164]% WHILE .P NEQ .PB DO !Until end of this inner loop
%[1164]% BEGIN !Graph elements discarded
%[1164]% ! during earlier collapse
%[1164]% IF .P[SRCLBL] NEQ 0 !If labeled, point
%[1164]% THEN !label at this loop
%[1164]% BEGIN
%[1164]% PA_.P[SRCLBL];
%[1164]% PA[SNEXTND]_.LOOP
%[1164]% END;
%[1164]% PREV_.P; !Keep track of one node back
%[1164]% P_.P[SRCLINK] !Next node in inner loop
%[1164]% END;
%[1164]% !Include the inner terminus label
%[1164]% PA_.P[SRCLBL];
%[1164]% PA[SNEXTND]_.LOOP;
%[1164]% P_.PREV !Drop back a node to allow
%[1164]% !outer loop to clean up graph
%[1164]% !elements for inner terminus
%[1164]% END;
P_.P[SRCLINK];
END;
!BECAUSE SUBSUMPTION MAY HAVE MOVED STATEMENTS WITH THE
!OPTIMIZERS WORDS INFRONT OF THE LOOP WE WILL ALSO LOOK
!BETWEEN LENTRY AND TOP
P_.LENTRY;
WHILE .P NEQ .TOP DO
BEGIN
IF .P[SRCOPT] NEQ 0 THEN
BEGIN
RELSGRAPHELM(P);
SAVSPACE(4,.P[SRCOPT]);
P[SRCOPT]_0;
END;
P_.P[SRCLINK];
END;
!RETURN THE SPACE CONSUMMED BY THE UNIQUE VALUE LIST
WHILE .UNIQVAL NEQ 0 DO
BEGIN
REGISTER BASE GP;
GP_.UNIQVAL[CLINK];
SAVSPACE(UNIQSIZ-1,.UNIQVAL);
UNIQVAL_.GP;
END;
END;
ROUTINE LOKENTRANCE=
BEGIN
!AFTER GPHBLD WE CHECK OUT LLL TO SEE WHICH LABELS ARE
!LOOP ENTRANCES.
!THE STATEMENTS WHICH ARE ENTRANCES ARE PUT INTO THE
!GRAPH WITH TOP AS PREDECESSOR AND AS SUCCESSORS OF TOP
!TOP IN AFFECT WILL SERVE AS THE SUPER ENTRY
!WE WILL ALSO CHECK TO SEE IF THE LOOP HAS NO EXITS AND SO THE
!CONTROL WORD AND INDUCTION VARIABLES MAY NOT NEED MATERIALIZATION
![1063] Statement deleted.
![1063] IF .EXITNO EQL 0 THEN TOP[NEDSMATRLZ]_0;
PA_.TOP[DOLBL];
!PA POINTS TO TOP OF CHAIN OF LOCAL LABELS
!FOLLOW THAT CHAIN AND COMPARE REFERENCE COUNTS.
!IF THEY DONT MATCH ITS AN ENTRANCE. ZERO THE
!LABLE TABLE FIELDS WHILE YOUR HERE
WHILE .PA NEQ 0 DO
BEGIN
IF .PA[SNREFNO] NEQ .PA[LREFCNT] THEN
BEGIN
!THIS IS AN ENTRANCE
PB_.PA[SNHDR];
!DONT INCLUDE STATEMENTS THAT WILL MAKE
!BLOW-UPS OR FORMATS
IF .PB[SRCOPT] NEQ 0 THEN
BEGIN
%[1063]% EXTERNAL FATLERR,E151;
!PUT THIS STATEMENT ON THE SUCCESSOR LIST FOR THE TOP OF
! THE LIST - NAMELY THE DO STATEMENT.
LNKFWD(.PB,.TOP);
LNKREV(.TOP,.PB);
!SET FLAG FOR GLOBAL ALLOCATOR USE
![1063] If loop entrances with absolutely no exits, then error!
%[1150]% IF NOT .PA[SNASSIGNED] THEN
%[1066]% IF .EXITNO EQL 0 THEN FATLERR(.PA[SNUMBER],0,E151<0,0>);
TOP[HASENT]_1;
END;
END;
!ZERO THE FIELDS
PB_.PA[SNNXTLAB]; !SAVE POINTER
PA[SNNXTLAB]_0;
! Delete one unnecessary line
![1125] PA[LREFCNT]_0;
!RESTORE POINTER
PA_.PB;
END;
END;
ROUTINE LOKEXIT (LABLE)=
BEGIN
EXTERNAL OPTERR,LOOP;
!SEARCH LLL FOR LABEL
!IF NOT THERE IT IS A LOOP EXIT
!ADD TO LOOP EXIT LIST
!LABEL IS DELIBERATELY MISSPELLED
MAP BASE LLLNO:EXITLST;
LABEL WHLEXT;
MAP PEXPRNODE LABLE;
! Local label count needs to be incremented for this label reference.
%[1112]% LABLE[LREFCNT]_.LABLE[LREFCNT]+1;
!POINT TO TOP OF LINKED LIST OF LOCAL LABELS.
LLLNO_.TOP[DOLBL];
WHILE .LLLNO NEQ 0 DO
%[1112]% IF .LLLNO EQL .LABLE THEN RETURN 0
%[1112]% ELSE LLLNO_.LLLNO[SNNXTLAB];
!IF HERE LABEL WAS NOT ON LIST FOR CURRENT
!LOOK AT SNEXTND FIELD
IF .LABLE[SNEXTND] NEQ 0 AND
.LABLE[SNEXTND] NEQ .LOOP
AND NOT .TOP[INNERDOFLG] THEN
BEGIN
!CHECK TO BE REALLY SURE THAT THE LOOP WE ARE
!BRANCHING BACK INTO IS INNERMORE TO THE ONE
!CURRENTLY BEING PROCESSED.
REGISTER BASE T:T1;
T_.LABLE[SNEXTND];
T1_.TOP;
!LOOK THROUGH THE STATEMENTS IN THIS LOOP.
!T POINTS TO THE DO DEPTH ANALYSIS ENTRY
!FOR THE LOOP CONTINAING THE LABEL
WHILE .T1 NEQ .BOTTOM DO
BEGIN
!FOR THIS TO BE TRUE T1 SHOULD BE A DOLOOP
IF .T1 EQL .T[DOSRC] THEN RETURN (2);
T1_.T1[SRCLINK];
END;
END;
!IF WE ARE STILL IS THIS ROUTINE IT MUST BE AN EXIT
EXITLST_.EPTR;
!EPTR WAS SET IN THE MAIN BODY OF GPHBLD
WHLEXT:
!THE WHILE TAKES CARE OF THE INITIAL CONDITION
WHILE .EXITLST NEQ 0 DO
BEGIN
!THE THE LABEL IS ALREADY THERE JUST EXIT WITH THE
!CORRECT VALUE
IF .EXITLST[ELBL] EQL .LABLE THEN RETURN 1;
!NOW FOR THE TERMINATING CONDITION
IF .EXITLST[CLINK] NEQ 0 THEN
EXITLST_.EXITLST[CLINK]
ELSE
LEAVE WHLEXT;
END;
!HERE WE KNOW WE HAVE TO ADD ON TO THE LIST AND THAT EXITLST
!POINTS TO THE END OF THE LIST
NAME<LEFT>_1;
IF .EPTR EQL 0 THEN
EXITLST_CORMAN()
ELSE
EXITLST_EXITLST[CLINK]_CORMAN();
!FILL IS THE LABLE FIELD
EXITLST[ELBL]_.LABLE;
EXITNO_.EXITNO+1;
!BE SURE TO SET EPTR
IF .EPTR EQL 0 THEN EPTR_.EXITLST;
RETURN 1;
END;
ROUTINE MAKLLL=
BEGIN
!CREATE A LINKED LIST OF THE LOCAL LABELS IN THIS INTERVAL.
!THE LINKS ARE KEPT IN THE SNNXTLAB FIELD OF THE LABEL
!TABLE. TOP[DOLBL] THUSLY IS ALWAYS THE HEAD OF THE LIST.
!LOCAL REFERENCE COUNTS ARE KEPT IN THE LREFCNT = SN1STLAB
!FIELD.
MAP BASE LLLNO;
PA_.TOP[DOLBL];
PA[SNEXTND]_.LOOP;
!MAKE LLLNO POINT TO THE HEAD OF THE LINK LIST WE ARE ABOUT TO
!BUILD . THE LIST IS CARRIED IN THE SNNXTLAB FIELD OF
!THE LABEL TABLE.
LLLNO_.TOP[DOLBL];
! Local label count incremented by DO plus label itself.
%[1112]% LLLNO[LREFCNT]_.LLLNO[LREFCNT]+2;
!NOW GET ALL THE OTHERS IN THE LOOP
!SNEXTND POINTS BACK TO THE DO DEPTH ANALYSIS FROM WHICH WE CAN
!ALWAYS GET TO THE DO STATEMENT ITSELF
P_.TOP[CLINK];
DO
BEGIN
IF .P[SRCLBL] NEQ 0 AND .P[SRCLBL] NEQ .TOP[DOLBL] THEN
BEGIN
PA_.P[SRCLBL];
LLLNO_LLLNO[SNNXTLAB]_.PA;
! Get the local reference count right.
%[1125]% LLLNO[LREFCNT]_.LLLNO[LREFCNT]+1;
!SET SNEXTND FIELD OF THE LABEL TABLE ENTRY
PA[SNEXTND]_.LOOP;
!ZERO THE LINK FIELD TO PREVENT LEFTOVERS
!MAKING TROUBLE
PA[SNNXTLAB]_0;
END;
!IF THIS IS A DO LOOP WE WANT TO SKIP THE LABELS
%[1164]% !THAT ARE DEFINED WITHIN IT.
IF .P[SRCID] EQL DOID THEN
BEGIN
P_.P[DOLBL];
%[1164]% P_.P[SNHDR]
END;
P_.P[CLINK]
END UNTIL .P EQL .BOTTOM;
END;
FORWARD DOMINATE,REFLOOD,PDOMINATE;
ROUTINE MOORE=
BEGIN
EXTERNAL OPTERR;
LABEL NODOM; ![637]
!DO FORWARD MOORE FLOOD
!HEAD POINTS TO TOP OF GRAPH
!INITIALIZE ITS LEVEL TO 1.
!FOLLOW THE SUCCESORE CHAIN (P1 IS FOLLOWING CHAIN, P2 IS POINTING
! AT ACTUAL SUCCESSOR STATEMENT NODE).
!INITIALIZE THE LEVEL NUMBER AND PREDOMINATORE FIELDS OF EACH SUCCESSOR.
!ALSO LINK THE NODES TOGETHER IN MOORE FLOOD ORDER (TAIL IS USED FOR THIS).
HEAD[LEVEL] _1;
DO
BEGIN
P1_.HEAD[SUCPTR];
WHILE .P1[CESLNK] NEQ 0 DO
BEGIN
P2_.P1[CESSOR];
IF .P2[LEVEL] EQL 0 THEN
BEGIN
%[637]% IF .P2[POSTDOM] EQL 0
%[637]% THEN
%[637]% NODOM: BEGIN
%[637]% !WE HAVE FOUND A PART OF THE GRAPH THAT THE
%[637]% !COMPILER THINKS IS PART OF AN INFINITE LOOP.
%[637]% !ACTUALLY, THERE ARE PROBABLY EXITS LIKE
%[637]% !CALL EXIT OR CALL DOSTOP THAT THE COMPILER
%[637]% !DOES NOT RECOGNIZE AS EXITS.
%[637]% !WE WANT TO FIND THE "BOTTOM" OF THIS LOOP
%[637]% !AND MAKE IT A PREDECESSOR TO THE END STATEMENT
%[637]% !TO CONNECT THE GRAPH.
%[637]% !WE WILL DO THIS BY LOOKING FOR A STATEMENT
%[637]% !THAT HAS BOTH NO POSTDOMINATOR (I.E. IS IN
%[637]% !THE LOOP) AND NO SUCCESSOR IN THE LOOP THAT
%[637]% !WE HAVE NOT ALREADY LOOKED AT (I.E. HAS A LEVEL
%[637]% !OF ZERO).
%[637]% LOCAL PHAZ2 PX:PY;
%[637]% PX_.P2[SUCPTR];
%[637]% WHILE .PX[CESLNK] NEQ 0
%[637]% DO
%[637]% BEGIN
%[637]% PY_.PX[CESSOR];
%[637]% IF .PY[POSTDOM] EQL 0
%[637]% AND .PY[LEVEL] EQL 0
%[637]% THEN
%[637]% LEAVE NODOM;
%[637]% PX_.PX[CESLNK]
%[637]% END;
%[637]% DISCONFLG_TRUE;
%[637]% LNKFWD(.LEND,.P2);
%[637]% LNKREV(.P2,.LEND)
%[637]% END;
P2[LEVEL] _.HEAD[LEVEL] + 1;
P2[PREDOM] _ .HEAD;
TAIL[BUSY] _ .P2;
TAIL_.P2;
END;
P1_.P1[CESLNK];
END;
HEAD_.HEAD[BUSY];
END UNTIL .HEAD EQL 0;
END;
!***********************************************
ROUTINE SANDBAG=
BEGIN
!THE NAME IS IN KEEPING WITH THE FLOOD IDEA
!THE ROUTINE REINITIALIZES THE LEVEL FIELDS OF THE
!OPTIMIZERS WORDS TO TRY AGAIN ON EITHER A FORWARD OR REVERSE
!MOORE FLOOD.
DO
BEGIN
HEAD[LEVEL]_0; !ZERO LEVEL FOR FLOOD ALGORITHM
OLDHEAD_.HEAD[BUSY];
!ALSO ZERO BUSY FIELD SO FORWARD BUSY LIST WILL TERMINATE
HEAD[BUSY]_0;
HEAD_.OLDHEAD;
END UNTIL .HEAD EQL 0;
END;
!*****************************************************
GLOBAL ROUTINE FLOOD =
BEGIN
MAP PHAZ2 TOP;
%[637]% EXTERNAL OPTERR,WARNERR;
%[637]% !ASSIGN MOORE FLOOD NUMBER AND SET UP BUSY LIST FOR
%[637]% !PREDOMINATOR ALGORITHM
%[637]%
%[637]% DO
%[637]% BEGIN
%[637]% !GET POSTDOMINATORS FIRST
%[637]% REFLOOD();
%[637]% PDOMINATE();
%[637]% !ZERO BUSY LIST AND LEVEL FIELDS FROM POSTDOMINATOR ALGORITHM
%[637]% HEAD_.OLDHEAD;
%[637]% SANDBAG();
%[637]% HEAD_.TOP; TAIL _ .TOP;
%[637]% HEAD[PREDOM]_.HEAD;
%[637]% DISCONFLG_FALSE;
%[637]% MOORE();
%[637]% !IF THE GRAPH IS DISCONNECTED, THEN MOORE WILL HAVE SET
%[637]% !DISCONFLG AND MADE MORE CONNECTION(S) IN THE GRAPH TO
%[637]% !HOPEFULLY CONNECT IT. IF SO, ZERO EVERYTHING AND START
%[637]% !OVER USING NEW PROGRAM GRAPH.
%[637]% IF .DISCONFLG THEN (HEAD_.TOP; SANDBAG())
%[637]% END UNTIL NOT .DISCONFLG;
%[637]%
%[637]% !IF WE DIDN'T REACH TOP AFTER ALL THAT, SOMETHING'S WRONG
%[1066]% IF .TOP[POSTDOM] EQL 0 THEN
%[1066]% BEGIN
%[1066]% ISN_0;
%[1066]% OPTERR(E37)
%[1066]% END;
%[637]%
%[637]% !NOW LOOP THROUGH THE PROGRAM LOOKING FOR STATEMENTS THAT WERE NOT
%[637]% !FOUND BY THE ABOVE MOORE FLOOD. THESE STATEMENTS ARE INACCESSIBLE
%[637]% !AND CAN BE DELETED.
%[637]% HEAD_.TOP;
%[637]% PREV_.TOP;
%[637]% WHILE .HEAD NEQ .LEND DO
%[637]% BEGIN
%1137% IF .HEAD[SRCOPT] NEQ 0 ! If in an inner loop, no optimizer words
%1137% AND .HEAD[LEVEL] EQL 0
%[637]% AND .HEAD[SRCID] NEQ ENDID !NEVER DELETE ENDS
%[637]% AND .HEAD[SRCID] NEQ ENTRID !NEVER DELETE ENTRIES
%[637]% THEN
%[637]% BEGIN
%[637]% !GENERATE A MESSAGE TO SAY THERE WAS
%[637]% !INACCESSIBLE CODE
%[637]%
%[637]% IF .HEAD[SRCISN] NEQ 0 THEN
%[637]% WARNERR(.HEAD[SRCISN],E105); !ISSUE WARNING MESSAGE
%[637]% !IF WE ARE REMOVING A DO MARK IT AS GONE
%[637]% IF .HEAD[SRCID] EQL DOID THEN
%[637]% BEGIN
%[637]% REGISTER BASE T;
%[637]% HEAD[DOREMOVED]_1;
%[637]% !WE WILL DELETE THE WHOLE LOOP
%1140% T_.HEAD[DOLBL];
%1140% DO
%1140% BEGIN
%1140% IF .HEAD[SRCID] EQL DOID THEN
%1140% IF .HEAD[HASENT] NEQ 0 ! Loop has entrances
%1140% THEN ! Inaccessible DO, but accessible labels
%1140% BEGIN
%1140% ISN_.HEAD[SRCISN];
%1140% OPTERR(E37); ! Quit. Optimizer would loop.
%1140% END;
%1140% HEAD_.HEAD[SRCLINK]
%1140% END
%1137% UNTIL .HEAD[SRCLBL] EQL .T;
%[637]% END;
%[637]% PREV[SRCLINK]_.HEAD[SRCLINK]
%[637]% END
ELSE
PREV_.HEAD;
HEAD_.HEAD[SRCLINK];
END; !WHILE LOOP
LEND_.PREV[SRCLINK];
HEAD_.TOP;
DOMINATE();
END;
!*********************************************
ROUTINE DOMINATE =
BEGIN
EXTERNAL CSTMNT,ISN;
MAP BASE CSTMNT;
!FIND PREDOMINATORS IN THE FORWARD GRAPH
!THE NOCHANGE GOVERNS THE ITERANTION. IT IS INIATIALLY TRUE
!AND BECOMES FALSE WHEN NO NODES WERE UPDATED ON AN ENTIRE PASS.
!THE SUCCESSORS OF HEAD ARE EXAMINED.
!P3 FOLLOWS THE SUCCESSOR LIST. PO POINTS TO THE ACTUAL SUCCESSOR.
!THE PREDOMINATOR OF EACH SUCCESSOR IS EXAMINED. THE LEVEL (MOORE FLOOD)
!IF THE SUCCESSOR IS COMPARED WITH THE LEVEL OF THE NODE (P1, INITIALLY
! HEAD) UNDER CONSIDERATION. THE PREDOMINATOR CHAINS ARE JUGGLED
!BACKWARD UNTIL THE LEVELS ABD EQUAL. THE PREDOMINATORE OF PO IS
!CHANGED IF APPROPRIATE.
LOCAL NOCHANGE;
HEAD_.TOP;
HEAD[PREDOM]_.TOP; !STOPS IT AT TOP
DO
BEGIN
NOCHANGE _ 1;
DO
BEGIN
!CSTMNT AND ISN FOLOW THE PROCESS FOR DEBUGGING PURPOSES.
CSTMNT_.HEAD;
ISN_.CSTMNT[SRCISN];
P1_.HEAD;
P3_.P1[SUCPTR];
WHILE .P3[CESLNK] NEQ 0 DO
BEGIN
PO_.P3[CESSOR];
P2_.PO[PREDOM];
WHILE .P1 NEQ .P2 DO
IF .P1[LEVEL] LSS .P2[LEVEL] THEN
P2_.P2[PREDOM] ELSE P1_.P1[PREDOM];
IF .PO[PREDOM] NEQ .P1 THEN
BEGIN
PO[PREDOM] _ .P2;
NOCHANGE _ 0;
END;
P3_.P3[CESLNK];
END;
HEAD_.HEAD[BUSY];
END UNTIL .HEAD EQL 0;
HEAD_.TOP;
END UNTIL .NOCHANGE;
END;
!***********************************************************
ROUTINE REFLOOD=
BEGIN
!ASSIGN MOORE FLOOD NUMBER AND SET UP BUSY LIST FOR
!POSTDOMINATOR ALGORITHM
!SEE COMMENTS IN ROUTINE MOORE FOR THE ALGORITHM. IT IS
!IDENTICAL TO THE PREDOMINATOR *FLOODING* PROCESS EXCEPT THAT
!IT IS STARTED AT LEND INSTEAD OF TOP.
!THE VARIABLES P1 AND P2 AND TAIL ALSO HAVE THE SAME FUNCTIONS.
EXTERNAL CSTMNT,ISN;
MAP BASE CSTMNT;
! LEND IS THE SUPEREXIT
HEAD_.LEND;
TAIL_.LEND;
OLDHEAD_.HEAD;
HEAD[POSTDOM]_.HEAD;
HEAD[LEVEL] _1;
DO
BEGIN
CSTMNT_.HEAD;
ISN_.CSTMNT[SRCISN];
P1_.HEAD[PREDPTR];
WHILE .P1[CESLNK] NEQ 0 DO
BEGIN
P2_.P1[CESSOR];
IF .P2[LEVEL] EQL 0 THEN
BEGIN
P2[LEVEL] _.HEAD[LEVEL] + 1;
P2[POSTDOM] _ .HEAD;
TAIL[BUSY] _ .P2;
TAIL_.P2;
END;
P1_.P1[CESLNK];
END;
HEAD_.HEAD[BUSY];
END UNTIL .HEAD EQL 0;
END;
!******************************************************
ROUTINE PDOMINATE =
BEGIN
!FIND POSTDOMINATORS IN THE REVERSE GRAPH
!SEE DOMINATE FOR DETAILS OF ALGORITHM. IT IS IDEBTICAL TO
!THE PREDOMINATORE ALGORITHM. THE VARIABLES PO,P1,P2 PREFORM
!THE SAME FUNCTIONS, EXCEPT THAT , OF COURSE, IT IS
!PREDECESSOR CHAINS THAT ARE FOLLOWED INSTEAD OF SUCCESSOR CHAINS
!AND THE POSTDOM FIELD THAT IS UPDATED.
EXTERNAL CSTMNT,ISN;
MAP BASE CSTMNT;
LOCAL NOCHANGE;
HEAD_.OLDHEAD;
DO
BEGIN
NOCHANGE _ 1;
DO
BEGIN
CSTMNT_.HEAD;
ISN_.CSTMNT[SRCISN];
P1_.HEAD;
P3_.P1[PREDPTR];
WHILE .P3[CESLNK] NEQ 0 DO
BEGIN
PO_.P3[CESSOR];
P2_.PO[POSTDOM];
WHILE .P1 NEQ .P2 DO
IF .P1[LEVEL] LSS .P2[LEVEL] THEN
P2_.P2[POSTDOM] ELSE P1_.P1[POSTDOM];
IF .PO[POSTDOM] NEQ .P1 THEN
BEGIN
PO[POSTDOM] _ .P2;
NOCHANGE _ 0;
END;
P3_.P3[CESLNK];
END;
HEAD_.HEAD[BUSY];
END UNTIL .HEAD EQL 0;
HEAD_.OLDHEAD;
END UNTIL .NOCHANGE;
END;
EXTERNAL DWP;
OWN LOOPTR;
MAP BASE LOOPTR;
OWN LUPSAV;
GLOBAL ROUTINE WALKER =
BEGIN
!GET A DO LOOP TO PROCESS
!CODE FOR FIRST TIME THROUGHT ONLY
!DWP IS A THREE VALUED FLAG.
! -1 INITIAL ENTRY. LUPSAV NOT VALID
! 0 NOT -1 OR 1
! 1 ONLY TREE ROOT FOUND LAST TIME. RETURN
! ZERO THIS TIME
MAP BASE LUPSAV;
!SHOULD WE QUIT
IF .DWP EQL 1 THEN RETURN (0)
ELSE
!IS THIS THE FIRST TIME
IF .DWP EQL -1 THEN
DWP_0
ELSE
BEGIN
!GRONK THE POINTER JUST PROCESSED
!********************************
!
!NOTE: THIS IS A DESTRUCTIVE WALK
!
!********************************
IF .LUPSAV[NEXTDO] NEQ 0 THEN
LUPSAV[NEXTDO]_0
ELSE
LUPSAV[PARLVL]_0;
END;
!NOW THE WALK PART
LUPSAV_0;
LOOPTR_.DLOOPTREE;
WHILE .LOOPTR[NEXTDO] NEQ 0 DO
BEGIN
LUPSAV_.LOOPTR;
LOOPTR_.LOOPTR[NEXTDO];
END;
WHILE .LOOPTR[PARLVL] NEQ 0 DO
BEGIN
LUPSAV_.LOOPTR;
LOOPTR_.LOOPTR[PARLVL];
WHILE .LOOPTR[NEXTDO] NEQ 0 DO
BEGIN
LUPSAV_.LOOPTR;
LOOPTR_.LOOPTR[NEXTDO];
END;
END;
IF .LUPSAV EQL 0 THEN
DWP_1
ELSE
DWP_0;
RETURN .LOOPTR
END;
END
ELUDOM