Google
 

Trailing-Edge - PDP-10 Archives - BB-4157D-BM - sources/ph3g.bli
There are 12 other files named ph3g.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) 1972,1977 BY DIGITAL EQUIPMENT CORPORATION
MODULE PH3G(RESERVE(0,1,2,3),SREG=#17,VREG=#15,FREG=#16,DREGS=4,START)=
BEGIN
!AUTHOR: NORMA ABEL/HPW/DCE/SJW/JNG

!	REQUIRES FIRST, TABLES, OPTMAC

GLOBAL BIND PH3GV = 5^24 + 1^18 + 245;	!VERSION DATE: 19-SEP-77

%(
REVISION HISTORY

184	-----	-----	INSERTING PRELOADS AT WRONG PLACE IN STRANGE CASE
185	-----	-----	FIX GETPRELOAD NOT TO FALSELY PRELOAD A SUBSET
			OF THE ASGN4USED VARIABLES.
186	-----	-----	FIX A ' THAT SHOLD BE " IN SORTNMAKE
			PLUS FIX RAYMERIT TO PROPERLY CREDIT
			LOCAL COMMON SUBS AS SUBSCRIPTS
187	-----	-----	FIX GETPRELOAD IN SKIPMAT AREAS
188	-----	-----	FIXENTRY IS MISSING PRELOADS
189	-----	-----	TRY AGAIN ON 188
190	-----	-----	MISPLACED END IN FIXENTRY
191	-----	-----	CONCEPTUAL ERROR IN MATERIALIZATIONS
			CAUSED BY SUBTLE LOOP STRUCTURE TOGETHER
			WITH SUBSUMPTION
192	-----	-----	USE NOINDVARFLG TO PREVENT BAD REGCONTETNS
			SUBSTITUTIONS
193	-----	-----	MODIFY MATERIALIZATION CONDITIONS ON
			INNER LOOPS ONLY OF A NEST
194	-----	-----	IN CASES 2 AND 4 TURN OFF MATRLZ BIT ONLY
			IF INDVAR IS GLOBALLY ALLOCATED.
195	-----	-----	MAKE LEAFLOOKER A CASE STATEMENT AND FIX
			SOME MINOR UNOPTIMALITIES
196	-----	-----	SET NOALLOC ON .R VARS GLOBALLY ALLOCATED
196	----	-----	FIX BOOLEAN NOT TO DO LOADS AND STORES
			'TWEEN CALLS
197	-----	-----	GUESS
198	-----	-----	CHECK FOR GLOBALLY ALLOCATED DO INDEX
			IN DETERMINING LOWEST AVAILABLE REGISTER
			TO GLOBALLY ALLOCATE
199	-----	-----	FIX A COUPLE OF BENCHMARKS PROBLEMS
			IN PRELOADING, SAVING, RESTORING
			AND MATERIALIZATION
200	-----	-----	REFINE VALUE SUBTRACTED FOR USE AS LIB
			FUNCTION ARG AND DO NOT ALLOCATE IF
			MERIT ISNT BETTER THAN SIMPLE MOVE
201	-----	-----	IN AN ASSIGNMENT STATEMENT WITH USER FUNCTION
			REFERENCES, NOT IMMEDIATELY FOLLOWED BY A CALL
			OR ANOTHER STATEMENT WITH A USER FUNCTION
			REF  SAVE ONLY GLOBALLY ALLOCATED
			ARGUMENTS TO THOSE FUNCTIONS
202	-----	-----	FIX 201
203	----	-----	ONE MORE TIME ON 201
204	-----	-----	ADD BUBBLE SORT TO DO CONBINATION
			OF LEAFSUBSTITUTE AND SAVE RESTORE
			PUT IT ALL INTO FLIPCODES
205	-----	-----	PUNT
206	-----	-----	DO NOT INCREMENT CALLREFNO IF THERE ARE
			NO ARGUMENTS
207	-----	-----	FIX REFERENCES TO PROEPITYP AND PROGNAME
208	-----	-----	DO NOT ALLOCATE A LOOP THAT HAS A USER FUNC.
			REFERENCE AS PART OF THE LOOP CONTROL. USRFNREF
209	-----	-----	MACRO CHKGIX WAS ERROREOUSLY CHECKING
			GLOBREG INSTEAD OF CHOSEN
			FLAG GETS VERY CONFUSED.
210	-----	-----	COMPLEXITY OF DO LOOP ITSELF NO BEING PROPERLY
			CONSIDERED

211	-----	-----	CALL DATPROC WHETHER OR NOT A REL FILE IS BEING PRODUCED
212	-----	-----	IN DOUBLE NEST ALLOCATION SAV .OS ASSIGNED
			BEFORE LENTRY. THIS IMPLIES THEY HAVE
			BEEN SUBSUMBED AND MAY BE USED LATER TOO.
213	-----	-----	USED4ASGND ANALYSIS INCOMPLETE FOR STATEMENTS
			THAT CONTAIN USER FUNCTION REFERENCES.
214	-----	-----	OUTER LOOP INDEX ALWAYS GETTING NO PRELOAD
			SET. NEED TO CHECK USED4ASGND TOO.
215	-----	-----	MESSING UP RESTORE OF ALLOCATED VARS
			IF CALL, USER FUNC REF CASE.
216	-----	-----	212 HAD A SIDE EFFECT THAT NEED CORRECTING
			FOR GUIDE 2 AND 4.
217	-----	-----	1. DO NOT GLOBALLY ALLOCATE IF BOUNDS SWITCH
			IS USED
			2. FIX CALLS SO THAT THE SAVE/RESTORE
			SEQUENCES WILL WORK WITH NO ARGS
218	-----	-----	ITEM MISSING FROM CASE IN CREDIT
219	-----	-----	BUG THAT SKIPS A REAL STATEMENT WHEN IT
			THINKS ITS SKIPPING A MATERIALIZATION
220	-----	-----	NOT SAVING AND RESTORING REGS ON A CALL WITH
			NO ARGS. CALL COULD CLOBBER REGS
221	-----	-----	IN SETTING UP PREVIOUS BASIC BLOCK POINTERS
			LOGICAL IFS WITH BRANCHS ARE NOT TAKEN
			INTO ACCOUNT PROPERLY
222	-----	-----	REGISTER PRELOADS ARE BEING INSERTED IN
			FRONT OF LOGICAL IFS WITH BRACHES AS THE
			TRUE BRANCH
223	-----	-----	NOT PROPERLY HANDLING LOOPS IN WHICH THE INDEX
			IS NEITHER GLOBALLY OR LOCALLY ALLOCATED.
224	-----	-----	BLEW 223 FOR MAIN PROGRAM WITH SINGLE LOOP
225	-----	-----	EMPTY SUBROUTINE DID NOT GET OPTIMIZED. DONT
			TRY TO ALLOCATE IT EITHER
226	-----	-----	DO NOT ALLOCATE ANY VARIABLE THAT DOES NOT
			AT LEAST SAVE A MOVEM
227	-----	-----	INSERT REGMASK NODE IF BASIC
			BLOCK STARTS WITH A LOGICAL IF WITH A BRANCH. 
			ALSO CLEAN UP GETPRELOAD BY MAKING THE REGMASK
			SET UP CODE A MACRO
228	-----	-----	MAKE SETDOIREG COGNISCENT OF DOUBLE PRECISION
			INDICES NEEDING AN EVEN ODD PAIR.
229	-----	240	NOT LEAVING TWO PAIR AND NOT DELETEING
			LOCALLY ALLOCATED DO LOOP INDEX REG
			FROM GLOBAL CONSIDERATION IF IT IS NOT
			WITHIN THE FIRST 10 OF
			THE UNSORTED LIST
230	15209	246	BRANCHES IN LOOPS ARE NOT FORCING USED4ASGND ON
231	15952	266	FIX INSERTIONS OF PRELOAD NODES AFTER REGMASK WHEN THERE 
 			ARE NO PREVIOUS LOOP MATERIALIZATIONS TO SKIP
232	16112	277	FIX SUBSTITUTIONS OF REGISTERS TO BE ONLY THE ONES
			TO BE SAVED
233	QAR	316	FIX 277 TO DO IT CORRECTLY, USING THE RIGHT BITS
234	17045	332	MAKE LEAFLOOKER TREAT ASSIGN STATEMENTS PROPERLY
235	17545	347	CHANGE RANGE OF SUBSTITUTION OF REGISTERS
			TO NOT INCLUDE LOGICAL IF'S AT BEGINNING
236	17545	350	FOR COMMON SUBS, DON'T FORGET TO SET THE
			FLAG TO CAUSE PRELOADING IF APPROPRIATE
237	18007	352	FIX EDIT 266 TO WORK CORRECTLY
238	18004	353	FIX ARGUMENTS TO SECOND OF TWO CONSECUTIVE CALLS
239	18704	400	FIX LOGICAL IF BEFORE NESTED DO LOOP
240V	-----	VER5	RAISE PRIORITY OF ASSIGNMENT TO MEMORY IN
			REGISTER ALLOCATION IN ASCRIBE
240	18869	404	FIX ASSOCIATE VARIABLES (CANNOT LIVE IN REG)
241	19121	431	FIX REGSUBDRIVER TO MATERIALIZE VARIABLES THAT
			HAVE BEEN ALLOCATED TO REGISTERS AND ARE
			INITIALIZED BEFORE THE OUTER LOOP OF A CASE 6
			PROGRAM (NESTED DO LOOPS).
242	19484	444	DON'T FORCE PRELOAD OF COMPILER VARIABLES IN
			GOTOFORCELOAD IF A GOTO IS ENCOUNTERED.
243	19699	454	DON'T SKIP 1 TOO MANY STATEMENTS WHEN PLACING
			A PRELOAD AFTER A DO LOOP.
244	20463	502	SORT SAVED VS NON-SAVED REGS CORRECTLY IN
			  FLIPCODES & FAKE ALL NECESSARY COUNTS

***** BEGIN VERSION 5A *****

245	23116	615	WHEN PRELOADING REGISTERS, BE CAREFUL WITH
			THE PLACEMENT OF LABELS.
)%

SWITCHES NOLIST;
REQUIRE FIRST.BLI;
REQUIRE TABLES.BLI;
REQUIRE OPTMAC.BLI;
SWITCHES LIST;
SWITCHES NOSPEC;

!
! MAIN ROUTINE NAMED CHANGED TO MRP3G FOR SINGLE SEGMENT
!
!THE MAIN ROUTINE IN THIS MODULE IS MRP3G WHICH IS CALLED FROM
!PHAZONTROL. IT IS THE ONLY GLOBAL ROUTINE IN THE MODULE. THE
!ROUTINE AUDITOR DOES ALL THE REAL WORK OF COMPUTING MERITS,
!SELECTING ALLOCATIONS AND SUBSTITUTING REGCONTENTS NODES FOR THE
!VARIABLES

BIND							!USED AS INDICES INTO THE MERIT TABLES
	LHSUSE=0,					!KAMERIT & KIMERIT
	DEXUSE=1,
	LCTLUSE=2,
	FUNUSE=3,
	PLAINUSE=4,
%[V5]%	ASGNMEM=5;

!FOR VALUES OF THE VARIOUS MERITS ASSIGNED
BIND MERITVAL=PLIT ( 3,					!USE ON LHS
		     3,					!USE AS INDEX
		     6,					!LOOP CONTROL
		     6,					!CALL OR FUNCTION REFERENCE
		     0,					!OTHERS
%[V5]%		     4);				! ASSGN TO MEM


!THE MERIT ON A CALL OR FUNCTION IS ACTUALLY NEGATIVE.  THIS IS
!HANDLED IN AUDITOR BY SUBTRACTING THE CUMULATED VALUE OF THE NUMBER
!OF FUNCTION REFERENCES (FNREFNO) TIMES THE MERIT FROM THESE TABLES

!THE VECTOR CHOSEN IS USED TO HOLD INFORMATION ABOUT VARIABLES
!WITH GREATEST MERIT.  THE ROUTINE LOOKUP (ALSO USED IN
!DEFINITION POINT COMPUTATION) CAN BE USED FOR THE LINEAR
!SEARCH.
!
!FORMAT OF CHOSEN
!
!*************************
!            *           *
!    MERIT   *     PTR   *
!            *           *
!*************************
!
!PTR POINTS TO SYMBOL TABLE ENTRY
!
!WHILE THE RUNNING TALLY IS IN PROGRESS THE CELL MINWD
!CONTAINS THE MINIMUM MERIT ON THE LIST AND THE INDEX
!OF THAT ITEM ON THE LIST
!
!MINWD
!
!**********************************
!                 *               *
!    MIN MERIT    *      INDEX    *
!                 *               *
!**********************************
EXTERNAL DATPROC,PREV;
MAP BASE PREV;
EXTERNAL CORMAN,MAKPR1,LOOKUP,TOP,BOTTOM,GLOBREG,LENTRY;
EXTERNAL CHOSEN,SPECCASE,ITMCT,QQ;
OWN CLEANSLATE,THISTAT,LASTAT,PA,PB,PC,P,RAISE,HEAD,
PD,MINWD,MAXCOMPLEX[10],REGAVAIL,SAVHITCH;
MAP PEXPRNODE P:PA:PB:PC:PD:THISTAT:LASTAT;
OWN LIBFNREFNO;	!LIBRARY FUNCTION REFERENCE.
OWN WAYBBB;		!POINTS TO BASIC BLOCK IN FRONT FOR PREVBB
			!*WAY* *B*ACK *B*ASIC *B*LOCK
MAP BASE WAYBBB;
OWN PREVBB;		!POINTS TO THE PASIC BLOCK INFRONT OF A 
			!DO THAT IS BEING ALLOCATED.
MAP BASE PREVBB;

	!**;[353], PH3G @3685, DCE, 17-FEB-76
	!**;[353], VARIABLE INDICATES 2 CALLS (OR THE LIKE) IN A ROW
	OWN CALLSEEN; ![353]

OWN SAVCODE,		!CODE TO DIRECT SAVING,RESTORING,PRELOADING AND
			!MATERIALIZATION FO REGISTERS
GUIDE;			!INDICATES EXACT ALLOCATION SITUATION. SEE COMMANTS
			!INNN FRONT OF GBLALLOC.
OWN OLDCSTMNT;	!TO SAVE VALUE OF CSTMNT WHEN NEEDED
OWN CALLREFNO;		!NUMBER OF CALLS IN THE LOOP
OWN T,		!GENERAL TEMP
SECIDX;			!INDEX OF SECOND LEVEL LOOP
MAP BASE T;
OWN FNREFNO;		!NUMBER OF USER FUNCTION REFERENCES
OWN REGTOALC;		!NUMBER OF REGISTERS ALLOCATED
OWN STARTSUB,STOPSUB;	!START REGCONTENTS SUBSTIRUTION AT
				!STARTSUB AND STOP IT AT STOPSUB

MAP BASE STARTSUB:STOPSUB;
FORWARD CALLSAVE,BLDREGCONTENTS,CALRESTORE,LEAFLOOKER,MATERIALIZE;
FORWARD CREDIT,CHKMAXLST,RAYMERIT;
!MACRO TO DETERMINE IF IT IS LEGAL TO ALLOCATE A LOOP.
!HAVING AN ENTRANCE OR A RETURN MAKES IT ILLEGAL
MACRO LEGALALLOC(NOD)=
	(NOT (NOD[HASENT] OR NOD[HASRTRN] OR NOD[USRFNREF]))$;

!MACRO TO COMPARE SAVCODE WITH CODE IN NODE
MACRO CODEMATCH(ITEM)=
	(ITEM<ALCFLG> EQL .SAVCODE)$;

!MACRO TO CHECK IF THE DO LOOP INDEX WAS GLOBALLY ALLOCATED
!AND SET THE FIELD IN THE DO LOOP NODE.
!ON THE OTHERHAND IF THE INDEX IS NEITHER LOCALLY NOR GLOBALLY
!ALLOCATED THE DOIREG FIELD MUST BE SET TO THE FIRST FREE REG
!SO THAT THERE IS NOT A CONFLICT.
!THE MODULE OWN MINWD CONTAINS THIS REGISTER NUMBER.
!IF THE INDEX IS DOUBLE PRECISION ALSO ASSURE THAT AN EVEN REG IS
!CHOSEN

MACRO SETDOIREG=
	BEGIN
		EXTERNAL BASE INDVAR;
		EXTERNAL BASE QQ;
		DECR I FROM .REGTOALC-1 TO 0 DO
			IF .GLOBREG[.I]<RIGHT> EQL .INDVAR THEN
			BEGIN
				QQ_.CHOSEN[.I];
				TOP[DOIREG]_.QQ[TARGTAC];
			END;
		IF NOT .TOP[IXGALLOCFLG] THEN
			IF .TOP[NEDSMATRLZ] OR .TOP[MATRLZIXONLY] THEN
				TOP[DOIREG]_(IF .MINWD AND .INDVAR[DBLFLG] THEN .MINWD+1 ELSE .MINWD);
	END$;

!MACRO TO SEARCH GLOBALLY ALLOCATED LIST AND SET BIT IN LUP NODE
!IF THE INDEX IS GLOBALLY ALLOCATED
MACRO CHKGIX=
	BEGIN
		DECR I FROM .REGTOALC-1 TO 0 DO
			IF .CHOSEN[.I]<RIGHT> EQL .INDVAR THEN
				TOP[IXGALLOCFLG]_1;
	END$;

!MACRO TO MAKE CODE DONE IN TWO PLACES EASIER TO READ
MACRO EASY1=
	BEGIN
		STARTSUB_.TOP;
		STOPSUB_.BOTTOM;
		REGSUBDRIVER();
		FLAG_0;
		DECR I FROM .REGTOALC-1 TO 0 DO
		BEGIN
			T_.GLOBREG[.I]<RIGHT>;
			IF .T[IDATTRIBUT(INDATA)] THEN
			BEGIN
				GLOBREG[.I]<ALCFLG>_PRELOAD;
				FLAG_1;
			END;
		END;

		SAVCODE_PRELOAD;
		GBSYREGS_.CLEANSLATE;
		IF .FLAG THEN
			CALRESTORE(.TOP);
	END$;

!MACRO TO CASE THE STATEMENT AFTER THE ONE  POINTED TO BY LOCLNK TO BE LABELED
MACRO LABFRST=
	BEGIN
		MAP BASE LOCLNK;
		REGISTER BASE T;
		T_GENLAB();
		T[SNHDR]_.LOCLNK;
		LOCLNK[SRCLBL]_.T;
		T[SNREFNO]_2;
		.T
	END$;


!MACROS DEFINING THE BITS SET IN THE LEFT HAVE OF A GLOBREG WORLD
!THAT GOVERN SAVES, RESTORES, PRELOADS, MATERIALIZATIONS,
!AND INDICATE VARIOUS PROPERTIES OF THE VARIABLE.
MACRO
	AWL=12$,		!ALL 
	PRELOAD=2$,		!PRELOAD THIS ONE
	MATRLZ=1$,		!MATERIALIZE THIS ONE

!DECLARED IN OPTMAC
!	ALCFLG=32,4$,	!THE FIELD THAT CONTAINS AWL,PRELOAD OR MATRLZ
!	ALCFLGS=ALCFLG$,
	NOTFORML=31,1$,		!NOT A FORMAL VARIABLE
	PROGVAR=30,1$,		!A PROGRAM DEFINED VARIABLE
	NOPRELOAD=29,1$,	!DO NOT PRELOAD THIS ONE

!	FLAGS DEFINED IN TABLES BUT PART OF THIS WORD
!	ASGND4USED=27,1$,	!VARIABLE RECEIVES
				!A VALUE PRIOR TO ITS FIRST REFERENCE
				!IN THIS CONTEXT
!	USED4ASGND=28,1$,	!VARIABLE IS REFERENCED BEFORE
				!AN ASSIGNMENT IN THIS CONTEXT

	NEDSAV=18,1$;		!THIS NEEDS TO BE SAVED ANY WAY


!IN THE ELSE CONDITION, A REGCONTENTS NODE WAS
!SUBSTITUTED DURING COMPLEXITY AND WE MUST
!SET THE GLOBALLY ALLOCATED FLAG AND TAKE THE REGISTER
!FROM THE POOL.
!MACRO TO GET PLACE AT WHICH ALLOCATION IS TO START
MACRO LOWERBD(NOD)=
	(IF NOD[NEDSMATRLZ] OR NOD[MATRLZIXONLY]
	 OR NOD[DOIREG] LSS .MINWD THEN .MINWD
	ELSE
	BEGIN
		CLEANSLATE_CLRBIT(.CLEANSLATE,NOD[DOIREG]);
		IF .INDVAR[DBLFLG] THEN
			CLEANSLATE_CLRBIT(.CLEANSLATE,NOD[DOIREG]+1);
		NOD[DOIREG]+1+.INDVAR[DBLFLG]
	END)$;

!MACRO TO HELP LOOK AT THE FIRST CHARACTER OF A VARIABLE NAME
MACRO IDDOT=0,3,30,6$;


!MACRO TO DELETE INNERDO LOOP INDEX FROM LIST OF VARIABLE WITH
!MERIT IF IT WAS LOCALLY ALLOCATED.
!UPDATED IN EDIT 240 TO LOOK AT COMPLETE LIST
MACRO REMOVINDVAR=
	BEGIN
	IF NOT .TOP[NEDSMATRLZ] AND NOT .TOP[MATRLZIXONLY]  THEN
		DECR I FROM 31 TO 0 DO	%[240]%

			IF .CHOSEN[.I]<RIGHT> EQL .INDVAR THEN
			BEGIN
				CHOSEN[.I]_0;
				REGTOALC_.REGTOALC-1;
				IF .REGTOALC LEQ 0 THEN RETURN;
			END;
	END$;

!MACRO TO SWITCH AROUND TWO ENTRIES IN GLOBREG AND CHOSEN.  ALSO RESET
!NEDSMATRLZ ON PARAMETER LUP.
!TRADE GINX1 AND GINX2 ENTRIES OF GLOBREG AND CHOSEN

MACRO SWAPG(LUP,GINX1,GINX2)=
	BEGIN
		REGISTER T;
		LUP[NEDSMATRLZ]_0;
		LUP[MATRLZIXONLY]_0;
		T_.GLOBREG[GINX1]<0,36>;
		GLOBREG[GINX1]_.GLOBREG[GINX2]<0,36>;
		GLOBREG[GINX2]_.T<0,36>;
		GLOBREG[GINX2]<NOPRELOAD>_1;
		T_.CHOSEN[GINX1];
		CHOSEN[GINX1]_.CHOSEN[GINX2];
		CHOSEN[GINX2]_.T;
	END$;

ROUTINE PLUSUNFLDO(STMT)=
BEGIN
	!UNDO THE AOBJN LOOP ENDING.
	!USED WHEN WE ARE NOT 100% SURE THAT WE CAN DO AN AOBJN
	!SOME OF THESE CASES ARE:
	!	1.NEDSMATRLZ WAS SET BY P2S SO THE UNFLDO CONDITION
	!	  WAS NOT ALSO FOUND
	!	2.ITS THE OUTER LOOP OF TWO BEING ALLOCATED

	EXTERNAL UNFLDO;

	MAP BASE STMT;

	UNFLDO(.STMT);
	STMT[SSIZONE]_1;
	STMT[INITLIMMED]_1;
	STMT[SSIZIMMED]_1;
END;
ROUTINE ASCRIBE(P)=
BEGIN
	MAP PEXPRNODE P;
	!BY STATEMENT TALLY MERIT
	LOCAL I;

	!SET MERIT TO PLAINUSE FIRST. CHANGE WHEREVER NECESSARY

	RAISE_.MERITVAL[PLAINUSE];

	!IF COMPLEXITY HAS SAID THIS STATEMENT NEEDS PAIRS OF REGS
	!THEN SET GOTEMDBL FLAG SO WE WILL LEAVE TWO PAIRS

	IF .P[PAIRMODEFLG] THEN GOTEMDBL_1;

	!FIRST LOOK AT ANY LOCAL COMMON SUBS THAT MAY BE THERE
	IF .P[SRCOPT] NEQ 0 THEN
	BEGIN
		LOCAL BASE TMP;
		TMP_.P[SRCOPT];
		!LOOK AT THE LINKED LIST OF COMMON SUBS
		WHILE .TMP NEQ 0 DO
		BEGIN
			CREDIT(.TMP[ARG2PTR]);
			TMP_.TMP[SRCLINK];
		END;
	END;

	SELECT .P[SRCID] OF NSET
ASGNID:	BEGIN						!ASSIGNMENT STATEMENT
%[V5]%		PC _ .P [LHEXP];			!LOOK AT LHS
%[V5]%		IF .PC [OPRCLS] EQL DATAOPR		!IS IT A VARIABLE
%[V5]%		  THEN BEGIN
%[V5]%		    IF .P [MEMCMPFLG]
%[V5]%		      THEN RAISE _ .MERITVAL [ASGNMEM]
%[V5]%		      ELSE RAISE _ .MERITVAL [LHSUSE];
%[V5]%		    CREDIT(.PC);
%[V5]%		  END
%[V5]%		  ELSE BEGIN				!IT MUST BE AN ARRAYREF
%[V5]%		    RAYMERIT(.PC);
%[V5]%		  END;
		!NOW THE RIGHT HAND SIDE
		!GIVE MORE CREDIT IF IT IS THERE ALL BY ITSELF
		IF .P[A2VALFLG] THEN
			!MORE CREDIT AS THE LHS GETS.
			RAISE_.MERITVAL[LHSUSE]
		ELSE
			RAISE_.MERITVAL[PLAINUSE];
		CREDIT(.P[RHEXP]);
	END;						!ASSIGNMENT STATEMENT
CALLID:	BEGIN						!SUBROUTINE CALL
		IF .P[CALLIST] NEQ 0 THEN
			CALLREFNO_.CALLREFNO+1;			!TALLY NUMBER OF CALLS
	END;
IFAID:	BEGIN						!ARITHMETIC IF
		CREDIT(.P[AIFEXPR]);
	END;
IFLID:	BEGIN						!LOGICAL IF
		CREDIT(.P[LIFEXPR]);
		ASCRIBE(.P[LIFSTATE]);
	END;
OPENID:	!AN OPEN STATEMENT. TREAT LIKE A CALL
	BEGIN
		CALLREFNO_.CALLREFNO + 1;
		P[USRFNREF]_1;
	END;
ALWAYS:	BEGIN
	I_
	(IF .P[SRCCMPLX] GTR 9 THEN 9 ELSE .P[SRCCMPLX]);
	MAXCOMPLEX[.I]_.MAXCOMPLEX[.I]+1;
	END;
TESN;
END;							!ASCRIBE


ROUTINE ASSOCIA(VAR)=
BEGIN
	!CHECK THE LIST OF ASSOCIATE VARIABLES. DO NOT ALLOCATE
	!ANY OF THEM. RETURN 1 TO STOP ALLOCATION

	EXTERNAL ASSOCPTR;

	REGISTER BASE T;

	IF .ASSOCPTR EQL 0 THEN RETURN;

	T_.ASSOCPTR;
	WHILE .T NEQ 0 DO
	BEGIN
		IF .T[LEFTP] EQL .VAR THEN RETURN(1);
		T_.T[RIGHTP];
	END;
END;

ROUTINE CREDIT(CNODE)=
BEGIN
	!INCREMENT MERIT BY RAISE. WALK TREE THRU AUDITOR
	!CNODE POINTS TO AN EXPRESSION. RAISE IS GLOBAL TO CREDIT
	!AND IS SET BY AUDITOR
	EXTERNAL CSTMNT; MAP BASE CSTMNT;
	MAP PEXPRNODE CNODE;
	CASE .CNODE[OPRCLS] OF SET
	!BOOLEAN
	BEGIN
		CREDIT(.CNODE[ARG1PTR]);
		CREDIT(.CNODE[ARG2PTR]);
	END;
	!DATAOPR
	BEGIN
		IF .CNODE[OPERSP] EQL VARIABLE OR
		.CNODE[OPERSP] EQL FORMLARRAY OR
		.CNODE[OPERSP] EQL FORMLVAR THEN
		BEGIN
			!FOR THE INITIAL RELEASE GLOBALS WILL BE HANDLED
			!AS COMMON. SOPHISTACATION CAN COME LATER.
			IF .CNODE[IDATTRIBUT(INEQV)] THEN RETURN;
			IF .CNODE[IDATTRIBUT(INCOM)] THEN RETURN;
			IF .CNODE[IDATTRIBUT(INASSI)] THEN RETURN;
			IF .CNODE[IDATTRIBUT(INNAM)] THEN RETURN;
			IF .CNODE[IDATTRIBUT(FENTRYNAME)] THEN RETURN;
			CNODE[MERIT]_.CNODE[MERIT]+.RAISE;!UPDATE MERIT
			!FOR A VARIABLE THAT IS DOUBLE WORD
			!SET THE FLAG AND DIVIDE THE MERIT
			!JUST ADDED BY 2
			IF .CNODE[DBLFLG] THEN
			BEGIN
				CNODE[MERIT]_.CNODE[MERIT]-.RAISE/2;
				GOTEMDBL_1;
			END;
			IF .CNODE[MERIT] NEQ 0 THEN
				CHKMAXLST(.CNODE);
		END;
	END;
	!RELATIONAL
	BEGIN
		CREDIT(.CNODE[ARG1PTR]);
		CREDIT(.CNODE[ARG2PTR]);
	END;
	!FNCALL
		IF .CNODE[OPERSP] NEQ LIBARY THEN
		BEGIN
			CSTMNT[USRFNREF]_1;
			FNREFNO_.FNREFNO+1;
		END
		ELSE
		BEGIN
			!LIBRARY FUNCTION. SET BIT IN SYMBOL
			!TABLE THAT SAYS THIS IS USED
			!AS LIB FUNCTION ARG. SUBTRACT IT AT END
			!AS WITH FNREFNO.

			LOCAL ARGUMENTLIST ARGNOD,P;
			MAP BASE P;
			LIBFNREFNO_.LIBFNREFNO+1;
			ARGNOD_.CNODE[ARG2PTR];	!PTR TO LIST
			INCR I FROM 1 TO .ARGNOD[ARGCOUNT] DO
			BEGIN
				!PICK UP POINTER TO ACTUAL ARG
				P_.ARGNOD[.I,ARGNPTR];
				IF .P[OPR1] EQL VARFL THEN
					P[LIBARGUSE]_1
				ELSE
					!MAKE SURE THAT LIBARG REFS
					!ARE COUNTED FOR CALLS TO LIB
					!THAT ARE FUNCTIONS OF OTHER CALLS TO
					!TO THE LIBRARY
					IF .P[OPRCLS] EQL FNCALL THEN
						CREDIT(.P);
			END;
		END;
	!ARITHMETIC
	BEGIN
		CREDIT(.CNODE[ARG1PTR]);
		CREDIT(.CNODE[ARG2PTR]);
	END;
	!TYPECNV
	BEGIN
		CREDIT(.CNODE[ARG2PTR]);
	END;
	!ARRAYREF
		RAYMERIT(.CNODE);
	!CMNSUB		!ILLEGAL
	BEGIN
	END;
	!NEGNOT
		CREDIT(.CNODE[ARG2PTR]);
	!SPECOP
		CREDIT(.CNODE[ARG1PTR]);
	!FIELDREF	!RELEASE GTR 1
	BEGIN
	END;
	!STORCLS
	BEGIN
	END;
	!REGCONTENTS
	BEGIN END;
	!LABOP
	BEGIN
	END;
	!STATEMENT
	BEGIN END;
	!IOLSCLS
	BEGIN
	END;
	!INLINFN
	BEGIN END
	TES;
END;							!CREDIT

ROUTINE RAYMERIT(PC)=
BEGIN
	!COMPUTE ARRAYREF MERIT
	OWN BASE ARGNOD;
	MAP PEXPRNODE PC;

	!COMPUTE MERIT FOR AN ARRAY SUBSRCIPT.
	!FORMALS ARE NOT A SPECIAL CASE HERE AS
	!THEY HAVE THE PSEUDO CREATED NODE POINTED TO BY
	!THE ARADDRVAR FIELD OF THE SYMBOL TABLE. THIS PSEUDO
	!NODE IS IN THE TREE AND WILL GET MERIT.

	!TAKE CARE OF CONSTANT SUBSCRIPT (ARG2PTR = 0)
	IF .PC[ARG2PTR] EQL 0 THEN RETURN;

	ARGNOD_.PC[ARG2PTR];				!SUBSCRIPT
	!ONLY GIVE CREDIT FOR INDEX
	!IF ITS BY ITSELF
	IF .ARGNOD[OPRCLS] EQL DATAOPR THEN
	BEGIN
		RAISE_.MERITVAL[DEXUSE];
		CREDIT(.ARGNOD);
	END ELSE
	IF .ARGNOD[OPRCLS] EQL CMNSUB THEN
	BEGIN
		IF .ARGNOD[A2VALFLG] THEN
		BEGIN
			RAISE_.MERITVAL[DEXUSE];
			CREDIT(.ARGNOD[ARG2PTR]);
		END;
	END ELSE
	BEGIN						!JUST PLAIN USE
		RAISE_.MERITVAL[PLAINUSE];
		CREDIT(.ARGNOD);
	END;
	RAISE_.MERITVAL[PLAINUSE];
END;

FORWARD MINCOMPUTE;
ROUTINE CHKMAXLST(VAR)=
BEGIN
	!LOOK AT LIST OF VARIABLES WHICH ARE CURRENTLY OF GREATEST MERIT.
	!THE LIST IS IN CHOSEN
	!VAR IS THE VARIABLE WHOSE MERIT IS UNDER EXAMINATION
	!
	LOCAL I;
	MAP PEXPRNODE VAR;
	I_LOOKUP(.VAR<RIGHT>);
	IF .I LSS 32 THEN
	CHOSEN[.I]<LEFT>_.VAR[MERIT]
	ELSE
	BEGIN						!VARIABLE IS NOT ON LIST
		!IF LIST IS NOT YET FULL (HEAD HAS COUNT) ADD TO THE LIST
		IF .HEAD LEQ 31 THEN		!HEAD CONTAINS COUNT
			(
			CHOSEN[.HEAD]<LEFT>_.VAR[MERIT];
			CHOSEN[.HEAD]<RIGHT>_.VAR;
			HEAD_.HEAD+1;)
			ELSE
			!IF THIS ONE HAS GREATER MERIT THAN THE
			!CURRENT MINIMUM ON THE LIST THEN REPLACE THE
			!OLD MINIMUM WITH THIS ONE AND RECOMPUTE THE MINIMUM
			BEGIN
				IF .MINWD EQL 0 THEN MINCOMPUTE();
				IF .VAR[MERIT] GTR .MINWD<LEFT> THEN
				BEGIN
				CHOSEN[.MINWD<RIGHT>]<LEFT>_.VAR[MERIT];
				CHOSEN[.MINWD<RIGHT>]<RIGHT>_.VAR;
				MINCOMPUTE();
				END;	!MIN REPLACEMENT AND RECOMPUTE
			END;
	END;
END;							!CHKMAXLST
ROUTINE MINCOMPUTE=
BEGIN
				!RECOMPUTE THE MINIMUM OF THE LIST
				MINWD<LEFT>_#100000;
				DECR K FROM 31 TO 0 DO
				BEGIN
					IF .CHOSEN[.K]<LEFT> LSS .MINWD<LEFT> THEN
					(MINWD<LEFT>_.CHOSEN[.K]<LEFT>;
					MINWD<RIGHT>_.K;);
				END;
END;


!
!*************************************************
!
ROUTINE MELDPLEX=
BEGIN
	!MELD IN CONSIDERATION OF THE COMPLEXITY OF THE
	!EXPRESSIONS INVOLVED AND ADJUST REGTOALC APPROPRIATELY
	!
	!THIS IS STRICTLY A HEURISTIC:
		!THE COMPLEXITY DISTRIBUTION IS EXAMINED.
		!THE NUMBER OF REGISTERS AVAILABLE IS DECREASED BY 1
			!FOR EACH STATEMENT OF COMPLEXITY GREATER
			!THAN THE 4 STANDARD COMPUTATION REGISTERS.
		!REGAVAIL ORIGINALLY CONTAINED THE NUMBER OF REGISTERS
		!IT WAS INTENDED TO ALLOCATE GLOBALLY.
		!REGTOALC CONTAINS THE ACTUALL NUMBER WE WILL ALLOCATE.
	!
	!THIS ROUTINE WILL ALSO DETERMINE THE TRUE VALUE OF
	!REGTOALC, THE NUMBER OF REGISTERS THAT **WILL** BE
	!GLOBALLY ALLOCATED. CHOSEN IS EXAMINED TO DETERMINE
	!IF THERE ARE ANY ENTRIES AT ALL.

	LABEL LOP1;

	LOP1:
	DECR I FROM 9 TO 4 DO
		IF .MAXCOMPLEX[.I] NEQ 0 THEN
		BEGIN
			REGAVAIL_.REGAVAIL-.I;
			LEAVE LOP1;
		END;
	REGTOALC_.REGAVAIL;

	!COUNT NON-ZERO ENTRIES IN CHOSEN
	!USE REGAVAIL AS A TEMP

	REGAVAIL_0;
	DECR I FROM 31 TO 0 DO
		IF .CHOSEN[.I] NEQ 0 THEN
			REGAVAIL_.REGAVAIL+1;
	!NOW SEE IF THIS IS LESS THEN REGTOALC DETERMINED
	!FROM THE COMPLEXITIES

	IF .REGAVAIL LSS .REGTOALC THEN REGTOALC_.REGAVAIL;
END;

EXTERNAL CLEANUP;

ROUTINE GRABFNREF(EXPR)=
BEGIN

	!EXAMINE EXPR FOR A FUNCTION REFERENCE TO A USER
	!FUNCTION. IF ANY GLOBALLY ALLOCATED VARIABLES ARE
	!ARGUMENTS TO THE FUNCTION CHANGE THEIR SAVCODE
	!<ALCLFG> TO BE MATRLZ

	MAP BASE EXPR;

	CASE .EXPR[OPRCLS] OF SET

	!BOOLEAN
	BEGIN
		GRABFNREF(.EXPR[ARG1PTR]);
		GRABFNREF(.EXPR[ARG2PTR]);
	END;

	!DATAOPR
		RETURN;

	!RELATIONAL
	BEGIN
		GRABFNREF(.EXPR[ARG1PTR]);
		GRABFNREF(.EXPR[ARG2PTR]);
	END;

	!FNCALL
	BEGIN

		REGISTER ARGUMENTLIST AG;
		IF .EXPR[OPERSP] EQL LIBARY THEN
			RETURN;
		!HERE WE HAVE A GENUINE USER FUNCTION REFERENCE
		AG_.EXPR[ARG2PTR];
		DECR I FROM .REGTOALC-1 TO 0 DO
		BEGIN
			!FOR EACH GLOBALLY ALLOCATEREG
			INCR ARG FROM 1 TO .AG[ARGCOUNT] DO
			BEGIN
				!FOR EACH ARGUMENT
				IF .AG[.ARG,ARGNPTR] EQL
					.GLOBREG[.I]<RIGHT> THEN
					GLOBREG[.I]<ALCFLG>_MATRLZ;
			END;
		END;
	END;

	!ARITHMETIC
	BEGIN
		GRABFNREF(.EXPR[ARG1PTR]);
		GRABFNREF(.EXPR[ARG2PTR]);
	END;
	
	!TYPECNV
		GRABFNREF(.EXPR[ARG2PTR]);

	!ARRAYREF
	BEGIN
		IF .EXPR[ARG2PTR] NEQ 0 THEN
			GRABFNREF(.EXPR[ARG2PTR]);
	END;

	!CMNSUB
		GRABFNREF(.EXPR[ARG2PTR]);

	!NEGNOT
		GRABFNREF(.EXPR[ARG2PTR]);

	!SPECOP
		GRABFNREF(.EXPR[ARG1PTR]);

	!FIELDREF
		RETURN;
	
	!STORECLS
		GRABFNREF(.EXPR[ARG2PTR]);

	!REGCONTENTS
		RETURN;

	!LABOP
		RETURN;

	!STATEMENT
		RETURN;

	!IOLSCLS
		RETURN;

	!INLINFN
	BEGIN
		GRABFNREF(.EXPR[ARG1PTR]);
		IF .EXPR[ARG2PTR] NEQ 0 THEN
			GRABFNREF(.EXPR[ARG2PTR]);
	END

	TES;
END;

ROUTINE FLIPCODES=
BEGIN
	!STUPID BUT EASIER THAN LOTS MORE BUGS.
	!CODES WERE INITIALIZED TO AWL.
	!SOME MAY HAVE BEEN RESET TO MATRLZ BY GRABFNREF.
	!WE WILL BE SAVING AND RESTORING BASED ON AWL
	!SO MAKE THOSE THAT SAY AWL NOW SAY MATRLZ AND
	!VISA VERSA
	!ALSO SORT GLOBREG SO THAT ALL THAT ARE NOT BEING
	!SAVED ARE LEAFSUBSTITUTED.


	!A MACRO OR TWO FOR LEGIBILITY
	LABEL FIND,CHECK,COUNTEM;	![277]
	LOCAL COUNT;	![277]

!**[502] FLIPCODES @4384 SJW 25-OCT-76
![502] REGS THAT ARE SAVED ARE THOSE CONTAINING VARS WHICH ARE ACTUAL
![502]   ARGS TO FUNCTION
%[502]%	EXTERNAL  ITMCT;	!SET UP BY SORTNMAKE IN GBLALLOC
%[502]%				!  TO BE REGTOALC - 1
%[502]%	MACRO SAVED(INX)=
%**;[316],PH3G,JNT,08-AUG-75%
%**;[316],IN FLIPCODES @ 4316%
		.GLOBREG[.INX]<ALCFLG> EQL AWL$;	![316]

	MACRO SWAAP(INX1,INX2)=
	BEGIN
		REGISTER T;
		T_.GLOBREG[.INX1]<0,36>;
		GLOBREG[.INX1]<0,36>_.GLOBREG[.INX2]<0,36>;
		GLOBREG[.INX2]<0,36>_.T<0,36>;
		T_.CHOSEN[.INX1];
		CHOSEN[.INX1]_.CHOSEN[.INX2];
		CHOSEN[.INX2]_.T;
	END$;

	DECR I FROM .REGTOALC-1 TO 0 DO
		IF .GLOBREG[.I]<ALCFLG> EQL AWL THEN
			GLOBREG[.I]<ALCFLG>_MATRLZ
		ELSE
			GLOBREG[.I]<ALCFLG>_AWL;

![502][277] SORT GLOBREG SO THAT THOSE THAT ARE NOT SAVED ARE LEAFSUBSTITUTED
![502][316][277] CALL LEAFLOOKER LOOKING ONLY AT THOSE NOT TO BE SAVED

	CHECK:	![277]
	DECR I FROM .REGTOALC-1 TO 0 DO	![277]
	BEGIN	![277]
%[502]%		IF NOT SAVED (I) THEN	![316][277]
		FIND:	![277]
		BEGIN	![277]
			INCR J FROM 0 TO .I DO	![277]
			BEGIN	![277]
%[502]%				IF SAVED (J) THEN	![316][277]
				BEGIN	![277]
					SWAAP(I,J);	![277] SORT ITEMS
					LEAVE FIND;	![277] LEAVE INNER LOOP
				END;	![277]
			END;	![277]
			LEAVE CHECK;	![277] FINISHED SORT IF NONE FOUND
		END;	![277]
	END;	![277] HAVE THEM SORTED

%[502]%	COUNT _ 0;
COUNTEM:	![502][277] COUNT THE NUMBER NOT SAVED FOR CALL TO LEAFLOOKER
	DECR I FROM .REGTOALC-1 TO 0 DO	![277]
%[502]%	IF NOT SAVED (I) THEN	![316][277] BY SCANNING BACK OVER
	BEGIN			![502][277] THOSE TO BE SAVED
%[502]%		COUNT _ .I + 1;	![277] I AT FIRST ONE NOT SAVED: COUNT MUST BE 1-RELATIVE

		LEAVE COUNTEM;	![277]
	END;	![277]

	IF .COUNT NEQ 0 THEN	![502][277] IF SOME NOT SAVED THEN
	BEGIN	![277]
		LOCAL SAVE;	![277]
		SAVE_.REGTOALC;	![277] SAVE REAL VALUE
		REGTOALC_.COUNT;	![277] FAKE OUT LEAFLOOKER WITH OUR COUNT
%[502]%		ITMCT _ .REGTOALC - 1;	!FAKE OUT LEAFSUBSTITUTE'S CALLEES
		LEAFLOOKER(.STARTSUB);	![277] SUBSTITUTE
		REGTOALC_.SAVE;	![277]
%[502]%		ITMCT _ .REGTOALC - 1;	!RESTORE OLD ITMCT
	END;	![277]

END;
ROUTINE REGSUBDRIVER=
BEGIN
	!DRIVER ROUITNE FOR SUBSTITUTION OF REGCONTENTS NODES.
	!THE SCOPE OF THE SUBSTITUTION STARTS AT STARTSUB AND ENDS AT
	!STOPSUB.

	EXTERNAL CSTMNT,LENTRY;
	LABEL LUP;
	OWN BASE SAVHITCH;
	MAP BASE STARTSUB:STOPSUB;

	!RESET THE FLAG TO INDICATE NO SAVING SEQUENCE DONE
	SAVEDFLG_0;

	!**;[353] PH3G @4408, DCE, 17-FEB-76
	CALLSEEN_0; ![353] INITIALIZE CALLSEEN (NONE YET SEEN)
	!LEAFSUBSTITUTE NEEDS CSTMNT SO WE WILL SAVE THE CURRENT
	!VALUE AND PUT IT BACK WHEN WE ARE DONE HERE

	!MAKE SURE ALL CODES ARE AWL
	DECR I FROM .REGTOALC-1 TO 0 DO
		GLOBREG[.I]<ALCFLG>_AWL;

	SAVCODE_AWL;
	FRSTBB_1;		!SET FIRST BASIC BLOCK FLAG

	!SKIP ANY CALLS THAT ARE AT THE TOP
	WHILE (.STARTSUB[SRCID] EQL CALLID) OR .STARTSUB[USRFNREF]  DO
		STARTSUB_.STARTSUB[SRCLINK];


	!SET FLAG TO INDICATE WE ARE OUTSIDE THE LOOP
	!AND DO NOT WHICH TO SUBSTITUTE INTO STATEMENT
	!WITH RHEXP=REGCONTENTS

	NOINDVARFLG_1;

	!SET FLAG IF THIS IS DOUBLE NEST
	ASGN4LENTRY_(.GUIDE EQL 6);

	OLDCSTMNT_.CSTMNT;
	THISTAT_LASTAT_.STARTSUB;
	WHILE .STARTSUB NEQ .STOPSUB[SRCLINK] DO
	BEGIN
		!RESET NOINDVARFLG IF THIS IS "THE" LOOP WE ARE ALLOCATING
		IF .STARTSUB EQL .TOP THEN
		BEGIN
			 NOINDVARFLG_0;
			!IF ALLOCATING ONLY THE INNER LOOP OF A
			!NEST MARK ITEMS THAT WERE ASSIGNED
			!OUTSIDE THE LOOP AS NEEDING TO
			!TO BE SAVED.

			IF .GUIDE EQL 5 THEN
			BEGIN
				DECR I FROM .REGTOALC-1 TO 0 DO
					IF .GLOBREG[.I]<ASGND4USED> THEN
							GLOBREG[.I]<NEDSAV>_1;
			END;

		END;

!**;[431] Insert @ 4455 in REGSUBDRIVER	JNG	21-Aug-76
%[431]%		!IF A DOUBLE NEST AND WE HAVE REACHED THE OUTER LOOP
%[431]%		!THEN WE MUST MARK ALL VARIABLES THAT WERE ALLOCATED TO
%[431]%		!REGISTERS AND WERE ASSIGNED INTO IN THE BASIC BLOCK
%[431]%		!PRECEDING THE OUTER LOOP AS NEEDING MATERIALIZATION
%[431]%		!UNCONDITIONALLY. THIS IS BECAUSE DEFINITION POINT
%[431]%		!ANALYSIS DID NOT MARK THESE VARIABLES AS BEING MODIFIED
%[431]%		!INSIDE THE OUTER LOOP, AND SINCE WE HAVE SUBSTITUTED
%[431]%		!A REGCONTENTS NODE FOR THE ORIGINAL ASSIGNMENT TO
%[431]%		!MEMORY, THE VARIABLE WILL NEVER END UP IN MEMORY
%[431]%		!UNLESS WE EXPLICITLY MATERIALIZE IT.
%[431]%
%[431]%		IF .GUIDE EQL 6 AND .STARTSUB EQL .OLDCSTMNT
%[431]%		THEN
%[431]%		BEGIN
%[431]%			DECR I FROM .REGTOALC-1 TO 0 DO
%[431]%				IF .GLOBREG[.I]<ASGND4USED> THEN
%[431]%					GLOBREG[.I]<NEDSAV>_1;
%[431]%		END;

		!IF A DOUBLE NEST AND WE ARE OUTSIDE THE MOTION PLACE
		!OF UNSUBSUMED ITEMS IN THE OUTER LOOP MARK
		!ANY .O AS NEEDING SAVING

		IF .ASGN4LENTRY THEN
		BEGIN
			!IF THIS IS LENTRY QUIT
			IF .STARTSUB EQL .LENTRY THEN
				ASGN4LENTRY_0
			ELSE
			BEGIN
				IF .STARTSUB[OPRS] EQL ASGNOS THEN
				BEGIN
					IF .STARTSUB[A1VALFLG] THEN
					BEGIN
						T_.STARTSUB[LHEXP];
						IF .T[IDDOTO] EQL
						SIXBIT".O" THEN
						BEGIN
							DECR I FROM .REGTOALC-1 TO 0 DO
							IF .GLOBREG[.I]<RIGHT> EQL .T THEN
								GLOBREG[.I]<NEDSAV>_1;
						END;
					END;
				END;
			END;
		END;

		!SAV WHERE WE START
		CSTMNT_.STARTSUB;
		SAVHITCH_.STARTSUB[SRCLINK];
		!SUBSTITUT IF THERE ARE NO USER FUNCTION REFS
	!**;[353], PH3G @4487, DCE, 17-FEB-76
	!**;[353], IF MORE THAN TWO CALLS OCCUR IN A ROW, WE WANT
	!**;[353], TO ALLOW REGCONTENTS SUBSTITUTION ON THE FIRST CALL, 
	!**;[353], NONE FOR ALL THE FOLLOWING CALLS (OR THE LIKE), AND THEN
	!**;[353], A RESTORE OF THE REGISTERS PRIOR TO CONTINUING.  THE
	!**;[353], VARIABLE CALLSEEN (SET IN LEAFLOOKER) INDICATES WE ARE
	!**;[353], IN SUCH A SITUATION, HAVING SUBSTITUTED IN THE FIRST
	!**;[353], CALL ALREADY.
%[353]%		IF .CALLSEEN NEQ 0 THEN
%[353]%		BEGIN
%[353]%			CALLSEEN_0;
%[353]%			T_.STARTSUB[SRCLINK];
%[353]%			WHILE .T[USRFNREF] OR (.T[SRCID] EQL CALLID) DO
%[353]%			BEGIN
%[353]%					THISTAT_.T;
%[353]%					T_.T[SRCLINK];
%[353]%					END;
%[353]%			SAVHITCH_.T;
%[353]%			CALRESTORE(.THISTAT); !RESTORE REGISTERS FINALLY
%[353]%			SAVEDFLG_0;
	!**;[353] REINITIALIZE SAVE CODES AFTER RESTORATION
%[353]%			DECR I FROM .REGTOALC-1 TO 0 DO
%[353]%				GLOBREG[.I]<ALCFLG>_AWL;
%[353]%		END  ELSE
		IF NOT .STARTSUB[USRFNREF] THEN
			LEAFLOOKER(.STARTSUB)
		ELSE
		BEGIN
			!TURN ON ALL USED4ASGND BITS. THIS MAY
			!BE NON-OPTIMAL BUT THERE IS NO CONVENIENT,
			!SHORT WAY TO EXAMINE THE EXPRESSIONS AND
			!SET THE BIT ONLY IF WE WANT TO. THOSE
			!NOT ALREADY ASGND4USED WILL, THEREFORE,
			!GET PRELOADED BY GETPRELOAD.

			DECR I FROM .REGTOALC-1 TO 0 DO
				IF NOT .GLOBREG[.I]<ASGND4USED> THEN
					GLOBREG[.I]<USED4ASGND>_1;

			!SET FLAG TO INDICATE THAT THERE ARE
			!SEVERAL IN A ROW

			T_.STARTSUB[SRCLINK];
			FLAG_.T[USRFNREF] OR (.T[SRCID] EQL CALLID);
			!SPECIAL CASE AN ASSIGNMENT WITH USRFNREF SET
			!TO SAVE AND RESTORE ONLY THOSE THAT ARE
			!ARGUMENTS

			IF .STARTSUB[SRCID] EQL ASGNID THEN
			BEGIN
				!IF NEXT STATEMENT DOES NOT ALSO
				!HAVE ONE OR IS NOT A CALL
				!OR ANY PREVIOUS STATEMENT DID NOT
				!CAUSE A STORE ALREADY
				IF NOT .FLAG AND NOT .SAVEDFLG THEN
				BEGIN
					GRABFNREF(.STARTSUB[LHEXP]);
					GRABFNREF(.STARTSUB[RHEXP]);
					FLIPCODES();
				END;
			END;

			!SAVE AND RESTORE AROUND STATEMENT
			!SET SAVE CODE
			SAVCODE_AWL;
			!IF ALL VARIABLES WERE NOT ALREADY MATERIALIZED
			!DO IT NOW.
			IF NOT .SAVEDFLG THEN
			BEGIN
				CALLSAVE(.LASTAT);
				SAVEDFLG_1;
			END;

			!IF ITS AN ASSIGNMENT STATEMENT AND THE LEFT HAND
			!SIDE SHOULD BE A REG THAN MAKE IT A REG AND DONT DO THE RESTORE
			IF (.STARTSUB[SRCID] EQL ASGNID) AND NOT .FLAG THEN
			BEGIN
				LUP:
				DECR I FROM .REGTOALC-1 TO 0 DO
					IF .GLOBREG[.I]<RIGHT> EQL
					   .STARTSUB[LHEXP] THEN
					BEGIN
						!DO THE SUBSTITUTION FOR THE
						!SINGLE REFERENCE
						STARTSUB[LHEXP]_
						.CHOSEN[.I];
						!SET THE FIELD SO RESTORE
						!WILL NOT HAPPEN
						GLOBREG[.I]<ALCFLG>_PRELOAD;
						LEAVE LUP;
					END;
			END;		!ITS AN ASSIGNMENT

			!SKIP TO THE PROPER PLACE TO RESTORE
			IF .FLAG THEN
			BEGIN
				WHILE .T[USRFNREF] OR (.T[SRCID] EQL CALLID) DO
				BEGIN
					THISTAT_.T;
					T_.T[SRCLINK];
				END;
				SAVHITCH_.T;
			END;

			!HAVE NOW SKIPPED ALL OR NONE. DO RESTORE
			CALRESTORE(.THISTAT);
			SAVEDFLG_0;


			!REINITIALIZE SAV CODES

			DECR I FROM .REGTOALC-1 TO 0 DO
				GLOBREG[.I]<ALCFLG>_AWL;

		END;		!USER FUNCTION CASE
		!SKIP OVER POTENTIAL RESTORE STATEMENTS INSERTED
		UNTIL .STARTSUB[SRCLINK] EQL .SAVHITCH DO
		BEGIN
			STARTSUB_.STARTSUB[SRCLINK];
				!THE FLAG SHOULD BE RESET ONLY IF WE
				!HAVE GENERATED THE RESTORES
				SAVEDFLG_0;
		END;

		LASTAT_.STARTSUB;
		THISTAT_STARTSUB_.STARTSUB[SRCLINK];
	END;	!WHILE
	CSTMNT_.OLDCSTMNT;
END;	!REGSUBDRIVER

FORWARD STOWONRETURN;
ROUTINE FIXENTRY=
BEGIN
	LOCAL T;
	MAP BASE TOP:T;
	OWN ARGUMENTLIST NEWLIST;
	!FOR EACH ENTRY:
	!	FIX THE PROLOGUE
	!	INSERT PRELOADS
	!	INSERT MATERIALIZATIONS

	!*********************
	!MACRO TO SET UP ENTRY LIST INFORMATION
	MACRO SETENTRY=
	BEGIN
		REGISTER BASE REG;
		!LOOK AT THE REGCONTENTS NODE
		!AND PUT THE REGISTER INTO
		!THE ENTAC OF THE ENTRY
		!LIST
		REG_.CHOSEN[.I];
		NEWLIST[.K,ENTAC]_.REG[TARGTAC];
		NEWLIST[.K,ENTGALLOCFLG]_1;
		!SET A FLAG TO HELP LATTER
		GLOBREG[.I]<NOPRELOAD>_1;
	END$;

	T_.TOP;
	WHILE .T NEQ 0 DO
	BEGIN
		IF .T[SRCID] EQL ENTRID THEN
		BEGIN

		!REINITIALIZE FLAGS AND FIELDS IN GLOBREG TO
		!PROPERLY HANDLE MULTIPLE ENTRIES

		DECR I FROM .REGTOALC-1 TO 0 DO
		BEGIN
			GLOBREG[.I]<NOPRELOAD>_0;
			GLOBREG[.I]<ALCFLG>_AWL;
			!IF THIS IS A SECONDARY ENTRY RESET ASGND4USED
			!AND SET USED4ASGND
			IF .T[ENTNUM] NEQ 0 THEN
			BEGIN
				GLOBREG[.I]<ASGND4USED>_0;
				GLOBREG[.I]<USED4ASGND>_1;
			END;
		END;

		!CHECK FOR NO PARAMETERS
		IF .T[ENTLIST] NEQ 0 THEN
		BEGIN
			NEWLIST_.T[ENTLIST];
			!FOR EACH ALLOCATED REGISTER LOOK AT THE
			!PARAMETERS
			DECR I FROM .REGTOALC-1 TO 0 DO
			BEGIN
				INCR K FROM 1 TO .NEWLIST[ARGCOUNT] DO
				BEGIN
					!IF A PARAMETER MATCHES AN
					!ALLOCATED VARIABLE
					IF .NEWLIST[.K,ARGNPTR] EQL
					   .GLOBREG[.I]<RIGHT> THEN
					BEGIN
						SETENTRY;
					END ELSE
					BEGIN
						!IF ITS A FORMAL ARRAY
						!WE HAVE TO COMPARE THE
						!KLUDGED ENTRY POINTED TO BY
						!THE DIMENSION TABLE
						REGISTER BASE TMP;
						TMP_.GLOBREG[.I]<RIGHT>;
						IF.TMP[OPERSP] EQL FORMLARRAY THEN
						BEGIN
							TMP_.TMP[IDDIM];
							IF NOT .TMP[ADJDIMFLG] THEN
							IF .TMP[ARADDRVAR] EQL .GLOBREG[.I]<RIGHT> THEN
							SETENTRY;
						END;
					END;
				END;
			END;


		END;		!PARAMETERS

		!PROLOGUE IS FIXED. DO PRELOADS
		FLAG_0;		!USE TO SAY IF THERE ARE SOME
		DECR I FROM .REGTOALC-1 TO 0 DO
		BEGIN
			!CHECK ASGND4USED AND SET NOPRELOAD

			IF .GLOBREG[.I]<ASGND4USED> THEN
				GLOBREG[.I]<NOPRELOAD>_1;
		END;

		DECR I FROM .REGTOALC-1 TO 0 DO
		BEGIN
			IF NOT .GLOBREG[.I]<NOPRELOAD>
			THEN
			BEGIN
				GLOBREG[.I]<ALCFLG>_PRELOAD;
				FLAG_1;
			END;
		END;

		SAVCODE_PRELOAD;
		IF .FLAG THEN
			CALRESTORE(.T);
		END;		!AN ENTRY STATEMENT

		T_.T[SRCLINK];	!MOVE ON TO NEXT ONE
	END;		!WHILE ON T

	!NOW DO MATERIALIZATIONS
	!USE FLAG TO INDICATE PRESENCE AGAIN
	FLAG_0;
	DECR I FROM .REGTOALC-1 TO 0 DO
	BEGIN
		!IF THERE ARE MULTIPLE ENTRIES WE HAVE TO
		!SAVE THE OPTIMIZER VARIABLES TOO. OTHERWISE
		!WE DO NOT

		IF .FLGREG<MULTENT> THEN
		BEGIN
			IF .GLOBREG[.I]<PROGVAR> THEN
			BEGIN
				FLAG_1;
				GLOBREG[.I]<ALCFLG>_MATRLZ;
			END;
		END ELSE
		BEGIN
			IF .GLOBREG[.I]<NOTFORML> AND
			.GLOBREG[.I]<PROGVAR> THEN
			BEGIN
				GLOBREG[.I]<ALCFLG>_MATRLZ;
				FLAG_1;
			END;
		END;
	END;
	SAVCODE_MATRLZ;
	IF .FLAG THEN
		STOWONRETURN();
END;	!FIXENTRY

ROUTINE MAKREGMASK=
BEGIN
	!CONSTRUCT AND RETURN A POINTER TO A REGMASK NODE
	REGISTER BASE T;
	EXTERNAL CORMAN;
	NAME<LEFT>_SRCSIZ;
	T_CORMAN();
	T[OPRCLS]_STATEMENT;
	T[SRCID]_REGMASK;
	.T
END;
ROUTINE SKIPMATERIALIZATION(STNODE)=
BEGIN
	!SKIP OVER MATERIALIZATION NODES INSERTED BY THE GLOBAL
	!ALLOCATOR. CALLED BY GETPRELOAD TO PREVENT PRELOADS
	!FROM BEING INSERTED IN FRONT OF MATERIALIZATIONS FROM
	!A PREVIOUS (CONTIGUOUS) GLOBALLY ALLOCATED LOOP.

	MAP BASE STNODE;
	REGISTER BASE RHNODE:TMP;

	!MAY ALSO NEED TO SKIP A REGMASK NODE
	TMP_.STNODE;
	IF .STNODE[SRCID] EQL REGMASK THEN
	BEGIN
		STNODE_.STNODE[SRCLINK];
	END;

	WHILE .STNODE[SRCID] EQL ASGNID AND .STNODE[SRCISN] EQL 0 DO
	BEGIN
		IF .STNODE[A1VALFLG] AND .STNODE[A2VALFLG] THEN
		BEGIN

			RHNODE_.STNODE[RHEXP];
			IF .RHNODE[OPRCLS] EQL REGCONTENTS THEN
			BEGIN
				TMP_.STNODE;
				STNODE_.STNODE[SRCLINK]
			END
			ELSE
				RETURN(.TMP);
		END ELSE
		RETURN(.TMP);
	END;
	.TMP
END;

ROUTINE GETPRELOAD=
BEGIN
	!FOR CASES 5 AND 6 DETERMINE WHICH VARIABLES NEED
	!PRELOADING AND FIND THE SPOT TO INSERT THE PRELOADS
	!CAUSE THE PRELOADS TO HAPPEN

	EXTERNAL BOTTOM;
	MAP BASE T:BOTTOM:PREVBB;
	EXTERNAL INDVAR,LOCLNK,GBSYREGS;
	MAP BASE LOCLNK;
	REGISTER BASE PRELLOC;		!PRELOAD LOCATION


	!**************************
	!USEFUL MACRO
	!**************************
	!
	!INSERT REGMASKNODE AT PRELLOC

	MACRO INSERTMASK=
	BEGIN
		T_MAKREGMASK();
		T[NEWREGSET]_.GBSYREGS<LEFT>;
		T[SRCLINK]_.PRELLOC[SRCLINK];
		PRELLOC[SRCLINK]_.T;
		PRELLOC_.T;
	END$;

	!***************************

	!FIRST DETERMINE WHO NEEDS PRELOADING

	!A VARIABLE DOES NOT NEED TO BE PRELOADED IF:
	!	IT IS ASSIGNED BEFORE ITS INITIAL USE 
	!	DURING REGCONTENTS SUBSTITUTION THIS
	!	INFO HAS BEEN COLLECTEDAND LEFT IT BITS IN
	!	GLOBREG.

	T_.PREVBB;
	!IF THIS JUST RANDOMLY HAPPENS TO BE AN ENTRY
	!MOVE T UP BY 1 STATEMENT
	IF .T[SRCID] EQL ENTRID THEN T_.T[SRCLINK];

	!USE FLAG TO TELL WHETHER OR NOT ANY PRELOADS ARE NECESSARY
	FLAG_0;
	!NOW SET FUNCTION INDICATORS
	DECR I FROM .REGTOALC-1 TO 0 DO
		!FIRST A PASS TO CHECK USED4ASGND AND SET NO PRELOAD
		IF .GLOBREG[.I]<ASGND4USED> THEN 
			GLOBREG[.I]<NOPRELOAD>_1
		ELSE
			GLOBREG[.I]<NOPRELOAD>_0;

	DECR I FROM .REGTOALC-1 TO 0 DO
		IF NOT .GLOBREG[.I]<NOPRELOAD> THEN
		BEGIN
			GLOBREG[.I]<ALCFLG>_PRELOAD;
			FLAG_1;
		END;

	!MAKE THE PROPER REGMASK NODE AND 
	!STICK IT IN FRONT

	!IF PREVBB IS A CONTINUE
	!THEN WE CAN STICK THEM AT PREVBB WITH NO HARM
	!UNLESS THERE IS A REGMASK IMMEDIATELY FOLLOWING
	!(E.G. TWO CONTIGUOUS LOOPS) IN WHICH CASE JUST
	!CHANGE THE REGMASK PATTERN
	T_.PREVBB[SRCLINK];
	IF .T[SRCID] EQL REGMASK THEN PREVBB_.T;

	IF .PREVBB[SRCID] EQL CONTID THEN
	BEGIN
		!IF DO LOOPS END HERE OR NOT WE WILL DO THIS
		!SET PRELOAD LOCATION AND
		!TRANSFORM THIS INTO A REGMASK NODE
		IF .PREVBB[SRCLBL] EQL 0 THEN
		BEGIN
			PRELLOC_.PREVBB;
			PREVBB[SRCID]_REGMASK;
			PREVBB[NEWREGSET]_.GBSYREGS<LEFT>;
		END ELSE
		BEGIN
			!LABELED CONTINUE. MAKE A SEPARATE
			!REGMASK NODE AND PUT IT AFTER THE
			!CONTINUE
			PRELLOC_MAKREGMASK();
			PRELLOC[SRCLINK]_.PREVBB[SRCLINK];
			PREVBB[SRCLINK]_.PRELLOC;
			PRELLOC[NEWREGSET]_.GBSYREGS<LEFT>;
!**;[454] Replace @ line 4876 in GETPRELOAD	JNG	18-Sep-76
%[454]%		END;
%[454]%		!UPDATE PRELLOC SO PRELOADS WILL GO
%[454]%		!AFTER MATERIALIZATIONS (IF ANY).
%[454]%		PRELLOC_SKIPMATERIALIZATION(.PRELLOC);
	END ELSE
	IF .PREVBB[SRCID] EQL REGMASK THEN
	BEGIN
		![266] SET REGMASK
		PREVBB[NEWREGSET]_.GBSYREGS<LEFT>;	![266]

		![266]IF THERE ARE PREVIOUSLY INSERTED MATERIALIZATIONS
		![266] THEN SET THE PLACE FOR INSERTION OF PRELOADS
		![266] AFTER THE MATERIALIZATIONS.  IF THERE ARE
		![266] NO MATERIALIZATIONS TO SKIP, PUT THE PRELOADS
		![266] DIRECTLY AFTER THE REGMASK.
		!**;[352], PH3G @4898, DCE, 16-FEB-76
		!**;[352], FIX THIS TO WORK WITH ONLY ONE TO SKIP
		!**;[352], IT WORKED FOR ALL OTHER CASES PREVIOUSLY.
	%[352]%	PRELLOC_SKIPMATERIALIZATION(.PREVBB);
	END
	ELSE
	!IF IT IS A DO LOOP. PUT THE PRELOADS HERE AND CHECK 
	!FOR THE DO INDEX BEING GLOBALLY ALLOCATED
	IF .PREVBB[SRCID] EQL DOID THEN
	BEGIN
		PRELLOC_.PREVBB;
		DECR I FROM .REGTOALC-1 TO 0 DO
			IF .GLOBREG[.I]<RIGHT> EQL .PREVBB[DOSYM] THEN
			BEGIN
				T_.CHOSEN[.I];
				PREVBB[DOIREG]_.T[TARGTAC];
				!INSURE NO PRELOAD
				GLOBREG[.I]<ALCFLG>_AWL;
			END;
		INSERTMASK;
	END
	ELSE
	!IF ITS A CALL DONT GO ANY FURTHER EITHER
	IF (.PREVBB[SRCID] EQL CALLID) OR .PREVBB[USRFNREF]  THEN
	BEGIN
		PRELLOC_.PREVBB;

		!SKIP OVER CALLS IN A SEQUENCE
		!OR STATEMENTS WITH USER FUNCTION REFERENCES.
		!THESE WERE SKIPPED IN RECONTENTS SUBSTITUTION TOO.

		WHILE (.PRELLOC[SRCID] EQL CALLID) OR .PRELLOC[USRFNREF] DO
		BEGIN
			PREVBB_.PRELLOC;
			PRELLOC_.PRELLOC[SRCLINK];
		END;
		PRELLOC_.PREVBB;


		INSERTMASK;
	END ELSE

	!IF ITS A LOGICAL IF WITH A BRANCHING STATMENT AS THE
	!TRUE BRANCH, THEN MAKE IT BE THE PRELOAD LOCATION

	IF (.PREVBB[SRCID] EQL IFLID) AND .PREVBB[TRUEISBR] THEN
	BEGIN
		PRELLOC_.PREVBB;
		INSERTMASK;
	END
	ELSE
	BEGIN
		!LOOK FOR THE STATEMENT INFRONT OF PREVBB
		!MAKE A REGMASK NODE, STICK IT IN AND
		!SET PRELLOC TO IT
		!START LOOKING FOR THE STATEMENT IN FRONT OF PREVBB AT
		!WAYBBB
		PRELLOC_.WAYBBB;
		!DO NOT ADJUST IF WAYBBB AND PREVBB ARE THE
		!SAME. IN THIS CASE THEY ARE THE START OF THE PROGRAM
		IF .WAYBBB EQL .PREVBB THEN
		ELSE
		WHILE .PRELLOC[SRCLINK] NEQ .PREVBB DO
			PRELLOC_.PRELLOC[SRCLINK];

		!ALSO GET RID OF STICKING IT IN FRONT OF THE ENTRY
		WHILE .PRELLOC[SRCID] EQL ENTRID DO
			PRELLOC_.PRELLOC[SRCLINK];
		!ALSO CHECK IF PREVBB IS AN ENTRY
		IF .PREVBB[SRCID] EQL ENTRID THEN
			PRELLOC_.PREVBB;
		!ALSO CHECK FOR A DO LOOP AND SET THE DO REGISTER
		!TO USE THE GLOBAL REGISTER IF IT IS ALLOCATED
		IF .PRELLOC[SRCID] EQL DOID THEN
		BEGIN
			DECR I FROM .REGTOALC-1 TO 0 DO
				IF .GLOBREG[.I]<RIGHT> EQL .PRELLOC[DOSYM] THEN
				BEGIN
					T_.CHOSEN[.I];
					PRELLOC[DOIREG]_.T[TARGTAC];
					!DONT PRELOAD IT
					GLOBREG[.I]<ALCFLG>_AWL;
				END;
		END;

		!NOW MAKE THE REGMASK NODE
		INSERTMASK;

		IF .PREVBB[SRCLBL] NEQ 0 THEN
!**;[615], GETPRELOAD @5088, DCE, 19-SEP-77
!**;[615], WE MUST BE MORE CAREFUL HERE IN CASE THE PRELOAD HAS BEEN
!**;[615], DONE AFTER THE STATEMENT AT PREVBB.  THIS MAY BE THE
!**;[615], CASE IF THE PREVIOUS BASIC BLOCK BEGINS THE SUBROUTINE,
!**;[615], AND IS LABELED.  IN THIS CASE, THE DANGER IS THAT THE LABEL
!**;[615], WOULD BE MOVED DOWN IN THE CODE TO THE PRELOAD LOCATION WHICH
!**;[615], IS NOT THE INTENT!
%[615]%		IF .PREVBB[SRCLINK] NEQ .PRELLOC THEN
		BEGIN
			!IF PREVBB WAS LABELED MOVE THE LABEL TO
			!THE NEW NODE JUST MADE
			PRELLOC[SRCLBL]_T_.PREVBB[SRCLBL];
			T[SNHDR]_.PRELLOC;
			PREVBB[SRCLBL]_0;
		END;
	END;
	SAVCODE_PRELOAD;
	!DO ACTUAL PRELOADS ONLY IF FLAG IS SET
	IF .FLAG THEN
		CALRESTORE(.PRELLOC);
	!ONE MORE THING. IF ALLOCATING A LOOP NEST
	!WE MUST INSERT A REGMASK NODE AT THE END OF
	!THE INNER LOOP TO PREVENT THE LOCAL ALLOCATOR
	!FROM ACCIDENTLY RELEASING THE INNER LOOPS INDEX REG
	IF .GUIDE EQL 6 THEN
	BEGIN
		T_MAKREGMASK();
		T[NEWREGSET]_.GBSYREGS<LEFT>;
		!LINK IT IN AT BOTTOM
		T[SRCLINK]_.BOTTOM[SRCLINK];
		BOTTOM[SRCLINK]_.T;
	END;
END;

ROUTINE GETMATERIAL=
BEGIN
	!IN CASES 5 AND 6  SET CODES FOR MATERIALIZATION
	!AND CAUSE THEM TO HAPPEN

	EXTERNAL BASE CSTMNT;

	LABEL L1;


	!USE FLAG TO DETERMINE IF THERE ARE ANY
	FLAG_0;
	DECR I FROM .REGTOALC-1 TO 0 DO
	BEGIN
		IF .GLOBREG[.I]<ALCFLG> EQL PRELOAD THEN
		BEGIN
			!SAVE ANY THAT WERE PRELOADED
			GLOBREG[.I]<ALCFLG>_MATRLZ;
			FLAG_1;
		END ELSE
		BEGIN
			T_.CSTMNT[DOLBL];
			!GET THE LIST OF VARIABLES CHANGED IN THIS
			!LOOP FROM THE LABEL TABLE OF THE TERMINATING
			!LABEL
			T_.T[SNSTATUS];
			L1:
			!NOW WALK THE LINKED LIST AND SAVE ALL CHANGED
			WHILE .T NEQ 0 DO
			BEGIN
				IF .GLOBREG[.I]<RIGHT> EQL .T[LEFTP] THEN
				IF .GLOBREG[.I]<PROGVAR> THEN
				BEGIN
					GLOBREG[.I]<ALCFLG>_MATRLZ;
					FLAG_1;
					LEAVE L1;
				END;
				T_.T[RIGHTP];
			END;

			!IF THIS IS AN INNERLOOP ONLY WE WILL
			!ASSUME THAT WE ARE DOING ONLY IT BECAUSE
			!THERE ARE PARALLEL INNER ONES. THE ASSUMPTION
			!CAN DO NO HARM. WE THEN ALSO NEED TO SAVE
			!ANY .O VARIABLES THAT WERE ASSIGNED
			!BEFORE USED AND ALSO SUBSUMED. UNFORTUNATELY
			!WE DO NOT HAVE THIS LATTER INFO SO WE WILL
			!JUST USE THE FIRST AND NOT BE PERFECTLY
			!OPTIMAL.

			IF .GUIDE GEQ 5 THEN
			BEGIN
				IF .GLOBREG[.I]<NEDSAV> THEN
				BEGIN
					GLOBREG[.I]<ALCFLG>_MATRLZ;
					FLAG_1;
				END;
			END;

		END;	!ELSE PART
	END;	!DECR LOOP
	!NOW DO IT
	SAVCODE_MATRLZ;
	IF .FLAG THEN
		MATERIALIZE();
END;
%[240]%	!	MODULE EDIT 228
ROUTINE GBLALLOC=
BEGIN
	EXTERNAL CSTMNT,GBSYREGS,INDVAR,GBSYCT;
	MAP BASE INDVAR;
	EXTERNAL EXITNO;
	EXTERNAL UNFLDO,LENTRY;
	EXTERNAL DOVARSUBSTITUTE;


	MAP BASE TOP:BOTTOM:CSTMNT:P;

	OWN NOFIT;
	!EXAMINE STATEMENTS IN A LOOP



	!*************************************************
	ROUTINE SORTNMAKE=
	BEGIN
		!ROUTINE SORTS LIST AND MAKES REGCONTENTS NODE
		!FOR THOSE THAT FIT. AT THE END REGTOALC
		!CONTAINS THE EXACT NUMBER OF ITEMS ALLOCATED.
		LABEL MAKNODS;


	!NOW ACTAULLY MAKE UP ORDERED  LIST OF VARIABLES IN REGISTER
	HEAD_0;						!USE HEAD AS A COUNTER
	!BASICALLY A BUBBLE SORT WHICH STOPS AFTER THE FIRST REGTOALC
	!ARE IN ORDER (THIS IS ROUGHLY 10 OR LESS).
	!AT THE SAME TIME ITEMS ARE SWITCHED INTO THE LIST GLOBREG.
	!THE PROCESSING OCCURS *DOWN* CHOSEN WITH *BUBBLING* UP
	!GLOBREG. PA,PB,PC,HEAD AND T ARE USED AS TEMPORARIES,
	!MOSTLY FOR INDICES AND POINTERS.
	PD_0;			!PD IS POINTER INTO CHOSEN.ZERO ENTRIES ARE SKIPPED
	WHILE .HEAD LEQ .REGTOALC AND .PD LEQ 31 DO
	BEGIN
		IF .CHOSEN[.PD] NEQ 0 THEN		!FOR NON-0 ENTRIES
		BEGIN
			PA_.CHOSEN[.PD];
			NOFIT_1;
			T_.HEAD-1;
			!INA PSEUDO -BUBBLE WAY
			IF .HEAD EQL 0 THEN GLOBREG[.HEAD]_.PA;
			WHILE .NOFIT AND .T GEQ 0 DO
			BEGIN
				IF .PA GTR .GLOBREG[.T] THEN
				BEGIN
					GLOBREG[.T+1]_.GLOBREG[.T];
					T_.T-1;
					IF  .T EQL -1 THEN
						GLOBREG[0]_.PA;
				END ELSE
				BEGIN
					NOFIT_0;
					GLOBREG[.T+1]_.PA;
				END;
			END;		!WHILE
			HEAD_.HEAD+1;
		END;			!NON ZERO ENTRY
		!IN EITHER CASE AN ITEM OF CHOSEN IS PROCESSED
		PD_.PD+1;
	END;			!WHILE ON HEAD AND PD
	IF .HEAD LSS .REGTOALC THEN REGTOALC_.HEAD;
	!


	!NOW REGTOALC HAS THE NUMBER OF VARIABLES THAT
	!WE WANT TO ALLOCATE. SOME MAY BE DOUBLE AND
	!SO ALL WILL NOT ACTUALLY GET ALLOCATED. MAKE
	!THOSE ADJUSTMENTS AND REGCONTENTS NODES FOR THOSE
	!THAT WILL ACTUALLY BE ALLOCATED.
	!MINWD WILL CONTAIN THE NUMBER OF THE REGISTER TO ALLOCATE
	!EACH TIME. HEAD WILL CONTAIN THE LIMIT NUMBER BEYOND WHICH
	!WE SHALL NOT GO. REGS INCLUDING HEAD MAY BE ALLOCATED.

	!MINWD IS SET PRIOR TO THE CALL TO THIS ROUTINE
	!IF THERE WERE DOUBLE WORD QUANTITIES IN THE LOOP
	!WE MUST MAKE SURE THAT THE LOCAL ALLOCATOR IS LEFT
	!AN EVEN-ODD PAIR.
	IF .GOTEMDBL THEN
		HEAD_#10
	ELSE
		HEAD_#12;
	!NOW WE KNOW WHERE TO START AND WHERE TO STOP.
	!START AT MINWD. STOP AT HEAD.

	MAKNODS:
		INCR I FROM 0 TO .REGTOALC-1 DO
		BEGIN
			PD_0;	!SET FLAG
			GLOBREG[.I]<LEFT>_0;	!ZERO MERIT HALF OF WD
			PA_.GLOBREG[.I];
			!IF ITS A DOUBLE WORD MAKE SURE ITS
			!EVEN
			IF .PA[DBLFLG] THEN
			BEGIN
				IF .MINWD THEN
					MINWD_.MINWD+1;
				!IF ITS STILL LEGIT
				IF .MINWD+1 LSS .HEAD THEN %[240]%
					!SET FLAG
					PD_1;
			END ELSE	!NOT DBLWORD
				PD_(.MINWD LSS .HEAD); %[240]%

			!PD NOW SAYS IFS IT OK TO ALLOCATE.
			!MINWD POINTS TO THE REGISTER NUMBER
			IF .PD THEN
			BEGIN
				CHOSEN[.I]_BLDREGCONTENTS(.PA);
				MINWD_.MINWD+1+.PA[DBLFLG];
				!ALSO SET SOME FLAGS IN THE LEFT HALF OF
				!OF THE ASSOCIATED GLOBREG ENTRY THAT
				!RECORD SOME OF THE PROPERTIES OF THE
				!VARIABLE JUST ALLOCATED.

				!IS IT A FORMAL
				IF NOT .PA[FORMLFLG] THEN
					GLOBREG[.I]<NOTFORML>_1;
				!IS IT A PROGRAMMER DEFINED VARIABLE
				IF .PA[IDDOT] NEQ SIXBIT"." THEN
					GLOBREG[.I]<PROGVAR>_1
				ELSE
				!IF ITS A .R DO NOT ALLOCATE THE VARAIBLE
				IF .PA[IDDOTO] EQL SIXBIT".R" THEN
					PA[IDATTRIBUT(NOALLOC)]_1;
			END ELSE
			!NOT LEGIT TO ALLOCATE
			BEGIN
				REGTOALC_.I;
				LEAVE MAKNODS;
			END;
		END;	!INCR LOOP

	!REGTOALC AT LAST CONTAINS THE NUMBER WE ARE (WILL BE AND
	!HAVE BEEN) ALLOCATING.

	!SET ITMCT
	ITMCT_.REGTOALC-1;

	!SET GLOBALS INCASE THIS IS GUIDE 1-4 WILL BE RESET ELSEWHERE IF
	!GUIDE IS 5 OR 6
	GBSYREGS_.CLEANSLATE<0,36>;
	GBSYCT_ONESCOUNT(.GBSYREGS);
	END;			!ROUITNE SORTNMAKE
	!*************************************************


	!AN OUTLINE OF THE PLAN:
	!THE CALLER OF THIS ROUTINE HAS DETERMINED THE CASE (THERE ARE
	!SIX OF THEM AND SET AN INDICATOR(GUIDE). THE PARAMETERS FOR THE
	!BASIC DETERMINATION (TOP, BOTTOM) WERE ALSO SET. ALL CASES
	!FOLLOW THE SAME PATH THROUGH QUITTING IF WE DONT WANT TO
	!ALLOCATE ANY. THEN:
	!CASE 1:
	!	A MAIN PROGRAM WITH NO LOOPS
	!	----------------------------
	!	SORTNMAKE
	!	SUBSTITUTE
	!	PRELOAD THOSE IN DATA

	!CASE 2:
	!	A MAIN PROGRAM WITH A SINGLE LOOP
	!	---------------------------------
	!	RESET BOUNDS
	!	CASE 1

	!CASE 3:
	!	A SUBPROGRAM WITH NO LOOPS
	!	--------------------------
	!	SORTNMAKE
	!	SUBSTITUTE
	!	FOR EACH ENTRY:
	!		FIX PROLOGUE
	!		PRELOAD
	!		MAKE FORMALS NOT ON ALL LISTS
	!	STOWON RETURN (FORMALS MARKED ABOVE + PROGRAMMER VARS.

	!CASE 4:
	!	A SUBPROGRAM WITH A LOOP
	!	------------------------
	!	RESET BOUNDS
	!	CASE 3

	!CASE 5:
	!	AN INNER LOOP ONLY
	!	------------------
	!	IF LOCAL ALLOC INDEX REMOVE IT FROM LIST IF THERE
	!	SET LOWER BOUND OF ALLOCATION REG NUMBER (MINWD)
	!	SORTNMAKE
	!	IF INDEX ON LIST MAKE IT FIRST
	!	SUBSTITUTE
	!	DETERMINE PRELOADS NEEDED (NOT SET IN PREVBB OR 1ST BB)
	!	PRELOAD
	!	MATERIALIZE ON EXITS

	!CASE 6:
	!	OUTER AND INNER LOOPS
	!	---------------------
	!	IF LOCAL ALLOC INDEX TAKE IT OFF LIST IF THERE
	!	SORTNMAKE
	!	IF INNER LOOP INDEX ON LIST MAKE IT FIRST
	!	IF OUTER LOOP INDEX ON LIST MAKE IT SECOND
	!	SUBSTITUTE
	!	DETERMINE PRELOADS NEEDED
	!	PRELOAD
	!	MATERIALIZE ALL AT EXITS FROM BOTH LOOPS

	!BASIC DETERMINATION OF THE DESIRABILITY OF ALLOCATION.
	!DETERMINE VALUE OF RAISE WHICH DEPENDS ON
	! USE OF THE VARIABLE
	!CALLS CREDIT TO WALK TREES ETC.

	IF .FLGREG<BOUNDS> THEN RETURN;

	HEAD_0;			!INITILIZE FOR EXTRIES INTO CHOSEN

	LIBFNREFNO_FNREFNO_CALLREFNO_0;

	!COMPUTE MERITS FOR VARIABLES IN THE LOOP
	P_.TOP[SRCLINK];

	!PUT THE COMPLEXITY OF THE LOOP ITSELF INTO THE DISTRIBUTION

	MAXCOMPLEX[(IF .TOP[SRCCMPLX] GTR 9 THEN 9
			ELSE .TOP[SRCCMPLX])]_1;

	!ALSO CONSIDER IF THE LOOP ITSELF HAS ANY DOUBLE PRECISION
	!INVOLVED IN ANY OF ITS COMPUTATIONS.

	IF .TOP[PAIRMODEFLG] THEN GOTEMDBL_1;

	!MAKE A SPECIAL CASE IF GUIDE IS 6 (ALLOCATING INNER AND
	!OUTER LOOPS BOTH) TO GIVE
	!THE OUTER INDEX A LITTLE CREDIT. BUT NOT A LOT

	IF .GUIDE EQL 6 THEN
	BEGIN
		RAISE_.MERITVAL[LCTLUSE];
		CREDIT(.CSTMNT[DOSYM]);
	END;

	!SAVE CSTMNT
	OLDCSTMNT_.CSTMNT;
	WHILE .P NEQ .BOTTOM[SRCLINK] DO
	BEGIN
		CSTMNT_.P;
		ASCRIBE(.P);
		P_.P[SRCLINK];
	END;
	!RESTORE CSTMNT
	CSTMNT_.OLDCSTMNT;

	!DO NOT BOTHER WITH ANY VARIABLE THAT IS NOT AT LEAST GOING TO
	!SAVE A MOVE (I.E. HAS AT LEAST THE MERIT OF A SINGLE LHS).

	DECR I FROM .HEAD-1 TO 0 DO
	BEGIN
		IF .CHOSEN[.I]<LEFT> LEQ .MERITVAL[LHSUSE]
	!**;[404], GBLALLOC @5341, DCE, 21-MAY-76
	!**;[404], UNDER NO CIRCUMSTANCES CAN AN ASSOCIATE VAR LIVE
	!**;[404], IN A REGISTER - ADD THIS TEST HERE.
	%[404% OR ASSOCIA(.CHOSEN[.I]<RIGHT>)
			THEN CHOSEN[.I]_0;
	END;

	!NOW SUBTRACT FNREFNO FROM ALL
	!ADJUST FNREFNO TO INCLUDE CALLS TO

	FNREFNO_.FNREFNO+.CALLREFNO;

	!IF ANY GO NEGATIVE DELETE FROM LIST
	!	ADJUST FNREFNO TO REFLECT THE ACTUAL COST OF THE NUMBER OF
	!	FUNCTION REFERENCES AND CALLS

	FNREFNO_.FNREFNO*.MERITVAL[FUNUSE];

	!ALSO ADJUST LIBFNREFNO
	!BUT LIBRARY FUNCTIONS ARE ONLY HALF OF USER FUNCTIONS
	!BECAUSE THERE IS ONLY THE STORE COST

	LIBFNREFNO_.LIBFNREFNO*(.MERITVAL[FUNUSE]/2);

	INCR K FROM 0 TO .HEAD-1 DO
	BEGIN
		IF .CHOSEN[.K]<LEFT> LSS .FNREFNO THEN	!ITS GOING NEGATIVE
		CHOSEN[.K]_0
		ELSE
		BEGIN
		CHOSEN[.K]<LEFT>_.CHOSEN[.K]<LEFT>-.FNREFNO;
		!IF WE ARE STILL IN THE GAME DEDUCT LIBFNREFNO TOO IF
		!IT APPLIES.

		P_.CHOSEN[.K]<RIGHT>;
		IF .P[LIBARGUSE] THEN
		BEGIN
			IF .CHOSEN[.K]<LEFT> LSS .LIBFNREFNO THEN
				CHOSEN[.K]_0
			ELSE
				CHOSEN[.K]<LEFT>_.CHOSEN[.K]<LEFT>-.LIBFNREFNO;
		END;
		END;

	END;
	!CONSIDER ACTUAL COMPLEXITY OF EXPRESSIONS INVOLVED
	!
	MELDPLEX();
	CLEANUP();

	!END OF DETERMINATION OF BASIC DESIRABILITY SECTION. THIS IS PERFORMED
	!IN ALL CASES.
	CLEANSLATE_.GBSYREGS;


	!DONT BOTHER WITH THE PROCESS, IF WE ARE NOT GOING TO ALLOCATE ANY
	IF .REGTOALC LEQ 0 THEN
	RETURN;
	!NOW WE WILL REALLY ALLOCATE SOMETHING.
	!SET THE CONTROL FIELD ON ALL ALLOCATED VARIABLES TO
	!AWL.

	DECR I FROM .REGTOALC-1 TO 0 DO
		GLOBREG[.I]<ALCFLGS>_AWL;


	!NOW WALK TREE AND PUT IN ALLOCATIONS
	SPECCASE_1;		!FLAG FOR LEAFSUBSTITUTE
	MINWD_2;

	!ZERO LENTRY
	LENTRY_0;

	!NOW DEPENDING ON THE VALUE OF GUIDE FOLLOW THE PLAN OUTLINED
	!ABOVE

	CASE .GUIDE OF SET

	BEGIN END;		!ZERO IS ILLEGAL

	!CASE 1 MAIN PROGRAM WITH NO LOOPS
	BEGIN
		SORTNMAKE();
		EASY1;
	END;

	!CASE 2  MAIN PROGRAM SINGLE LOOP
	BEGIN
		!TAKE INDUCTION VARIABLE FROM LIST IF LOCALLY ALLOCATED
		REMOVINDVAR;
		!UNDO THE AOBJN ENDING IF NEDSMATRLZ WAS SET BY P2S
		!ALSO RESET NEDSMATRLZ AND MATRLZIXONLY
		CHKGIX;
		IF (.TOP[NEDSMATRLZ] OR .TOP[MATRLZIXONLY]) AND .TOP[IXGALLOCFLG]  THEN
		BEGIN
			PLUSUNFLDO(.TOP);
			TOP[NEDSMATRLZ]_0;
			TOP[MATRLZIXONLY]_0;
			IF .CALLREFNO NEQ 0 THEN TOP[MATRLZCTLONLY]_1;
		END;
		!RESET BOUNDS
		MINWD_LOWERBD(.TOP);
		IF .MINWD NEQ 2 THEN TOP[IXGALLOCFLG]_1;


		!SET BOTTOM UP TO THE END STATEMENT

		BOTTOM_.SORCPTR<RIGHT>;
		SORTNMAKE();
		SETDOIREG;
		!ALSO EXPAND THE SCOPE FOR THE SUBSTITUTION. UNFUDGDO
		!HAS ADJUSTED SORCPTR LEFT TO POINT TO THE PSEUDO
		!DO LOOP NODE. UNFUDGDO IS IN PHA2.
		TOP_.SORCPTR<LEFT>;

		EASY1;
	END;

	!CASE 3  SUBPROGRAM WITH NO LOOPS
	BEGIN
		SORTNMAKE();
		STARTSUB_.TOP;
		STOPSUB_.BOTTOM;
		REGSUBDRIVER();
		FIXENTRY();
	END;

	!CASE 4  SUBPROGRAM WITH A SINGLE LOOP
	BEGIN
		!SEE COMMENT IN CASE 2
		!TAKE LOCALLY ALLOCATED INDUCTION VARIABLE OFF LIST
		REMOVINDVAR;
		CHKGIX;
		!DONT AOBJN IT NOR MATERIALIZE THE INDEX
		IF (.TOP[NEDSMATRLZ] OR .TOP[MATRLZIXONLY]) AND .TOP[IXGALLOCFLG]  THEN
		BEGIN
			PLUSUNFLDO(.TOP);
			TOP[NEDSMATRLZ]_0;
			TOP[MATRLZIXONLY]_0;
			IF .CALLREFNO NEQ 0 THEN TOP[MATRLZCTLONLY]_1;
		END;
		TOP_.SORCPTR<LEFT>;
		MINWD_LOWERBD(.TOP);
		IF .MINWD NEQ 2 THEN TOP[IXGALLOCFLG]_1;


		BOTTOM_.TOP[DOLBL];
		BOTTOM_.BOTTOM[SNHDR];
		!SORT, MAKE REGCONTENTS NODES AND SUBSTITUE THEM
		SORTNMAKE();
		STARTSUB_.TOP;
		STOPSUB_.BOTTOM;
		REGSUBDRIVER();
		!SET REG FIELD IN DO NODE IF GLOBALLY ALLOCATED
		SETDOIREG;
		FIXENTRY();
	END;
	!CASE 5  INNER LOOP ONLY
	BEGIN
		!TAKE THE INDEX OFF THE LIST IF IT WAS LOCALLY
		!ALLOCATED
		REMOVINDVAR;
		!SET MINWD
		MINWD_LOWERBD(.TOP);

		IF .MINWD NEQ 2 THEN TOP[IXGALLOCFLG]_1;
		!SORT THE LIST, MAKE REGCONTENTS NODES
		SORTNMAKE();

		!PREVENT ANY FALSE COMPARES
		SECIDX_-1;

		!MAKE THE INDEX VARIABLE FIRST ON THE LIST OF IT IS
		!NOW ON THE LIST AT ALL
		DECR I FROM .REGTOALC-1 TO 0 DO
		BEGIN
			IF .GLOBREG[.I]<RIGHT> EQL .INDVAR THEN
			BEGIN
				SWAPG(.TOP,.I,0);
				TOP[IXGALLOCFLG]_1;
				!IF ITS AOBJN AND THERE ARE CALLS
				!MAKE IT NOT AOBJN AND SAVE THE CONTROL
				!WORD ONLY
				IF .TOP[FLCWD] AND .CALLREFNO NEQ 0 THEN
				BEGIN
					PLUSUNFLDO(.TOP);
					TOP[MATRLZCTLONLY]_1;
				END;
				!ALSO SET NOPRELOAD FLAG
				GLOBREG[0]<NOPRELOAD>_1;
			END;
		END;

		!SET THE FIELD OF THE DO LOOP NODE THAT TELLS IT
		!WHICH REGISTER TO USE FOR THE INDEX

		SETDOIREG;

		!SET STARTSUB AND STOPSUB AND DO SUBSTITUTION
		T_.TOP[DOLBL];
		WAYBBB_.T[SN1STLAB];
		PREVBB_STARTSUB_.T[SNNXTLAB];
	!**;[347], GBLALLOC @5539, DCE, 9-FEB-76
	!**;[347], DO NOT ALLOW THE BASIC BLOCK TO BEGIN WITH A
	!**;[347], LOGICAL IF STATEMENT.  THIS PREVENTS FUTURE PRELOADS
	!**;[347], OF REGISTERS FROM HAPPENING IN FRONT OF AN IF STATEMENT
	!**;[347], WHICH MIGHT MEAN POOR CODE.  STEP THE STARTSUB TO THE
	!**;[347], NEXT STATEMENT INSTEAD.
%[347]%		IF .STARTSUB[SRCID] EQL IFLID
%[347]%		THEN STARTSUB_.STARTSUB[SRCLINK];
		STOPSUB_.BOTTOM;

		REGSUBDRIVER();

		!COLLECT AND CAUSE PRELOADS TO HAPPEN
		GETPRELOAD();

		!COLLECT AND CAUSE MATERILIZATIONS TO HAPPEN
		GETMATERIAL();
		!MAKE A REGMASK NODE
		!TO INDICATE END OF SCOPE OF MODIFIED GBSYREGS
		CSTMNT_MAKREGMASK();
		CSTMNT[NEWREGSET]_#177760;
		CSTMNT[SRCLINK]_.BOTTOM[SRCLINK];
		BOTTOM[SRCLINK]_.CSTMNT;
	END;

	!CASE 6 INNER AND OUTER LOOP
	BEGIN
		EXTERNAL CSTMNT; MAP BASE CSTMNT;

		!A SYNOPSIS OF THE CAST
		!TOP- POINTS TO INNER LOOP
		!CSTMNT-POINTS TO OUTER LOOP
		!BOTTOM-POINTS TO END OF INNER LOOP
		!INDVAR-POINTS TO INNER LOOP INDEX VARIABLE

		!TAKE LOCALLY ALLOCATED INDEX FROM LIST
		REMOVINDVAR;

		!UNDO THE AOBJN PART OF THE OUTER LOOP
		!WE CANNOT DO THE ANALYSIS TO PERMIT IT TO STAY
		!AS AN AOBJN. ALSO SETTING THE IMMEDIATE FLAG WOULD
		!BE A DRAG.
		IF .CSTMNT[FLCWD] THEN
			PLUSUNFLDO(.CSTMNT);

		!SET MINWD
		MINWD_LOWERBD(.TOP);

		IF .MINWD NEQ 2 THEN TOP[IXGALLOCFLG]_1;
		!SORT AND MAKE REGCONTENTS NODES
		SORTNMAKE();

		!ESTABLISH SECIDX AS POINTER TO OUTER LOOP INDEX
		SECIDX_.CSTMNT[DOSYM];

		!GET INDEX VARIABLES INTO TOP SPOTS IN GLOBREG
		!IF THEY ARE THER AT ALL

		DECR I FROM .REGTOALC-1 TO 0 DO
		BEGIN
			IF .GLOBREG[.I]<RIGHT> EQL .INDVAR THEN
			BEGIN
				SWAPG(.TOP,.I,0);
				TOP[IXGALLOCFLG]_1;
				IF .CALLREFNO NEQ 0 THEN 
					TOP[MATRLZCTLONLY]_1;
			END
			ELSE
			IF .GLOBREG[.I]<RIGHT> EQL .SECIDX THEN
			BEGIN
					!WE HAVE TO CHECK TO SEE IF THIS
					!IS THE ONLY ONE
					IF .REGTOALC NEQ 1 THEN
					SWAPG(.CSTMNT,.I,1);
					CSTMNT[IXGALLOCFLG]_1;
					CSTMNT[NEDSMATRLZ]_0;
					CSTMNT[MATRLZIXONLY]_0;
					CSTMNT[MATRLZCTLONLY]_1;

					!ALSO SET FIELD IN DO STATEMENT
					!NODE (CSTMNT)
					!THE SWAP HAS ALREADY OCCURRED
					T_.CHOSEN[(QQ_(IF .REGTOALC EQL 1 THEN 0 ELSE 1))];
					CSTMNT[DOIREG]_.T[TARGTAC];
					!SAVE THE CONTOL WORD IF THERE WERE
					!CALLS
					IF .CALLREFNO NEQ 0 THEN
						CSTMNT[MATRLZCTLONLY]_1;
					!ALSO SET NO PRELOAD
					GLOBREG[.QQ]<NOPRELOAD>_1;
			END;
		END;

		!SET THE REGISTER FOR THE DO LOOP INDEX
		SETDOIREG;

		!SET UP PARAMETERS FOR SUBSTITUTION
		T_.CSTMNT[DOLBL];
		WAYBBB_.T[SN1STLAB];
		PREVBB_STARTSUB_.T[SNNXTLAB];
		STOPSUB_.T[SNHDR];

		LENTRY_.CSTMNT[DOPRED];

	!**;[400], GBLALLOC @5635, DCE, 3-MAY-76
	!**;[400], DO NOT ALLOW A LOGICAL IF STATEMENT TO BEGIN THE
	!**;[400], BASIC BLOCK WHICH PRECEDES THE SET OF NESTED LOOPS
	%[400]%	IF .STARTSUB[SRCID] EQL IFLID THEN STARTSUB_.STARTSUB[SRCLINK];
		REGSUBDRIVER();

		!NOW PRELOAD AS CASE 5
		GETPRELOAD();

		!AND MATERIALIZE AT OUTSIDE OF OUTER LOOP
		TOP_.CSTMNT;
		BOTTOM_.STOPSUB;
		GETMATERIAL();

		!MAKE REGMASK NODE TO RESET GBSYREGS
		CSTMNT_MAKREGMASK();
		CSTMNT[SRCLINK]_.BOTTOM[SRCLINK];
		BOTTOM[SRCLINK]_.CSTMNT;
		CSTMNT[NEWREGSET]_#177760;
	END;

	TES;


END;


ROUTINE BLDREGCONTENTS(VAR)=
BEGIN
	EXTERNAL CLOBBREGS;
	REGISTER BASE T;
	MAP BASE VAR:QQ;
	!NEED TO COPY VALTYPE STUFF ETC. FROM SYMBOLTABLE
	QQ_MAKPR1(0,REGCONTENTS,0, .VAR[VALTYPE],0, .VAR);
	QQ[TARGTAC]_QQ[TARGADDR]_.MINWD;
	QQ[INREGFLG]_1;

	!RESET BITS IN CLEASLATE IT SAY REGS ARE USED.
	!SET BITS IN CLOBBREGS TO SAY BITS ARE USED.

	CLEANSLATE_CLRBIT(.CLEANSLATE,.MINWD);
	CLOBBREGS_SETBIT(.CLOBBREGS,.MINWD);
	!IF DOUBLE PRECISION DO IT FOR MIN+1 ALSO
	IF .VAR[DBLFLG] THEN
	BEGIN
		CLEANSLATE_CLRBIT(.CLEANSLATE,.MINWD+1);
		CLOBBREGS_SETBIT(.CLOBBREGS,.MINWD+1);
	END;

	.QQ
END;



%ROUTINE TO FORCE PRELOADING OF VARIABLES NOT DEFINED WHEN A BRANCH
 STATEMENT IS ENCOUNTERED%
ROUTINE GOTOFORCELOAD=
BEGIN
	DECR I FROM .REGTOALC-1 TO 0 DO
!**;[444] Insert @ line 5691 in GOTOFORCELOAD	JNG	13-Sep-76
	!NO NEED TO PRELOAD COMPILER VARIABLES JUST ON THE BASIS OF
	!A GOTO, SINCE THE GOTO WAS ALREADY CONSIDERED WHEN PLACING
	!USES AND ASSIGNMENTS OF COMPILER VARIABLES (.O & .R)
%[444]%	IF .GLOBREG[.I]<PROGVAR> THEN	!IF NOT A COMPILER VARIABLE
%[444]%		IF NOT .GLOBREG[.I]<ASGND4USED> THEN
%[444]%			GLOBREG[.I]<USED4ASGND>_1;
END;

EXTERNAL LEAFSUBSTITUTE,IOSUBSTITUTE;

ROUTINE LEAFLOOKER(P)=
BEGIN
	!CONTROL ROUTINE AT THE STATEMENT LEVEL FOR
	!SUBSTITUTION OF REGCONTENTS NODES.
	!P   - POINTS TO A STATEMENT
	EXTERNAL CSTMNT,MISCIO,DOVARSUBSTITUTE,SWAPEM,LOWLIM;
	LOCAL BASE TMP;
	MAP PEXPRNODE P:TOP;
	OWN BASE CLOGIF;


	!MACRO  TO CHECK THE UNIT NUMBER

	MACRO CHKUNIT=
	BEGIN
		TMP_.P[IOUNIT];
		IF .TMP[OPRCLS] EQL DATAOPR THEN
			P[IOUNIT]_SWAPEM(.TMP)
		ELSE
			LEAFSUBSTITUTE(.TMP);
	END$;
	CLOGIF_LOWLIM_0;

		!LOOK FOR COMMON SUB-EXPRESSIONS THAT
		!MAY BE THERE FROM LOCAL ELIMINATION
		!ON STATEMENTS THAT  DO NOT POSTDOMINATE
		!THE ENTRY OF THEIR LOOP

		IF .P[SRCCOMNSUB] NEQ 0 THEN
		BEGIN
			TMP_.P[SRCCOMNSUB];
			DO
			BEGIN
				IF .TMP[A2VALFLG] THEN
				BEGIN
					DECR I FROM .ITMCT TO 0 DO
					BEGIN
						IF .TMP[ARG2PTR] EQL .GLOBREG[.I]<RIGHT> THEN
						BEGIN
						TMP[ARG2PTR]_.CHOSEN[.I];
	!**;[350], LEAFLOOKER @5737, DCE, 9-FEB-76
	!**;[350], DON'T FORGET TO SET ASGND4USED HERE TO CAUSE
	!**;[350], PRELOADING OF REGCONTENTS NODE IF APPROPRIATE.
	!**;[350], WITHOUT THIS, A STATEMENT LIKE:
	!**;[350], A(K)=B(K)  WHICH PRECEDES A DO LOOP WITH AN
	!**;[350], ASSIGNMENT TO K MAY GET BAD CODE GENERATED FOR IT.
	!**;[350], IN FACT NO PRELOAD OF K WOULD HAPPEN, SO THAT THE
	!**;[350], ASSIGNMENT WOULD LOOK FOR K IN A REGISTER WHICH
	!**;[350], HAD NOT BEEN PRELOADED (INITIALIZED).
	%[350]%		IF NOT .GLOBREG[.I]<ASGND4USED>
	%[350]%		THEN GLOBREG[.I]<USED4ASGND>_1;
						!SET THE IMMED FLG IF IT IS
						!AN AOBJN GUY.
						IF .TOP[FLCWD] AND
						.GLOBREG[.I]<RIGHT> EQL .TOP[DOSYM] THEN
							TMP[A2IMMEDFLG]_1;
						END;
					END;
				END ELSE
				LEAFSUBSTITUTE(.TMP[ARG2PTR]);
				TMP_.TMP[CLINK];
			END UNTIL .TMP EQL 0;
		END;

	CASE .P[SRCID] OF SET
	!*****
	%ASGNID%
	BEGIN
		TMP_.P[RHEXP];
		IF .TMP[OPRCLS] EQL REGCONTENTS
		 AND .NOINDVARFLG THEN RETURN;
		LEAFSUBSTITUTE(.P[RHEXP]);
		LEAFSUBSTITUTE(.P[LHEXP]);
		!RESET BB FLAG . CODE MAY NOT BE IDEAL BUT
		!WILL ALWAYS BE RIGHT
		FRSTBB_0;

	END;
	!*****
	%ASSIGN%
	!**;[332],LEAFLOOKER @5766,(5710 IN 4(210)),DCE,18-NOV-1975
	![332] THIS IS RIGHT AFTER %ASSIGN% IN LEAFLOOKER
	!**;[332], THERE CAN BE SUCH A CASE!
%[332]%	LEAFSUBSTITUTE(.P[ASISYM]);
	!*****
	%CALLID%						!CALL STATEMENT
	BEGIN

		!IF NOT PREVIOUSLY SAVED SAVE EVERYBODY
		!OR IF NOT IN THE FIRST BASIC BLOCK
		IF NOT .SAVEDFLG AND NOT .FRSTBB THEN
		BEGIN
			CALLSAVE(.LASTAT);
			SAVEDFLG_1;
		END;
		IF .P[CALLIST] NEQ 0 THEN
		BEGIN
			LOCAL ARGUMENTLIST ARGL;
			ARGL_.P[CALLIST];
			INCR I FROM 1 TO .ARGL[ARGCOUNT] DO
			BEGIN
				TMP_.ARGL[.I,ARGNPTR];
				IF .TMP[OPRCLS] NEQ LABOP AND .TMP[OPRCLS] NEQ DATAOPR  THEN
				LEAFSUBSTITUTE(.ARGL[.I,ARGNPTR]);
			END;
		END;
		!ONLY RESTORE IF THE NEXT STATEMENT WOULD NOT CAUSE  A
		!SAVE AGAIN RIGHT AWAY
		!SET TMP TO THE NEXT STATEMENT. IF THIS CALL WAS THE
		!TRUE BRANCH OF THE LOGICAL IF MAKE IT THE NEXT STATEMENT
		TMP_(IF .P[SRCLINK] NEQ 0 THEN .P[SRCLINK]
					ELSE
					IF .CLOGIF NEQ 0 THEN
						.CLOGIF[SRCLINK]);
	!**;[353], PH3G @5797, DCE, 17-FEB-76
	!**;[353], SET CALLSEEN IF TWO CALLS IN A ROW (OR THE LIKE)
	!**;[353], THIS WILL TRIGGER THE SKIPPING OF ALL CALLS AFTER
	!**;[353], THE FIRST BACK IN REGSUBDRIVER
%[353]%		IF .TMP[USRFNREF] OR .TMP[SRCID] EQL CALLID
%[353]%		THEN CALLSEEN_1
%[353]%		ELSE CALRESTORE(IF .P[SRCLINK] NEQ 0 THEN .P
%[353]%			ELSE .THISTAT);
		FRSTBB_0;
	END;
	!*****
	%CONTINUE%
	BEGIN END;
	!*****
	%DOID%
	BEGIN
		!CHECK TO MAKE SURE WE SHOULD HAVE ONE
		IF .GUIDE GEQ 5 THEN
			DOVARSUBSTITUTE(.P);
		FRSTBB_0;
	END;
	!*****
	%ENTRY%
		FRSTBB_0;
	!*****
	%COMNSUB%
	BEGIN END;
	!*****
	%GOTO%
	GOTOFORCELOAD();	![246] FORCE PRELOADING
	!*****
	%AGOID%
	BEGIN	![246]
		GOTOFORCELOAD();	![246]
		LEAFSUBSTITUTE(.P[AGOTOLBL]);
	END;	![246]
	!*****
	%CGOID%						!COMPUTED GO TO
	BEGIN	![246]
		GOTOFORCELOAD();	![246]
		LEAFSUBSTITUTE(.P[CGOTOLBL]);
	END;	![246]
	!*****
	%IFAID%						!ARITHMETIC IF
	BEGIN	![246]
		GOTOFORCELOAD();
		LEAFSUBSTITUTE(.P[AIFEXPR]);
	END;	![246]
	!*****
	%IFLID%						!LOGICAL IF
	BEGIN
		LEAFSUBSTITUTE(.P[LIFEXPR]);
		!FUDGE CSTMNT TO POINT TO THE OTHER STATEMENT
		CLOGIF_TMP_.CSTMNT;
		CSTMNT_.P[LIFSTATE];
		LEAFLOOKER(.P[LIFSTATE]);
		CSTMNT_.TMP;
	END;
	!*****
	!*****
	%RETURN%
	BEGIN
		IF .P[RETEXPR] NEQ 0 THEN LEAFSUBSTITUTE(.P[RETEXPR]);
	END;
	!*****
	%STOP%
	BEGIN END;
	%READID%
	BEGIN
		FRSTBB_0;
		MISCIO(.P);
		TMP_.P[IOLIST];
		WHILE .TMP NEQ 0 DO
		BEGIN
			IOSUBSTITUTE(.TMP);
			TMP_.TMP[SRCLINK];
		END;
	END;
	!*****
	%WRITID%
	BEGIN
		MISCIO(.P);
		TMP_.P[IOLIST];
		WHILE .TMP NEQ 0 DO
		BEGIN
			IOSUBSTITUTE(.TMP);
			TMP_.TMP[SRCLINK];
		END;
	END;
	!*****
	%DECODE%
	BEGIN
		FRSTBB_0;
		MISCIO(.P);
		TMP_.P[IOLIST];
		WHILE .TMP NEQ 0 DO
		BEGIN
			IOSUBSTITUTE(.TMP);
			TMP_.TMP[SRCLINK];
		END;
	END;
	!*****
	%ENCODE%
	BEGIN
		FRSTBB_0;
		MISCIO(.P);
		TMP_.P[IOLIST];
		WHILE .TMP NEQ 0 DO
		BEGIN
			IOSUBSTITUTE(.TMP);
			TMP_.TMP[SRCLINK];
		END;
	END;
	!*****
	%REREAD%
	BEGIN
		FRSTBB_0;
		MISCIO(.P);
		TMP_.P[IOLIST];
		WHILE .TMP NEQ 0 DO
		BEGIN
			IOSUBSTITUTE(.TMP);
			TMP_.TMP[SRCLINK];
		END;
	END;
	!*****
	%FINDID%
		MISCIO(.P);
	!*****
	!*****
	%CLOSE%		BEGIN END;
	!*****
	%INPUT%		BEGIN END;
	!*****
	%OUTPUT%	BEGIN END;
	!*****
	%BACKSPACE%
		CHKUNIT;
	!*****
	%BACK FILE%
		CHKUNIT;
	!*****
	%REWIND%
		CHKUNIT;
	!*****
	%SKIP FILE%
		CHKUNIT;
	!*****
	%SKIP RECORD%
		MISCIO(.P);
	!*****
	%UNLOAD%
		CHKUNIT;
	!*****
	%RELEASE%
		CHKUNIT;
	!*****
	%END FILE%
		CHKUNIT;
	TES;
	!REST FIRST BASIC BLOCK FLG IF STATEMENT IS LABELED
	IF .P[SRCLBL] NEQ 0 THEN FRSTBB_0;
END;

FORWARD MAKSTASH;
ROUTINE CALLSAVE(HOOK)=
!MATERIALIZE EVERYTHING IN A REGISTER BEFORE A CALL OR FUNCTION REFERENCE
BEGIN
	MAP BASE PREV;

		!MAKSTASH WILL MAKE THE CORRECT SET OF
		!ASSIGNMENTS AND WILL LINK THEM TO
		!ITS PARAMETER. WE MUST LINK THIS SET OF
		!ASSIGNMENTS TO THE INITIAL VALUE OF HOOK[SRCLINK]
		!MAKSTASH RETURNS A POINTER TO THE LAST STATEMENT
		!IT CREATED.

		MAP BASE HOOK;
		LOCAL T;

		T_.HOOK[SRCLINK];
		HOOK_MAKSTASH(.HOOK);
		HOOK[SRCLINK]_.T;
END;			!CALLSAVE
ROUTINE CALRESTORE(HOOK)=
BEGIN
	MAP BASE HOOK:PREV:QQ;
	LABEL LOADEM;
	EXTERNAL MAKASGN;
	!PUT VALUES BACK INTO REGISTERS AFTER A FUNCTION CALL OR REFERENCE
	PREV_.HOOK;
	!SAVE THE LINK ON THIS ONE TO LINK UP THE END
	PD_.HOOK[SRCLINK];

	INCR I FROM 0 TO .REGTOALC-1 DO
	LOADEM:
	BEGIN
		IF NOT CODEMATCH(.GLOBREG[.I]) THEN LEAVE LOADEM;
		QQ_MAKASGN(.CHOSEN[.I],.GLOBREG[.I]);
		PREV[SRCLINK]_.QQ;	!LINK UP

		!SET FLAGS AND FIELDS NECESSRY FOR CG
		QQ[A1SAMEFLG]_1;
		QQ[SRCCMPLX]_1;
		T_.CHOSEN[.I];
		QQ[ASMNTREG]_.T[TARGTAC];
		PREV_.QQ;
	END;
	PREV[SRCLINK]_.PD;

END;
ROUTINE LABLLOK(STMT,LABLE,MATLAB)=

BEGIN
	!LOOK AT LABEL LISTS FOR LABEL.
	!REPLACE IN WITH MATLAB.

	MAP PEXPRNODE STMT;

	!IF THERE IS AN ASSIGNED GO TO WITHOUT ANY ASSIGNS
	!WE COULD STILL BE HERE.  SO WE HAVE TO CHECK FOR
	!THE ABSENCE OF A LIST.
	!A COMPUTES GO TO SHOULD NEVER HAVE GOTOLIST 0
	IF .STMT[GOTONUM] EQL 0 THEN
	BEGIN
		IF .STMT[GOTOLBL] EQL .LABLE THEN
		BEGIN
			STMT[GOTOLBL]_.MATLAB;
			!MAKE THE STATEMENT A STRAIGHT GO TO 
			STMT[SRCID]_GOTOID;
		END;
	END ELSE
	DECR I FROM .STMT[GOTONUM]-1 TO 0 DO

	IF @(.STMT[GOTOLIST]+.I) EQL .LABLE THEN
	BEGIN
		PC_.STMT[GOTOLIST]+.I;
		PC[CESLNK]_.MATLAB;
	END;
END;



FORWARD MATLOK;
ROUTINE  MAKRETU(HOOK)=
BEGIN
	!HOOK POINTS TO THE PLACE WE WILL BUILD A RETURN STATEMENT
	!WE WILL RETURNA POINTER TO THE RETURN STATEMENT MADE

	MAP BASE P:HOOK;

	NAME<LEFT>_SRCSIZ+RETUSIZ;
	P_CORMAN();
	P[OPRCLS]_STATEMENT;
	P[SRCID]_RETUID;

	P[SRCLINK]_.HOOK[SRCLINK];
	HOOK[SRCLINK]_.P;
	.P
END;

ROUTINE MAKSTASH(HOOK)=
BEGIN
	!MAKE AND LINK ALL THE ASSIGNMENT STATEMENTS FOR
	!A MATERIALIZATION
	!HOOK IS SET TO THE PLACE TO LINK THE FIRST ONE.
	!MAKSTASH RETURNS A POINTER TO THE LAST ONE MADE

	!ALSO SET LOCLNK TO THE FIRST ASSIGNMENT MADE
	EXTERNAL TOP,INDVAR,LOCLNK,MAKASGN;
	MAP BASE P:TOP:HOOK:LOCLNK;
	LABEL SAVEM;

	LOCLNK_.HOOK;
	PREV_.HOOK;
	DECR K FROM .REGTOALC-1 TO 0 DO
	SAVEM:
	BEGIN

		IF .GLOBREG[.K]<ALCFLG> NEQ .SAVCODE THEN LEAVE SAVEM;
		P_MAKASGN(.GLOBREG[.K],.CHOSEN[.K]);
			!SPECIAL CHECK TO SET FLAGS
			IF .GLOBREG[.K] EQL .INDVAR THEN
				IF .TOP[FLCWD] THEN
					P[A2IMMEDFLG]_1;
		!COMPLETE HOOKUP. MAY BE ALTERED OUTSIDE
		P[SRCLINK]_.HOOK[SRCLINK];
		HOOK[SRCLINK]_.P;
		HOOK_.P;
	END;	!END OF DECR LOOP ON REGTOALC
	!MAKE LOCLNK POINT TO THE FIRST STATEMENT INSERTED
	IF .HOOK NEQ .LOCLNK THEN LOCLNK_.LOCLNK[SRCLINK];
	.HOOK
END;

ROUTINE NAMESET=
BEGIN
	EXTERNAL NAMLPTR;
	MAP BASE QQ;
	!ONE SMALL CHORE. GO THROUGH ANY NAMELISTS AND SET THE
	!BIT IN THE SYMBOL FOR VARIBALES IN THE NAMELIST

	QQ_.NAMLPTR<LEFT>;
	WHILE .QQ NEQ 0 DO
	BEGIN
		INCR I FROM 0 TO .QQ[NAMCNT]-1 DO
		BEGIN
			REGISTER BASE T1;
			T1_@(.QQ[NAMLIST]+.I);
			T1[IDATTRIBUT(INNAM)]_1;
		END;
		QQ_.QQ[CLINK];
	END;
END;

ROUTINE STOWONRETURN=
BEGIN
	!LOOK FOR ALL RETURN STATEMENTS AND STORE ALLOCATED
	!VARIABLES AWAY.

	!MACRO TO TRANSFORM ITS PARAMETER INTO A GO TO STATEMENT.
	!PARAMETER MUST BE MAPPED TO BASE AND BE A RETURN. NOTE THAT
	!THIS WILL NOT WORK IF THE SIZE (RELATIVE) OF THE NODES
	!CHANGES.

	MACRO MAKAGO(NOD,LABLE)=
	BEGIN
		NOD[SRCID]_GOTOID;
		NOD[GOTOLBL]_.LABLE;
	END$;

	LABEL WHLPREV;
	OWN BASE RETSPOT;
	EXTERNAL BASE LOCLNK;
	EXTERNAL GENLAB;
	MAP BASE BOTTOM:PD:TOP;
	LOCAL BASE STMT;
	MAP BASE PREV:HEAD:PA:QQ;


	!BOTTOM SHOULD POINT TO THE STATEMENT BEFORE THE END
	!IF IT DOES NOT MAKE IT DO SO
	UNTIL .BOTTOM[SRCLINK]  EQL .SORCPTR<RIGHT> DO
		BOTTOM_.BOTTOM[SRCLINK];
	!IF IT IS NOT AN ABSOLUTE BRANCH INSERT A RETURN.
	IF .BOTTOM[SRCID] EQL GOTOID OR
	   .BOTTOM[SRCID] EQL STOPID OR
	   .BOTTOM[SRCID] EQL RETUID THEN
		LOCLNK_.BOTTOM
	ELSE
	BEGIN
		LOCLNK_MAKRETU(.BOTTOM);
		LOCLNK[SRCLINK]_.SORCPTR<RIGHT>;
	END;

	RETSPOT_0;	!NO RETURN STORES MADE.
	STMT_.SORCPTR<LEFT>;
	WHILE .STMT NEQ 0 DO
	BEGIN
		HEAD_.STMT;
		PREV_.STMT;
		WHLPREV:
		WHILE 1 DO
		BEGIN
			!SPECIFICALLY QUIT IF A RETURN OR BOTTOM
			IF .PREV[SRCID] EQL ENDID THEN RETURN;
			IF .PREV[SRCID] EQL RETUID THEN LEAVE WHLPREV;
			!THOSE LOGICAL IFS, ONCE AGAIN,
			!CAUSE A SPECIAL SIDE TRIP.
			IF .PREV[SRCID] EQL IFLID THEN
			BEGIN
				PA_.PREV[LIFSTATE];
				!LOOK TO SEE IF TRUE BRANCH IS A RETURN
				IF .PA[SRCID] EQL RETUID THEN
				BEGIN
					!IF WE ALREADY HAVE A SET OF
					!RETURN MATERIALIZATIONS THEY ARE
					!LABELED BY RETSPOT (NON-ZERO)
					!IF THIS IS A RETURN(I) MAKE A
					!SEPARATE ONE TOO
					IF .RETSPOT NEQ 0 AND .PA[RETEXPR] EQL 0  THEN
						MAKAGO(PA,RETSPOT)
					ELSE
					BEGIN
						!MAKE A SET OF MATERIALIZATIONS
						!THROW THEM IN AT THE END
						!SAVE OUR PLACE
						PD_.PREV;
						PREV_MAKSTASH(.LOCLNK);
						!PREV POINTS TO LAST ONE
						!OF ASSIGNMENTS NOW
						!MAKE A RETURN HERE TOO
						PREV_MAKRETU(.PREV);
						!PREV NOW POINTS TO THAT
						!RETURN.
						!SET A FLAG SO WE KNOW WE
						!MADE IT. THIS IS NEEDED
						!SO THAT WHEN IT IS ENCOUNTERED
						!LATER WE DO NOT MAKE AN
						!INFINITE LOOP
						PREV[A2NOTFLG]_1;
						!LABEL THE FIRST SAVE
						QQ_LABFRST;
						!SEE IF THIS A RETURN (I)
						IF .PA[RETEXPR] NEQ 0 THEN
						BEGIN
							PREV[RETEXPR]_.PA[RETEXPR];
							PA[RETEXPR]_0;
						END ELSE
						RETSPOT_.QQ;
						!NOTE THAT
						!THIS TRUE BRANCH
						!CAN NEVER BE LABELED
						!RESET LOCLNK
						LOCLNK_.PREV;
						!RESET PREV
						PREV_.PD;
						MAKAGO(PA,QQ);
					END;
				END;
			END;
			HEAD_.PREV;
			PREV_.PREV[SRCLINK];
		END;		!WHILE 1 DO




		!HEAD NOW POINTS TO THE STATEMENT BEFORE
		!A RETURN AND PREV TO THE RETURN.
		PREV_.HEAD;
		HEAD_.HEAD[SRCLINK];
		! PREV POINTS TO THE STATEMENT BEFORE THE
		!RETURN, HEAD TO THE RETURN ITSELF
		!ON THE OTHERHAND IF WE ALREADY HAVE A SET OF
		!STORES MADE UP, RETSPOT POINTS TO THE LABEL
		!AND WE CAN CHEAPLY MAKE THIS RETURN A GO TO THAT LABEL
		!BUT FIRST WE MUST CHECK THAT THIS IS NOT
		!A RETURN MADE BY A TRUE BRANCH OF A LOGICAL IF
		IF .HEAD[A2NOTFLG] THEN
		BEGIN
			HEAD[A2NOTFLG]_0;	!LETS BE TIDY
			RETURN;
		END;

		IF (.RETSPOT NEQ 0) AND (.HEAD[RETEXPR] EQL 0)  THEN
		BEGIN
			MAKAGO(HEAD,RETSPOT)
		END ELSE
		BEGIN
			!DO IT ALL NOW
			PREV_MAKSTASH(.PREV);
			!LABEL THE FIRST ONE
			QQ_LABFRST;
			IF .HEAD[RETEXPR] EQL 0 THEN RETSPOT_.QQ;
		END;
		!FINAL LINK UP

		PREV[SRCLINK]_.HEAD;
		STMT_.HEAD[SRCLINK];
	END;	!WHILE ON STMT
END;	!ROUTINE
ROUTINE MATERIALIZE=
BEGIN
	EXTERNAL EXITNO;
	MAP BASE EXITNO;
	EXTERNAL GENLAB;
	EXTERNAL INDVAR;

	MAP PHAZ2 TOP;

	EXTERNAL CHOSEN,REGTOALC,GLOBREG,SAVSPACE;
	EXTERNAL LOCLNK;
	MAP BASE LOCLNK;

	MAP BASE BOTTOM:HEAD:PD;
	MAP PEXPRNODE QQ;
	 MAP PEXPRNODE PREV;
	!MATERIALIZE VARIABLES ASSIGNED TO REGISTERS

	ROUTINE SETBBALCFIELDS=
	BEGIN
		!LOCAL ROUITNE TO SET TWO FIELDS IN THE
		!MATERIALIZATION NODES CREATED TO HELP THE
		!BASIC BLOCK ALLOCATOR KEEP GLOBALLY
		!ALLOCATED VARIABLES IN REGISTERS
		PREV_.LOCLNK;
		!THE INSERTED STATEMENTS ARE BETWEEN LOCLNK
		!AND HEAD
		WHILE .PREV NEQ .HEAD DO
		BEGIN
			PREV[SRCSONNXTUSE]_0;
			PREV[SRCSAVREGFLG]_1;
			PREV_.PREV[SRCLINK];
		END;
	END;		!LOCAL ROUITNE


	!BOTTOM POINTS AT A CONTINUE WHICH HAS A FIELD THAT
	!POINTS TO THE LINKED LISTS OF EXITS.

	!SET UP TWO MODULE OWNS
	PREV_.BOTTOM;
	HEAD_.BOTTOM[SRCLINK];


	!IF THE FULLFILLMENT EXIT IS THE ONLY ONE GET OUT NOW
	IF .BOTTOM[OPTINFO] EQL 0 THEN
	BEGIN
		!FULFILLMENT EXIT ONLY
		SAVCODE_MATRLZ;
		!IF EITHER INDEX IS ON THE LIST
		!DONT LET IT BE SAVED AT ALL
		IF .INDVAR NEQ 0 THEN
			IF .GLOBREG[0]<RIGHT> EQL .INDVAR THEN
				GLOBREG[0]<ALCFLG>_AWL;

		IF .SECIDX NEQ 0 THEN
			IF .GLOBREG[1]<RIGHT> EQL .SECIDX THEN
				GLOBREG[1]<ALCFLG>_AWL
			ELSE
				!IF IT IS THE ONLY ONR ALLOCATED IT IS FIRST
				IF .GLOBREG[0]<RIGHT> EQL .SECIDX THEN
					RETURN;

		PREV_MAKSTASH(.BOTTOM);
		PREV[SRCLINK]_.HEAD;
		SETBBALCFIELDS();
		RETURN;
	END;
	SAVCODE_MATRLZ;
	!GENERATE MATERIALIZATIONS FOR FULLFILLMENT EXIT TOO
	PREV_MAKSTASH(.BOTTOM);

	!NOW THE OTHER (EARLY EXITS) EXITS REMAIN TO BE
	!PROCESSED. AFTER THE MATERIALIZATIONS FROM THE
	!FULLFILLMENT EXIT MAKE A GOTO AROUND THE OTHER
	!MATERIALIZATIONS WE WILL GENERATE.

	!IF THERE ARE MORE EXITS THAN STANDARD THEN
	!	1. MAKE THE STATEMENT AFTER BOTTOM BE A GO TO
	!	   AROUND THE MATERIALIZATIONS
	!	2. CREATE A LABEL FOR THE ATATEMENT AFTER BOTTOM
	!	   IF NECESSARY.

		IF .HEAD[SRCLBL] NEQ 0 THEN
			PD_.HEAD[SRCLBL]
		ELSE
		BEGIN
			PD_GENLAB();
			HEAD[SRCLBL]_.PD;
			PD[SNHDR]_.HEAD;
			PD[SNREFNO]_2;
		END;

		!MAKE THE GO TO
		NAME<LEFT>_GOTOSIZ+SRCSIZ;
		PA_CORMAN();
		PA[OPRCLS]_STATEMENT;
		PA[SRCID]_GOTOID;
		PA[GOTOLBL]_.PD;
		!ADJUST LINKS
		PA[SRCLINK]_.HEAD;
		PREV[SRCLINK]_.PA;
		PREV_.PA;


	!FOR EACH EXIT  MAKE A SET OF
	!ASSIGNMENTS AND A GO TO THE EXIT LABEL
	!THATS THE EASY PART

	EXITNO_.BOTTOM[OPTINFO];
	WHILE .EXITNO NEQ 0 DO
	BEGIN

		OWN BASE THSEXT;	!PTR TO CURRENT ITEM ON EXITLST
		THSEXT_.EXITNO[LEFTP];
		PREV_MAKSTASH(.PREV);

		!MAKE THE GO TO STATEMENT NODE
		NAME<LEFT>_GOTOSIZ+SRCSIZ;
		PA_CORMAN();
		PA[OPRCLS]_STATEMENT;
		!DETERMINE IF IT IS AN ASSIGNED GO TO OR A REGULAR ONE
		!NOTE * NEVER * HERE WITH A COMPUTED GO TO
		IF .THSEXT[OPRCLS] EQL LABOP THEN
			PA[SRCID]_GOTOID
		ELSE
			PA[SRCID]_AGOID;
		PA[GOTOLBL]_.THSEXT;
		PREV[SRCLINK]_.PA;
		PA[SRCLINK]_.HEAD;
		PREV_.PA;
		!NOW THE TIME CONSUMING PART.
		!LOOK A THE ORIGINAL BRANCH STATEMENT.
		!CHANGE IT TO BRANCH TO QQ.
		P_.TOP[SRCLINK];
		QQ_LABFRST;
		WHILE .P NEQ .BOTTOM[SRCLINK] DO
		BEGIN
			MATLOK(.P,.THSEXT,.QQ);
			P_.P[SRCLINK];
		END;
		EXITNO_.EXITNO[RIGHTP];
	END;			!FOR EACH EXIT
		!SET BASIC BLOCK ALLOCATOR FIELDS ON INSERTED STATEMENTS
		SETBBALCFIELDS();
	!THATS ALL!!!!!
END;				!MATERIALIZE

!
!******************************************
!
!
ROUTINE MATLOK(PB,LABL,NEWLAB)=
BEGIN
	!PB IS POINTER TO THE STATEMENT
	!THIS ROUTINE LOOKS AT ALL POSSIBLE BRANCHES AND SUBSTITUTES
	!NEWLAB FOR AN LABEL REFERENCE THAT MATCHES LABL


	!EXTRA LEVEL NEEDED FOR LOGICAL IF STATEMENT

	!MACROS TO PROCESS I/O STATEMENT END AND ERR LABELS.
	!IT IS A MACRO IN THE HOPE THAT BLISS WILL CROSS JUMP
	!IT FOR US.

	MACRO IOMAT=
	BEGIN
		IF .PB[IOERR] EQL .LABL THEN PB[IOERR]_.NEWLAB;
		IF .PB[IOEND] EQL .LABL THEN PB[IOEND]_.NEWLAB;
	END$;

	MAP BASE PB;
	SELECT .PB[SRCID] OF NSET			!ALL BRANCHING STATEMENTS

GOTOID:	BEGIN						!GO TO

		IF .PB[GOTOLBL] EQL .LABL THEN
			PB[GOTOLBL]_.NEWLAB;
	END;
CGOID:	BEGIN						!COMPUTED GO TO
		LABLLOK(.PB,.LABL,.NEWLAB);
							!CESLNK IS RIGHT HALF THROUGH THE
							!STRUCTURE
	END;

AGOID:	BEGIN						!ASSIGNED GO TO
							!OPTIONAL LIST IS PRESENT
	LABLLOK(.PB,.LABL,.NEWLAB);
	END;

IFLID:	BEGIN						!LOGICAL IF
		MATLOK(.PB[LIFSTATE],.LABL,.NEWLAB);
	END;

IFAID:	BEGIN						!ARITHMETIC IF
		IF .PB[AIFLESS] EQL .LABL THEN
		PB[AIFLESS]_.NEWLAB;
		IF .PB[AIFEQL] EQL .LABL THEN
		PB[AIFEQL]_.NEWLAB;
		IF .PB[AIFGTR] EQL .LABL THEN
		PB[AIFGTR]_.NEWLAB;
	END;
CALLID:	BEGIN						!CALL
							!MAY HAVE LABEL AS PARAMETER
		IF .PB[CALLIST] NEQ 0 THEN
		BEGIN
			LOCAL ARGUMENTLIST ARGL;
			ARGL_.PB[CALLIST];
			INCR J FROM 1 TO .ARGL[ARGCOUNT] DO
			BEGIN
				PA_.ARGL[.J,ARGNPTR];
				IF .PA[OPRCLS] EQL .LABOP THEN
				BEGIN
					IF .PA EQL .LABL THEN
					ARGL[.J,ARGNPTR]_.NEWLAB;
				END;
			END;
		END;
	END;

WRITID:	IOMAT;

READID:	IOMAT;

ENCOID:	IOMAT;

DECOID:	IOMAT;

	TESN;
END;			!MATLOK

!
!

ROUTINE INITEM=
BEGIN
	EXTERNAL GBSYREGS,GBSYCT;

	!REINITIALIZE SOME GLOBALS
	DECR I FROM 31 TO 0 DO
		CHOSEN[.I]_0;
	DECR I FROM 15 TO 0 DO
		GLOBREG[.I]_0;
	GOTEMDBL_0;
	!ALSO SET SOME OWNS
	MINWD_0;
	DECR I FROM 9 TO 0 DO
		MAXCOMPLEX[.I]_0;

	!ALSO INITIALIZE SOME GLOBALS

	CLEANSLATE_
	GBSYREGS_#177760000000;
	GBSYCT_12;
	REGAVAIL_8;
END;

GLOBAL ROUTINE MRP3G=
BEGIN
	LABEL ALCREGS;
	EXTERNAL ALCTEMP,ALCTMPS,ALCCON,HISEGBLK;
	EXTERNAL RETNCT,ASVCT;
	EXTERNAL INITREGCANDIDATES,CMPBLOCK;
	EXTERNAL ALLOCATE,RELINIT;
	EXTERNAL STBSYR,STRGCT,ALCSTMNT,LENTRY;
	EXTERNAL GBSYREGS,GBSYCT;
	EXTERNAL LSTLNK,FTEMP,FRSTLNK;
	EXTERNAL FORMPTR,DMPFORMAT;
	EXTERNAL ALCBLOCK,NOBBREGSLOAD,INIRGSTATE;
	EXTERNAL DOCNT,DOWDP;

	!CONTROL GLOBAL REGISTER ALLOCATION

	LABEL EXAMSTAT;

	EXTERNAL CSTMNT,INDVAR,ISN;
	MAP BASE TOP:P:CSTMNT:LENTRY:BOTTOM:WAYBBB;



	DOWDP_0;
	!INITIALIZE THE RELFILE IF ONE WAS REQUESTED

	IF .FLGREG<OBJECT> THEN
		RELINIT();

	!ALLOCATE ARRAYS AND SCALARS, COMMON AND EQUIVALENCE
	ALLOCATE();

	NAMESET();		!SET INNAM BIT FOR VARIABLES IN NAMELISTS
	RETNCT_0;	!CT OF RETURN STMNTS
	ASVCT_0;	!CT OF ASSIGNMENTS OF THE FN VAL THAT DIRECTLY PRECEDE RETURN STMNTS
	!GET COMPLEXITY FOR ALL STATEMENTS
	INITREGCANDIDATES();
	CSTMNT_.SORCPTR<LEFT>;
	WHILE .CSTMNT NEQ 0 DO
		CMPBLOCK();

	!NOW GO THROUGH ONCE MORE AND SAVE AWAY
	!	1. THE PREVIOUS BASIC BLOCK IN THE LABEL TABLE
	!	2. THE STATEMENT IN FRONT OF THE PREVIOUS BASIC BLOCK

	!FOR THIS PURPOSE THE DEFINITION A BASIC BLOCK IS SLIGHTLY
	!DIFFERENT THAN FOR THE LOCAL ALLOCATOR. A BASIC BLOCK STARTS
	!AT A DO, ENTRY OR LABELED STATEMENT.

	WAYBBB_PREVBB_
	CSTMNT_.SORCPTR<LEFT>;

	WHILE .CSTMNT NEQ 0 DO
	BEGIN
		!IS IT A DO
		IF .CSTMNT[SRCID] EQL DOID THEN
		BEGIN
			!YES, IS IT ONE THAT CAN POTENTAILLY GET ALLOCATED
			IF .CSTMNT[EXTALLOC] OR .CSTMNT[INNERDOFLG] THEN
			BEGIN
				!STASH THINGS AWAY IN THE LABEL TABLE
				!SNNXTLAB POINTS TO PREVIOUS BB
				!SN1STLAB POINTS TO STATEMENT BEFORE
				!PREVIOUS BB.
				T_.CSTMNT[DOLBL];
				!SAVE PREVBB IN SNNXTLAB
				T[SNNXTLAB]_.PREVBB;
				!NOW DO THE FINE TUNING
				IF .WAYBBB NEQ .PREVBB THEN
					UNTIL .WAYBBB[SRCLINK] EQL .PREVBB DO
						WAYBBB_.WAYBBB[SRCLINK];

				!NOW SAVE IT
				T[SN1STLAB]_.WAYBBB;
			END;		!LOOP WE CARE ABOUT
			WAYBBB_.PREVBB;
			PREVBB_.CSTMNT;
		END ELSE	!NOT A DO
		!IS IT LABELED. WE HAVE ALREADY REMOVED UNREFERENCED LABELS
		!IS IT AN ENTRY
		IF (.CSTMNT[SRCID] EQL ENTRID) OR (.CSTMNT[SRCLBL] NEQ 0)
		OR .CSTMNT[USRFNREF]
		OR ((.CSTMNT[SRCID] EQL IFLID) AND .CSTMNT[TRUEISBR])
		OR (.CSTMNT[SRCID] EQL CALLID)  THEN
		BEGIN
			WAYBBB_.PREVBB;
			PREVBB_.CSTMNT;
		END;
		!DONE WITH SPECIAL STUFF. LOOK AT NEXT STATEMENT
		CSTMNT_.CSTMNT[SRCLINK];
	END;		!WHILE ON CSTMNT

	FRSTLNK_0;		!VARIABLE FOR LOCAL REGISTER TEMPS
	LSTLNK_0;		!VARIBALE FOR LOCAL REGISTER TEMPS
	NOBBREGSLOAD_FALSE;

	INIRGSTATE();		!INITIALIZE FOR BB REG ALLOCATION

	INITEM();
	GUIDE_0;

	ALCREGS:		!BLOCK IN WHICH REG ALLOC IS PERFORMED
	BEGIN

	IF .DLOOPTREE EQL 0 THEN	!NO LOOPS PRESENT
	BEGIN
		!IT IS EITHER A A MAIN OR SUB PROGRAM.
		!SEE WHICH
		IF .FLGREG<PROGTYP> EQL MAPROG THEN
			GUIDE_1
		ELSE
			!CHECK FOR &$# BLOCK DATA
			IF .FLGREG<PROGTYP> EQL BKPROG THEN
				LEAVE ALCREGS
			ELSE
				GUIDE_3;

		!SET UP GLOBALS FOR ALLOCATION ROUTINE
		LENTRY_TOP_.SORCPTR<LEFT>;
		!PHA2 HAS LEFT THIS AS THE FUDGED DO NODE
		BOTTOM_.TOP[DOLBL];

		!UNLESS THIS IS AN EMPTY SUBPROGRAM. IN THIS CASE
		!IT IS NOT SET UP AND THE LABEL FIELS WILL BE ZERO
		!SO WE WILL QUIT

		IF .BOTTOM EQL 0 THEN LEAVE ALCREGS;

		BOTTOM_.BOTTOM[SNHDR];
		!BOTTOM POINTS TO THE STATEMENT BEFORE THE END STATEMENT

		GBLALLOC();
	END ELSE
	BEGIN
		!LOOPS ARE PRESENT
		!EXAMINE THE CODE
		CSTMNT_.SORCPTR<LEFT>;
		EXAMSTAT:
		WHILE .CSTMNT NEQ 0 DO
		BEGIN
			!WE ONLY CARE ABOUT DO LOOPS
			IF .CSTMNT[SRCID] EQL DOID THEN
			BEGIN
				GUIDE_0;
				INITEM();
				!IS IT AN INNER ONE
				IF .CSTMNT[INNERDOFLG] THEN
				BEGIN
					T_.CSTMNT[DOLBL];
					!LOOK AT PREVBB STORED IN
					!LABEL TABLE AND SEE IF IT
					!IS A MAIN OR SUB PROGRAM
					IF (.T[SNNXTLAB] EQL .SORCPTR<LEFT>
					 OR .T[SNNXTLAB] EQL 0) AND
					.DOCNT EQL 1   THEN
					BEGIN
						IF .FLGREG<PROGTYP> EQL MAPROG THEN
							GUIDE_2
						ELSE
							GUIDE_4;

						!THE LEGALITY OF THE ALLOCATION
						!IS IRRELEVANT. SET THE
						!PARAMETERS
						LENTRY_TOP_.CSTMNT