Google
 

Trailing-Edge - PDP-10 Archives - AP-D480B-SB_1978 - strega.bli
There are 26 other files named strega.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
!AUTHOR: S. MURPHY/HPW/DCE/SJW/JNG
MODULE	STREGA(SREG=#17,VREG=#15,FREG=#16,DREGS=4,RESERVE(0,1,2,3)) =
BEGIN

GLOBAL BIND STREV = 5^24 + 1^18 + 218;	!VERSION DATE: 21-SEP-77

%(
REVISION HISTORY

178	-----	-----	ADD ROUTINES ALCE1LIST AND ALCE2LIST TO
			PERFORM ALLOCATON FOR E1LISTCALL AND
			E2LISTCALL NODES
179	----	-----	MODIFY "ALCCALL" SO THAT DONT ASSUME ALL
			REGS ARE CLOBBERED BY A CALL TO "ADJ1." AND "ADJG."
			ALSO, INSERT CODE IN CMSTMN TO CHECK WHETHER A STMNT
			INCLUDES ANY FN CALLS AND SET "FNCALLSFLG" IN
			THE STMNT NODE IF IT DOES.
			ALSO, REMOVE CODE FROM "CMSTMN" THAT CAUSED PAIRMODEFLG
			TO NEVER BE SET IN AN IO STMNT (BECAUSE IO
			STMNTS DIDNT HAVE FLAGS FIELDS ONCE UPON A TIME)
185	-----	-----	ADD CODE TO PROCESS COMMON SUBS ON CALL STMNTS
			(HAVE SKIPPED SOME VERSION NUMBERS FOR THE
			EXPERIMENTAL REGISTER 0 VERSION)
186	-----	-----	IN "ALCAIF" IF THE REG TO BE TESTED MUST FIRST
			BE LOADED (IE IF "A1SAMEFLG" IS NOT SET), DO
			NOT ALLOW REGISTER 0 TO BE USED (SINCE WE LOAD
			THE REG WITH A SKIP INSTRUCTION)

187	-----	-----	IN "ALCASMNT", DO NOT CALL "ALCINTMP" TO
			TARGET THE RHS TO THE LHS VAR IF THE LHS IS A
			REGCONTENTS (THIS ONLY OCCURS IF "LHINREGALC"
			HAS FAILED TO TARGET THE RHS TO THE LHS REG)
188	-----	-----	CORRECT TYPO IN 187
189	-----	-----	ADD CODE TO HANDLE AN ARBITRARY EXPRESSION
			AS AN ARG IN AN OPEN STMNT
190	-----	-----	ADD CODE TO HANDLE AN ARBITRARY EXPRESSION
			AS A UNIT NUMBER
191	-----	-----	FIX LHINREG TO CORRECTLY HANDLE DOUBLE
			PRECISION ARRAYREF.
192	-----	-----	FIX ALCIOLIST TO PASS CORRECT DP REG BITS
193	-----	-----	MAKE ARRAY-REFS AS UNITS,RECORDS,AND UNDER OPEN/CLOSE
			WORK BY CALLING "ALCTVARR" SO THAT A PTR TO THE STORECLS
			NODE CAN BE LINKED UNDER THE STMNT NODE
194	-----	-----	CHANGE ALL CALLS TO THE MACRO "CLBNXREG"
			INTO CALLS TO THE ROUTINE "CLOBBNX"
195	-----	-----	IN ALCE1LIST,ALCE2LIST, FOR COUNT OR INCR
			AN ARRAY REF, LINK THE STORECLS NODE IN UNDER
			THE E1/E2LISTCALL NODE
196	-----	-----	IN "LHINREGALC", WHEN ARE TARGETTING TO REG 0,
			ALLOW REG 1 TO BE USED IN THE COMPUTATION
197	-----	-----	IN "ALCASMNT", WHEN CALL "SAVEREG" TO REMEMBER
			THAT THE VAL OF RHS IS IN A REG - IF A1NEGFLG
			WAS SET AND THE VAR IS DOUBLE-PREC, THE REGISTER
			WILL BE NEGATED (SINCE THERE IS NO "MOVN" FOR DP)
			HENCE THE REG WONT CONTAIN THE VAR
198	-----	-----	SAME FIX AS 197 - ANOTHER CALL TO "SAVEREG"
199	-----	-----	ONLY CALL FNVALCH1 IF WE ARE IN A FUNCTION
			INSTEAD OF FOR EVERY ASSIGNMENT
200	-----	-----	IN ALCASMNT, IN LOCAL ROUTINE "SETREGFORA2VAL"
			WHEN CHECK FOR SPECIAL CASE OF NEGATED AOBJN WD,
			MUST NOW LOOK AT "A1NEGFLG" (FORMERLY A2NEGFLG)
201	-----	----	IN STCMOPEN AND ALCOPEN, MUST CHECK FOR THE VAL
			OF AN OPEN PARAM EQUAL TO ZERO BEFORE WALKING
			DOWN THE TREE (SINCE THE ARG "DIALOG" CAN HAVE A 
			NULL VAL)
202	254	15425	FOR RELATIONALS, DO NOT ALLOCATE CMNSUB TO 0 SINCE
			WE MIGHT HAVE JUST MADE A SETO 0,0
203	261	15772	CLEAR REGSTATE EACH STATEMENT IF DEBUG:LABELS
204	270	16013	CLEAR REGSTATE FOR ALL VARIABLES POSSIBLY CLOBBERED
			IN A NAMELIST INPUT STATEMENT.
205	300	-----	FIX 204 TO ONLY CHECK RIGHT HALF FOR -1
206	301	16154	REALIZE THAT FUNCTION CALLS WILL CLOBBER ANY
			ARGUMENTS LEFT IN 1 BY FUNCTION PROLOGS
207	310	16602	ALLOCATE UNIT BEFORE OPEN AND CLOSE ARGS
208	311	16665	ALLOCATE REGS IN ALCIOCALL ONLY FOR NON-DATA ITEMS
209	363	18269	PREVENT COMPLEMENTED VAR FROM BEING SAVED
210	403	18961	BAD CODE FOR I=I/J OR A=B*A
211	446	20652	BAD CODE FOR I=I*3 AND I=I**7 (QAR753)
212	471	20309	BAD CODE FOR LOGICAL LHS IN COMMON OR EQUIVALENCE
213	503	19976	ON A(L) = FUNCT. CALL, DON'T LEAVE L IN REG 1.
			IF EVALUATING LH FIRST

	BEGIN VERSION 5A, 7-NOV-76

214	522	20819	ON AN ARRAYREF IN AN IOLIST WHEN WE'RE OUT OF
			REGS, CHECK NEGFLGS BEFORE USING EXISTING REG
			CONTAINING DESIRED SUBSCRIPT.
215	527	20317	CLOBBER ALL COMMON OR EQUIV VARS ON RANDOM READ,
			WRITE, FIND SINCE ASSOCIATE VAR IS UNKNOWN TO US!
216	532	20323	TREAT ARRAY AS ASSOCIATE VARIABLE CORRECTLY
217	546	22030	FIX OPERATIONS WHICH CLOBBER NEXT REGISTER (IDIV)
218	616	22345	BE CAREFUL ALLOCATING NEW REGISTER FOR I/O LIST ELEMENT

)%

	BIND REG0=0;	!REGISTER 0 - THIS REG IS FREQUENTLY AN EXCEPTION
	EXTERNAL
		ALCTVARR,
		CGERR,NXTTMP,ALOCONST,TBLSEARCH,C1H,C1L,DNEGCNST,MAKEPR,
		MAKPR1;
	FORWARD
		CMSTMN(0),ALCSTMN(0),
		STCMASMNT(0),STCMAGO(0),STCMCGO(0),STCMSTOP(0),
		CMPDECENC(0),STCMCSB(0),ALCASMNT(0),ALCMEMCMP(0),ORDERMEMCMP(0), 
		ALCAGO(0),ALCCGO(0),
		ALCDECENC(0),ALCOPEN(0),
		ALCCMNSB(0),STCMLIF(0),STCMAIF(0),SCMASSI(0),STCMOPEN(0),
		ALCE1LIST(3),ALCE2LIST(3),
		ALCLIF(0),ALCAIF(0),ALCASSI(0),ALCCALL(0),ALCIOLST(0),
		ALCIOCALL(1),LHINREGALC(0);

EXTERNAL	EXCHARGS;
	EXTERNAL
		SETCOMPLEXITY,PRCNSTARG,ALCINREG,ALCARRAY,ALCINTMP;


EXTERNAL  TREEPTR,GBSYREGS,GBSYCT,RESNAME;

EXTERNAL CSTMNT;

EXTERNAL STBSYR,STRGCT;

EXTERNAL STCMDO,ALCDOSTMT,ALCDOEND;
EXTERNAL	ALCNARG;
EXTERNAL	ALCENTRY, ALCRETURN,STCMSFN;
EXTERNAL CMPLIOLST;
EXTERNAL	RGTOSAVE;
EXTERNAL	ALCSFN;
EXTERNAL	STCMRETURN;
EXTERNAL REGTOUSE,RGTOU1;
EXTERNAL SETTARGINREG;
EXTERNAL SETTAC;
EXTERNAL SAVREGCONTAINING;	!ROUTINE IN BASIC BLOCK ALLOCATOR (MODULE "CMPBLO")
				! WHICH CHECKS WHETHER A VAR COULD HAVE BEEN LEFT
				! IN A REG FROM A PREV STMNT AND IF SO MARKS THAT STMNT
				! TO LEAVE THE VAR
EXTERNAL ADDREGCANDATE;	!ROUTINE IN BASIC BLOCK ALLOCATOR WHICH
				! ADDS A VAR TO THE SET OF VARS THAT CAN BE LEFT IN REGS

EXTERNAL REGCLOBB;	!THIS ROUTINE IS CALLED WHENEVER AN ALLOCATION IS PERFORMED
			! WHICH WOULD CAUSE THE PREVIOUS CONTENTS OF A REG TO BE CLOBBERED
			! IT CLEARS THE BB REG ALLOC ENTRIES FOR THAT REG
EXTERNAL VARCLOBB;	!THIS ROUTINE IS CALLED WHENEVER A NODE IS PROCESSED
			! WHICH WOULD CLOBBER THE VAL OF A VARIABLE. IT CLEARS ANY
			! BB ALLOC ENTRIES THAT REFER TO THAT VAR
EXTERNAL NOBBREGSLOAD;	!THIS FLAG IS TRUE WHEN NODES ARE BEING
			! PROCESSED WHICH ARE NOT ALWAYS EXECUTED WHEN THE BLOCK
			! IN WHICH THE ARE CONTAINED IS EXECUTED (EG FOR THE STMNT
			! UNDER A LOG IF). WHEN THIS FLAG IS SET, CANNOT ASSUME
			! THAT REGS SET BY EVAL OF THE NODE HAVE A GIVEN VAL
EXTERNAL CLRRGSTATE;	!ROUTINE TO CLEAR THE BASIC BLOCK ALLOCATOR TABLES
			! SO THAT ALL ASSUMPTIONS ABOUT THE CONTENTS OF REGS
			! ARE NO LONGER HELD
EXTERNAL SAVEREG;	!ROUTINE TO ADD A REGISTER TO THE SET OF REGS WHOSE
			! CONTENTS THE BB ALLOCATOR KNOWS ABOUT
EXTERNAL INPFLAG;	!THIS FLAG IS TRUE WHILE PROCESSING AN IOLSIST FOR
			! A STMNT THAT DOES INPUT, FALSE WHILE PROCESSING AN IOLIST
			! FOR A STMNT THAT DOES OUTPUT
EXTERNAL AFREEREG;	!ROUTINE TO GET A FREE REGISTER TO USE. IF POSSIBLE,
			! IT RETURNS A REG WHICH WILL NOT BE USEFUL LATER
			! IN THIS BASIC BLOCK
			! IF NOT, RETURNS THE REG WHOSE NEXT USE IS FURTHEST AWAY
EXTERNAL REGCONTAINING;	!ROUTINE OF BASIC BLOCK ALLOCATOR WHICH
			! CHECKS WHETHER ANY REG HOLDS A GIVEN VAR. IF SO IT
			! IT RETURNS THE REG, IF NOT IT RETURNS -1
SWITCHES NOLIST;
REQUIRE FIRST.BLI;
REQUIRE TABLES.BLI;
SWITCHES LIST;



EXTERNAL DBLMODE;		!THIS FLAG WORD IS SET WHEN A STATEMENT IS BEING
			! ALLOCATED DOUBLE-PRECISION MODE (IE FOR AN ASSIGNMENT
			! STMNT IF THE TOP-LEVEL EXPRESSIONS ARE DOUBLE-PRECISION)

MAP PEXPRNODE TREEPTR;

MAP BASE CSTMNT;


GLOBAL ROUTINE STREGA=
%(***************************************************************************
	ROUTINE TO PERFORM LOCAL REGISTER ALLOCATION FOR A STATEMENT.
	CALLED WITH THE GLOBAL CSTMNT POINTING TO THE STATEMENT.
	CALLED WITH THE GLOBALS
		STBSYR - HAS BIT SET FOR EACH REG AVAILABLE FOR USE IN EVALUATING
			THIS STATEMENT
		STRGCT - CT OF REGS AVAILABLE
***************************************************************************)%
BEGIN
	%(***PERFORM COMPLEXITY ANALYSIS ON THE STMNT***)%
	CMSTMN();

	%(***PERFORM REGISTER ALLOCATION ON THE STMNT***)%
	ALCSTMN();

END;


GLOBAL ROUTINE CMSTMN=
%(***************************************************************************
	TO PERFORM COMPLEXITY ANALYSIS ON A STATEMENT.
	CALLED WITH THE GLOBAL CSTMNT POINTING TO THE STATEMNET TO BE PROCESSED.
***************************************************************************)%
BEGIN
	EXTERNAL CMPFNARGS;
	EXTERNAL LPIXSUB;	!ROUTINE TO SUBSTITUTE REGCONTENTS NODES FOR
				! REFERENCES TO THE LOOP INDEXIN AN INNERMOST
				! DO LOOP
	EXTERNAL PAIRMODE;	!GLOBAL WHICH WILL BE SET TO TRUE WHILE PERFORMING COMPLEXITY
				! PASS OVER ANY NODE THAT REQUIRES AN ADJACENT
				! PAIR OF REGISTERS
	EXTERNAL STCMSUB;
	GLOBAL FNREF;	!GLOBAL THAT WILL GET SET IF ANY FN CALLS ARE
			! ENCOUNTERED IN PROCESSING A STMNT
	OWN PEXPRNODE RECNO;	!PTR TO SYMBOL TABLE OR CONSTANT TABLE ENTRY
				! FOR A RECORD NUMBER FOR AN IO STMNT

	%(***DEFINE A ROUTINE TO USE TO ALLOCATE CORE FOR ANY CONSTANT USED AS
		A RECORD NUMBER IN AN IO STMNT***)%
	ROUTINE CMPRECNO=
	BEGIN
		IF (RECNO_.CSTMNT[IORECORD]) NEQ 0
		THEN
		BEGIN
			IF .RECNO[OPR1] EQL CONSTFL
			THEN ALOCONST(.RECNO)

			%(***IF RECORD NUMBER IS AN EXPRESSION
				PERFORM COMPLEXITY WALK ON IT***)%
			ELSE
			BEGIN
				TREEPTR_.RECNO;
				SETCOMPLEXITY();
			END;
		END
	END;

	ROUTINE CMPREPT=
	%(***DEFINE ROUTINE FOR HANDLING REPT FIELDS OF IO STMNTS***)%
	BEGIN
		IF .CSTMNT[IOREPT] EQL 0
		THEN
		CSTMNT[SRCCMPLX]_0
		ELSE
		BEGIN
			TREEPTR_.CSTMNT[IOREPT];
			CSTMNT[SRCCMPLX]_SETCOMPLEXITY();
		END
	END;

	ROUTINE CMPUNIT=
	%(***DEFINE ROUTINE TO PERFORM COMPLEXITY WALK FOR A UNIT NUMBER
		WHICH IS AN EXPRESSION OR ARRAY-REF**)%
	BEGIN
		TREEPTR_.CSTMNT[IOUNIT];
		IF .TREEPTR[OPRCLS] NEQ DATAOPR	!IF UNIT NOT A SIMPLE VAR OR CONST
		THEN SETCOMPLEXITY()
	END;



	%(***IF WE ARE IN A DO LOOP IN WHICH THE
		LOOP INDEX LIVES IN A REGISTER, SUBSTITUTE "REGCONTENTS" NODES FOR
		ALL REFERENCES TO THE LOOP INDEX THAT OCCUR IN THIS STMNT***)%
	LPIXSUB();

	PAIRMODE_FALSE;	!INIT GLOBAL WHICH WILL BE USED TO DETERMINE WHETHER THIS
			! STATEMENT INCLUDES ANY EXPRESSIONS THAT REQUIRE REGISTER PAIRS
	FNREF_FALSE;	!INIT GLOBAL THAT WILL BE USED TO DETERMINE WHETHER THIS STMNT
			! CONTAINS ANY FN REFERENCES

	%(***SRCID OF STMNT DETERMINES ACTION TO BE TAKEN***)%
	CASE .CSTMNT[SRCID] OF SET

	STCMASMNT();					!FOR ASSIGNMENT
	SCMASSI();					! ASSIGN
	BEGIN						! CALL
		CSTMNT[SRCCMPLX]_(IF .CSTMNT[CALLIST] EQL 0	
			THEN 0
			ELSE CMPFNARGS(.CSTMNT[CALLIST],FALSE));
		STCMCSB();	!PROCESS ANY COMMON SUBS
	END;
	CSTMNT[SRCCMPLX]_0;				! CONTINUE
	STCMDO();					! DO
	STCMSUB();					! ENTRY
	STCMASMNT();					! COMMON SUB (SAME AS ASMNT

	CSTMNT[SRCCMPLX]_0;				! GOTO
	STCMAGO();					! ASSIGNED GOTO
	STCMCGO();					! COMPUTED GOTO
	STCMAIF();					! ARITHMETIC IF
	STCMLIF();					! LOGICAL IF
	STCMRETURN();					! RETURN
	STCMSTOP();					! STOP

	BEGIN						! READ
		CMPLIOLST();
		CMPRECNO();
		CMPUNIT();
	END;
	BEGIN						! WRITE
		CMPLIOLST();
		CMPRECNO();
		CMPUNIT();
	END;
	CMPDECENC();					! DECODE
	CMPDECENC();					! ENCODE
	BEGIN						! REREAD
		CMPLIOLST();
		CMPUNIT()
	END;
	BEGIN						! FIND
		CSTMNT[SRCCMPLX]_0;
		CMPRECNO();
		CMPUNIT();
	END;
	BEGIN						! CLOSE
		STCMOPEN();
		CMPUNIT()
	END;
	CSTMNT[SRCCMPLX]_0;				! INPUT (NOT IN RELEASE 1)
	CSTMNT[SRCCMPLX]_0;				!  OUTPUT (NOT IN RELEASE 1)

	(CMPREPT();CMPUNIT());			! BACKSPACE
	(CMPREPT();CMPUNIT());			! BACKFILE
	(CSTMNT[SRCCMPLX]_0;CMPUNIT());		! REWIND
	(CMPREPT();CMPUNIT());			! SKIPFILE
	(CMPREPT();CMPUNIT());			! SKIP RECORD
	(CSTMNT[SRCCMPLX]_0;CMPUNIT());		! UNLOAD
	(CSTMNT[SRCCMPLX]_0;CMPUNIT());		! RELEASE
	(CMPREPT();CMPUNIT());			! ENDFILE

	CSTMNT[SRCCMPLX]_0;				! END
	STCMSTOP();					! PAUSE
	BEGIN					! OPEN
		STCMOPEN();
		CMPUNIT()
	END;
	STCMSFN();					! SFN
	CSTMNT[SRCCMPLX]_0;				!  FORMAT
	CSTMNT[SRCCMPLX]_0;				! BLT (NOT IN RELEASE 1)
	CSTMNT[SRCCMPLX]_0;				! GLOBAL ALLOCATOR ID
	TES;

	IF .PAIRMODE	!IF ANY EXPRESSIONS WERE ENCOUNTERED THAT REQUIRED ADJACENT REG PAIRS
	THEN CSTMNT[PAIRMODEFLG]_1;	!SET FLAG IN STMNT 

	IF .FNREF THEN CSTMNT[FNCALLSFLG]_1;	!IF ANY FN CALLS WERE ENCOUNTERED SET FLAG IN STMNT
END;

GLOBAL ROUTINE ALCSTMN=
%(***************************************************************************
	ROUTINE TO PERFORM LOCAL REGISTER ALLOCATION FOR A STATEMENT.
	CALLED WITH THE GLOBAL CSTMNT POINTING TO THE STATEMENT.
	CALLED WITH THE GLOBALS
		STBSYR - HAS BIT SET FOR EACH REG AVAILABLE FOR USE IN EVALUATING
			THIS STATEMENT
		STRGCT - CT OF REGS AVAILABLE
***************************************************************************)%
BEGIN
	EXTERNAL INPFLAG;	!GLOBAL FLAG THAT IS SET TO TRUE WHILE THE IOLIST
				! OF A STATEMENT THAT DOES INPUT IS BEING PROCESSED (EG READ,DECODE)
				! AND TO FALSE WHILE THE IOLIST OF A STATEMENT THAT DOES NOT
				! DO INPUT IS BEING PROCESSED
	EXTERNAL PAIRMODE;	!DURING REG ALLOC PASS, IF THIS GLOBAL IS TRUE, WE
				! WILL ASSUME THAT THE REGISTERS REQUIRED BY A
				! GIVEN SUBEXPRESSION MUST ALL BE IN ADJACENT PAIRS
	ROUTINE ALCREPT=
	%(***DEFINE ROUTINE TO PERFORM REG ALLOC FOR REPT FIELD FOR AN IO STMNT***)%
	BEGIN
		IF .CSTMNT[IOREPT] NEQ 0
		THEN
		BEGIN
			TREEPTR_.CSTMNT[IOREPT];
			IF .TREEPTR[OPRCLS] NEQ DATAOPR	!IF NOT A SIMPLE VAR OR CONST
			THEN
			ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.STBSYR,.STRGCT);
		END
	END;


	ROUTINE ALCUNIT=
	%(***ROUTINE TO PERFORM REG ALLOC FOR A UNIT NUMBER WHICH IS
		AN EXPRESSION OR ARRAYREF***)%
	BEGIN
		TREEPTR_.CSTMNT[IOUNIT];
		IF .TREEPTR[OPRCLS] NEQ DATAOPR	!IF NOT A SIMPLE VAR OR CONST
		THEN
		BEGIN
			IF .TREEPTR[OPRCLS] EQL ARRAYREF
			!FOR AN ARRAYREF - MUST LINK A STORECLS NODE UNDER THE STMNT NODE
			THEN CSTMNT[IOUNIT]_ALCTVARR(.STBSYR,.STRGCT)
			ELSE
			ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.STBSYR,.STRGCT)
		END;
	END;



!**;[527], STREGA @3520, DCE, 6-JAN-77
%[527]%	EXTERNAL CLOBBCOMEQV;
	ROUTINE ALCRANDIO=
	%(*************
		PERFORM REG ALLOC FOR RANDOM ACCESS IO.
		MUST  PERFORM ALLOCATION FOR THE CALC OF THE RECORD NUMBER
		AND ALSO BB ALLOCATOR MUST ASSUME THAT THE VALS OF ALL ASSOCIATE
		VARIABLES ARE CHANGED.
	*************)%
	BEGIN
		REGISTER ASSCELEM;	!AN ELEMENT ON THE LINKED LIST OF ASSOC-VAR PTRS

		EXTERNAL ASSOCPT;	!GLOBAL POINTING TO LIST OF ALL ASSOC VARS
					! IN THIS SUBPROGRAM
		IF (TREEPTR_.CSTMNT[IORECORD]) EQL 0	!IF DO NOT HAVE RANDOM ACCESS
		THEN RETURN;			! NO PROCESSING IS NEEDED

		IF .TREEPTR[OPRCLS] NEQ DATAOPR	!IF THE RECORD NUMBER IS NOT A SIMPLE VAR OR CONST
		THEN
		BEGIN
			IF .TREEPTR[OPRCLS] EQL ARRAYREF
			!FOR AN ARRAYREF - MUST LINK A STORECLS NODE UNDER THE STMNT NODE
			THEN CSTMNT[IORECORD]_ALCTVARR(.STBSYR,.STRGCT)
			ELSE
			ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.STBSYR,.STRGCT)
		END;


		ASSCELEM_.ASSOCPT;
		UNTIL .ASSCELEM<RIGHT> EQL 0	!LOOK AT ALL ASSOC VARS IN THE PROGRAM
						! RIGHT HALF OF EACH ENTRY ON THE LINKED
						! LIST PTS TO NEXT ELEM
		DO
		BEGIN
			[email protected]<RIGHT>;	!GET THE CONTENTS OF THE NEXT ELEMENT
			VARCLOBB(.ASSCELEM<LEFT>);	!LEFT HALF OF WD ON ASSOC VAR
						! LIST PTS TO SYM TABLE ENTRY FOR THE VAR
		END;
!**;[527], ALCRANDIO @3556 (BETWEEN END STMNTS), DCE, 6-JAN-77
!**;[527], IF THE OPEN OCCURS OUTSIDE THIS PROGRAM MODULE, THEN
!**;[527], WE MUST ASSUME THAT ALL COMMON/EQUIV VARS ARE CLOBBERED
!**;[527], SINCE THEY COULD BE ASSOCIATE VARIABLES!
%[527]%	CLOBBCOMEQV();
	END;


	ROUTINE CHECKNLIST (LISTPTR)=	![270]
	%(***********	ROUTINE ADDED BY [270]
		CHECK THE LIST OF VARIABLES POINTED TO BY A NAMELIST NAME
		AND CLEAR OUT ANY WHICH ARE CURRENTLY LIVING IN REGISTERS
		SINCE THEY MAY BE CLOBBERED DURING AN INPUT REFERENCING
		THAT NAMELIST NAME.
	*************)%
	BEGIN	![270]
		REGISTER T1;	![270]
		MAP BASE LISTPTR;	![270]
		![270] LISTPTR POINTS TO A NAMELIST BLOCK CONTAINING POINTERS
		![270] TO ALL THE VARIBLES SYMBOL TABLE ENTRIES
		INCR I FROM 0 TO .LISTPTR[NAMCNT]-1 DO	![270] SCAN THRU THE LIST OF POINTERS
		BEGIN	![270]
			T1_@(.LISTPTR[NAMLIST]+.I);	![270] GET THE SYMBOL TABLE POINTER
			VARCLOBB(.T1<RIGHT>);	![270] GET RID OF IT IF IN REG
		END;	![270]
	END;	![270]


	DBLMODE_FALSE;	!FLAG WILL BE SET TO TRUE WHEN A STMNT IS PROCESSED
			! IN DOUBLE-WD MODE (IE USES REG PAIRS). INITIALIZE IT TO FALSE.

	IF .CSTMNT[PAIRMODEFLG]	!IF THIS STMNT REQUIRES ANY ADJACENT REG PAIRS
	THEN PAIRMODE_TRUE	! INIT GLOBAL INDICATING THAT AT LEAST
	ELSE PAIRMODE_FALSE;	! ONE FREE PAIR SHOULD ALWAYS BE LEFT


	IF .FLGREG<DBGLABL>	![261] FORGET ABOUT OPTIMIZING REGISTER
	THEN	![261] USAGE ACROSS STATEMENTS IF FORDDT MAY CHANGE
	CLRRGSTATE();	![261] VALUES IN CORE

	%(***ACTION TO BE TAKEN IS DETERMINED BY THE SRCID***)%
	CASE .CSTMNT[SRCID] OF SET

	ALCASMNT();		!ASSIGNMENT
	ALCASSI();		!ASSIGN
	ALCCALL();		!CALL
	BEGIN END;		!CONTINUE
	ALCDOSTMT();		!DO
	ALCENTRY();		!ENTRY
	ALCASMNT();		!COMMON SUB - SAME AS ASSIGNMENT

	BEGIN END;		! GOTO
	ALCAGO();		! ASSIGNED GOTO
	ALCCGO();		! COMPUTED GOTO
	ALCAIF();		! ARITH IF
	ALCLIF();		! LOGICAL IF
	ALCRETURN();		! RETURN
	BEGIN END;		! STOP

	BEGIN			! READ
		ALCRANDIO();
		ALCUNIT();
		INPFLAG_TRUE;	!SET GLOBAL FLAG TO INDICATE THAT THE IOLIST TO BE
				! PROCESSED DOES INPUT
		IF .CSTMNT[IONAME] NEQ 0	![270] SEE IF NAMELIST
		AND .CSTMNT[IONAME] NEQ #777777	![300] TYPE READ
		THEN	![270] YES
		BEGIN	![270]
			LOCAL BASE T1;	![270] SEE IF NAMELIST
			T1_.CSTMNT[IONAME];	![270] BIT IS ON IN SYMBOL
			IF .T1[IDATTRIBUT(NAMNAM)] EQL 1	![270] TABLE ENTRY
			THEN CHECKNLIST(.T1[IDCOLINK]);	![270] THEN CLEAR ANY REGISTERS CONTAINING
		END;	![270] VARIBLES IN THE NAMELIST
		ALCIOLST();	!PROCESS THE IOLIST		
	END;
	BEGIN			! WRITE
		ALCRANDIO();
		ALCUNIT();
		INPFLAG_FALSE;	!SET GLOBAL FLAG TO INDICATE THAT THE IOLIST TO BE
				! PROCESSED DOES NOT DO INPUT
		ALCIOLST();		
	END;
	BEGIN			! DECODE
		INPFLAG_TRUE;	!SET GLOBAL FLAG TO INDICATE THAT THE IOLIST TO BE
				! PROCESSED DOES INPUT
		ALCDECENC();
	END;
	BEGIN			! ENCODE
		INPFLAG_FALSE;	!SET GLOBAL FLAG TO INDICATE THAT THE IOLIST TO BE
				! PROCESSED DOES NOT DO INPUT
		ALCDECENC();
	END;
	BEGIN			!REREAD
		ALCUNIT();
		INPFLAG_TRUE;	!SET GLOBAL FLAG TO INDICATE THAT THE IOLIST TO BE
				! PROCESSED DOES INPUT
		ALCIOLST();
	END;
	(ALCRANDIO();ALCUNIT());	! FIND
	(ALCUNIT();ALCOPEN());	![310] CLOSE
	BEGIN END;		! INPUT (NOT IN RELEASE 1)
	BEGIN END;		! OUTPUT (NOT IN RELEASE 1)

	(ALCREPT();ALCUNIT()); !BACKSPACE
	(ALCREPT();ALCUNIT()); !BACKFILE
	ALCUNIT();		!REWIND
	(ALCREPT();ALCUNIT()); !SKIPFILE
	(ALCREPT();ALCUNIT()); !SKIPRECORD
	ALCUNIT();		!UNLOAD
	ALCUNIT();		!RELEASE
	(ALCREPT();ALCUNIT()); !ENDFILE;

	BEGIN END;		!END
	BEGIN END;		!PAUSE
	(ALCUNIT();ALCOPEN()); ![310] OPEN
	ALCSFN();		!SFN
	BEGIN END;		!FORMAT
	BEGIN END;		!BLT (NOT IN RELEASE 1)
	BEGIN			!GLOBAL ALLOCATOR ID - INDICATING
				! THAT SET OF REGISTERS AVAILABLE SHOULD CHANGE
		GBSYREGS<LEFT>_.CSTMNT[NEWREGSET];	!SET OF REGS TO BE
					! USED IN STMNTS FOLLOWING
		GBSYCT_ONESCOUNT(.GBSYREGS);
	END;
	TES;





	%(***IF THIS STMNT HAS A LABEL, PERFORM REG ALLOC FOR ANY DO-LOOP TERMINATION
		IMPLIED BY THAT LABEL****)%
	IF .CSTMNT[SRCLBL] NEQ 0
	THEN ALCDOEND(.CSTMNT[SRCLBL]);

END;

GLOBAL ROUTINE  STCMASMNT=
%(***************************************************************************
	ROUTINE TO PERFORM THE COMPLEXITY PASS FOR AN ASSIGNMENT
	STATEMENT.
	DETERMINES THE NUMBER OF REGS  NECESSARY FOR COMPUTATION OF THE
	LEFT AND RIGHT SIDES AND FOR ALL COMMON SUBEXPRESSIONS.
	DETERMINES WHICH SIDE SHOULD BE COMPUTED  FIRST.
	CALLED WITH THE GLOBAL CSTMNT POINTING TO THE STATEMENT NODE.
	THIS ROUTINE IS NOT CALLED RECURSIVELY.
***************************************************************************)%
BEGIN
	EXTERNAL ORDERMEMCMP;	!ROUTINE TO ORDER THE ARGS OF AN OP TO MEMORY
				! SO THAT ARG2 IS IDENTICAL TO THE LHS OF THE ASSIGNMENT STMNT
	EXTERNAL FNVLCH1;	!CHECK FOR ASSIGNMENT OF FN VAL DIRECTLY BEFORE RETURN
	OWN CMPLX1:CMPLX2;
	OWN PEXPRNODE ARG1NODE;
	OWN PEXPRNODE LHNODE;
	OWN PEXPRNODE RHNODE;


	IF .FLGREG<PROGTYP> EQL FNPROG 
	THEN
		FNVLCH1();	!KEEP A CT OF ASSIGNMENTS OF THE FN VAL THAT DIRECTLY
			! PRECEDE RETURN STMNTS
	RHNODE_.CSTMNT[RHEXP];
	LHNODE_.CSTMNT[LHEXP];


	IF .CSTMNT[MEMCMPFLG]	!IF THIS ASSIGNMENT WILL BE PERFORMED TO MEMORY
		AND .RHNODE[OPRCLS] NEQ SPECOP	! AND THE OPERATION IS ARITHMETIC OR BOOLEAN
	THEN
	BEGIN
		 ORDERMEMCMP();	!ORDER THE ARGS UNDER RHS SO THAT THE ARG THAT MATCHES LHS IS ARG2
		ARG1NODE_.RHNODE[ARG1PTR];	!GET PTR TO ARG NOT IDENTICAL TO LHS

		IF .ARG1NODE[OPERATOR] EQL INTCONST	!IF THAT ARG IS THE INTEGER CONSTANT
			AND .ARG1NODE[CONST2] EQL 1	! ONE
			AND .RHNODE[OPERATOR] EQL INTADD	!AND THE OPERATION IS INTEGER ADD (OR SUB)
		THEN RHNODE[OPTOBOTHFLG]_1;		!THEN PERFORM THIS OP TO BOTH RATHER THAN
						! TO MEMORY (SO THAT CAN PEEPHOLE AOS AND SOS)
	END;

	IF .CSTMNT[A1VALFLG]
	THEN
	%(***IF LHS IS A SIMPLE VARIABLE, SET UP PTR TO THE SYMBOL TABLE ENTRY***)%
	BEGIN
		RESNAME_.CSTMNT[LHEXP];
		CMPLX1_0;

	END
	ELSE
	%(***IF LHS REQUIRES EVALUATION (IE IS AN ARRAY REFERENCE), DETERMINE NUMBER OF
		REGS NEEDED FOR THAT CALC***)%
	BEGIN
		TREEPTR_.CSTMNT[LHEXP];
		CMPLX1_SETCOMPLEXITY();
		RESNAME_.LHNODE[ARG1PTR];
	END;

	%(***DETERMINE THE NUMBER OF REGS NECESSARY FOR EVALUATION OF RHS***)%
	IF NOT .CSTMNT[A2VALFLG]
	THEN
	BEGIN
		TREEPTR_.CSTMNT[RHEXP];
		CMPLX2_SETCOMPLEXITY();
	END;

	%(***IF RIGHT HAND SIDE IS A VARIABLE OR A CONSTANT, STILL NEED ONE REG TO LOAD THE VAL INTO***)%
	IF .RHNODE[OPRCLS] EQL DATAOPR
	THEN
	BEGIN
		CMPLX2_1;

		%(***IF RHNODE IS A CONSTANT, DETERMINE WHETHER IT IS
			AN IMMED CONSTANT AND IF NOT ALLOCATE CORE FOR IT***)%
		IF .RHNODE[OPR1] EQL CONSTFL
		THEN
		PRCNSTARG(.CSTMNT,.RHNODE,FALSE);


		%(**IF RHS COULD HAVE BEEN LEFT IN A REG EARLIER, DO SO**)%
		SAVREGCONTAINING(.RHNODE);

		%(**IF THE VAR ON THE RHS IS NEEDED LATER, WILL BE ABLE TO USE
			IT FROM THE REG USED FOR THIS ASMNT**)%
		ADDREGCANDATE(.RHNODE,.CSTMNT);


	END;

	%(***IF THE RHS IS DOUBLE-PREC, NEED TWICE AS MANY REGS AS HAVE COMPUTED***)%
	IF .RHNODE[DBLFLG] THEN CMPLX2_2*.CMPLX2;


	%(***SET FIELD IN THE ASSIGNMENT-STMNT NODE TO INDICATE THE NUMBER OF REGS
		NECESSARY TO EVAL THE STMNT EXCLUSIVE OF COMMON SUBEXPRS***)%
	CSTMNT[SRCCMPLX]_
		(IF .CMPLX1 GTR .CMPLX2
		THEN .CMPLX1
		ELSE
		IF .CMPLX2 GTR .CMPLX1
		THEN .CMPLX2
		ELSE .CMPLX1+1 );


	%(***PERFORM COMPLEXITY ANALYSIS FOR EACH COMMON SUBEXPRESSION UNDER
		THIS NODE*******)%
	STCMCSB();

	%(**IF THE LHS VAR IS NEEDED LATER, IT CAN BE USED DIRECTLY FROM THE REG
		USED FOR THIS ASMNT***)%
	IF .CSTMNT[A1VALFLG] THEN ADDREGCANDATE(.LHNODE,.CSTMNT);
END;


GLOBAL ROUTINE STCMAGO=
%(***************************************************************************
	ROUTINE TO COMPUTE THE COMPLEXITY OF AN ASSIGNED GOTO
***************************************************************************)%
BEGIN
	%(***COMPUTE COMPLEXITY OF THE ASSIGNED VAL (MAY BE AN ARRAY-REF***)%
	TREEPTR_.CSTMNT[AGOTOLBL];
	IF .TREEPTR[OPRCLS] EQL DATAOPR
	THEN
	CSTMNT[SRCCMPLX]_0
	ELSE
	CSTMNT[SRCCMPLX]_SETCOMPLEXITY();

	%(***FIND COMPLEXITY OF ANY COMMON SUBEXPRS***)%
	STCMCSB();
END;


GLOBAL ROUTINE STCMCGO=
%(***************************************************************************
	ROUTINE TO COMPUTE COMPLEXITY OF A COMPUTED GOTO
***************************************************************************)%
BEGIN
	%(***CALCULATE THE COMPLEXITY OF THE EXPRESSION TO BE COMPUTED***)%
	TREEPTR_.CSTMNT[CGOTOLBL];
	IF .TREEPTR[OPRCLS] EQL DATAOPR
	THEN
	BEGIN
		IF .TREEPTR[OPR1] EQL CONSTFL THEN ALOCONST(.TREEPTR);
		CSTMNT[SRCCMPLX]_0
	END
	ELSE
	CSTMNT[SRCCMPLX]_SETCOMPLEXITY();

	%(***FIND COMPLEXITY OF ANY COMMON SUBEXPRS***)%
	STCMCSB();
END;

GLOBAL ROUTINE STCMSTOP=
%(***************************************************************************
	ROUTINE TO PERFORM THE COMPLEXITY FOR STOP AND PAUSE.
	THE ARG FOR STOP/PAUSE CAN ONLY BE A VARIABLE OR A CONSTANT OR
	LITERAL (CANNOT BE AN EXPRESSION).
	MUST ALLOCATE THE CONSTANT OR LITERAL IF THERE IS ONE.
***************************************************************************)%
BEGIN
	OWN PEXPRNODE STOPEXPR;

	IF (STOPEXPR_.CSTMNT[STOPIDENT]) NEQ 0
	THEN
	BEGIN
		IF .STOPEXPR[OPR1] EQL CONSTFL
		THEN ALOCONST(.STOPEXPR);
	END;

	CSTMNT[SRCCMPLX]_0;
END;
GLOBAL ROUTINE STCMLIF=
%(***************************************************************************
	ROUTINE TO PERFORM THE COMPLEXITY PASS FOR A LOGICAL IF.
	DETERMINES THE NUMBER OF REGS NECESSARY FOR COMPUTATION OF
	THE LOGICAL EXPRESSION AND FOR THE SUBSTATEMENT AND FOR ANY COMMON SUBEXPRS.
	SETS THE COMPLEXITY OF THE STATEMENT TO THE MAXIMUM OF THESE.
	CALLED WITH THE GLOBAL CSTMNT POINTING TO THE STATEMENT TO BE PROCESSED.
	THIS ROUTINE IS NEVER CALLED RECURSIVELY (SINCE IT IS ILLEGAL TO EMBED
	A LOGICAL IF INSIDE ANOTHER)
***************************************************************************)%
BEGIN
	EXTERNAL CMPLREL,CMPLBL;
	EXTERNAL PAIRMODE;	!GLOBAL THAT GETS SET WHEN PROCESSING A STMNT THAT USES ANY REG PAIRS
	EXTERNAL FNREF;		!GLOBAL THAT GETS SET WHEN PROCESSING A STMNT THAT CONTAINS FN CALLS
	LOCAL CEXPRPAIRMODE;	!VALUE OF "PAIRMODE" FOR THE CONDITIONAL EXPR
				! (TRUE IFF THE COND USES ANY REG PAIRS)
	LOCAL CEXPRFNREF;	!VALUE OF "FNREF" FOR THE CONDITIONAL EXPR (TRUE IFF
				! THERE ARE ANY FN CALLS IN THE CEXPR)
	OWN PEXPRNODE CONDEXPR;
	OWN BASE SAVSTMNT;			!SAVE PTR TO THIS STMNT

	%(***PERFORM COMPLEXITY ANALYSIS ON THE CONDITIONAL EXPR***)%
	CONDEXPR_.CSTMNT[LIFEXPR];
	TREEPTR_.CONDEXPR;

	%(****FOR RELATIONALS AND CONTROL-TYPE BOOLEANS, NEED NEVER COMPUTE A VALUE***)%
	IF .CONDEXPR[VALTYPE] EQL CONTROL
	THEN
	BEGIN
		IF .CONDEXPR[OPRCLS] EQL BOOLEAN
		THEN
		CSTMNT[SRCCMPLX]_CMPLBL()
		ELSE
		IF .CONDEXPR[OPRCLS] EQL RELATIONAL
		THEN
		CSTMNT[SRCCMPLX]_CMPLREL()
		ELSE
		CGERR()
	END

	%(***FOR EXPRESSIONS WHICH DO NOT HAVE VALTYPE CONTROL, WILL COMPUTE A VAL AND TEST IT***)%
	ELSE
	BEGIN
		%(***IF CONDEXPR IS A CONSTANT, THIS STMNT WILL HAVE BEEN FOLDED AWAY IN
			P2SKEL IF P2SKEL IS USED; IF P2SKEL IS NOT USED, A CONSTANT
			CONDEXPR IS ALLOCATED TO CORE****)%
		IF .CONDEXPR[OPR1] EQL CONSTFL THEN ALOCONST(.TREEPTR);
		CSTMNT[SRCCMPLX]_SETCOMPLEXITY();
	END;


	CEXPRPAIRMODE_.PAIRMODE;	!SAVE KNOWLEDGE OF WHETHER THE COND EXPR USED ANY REG PAIRS
	CEXPRFNREF_.FNREF;		!SAVE KNOWLEDGE OF WHETHER THE COND EXPR HAD ANY FN CALLS

	%(***COMPUTE THE COMPLEXITY OF THE SUBSTATEMNT***)%
	SAVSTMNT_.CSTMNT;			!SAVE PTR TO THIS STMNT

	CSTMNT_.CSTMNT[LIFSTATE];

	CMSTMN();

	%(**THE IF STATEMENT REQUIRES AT LEAST AS MANY REGS AS ARE NECESSARY FOR
		COMPUTATION OF THE SUBSTATEMENT***)%
	IF .SAVSTMNT[SRCCMPLX] LSS .CSTMNT[SRCCMPLX]
	THEN
	SAVSTMNT[SRCCMPLX]_.CSTMNT[SRCCMPLX];

	CSTMNT_.SAVSTMNT;			!RESTORE VAL OF CSTMNT

	%(***PERFORM COMPLEXITY ANALYSIS FOR COMMON SUBEXPRS***)%
	STCMCSB();

	PAIRMODE_.PAIRMODE OR .CEXPRPAIRMODE;	!THE IF REQUIRES A REG PAIR IF EITHER THE COND EXPR
					! OR THE SUBSTMNT REQUIRES ONE
	FNREF_.FNREF OR .CEXPRFNREF;	!THE IF STMNT CONTAINS A FN REF IF EITHER THE
				! COND EXPR OR  THE SUBSTMNT DOES


END;



GLOBAL ROUTINE STCMAIF=
%(***************************************************************************
	ROUTINE TO PERFORM THE COMPLEXITY PASS FOR AN ARITHMETIC IF.
	DETERMINES THE NUMBER OF REGS NECESSARY FOR COMPUTATION OF THE
	ARITHMETIC EXPRESSION AND FOR ANY COMMON SUBEXPRESSIONS.
	SETS THE COMPLEXITY OF THE STATEMENT TO THE MAX OF THESE.
	CALLED WITH THE GLOBAL CSTMNT POINTING TO THE STATEMENT FOR
	WHICH ANALYSIS IS TO BE PERFORMED.
***************************************************************************)%
BEGIN
	%(***PERFORM COMPLEXITY ANALYSIS OF THE ARITH EXPR***)%
	TREEPTR_.CSTMNT[AIFEXPR];

	%(***IF THE ARITH EXPR IS A VARIABLE, WILL STILL USE A REG TO HOLD THE VAL***)%
	IF .TREEPTR[OPRCLS] EQL DATAOPR
	THEN
	BEGIN
		SAVREGCONTAINING(.TREEPTR);	!IF BB ALLOCATOR CAN LEAVE THIS VAR IN A
						! REG, HAVE IT DO SO
		%(***IF CONDEXPR IS A CONSTANT, THIS STMNT WILL HAVE BEEN FOLDED AWAY IN 
			P2SKEL IF IT WAS USED; IF P2SKEL NOT USED, A CONSTANT CONDEXPR
			IS ALLOCATED TO CORE****)%
		IF .TREEPTR[OPR1] EQL CONSTFL THEN ALOCONST(.TREEPTR);
		CSTMNT[SRCCMPLX]_1
	END
	ELSE
	CSTMNT[SRCCMPLX]_SETCOMPLEXITY();

	%(***PERFORM COMPLEXITY ANALYSIS FOR ANY COMMON SUBEXPRSSIONS***)%
	IF .CSTMNT[SRCCOMNSUB] NEQ 0
	THEN STCMCSB();
END;


GLOBAL ROUTINE SCMASSI=
%(***************************************************************************
	PERFORM COMPLEXITY ANALYSIS FOR AN ASSIGN STMNT.
***************************************************************************)%
BEGIN
	EXTERNAL CMPLXARRAY;
	TREEPTR_.CSTMNT[ASISYM];

	%(***IF VAR ASSIGNED TO IS AN ARRAYREF, PERFORM COMPLEXITY ANALYSIS ON IT***)%
	IF .TREEPTR[OPRCLS] EQL ARRAYREF
	THEN
	BEGIN
		CSTMNT[SRCCMPLX]_CMPLXARRAY();
		IF .CSTMNT[SRCCMPLX] EQL 0 THEN CSTMNT[SRCCMPLX]_1;
	END
	ELSE
	CSTMNT[SRCCMPLX]_1;
END;




GLOBAL ROUTINE STCMOPEN=
%(***************************************************************************
	TO PERFORM COMPLEXITY PASS FOR AN OPEN STATEMENT.
	MUST ALLOCATE ALL CONSTANTS THAT OCCUR UNDER THIS STMNT.
***************************************************************************)%
BEGIN
	REGISTER PEXPRNODE ARGVAL;	!PTR TO SYMBOL OR CONSTANT TABLE ENTRY
				! FOR THE VALUE TO BE PASSED TO FOROTS
				! FOR A GIVEN ARG
	REGISTER OPENLIST ARVALLST;	!LIST OF ARGS UNDER THIS OPEN STMNT
	OWN CMPLXMAX;	!MAXIMUM COMPLEXITY OF THE ARGS
	ARVALLST_.CSTMNT[OPLST];

	CMPLXMAX_0;

	%(***WALK THRU THE LIST OF ARGS - FOR ANY ARG THAT IS A CONSTANT OR A LITERAL
		ALLOCATE CORE FOR THAT CONSTANT/LITERAL***)%
	INCR I FROM 0 TO (.CSTMNT[OPSIZ]-1)
	DO
	BEGIN
		ARGVAL_.ARVALLST[.I,OPENLPTR];

		IF .ARGVAL EQL 0	!FOR THE PARAM "DIALOG" MAY HAVE
		THEN BEGIN END		! A NULL ARG; DO NOTHING
		ELSE
		IF .ARGVAL[OPRCLS] EQL DATAOPR	!VAL A VAR OR CONST
		THEN
		(IF .ARGVAL[OPR1] EQL CONSTFL THEN ALOCONST(.ARGVAL)) !ALLOCATE CORE FOR A CONST
		ELSE			!VAL AN EXPRESSION (OR ARRAYREF)
		BEGIN
			REGISTER CMPL1;

			%(**PERFORM "COMPLEXITY" PASS OVER THIS EXPRESSION,
				IF ITS COMPLEXITY IS GTR THAN THE MAXIMUM, CHANGE THE MAXIMUM**)%
			TREEPTR_.ARGVAL;
			IF (CMPL1_SETCOMPLEXITY()) GTR .CMPLXMAX
			THEN CMPLXMAX_.CMPL1;
		END;
	END;

	CSTMNT[SRCCMPLX]_.CMPLXMAX;
END;



GLOBAL ROUTINE CMPDECENC=
%(***************************************************************************
	TO PERFORM COMPLEXITY PASS FOR AN ENCODE OR DECODE STMNT.
	THE ENCODE VAR MAY BE AN ARRAY REF THAT NEEDS TO HAVE AN ADDRESS CALC
	PERFORMED.
***************************************************************************)%
BEGIN
	EXTERNAL CMPLXARRAY,TREEPTR;
	OWN CMPL1;
	OWN PEXPRNODE ENCVAR;
	OWN PEXPRNODE ENCCT;

	ENCVAR_.CSTMNT[IOVAR];		!ENCODE/DECODE VARIABLE
	ENCCT_.CSTMNT[IOCNT];		!CHAR CT

	%(***IF CHAR CT IS AN EXPRESSION, PERFORM COMPLEXITY ANALYSIS FOR ITS
		CALCULATION***)%
	IF .ENCCT[OPRCLS] NEQ DATAOPR
	THEN
	BEGIN
		TREEPTR_.ENCCT;
		SETCOMPLEXITY()
	END;


	%(***IF ENCODE/DECODE VARIABLE IS AN ARRAY REF (RATHER  THAN A SYMBOL TABLE
		ENTRY FOR AN ARRAY NAME) - PERFORM COMPLEXITY PASS ON ADDRESS CALCULATION***)%
	IF .ENCVAR[OPRCLS] EQL ARRAYREF
	THEN
	BEGIN
		TREEPTR_.ENCVAR;
		CMPL1_CMPLXARRAY()
	END
	ELSE
	IF .ENCVAR[OPRCLS] EQL DATAOPR
	THEN CMPL1_0
	ELSE CGERR();

	CMPLIOLST();		!PERFORM COMPLEXITY ANALYSIS ON THE IOLIST
				! LEAVE THE STMNT COMPLEXITY FIELD SET TO THE NUMBER
				! OF REGS NECESSARY FOR COMP OF THE IOLIST

	%(***IF THE ADDR CALC FOR THE ENCODE VAR REQUIRES MORE REGS THAN CALC
		OF THE IOLIST DOES, ADJUST THE COMPLEXITY FIELD OF THE STMNT***)%
	IF .CMPL1  GTR .CSTMNT[SRCCMPLX]
	THEN CSTMNT[SRCCMPLX]_.CMPL1;
END;

GLOBAL ROUTINE STCMCSB=
%(***************************************************************************
	ROUTINE TO PERFORM COMPLEXITY ANALYSIS FOR EACH COMMON SUBEXPR UNDER THE NODE
	POINTED TO BY CSTMNT.
	LEAVES THE COMPLEXITY FIELD OF THE STATEMENT SET TO THE MAX OF ITS
	INITIAL VAL AND THE MAX COMPLEXITY OF ANY COMMON SUB
***************************************************************************)%
BEGIN
	OWN CMPLX1;
	REGISTER PEXPRNODE  CCMNSUB;

	CCMNSUB_.CSTMNT[SRCCOMNSUB];

	UNTIL .CCMNSUB EQL 0
	DO
	BEGIN
		IF .CCMNSUB[A2VALFLG]	!IF THIS CSB IS A SINGLE VARIABLE
		THEN
		BEGIN
			SAVREGCONTAINING(.CCMNSUB[ARG2PTR]);	!IF THE CSB COULD HAVE BEEN
							! LEFT IN A REG BY A PREV STMNT, DO LEAVE IT
			ADDREGCANDATE(.CCMNSUB[ARG2PTR],.CCMNSUB);	!IF THIS VAR SHOULD BE NEEDED LATER
							! WILL BE ABLE TO USE IT FROM THE
							! REG WHERE THIS STMNT LEFT IT
			CCMNSUB[COMPLEXITY]_0;
		END

		ELSE		!IF THE CSB IS AN EXPRESSION
		BEGIN
			TREEPTR_.CCMNSUB[ARG2PTR];
			CMPLX1_SETCOMPLEXITY();
			IF .CMPLX1 GTR .CSTMNT[SRCCMPLX]
			THEN CSTMNT[SRCCMPLX]_.CMPLX1;

			CCMNSUB[COMPLEXITY]_.CMPLX1;
		END;

		CCMNSUB_.CCMNSUB[CLINK];
	END;

END;


GLOBAL ROUTINE ALCASMNT=
%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR AN ASSIGNMENT STATEMENT.
	DETECTS OPERATONS OF THE FORM:
		A=A+B+C+...
		A=A*B*C....
	TO BE OPERATIONS TO MEMORY.

	CALLED WITH THE GLOBAL CSTMNT POINTING TO THE STATEMENT NODE FOR
	WHICH ALLOCATION IS TO BE PERFORMED.

	THIS ROUTINE IS NEVER CALLED RECURSIVELY.
***************************************************************************)%
BEGIN
	EXTERNAL FNVALCHK;	!ROUTINE TO CHECK FOR THE CASE OF AN ASSIGNMENT OF A FN VAL
				! DIRECTLY PRECEEDING A RETURN
	OWN PEXPRNODE ARGNODE:LHNODE:RHNODE;
	OWN RA,RB;
	OWN PEXPRNODE SUBNODE;
	OWN RSV;


	%(***TO SET THE REG FOR COMPUTATION OF THE STATEMENT TO THE SAME REG
		INTO WHICH THE RIGHT-HAND SIDE WAS COMPUTED***)%
	MACRO SETREGTORH=
	BEGIN
		CSTMNT[ASMNTREG]_.RHNODE[TARGTAC];
		CSTMNT[A2SAMEFLG]_1;
	END$;



	ROUTINE USEAFREEREG=
	%(*****ROUTINE TO GET A LEGAL REG FOR COMPUTATION OF THE ASSIGNMENT AND
		SET THE REG-TO-BE-USED TO THAT REG*****)%
	BEGIN
		RA_REGTOUSE(.CSTMNT,.RHNODE,.LHNODE,.RA,.STBSYR);
		CSTMNT[ASMNTREG]_.RA;	!SET THE REG TO BE USED FOR THE
						! ASSIGNMENT TO RA
		REGCLOBB(.RA);	!MUST ASSUME THAT PREVIOUS CONTENTS OF
						! RA ARE CLOBBERED. CLEAR BASIC BLOCK ALLOC
						! TABLE ENTRIES FOR RA
		IF .RHNODE[DBLFLG]	!IF THE VAL BEING ASSIGNED USES 2 WDS
		THEN				!MUST ALSO ASSUME THAT THE REG AFTER
		REGCLOBB(.RA+1);	! RA IS CLOBBERED
	END;


	ROUTINE SETREGFORA2VAL=
	%(***ROUTINE TO SET THE "REG FOR COMP" OF THE STMNT WHEN THE RIGHT HAND SIDE IS
		A VARIABLE OR REGCONTENTS (IE WHEN A2VALFLG IS SET)***)%
	BEGIN
		IF .RHNODE[OPRCLS] EQL REGCONTENTS
		THEN
		%(***IF RHS IS A VAR WHICH LIVES IN A REG, WILL USUALLY WANT TO SET
			REG-FOR-COMP OF STMNT TO THAT REG***)%
		BEGIN
			%(***HAVE THE EXCEPTION THAT IF THE RHS IS AN AOBJN WORD
				FOR A LOOP CONTROL, WANT TO USE ONLY THE RIGHT HALF.
				THIS IS A PROBLEM IFF EITHER A2NEGFLG OR A2NOTFLG IS SET,
				IN WHICH AN EXTRA REG WILL BE NEEDED.
			*******)%
			IF .CSTMNT[A2IMMEDFLG] AND 
				(.CSTMNT[A1NEGFLG] OR .CSTMNT[A1NOTFLG]
				OR .CSTMNT[A2NEGFLG] OR .CSTMNT[A2NOTFLG])
			THEN
			USEAFREEREG()
			ELSE
			SETREGTORH
		END
		ELSE
		IF (RB_REGCONTAINING(.RHNODE)) GEQ 0	!IF THE RIGHT HAND SIDE WAS LEFT IN
							! A REG BY AN EARLIER STMNT IN THIS BASIC BLOCK
			AND .CSTMNT[A2NGNTFLGS] EQL 0	!AND THE RHS WILL NOT BE PICKED UP
							! BY A MOVN
		THEN
		BEGIN
			CSTMNT[ASMNTREG]_.RB;	!USE THAT REG FOR THE ASSIGNMENT
			CSTMNT[A2SAMEFLG]_1;	!NEED NOT RELOAD THE REG
			CSTMNT[A2IMMEDFLG]_0;	!IF THE RHS WAS PREVIOUSLY AN IMMED CONST, WOULD
						! HAVE HAD THIS FLAG SET. MUST BE CAREFUL
						! TO TURN IT OFF BECAUSE THE ONLY PLACE THAT
						! WE CAN HAVE "A2SAMEFLG" AND "A2IMMEDFLG"
						! BOTH SET IS FOR RHS AN AOBJN REG
			REGCLOBB(.RB);		!DELETE THE PREVIOUS ENTRY IN THE "REGSTATE"
						! TABLE FOR RB (SINCE WE CAN ONLY REMEMBER
						! A MAX OF 2 VARS PER REG)
		END
		ELSE
		%(***IF RHS IS A VARIABLE WHICH DOES NOT LIVE IN A REG, SET REG
			FOR COMP OF STMNT TO RA****)%
		USEAFREEREG()
	END;






	FNVALCHK();	!IF LHS OF THIS STMNT IS THE FN ENTRY NAME (IE IS THE VAL TO BE RETURNED)
			! AND THE NEXT STMNT IS A RETURN, SUBSTITUTE A REGCONTENTS 0 FOR THE LHS

	RHNODE_.CSTMNT[RHEXP];
	LHNODE_.CSTMNT[LHEXP];


	%(****PERFORM REGISTER ALLOCATION FOR THE COMMON SUBEXPRS UNDER THIS STMNT.****)%
	DBLMODE_FALSE;
	ALCCMNSB();


	%(***IF THIS STATEMENT IS DOUBLE-PREC, ADJUST SET OF BUSY REGS SO
		THAT ONLY EVEN REGS WILL BE ALLOCATED****)%
	IF .RHNODE[DBLFLG]
	THEN
	BEGIN
		STBSYR_DPBSYREGS(.STBSYR);
		STRGCT_ONESCOUNT(.STBSYR);
		DBLMODE_TRUE;
	END
	ELSE DBLMODE_FALSE;








	%(****IF THE LEFT-HAND SIDE OF THE ASSIGNMENT IS A VARIABLE THAT WAS ALLOCATED
		TO LIVE IN A REGISTER, WILL PROCESS THE RIGHT-HAND SIDE IN A SPECIAL
		MANNER*****)%
	IF .LHNODE[OPRCLS] EQL REGCONTENTS
	THEN
	BEGIN
		IF .CSTMNT[MEMCMPFLG]
		THEN
		BEGIN
			CSTMNT[MEMCMPFLG]_0;	!IF IN P2SKEL HAD DECIDED TO PERFORM THIS
						! OP TO MEMORY - UNDO THAT DECISION
			RHNODE[MEMCMPFLG]_0;
			CSTMNT[OPTOBOTHFLG]_0;	! (ALSO UNDO DECISION TO DO OP "TO BOTH")
			RHNODE[OPTOBOTHFLG]_0;
		END;
		IF LHINREGALC() THEN RETURN;
	END;


	%(***IF THE RIGHT-HAND SIDE IS TO BE COMPUTED DIRECTLY TO MEMORY*****)%
	IF .CSTMNT[MEMCMPFLG]
	THEN
	BEGIN
		ALCMEMCMP();
		RETURN;
	END;


	RA_AFREEREG(.STBSYR,.CSTMNT[SRCSAVREGFLG],.LHNODE[DBLFLG]);

	%(***IF RIGHT HAND SIDE IS AN EXPRESSION WHOSE VAL MUST BE NEGATED BY AN EXTRA MOVN
		(IE IT  IS NOT A DATA ITEM OR ARRAYREF THAT WOULD HAVE TO BE PICKED UP ANYWAY)
		OR IF LEFT HAND SIDE IS AN ARRAYREF (AND HENCE THERE IS NO VALUE IN
		LEAVING ITS VAL IN A REG FOR FUTURE USES) AND THE RHS IS A SIMPLE
		VAR (AND HENCE ITS VAL MIGHT BE USEFUL IN A REG)
		SHOULD DO THE NEGATE AS A PART OF THE STORE OPERATION
		HENCE IN THESE CASES SHOULD PUT NEG (AND NOT) FLAGS OVER LEFT
		RATHER THAN RIGHT HAND SIDE***)%
	IF (.RHNODE[OPRCLS] NEQ DATAOPR AND .RHNODE[OPRCLS] NEQ ARRAYREF)
		OR
			( NOT .CSTMNT[A1VALFLG]
			 AND .CSTMNT[A2VALFLG]		!AND RHS IS A SIMPLE VAR
							! (NB FOR A(I)=-A(I)
							! WANT TO CREATE THE PEEPHOLE
							! MOVN, MOVEM)
			AND NOT (.RHNODE[OPERATOR] EQL INTCONST
				AND .RHNODE[CONST2] EQL 1)	!AND RHS IS NOT INTEGER 1
							! (BECAUSE WE WANT TO GET THE
							! MOVNI 1, MOVEM PEEPHOLE)
			)

	THEN
	BEGIN
		CSTMNT[A1NEGFLG]_.CSTMNT[A2NEGFLG];	!(A1NEGFLG WOULD NOT HAVE PREVIOUSLY BEEN SET)
		CSTMNT[A1NOTFLG]_.CSTMNT[A2NOTFLG];
		CSTMNT[A2NEGFLG]_0;
		CSTMNT[A2NOTFLG]_0;
	END;



	%(***IF LEFT HAND SIDE OF STATEMENT IS A SIMPLE VARIABLE, PERFORM REGISTER
		ALLOCATION FOR THE RIGHT HAND SIDE****)%

	IF .CSTMNT[A1VALFLG]
	THEN
	BEGIN
		IF .CSTMNT[A2VALFLG]
		THEN
		%(***IF RIGHT-HAND SIDE IS ALSO A SIMPLE VARIABLE***)%
		SETREGFORA2VAL()
		ELSE
		BEGIN
			TREEPTR_.RHNODE;

			%(***IF THERE ARE NO REFERENCES TO THE LHS WITHIN THE EXPRESSION
				ON THE RHS AND THE RHS IS NOT AN ARRAYREF,
				AND THE NEG AND NOT FLAGS IN THE STATEMENT ARE BOTH 0,
				 ALLOCATE THE RHS TO BE COMPUTED TO THE
				VARIABLE ON THE LHS*******)%
			IF NOT .RHNODE[RESRFFLG] AND (NOT .RHNODE[OPRCLS] EQL ARRAYREF)
	!**;[471], ALCASMNT @4344, DCE, 5-OCT-76
	!**;[471], IF LHS OF ASSIGNMENT STMNT IS A LOGICAL VARIABLE,
	!**;[471], AND IT IS IN COMMON OR EQUIVALENCED, THEN IT COULD
	!**;[471], BE NEEDED FOR EVALUATION OF RHS, SO PREVENT EARLY
	!**;[471], INITIALIZATION OF LHS TO -1
	%[471]%			AND NOT(.LHNODE[VALTYPE] EQL LOGICAL
	%[471]%				AND (.LHNODE[IDATTRIBUT(INEQV)] OR
	%[471]%				.LHNODE[IDATTRIBUT(INCOM)]))
				AND (NOT .LHNODE[OPRCLS] EQL REGCONTENTS)
				AND (.CSTMNT[A2NGNTFLGS] EQL 0)
				AND (.CSTMNT[A1NGNTFLGS] EQL 0)
			THEN
			BEGIN
				ALCINTMP(.LHNODE,.STBSYR,.STRGCT);
				IF .RHNODE[TARGTMEM] EQL .LHNODE
				THEN
				%(***IF COULD COMPUTE RHS DIRECTLY TO LHS***)%
				BEGIN
					CSTMNT[MEMCMPFLG]_1;
					VARCLOBB(.LHNODE);	!THE VAL OF THE VAR ON LHS HAS BEEN
								! MODIFIED, CLEAR
								! ANY BB ALLOC ENTRIES THAT REFER
								! TO THAT VAR
					IF .CSTMNT[SRCSAVREGFLG]	!IF VAL OF LHS VAR IS USEFUL TO LEAVE
									! IN A REG
						AND .RHNODE[STOREFLG]	!AND RHS WAS COMPUTED INTO A REG
									! AND THEN STORED INTO LHS VAR
					THEN
					SAVEREG(.RHNODE[TARGTAC],	!REMEMBER THAT LHS VAR
						.LHNODE,0,.CSTMNT[SRCSONNXTUSE]);	!IS IN THAT REG
					RETURN;
				END;
			END

			ELSE
			%(***OTHERWISE, ALLOCATE THE RHS TO BE COMPUTED TO THE REG RA***)%
			ALCINREG(.RA,.STBSYR,.STRGCT);

			%(***DETERMINE REG FOR COMPUTATION OF THE STMNT***)%
			IF .CSTMNT[ALCRETREGFLG]
			THEN
			%(***IF REG FOR COMPUTATION OF STMNT HAS ALREADY BEEN DETERMINED TO
				BE THE FN-RETURN REG****)%
			BEGIN  END
			ELSE
			IF .RHNODE[INREGFLG]
			THEN
			%(***IF RHS IS COMPUTED INTO A REG, USE THAT REG AS REG FOR COMP FOR STMNT***)%
			SETREGTORH
			ELSE
			%(***OTHERWISE USE SOME FREE REG***)%
			USEAFREEREG()
		END;

		VARCLOBB(.LHNODE);	!THE VAL OF THE VAR ON THE LHS HAS BEEN MODIFIED
					! CLEAR ANY BB ALLOC ENTRIES THAT REFER TO IT

		IF .CSTMNT[SRCSAVREGFLG]	!IF VAL OF EITHER VAR ON LHS OR RHS IS OF FUTURE USE
						! TO HAVE IN A REG
			AND .CSTMNT[A1NGNTFLGS] EQL 0	!AND VAL WILL NOT BE STORED WITH "MOVNM"
			AND NOT(.CSTMNT[A2IMMEDFLG] AND .CSTMNT[A2SAMEFLG])	!AND VAL WILL NOT BE STORED
								! WITH "HRRZM" (DUE TO RHS BEING
								! RIGHT HALF OF AOBJN WD)
		THEN
		SAVEREG(.CSTMNT[ASMNTREG],	!REMEMBER THAT REG USED CONTAINS
			.LHNODE,		! VAL OF VAR ON LHS
			(IF .RHNODE[OPRCLS] EQL DATAOPR 	!AND IF RHS IS A VAR
				AND .CSTMNT[A2NGNTFLGS] EQL 0	! AND WAS NOT PICKED UP WITH "MOVN"
				AND NOT (.CSTMNT[A1NEGFLG] AND
					 .LHNODE[VALTYPE] EQL DOUBLPREC)	!AND DONT HAVE TO NEGATE A DP VAL (THERE IS NO MOVNM FOR DP)
			THEN .RHNODE		! IT ALSO CONTAINS VAL OF VAR ON RHS
			ELSE 0),
			.CSTMNT[SRCSONNXTUSE]);	! AND THE NEXT USE OF THAT VAR WAS
						! POINTED TO BY THE ASSIGNMNT STMNT
		RETURN

	END;




	%(***IF LEFT-HAND SIDE IS NOT A SIMPLE VARIABLE, IT MUST BE AN ARRAY****)%
	IF .LHNODE[OPRCLS] NEQ ARRAYREF
	THEN CGERR();


	%(****IF RIGHT HAND SIDE IS A SIMPLE VARIABLE, PERFORM REGISTER ALLOCATION FOR
		LEFT HAND SIDE*******)%

	IF .CSTMNT[A2VALFLG]
	THEN
	BEGIN
		TREEPTR_.LHNODE;
		ALCARRAY(.STBSYR,.STRGCT);

		%(***GET REG FOR COMP FOR STMNT- DO NOT USE THE REG IN WHICH THE
			INDEX INTO THE ARRAY WAS LEFT***)%
		IF .LHNODE[TARGXF] NEQ 0
		THEN
		BEGIN
			 STBSYR_CLRBIT(.STBSYR,.LHNODE[TARGXF] );
			IF .LHNODE[DBLFLG]	!IF A 2 WD VAL IS TO BE STORED
			THEN		! THEN IF THE INDEX WAS IN AN ODD REG, MUST NOT
			STBSYR_CLRBIT(.STBSYR,.LHNODE[TARGXF]-1)	!USE THE PRECEEDING EVEN
					! REG (IF INDEX IN AN EVEN REG, THEN PRECEEDING REG
					! IS ALREADY OUT OF THE SET BECAUSE IT IS ODD)
		END;

		RA_AFREEREG(.STBSYR,.CSTMNT[SRCSAVREGFLG],.LHNODE[DBLFLG]);

		%(***DECIDE WHICH REG TO COMPUTE THE STMNT IN (GIVEN THAT A2VALFLG WAS SET)***)%
		SETREGFORA2VAL();

		VARCLOBB(.LHNODE);	!IF THE ARRAY ON LHS IS IN COMMON OR EQV MUST
					! ASSUME THAT VARS IN COMMON/EQV ARE CLOBBERED

		IF .CSTMNT[SRCSAVREGFLG]	!IF VAR ON RHS IS USEFUL TO LEAVE IN A REG
			AND  .CSTMNT[A2NGNTFLGS] EQL 0	! AND WAS NOT PICKED UP WITH "MOVN"
			AND .RHNODE[OPRCLS] EQL DATAOPR	! AND WAS NOT REPLACED BY A "REGCONTENTS"
			AND NOT (.CSTMNT[A1NEGFLG] AND
				 .LHNODE[VALTYPE] EQL DOUBLPREC)	!AND DONT HAVE TO NEGATE A DP VAL (THERE IS NO MOVNM FOR DP)
		THEN SAVEREG(.CSTMNT[ASMNTREG],		!REMEMBER TAHT REG USED FOR ASSIGNMNET
			.RHNODE,0,.CSTMNT[SRCSONNXTUSE]);	! CONTAINS VAR ON RHS


		RETURN;
	END;


	%(***IF COMPUTATION OF THE RHS WILL CLOBBER ALL REGISTERS AVAILABLE, THEN
		SHOULD ALWAYS COMPUTE RHS BEFORE COMPUTING LHS, SO THAT
		DO NOT NEED TO LEAVE PTR TO LHS IN A TEMPORARY***)%
	IF .RHNODE[COMPLEXITY] GEQ .STRGCT
	THEN CSTMNT[RVRSFLG]_1;




	%(***IF RIGHT HAND SIDE IS COMPUTED BEFORE ADDRESS CALC FOR LEFT HAND SIDE****)%

	IF .CSTMNT[RVRSFLG]
	THEN
	BEGIN
		IF .LHNODE[COMPLEXITY] LSS .STRGCT
		THEN
		%(***IF ADDRESS CALCULATION CAN BE PERFORMED WITHOUT CLOBBERING
			THE REG IN WHICH RIGHT-HAND-SIDE VAL IS LEFT***)%
		BEGIN
			TREEPTR_.RHNODE;
			ALCINREG(.RA,.STBSYR,.STRGCT);

			%(***DETERMINE WHICH (IF ANY) REG MUST BE SAVED WHILE COMPUTING
				THE LHS BECAUSE IT HOLDS EITHER THE VAL OR A PTR TO THE
				VAL OF THE RIGHT-HAND-SIDE***)%
			RSV_RGTOSAVE(.RHNODE);
			IF .RSV NEQ -1
			THEN
			BEGIN
				%(***IF SOME REG MUST BE SAVED, ADJUST SET OF BUSY REGS***)%
				STBSYR_CLRBIT(.STBSYR,.RSV);
				STRGCT_.STRGCT-1;
			END;

			TREEPTR_.LHNODE;
			ALCARRAY(.STBSYR,.STRGCT);
			IF .RHNODE[INREGFLG]
			THEN
			SETREGTORH
			ELSE
			USEAFREEREG()
		END
		ELSE
		BEGIN
			TREEPTR_.RHNODE;
			ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.STBSYR,.STRGCT);
			TREEPTR_.LHNODE;
			ALCARRAY(.STBSYR,.STRGCT);
			USEAFREEREG()
		END;

	END

	ELSE

	%(****IF ADDRESS CALC FOR LEFT-HAND SIDE IS PERFORMED BEFORE RIGHT-HAND SIDE IS COMPUTED***)%

	BEGIN
!**;[503] Insert @ line 4523 in ALCASMNT	JNG	26-Oct-76
%[503]%		%(***IF LH'S SUBSCRIPT IS A VARIABLE (LEAF) AND THE RH
[503]			CONTAINS SOME FUNCTION CALLS, THEN WE MUST CLEAR
[503]			THE MEMORY OF AC 1, SO ALCARRAY WON'T TRY TO
[503]			LEAVE THE SUBSCRIPT IN AC 1 IF ITS ALREADY
[503]			THERE (ALCARRAY NEVER LEAVES IT IN AC 0)***)%
%[503]%		IF .LHNODE[A2VALFLG] AND .RHNODE[FNCALLSFLG]
%[503]%		THEN REGCLOBB(1);
%[503]%
		%(***CAN ASSUME THAT THE COMPUTATION OF RHS WILL NOT CLOBBER
			THE PTR TO LHS****)%

		%(***PERFORM REG ALLOC FOR COMPUTATION OF THE ADDRESS OF THE LHS***)%
		TREEPTR_.LHNODE;
		ALCARRAY(.STBSYR,.STRGCT);

		%(***IF PTR TO LEFT-HAND-SIDE IS LEFT IN A REG, DO NOT USE THAT REG IN
			COMPUTATION OF RIGHT-HAND-SIDE***)%
		IF .LHNODE[TARGXF] NEQ 0
		THEN
		BEGIN
			STBSYR_CLRBIT(.STBSYR,.LHNODE[TARGXF]);
			IF .LHNODE[DBLFLG]	!IF A 2 WD VAL IS TO BE STORED
			THEN		! THEN IF THE INDEX WAS IN AN ODD REG, MUST NOT
			STBSYR_CLRBIT(.STBSYR,.LHNODE[TARGXF]-1);	!USE THE PRECEEDING EVEN
					! REG (IF INDEX IN AN EVEN REG, THEN PRECEEDING REG
					! IS ALREADY OUT OF THE SET BECAUSE IT IS ODD)
			STRGCT_.STRGCT-1;
		END;

		%(***PERFORM REGISTER ALLOC FOR THE COMPUTATION OF THE RHS***)%
		RA_AFREEREG(.STBSYR,FALSE,.LHNODE[DBLFLG]);
		TREEPTR_.RHNODE;

		ALCINREG(.RA,.STBSYR,.STRGCT);

		IF .RHNODE[INREGFLG]
		THEN
		SETREGTORH
		ELSE
		USEAFREEREG()
	END;

	VARCLOBB(.LHNODE);	!ASSUME VAL OF LHS IS CLOBBERED
END;	!END OF ROUTINE "ALCASMNT"


	




GLOBAL ROUTINE ALCMEMCMP=
%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR AN ASSIGNMENT STMNT TO BE
	PERFORMED DIRECTLY TO MEMORY. IT IS ASSUMED THAT IF THE
	OPERATION HAS 2 ARGS (IE IS EITHER A BOOLEAN OR ARITHMETIC) THEN  ARG2 UNDER
	THE RIGHT HAND SIDE IS EQUAL TO THE LEFT HAND SIDE.
	CALLED WITH THE GLOBAL CSTMNT POINTING TO THE ASSIGNMENT STMNT.
***************************************************************************)%
BEGIN
	EXTERNAL CLOBBNX;
	OWN PEXPRNODE RHNODE:LHNODE:ARG1NODE:ARG2NODE;
	EXTERNAL GETRGPAIR;	!ROUTINE TO GET A PAIR OF FREE REGISTERS
	OWN RA,RB;
	EXTERNAL EXCHARGS;

	RHNODE_.CSTMNT[RHEXP];
	LHNODE_.CSTMNT[LHEXP];
	ARG1NODE_.RHNODE[ARG1PTR];
	ARG2NODE_.RHNODE[ARG2PTR];
	RA_AFREEREG(.STBSYR,.CSTMNT[SRCSAVREGFLG],.LHNODE[DBLFLG]);

	IF CLOBBNX(.RHNODE)	!IF THIS OPERATION CLOBBERS THE REG AFTER THE
				! REG ON WHICH IT IS PERFORMED (IE INTEGER DIVIDE)
		AND .RHNODE[OPTOBOTHFLG]	! AND WE WILL BE GENERATING AN OP-TO-BOTH
				! (RATHER THAN TO MEMORY - SINCE OPS TO MEM DONT CLOBBER THAT REG)
	THEN
	RA_GETRGPAIR(.RA,.STBSYR);	!GET A REG TO USE THAT DOES NOT HAVE A USEFUL VAL
				! IN THE REG FOLLOWING

	%(***FOR P2PL1MUL,SQUARE, AND CUBE - THE ARG THAT IS EQL TO THE LEFT HAND
		SIDE IS ARG1 (AND THIS IS THE ONLY ARG). HENCE DONT HAVE TO
		WORRY ABOUT ALLOCATING THE OTHER ARG***)%
	IF .RHNODE[OPRCLS] EQL SPECOP
	THEN
	BEGIN
		RA_RGTOU1(.RHNODE,.RHNODE[ARG1PTR],.RA,.STBSYR);
		SETTAC(.RHNODE,.RA)
	END

	%(***FOR ARITHMETIC AND BOOLEAN OPERATORS***********)%

	ELSE
	BEGIN

		%(***FOR ARITH OPS, CANNOT HAVE NEG ON ARG2. REMOVE A2NEGFLG BY
			A+(-B)=A-B,  A*(-B)=-A*B, A/(-B)=(-A)/B
			 SINCE REMOVING NEG FROM ARG2 MAY CHANGE "A1NEGFLG" MUST DO IT BEFORE
			DECIDE WHETHER CAN USE ARG1 DIRECTLY FROM A GIVEN REG.***)%
		IF .RHNODE[A2NEGFLG] AND .RHNODE[OPRCLS] EQL ARITHMETIC
		THEN
		BEGIN
			IF ADDORSUB(RHNODE)	!MAKE ADD INTO SUB, SUB INTO ADD
			THEN CMPLSP(RHNODE)
			ELSE IF MULORDIV(RHNODE)	!FOR MUL, DIV
			THEN RHNODE[A1NEGFLG]_NOT.RHNODE[A1NEGFLG]	!REVERSE THE NEG ON ARG1
			ELSE CGERR();	!OPS TO MEM CANNOT BE EXPONEN
			RHNODE[A2NEGFLG]_0;
		END;

		%(****PERFORM REGISTER ALLOCATION FOR ARG1 UNDER THE RIGHT HAND SIDE****)%
		IF .RHNODE[A1VALFLG]
		THEN
		BEGIN
			%(***IF ARG1 IS A REGCONTENTS NODE THEN
				1. IF ONLY WANT TO USE THE RIGHT HALF OF TH REG
					THEN MUST MOVE IT INTO RA
				2. IF THE OPERATION CLOBBERS THE REG USED
					THEN MUST MOVE IT TO RA
				3. OTHERWISE, USE THAT REGISTER AS REGFORCOMP
					FOR RHNODE
			********)%
			IF .ARG1NODE[OPRCLS] EQL REGCONTENTS AND NOT .RHNODE[A1IMMEDFLG]
				AND NOT .RHNODE[A1NEGFLG] AND NOT .RHNODE[A1NOTFLG]
				!(DOUBLE-PREC AND COMPLEX OPS TO MEMORY  CLOBBER THE REG)
				AND NOT .RHNODE[DBLFLG]
			THEN
			BEGIN
				RHNODE[TARGTAC]_.ARG1NODE[TARGTAC];
				RHNODE[A1SAMEFLG]_1;
			END

			ELSE
			IF (RB_REGCONTAINING(.ARG1NODE)) GEQ 0	!IF ARG1 WAS LEFT IN A REG
			THEN					! EARLIER IN THIS BB
			BEGIN
				IF .RHNODE[A1NGNTFLGS] NEQ 0	!IF ARG1 MUST BE NEGATED/COMPLEMENTED
					AND NOT BITSET (.STBSYR,.RB)	! AND WE CANNOT CLOBBER RB
				THEN				! MUST NOT USE RB
				SETTAC(.RHNODE,.RA)	!USE RA
				ELSE
				BEGIN
					SETTAC(.RHNODE,.RB);	!USE THAT REG FOR THIS OP TO MEMORY
					RHNODE[A1SAMEFLG]_1;	!DONT RELOAD THE REG
				END
			END

			%(***IF ARG1 IS A SCALAR, USE RA***)%
			ELSE
			SETTAC(.RHNODE,.RA);


			IF .RHNODE[SAVREGFLG]	!IF VAL OF ARG1 WILL BE USEFUL TO HAVE IN A REG LATER
				AND .ARG1NODE[OPRCLS] EQL DATAOPR
				AND NOT .RHNODE[DBLFLG]	! AND THE OPERATION IS NOT DP OR COMPLEX (WHICH
							! OPS CLOBBER THE REG USED FOR THE OP TO MEMORY)
				AND NOT .RHNODE[OPTOBOTHFLG]	!AND WE HAVE NOT ALREADY DECIDED
							! TO PERFORM THE OPERATION TO BOTH
	!**;[363], ALCMEMCMP @4674, DCE, 30-MAR-76
	!**;[363], TEST FOR NOT ON PARENT NODE TOO!
	%[363]%			AND NOT .RHNODE[A1NOTFLG]
				AND NOT .RHNODE[A1NEGFLG]	!AND ARG1 WAS NOT PICKED UP BY "MOVN"
			THEN SAVEREG(.RHNODE[TARGTAC],	!REMEMBER THAT THE REG USED
				.ARG1NODE,0,.RHNODE[SONNXTUSE]);	!CONTAINS VAL OF ARG1
		END
		ELSE
		BEGIN
			TREEPTR_.RHNODE[ARG1PTR];
			ALCINREG(.RA,.STBSYR,.STRGCT);
			IF .RHNODE[ALCRETREGFLG]
			THEN
			%(***IF WE DECIDED ON THE COMPLEXITY-PASS TO USE THE FN-RETURN REGISTER
				FOR COMPUTATION OF RHNODE*****)%
			BEGIN END
			ELSE
			IF .ARG1NODE[INREGFLG] AND NOT .ARG1NODE[ALCRETREGFLG]
			THEN
			%(***IF THE LEFT-ARGUMENT OF RHNODE HAD ITS VAL LEFT IN A REG****)%
			BEGIN
				RHNODE[TARGTAC]_.ARG1NODE[TARGTAC];
				RHNODE[A1SAMEFLG]_1;
			END
			ELSE
			%(***OTHERWISE USE RA TO COMPUTE RHNODE****)%
			BEGIN
				RA_REGTOUSE(.RHNODE,.RHNODE[ARG1PTR],.RHNODE[ARG2PTR],.RA,.STBSYR);
				SETTAC(.RHNODE,.RA)
			END
		END;
	END;


	%(***IF THIS OPERATION IS MOST OPTIMALLY PERFORMED FROM A REG
		THAT WE CANNOT CLOBBER, THEN WE CANNOT DO IT "TO BOTH"***)%
	IF .RHNODE[OPTOBOTHFLG]
	THEN
	BEGIN
		IF NOT BITSET(.STBSYR,.RHNODE[TARGTAC])	!IF THE REG USED CANNOT BE CLOBBERED
			OR
			(CLOBBNX(.RHNODE)		!OR IF THIS OPERATION WILL CLOBBER
							! THE REG FOLLOWING THE REG USED
			 AND NOT BITSET(.STBSYR,.RHNODE[TARGTAC]+1)	! AND THAT REG CANNOT BE CLOBBERED
			)
		THEN
		(CSTMNT[OPTOBOTHFLG]_0;RHNODE[OPTOBOTHFLG]_0);	!TURN OFF FLAGS FOR
							! "PERFORM OP TO BOTH"
	END;



	%(***IF THE ELEMENT ON THE LHS (WHICH IS ALSO ARG2 UNDER THE RHS) IS
		AN ARRAY REF, PERFORM ALLOC FOR THOSE 2 NODES***)%
	IF NOT .CSTMNT[A1VALFLG]
	THEN
	BEGIN
		OWN BSYRG1;
		RA_.RHNODE[TARGTAC];
		BSYRG1_CLRBIT(.STBSYR,.RA);	!WHEN COMPUTING THE SS DO NOT USE
						! THE REG USED FOR THE OPERATION TO MEM

		TREEPTR_.LHNODE;
		IF .TREEPTR[OPRCLS] NEQ ARRAYREF THEN CGERR();
		ALCARRAY(.BSYRG1,.STRGCT-1);
		TREEPTR_(IF .RHNODE[OPRCLS] EQL SPECOP THEN .RHNODE[ARG1PTR] ELSE .RHNODE[ARG2PTR]);
		IF .TREEPTR[OPRCLS] NEQ ARRAYREF THEN CGERR();
		ALCARRAY(.BSYRG1,.STRGCT-1);
		%(***THE FIRST COMPUTATION TO PERFORM SHOULD ALWAYS BE
			THAT OF ARG1 UNDER THE RIGHT-HAND SIDE***)%
		CSTMNT[RVRSFLG]_1;
		RHNODE[RVRSFLG]_0;
	END;

	RHNODE[A2SAMEFLG]_1;		!WILL COMPUTE INTO THE LOC CONTAING ARG2
	RHNODE[MEMCMPFLG]_1;
	VARCLOBB(.LHNODE);	!THE VAL OF THE VAR ON THE LHS OF THIS ASSIGNMENT STMNT
				! HAS NOW BEEN MODIFIED. MUST CLEAR ANY BB ALLOC
				! TABLE ENTRIES THAT REFER TO THAT VAR

	IF .CSTMNT[SRCSAVREGFLG]	!IF THE LHS OF THIS ASSIGNMENT WILL BE
				! USEFUL TO HAVE IN A REG LATER
	   AND .CSTMNT[OPTOBOTHFLG]	! AND THIS OPERATION IS PERFORMED "TO BOTH"
	THEN SAVEREG(.RHNODE[TARGTAC],	!THEN REMEMBER THAT THE REG USED FOR THIS OP
		.LHNODE,0,.CSTMNT[SRCSONNXTUSE]);	! CONTAINS THE VAL OF THE VAR ON THE LHS
END;	!END OF ROUTINE ALCMEMCMP



GLOBAL ROUTINE ORDERMEMCMP=
%(***************************************************************************
	ROUTINE TO ORDER ARGS OF AN ARITH OR BOOLEAN OP TO MEMORY SO THAT
	ARG2 IS IDENTICAL TO THE LHS OF THE ASSIGNMENT STMNT
	BE PERFORMED TO MEMORY.
***************************************************************************)%
BEGIN
	OWN PEXPRNODE RHNODE:LHNODE:ARG1NODE:ARG2NODE;
	EXTERNAL EXCHARGS;	!ROUTINE TO EXCHANGE ARG1 AND ARG2 OF AN OPERATOR
				! IF POSSIBLE

	ROUTINE ARREQLLH(NODE)=
	%(***TO DETERMINE IF 'NODE' IS AN ARRAYREF THAT IS IDENTICAL TO AN ARRAYREF
		ON THE LEFT-HAND-SIDE OF THIS ASSIGNMENT STMNT***)%
	BEGIN
		MAP PEXPRNODE NODE;
		IF .NODE[ARGWD] EQL .LHNODE[ARGWD]	!IF ARRAY NAME AND VARIABLE PART
							! OF SS EXPR ARE IDENTICAL
		THEN
		RETURN (.NODE[TARGET] EQL .LHNODE[TARGET] AND .NODE[OPRCLS] EQL ARRAYREF)
		ELSE RETURN FALSE
	END;


	RHNODE_.CSTMNT[RHEXP];
	LHNODE_.CSTMNT[LHEXP];
	ARG1NODE_.RHNODE[ARG1PTR];
	ARG2NODE_.RHNODE[ARG2PTR];



	%(***MUST BE SURE THAT THE ARG UNDER RHNODE WHICH IS EQUAL TO THE LEFT-HAND SIDE
		IS THE 2ND ARG (ARGS MAY HAVE BEEN REVERSED SOMETIME SINCE P2SKEL)***)%
	IF .CSTMNT[A1VALFLG]
	THEN
	BEGIN
		IF .ARG2NODE NEQ .LHNODE
		THEN
		BEGIN
			IF .ARG1NODE NEQ .LHNODE THEN CGERR();

			IF NOT EXCHARGS(.RHNODE) THEN CGERR();

			ARG1NODE_.RHNODE[ARG1PTR];
			ARG2NODE_.RHNODE[ARG2PTR];
		END
	END

	ELSE
	%(***FOR THE LEFT HAND SIDE AN ARRAYREF***)%
	IF .LHNODE[OPRCLS] EQL ARRAYREF
	THEN
	BEGIN
		IF NOT ARREQLLH(.ARG2NODE)
		THEN
		%(***IF ARG2 IS NOT EQUAL TO LHS***)%
		BEGIN
			%(***IF NEITHER ARG UNDER RHNODE WAS EQL TO LHNODE, SHOULD
				NOT HAVE CALLED THIS ROUTINE***)%
			IF NOT ARREQLLH(.ARG1NODE) THEN CGERR();

			%(***IF ARG1 AND ARG2 CANNOT BE SWAPPED, THEN COULD NEVER
				HAVE HAD THEM REVERSED EARLIER(IN P2SKEL WHEN DETECTED
				THIS COMP TO MEMORY) - HENCE HAVE A COMPILER BUG***)%
			IF NOT EXCHARGS(.RHNODE) THEN CGERR();

			%(***HAVE NOW SWITCHED THE ARGS (EXCHARGS DOES THIS)***)%
			ARG1NODE_.RHNODE[ARG1PTR];
			ARG2NODE_.RHNODE[ARG2PTR];
		END
	END;
END;	!END OF ROUTINE ORDERMEMCMP

GLOBAL ROUTINE ALCASSI=
%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR AN ASSIGN STATEMENT.
	IF VAR ASSIGNED TO IS AN ARRAYREF, MUST PERFORM ALLOC FOR IT.
	THE "ASSIGN" OPERATION IS ALWAYS PERFORMED IN REGISTER 1.
***************************************************************************)%
BEGIN
	TREEPTR_.CSTMNT[ASISYM];

	IF .TREEPTR[OPRCLS] EQL ARRAYREF
	THEN
	ALCARRAY(.STBSYR,.STRGCT);

	REGCLOBB(1);	!THE CONTENTS OF REG 1 WILL BE CLOBBERED BY EVAL
			! OF THIS STMNT. CLEAR BB ALLOC TABLE ENTRY FOR REG 1
	VARCLOBB(.CSTMNT[ASISYM]);	!THE VARIABLE ASSIGNED HAS HAD ITS VAL MODIFIED.
					! CLEAR ANY BB ALLOC ENTRIES THAT REFER TO THAT VAR
END;

GLOBAL ROUTINE ALCCALL=
%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR A CALL STMNT.
***************************************************************************)%
BEGIN
	EXTERNAL CLOBBREGS;	!WD CONTAINING BIT PTN FOR REGS CLOBBERED
				! BY THIS ROUTINE
	EXTERNAL ALCFNARGS;
	REGISTER PEXPRNODE SYMPTR;	!PTR TO SYMBOL TABLE ENTRY FOR THE
					! SUBROUTINE NAME

	ALCCMNSB();	!PERFORM ALLOCATION FOR ANY COMMON SUBS

	IF .CSTMNT[CALLIST] NEQ 0
	THEN
	BEGIN
		TREEPTR_.CSTMNT[CALLIST];
		ALCFNARGS(.STBSYR,.STRGCT,FALSE);
	END;

	%(**THE SUBROUTINE CALLED CAN POTENTIALLY CLOBBER ALL THE REGS,
		(UNLESS IT'S A LIBRARY SUBROUTINE SUCH AS "ADJ1.")
		HENCE IF THIS IS A FN IT WILL HAVE TO SAVE/RESTORE THEM ALL**)%
	SYMPTR_.CSTMNT[CALSYM];	!SYM TABLE ENTRY FOR ROUTINE NAME
	IF NOT .SYMPTR[IDLIBFNFLG]	!IF THE ROUTINE IS NOT A LIBRARY ROUTINE
	THEN
	CLOBBREGS_.CLOBBREGS OR #177760000000	!SET BITS FOR REGS 2-15
END;

GLOBAL ROUTINE ALCAGO=
%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR AN ASSIGNED GOTO
	(NOTE THAT THE ASSIGNED VAL MAY BE AN ARRAYREF THAT REQUIRES CALCULATION)
	THE ACTUAL TESTING OF THE VAL WILL ALWAYS BE PERFORMED IN REG 1.
	CALLED WITH THE GLOBALS
		CSTMNT - PTR TO THE STMNT
		STBSYR - HAS A BIT SET FOR EACH REG AVAILABLE FOR USE IN COMPUTING
			THIS STMNT
		STRGCT - CT OF REGS AVAILABLE FOR USE IN COMPUTING THIS STMNT
***************************************************************************)%
BEGIN
	%(***PERFORM REGISTER ALLOCATION FOR ANY COMMON SUBEXPRS UNDER THIS STATEMENT***)%
	ALCCMNSB();

	%(***PERFORM REG ALLOC FOR ACCESSING THE ASSIGNED VAR***)%
	TREEPTR_.CSTMNT[AGOTOLBL];
	IF .TREEPTR[OPRCLS] NEQ DATAOPR
	THEN
	ALCINREG(AFREEREG(.STBSYR,FALSE,FALSE),.STBSYR,.STRGCT);

	REGCLOBB(1);	!THE CONTENTS OF REG 1 ARE CLOBBERED BY EVAL OF THIS
			! STMNT. CLEAR BB ALLOC ENTRIES FOR REG 1

END;


GLOBAL ROUTINE ALCCGO=
%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR A COMPUTED GOTO.
	PERFORMS REGISTER-ALLOCATION FOR THE COMPUTATION OF THE COMPUTED
	EXPRESSION. THAT VAL WILL ALWAYS BE MOVED TO REG #1 (AS PART OF A SKIP
	OPERATION THAT TESTS ITS RANGE) FOR EXCUTION OF THE GOTO
	CALLED WITH THE GLOBALS
		CSTMNT - PTR TO THE STMNT
		STBSYR - HAS A BIT SET FOR EACH REG AVAILABLE FOR USE IN COMPUTING
			THIS STMNT
		STRGCT - CT OF REGS AVAILABLE FOR USE IN COMPUTING THIS STMNT
***************************************************************************)%
BEGIN
	%(***PERFORM REGISTER ALLOCATION FOR ANY COMMON SUBEXPRS UNDER THIS STATEMENT***)%
	ALCCMNSB();

	%(***PERFORM REGISTER ALLOCATION FOR COMPUTATION OF THE COMPUTED EXPR***)%
	TREEPTR_.CSTMNT[CGOTOLBL];
	IF .TREEPTR[OPRCLS] NEQ DATAOPR
	THEN
	ALCINREG(AFREEREG(.STBSYR,FALSE,FALSE),.STBSYR,.STRGCT);

	REGCLOBB(1);	!THE CONTENTS OF REG 1 ARE CLOBBERED BY EVAL OF THIS
			! STMNT. CLEAR BB ALLOC ENTRIES FOR REG 1

END;



GLOBAL ROUTINE ALCLIF=
%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR A LOGICAL IF STATEMNT.
	CALLED WITH THE GLOBALS
		CSTMNT - PTR TO THE STMNT
		STBSYR - HAS A BIT SET FOR EACH REG AVAILABLE FOR USE IN COMPUTING
			THIS STMNT
		STRGCT - CT OF REGS AVAILABLE FOR USE IN COMPUTING THIS STMNT
***************************************************************************)%
BEGIN
	EXTERNAL ALCRL1,ALCCNT;
	OWN PEXPRNODE CONDEXPR;
	OWN BASE SAVSTMNT;
	OWN SAVBSYR,SAVRCT;

	SAVBSYR_.STBSYR;
	SAVRCT_.STRGCT;


	CONDEXPR_.CSTMNT[LIFEXPR];

	%(***IF THIS STATEMENT IS DOUBLE-PREC, ADJUST SET OF BUSY REGS SO
		THAT ONLY EVEN REGS WILL BE ALLOCATED****)%
	IF .CONDEXPR[DBLFLG]
	THEN
	BEGIN
		STBSYR_DPBSYREGS(.STBSYR);
		STRGCT_ONESCOUNT(.STBSYR);
		DBLMODE_TRUE;
	END
	ELSE
	DBLMODE_FALSE;

	%(***PERFORM REGISTER ALLOCATION FOR ANY COMMON SUBEXPRS UNDER THIS STMNT***)%
	ALCCMNSB();

	%(***PERFORM REGISTER ALLOCATION FOR THE CONDITIONAL EXPRESSION***)%

	TREEPTR_.CONDEXPR;

	%(***IF THE EXPRESSION IS OF TYPE CONTROL, NEED NEVER COMPUTE A VALUE FOR IT***)%
	IF .CONDEXPR[VALTYPE] EQL CONTROL
	THEN
	BEGIN
		IF .CONDEXPR[OPRCLS] EQL RELATIONAL	!FOR A RELATIONAL
		THEN ALCRL1(.STBSYR,.STRGCT)
		ELSE
		IF .CONDEXPR[OPRCLS] EQL BOOLEAN	!FOR A BOOLEAN
		THEN
		BEGIN
			NOBBREGSLOAD_TRUE;	!CANNOT ASSUME THAT ALL CODE FOR A CONTROL
						! BOOLEAN WILL BE EXECUTED - SO SET FLAG
						! TO MAKE NO ASSUMPTIONS ABOUT REGS BEING LOADED
			ALCCNT(.STBSYR,.STRGCT);
			NOBBREGSLOAD_FALSE;	!CLEAR FLAG
		END
		ELSE CGERR();	!A CONTROL-TYPE EXPR MUST BE BOOLEAN OR RELATIONAL
	END

	%(***OTHERWISE WILL HAVE TO COMPUTE THE VAL AND TEST IT***)%
	ELSE
	BEGIN
		IF .CONDEXPR[OPRCLS] EQL BOOLEAN	!IF THE CONDITIONAL EXPR IS A BOOLEAN
		THEN
		BEGIN
			%(***WHEN BOOLEANS IN WHICH ARG1 IS A MASK AND ARG2 IS OF TYPE CONTROL
				ARE USED IN A LOGICAL IF - THE CODE GENERATED WILL TEST THE
				THE VAL OF THE MASK AND NOT EXECUTE THE  CONTROL PART
				IF ITS NOT NECESSARY
			*****)%
			OWN PEXPRNODE ARG2NODE;
			ARG2NODE_.CONDEXPR[ARG2PTR];
			IF .ARG2NODE[VALTYPE] EQL CONTROL	!AND THE 1ST TERM OF THE BOOLEAN
								! IS A MASK AND THE 2ND IS OF TYPE CONTROL
			THEN
			NOBBREGSLOAD_TRUE			!DONT MAKE ASSUMPTION THAT ALL
								! CODE FOR THIS BOOLEAN IS ALWAYS EXECUTED
		END;
		ALCINREG(AFREEREG(.STBSYR,FALSE,FALSE),.STBSYR,.STRGCT);
	END;

	%(***PERFORM REGISTER ALLOCATION FOR THE SUBSTATEMENT****)%
	SAVSTMNT_.CSTMNT;
	STBSYR_.SAVBSYR;
	STRGCT_.SAVRCT;
	CSTMNT_.CSTMNT[LIFSTATE];

	NOBBREGSLOAD_TRUE;	!DO NOT ASSUME THAT ANY REGS INITIALIZED BY EVALUATION
				! OF THE SUBSTATEMENT CAN BE USED LATER (SINCE THE SUBSTATEMENT
				! IS NOT ALWAYS EVALUATED)
	ALCSTMN();	!PERFORM ALLOCATION FOR EVALUATION OF THE SUBSTATEMENT
	NOBBREGSLOAD_FALSE;	!RESET FLAG SO THAT WILL ONCE AGAIN ASSUME THAT
				! CODE IS EXECUTED (IF THIS BASIC BLOCK IS EXECUTED)

	CSTMNT_.SAVSTMNT;

END;


GLOBAL ROUTINE ALCAIF=
%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR AN ARITHMETIC IF.
	CALLED WITH THE GLOBALS
		CSTMNT - PTR TO THE STATEMENT
		STBSYR - HAS A BIT SET FOR EACH REG AVAILABLE FOR USE
			IN COMPUTING THIS STMNT
		STRGCT - CT OF REGS AVAILABLE
***************************************************************************)%
BEGIN
	OWN RA,RB;
	TREEPTR_.CSTMNT[AIFEXPR];

	%(*****IF THE VALUE IS DOUBLE-WD, ADJUST THE SET OF REGS SO THAT ONLY EVEN
		REGS WILL BE ALLOCATED*****)%
	IF .TREEPTR[DBLFLG]
	THEN
	BEGIN
		STBSYR_DPBSYREGS(.STBSYR);
		STRGCT_ONESCOUNT(.STBSYR);
		DBLMODE_TRUE;
	END
	ELSE
	DBLMODE_FALSE;

	%(***PERFORM REGISTER ALLOCATION FOR ANY COMMON SUBEXPRS UNDER THIS STMNT***)%
	IF .CSTMNT[SRCCOMNSUB] NEQ 0 THEN ALCCMNSB();

	%(***PERFORM REGISTER ALLOCATION FOR THE COMPUTATION OF THE ARITHMETIC EXPRESSION***)%

	TREEPTR_.CSTMNT[AIFEXPR];
	RA_AFREEREG(.STBSYR,FALSE,.TREEPTR[DBLFLG]);

	ALCINREG(.RA,.STBSYR,.STRGCT);

	%(***DECIDE WHAT REG TO USE WHEN TESTING THE VALUE OF THE EXPR***)%
	TREEPTR_.CSTMNT[AIFEXPR];
	IF .TREEPTR[INREGFLG]
	THEN
	BEGIN
		CSTMNT[AIFREG]_.TREEPTR[TARGTAC];
		CSTMNT[A1SAMEFLG]_1;
	END

	ELSE
	IF (RB_REGCONTAINING(.CSTMNT[AIFEXPR])) GEQ 0	!IF VAR TO BE TESTED WAS LEFT IN A REG
	THEN
	BEGIN
		CSTMNT[AIFREG]_.RB;	!USE THAT REG
		CSTMNT[A1SAMEFLG]_1;	!DONT RELOAD THE REG
	END

	ELSE
	BEGIN
		%(**PICK A REG TO LOAD THE VAL TO BE TESTED - SINCE THE REG
			GETS LOADED WITH A SKIP INSTR, DO NOT ALLOW REG 0 TO BE USED**)%
		RA_RGTOU1(.CSTMNT,.TREEPTR,.RA,CLRBIT(.STBSYR,REG0));
		CSTMNT[AIFREG]_.RA;
		REGCLOBB(.CSTMNT[AIFREG]);	!THE PREVIOUS CONTENTS OF THE
						! REG ASSIGNED WILL BE CLOBBERED.
						! CLEAR BB ALLOC ENTRIES FOR THAT REG
	END;
END;


GLOBAL ROUTINE ALCDECENC=
%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR ENCODE/DECODE STMNTS.
***************************************************************************)%
BEGIN
	OWN RA;
	EXTERNAL ALCARRAY,TREEPTR;
	OWN PEXPRNODE ENCVAR;
	OWN PEXPRNODE ENCCT;		!EXPRESSION FOR CHAR CT

	ENCVAR_.CSTMNT[IOVAR];
	ENCCT_.CSTMNT[IOCNT];


	%(***IF THE CHARACTER CT IS AN EXPRESSION, PERFORM REGISTER ALLOC FOR
		ITS CALCULATION***)%
	IF .ENCCT[OPRCLS] NEQ DATAOPR
	THEN
	BEGIN
		TREEPTR_.ENCCT;
		ALCINREG(AFREEREG(.STBSYR,FALSE,FALSE),.STBSYR,.STRGCT);

		%(***IF SOME REGISTER MUST BE PRESERVED IN ORDER TO PRESERVE THE
			VAL OF THE COUNT, DONT WANT TO USE THAT REG IN CALCULATING
			THE ARRAY ADDRESS***)%
		IF (RA_RGTOSAVE(.ENCCT)) NEQ -1
		THEN (STBSYR_CLRBIT(.STBSYR,.RA); STRGCT_.STRGCT-1);

	END;

	%(***IF THE ENCODE-ARRAY IS ACTUALLY AN "ARRAYREF" NODE (IE INCLUDES AN
		OFFSET WITHIN THE ARRAY), PERFORM REGISTER ALLOCATION FOR THE ADDRESS
		CALCULATION***)%
	IF .ENCVAR[OPRCLS] EQL ARRAYREF
	THEN
	BEGIN
		TREEPTR_.ENCVAR;
		ALCARRAY(.STBSYR,.STRGCT);
	END;

	ALCIOLST();	!PERFORM REG ALLOC FOR THE IOLIST

	IF .CSTMNT[SRCID] EQL ENCOID	!FOR ENCODE STMNTS MUST ASSUME THAT
	THEN VARCLOBB(.ENCVAR);	! THE ARRAY BEING ENCODED INTO (AND ANY VARS POTENTIALLY EQUIVALENCED
				! TO IT) HAS IT CONTENTS MODIFIED
END;	!END OF  ALCDECENC


GLOBAL ROUTINE ALCOPEN=
%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR AN OPEN STMNT -
	FOR THE CALCULATION OF ARGS THAT ARE EXPRESSIONS (EG ARRAYREFS
	WITH EXPRESSIONS IN THE SUBSCRIPTS)
***************************************************************************)%
BEGIN
!**;[532], ALCOPEN @5155, DCE, JAN-14-77
%[532]%	EXTERNAL ALCTARY;
	REGISTER OPENLIST ARVALLST;
	ARVALLST_.CSTMNT[OPLST];	!LIST OF ARGS UNDER THE OPEN

	%(**WALK THRU THE LIST OF ARGS, PERFORM REGISTER ALLOC FOR THE CALC OF ANY ARG
		THAT IS NOT A VAR OR CONST***)%
	INCR I FROM 0 TO (.CSTMNT[OPSIZ]-1)
	DO
	BEGIN
		TREEPTR_.ARVALLST[.I,OPENLPTR];	!EXPRESSION NODE FOR THE VAL OF THE ITH ARG
		IF .TREEPTR EQL 0	!IF HAVE A NULL VAL FOR "DIALOG", DO NOTHING
		THEN BEGIN END
		ELSE
		IF .TREEPTR[OPRCLS] NEQ DATAOPR
		THEN
		BEGIN
!**;[532], ALCOPEN @5170, DCE, 14-JAN-77
!**;[532], BE SURE TO HANDLE ARRAY FOR ASSOCIATE VARIABLE CORRECTLY HERE
!**;[532], SO THAT THE ADDRESS IS SET UP RATHER THAN THE VALUE IN THE ARRAY ELEMENT
%[532]%			IF .TREEPTR[OPRCLS] EQL ARRAYREF !FOR ARRAY ELEMENT
%[532]%			THEN ARVALLST[.I,OPENLPTR]_ !LINK IN PTR TO STORECLS NODE
%[532]%			(IF .ARVALLST[.I,OPENLCODE] EQL OPNCASSOCIATE
%[532]%			THEN ALCTARY(.STBSYR,.STRGCT) !HERE IS THE CHANGE
%[532]%			ELSE ALCTVARR(.STBSYR,.STRGCT))
			ELSE ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.STBSYR,.STRGCT);
		END;
	END;
END;	!END OF "ALCOPEN"


GLOBAL ROUTINE ALCCMNSB=
%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR ALL COMMON SUBEXPRS UNDER
	THE STATEMENT "CSTMNT".
	DEPENDING ON THE NUMBER OF REGS NECESSARY TO COMPUTE THE STATEMENT
	AND THE NUMBER OF REGS AVAILABLE (WHICH IS INDICATED BY THE GLOBAL "STRGCT",
	LEAVES AS MANY COMMON SUBEXPRS AS POSSIBLE IN REGISTERS.
***************************************************************************)%
BEGIN
	EXTERNAL PAIRMODE;	!THIS GLOBAL IS SET TO TRUE IFF THIS STMNT USES ANY REG PAIRS
	EXTERNAL FREEPAIRS;	!ROUTINE TO COUNT THE NUMBER OF EVEN-ODD REG PAIRS INDICATED
				! TO BE FREE BY A BIT PATTERN IN
				! WHICH 0'S REPRESENT BUSY REGS, 1'S REPRESENT FREE REGS
	OWN RA,RB;
	OWN PEXPRNODE CCMNSUB:ARGNODE;
	OWN BASE CCSTMNT;	![254] SAVE CSTMNT
	OWN BSYRG1,REGCT1;
	OWN REGSNEEDED;		!NUMBER OF REGISTERS NEEDED (EXCEPT FOR COMMON SUBEXPRS)
			! FOR COMPUTATION OF THIS STMNT
	OWN PAIRSNEEDED;	!FOR STMNTS THAT REQUIRE REG PAIRS, MAX NUMBER OF PAIRS NEEDED
	OWN FREERGPAIRS;	!NUMBER OF REG PAIRS FREE


	CCMNSUB_.CSTMNT[SRCCOMNSUB];
	CCSTMNT_.CSTMNT;	![254] SAVE CSTMNT FOR ALC TO 0 CHECK

	REGSNEEDED_.CSTMNT[SRCCMPLX];	!NUMBER OF REGS NEEDED FOR THIS STMNT
	PAIRSNEEDED_(.CSTMNT[SRCCMPLX]+1)/2;	!MAX NUMBER OF PAIRS NEEDED


	%(**WALK THRU ALL COMMON SUBS ON THIS STMNT***)%
	UNTIL .CCMNSUB EQL 0
	DO
	BEGIN
		ARGNODE_.CCMNSUB[ARG2PTR];
		TREEPTR_.ARGNODE;


		%(***IF THIS COMMON SUBEXPR IS DOUBLE-PREC AND THE STATEMENT IS NOT,
			THEN MUST ADJUST THE SET OF AVAILABLE REGS TO INCLUDE ONLY EVEN REGS***)%
		IF .ARGNODE[DBLFLG] AND NOT .DBLMODE
		THEN
		BEGIN
			BSYRG1_DPBSYREGS(.STBSYR);
			REGCT1_ONESCOUNT(.BSYRG1);
		END
		ELSE
		BEGIN
			BSYRG1_.STBSYR;
			REGCT1_.STRGCT;
		END;


		%(***IF THIS COMMON SUB WILL BE USED AS A SS, DONT USE REG 0 FOR IT**)%
		IF .CCMNSUB[CSSSFLG]
		THEN
		BEGIN
			IF BITSET(.BSYRG1,0) THEN
			(REGCT1_.REGCT1-1; BSYRG1_CLRBIT(.BSYRG1,0))
		END;


		%(***DETERMINE HOW MANY REG PAIRS ARE NOW AVAILABLE**)%
		FREERGPAIRS_
			IF .DBLMODE OR .ARGNODE[DBLFLG]		!IF BSYRG1 IS ALREADY IN TERMS OF PAIRS
			THEN .REGCT1
			ELSE FREEPAIRS(.STBSYR);


		%(***IF THERE ARE ENOUGH REGISTERS FREE SO THAT THIS THIS EXPRESSION
			CAN BE LEFT IN A REG WHILE CALCULATING THE WHOLE STATEMENT,
			LEAVE THIS EXPR IN A REG.
			OTHERWISE LEAVE IT IN A TEMPORARY.
		********)%
		IF (NOT .PAIRMODE	!WHEN THIS STMNT NEEDS NO ADJACENT PAIRS
			AND .STRGCT GTR .REGSNEEDED+1)	!NUMBER OF REGS LEFT SHOULD BE 
							! GREATER THAN 1 MORE THAN NUMBER NEEDED
		  OR
			(.FREERGPAIRS GTR .PAIRSNEEDED+1)	!IF STMNT WILL NEED PAIRS, SHOULD
							! HAVE AT LEAST  1 EXTRA PAIR BEFORE RISK
							! USING UP A PAIR
		  OR
			(.CCMNSUB[CSSSFLG]	!IF THIS CSB IS USED AS A SUBSCRIPT
			 AND .FREERGPAIRS GTR 2)	!THEN PUT IT IN A REG AS LONG AS
						! 2 PAIRS CAN BE LEFT
		THEN
		BEGIN
			RA_AFREEREG(.BSYRG1,.CCMNSUB[SAVREGFLG],.CCMNSUB[DBLFLG]);
			IF NOT .CCMNSUB[A2VALFLG]
			THEN
			ALCINREG(.RA,.BSYRG1,.REGCT1);

			%(***IF THE COMMON SUB WAS COMPUTED INTO A REG WHERE IT CAN
				BE LEFT - LEAVE IT THERE***)%
			IF .ARGNODE[INREGFLG] AND NOT .ARGNODE[ALCRETREGFLG]
				!IF THE COMMON SUB IS THE RIGHT HALF OF AN AOBJN WD
				! AND IS USED IN A CONTEXT THAT REQUIRES A FULL WD,
				! CANNOT USE THE AOBJN REG
				AND NOT (.CCMNSUB[A2IMMEDFLG] AND .CCMNSUB[CSFULLWDFLG])
			THEN
			BEGIN
				CCMNSUB[TARGTAC]_.ARGNODE[TARGTAC];
				CCMNSUB[TARGADDR]_.CCMNSUB[TARGTAC];
				CCMNSUB[A2SAMEFLG]_1;
			END

			ELSE
			IF (RB_REGCONTAINING(.ARGNODE)) GEQ 0	!IF ARG IS A VAR WHOSE VAL WAS LEFT IN A REG
				AND	![254] IF IT'S AN ASSIGNMENT STATEMENT
				(IF .CCSTMNT[SRCID] EQL ASGNID AND .CCSTMNT[OPRCLS] EQL STATEMENT	![254]
				THEN	![254] IF THE LEFT HALF IS A REGCONTENTS
				BEGIN	![254] NODE TO 0
				LOCAL PEXPRNODE T1;	![254]
				T1_.CCSTMNT[LHEXP];	![254]
				IF .T1[OPRCLS] EQL REGCONTENTS AND .RB EQL 0	![254]
				THEN FALSE	![254] WE CAN'T USE ZERO
				ELSE TRUE	![254] ANYTHING BUT 0
				END		![254]
				ELSE TRUE)	![254]
				AND NOT ((.RB EQL RETREG	![301] THIS IS NOT 0
					OR .RB EQL (RETREG+1))	![301] OR 1
					AND .CSTMNT[FNCALLSFLG])	![301] WHEN THERE IS A FUNCTION CALL
								![301] UNDER THIS NODE
				AND .CCMNSUB[A2NGNTFLGS] EQL 0	! AND ARG NEED NOT BE NEGATED
				AND NOT(.RB EQL 0 AND .CCMNSUB[CSSSFLG])	!AND DO NOT HAVE A VAR WHICH WILL
							! BE USED AS A SS IN REG 0
			THEN
			BEGIN
				CCMNSUB[TARGTAC]_.RB;	!THEN USE THAT REG
				CCMNSUB[TARGADDR]_.RB;
				CCMNSUB[A2SAMEFLG]_1;	!DONT RELOAD THE REG
			END
			ELSE
			BEGIN
				RA_RGTOU1(.CCMNSUB,.ARGNODE,.RA,.BSYRG1);
				SETTARGINREG(.CCMNSUB,.RA)
			END;

			CCMNSUB[INREGFLG]_1;

			RA_.CCMNSUB[TARGTAC];
			%(***REMOVE THE REG HOLDING THIS COMMON SUB FROM THE REG POOL***)%
			STBSYR_CLRBIT(.STBSYR,.RA);
			STRGCT_.STRGCT-1;

			%(***IF THE COMMON SUB IS DOUBLE-WD, REMOVE THE REG HOLDING THE RIGHT HALF
				FROM THE REG POOL***)%
			IF .ARGNODE[DBLFLG]
			THEN
			BEGIN
				STBSYR_CLRBIT(.STBSYR,.RA+1);
				STRGCT_.STRGCT-1;
			END;


			IF .ARGNODE[OPRCLS] EQL DATAOPR	!IF THE COMMON SUB IS A VAR
				AND .CCMNSUB[SAVREGFLG]	! WHICH WILL BE USEFUL IN A REG IN A LATER STMNT
				AND .CCMNSUB[A2NGNTFLGS] EQL 0	! AND  WAS NOT PICKED UP WITH "MOVN"
			THEN SAVEREG(.CCMNSUB[TARGTAC],	!REMEMBER THAT THIS REG
				.ARGNODE,		! CONTAINS THE VAL OF THAT VAR
				0,.CCMNSUB[SONNXTUSE]);

		END

		ELSE
		%(***IF CANNOT SPARE A REG TO LEAVE THIS COMMON SUBEXPR IN****)%
		BEGIN
			IF .CCMNSUB[A2VALFLG]
			THEN
			BEGIN
				%(***IF THIS ARG IS THE RIGHT HALF OF AN AONJN WD
					AND WE WILL NEED THE WHOLE THING, MUST LOAD AND STORE IT***)%
				IF .CCMNSUB[A2IMMEDFLG] AND .CCMNSUB[CSFULLWDFLG]
				THEN
				BEGIN
					RA_AFREEREG(.BSYRG1,.CCMNSUB[SAVREGFLG],FALSE);
					CCMNSUB[TARGTAC]_.RA;
					REGCLOBB(.CCMNSUB[TARGTAC]);	!MUST ASSUME THAT THE PREVIOUS
									! CONTENTS OF THE REG USED ARE CLOBBERED
					CCMNSUB[TARGADDR]_NXTTMP(FALSE);
				END

				ELSE
				%(***IF THE COMMON SUB IS A REGCONTENTS THAT CAN BE USED, USE IT**)%
				IF .ARGNODE[OPRCLS] EQL REGCONTENTS
				THEN
				BEGIN
					CCMNSUB[TARGET]_.ARGNODE[TARGET];
					CCMNSUB[A2SAMEFLG]_1;
				END

				ELSE
				BEGIN
					CCMNSUB[TARGET]_.ARGNODE;
					CCMNSUB[A2SAMEFLG]_1;
				END
			END
			ELSE
			BEGIN
				ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.BSYRG1,.REGCT1);
				CCMNSUB[TARGET]_.ARGNODE[TARGET];
				CCMNSUB[A2SAMEFLG]_1;
			END;
		END;

		CCMNSUB_.CCMNSUB[CLINK];

	END;
END;



GLOBAL ROUTINE ALCIOLST=
%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR AN IOLIST.
	CLAAED WITH THE GLOBAL CSTMNT POINTING TO THE STATEMENT FOR
	WHICH AN IOLIST IS TO BE PROCESSED.
	CALLED WITH THE GLOBALS STBSYR AND STRGCT INDICATING WHICH REGS
	ARE AVAILABLE FOR USE.
***************************************************************************)%
BEGIN
	EXTERNAL ALCINREG,ALCINTMP,ALCTARY;

	LOCAL BASE IOLELEM;
	LOCAL SAVSTMNT,SAVBSYR,SAVRGCT;

	%(***GET PTR TO 1ST ELEM ON IOLIST TO BE PROCESSED***)%
	IOLELEM_.CSTMNT[IOLIST];

	%(****SAVE PTR TO CURRENT STATEMENT (IF THERE ARE DO-STMNTS ON THE IOLIST
		WILL CLOBBER CSTMNT,STBSYR,STRGCT)*****)%
	SAVSTMNT_.CSTMNT;
	SAVBSYR_.STBSYR;
	SAVRGCT_.STRGCT;

	%(*****WALK THRU THE ELEMENTS ON THE IOLIST******)%
	UNTIL .IOLELEM EQL 0
	DO
	BEGIN
		IF .IOLELEM[OPRCLS] EQL STATEMENT
		THEN
		BEGIN
			CSTMNT_.IOLELEM;
			ALCSTMN();

			%(**IF THIS STMNT IS A DO STMNT, MUST TERMINATE THE PREVIOUS BASIC BLOCK
				(SINCE SOME VAR MIGHT BE CLOBBERED LATER IN THE LIST AND ON
				LOOPING BACK MIGHT MAKE A FALSE ASSUMPTION ABOUT ITS VAL
				BEING IN A REG)
			***)%
			IF .IOLELEM[SRCID] EQL DOID
			THEN
			BEGIN
				CLRRGSTATE();	!MUST DELETE ALL ASSUMPTIONS ABOUT
							! THE CONTENTS OF REGISTERS

				IF .IOLELEM[SAVREGFLG]	!IF THE DO INDEX WILL BE USEFUL
							! LATER, REMEMBER WHAT REG ITS IN
				THEN SAVEREG(.IOLELEM[DOIREG],
					.IOLELEM[DOSYM],0,.IOLELEM[SRCSONNXTUSE],
					FALSE);
			END;

		END

		ELSE
		IF .IOLELEM[OPRCLS] EQL IOLSCLS
		THEN
		BEGIN
			CASE .IOLELEM[OPERSP] OF SET

			%(***FOR A DATACALL NODE - PERFORM REG ALLOC FOR THE
				EXPRESSION UNDER THIS NODE*****)%
			BEGIN
				TREEPTR_.IOLELEM[DCALLELEM];
				IF .TREEPTR[OPRCLS] NEQ DATAOPR
				THEN
				BEGIN
					LOCAL STBSY1,STRG1;
					IF .TREEPTR[DBLFLG] THEN
					BEGIN
						STBSY1_DPBSYREGS(.STBSYR);
						STRG1_ONESCOUNT(.STBSY1);
					END ELSE
					BEGIN
						STBSY1_.STBSYR;
						STRG1_.STRGCT;
					END;
					ALCINREG(AFREEREG(.STBSY1,FALSE,.TREEPTR[DBLFLG]),.STBSY1,.STRG1);
				END;
				IF .INPFLAG	!IF INPUT IS BEING PERFORMED
				THEN VARCLOBB(.IOLELEM[DCALLELEM])	!THE VAL OF THE VAR WILL BE
							! CLOBBERED, HENCE MUST FORGET ASSUMPTIONS
							! ABOUT THAT VAR BEING IN SOME REG
			END;

			%(***FOR AN SLISTCALL NODE - PERFORM REG ALLOC FOR THE OPERATION
				TO CALCULATE THE NUMBER OF ELEMS IN THE ARRAY (IF ARRAY
				HAS VARIABLE BOUNDS)****)%
			BEGIN
				TREEPTR_.IOLELEM[SCALLCT];
				IF .TREEPTR[OPRCLS] NEQ DATAOPR
				THEN
				ALCINREG(AFREEREG(.STBSYR,FALSE,.TREEPTR[DBLFLG]),.STBSYR,.STRGCT);

				IF .INPFLAG	!IF INPUT IS BEING PERFORMED
				THEN VARCLOBB(.IOLELEM[SCALLELEM]);	!MUST ASSUME THAT ELEMENTS OF THE
								! ARRAY AND ALL VARS EQUIVALENCED TO THEM
								! ARE CLOBBERED
			END;

			%(***FOR AN IOLSTCALL NODE***************)%
			ALCIOCALL(.IOLELEM);

			%(****FOR AN E1LISTCALL NODE - OPTIMIZED CODE ONLY***)%
			BEGIN
				LOCAL BASE SAVCSTMNT;
				SAVCSTMNT_.CSTMNT;
				CSTMNT_.IOLELEM;
				ALCCMNSB();
				CSTMNT_.SAVCSTMNT;
				ALCE1LIST(.IOLELEM,.STBSYR,.STRGCT)
			END;

			%(***FOR AN E2LISTCALL NODE - OPTIMIZED CODE ONLY***)%
			BEGIN
				LOCAL BASE SAVCSTMNT;
				SAVCSTMNT_.CSTMNT;
				CSTMNT_.IOLELEM;
				ALCCMNSB();
				CSTMNT_.SAVCSTMNT;
				ALCE2LIST(.IOLELEM,.STBSYR,.STRGCT)
			END

			TES;
		END;

		%(***RESTORE STBSYR,STRGCT FOR THE NEXT ELEM ON IOLIST***)%
		STBSYR_.SAVBSYR;
		STRGCT_.SAVRGCT;

		%(***GO ON TO NEXT ELEMENT****)%
		IOLELEM_.IOLELEM[CLINK];

	END;

	CSTMNT_.SAVSTMNT;
END;



GLOBAL ROUTINE ALCIOCALL(IOLSNODE)=
%(***************************************************************************
	TO PERFORM REGISTER ALLOCATION FOR AN IOLSTCALL NODE.
	THE ARG IOLSNODE PTS TO AN IOLSTCALL NODE.
	FOR IOLIST ELEMENTS THAT REQUIRE COMPUTATION, LEAVE AS MANY
	AS POSSIBLE IN THE REGS IN WHICH THEY WERE COMPUTED (RATHER THAN
	STORING THEM IN TEMPORARIES). ALSO LEAVE AS MANY ARRAY OFFSETS
	AS POSSIBLE IN REGISTERS.
***************************************************************************)%
BEGIN
	EXTERNAL RGTOSAVE;
	EXTERNAL ALCTARY;
	MAP BASE IOLSNODE;
	EXTERNAL TREEPTR;
	MAP PEXPRNODE TREEPTR;
	OWN BASE IOLELEM;
	OWN REGSREQ;
	OWN FREGCT,BSYREGS;	!REGISTERS AVAILABLE FOR USE AT THE CURRENT PT IN
				! THE IOLIST (AS EARLY ELEMS GET LEFT IN REGS,
				! THESE VARIABLES ARE ADJUSTED SO THAT LATER ELEMS
				! WONT CLOBBER THOSE REGS)
	OWN FRGCT1,BSYRG1;	!FOR A DATACALL NODE - THESE ARE ADJUSTED TO ACCOUNT
				! FOR  A DOUBLE PRECISION EXPRESSION
	OWN RA;
	OWN PEXPRNODE ARGNODE;
	OWN SAVSTMNT;


	%(***SAVE VAL OF THE GLOBAL CSTMNT***)%
	SAVSTMNT_.CSTMNT;

	%(***PERFORM REGISTER ALLOCATION FOR ANY COMMON SUBEXPRS ON THIS IOLST***)%
	CSTMNT_.IOLSNODE;
	ALCCMNSB();

	%(***GET NUMBER OF REGS REQUIRED FOR REST OF THIS IOLSTCALL***)%
	REGSREQ_.IOLSNODE[SRCCMPLX];

	BSYREGS_.STBSYR;
	FREGCT_.STRGCT;

	%(***WALK THRU ELEMENTS ON THIS IOLSTCALL***)%
	IOLELEM_.IOLSNODE[IOLSTPTR];
	UNTIL .IOLELEM EQL 0
	DO
	BEGIN
		CASE .IOLELEM[OPERSP] OF SET

		%(***FOR A DATACALL NODE****)%
		BEGIN
			TREEPTR_.IOLELEM[DCALLELEM];
			ARGNODE_.TREEPTR;

			IF  .INPFLAG		! IF INPUT IS BEING PERFORMED 
			THEN			!MUST ASSUME THE VAL OF THE VAR IS CLOBBERED
			VARCLOBB(.ARGNODE);	! AND HENCE THAT ASSUMPTIONS ABOUT REGS CONTAINING
						! THE VAR ARE NOW FALSE

			IF .ARGNODE[OPRCLS] NEQ DATAOPR	![311] IF NEED TO CALCULATE
!**;[616], ALCIOCALL @5622, DCE, 21-SEP-77
!**;[616], DO NOT NEED TO GET A NEW REGISTER IF THIS ELEMENT IS A REGCONTENTS NODE
		%[616]%	THEN IF .ARGNODE[OPRCLS] NEQ REGCONTENTS
			THEN	![311] THE VALUE OF THIS ITEM
			BEGIN	![311] THEN ALLOCATE THE REGS

				%(***IF THIS ELEMENT IS DOUBLE-PREC - MUST ADJUST SET OF FREE REGS***)%
				IF .ARGNODE[DBLFLG]
				THEN
				(BSYRG1_DPBSYREGS(.BSYREGS); FRGCT1_ONESCOUNT(.BSYRG1) )
				ELSE
				(BSYRG1_.BSYREGS; FRGCT1_.FREGCT);

				%(***IF THERE ARE ENOUGH REGS TO LEAVE ALL FURTHER ARGS IN REGS***)%
				IF .REGSREQ LEQ .FREGCT
				THEN
				BEGIN
					ALCINREG(AFREEREG(.BSYRG1,FALSE,.TREEPTR[DBLFLG]),.BSYRG1,.FRGCT1);

					%(***IF THIS ARG WAS LEFT IN A REG, MUST TAKE THAT REG
						OUT OF THE SET OF REGS AVAILABLE FOR USE FOR
						LATER ELEMENTS****)%
					RA_RGTOSAVE(.ARGNODE);
					IF .RA NEQ -1
					THEN
					BEGIN
						BSYREGS_CLRBIT(.BSYREGS,.RA);

						%(***IF THIS ARG WAS DOUBLE-PREC MUST ALSO
							REMOVE THE REG AFTER RA FROM THE SET***)%
						IF .ARGNODE[DBLFLG]
						THEN
						BEGIN
							BSYREGS_CLRBIT(.BSYREGS,.RA+1);
							FREGCT_.FREGCT-2;
							REGSREQ_.REGSREQ-2;
						END
						ELSE
						BEGIN
							FREGCT_.FREGCT-1;
							REGSREQ_.REGSREQ-1;
						END;
					END;
				END

				%(***IF THERE ARE NOT ENOUGH REGS, THEN IF THIS ELEM IS COMPUTED,
					LEAVE IT IN A TEMP***)%
				ELSE
				BEGIN
					IF .TREEPTR[OPRCLS] EQL ARRAYREF
					THEN
					%(***FOR AN ARRAYREF - IF THE SS IS ALREADY IN A REG, CAN PASS
						FOROTS ARG IN THE FORM "ADDR(R)"
						OTHERWISE, MUST MATERIALIZE THE ADDRESS REFERENCED***)%
					BEGIN
!**;[522] Insert @ line 5640 in ALCIOCALL	JNG	16-Dec-76
%[522]%						IF .TREEPTR[A2VALFLG] AND NOT .TREEPTR[A2NEGFLG]
						THEN
						BEGIN
							OWN PEXPRNODE SSNODE;
							SSNODE_.TREEPTR[ARG2PTR];
							IF (.SSNODE[OPRCLS] EQL REGCONTENTS) OR 
								(.SSNODE[OPRCLS] EQL CMNSUB
									AND .SSNODE[INREGFLG])
							THEN
							BEGIN 
								%(***SET THE "INDEX" FIELD TO
									BE USED TO REFERENCE THE ELEMENT
									TO THE REG THAT HOLDS THE SS***)%
								TREEPTR[TARGXF]_.SSNODE[TARGTAC];
								TREEPTR[A2SAMEFLG]_1
							END

							ELSE IOLELEM[DCALLELEM]_ALCTARY(.BSYRG1,.FRGCT1)
						END
						ELSE
						IOLELEM[DCALLELEM]_ALCTARY(.BSYRG1,.FRGCT1)
					END
					ELSE
					ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.BSYRG1,.FRGCT1);

					%(***IF AN ARG THAT MIGHT HAVE BEEN LEFT IN A REG WAS
						LEFT IN A TEMP, CAN REDUCE THE NUMBER OF FUTURE REGS
						REQUIRED BY 1***)%
					IF .TREEPTR[OPRCLS] NEQ DATAOPR AND .TREEPTR[OPRCLS] NEQ CMNSUB
					THEN
					BEGIN
						IF .TREEPTR[COMPLEXITY] NEQ 0
						THEN
						BEGIN
							%(***FOR DOUBLE-WD VAL HAVE 2 EXTRA REGS**)%
							IF .TREEPTR[DBLFLG]
							THEN REGSREQ_.REGSREQ-2
							ELSE REGSREQ_.REGSREQ-1;
						END
					END;
				END;
			END;	![311] OF IF NEQ DATAOPR
		END;

		%(***FOR AN SLISTCALL NODE***)%
		BEGIN
			IF .INPFLAG	!IF INPUT IS BEING PERFORMED
			THEN VARCLOBB(.IOLELEM[SCALLELEM]);	!MUST ASSUME THAT ELEMS OF THIS ARRAY
								! (AND VARS POTENTIALLY EQUIVALENCED TO THEM)
								! ARE CLOBBERED
			TREEPTR_.IOLELEM[SCALLCT];
			IF .TREEPTR[OPRCLS] NEQ DATAOPR
			THEN
			%(***DONT BOTHER TO TRY TO LEAVE THIS IN A REG***)%
			ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.BSYREGS,.FREGCT);
		END;

		%(***AN IOLSTCALL WITHIN AN IOLSTCALL IS ILLEGAL***)%
		BEGIN
		END;

		%(***FOR AN E1LISTCALL NODE - OPTIMIZED CODE ONLY***)%
		ALCE1LIST(.IOLELEM,.BSYREGS,.FREGCT);

		%(***FOR AN E2LISTCALL NODE - OPTIMIZED CODE ONLY***)%
		ALCE2LIST(.IOLELEM,.BSYREGS,.FREGCT)

		TES;

		%(***GO ON TO NEXT ELEMENT***)%
		IOLELEM_.IOLELEM[CLINK];
	END;

	%(***RETSORE CSTMNT***)%
	CSTMNT_.SAVSTMNT;
END;





GLOBAL ROUTINE ALCE1LIST(IOLELEM,BSYREGS,FREGCT)=
%(**********************************************************************
	PERFORM REGISTER ALLOCATION FOR AN E1LISTCALL NODE
	STORE THE RESULTS OF ALL CALCULATIONS REQUIRED BY
	ELEMENTS IN THE E1LISTCALL NODE IN TEMPORARIES
**********************************************************************)%
BEGIN
	MAP BASE IOLELEM;
	LOCAL BASE IOARRAY;
	EXTERNAL ALCTVARR;	!ALLOCATE THE VAL OF AN ARRAY ELEM TO 
			! A TEMP
	EXTERNAL ALCTARY,ALCINTMP;
	EXTERNAL TREEPTR;
	MAP PEXPRNODE TREEPTR;

	%(***ALLOCATE THE COUNT EXPRESSION***)%

	TREEPTR_.IOLELEM[ECNTPTR];
	IF .TREEPTR[OPRCLS] EQL ARRAYREF	!REF TO AN ARRAY ELEM
	THEN	IOLELEM[ECNTPTR]_ALCTVARR(.BSYREGS,.FREGCT)	!LINK A STORECLS NODE INTO THE TREE
	ELSE
	IF .TREEPTR[OPRCLS] NEQ DATAOPR THEN
	 ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.BSYREGS,.FREGCT);

	%(***ALLOCATE THE INCREMENT EXPRESSION***)%

	TREEPTR_.IOLELEM[E1INCR];
	IF .TREEPTR[OPRCLS] EQL ARRAYREF
	THEN IOLELEM[E1INCR]_ALCTVARR(.BSYREGS,.FREGCT)
	ELSE
	IF .TREEPTR[OPRCLS] NEQ DATAOPR THEN
	 ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.BSYREGS,.FREGCT);

	%(***ALLOCATE THE ARRAY REFERENCES***)%

	IOARRAY_.IOLELEM[ELSTPTR];
	WHILE .IOARRAY NEQ 0 DO
	BEGIN
		LOCAL BASE VARNAME;
		TREEPTR_.IOARRAY[E2ARREFPTR];
		IF .TREEPTR[OPRCLS] EQL ARRAYREF THEN
		 IF .TREEPTR[ARG2PTR] NEQ 0 THEN
		  IOARRAY[E2ARREFPTR]_ALCTARY(.BSYREGS,.FREGCT);
		VARNAME_.IOARRAY[E2ARREFPTR];
		IF .INPFLAG THEN VARCLOBB(
		 IF .VARNAME[OPRCLS] NEQ ARRAYREF THEN .VARNAME ELSE
		 .VARNAME[ARG1PTR]);
		IOARRAY_.IOARRAY[CLINK]
	END

END;






GLOBAL ROUTINE ALCE2LIST(IOLELEM,BSYREGS,FREGCT)=
%(**********************************************************************
	PERFORM REGISTER ALLOCATION FOR AN E2LISTCALL NODE
	STORE THE RESULTS OF ALL CALCULATIONS REQUIRED BY
	ELEMENTS IN THE E2LISTCALL NODE IN TEMPORARIES
**********************************************************************)%
BEGIN
	EXTERNAL ALCTARY,ALCINTMP;
	LOCAL BASE IOARRAY;
	MAP BASE IOLELEM;
	EXTERNAL TREEPTR;
	MAP PEXPRNODE TREEPTR;

	%(***ALLOCATE THE COUNT EXPRESSION***)%

	TREEPTR_.IOLELEM[ECNTPTR];		!ALLOCATE EXPRESSION
	IF .TREEPTR[OPRCLS] EQL ARRAYREF	!REF TO AN ARRAY ELEM
	THEN	IOLELEM[ECNTPTR]_ALCTVARR(.BSYREGS,.FREGCT)	!LINK A STORECLS NODE INTO THE TREE
	ELSE
	IF .TREEPTR[OPRCLS] NEQ DATAOPR THEN	!IN A TEMPORARY
	 ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.BSYREGS,.FREGCT);


	%(***ALLOCATE THE INCREMENT EXPRESSIONS***)%

	IOARRAY_.IOLELEM[ELSTPTR];		!LOCATE LIST
	WHILE .IOARRAY NEQ 0 DO
	BEGIN
		TREEPTR_.IOARRAY[E2INCR];		!ALLOCATE EXPRESSION
		IF .TREEPTR[OPRCLS] EQL ARRAYREF
		THEN IOARRAY[E2INCR]_ALCTVARR(.BSYREGS,.FREGCT)
		ELSE
		IF .TREEPTR[OPRCLS] NEQ DATAOPR THEN
		 ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.BSYREGS,.FREGCT);
		IOARRAY_.IOARRAY[CLINK]
	END;

	%(***ALLOCATE THE ARRAYREF COMPUTATIONS***)%

	IOARRAY_.IOLELEM[ELSTPTR];		!LOCATE LIST
	WHILE .IOARRAY NEQ 0 DO
	BEGIN
		LOCAL BASE VARNAME;
		TREEPTR_.IOARRAY[E2ARREFPTR];		!ALLOCATE EXPRESSION
		IF .TREEPTR[OPRCLS] EQL ARRAYREF THEN
		 IF .TREEPTR[ARG2PTR] NEQ 0 THEN
		  IOARRAY[E2ARREFPTR]_ALCTARY(.BSYREGS,.FREGCT);
		VARNAME_.IOARRAY[E2ARREFPTR];
		IF .INPFLAG THEN VARCLOBB(
		 IF .VARNAME[OPRCLS] NEQ ARRAYREF THEN .VARNAME ELSE
		 .VARNAME[ARG1PTR]);
		IOARRAY_.IOARRAY[CLINK]
	END

END;







GLOBAL ROUTINE LHINREGALC=
%(*****
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR AN ASSIGNMENT STATEMENT
	WHEN THE LEFT-HAND-SIDE IS ALLOCATED TO A REGISTER.
	THIS ROUTINE ATTEMPTS TO COMPUTE THE VALUE OF THE RIGHT-HAND-SIDE
	INTO THAT REGISTER.  IT IS ABLE TO DO SO IF EITHER:
		1.  THERE IS NO REFERENCE TO THE LHS VARIABLE IN THE
	    RHS EXPRESSION
		2.  THERE IS A REFERENCE TO THE LHS VARIABLE AT A DEPTH OF
		    1 OR 2 WITHIN THE RHS EXPRESSION.
	RETURNS TRUE IF SUCCEEDED, FALSE IF FAILED (IN WHICH CASE REGISTER
	ALLOCATION FOR THIS EXPRESSION MUST STILL BE PERFORMED)
*****)%
BEGIN
	!**;[403], LHINREGALC @5853, DCE, 17-MAY-76
	EXTERNAL CLOBBNX; ![403] NEED THIS FOR TEST
	REGISTER PEXPRNODE RHNODE;
	OWN PEXPRNODE LHNODE;
	OWN RA;
	OWN PEXPRNODE ARG1NODE;
	REGISTER PEXPRNODE ARG2NODE;

	%(***LOCAL ROUTINE TO SET REG FOR COMPUTATION OF RIGHT HAND EXPR EQUAL TO
	     REG TO WHICH LHS VARIABLE WAS ALLOCATED*****)%
	ROUTINE SETRHRGTOLH=
	BEGIN
		RHNODE[TARGTAC]_.LHNODE[TARGTAC];
		CSTMNT[ASMNTREG]_.LHNODE[TARGTAC];
		CSTMNT[A1SAMEFLG]_1;
		CSTMNT[A2SAMEFLG]_1;
	END;

	%(***LOCAL ROUTINE TO SPECIFY THAT THE COMPUTATION OF THE VALUE OF THE NODE
	     "PNODE" BE PERFORMED IN THE REGISTER USED FOR LHS WHEN ARG1
	     UNDER "PNODE" IS EQUAL TO LHS
		CAN BE CALLED FOR PNODE OF OPRCLS:
			ARITHMETIC,BOOLEAN,SPECOP
	****)%
	ROUTINE CMPNODINLH(PNODE)=
	BEGIN
		MAP PEXPRNODE PNODE;
		PNODE[A1SAMEFLG]_1;
		PNODE[TARGTAC]_.LHNODE[TARGTAC];
		%(****PERFORM REG ALLOC FOR ARG2 UNDER PNODE***)%
		IF NOT .PNODE[A2VALFLG] AND .PNODE[OPRCLS] NEQ SPECOP
		THEN
		BEGIN
			TREEPTR_.PNODE[ARG2PTR];
			ALCINREG(AFREEREG(.STBSYR,FALSE,.TREEPTR[DBLFLG]),.STBSYR,.STRGCT);
		END;
	END;


	ROUTINE CMPRHINLH=
	%(***LOCAL ROUTINE TO ALLOCATE THE COMPUTATION OF RHNODE TO BE
	     PERFORMED IN THE REGISTER ALLOCATED TO LHS, WHEN THE FIRST
	     ARG UNDER THE FIRST ARG OF RHNODE IS KNOWN TO BE EQUAL TO
	     THE VARIABLE ON THE LHS
	****)%
	BEGIN
		%(***IF THE COMPUTATION OF ARG2 UNDER RHS INCLUDES A REFERENCE
			TO THE VARIABLE FROM THE LHS, MUST COMPUTE ARG2 BEFORE
			COMPUTE ARG1 (SINCE THE COMPUTATION OF ARG1 WILL
			CLOBBER THE REG THAT HOLDS THAT VAR)
		***)%
		IF .ARG2NODE[RESRFFLG] AND NOT .RHNODE[RVRSFLG]
		THEN
		BEGIN
			RHNODE[RVRSFLG]_1;

			%(**IF ON COMPLEXITY PASS WE ALLOCATED ARG2 TO BE COMPUTED
				INTO FN-RETURN REG, AND THE COMPUTATION OF ARG1 WILL
				CLOBBER FN-RETURN REG, THEN WE MUST UNDO THAT ALLOCATION***)%
			IF .ARG2NODE[ALCRETREGFLG] AND .ARG1NODE[FNCALLSFLG]
			THEN
			BEGIN
				ARG2NODE[ALCRETREGFLG]_0;
				ARG2NODE[INREGFLG]_0;
				ARG2NODE[A1SAMEFLG]_0;
				ARG2NODE[A2SAMEFLG]_0;
			END
		END;


		%(***PERFORM REGISTER ALLOCATION FOR THE COMPUTATION OF ARG2 UNDER RHNODE
			(WE KNOW THAT THE VAL OF ARG1 WILL BE LEFT IN THE REG IN WHICH LHS
			IS ALLOCATED)
		****)%
		IF NOT .RHNODE[A2VALFLG] AND .RHNODE[OPRCLS] NEQ SPECOP
		THEN
		BEGIN
			TREEPTR_.ARG2NODE;
			ALCINREG(AFREEREG(.STBSYR,FALSE,.TREEPTR[DBLFLG]),.STBSYR,.STRGCT);

			%(***IF ARG2 IS COMPUTED BEFORE ARG1, THEN MUST NOT USE
				THE REG IN WHICH VAL OF ARG2 WAS LEFT IN COMPUTING ARG1**)%
			IF .RHNODE[RVRSFLG]
			THEN
			BEGIN
				OWN RB;
				IF (RB_RGTOSAVE(.ARG2NODE)) NEQ -1	!IF SOME REG MUST BE PRESERVED
									! TO PRESERVE VAL OF ARG2
				THEN
				BEGIN
					STBSYR_CLRBIT(.STBSYR,.RB);	!TAKE THAT REG OUT OF SET AVAILABL
					%(***IF THAT REG IS THE REG TO WHICH LHS WAS
						ALLOCATED, ARE IN AN IMPOSSIBLE SITUATION.
						THIS SHOULD NEVER OCCUR***)%
					IF .RB EQL .LHNODE[TARGTAC] THEN CGERR();
				END;
			END;
		END;

		%(***PERFORM ALLOCATION OF ARG1 UNDER RHNODE, COMPUTING ITS VAL INTO
			THE REG USED FOR LHS***)%
		CMPNODINLH(.ARG1NODE);

		RHNODE[TARGTAC]_.ARG1NODE[TARGTAC];
		RHNODE[A1SAMEFLG]_1;

		SETRHRGTOLH();		!SET FIELDS OF CSTMNT TO INDICATE THAT RHNODE WAS
					! COMPUTED INTO THE REG FOR LHNODE
	END;






	ROUTINE ALCTORETREG=
	%(*********************
		ROUTINE TO ALLOCATE THE RIGHT HAND SIDE WHEN IT HAS BEEN DETERMINED
		THAT IT CAN BE COMPUTED INTO THE FN RETURN REG, AND THE LHS
		IS ALSO A REGCONTENTS FOR THE FN RETURN REG
	***********************)%
	BEGIN
		TREEPTR_.RHNODE;
		ALCINREG(AFREEREG(.STBSYR,FALSE,.RHNODE[DBLFLG]),.STBSYR,.STRGCT);
		CSTMNT[ASMNTREG]_RETREG;	!USE RETREG FOR THE ASSIGNMNET
		CSTMNT[A1SAMEFLG]_1;
		CSTMNT[A2SAMEFLG]_1;
		RETURN TRUE
	END;

	ROUTINE MUSTSAVLHREG(ANODE)=
	%(***************
		TESTS WHETHER THE VALUE OF ANODE WILL BE INACCESSIBLE IF THE
		REGISTER THAT HOLDS THE VARIABLE ON THE LHS HAS BEEN CLOBBERED.
		THIS IS TRUE ONLY IF ANODE IS AN ARRAYREF THAT WILL HAVE THE
		LHS VAR AS ITS SUBSCRIPT OR FOR DUMMY TYPE CONVERSION NODES
		THAT HAVE THE LHS VAR UNDER THEM
	******************)%
	BEGIN
		MAP PEXPRNODE ANODE;
		IF .ANODE EQL .LHNODE THEN RETURN TRUE	!TO REF THE LHS VAR ITSELF,
								! THE VAL MUST BE PRESERVED
		ELSE
		IF .ANODE[OPRCLS] EQL ARRAYREF	!FOR AN ARRAYREF, IF THE INDEX
		THEN RETURN MUSTSAVLHREG(.ANODE[ARG2PTR])	! IS A NODE THAT REQUIRES THE LHS TO
								! BE PRESERVED

		ELSE
		IF .ANODE[OPRCLS] EQL TYPECNV
		THEN
		BEGIN
			%(***IF THE ARG UNDER A DUMMY TYPE-CNV NODE REQUIRES THE REG TO
				BE PRESERVED, THEN THE TYPE-CNVNODE DOES ALSO***)%
			IF NOCNV(ANODE) THEN RETURN MUSTSAVLHREG(.ANODE[ARG2PTR])
			ELSE RETURN FALSE
		END
		ELSE RETURN FALSE
	END;











	LHNODE_.CSTMNT[LHEXP];

	%(***IF RHS IS A SCALAR, SIMPLY SET TARGET TO REG ALLOCATED FOR LHS***)%
	IF .CSTMNT[A2VALFLG]
	THEN
	BEGIN
		CSTMNT[ASMNTREG]_.LHNODE[TARGTAC];
		CSTMNT[A1SAMEFLG]_1;
		IF .CSTMNT[RHEXP] EQL .LHNODE
			OR REGCONTAINING(.CSTMNT[RHEXP]) EQL .LHNODE[TARGTAC]	!IF THE VAR ON RHS WAS ALREADY IN THE DESIRED REG
		THEN
		CSTMNT[A2SAMEFLG]_1
		ELSE REGCLOBB(.CSTMNT[ASMNTREG]);	!IF LEFT SOME VAR IN LHS REG WHILE
							! COMPUTING RHS, THAT VAR IS NOW NO LONGER THERE

		RETURN TRUE;
	END;


	RA_.LHNODE[TARGTAC];
	RHNODE_.CSTMNT[RHEXP];


	%(***IF THE LHS IS THE FN-RETURN REG AND THE RHS HAS ALREADY BEEN DETERMINED
		TO BE EVALUATED TO IT, THEN JUST DO
		REST OF ALLOCATION FOR RHS EXPRESSION***)%
	IF .RA EQL RETREG AND .RHNODE[ALCRETREGFLG] AND .RHNODE[TARGTAC] EQL RETREG AND .RHNODE[INREGFLG]
	THEN RETURN ALCTORETREG();


	%(***IF RHS IS AN ARRAY-REF - LOAD THE VAL INTO THE DESIRED REG***)%
	IF .RHNODE[OPRCLS] EQL ARRAYREF
	THEN
	BEGIN
		TREEPTR_.RHNODE;
		ALCARRAY(.STBSYR,.STRGCT);
		CSTMNT[ASMNTREG]_.LHNODE[TARGTAC];
		CSTMNT[A1SAMEFLG]_1;
		REGCLOBB(.CSTMNT[ASMNTREG]);
		RETURN TRUE;
	END;

	%(***IF THERE IS NO REFERENCE TO THE VARIABLE ON THE LHS IN THE
	     EXPRESSION ON THE RHS, SIMPLY ALLOCATE THE EXPRESSION TO BE
	     COMPUTED INTO THE REG USED FOR THE VARIABLE IF POSSIBLE
	****)%
	IF NOT .RHNODE[RESRFFLG]
		AND NOT (.RA EQL RETREG AND .RHNODE[FNCALLSFLG])	!IF LHS IS FN RETURN REG
								! AND HAVE FNCALLS ON RHS
	THEN
	BEGIN
		OWN STBSYR1;		!SET OF REGS AVAILABLE FOR USE IN COMPUTING THE
					! THE VAL OF THE RHS

		%(***FOR COMPUTING THE RHS OF THIS STMNT, CAN USE THE REG TO WHICH
			THE LHS WAS ALLOCATED (SINCE THE LHS VARIABLE DOES NOT OCCUR
			IN THE RHS EXPRESSION)***)%
		STBSYR1_SETBIT(.STBSYR,.RA);

		%(**WHEN TARGETTING TO REG 0 (FN RET REG) ALLOW REG 1 TO BE USED ALSO**)%
		IF .RA EQL RETREG
		THEN STBSYR1_SETBIT(.STBSYR1,RETREG+1);
		TREEPTR_.RHNODE;
		ALCINREG(.RA,.STBSYR1,ONESCOUNT(.STBSYR1));
		CSTMNT[ASMNTREG]_.LHNODE[TARGTAC];
		CSTMNT[A1SAMEFLG]_1;
		IF .RHNODE[TARGTAC] EQL .CSTMNT[ASMNTREG] AND .RHNODE [INREGFLG]
		THEN
		CSTMNT[A2SAMEFLG]_1
		ELSE REGCLOBB(.CSTMNT[ASMNTREG]);	!IF LEFT SOME VAR IN LHS REG WHILE
							! COMPUTING RHS, THAT VAR IS NOW NO LONGER THERE
		RETURN TRUE;
	END;




	%(***IF RHS CONTAINS A REFERENCE TO LHS VAR AND IS A SPECIAL OPERATOR
	     (P2MUL OR P2DIV), CHECK FOR ARG1 OF THAT OPERATOR EQUAL
	     TO THE LHS - IF IT IS, PERFORM THE OPERATION IN THE REG
	     ALLOCATED TO LHS - OTHERWISE GIVE UP
	****)%
	IF .RHNODE[OPRCLS] EQL SPECOP
	THEN
	BEGIN
!**[446] LHINREGALC @6120 SJW 16-SEP-76
![446] MUST NOT CLOBBER LHS REG IF P2PL1OP OR EXPCIOP NOT A POWER OF 2
%[446]%		IF .RHNODE [OPERSP] EQL P2PL1OP OR
%[446]%		   (.RHNODE [OPERSP] EQL EXPCIOP AND
%[446]%		    NOT POWOF2 (.RHNODE [ARG2PTR]))
%[446]%			THEN RETURN FALSE;
		IF .RHNODE[ARG1PTR] EQL .LHNODE
		THEN
		BEGIN
			SETRHRGTOLH();
			RHNODE[A1SAMEFLG]_1;
			RETURN TRUE;
		END
		ELSE
		RETURN FALSE;
	END;


	%(***IF RHS CONTAINS A REFERENCE TO LHS VAR AND IS A RELATIONAL,
	     FUNCTION CALL, TYPE-CONVERSION, OR NEG/NOT - DON'T BOTHER
	****)%
	IF .RHNODE[OPRCLS] NEQ ARITHMETIC AND .RHNODE[OPRCLS] NEQ BOOLEAN
	THEN
	RETURN FALSE;


	%(********WHEN THE LHS IS THE FN RETURN REG AND THE RHS IS AN ARITH OR BOOLEAN
		EXPRESSION THAT CONTAINS FUNCTION CALLS BUT WAS NOT ALLOCATED TO THE FN RETURN
		REG ALREADY, CHECK FOR RHS OF THE FORM:
			<EXPR> OP <FN-CALL>
		  OR	<EXPR> OP <EXPR ALLOCATED TO FN RETURN REG>
		AND REVERSE THE 2 OPERATORS IF CAN DO SO
	*********)%
	IF .RA EQL RETREG
	THEN
	BEGIN
		ARG1NODE_.RHNODE[ARG1PTR];
		ARG2NODE_.RHNODE[ARG2PTR];
		IF .ARG2NODE[ALCRETREGFLG]	!IF ARG2 WAS ALLOCATED TO FN RETURN REG
			AND .ARG2NODE[INREGFLG] AND .ARG2NODE[TARGTAC] EQL RETREG
			AND COMMUTATIVE(RHNODE)	!AND THE RHS EXPRESSION IS COMMUTATIVE
			AND NOT .ARG1NODE[FNCALLSFLG]	!AND ARG1 DOES NOT INCLUDE FN CALLS
		THEN
		BEGIN
			EXCHARGS(.RHNODE);	!LET ARG1 BE THE ARG COMPUTED INTO FN RETURN REG
			RHNODE[RVRSFLG]_0;	!ALWAYS COMPUTE THAT ARG FIRST
			RHNODE[ALCRETREGFLG]_1;	!COMPUTE THE RHS IN THE FN RET REG
			RHNODE[TARGTAC]_RETREG;
			RHNODE[INREGFLG]_1;
			RHNODE[A1SAMEFLG]_1;	!ARG1 OF RHS WONT HAVE TO BE LOADED INTO THE REG
			RETURN ALCTORETREG()
		END
		ELSE RETURN FALSE;	!IF LHS IS FN RETURN REG, RHS CONTAINS FN CALLS
				! AND NEITHER RHS, NOR ARG2 UNDER RHS WAS ALLOCATED TO FN
				! RET REG, GIVE UP ON OPTIMALITY
	END;


	%(*******WHEN RHS EXPRESSION IS ARITHMETIC OR BOOLEAN AND CONTAINS
	     A REFERENCE TO LHS VAR***)%
	!**;[546], LHINREGALC @6202, DCE, 14-MAR-77
	!**;[546], FIX UP 403 TO CONSIDER MORE CASES LIKE:
	!**;[546],	I=I/J
	!**;[546],	I=(I+K)/J
	!**;[546],	I=J+(I/K)
	!**;[546], AND OTHER ASSOCIATED PROBLEMS!
	!**;[546], THESE ALL DEPEND UPON THE REG AFTER THE ONE
	!**;[546], IN WHICH THE LHS IS LIVING GETTING OVERWRITTEN BY
	!**;[546], SOME OPERATION PERFORMED DIRECTLY IN THE REG FOR LHS.
	%[546]%	IF CLOBBNX(.RHNODE) THEN RETURN FALSE;


	%(***IF ARG1 IS EQUAL TO LHS VAR, SIMPLY PERFORM OP IN LHS REG***)%
	IF .RHNODE[ARG1PTR] EQL .LHNODE
	THEN
	BEGIN
		SETRHRGTOLH();
		CMPNODINLH(.RHNODE);
		RETURN TRUE;
	END;


	%(***IF ARG2 IS EQUAL TO LHS VAR. ATTEMPT TO SWAP THE ARGS.
	     IF CAN DO SO, THE PERFORM OP IN LHS REG***)%
	IF .RHNODE[ARG2PTR] EQL .LHNODE
	THEN
	BEGIN
		IF COMMUTATIVE(RHNODE)
		THEN
		BEGIN
			SWAPARGS(RHNODE);
			SETRHRGTOLH();
			CMPNODINLH(.RHNODE);
			RETURN TRUE;
		END
		ELSE
		RETURN FALSE
	END;


	%(***SEARCH DOWN ONE LEVEL ONLY FOR REFERENCES TO LHS.
		THUS CAN HANDLE:
		A=A+C
		A=A+B+C
		A=A*B+C*D
		BUT NOT:
		A=A*B+C*D+E*F
		A=A+B+C+D
	****)%
	ARG1NODE_.RHNODE[ARG1PTR];
	ARG2NODE_.RHNODE[ARG2PTR];
	%(***IF EITHER OF THE ARGS WILL BE IMPOSSIBLE TO REFERENCE IF THE
		OTHER ARG IS COMPUTED INTO THE REG HOLDING THE LHS VAR,
		THEN GIVE UP. (EG I=I*J+K(I) CANNOT BE COMPUTED BY COMPUTING
		I*J IN THE REG FOR I)
	*****)%
	IF .ARG1NODE[RESRFFLG] AND .ARG2NODE[RESRFFLG] AND .RHNODE[OPRCLS] NEQ SPECOP
	THEN
	BEGIN
		IF MUSTSAVLHREG(.ARG1NODE) OR MUSTSAVLHREG(.ARG2NODE)
		THEN RETURN FALSE
	END;
	IF .ARG1NODE[OPRCLS] EQL ARITHMETIC OR .ARG1NODE[OPRCLS] EQL BOOLEAN OR .ARG1NODE[OPRCLS] EQL SPECOP
	THEN
	BEGIN
		IF .ARG1NODE[ARG1PTR] EQL .LHNODE
		THEN
		BEGIN
	!**;[546], LHINREGALC @6264 (ARG1PTR IS LHNODE), DCE, 14-MAR-77
	%[546]%		IF CLOBBNX(.ARG1NODE) THEN RETURN FALSE;
			CMPRHINLH();
			RETURN TRUE;
		END
		ELSE
		IF .ARG1NODE[ARG2PTR] EQL .LHNODE
		THEN
		BEGIN
			IF COMMUTATIVE(ARG1NODE)
			THEN
			BEGIN
				SWAPARGS(ARG1NODE);
				CMPRHINLH();
				RETURN TRUE;
			END;
		END;
	END;
	IF NOT .RHNODE[A2VALFLG] AND COMMUTATIVE(RHNODE)
	THEN
	BEGIN
		IF .ARG2NODE[ARG1PTR] EQL .LHNODE
		THEN
		BEGIN
	!**;[546], LHINREGALC @6286 (ARG2NODE[ARG1PTR] = LHNODE), DCE, 14-MAR-77
	%[546]%		IF CLOBBNX(.ARG2NODE) THEN RETURN FALSE;
			SWAPARGS(RHNODE);
			RHNODE[RVRSFLG]_NOT .RHNODE[RVRSFLG];	!WHEN EXCHANGE ARG1 AND ARG2
								! COMPUTE THEM IN THE ORDER
								! ORIGINALLY DETERMINED
			ARG1NODE_.RHNODE[ARG1PTR];
			ARG2NODE_.RHNODE[ARG2PTR];
			CMPRHINLH();
			RETURN TRUE;
		END
		ELSE
		IF .ARG2NODE[ARG2PTR] EQL .LHNODE
		THEN
		BEGIN
			IF COMMUTATIVE(ARG2NODE)
			THEN
			BEGIN
				SWAPARGS(ARG2NODE);
				SWAPARGS(RHNODE);
				RHNODE[RVRSFLG]_NOT .RHNODE[RVRSFLG];	!WHEN EXCHANGE ARG1 AND ARG2
								! COMPUTE THEM IN THE ORDER
								! ORIGINALLY DETERMINED
				ARG1NODE_.RHNODE[ARG1PTR];
				ARG2NODE_.RHNODE[ARG2PTR];
				CMPRHINLH();
				RETURN TRUE;
			END
		END
	END;


	RETURN FALSE;
END;
END
ELUDOM