Google
 

Trailing-Edge - PDP-10 Archives - AP-D480B-SB_1978 - gcmnsb.bli
There are 12 other files named gcmnsb.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) 1974,1977 BY DIGITAL EQUIPMENT CORPORATION
MODULE GCMN(RESERVE(0,1,2,3),SREG=#17,FREG=#16,VREG=#15,DREGS=4,GLOROUTINES)=
BEGIN


!AUTHOR: NORMA ABEL/HPW/MD/DCE/SJW


!	REQUIRES FIRST, TABLES, OPTMAC

GLOBAL BIND GCMNV=5^24 + 1^18 + 103;	!VERSION DATE: 29-DEC-76

%(REVISION HISTORY

18	-----	-----	MAKE T A PARAMETER TO CMNLNK
19	-----	-----	DONT USE IDADDR SO DATA OPTS CAN BE DONE
20	_____	_____	FIX FINDTHESPOT TO HANDLE IOLSCLS NODES
21	-----	-----	IN MOVCNST FIX IDOPTIM SETTING AND SEARCH FOR
			NON-STATEMENT PARENT
22	-----	-----	DONT CALL CHKINIT WITH AN ARG LIST
23	-----	-----	CALL IOGELO FOR READ/WRITE/ENOCDE/DECODE
24	-----	-----	KEEP CNSMOVFLG SET THRU 2ND CALL TO MOVCNST
25	-----	-----	CALL IOGELO FOR RERED STATEMENT
26	-----	-----	IMPLDO NO LONGER A GLOBAL
27	-----	-----	ADD CHK TO DOTOHASGN TO PREVENT SELF LINKING
			WHEN IT EITHER LOOPS OR DELETES
28	-----	-----	ADD CODE TO DOTOHASGN FOR SIMPLE ASSIGNMENT MOTION
29	-----	-----	SAVE AND RESTORE ENTRY[1] IN CHKINIT
			MAKE GLOBDEPD ZERO DEFPTS IN FRONT OF THE LOOP
30	-----	-----	FIX FUMBLE IN 29
31	-----	-----	PATCH CHKDOM FOR 29
32	-----	-----	PATCHES MADE SEPARATELY ON 31,45
33	-----	-----	INSERT CODE TO UNDO ARRAY HASH ENTRIES POINTED
			TO BY EXPRESSION NODES. ROUTINE SCRUBARRAY
			AND CODE IN MOVCNST
34	-----	-----	FORGOT CALL TO SRCUBARRAY LAST TIME
35	-----	-----	FIX UP SOME ARRAY STUFF IN CHKDOM
36	-----	-----	CAUSE GLOBMOV TO SET TOLENTRY BIT IN
			SYMBOL OF .O VARIABLE
37	-----	-----	ADD PUTBACKARRAY, AND STUFF FOR ARRAY REFS
			UNDER FUNCTIONS AS COMMON SUBS
38	-----	-----	FIX PUTBACKARRAY AND SCRUBARRAY
39	-----	-----	ON CONSTANT MOTION ITERATION , SKIP INNER MORE LOOPS
40	-----	-----	ADD EDITS FROM 31,45
41	-----	-----	ADD CALL TO SCRUBARRAY IN FRONT OF SLING HASH
42	-----	-----	MAKE MAKETRY KNOW ABOUT TREE SHAPE
43	-----	-----	REMOVE ARRAY FUDGE IF EXPR DOESNT MAKE IT
			INTO THE HASH TABLE
44	-----	-----	DO NOT NEXTUP ON IOLSCLS NODES
			OUT OF MOVCNST
45	-----	-----	TYPO IN PUTBACKARRAY IS KILLING NODES
46	-----	-----	SET AND TEST NOHHASSLE BIT IN CHKDOMINANCE
47	-----	-----	FIX ORDER OF ARGS WHEN BUILDING STGHT NODES
			FROM ANRY ONES IN MOVCNST
48	-----	-----	MAKE NEWCOPY AND PUTBACKARRAY USE
			LINKED LIST OF ARRAY REFS FROM EXPRESSION
			HASH TABLE
49	_____	_____	MAKE A1 AND A2 ARREF CHECK THE VALFLG ON THE
			ARRAYREF
50	-----	-----	FNARRAY USING ARAYREF TO CALL XPUNGE INSTEAD OF
			FUNCTION REFERENCE
51	-----	-----	PUTBACKARRAY IS NOT ALWAYS
			SETTING ARY BUT ALWAYS ZEROS ARY[USECNT]
52	-----	-----	FIX ERROR MESSAGES
53	-----	-----	DITTO
54	-----	-----	CHKDOMINANCE MUST ZERO PHI FOR INVALID
			ATTEMPTS TO ENTER AN EXPRESSION
55	-----	-----	PASS NEDSANEG FOR CONSTANT MOTION COMPS
56	-----	-----	MAKE DOTOASGN COGNISCENT FO ARRAY REF STUFF
57	-----	-----	FIX A BAD RETURN FROM CHKDOMINANCE THAT DID
			NOT 'TIL NOW ZERO PHI FOR THE ARRAYREF STUFF
58	-----	-----	MAKE SURE DOTOHASGN LOOKS AT ENCODE/DECODE
			AND REREAD
59	-----	-----	FIX 58
60	-----	-----	MAJOR CHANGE IN CONCEPT IN FINDTHESPOT.
			INSERT NEW STATEMENT AFTER ALL OTHERS
			CREATED BY OPTIMIZER AT THIS POINT.
61	-----	-----	REFINE 60 A LITTLE TO PUT THE COMMON SUB
			INFRONT OF THE CURRENT STATEMENT IF WE HAPPEN
			TO RUN INTO IT.
62	-----	-----	IN CHKDOMINANCE, WHEN AN ARRAY EXPRESSION
			FAILS FOR CONSIDERATION AS A COMMON SUB,
			REPLACE THE ARRAY PART (NOW A POINTER TO
			A HASH ENTRY) WITH A UNIQUE ARRAY REF
			BY USING NEWCOPY INSTEAD OF A BLIND SUBS.
			OF THE FIRST ARRAY REF
63	-----	-----	SCAN THE PARENT POINTER CHAIN FOR AN EXPRESSION
			IN CHKDOMINANCE TO MAKE SURE THAT THE
			STATEMENT USED IN DETERMINING THE MOTION PLACE
			AND ALSO ELIGIBILITY FOR MOTION IS THE STATEMENT
			OF WHICH THE EXPRESSION IS A PART. IF CALLED THRU
			NEXTUP NOT DOING THIS MAY CAUSE ERRONEOUS MOTION
			PLACES TO BE ESTABLISHED.
64	-----	-----	63 WILL NOT WORK FOR EXPRESSIONS UNDER AN
			IMPLIED DO LOOP. MAKE SURE OPTIMIZER INFO
			IS THERE TOO.
65	-----	-----	63 IS REALLY A GOOD IDEA USE IT TO PREVENT
			BOGUS ENTRIES WHICH IS , OF COURSE, ITS PURPOSE.
66	-----	-----	MOVCNST IS GETTING CONFUSED  AND  CALLING
			NEXTUP WHEN IT SHOULD NOT
67	243	14916	INT COMP ERROR BECAUSE DOTOHASGN DOES NOT
			TEST FOR FULL OPRS FIELD.
68	244	14940	ADD CONDITION TO FINDTHESPOT
69	340	16989	PREVENT CALL TO MATCHER FROM CHANGING
			THE VALUE OF PHI.
70	370	17938	TAKE OUT [244] - IT WAS INCORRECT
71	401	17813	GET HASH PTRS OUT OF TREES (ARRAYREFS)
72	VER5	-----	TURN OFF "CSE SEEN" FLAG SO GLOBELIM RECALLABLE
			REMOVE MOVED .O FROM BUSY & POSTDOM LISTS IN DOTOHASGN
			REDUCE .R + X TO .O IN MOVCNST
			FIX DOUBLE WHILE LOOP ERROR IN GLOBDEPD
			CHECK ORFIXFLG & CALL DOTOFIX IN GLOBDEPD
			IGNORE HASH TBL ENTRIES BUILT BY DOTORFIX IN MOVCNST
			FIX BUG SO EMPTY HASH ENTRIES ARE IGNORED IN MOVCNST
			SET NOALLOC ON SUBSUMED .O IN GLOBDEPD
			CHECK GLOBELIM2 IN CHKINIT
			CHECK OMOVDCNS IN GLOBDEPD
			ZERO ONLY EXPRUSE IN GLOBDEPD
			SET OMOVDCNS IN MOVCNST
			RESET OMOVDCNS ON .O WHICH BECOMES CSE IN DOTOHASGN
			DON'T SUBSUME .O = .R + X IN DOTOHASGN
			CALL IOGELO ON 1ST GLOBELIM ONLY IN GLOBELIM &
			  THEN SET/RESET IMPLIED DO FLAG AROUND CALL
73	416	QA650	ZERO USECNT IN HASH TBL FOR .R+X IN MOVCNST
			  IF CAN'T MOVE .R+X SO HASH TBL ENTRY WILL
			  BE IGNORED ON NEXT LOOP THRU TBL
74	437	QA771	DON'T LET DOTOHASGN MOVE .O=EXPR IF .O CAME
			  FROM .R (EXPR CAN MOVE AS CONSTANT)
75	440	QA771	DON'T NEXTUP .O IF CAME FROM .R IN MOVCNST
76	455	QA784	CAN'T MOVE EXPRESSIONS OUT OF IMPLIED DO IF
			  INSIDE LOGICAL IF
77	456	QA784	FIX FINDTHESPOT SO CALLER TELLS IT WHERE TO STOP
			ADD NEW ROUTINE FINDPA FOR GLOBMOV AND DOTOHASGN
			CALL FINDTHESPOT WITH 2ND PARAM IN GLOBMOV AND
			  DOTOHASGN
100	507	-----	FIX EDIT 440 TO ALLOW NEXTUP OF .O WHICH CAME
			  FROM .R IN MOVCNST IF MOM IS ARITHMETIC
101	513	QA771	IN MOVCNST WHEN .O IS CREATED, PASS ORFIXFLG
			  UP FROM ANY .O BEING SUBSUMED
			CHANGE [507] TO FREE VARAIBLE T IN MOVCNST
102	514	QA806	IN MOVCNST IF NARY, INSURE A .R IS 1ST ARG
			  SINCE [V5] CODE EXPECTS .R + X NOT X + .R

	BEGIN VERSION 5A, 7-NOV-76

103	526	QA1035	IN CHKDOM IF FNARY AND NO MATCH ON "FUNC(ARRAYREF)",
			  PUT BACK ARRAYREF SO HASH ENTRY NOT IN TREE
)%

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

REQUIRE OPTMAC.BLI;



OWN T,TS,LSTWARNLINE,PB,P1,P2,PO;

MAP BASE T:TS:PB:P1:P2:PO;

FORWARD FINDTHESPOT,PUTBACKARRAY;


!**[456] NEW ROUTINE FINDPA @3661 BEFORE DOTOHASGN SJW 22-SEP-76

ROUTINE  FINDPA  (EXPR)  =
BEGIN

!	FIND STATEMENT IN WHICH THIS EXPR IS
!	CALLED BY GLOBMOV AND DOTOHASGN FOR STOPPING POINT FOR
!	  FINDTHESPOT

	MAP PHAZ2  EXPR;
	EXTERNAL SKERR;
	LOCAL PHAZ2  P;

	P _ .EXPR [PARENT];
	WHILE  TRUE  DO
	  BEGIN
	    IF .P EQL 0
	      THEN SKERR ();		! 0 PAPA IS ERROR
	    IF .P [OPRCLS] EQL STATEMENT OR
	       .P [OPRCLS] EQL IOLSCLS
	      THEN RETURN (.P);		! FOUND PAPA STATEMENT
	    P _ .P [PARENT];
	  END;				! OF WHILE  TRUE  DO
END;					! OF ROUTINE FINDPA

ROUTINE DOTOHASGN(EXPR,PHI)=
BEGIN

	!ROUTINE CHECKS THE PARENT OF EXPR.
	!IF THE PARENT IS AN ASSIGNMENT STATEMENT OF THE FORM
	!.OXXX=EXPR THEN PHI[TEMPER] IS SET TO THE .O
	!VARIABLE. THEN THE STATEMENT IS LINKED OUT
	!OF THE TREE WHERE IT IS AND INTO THE TREE AT
	!PHI[STPT]
%[V5]%!	BUT ******* DONT SUBSUME (OR MOVE) .O = .R + X SINCE .R CANT
%[V5]%!	              MOVE OUTSIDE LOOP

	LABEL LINEAR;
	EXTERNAL SKERR,TOP;
	EXTERNAL SAVSPACE,UNLIST,LENTRY,LOOP;

%[V5]%	EXTERNAL  UNBUSY;

	MAP PHAZ2 TOP;
	MAP BASE EXPR:PHI;
	REGISTER BASE T:TS;

%[V5]%	T _ .EXPR [ARG1PTR];
%[V5]%	IF .T [IDDOTO] EQL SIXBIT ".R"
%[V5]%	  THEN RETURN;

	T_.EXPR[PARENT];
	IF .T NEQ 0 THEN
	BEGIN
		IF .T[OPRS] EQL ASGNOS AND .T[SRCISN] EQL 0 THEN	![243]
		BEGIN
			TS_.T[LHEXP];
			IF .TS[IDDOTO] EQL SIXBIT".O" THEN
			BEGIN

![437] DOTOHASGN @3690 SJW 2-SEP-76
![437]	.O=EXPR CAN'T MOVE IF .O CAME FROM .R SINCE THIS ASSIGNMENT
![437]	  STATEMENT IS .R INITIALIZATION.  EXPR CAN MOVE AS CONSTANT
%[437]%			  IF .TS [ORFIXFLG]
%[437]%			    THEN RETURN;
%[V5]%!			  .O IS NOW A COMSUB EVEN IF IT MOVED AS
%[V5]%!			    A CONSTANT TO GET HERE
%[V5]%
%[V5]%			  TS [OMOVDCNS] _ 0;

!**[456] DOTOHASGN @3706 SJW 22-SEP-76
![456] GET STOPPING POINT FOR FINDTHESPOT
%[456]%				P1 _ FINDTHESPOT (.PHI [STPT],
%[456]%				                  IF .PHI [STPT] EQL .LENTRY
%[456]%						    THEN .TOP
%[456]%						    ELSE FINDPA (.PHI [LKER])
%[456]%						 );
				!LINEAR SEARCH FOR THE STATEMENT IN
				!FRONT OF T
				P2_.TOP;
			LINEAR: WHILE .P2 NEQ 0 DO
				BEGIN
				IF .P2[SRCLINK] EQL .T THEN LEAVE
				 LINEAR;
				IF (.P2[OPRS] GEQ READOS) AND (.P2[OPRS]
				LEQ REREDOS) THEN
				BEGIN
					LOCAL BASE SAVEP2;
					SAVEP2_.P2;
					P2_.P2[IOLIST];
					WHILE .P2 NEQ 0 DO
					BEGIN
						IF .P2[SRCLINK] EQL .T THEN LEAVE LINEAR;
						P2_.P2[SRCLINK]
					END;
					P2_.SAVEP2
				END;
				P2_.P2[SRCLINK]
				END;
				IF .P2 EQL 0 THEN SKERR();
				!SET IDOPTIM FIELD SO THE WE CAN
				!GLOBLDEPD THESE LATER
				TS[IDOPTIM]_.EXPR;

				!CHECK THAT P1 (PLACE GOING) IS
				!NOT ALREADY WHERE IT IS (P2)

				IF .P1 NEQ .P2 THEN
				BEGIN
					TS_.P1[SRCLINK];
					P1[SRCLINK]_.T;
					P2[SRCLINK]_.T[SRCLINK];
					T[SRCLINK]_.TS;
				END;

				PHI[TEMPER]_.T[LHEXP];

				!IF THERE IS AN ARRAY INVOLVED THEN
				!PUT THE ARRAYREFERENCE BACK IN PLACE

				IF .PHI[A1ARY] OR .PHI[A2ARY] THEN
					PUTBACKARRAY(.PHI,STGHT);

				!IF IT MOVED OUT OF THE LOOP, TAKE IT
				!OFF THE LIST OF ITEMS THAT CHANGED IN
				!THE LOOP
				IF .PHI[STPT] EQL .LENTRY AND .LOOP NEQ  0 THEN
				BEGIN
					IF NOT .IMPLDO THEN
					BEGIN
						IF UNLIST(.TOP[DOCHNGL],.T[LHEXP],CHNGSIZ) THEN
						BEGIN
							P1_.TOP[DOCHNGL];
							TOP[DOCHNGL]_.P1[RIGHTP];
							SAVSPACE(CHNGSIZ-1,.P1);
						END;
%[V5]%						UNBUSY (.T);	! REMOVE FROM BUSY LIST
					END;
				END;
						
			END;
		END;
	END;
END;

!**********************************
!
ROUTINE FINDTHESPOT (PLACE, BARRIER) =	![456]
!**[456] FINDTHESPOT @3777 SJW 22-SEP-76
![456] 2ND PARAM FOR FINDTHESPOT IS PLACE NOT TO MOVE PAST
BEGIN
	MAP BASE PLACE;
%[456]%	MAP BASE BARRIER;
	EXTERNAL PREV,CSTMNT;

		!PUT AT THE END OF ALL OTHER
		!POSSIBLE STATEMENTS AT THIS
		!POINT
		!THAT WERE CREATED BY THE OPTIMIZER. THE RATHER
		!SHAKY TEST OF SRCISN==0 IS USED.
![456]	THE ADDITIONAL CONSTRAINT IS ADDED THAT THE
![456]	STATEMENT WE ARE ABOUT TO PASS BY IS NOT
![456]	THE PARAM BARRIER = TOP IF PLACE = LENTRY,
![456]	ELSE THE STATEMENT THE ORIGINAL EXPR CAME FROM
![456]	(FOUND BY FINDPA FOR CALLER) FOR COMSUB BEING RELOCATED, IE,
![456]	CAN'T PUT .O INITIALIZATION AFTER .O USEAGE

		PREV_.PLACE;
		PLACE_.PLACE[SRCLINK];

		!DONT BOTCH UP I/O LISTS EITHER
		WHILE .PLACE[OPRCLS] EQL STATEMENT DO
			IF .PLACE[SRCISN] EQL 0
			 AND .PLACE[SRCID] EQL ASGNID
!**[456] FINDTHESPOT @3798 SJW 22-SEP-76
%[456]%			AND .PLACE NEQ .BARRIER
	!**;[370], FINDTHESPOT @3726, DCE, 13-APR-76
	!**;[370], REMOVE [244], THE REAL FIX IS IN REDUCE
	![370]		AND (.PLACE[SRCOPT] EQL 0 ) ![244] NEW CONSTRAINT
			THEN
			BEGIN
				PREV_.PLACE;
				PLACE_.PLACE[SRCLINK];
			END ELSE
				RETURN(.PREV);

			.PREV
END;

ROUTINE GLOBMOV (CNODE, PHI, OTEMP) =		![456]
!**[456] GLOBMOV @3812 SJW 22-SEP-76
![456] PASS GLOBMOV ENTIRE HASH ENTRY FROM CMNMAK
!MOVE GLOBAL COMMON SUB-EXPRESSION TO FINAL RESTING PLACE.
BEGIN
%[456]%	EXTERNAL LOOP,MAKASGN,LENTRY,TOP;
	MAP BASE LOOP;
%[456]%	MAP PHAZ2 PHI:OTEMP:CNODE;
%[456]%	LOCAL PHAZ2  PLACE;
!CALLED BY GLOBAL OPTIMIZER ONLY.
!CNODE WILL POINT TO THE COMMON SUB-EXPRESSION ITSELF. (NOT
!A COMMON SUB-EXPRESSION **NODE**.
!PLACE POINTS TO THE PLACE WHERE THE STATEMENT THAT IS BUILT
!WILL BE LINKED IN. OTEMP IS THE LHS OF THE STATEMENT.

!THE BASIC FUNCTION OF THE ROUTINE IS TO BUILD T=CMNSB STATEMENT
!AND LINK IT INTO THE ENCODED SOURCE TREE.

		!GENERATE
		!  T=EXPRESSION NODE
		!MAKE SOURCE NODE
		!****NOTE****
		!CANNOT SET EXPRESSION PARENT
		!AS TEMP IS NOT YET LINKED
		!BACK IN. MUST SET PARENT IN
		!GLOBLDEPD

		P1_.CNODE[PARENT];
		PO_MAKASGN(.OTEMP,.CNODE );
		CNODE[PARENT]_.P1;

		!RETURNS POINTING TO THE PLACE TO
		!PUT IT.
!**[456] GLOBMOV @3842 SJW 22-SEP-76
![456] CALL FINDTHESPOT WITH 2ND PARAM = PLACE TO STOP
%[456]%		PLACE _ .PHI [STPT];
%[456]%		P1 _ FINDTHESPOT (.PLACE,
%[456]%				  IF .PLACE EQL .LENTRY
%[456]%				    THEN .TOP
%[456]%				    ELSE FINDPA (.PHI [LKER])
%[456]%				 );
		!LINK IT IN

		PO[SRCLINK]_.P1[SRCLINK];
		P1[SRCLINK]_.PO;

		!IF MOVED OUT OF THE LOOP THEN SET TOLENTRY BIT

		IF .PLACE EQL .LENTRY THEN
			OTEMP[IDATTRIBUT(TOLENTRY)]_1;

END;
!
!

!
GLOBAL ROUTINE GETOPTEMP(VTYP)=
	!CREATE A .O TEMPORARY FOR THE OPTIMIZER
!	VERYFRST (NOT MNUMONIC OR APROPRIATE BUT THERE) IS A COUNTER
!	A NAME IS MADE WITH .OVERYFRST.
BEGIN
	EXTERNAL TBLSEARCH;
	EXTERNAL VERYFRST;
	REGISTER BASE HEAD;

	NAME_IDTAB;
	ENTRY_SIXBIT'.O'+MAKNAME(VERYFRST);
	!LOOK IT UP IN THE SYMBOL TABLE
	HEAD_TBLSEARCH();
	HEAD[VALTYPE]_.VTYP;
	VERYFRST_.VERYFRST+1;
	.HEAD
END;
ROUTINE CHKINIT(VAR)=
BEGIN
	!ROUTINE CHECKS TO SEE WHETHER OR NOT VAR IS
	!INITIALIZED

!	NO WARNINGS ON 2ND GLOBELIM SINCE THEY WERE GIVEN ON 1ST PASS

	MAP BASE VAR;
	EXTERNAL WARNERR;
	!IT IS NOT INITIALIZED (WE ALREADY KNOW ITS A MAIN SECTION OF CODE
	!AND THE DEFINITION POINT IS LENTRY) IF
	!	1. IT IS NOT IN A DATA STATEMENT
	!	2. IT IQ NOT A FORMAL
	!	3. IT IS NOT A CONSTANT
	!	4. IT IS NOT IN COMMON
	!	5. IT IS NOT IN AN EQUIVALENCE STATEMENT

%[V5]%!	DO NOT ALLOW CHECK ON COMPILER VAR (.O, .R) !

	!FOR THE ARRAY REFERENCE STUFF, CHECK FOR OPRCLS EQL DATAOPR
	!IF WE ARE PASSING A HASH TABLE ENTRY THE OPRCLS FIELD
	!JUST HAPPEND TO MATCH THE HOP FIELD SO A CHECK ON OPRCLS
	!IS VALID

%[V5]%	MACRO  IDDOT  =  0,3,30,6$;

%[V5]%	IF .GLOBELIM2			! NO WARNINGS ON 2ND PASS
%[V5]%	  THEN RETURN;

	IF .VAR[OPRCLS] NEQ DATAOPR THEN RETURN;

%[V5]%	IF .VAR [IDDOT] EQL SIXBIT "."	! CANT CHECK COMPILER VARS
%[V5]%	  THEN RETURN;

	IF NOT .VAR[IDATTRIBUT(INDATA)] AND
	   .VAR[OPR1] NEQ CONSTFL AND
	   NOT .VAR[FORMLFLG]
	   AND NOT .VAR[IDATTRIBUT(INCOM)]
	   AND NOT .VAR[IDATTRIBUT(INEQV)]
	   AND .LSTWARNLINE NEQ .VAR THEN
	BEGIN
		!NOTE THE MISSING DOT IS DELIBERATE.
		EXTERNAL ISN;
		WARNERR(VAR[IDSYMBOL],.ISN,E79<0,0>);
		LSTWARNLINE_.VAR;
	END;
END;

FORWARD NEWCOPY;
ROUTINE CHKDOMINANCE(CNODE,SHAPE)=
BEGIN


EXTERNAL TOP,LENTRY,MAKETRY,BOTTOM,PHI,NAN,MATCHER,HASHIT,TBLSRCH;
EXTERNAL LOOP,LEND,WARNERR,SKERR,ISN,A1NODE;
MAP BASE A1NODE:PHI;
LOCAL ADJPLACE;		!FLAG TO SET PLACE BACK TO CORRECT PLACE
LOCAL BASE APHI;	!HOLDS HASH POINTER FOR ARRAY ENTRY TO UNDO
MAP PHAZ2 PB;
LOCAL BASE PLACE;
EXTERNAL CSTMNT;	!POINTS TO THE STATEMENT
MAP BASE CSTMNT;
OWN BASE TAININGSTMT;

LOCAL ARGUMENTLIST AG;
	OWN DEF1PLACE,DEF2PLACE;

!******
!MAKE SURE THAT THE PLACE TO WHICH MOTION WOULD OCCUR
!HAS THE CURRENT STATEMENT (CSTMNT POINTS TO IT) AS POSTDOMINATOR.
!THIS INVOLVES:
!	1.DETERMINING THE PLACE TO WHICH MOTION WOULD OCCUR.
!	2.LOOKING FOR CSTMNT ON THE PREDOMINATOR LIST OF
!	  THE PLACE TO WHICH MOTION WOULD OCCUR.
!	3. IF 2 IS FALSE THEN THE PARENFLG IS SET ON THE
!	 STATEMENT (IF AN ASSIGNMENT). THIS IS A FUDGE TO
!	PERMIT LOOKING FOR LOCAL COMMON SUBS IN SUCH
!	STATEMENTS AT THE END OF OPTIMIZATION (PHA2).

MAP PEXPRNODE CNODE;
	!TAKE ARRAY REFERENCES OFF THE TOP

!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*
PHI_0;


IF .SHAPE GTR SKEW THEN
BEGIN

	CASE .SHAPE-STAR1 OF SET

	!STAR1
	!STRAIGHT NODE WITH ARRAYREF AS ARGUMENT 1

	    CHKDOMINANCE(.CNODE[ARG1PTR],UNARY);

	!STAR2
	!STRAIGHT NODE WITH ARRAYREF AS ARGUMENT 2

	    CHKDOMINANCE(.CNODE[ARG2PTR],UNARY);

	!SKAR1
	!SKEWED NODE WITH ARRAYREF AS ARG 1
	BEGIN

		PB_.CNODE[ARG1PTR];
		CHKDOMINANCE(.PB[ARG2PTR],UNARY);
	END;

	!SKAR2
	!SKEWED NODE WITH ARRAYREF AS ARG 2

	    CHKDOMINANCE(.CNODE[ARG2PTR],UNARY);

	!FNARY
	!LIBRARY FUNCTION REF WITH ARRAYREF AS ARGUMENT

	BEGIN
		AG_.CNODE[ARG2PTR];
		CHKDOMINANCE(.AG[1,ARGNPTR],UNARY);
	END

	TES;
	IF .PHI NEQ 0 THEN
	BEGIN

		!SAVE HASH POINTER FOR LATER UNDO IF REQUIRED
		APHI_.PHI;

		CASE .SHAPE-STAR1 OF SET

		!STAR1
		    FUDGA1;
		!STAR2
		    FUDGA2;
		!SKAR1
		BEGIN
			A1NODE_.CNODE[ARG1PTR];
			A1NODE[ARG2PTR]_.PHI;
			A1NODE[DEFPT2]_.PHI[STPT];
		END;
		!SKAR2
		    FUDGA2;
		!FNARY
		BEGIN
			AG_.CNODE[ARG2PTR];
			AG[1,ARGNPTR]_.PHI;
!**[526] CHKDOM @4080 IN !FNARY SJW 29-DEC-76
%[526]%			PLACE _ .CNODE [DEFPT2];	! SAVE DEFPT2
			CNODE[DEFPT2]_.PHI[STPT];

			PHI_0;
			CHKDOMINANCE(.CNODE,UNARY);

!**[526] CHKDOM @4086 IN !FNARY SJW 29-DEC-76
%[526]%			IF .PHI NEQ 0
%[526]%			  THEN PHI [A2ARY] _ 1
%[526]%			  ELSE BEGIN			! PUT BACK ARRAYREF
%[526]%			    AG [1,ARGNPTR] _ NEWCOPY (.AG [1,ARGNPTR], .CNODE);	! ARRAYREF'S DAD IS CNODE = FNCALL
%[526]%			    CNODE [DEFPT2] _ .PLACE;	! RESTORE DEFPT2
%[526]%			  END;

			RETURN;
		END

		TES;

		PHI_0;

		NOHHASSLE_0;

		CHKDOMINANCE(.CNODE,(IF .SHAPE GEQ SKAR1 THEN SKEW
					ELSE STGHT));
		IF .PHI NEQ 0 THEN
		BEGIN

			!SET COMMENTS IN OPTMAC FOR NOHHASSLE BIT
			!REQUIREMENTS
			!BRIEFLY, PHI COULD POSSIBLY NOT BE
			!'THE' HASH ENTRY FOR THE ARRAY EXPR
			!IT COULD BE AN ENTRY THAT WAS MADE BECAUSE
			!OF ONE OR MORE MATCHES (NEXTUP, ETC.).
			!NOHHASSLE IS SET IF THIS IS A @POSSIBILITY.

			IF .NOHHASSLE THEN RETURN;
			IF .SHAPE EQL STAR1
			    OR .SHAPE EQL SKAR1 THEN
	
			    PHI[AR1ARY]_1
			ELSE
			    PHI[AR2ARY]_1;
		END ELSE
		!THE EXPRESSION A OP ARRAYREF DID NOT
		!QUALIFY TO BE HASHED OR MATCHED (PHI IS 0)
		!SO WE WANT TO UNDO THE ARRAYREF HASH POINTERS
		!FROM THE EXPRESSION NOW.
		BEGIN
			CASE .SHAPE-STAR1 OF SET

			!STAR1
			BEGIN
				CNODE[ARG1PTR]_NEWCOPY(.APHI,.CNODE);
				CNODE[DEFPT1]_0;
			END;

			!STAR2
			BEGIN
				CNODE[ARG2PTR]_NEWCOPY(.APHI,.CNODE);
				CNODE[DEFPT2]_0;
			END;

			!SKAR1
			BEGIN
				A1NODE_.CNODE[ARG1PTR];
				A1NODE[ARG2PTR]_NEWCOPY(.APHI,.A1NODE);
				A1NODE[DEFPT2]_0;
			END;

			!SKAR2
			BEGIN
				CNODE[ARG2PTR]_NEWCOPY(.APHI,.CNODE);
				CNODE[DEFPT2]_0;
			END

			!SHOULD NOT BE HERE WITH FNARY
			TES;
		END;
	END;
	RETURN;
END;
	!IF EITHER DEFPT IS THE CURRENT STATEMENT DO NOT
	!CONSIDER THIS STATEMENT FOR GLOBAL COMMON SUBS.
	!DO NOT SET THE FLAG TO CAUSE IT TO GET LOCAL ONES EITHER.
	!IF SUCH WERE DONE TROUBLE MIGHT INSUE. IT WOULD ALOS WASTE
	!TIME.

	IF
	BEGIN
		%(
		IF NODE IS UNARY OR STGHT WE WANT TO CHECK
		DEFPT1. IF NODE IS SKEW LOOK AT DEFPT2 IN THE
		DAUGHTER OF THE CURRENT EXPRESSION
		)%
		IF .SHAPE NEQ SKEW
		THEN
			.CNODE[DEFPT1] EQL .CSTMNT
		ELSE
		BEGIN
			A1NODE_.CNODE[ARG1PTR];
			.A1NODE[DEFPT2] EQL .CSTMNT
		END
	END
	OR .CNODE[DEFPT2] EQL .CSTMNT THEN RETURN;


	!IN THE FOLLOWING ALGORITHMS, SET TAININGSTMT TO
	!BE THE STATEMENT THAT DOES INDEED CONTAIN THE
	!EXPRESSION WE ARE CONSIDERING.

	TAININGSTMT_.CNODE;

	UNTIL .TAININGSTMT[OPRCLS] EQL STATEMENT
	OR    .TAININGSTMT[OPRCLS] EQL IOLSCLS
	DO
	BEGIN
		TAININGSTMT_.TAININGSTMT[PARENT];
		IF .TAININGSTMT EQL 0 THEN SKERR();
	END;

	IF (.TAININGSTMT[OPRCLS] NEQ STATEMENT)
	OR (.TAININGSTMT[SRCOPT] EQL 0) THEN
	   TAININGSTMT_.CSTMNT;

	!AS A TIME TRADE OFF, LOOK IT UP FIRST. IF ALREADY
	!THERE WE DO NOT HAVE TO HASSLE WITH DETERMINING IF
	!IT SHOULD GO THERE OR NOT

	HASHIT(.CNODE,.SHAPE);
	PHI_TBLSRCH();
!**;[340],CHKDOMINANCE @4062, DCE, 07-JAN-76
!**;[340], SAVE VALUE OF PHI AGAINST CHANGE IN CALLS FROM MATCHER
%[340]%	IF .FLAG THEN BEGIN
!**;[401], CHKDOMINANCE @4062, DCE, 6-MAY-76
!**;[401], THE FOLLOWING CODE ENSURES THAT PHI GETS SET TO
!**;[401], ZERO IN THE CASE THAT MATCHER FAILED WHEN DEALING WITH AN
!**;[401], ARRAY REFERENCE.  IT HAS THE EFFECT OF KEEPING POINTERS TO
!**;[401], HASH TABLE ENTRIES (ARRAYREFS) OUT OF THE STATEMENT TREES SO
!**;[401], THAT THEY CAN NEVER BE LEFT THERE INADVERTENTLY.
%[401]%				LOCAL T;
%[401]%				T_.PHI[USECNT];
%[340]%				APHI_.PHI;
%[340]%				MATCHER(.CNODE,.SHAPE,.NAN,.PHI);
%[340]%				PHI_.APHI;
%[401]%				IF (.PHI[USECNT] EQL .T) AND
%[401]%					(.SHAPE EQL SKEW) AND
%[401]%					.ARREFCMNSBFLG
%[401]%				THEN PHI_0;
%[401]%				RETURN
%[340]%			END;
	BEGIN

		!MUST TAKE SHAPE INTO CONSIDERATION
		IF .SHAPE EQL SKEW THEN
		BEGIN
			A1NODE_.CNODE[ARG1PTR];
			DEF1PLACE_.A1NODE[DEFPT2];
			DEF2PLACE_.CNODE[DEFPT2];
			!MAKE A1NODE BE LOGICAL ARG1
			A1NODE_.A1NODE[ARG2PTR];
		END ELSE
		BEGIN
			DEF1PLACE_.CNODE[DEFPT1];
			DEF2PLACE_.CNODE[DEFPT2];
			A1NODE_.CNODE[ARG1PTR];
		END;
		!IF BOTH DEF POINTS ARE THE SAME NO MORE WORK IS NEEDED
		IF .DEF1PLACE EQL .DEF2PLACE THEN
			PLACE_.DEF1PLACE
		ELSE
		BEGIN


			!UNLESS THE EXPRESSION IS SKEW
			!WE DON'T WANT TO RECONSIDER HER
			IF .CNSMOVFLG THEN RETURN;

			!FOR TYPE CONVERSIONS
			!    NEGNOTS
			!    FUNCTION REFS (LIBRARY)
			!DEF1PLACE IS ZERO. SO, USE DEF2PLACE
			!AND SKIP THE LOOK

			IF (.SHAPE EQL UNARY)
			   AND (.DEF1PLACE EQL 0)
			   AND (.DEF2PLACE NEQ 0) THEN
				PLACE_.DEF2PLACE
			ELSE
			BEGIN
				!CHECK AGAIN NOW THAT SHAPE HAS BEEN
				!CONSIDERED IN SETTING DEF1PLACE
				!AND DEF2PLACE AND WE ARE SURE THAT
				!TAININGSTMT  IS SET UP.

				IF (.DEF1PLACE EQL .TAININGSTMT) OR
				   (.DEF2PLACE EQL .TAININGSTMT) THEN
				BEGIN
					PHI_0;
					RETURN;
				END;

				!NOW ON TO THE REAL ANALYSIS (AT LAST!)
				PB_.TAININGSTMT;		!PB IS TEMP
				DO
					PB_.PB[PREDOM]
				UNTIL .PB EQL .DEF1PLACE
				OR   .PB  EQL .DEF2PLACE
				OR   .PB EQL .TOP;
				PLACE_.PB;
				!WE CAN ONLY LOOK AS FAR AS TOP BUT MAYBE IT IS
				!REALLY SUPPOSED TO BE LENTRY
				IF .PB EQL .TOP THEN
					IF .DEF1PLACE NEQ .TOP THEN
						IF .DEF2PLACE  NEQ .TOP THEN
							PLACE_.LENTRY;
	
			END;
		END;

		!LOOK FOR SPECAIL CONSTANT MOTION CASE.
		!WORK ALREDY DONE JUST SET STPT AND QUIT
		IF .CNSMOVFLG THEN
		BEGIN
			IF .PLACE NEQ .LENTRY THEN RETURN;
			PHI_MAKETRY(.PHI,.CNODE,.SHAPE);
			IF .SHAPE EQL SKEW THEN PHI[NBRCH]_1;
			IF .NAN THEN PHI[NEDSANEG]_1;
			PHI[STPT]_.LENTRY;
			RETURN;
		END;

		!CHECK FOR VARIABLE INITIALIZED
		!NO MATTER THE SHAPE OF THE NODE A1NODE NOW POINTS
		!TO LOGICAL ARG1 AND CNODE[ARG2PTR] TO LOGICAL ARG2.
		!DEF1PLACE AND DEF2PLACE POINT TO THE CORRESPONDING
		!DEFINITION POINTS. WE WILL NOW USE THIS INFO
		!TO CHECK FOR THE VARIBALE BEING INITIALIZED

		IF .LOOP EQL 0 THEN	!MAIN COFE SECTION
		BEGIN
			IF .DEF1PLACE EQL .LENTRY THEN
				CHKINIT(.A1NODE);
			IF .DEF2PLACE EQL .LENTRY THEN
			BEGIN
				!CHECK FOR A FUNCTION CALL
				!AND GET THE ARG
				IF .CNODE[OPRCLS] EQL FNCALL THEN
				BEGIN
					REGISTER ARGUMENTLIST AG;
					AG_.CNODE[ARG2PTR];
					CHKINIT(.AG[1,ARGNPTR]);
				END ELSE
					!REGULAR CASE
					CHKINIT(.CNODE[ARG2PTR]);
			END;
		END;
		!PLACE NOW POINTS TO THE STATEMENT THAT IS THE DEFPT OF THE
		!EXPRESSION.  WE CHECK TO SEE IF PA POSTDOMINATES PLACE
		!IF THIS IS A MAIN PROGRAM LENTRY (WHICH COULD POSSIBLY BE THE
		!VALUE OF PLACE AT THIS POINT) IS THE  DUMMY CONTINUE WHICH
		!DOES NOT HAVE THE OPTIMIZERS WORDS (POSTDOM, PREDOM ,ETC.)
		!THEREFOR, WE WILL TEST AND ADJUST

		IF .PLACE EQL 0 THEN
		BEGIN
			PHI_0;
			RETURN;
		END;

		ADJPLACE_0;
		IF .PLACE EQL .LENTRY THEN
			(PLACE_.TOP;
				ADJPLACE_1);
	
		PB_.PLACE;		!PS IS TEMP AGAIN
		DO
			PB_.PB[POSTDOM]
		UNTIL .PB EQL .TAININGSTMT
		OR    .PB EQL .BOTTOM
		OR    .PB EQL .LEND
		OR    .PB EQL 0;
		IF .PB EQL 0 THEN SKERR();
		!THE GRAPH IS BAD CALL SKERR FOR NOW.
		IF .PB EQL .LEND OR .PB EQL .BOTTOM THEN
		BEGIN
			!MAKE SURE PHI IS ZERO FOR THE UNSUCCESSFUL
			!ATTEMPT.
			PHI_0;
			RETURN;
		END;

		PHI_MAKETRY(.PHI,.CNODE,.SHAPE);
		IF .SHAPE EQL SKEW THEN
		PHI[NBRCH]_1;
		IF .NAN THEN PHI[NEDSANEG]_1;
		IF .ADJPLACE THEN 
			PHI[STPT]_.LENTRY
		ELSE
		BEGIN
			!TO PREVENT MOTION INTO A LOOP.
			!THE POTENTIAL EXISTS IS A STRUCTURE LIKE
			!DO
			!IF () 10,10,20
			!10	CONTINUE
			!20	COMPUTE
			IF (.PLACE NEQ .TOP) AND (.PLACE[SRCID] EQL DOID) THEN
			BEGIN
				PB_.PLACE[DOLBL];
				PB_.PB[SNHDR];
				PLACE_.PB[SRCLINK];
			END;
			PHI[STPT]_.PLACE;
		END;
	END;
END;
!
!***************************************************
!

EXTERNAL EHASH; 
GLOBAL ROUTINE MOVCNST =
BEGIN
!MOVE ALL REGION CONSTANT EXPRESSIONS OUT OF THE LOOP

%[V5]%	MACRO  IDDOTR  =  0,3,24,12$;
%[V5]%	EXTERNAL  DOTRCNTOK, DOTORFIX;


	LOCAL BASE HASHP;
	EXTERNAL QQ,CSTMNT,ISN,SKERR,CMNMAK;
	LABEL GOT1;
	MAP BASE PB:QQ:CSTMNT:T;
	EXTERNAL EHASHP,LENTRY,MAKEPR,NARY2,STPRECLUDE,CMNLNK,NEXTUP;
	OWN CNSTTOGO;
	EXTERNAL MAKASGN;
	LOCAL BASE CNODE;	!USED TO POINT TO EXPRESSION
	EXTERNAL LOKCALST;

%[V5]%	LOCAL BASE  DOTO;
%[V5]%	LABEL  LWHILE;

	!ITERATE THROUGH THE HASH TABLE UNTIL THERE ARE NO MORE
	!TO MOVE.
	CNSTTOGO_1;
	WHILE .CNSTTOGO DO
	BEGIN
		CNSTTOGO_0;
		INCR K FROM 0 TO EHSIZ-1 DO
		BEGIN
			EHASHP_EHASH[.K]<0,0>;
			HASHP_.EHASH[.K];
			WHILE .HASHP NEQ 0 DO
			BEGIN
LWHILE:			  BEGIN		%[V5]%
%[V5]%			    IF .HASHP [EMPTY]		! NOT IN USE ?
%[V5]%			      THEN LEAVE LWHILE;	! IGNORE IT
%[V5]%			    DOTO _ .HASHP [TEMPER];
%[V5]%			    IF .DOTO NEQ 0  THEN
%[V5]%			    IF .DOTO [ORFIXFLG]	! EXPR BUILT BY DOTORFIX
%[V5]%			      THEN LEAVE LWHILE;	! DONT TOUCH IT

				!SET FLAG FOR ARRAY STUFF IS APPROPRIATE

				IF .HASHP[A1ARY] OR .HASHP[A2ARY] THEN
					ARREFCMNSBFLG_1
				ELSE
					ARREFCMNSBFLG_0;


				!NOW CHECK FOR CONSTANT MOTION

		GOT1:
				IF (.HASHP[STPT] EQL .LENTRY)		!PLACE TO GO IS ENTRY
				AND
				(.HASHP[USECNT] EQL 1)	!WASN'TA COMMON
							!SUB-EXPRESSION
				THEN
				BEGIN

					!DO NOT BE HASTY. IF THIS IS AN
					!ARRAY REFERENCE, SKIP IT ANYWAY

					IF .HASHP[OPRCLS] EQL ARRAYREF THEN
					BEGIN
						HASHP[USECNT]_0;
						LEAVE GOT1;
					END;

					CNSTTOGO_1;
					!SET FLAG IN HASH TABLE
					!SO WE CAN GLOBDEPD
					HASHP[MOVDCNS]_1;
					!MAKE AN ASSIGNMENT STATEMENT
					!OF .OXXXXX=EXPRESSION
					CNODE_.HASHP[LKER];

					!TRY SUBSUMPTION
					IF NOT .HASHP[NBRCH] THEN
						DOTOHASGN(.CNODE,.HASHP);
					!IF IT WAS SUBSUMED
%[V5]%					DOTO _ .HASHP [TEMPER];
%[V5]%					IF .DOTO NEQ 0 THEN
					BEGIN
						HASHP[USECNT]_0;
%[V5]%						DOTO [OMOVDCNS] _ 1;
						LEAVE GOT1;
					END;



				!IF THE EXPRESSION IS NARY MAKE A
				!STRAIGHT ONE, AND DO THE ELIMINATION
				!HASSLE (SEE MATCHER, NARY2 FOR
				!BLOODY DESCRIPTION OF THE COMPLETE HASSLE).
				IF .HASHP[NBRCH] THEN
				BEGIN		!OMIGOD ITS NARY
					!ON THE OTHERHAND IT MAY
					!HAVE BEEN NARY BUT ISNT ANY
					!MORE. CHECK AND RESET NBRCH
					!FOR FUTURE TESTS.
					IF .CNODE[A1VALFLG] THEN
					BEGIN
						HASHP[NBRCH]_0;
						!SET PB
						PB_.CNODE;
					END
					ELSE
					BEGIN		!U LOSE ITS NARY
						QQ_.CNODE[ARG1PTR];
!**[514] MOVCNST @4503 SJW 7-NOV-76
![514] IF NARY INSURE .R IS 1ST ARG SINCE [V5] CODE EXPECTS .R + X
%[514]%						T _ .CNODE [ARG2PTR];
%[514]%						IF .T [IDDOTR] EQL SIXBIT ".R" AND
%[514]%						   .CNODE [OPRCLS] EQL ARITHMETIC
%[514]%						  THEN BEGIN
%[514]%						    PB _ MAKEPR (.CNODE [OPRCLS],
%[514]%								 .CNODE [OPERSP],
%[514]%								 .CNODE [VALTYPE],
%[514]%								 .CNODE [ARG2PTR],
%[514]%								 .QQ [ARG2PTR]);
%[514]%						    PB [A1FLGS] _ .CNODE [A2FLGS];
%[514]%						    PB [A2FLGS] _ .QQ [A2FLGS];
%[514]%						    PB [DEFPT1] _ .CNODE [DEFPT2];
%[514]%						    PB [DEFPT2] _ .QQ [DEFPT2];
%[514]%						  END
%[514]%						  ELSE BEGIN
						PB_MAKEPR(.CNODE[OPRCLS],
						.CNODE[OPERSP],
						.CNODE[VALTYPE],
						.QQ[ARG2PTR],
						.CNODE[ARG2PTR]);
						!SET THE FLAGS
						PB[A1FLGS]_.QQ[A2FLGS];
						PB[A2FLGS]_.CNODE[A2FLGS];
						!SET THE DEFPTS
						PB[DEFPT1]_.QQ[DEFPT2];
						PB[DEFPT2]_.CNODE[DEFPT2];
!**[514] MOVCNST @4514 SJW 7-NOV-76 (END THE ELSE)
%[514]%						  END;
						NARY2(.CNODE);
					END;
				END ELSE
				BEGIN
					!IT STRAIGHT, SO DO THE NARY/
					!STRAIGHT THING. ALSO SET UP PB
					STPRECLUDE(.CNODE);
					PB_.CNODE;
				END;

				!BUILD NODE AND LINK IT IN
%[V5]%						! CHECK .R + X -> .O
%[V5]%				T _ .PB [ARG1PTR];	! REA MAKES .R 1ST ARG
%[V5]%				IF .PB [OPR1] EQL ADDOPF AND
%[V5]%				   .T [IDDOTR] EQL SIXBIT ".R"
%[V5]%				  THEN BEGIN
%[V5]%					! .R USE CNT = 1 IFF ONLY USE OF
%[V5]%					! OF .R IN LOOP IS .R <- .R + Z
%[V5]%				    IF DOTRCNTOK (.T)
%[V5]%				      THEN T _ DOTORFIX (.PB, .HASHP)
%[416]%	!**[416] MOVCNST @4465 SJW 5-AUG-76
%[416]%				      ELSE BEGIN		! CAN'T TOUCH IT
%[416]%					HASHP [USECNT] _ 0;	! IGNORE THIS ENTRY ON NEXT PASS
%[V5]%					LEAVE GOT1;
%[416]%				      END
%[V5]%				  END
%[V5]%				  ELSE
%[V5]%				    T _ CMNMAK (.PB,		!EXPRESSION
					 .HASHP[NEDSANEG],	!NEEDS A NEG
					 .HASHP);		!POINTER TO HASH


				QQ_CMNLNK(.T,.CNODE,IF .HASHP[NBRCH] THEN SKEW
						ELSE STGHT,.HASHP[NEDSANEG],
						.HASHP);

%[V5]%				DOTO _ .HASHP [TEMPER];
%[V5]%				DOTO [OMOVDCNS] _ 1;

!**[513] MOVCNST @4550 SJW 5-NOV-76
![513] PASS UP ORFIXFLG FROM ANY .O UNDER THIS ONE
%[513]%				IF .PB [A1VALFLG]
%[513]%				  THEN BEGIN
%[513]%				    T _ .PB [ARG1PTR];
%[513]%				    IF .T [IDDOTO] EQL SIXBIT ".O"
%[513]%				      THEN DOTO [ORFIXFLG] _ .DOTO [ORFIXFLG] OR .T [ORFIXFLG];
%[513]%				  END;
%[513]%				IF .PB [A2VALFLG]
%[513]%				  THEN BEGIN
%[513]%				    T _ .PB [ARG2PTR];
%[513]%				    IF .T [IDDOTO] EQL SIXBIT ".O"
%[513]%				      THEN DOTO [ORFIXFLG] _ .DOTO [ORFIXFLG] OR .T [ORFIXFLG];
%[513]%				  END;

				!CHKDOMINANCE DEPENDS ON CSTMNT
				!POINTING TO THE STATEMENT.THEREFORE,
				!WE WILL FOLLOW THE PARENT LINKS UNTIL
				!!!WE FIND THE STATEMENT
				CSTMNT_.QQ;
				UNTIL .CSTMNT[OPRCLS] EQL STATEMENT OR
					.CSTMNT[OPRCLS] EQL IOLSCLS DO
				BEGIN
					CSTMNT_.CSTMNT[PARENT];
					!!QUIT  ON ERROR
					IF .CSTMNT EQL 0 THEN SKERR();
				END;
				!IF WE ARE AT A STATEMENT THAT IS CURRENTLY
				!BEING OPTIMIZED
!**[440] MOVCNST @4507 SJW 8-SEP-76
![440] CAN'T NEXTUP (IE, TRY TO COMBINE INTO BIGGER COMSUB) THIS
![440]   .O'S MOM IF THIS .O CAME FROM .R SINCE .O NOT REALLY CONSTANT
![507]   UNLESS MOM IS ARITHMETIC SINCE ADDITIONAL CONSTANT TERMS
![507]   WILL LEAVE ENTIRE EXPR TO VARY ONLY WITH THE .R INCR
![507]   WHICH BECAME THIS .O'S INCR AT END OF LOOP
%[440]%				IF (.CSTMNT[OPRCLS] EQL STATEMENT) AND
%[440]%				   (.CSTMNT[SRCOPT] NEQ 0)         AND
!**[513] MOVCNST @4572 SJW 5-NOV-76
%[513]%				   (NOT .DOTO [ORFIXFLG] OR .QQ [OPRCLS] EQL ARITHMETIC)
				THEN
				BEGIN
					ISN_.CSTMNT[SRCISN];
					!SEE IF THERE IS NOW ANOTHER
					!ONLY IF CSTMNT IS NOT AN IOLSCLS NODE
					NEXTUP(.QQ);
				END;

				!MAKE SURE WE DO NOT CONSIDER THIS ONE AGAIN
				HASHP[USECNT]_0;
			END;		!IF STATEMENT
%[V5]%			    END;	! OF LWHILE
			  HASHP_.HASHP[CLINK];
			END;			!WHILE
		END;				!INCR
	END;		!WHILE ON CNSTTOGO
END;
ROUTINE GLOBDEPD (CURVERYFRST) =		%[V5]%
BEGIN

%[V5]%!	CURVERYFRST IS SIXBIT VALUE OF VERYFRST BEFORE THIS LOOP WAS
%[V5]%!	  PROCESSED => ONLY GLOBDEP THOSE .O GEQ CURVERYFRST, IE,
%[V5]%!	  ONLY THOSE CREATED FROM THIS LOOP

	!FOR GLOBAL OPTIMIZATION ONLY
	!LOOK FOR GROUPS OF STATEMENTS CREATED BY THE OPTIMIZER
	!FOR COMMON SUB-EXPRESSION ELIMINATION OR CONSTANT COMPUTATIONS.
	!WHEN FOUND, LOOK AT GLOBAL COMMON SUB TEMPS, HASH
	!THE EXPRESSIONS TO WHICH THEY CORRESPOND, LOOK THEM UP.
	!IF USECNT OF DEPENDENT ONE = USECNT OF PARENT ONE THEN
	!SEE IF THE DEPENDENT ONE IS IN THIS GROUP OF STATEMENTS
	!. IF THAT IS TRUE THEN ELIMINATE THE DEPENDENT ONE.


%[V5]%	MACRO  IDVERYFRST  =  0,3,0,24$;	! LAST 4 SIXBIT CHARS

	EXTERNAL TPREV,PHI,PREV;
	OWN PAE;
	MAP BASE PAE:T:P1:PO:TPREV:PHI;

	EXTERNAL SAVSPACE,TOP,LEND,QQ,LOOP,LENTRY;
	EXTERNAL HASHIT,TBLSRCH,LOK1SUBS,LOK2SUBS;
	LABEL WHL1,WHL2;

%[V5]%	LABEL  LWHL;
%[V5]%	EXTERNAL  DOTOFIX;		! FIX .O INCR IF CAME FROM .R


	!MACRO TO SET PARENT POINTERS STRAIGHT

	MACRO SETDAD=
	BEGIN
		IF .PAE[SRCID] EQL ASGNID THEN
			IF NOT .PAE[A2VALFLG] THEN
			BEGIN
				PO_.PAE[RHEXP];
				PO[PARENT]_.PAE;
			END;
	END$;
	OWN GHEAD,SAVTOP;
	LOCAL UPFRONT;

	SAVTOP_.TOP;		!SAVE VALUE OF TOP



	PAE_.LENTRY; PREV_.LENTRY;
	!SET FLAG TO SAY WE ARE IN FRONT OF THE LOOP
	UPFRONT_1;

LWHL:	WHILE .PAE NEQ .LEND DO		%[V5]%
	BEGIN
		!PARENT POINTERS COULD NOT BE SET EARLIER. MAKE SURE
		!THEY ARE SET NOW. NEED TO LOOK ONLY AT OPTIMIZER
		!CREATED ASSIGNMENTS BUT WILL DO IT FOR ALL
		!ASSIGNMENTS AS EXTRA ASSURANCE.

		GHEAD_.PAE;
		!FOR ALL THOSE IN THIS GROUP THAT WE ARE INTERESTED IN
		!  IE, OPT ASGN STMT WITH LHEXP = .O & NOT A2VAL

		WHILE OPTCMN(PAE) DO
		BEGIN
			PO_.PAE[RHEXP];
			!NOW, SET THE PARENT OF THE EXPRESSION
			PO[PARENT]_.PAE;
			HASHIT(.PO,STGHT);
			PHI_TBLSRCH();
			!CHECK FOR THERE OR NOT

			IF .FLAG THEN
			IF .PHI[CMNUNDER] THEN
			BEGIN
				IF LOK1SUBS(.PO,1) THEN		! RHS = .O OP Y ?
				BEGIN
					!COMPARE USECNTS
%[V5]%				  IF (.QQ<RIGHT> EQL .PHI[USECNT] AND .PHI [USECNT] NEQ 0)  OR		! QQ = OMOVDCNS,,EXPRUSE OF RHS .O
%[V5]%				     (.QQ<RIGHT> EQL 1 AND .PHI[MOVDCNS])  OR
%[V5]%				     (.PHI [MOVDCNS] AND .QQ<LEFT>)

				    THEN
					BEGIN
%[V5]%						T _ .PO [ARG1PTR];	! .O SYMTAB PTR
%[V5]%						IF .T [IDVERYFRST] GEQ .CURVERYFRST
%[V5]%						THEN BEGIN
%[V5]%						IF .T [ORFIXFLG]	! .O CAME FROM .R ?
%[V5]%						  THEN DOTOFIX (.T, .PAE);	! FIX .O INCR
						TPREV_.PREV;
						P1_.GHEAD;
						WHL1:
						!LOOK FROM THE START OF THE GROUP TO HERE
						WHILE .P1 NEQ .PAE DO
						BEGIN
							IF .P1[LHEXP] EQL
								.PO[ARG1PTR] THEN
							BEGIN
%[V5]%								T [IDATTRIBUT (NOALLOC)] _ 1;
								TPREV[SRCLINK]_.P1[SRCLINK];
								T_.PO[ARG1PTR];
								PO[ARG1PTR]_.T[IDOPTIM];
								PO[A1VALFLG]_0;
								!FIX PARNET
								T_.PO[ARG1PTR];
								T[PARENT]_.PO;
								IF .P1 EQL .GHEAD THEN
								GHEAD_.P1[SRCLINK];
								!IF IN FRONT OF
								!TOP ZERO THE DEFPTS
								IF .UPFRONT THEN
								T[DEFPT1]_
								T[DEFPT2]_
								PO[DEFPT1]_
								0;
								SAVSPACE(ASGNSIZ+SRCSIZ-1,.P1);
								LEAVE WHL1;
							END;
							TPREV_.P1;
							P1_.P1[SRCLINK];
%[V5]%						END;
						END;
					END;
				END;
				!THAT WAS THE FIRST ARG, NOW THE SECOND
				!LOKXSUBS RETURNS YHE USECNT OF THE DEPENDENT
				!EXPRESSION IN QQ.
				IF LOK2SUBS(.PO,1) THEN
				BEGIN
%[V5]%				  IF (.QQ<RIGHT> EQL .PHI[USECNT] AND .PHI [USECNT] NEQ 0)  OR
%[V5]%				     (.QQ<RIGHT> EQL 1 AND .PHI[MOVDCNS])  OR
%[V5]%				     (.PHI [MOVDCNS] AND .QQ<LEFT>)
				  THEN
					BEGIN
%[V5]%						T _ .PO [ARG2PTR];	! .O SYMTAB PTR
%[V5]%						IF .T [IDVERYFRST] GEQ .CURVERYFRST
%[V5]%						THEN BEGIN
%[V5]%						IF .T [ORFIXFLG]	! .O CAME FROM .R ?
%[V5]%						  THEN DOTOFIX (.T, .PAE);	! FIX .O INCR
						TPREV_.PREV;
						P1_.GHEAD;
						WHL2:
						!LOOK FROM THE START TO THIS ONE
						WHILE .P1 NEQ .PAE DO
						BEGIN
							IF .P1[LHEXP] EQL
							.PO[ARG2PTR] THEN
							BEGIN
								T [IDATTRIBUT (NOALLOC)] _ 1;
								TPREV[SRCLINK]_.P1[SRCLINK];
								T_.PO[ARG2PTR];
								PO[ARG2PTR]_.T[IDOPTIM];
								!RESET VALFLG
								PO[A2VALFLG]_0;
								!FIX PARENT
								T_.PO[ARG2PTR];
								IF .P1 EQL .GHEAD THEN
								GHEAD_.P1[SRCLINK];
								!IF IN FRONT OF TOP
								!ZERO THE DEFPTS
								IF .UPFRONT THEN
								T[DEFPT1]_
								T[DEFPT2]_
								PO[DEFPT2]_
								0;
								T[PARENT]_.PO;
								SAVSPACE(ASGNSIZ+SRCSIZ-1,.P1);
								LEAVE WHL2;
							END;
							TPREV_.P1;
							P1_.P1[SRCLINK];
%[V5]%						END;
						END;
					END;
				END;
			END;		!PHI[CMNUNDER]
			PAE_.PAE[SRCLINK];
%[V5]%			IF .PAE EQL .LEND
%[V5]%			  THEN LEAVE LWHL;
		END;
		!RESET FLAG IF WE ARE PASSING THROUGH TOP
		IF .PAE EQL .TOP THEN UPFRONT_0;
		PREV_.PAE;
		PAE_.PAE[SRCLINK];
	END;
	!CLEANUP THE SYMBOL TABLE ENTRIES
	DECR I FROM SSIZ-1 TO 0 DO
	BEGIN
		PAE_.SYMTBL[.I];
		WHILE .PAE NEQ 0 DO
		BEGIN
			IF .PAE[IDDOTO] EQL SIXBIT".O" THEN
%[V5]%				PAE [EXPRUSE] _ 0;	! DONT TOUCH OMOVDCNS,ORFIXFLG
			PAE_.PAE[SRCLINK];
		END;
	END;

	!RESTORE THE VALUE OF TOP
	TOP_.SAVTOP;
END;
FORWARD SCRUBARRAY;
GLOBAL ROUTINE GLOBELIM (CURVERYFRST) =		%[V5]%
BEGIN

%[V5]%!	CURVERYFRST IS SIXBIT VALUE OF VERYFRST BEFORE CALLS
%[V5]%!	  HERE ON THIS LOOP: TO BE PASSED TO GLOBDEP SO ONLY .O
%[V5]%!	  CREATED FROM THIS LOOP GET RECOMBINED

	EXTERNAL IOGELO,HAULASS,SLINGHASH;
	LOCAL BASE OLDPO;
	LOCAL PHAZ2 PO;
	EXTERNAL CSTMNT,LOOP,ISN,LENTRY,LEND,BOTTOM,TOP;
	MAP BASE CSTMNT:LENTRY:TOP;
	EXTERNAL ELIM,REA;
!********************************************
	!GLOBAL COMMON SUB-EXPRESSION ELIMINATION CONTROLLER
	!
!**************************************************

	CNSMOVFLG_0;
	LSTWARNLINE_0;
	!PROCESSING ORDER IS :
	!	1. ALL ASSIGNMENTS OF THE FORM .OXXXX=EXPR. THIS
	!	   WILL BE A CHEAT AT SUBSUMPTION
	!	2. ALL SURE TO BE EXECUTED STATEMENTS (POSTDOMINATORS
	!	   OF TOP
	!	3. THEN THE REST IN BUSY ORDER
	PO_.TOP;
	DO
	BEGIN
		CSTMNT_.PO;
		ISN_.CSTMNT[SRCISN];
		IF .ISN EQL 0 THEN
		BEGIN
			IF .PO[SRCID] EQL ASGNID AND .PO[SRCOPT] NEQ 0 THEN
			BEGIN
				ELIM(.PO);
				PO[CSDONE]_1;
			END
		END
		ELSE
		IF .PO[SRCID] GEQ READID AND .PO[SRCID] LEQ REREDID
%[V5]%		   AND NOT .GLOBELIM2
!**[455] GLOBELIM @4773 SJW 20-SEP-76
![455] CAN'T MOVE EXPRESSIONS OUT OF IMPLIED DO IF INSIDE LOGICAL IF,
![455]   IE, SRCLINK = 0
%[455]%		   AND .PO [SRCLINK] NEQ 0 THEN
%[V5]%		BEGIN		! PROCESS I/O STATEMENT ON 1ST GLOBELIM ONLY
%[V5]%			IMPLDO _ 1;	! PROCESSING IMPLIED DO
%[V5]%			IOGELO(.PO);
%[V5]%			IMPLDO _ 0;	! IMPLIED DO DONE
		END;
		PO_.PO[BUSY];
	END UNTIL .PO EQL 0;

	OLDPO_PO_.TOP;
	DO
	BEGIN
		CSTMNT_.PO;
		ISN_.CSTMNT[SRCISN];
		IF .PO[SRCID] NEQ DOID AND NOT .PO[CSDONE] THEN
		BEGIN
			ELIM(.PO);
			PO[CSDONE]_1;
		END;
		OLDPO_.PO;
		PO_.PO[POSTDOM];
	END UNTIL .PO EQL .OLDPO;
	!NOW THE REST IN BUSY ORDER
	PO_.TOP;
	DO
	BEGIN
		IF .PO[SRCID] NEQ DOID THEN
			IF NOT .PO[CSDONE] THEN
			BEGIN
				CSTMNT_.PO;
				ISN_.CSTMNT[SRCISN];
				ELIM(.PO);
			END;
%[V5]%		PO[CSDONE]_0;		! TURN OFF FLAG SO RECALLABLE
		PO_.PO[BUSY];
	END UNTIL .PO EQL 0;
	!WE DO NOT WANT TO MOVE CONSTANT COMPUTATIONS IF THIS IS THE
	!MAIN PROGRAM
	!TO DO SO WOULD PESSIMIZE THE CODE.

	IF .LOOP NEQ 0 THEN
	MOVCNST();

%[V5]%	GLOBDEPD (.CURVERYFRST);

	SCRUBARRAY();
	SLINGHASH();

	!GLOBDEPD MAY HAVE CREATED SOME EXPRESSIONS THAT ARE
	!COMPOSED OF .O VARIABLES THAT COULD MOVE OUT OF THE
	!LOOP AS CONSTANT COMPUTATIONS. WE WILL TRY TO GET THESE NOW.
	!ONCE AGAIN THIS IS VALID ONLY IF WE ARE NOT IN MAIN CODE

	IF .LOOP NEQ 0 THEN
	BEGIN
		CNSMOVFLG_1;
		PO_.TOP;
		WHILE .PO NEQ .BOTTOM DO
		BEGIN
			!THIS CONCERNS ONLY STATEMENTS
			!THAT WERE OPTIMIZER INSERTED
			!SKIP INNER MORE DO LOOPS

			IF .PO[SRCID] EQL DOID THEN
			BEGIN
				PO_.PO[DOLBL];
				PO_.PO[SNHDR];
			END;
			IF .PO[SRCOPT] EQL 0 THEN
				IF .PO[SRCID] EQL ASGNID THEN
					REA(.PO[RHEXP]);
			PO_.PO[SRCLINK];
		END;

		MOVCNST();
		CNSMOVFLG_0;
%[V5]%		GLOBDEPD (.CURVERYFRST);

		!TRY MOVING SIMPLE ASSIGNMENTS
		HAULASS();
	END;

	!CLEAN UP HASH TABEL
	SCRUBARRAY();

	!CLEAN OUT EXPRESSION HASH TABLE
	SLINGHASH();


END;

GLOBAL ROUTINE SCRUBARRAY=
BEGIN
	!GO THROUGH THE EXPRESSION HASH TABLE AND FIX UP 
	!EXPRESSION NODES THAT AHVE BEEN SOILED BY THE
	!ARRAY REFERENCES COMMON SUB PROCESS

	EXTERNAL EHASH;

	EXTERNAL BASE EHASHP;
	MAP BASE P1:P2;

	DECR I FROM EHSIZ-1 TO 0 DO
	BEGIN
		EHASHP_.EHASH[.I];

		WHILE .EHASHP NEQ 0 DO
		BEGIN

			IF NOT .EHASHP[EMPTY] AND .EHASHP[USECNT] EQL 1 THEN
				PUTBACKARRAY(.EHASHP,
				(IF .EHASHP[NBRCH] THEN SKEW
					ELSE STGHT));

			EHASHP_.EHASHP[CLINK];

		END;	!WHILE
	END;		!DECR
END;

GLOBAL ROUTINE A2ARREF(EXPR)=
BEGIN

	!CHECK CONDITIONS FOR A NODE OF THE
	!FORM
	!	    OP
	!	*	*
	!	DATAOPR	ARRAYREF
	!
	!AND
	!	    OP
	!	*	*
	!	OP	ARRAYREF
	!	  *
	!	  DATAOPR
	!

	MAP BASE EXPR;
	REGISTER BASE T;
	EXTERNAL XPUNGE;

	!GET OUT FAST IF ARG2 IS NOT AN ARRAYREF
	T_.EXPR[ARG2PTR];
	IF .T[OPRCLS] NEQ ARRAYREF THEN
		RETURN;

	!ITS AN ARRAYREF. DOES IT HAVE A LEAF AS SUBSCRIPT
	IF NOT .T[A2VALFLG] THEN RETURN;

	!NOW LOOK FOR STRAIGHT CONDITION
	ARREFCMNSBFLG_1;
	IF .EXPR[A1VALFLG] AND NOT .T[PARENFLG] THEN
		XPUNGE(.EXPR,STAR2)
	ELSE
	BEGIN

		T_.EXPR[ARG1PTR];
		IF .T[OPERATOR] EQL .EXPR[OPERATOR]
		AND NOT .T[PARENFLG]
		AND .T[A2VALFLG] THEN
		XPUNGE(.EXPR,SKAR2);
	END;
	ARREFCMNSBFLG_0;
END;

GLOBAL ROUTINE A1ARREF(EXPR)=
BEGIN

	!CHECK CONDITIONS FOR
	!NODE OF THE FORM
	!	    OP
	!	*	*
	!	ARREF	DATAOPR
	!
	!AND
	!	    OP
	!	*	*
	!	OP	DATAOPR
	!	  *
	!	  ARREF
	!
	!SORT ORDER (CANONICALIZATION) MAKE THIS UNLIKELY
	!BUT OTHER COMMON SUBS COULD MAKE IT HAPPEN
	MAP BASE EXPR;	REGISTER BASE T;

	EXTERNAL XPUNGE;

	IF .EXPR[OPRCLS] EQL SPECOP THEN RETURN;

	IF NOT .EXPR[A2VALFLG] THEN RETURN;

	T_.EXPR[ARG1PTR];
	ARREFCMNSBFLG_1;
	IF .T[OPRCLS] EQL ARRAYREF THEN
	BEGIN
		IF .T[A2VALFLG] THEN
		    XPUNGE(.EXPR,STAR1);
	END
	ELSE
	BEGIN

		IF(.EXPR[OPERATOR] EQL .T[OPERATOR])
		AND NOT .T[PARENFLG] THEN
		BEGIN

			T_.T[ARG2PTR];
			IF .T[OPRCLS] EQL ARRAYREF AND .T[A2VALFLG] THEN
			    XPUNGE(.EXPR,SKAR1);
		END;
	END;
	ARREFCMNSBFLG_0;
END;



GLOBAL ROUTINE NEWCOPY(PHI,DAD)=
BEGIN

	!TAKE AN ARRAYREF OFF OF THE LIST
	!POINTED TO BY THE LKER FIELD OF PHI
	!GIVE IT A DAD OF DAD

	MAP BASE PHI;
	REGISTER BASE T;

	EXTERNAL SKERR;

	IF .PHI[LKER] EQL 0 THEN SKERR();

	!TAKE NEXT NODE
	T_.PHI[LKER];

	!TAKE NODE OFF OF LIST
	PHI[LKER]_.T[PARENT];

	T[PARENT]_.DAD;

	.T
END;

GLOBAL ROUTINE PUTBACKARRAY(HASHPTR,SHAPE)=
BEGIN
	!IF THE HASH ENTRY CONTIANS AN ARRAY REF AS AN
	!AERGUMENT, PUT THE ACTUAL ARRAYREFERENCE NODE
	!BACK IN PLACE IN THE EXPRESSION. WITHOUT THIS
	!ADJUSTMENT THE EXPRESSION IS LEFT POINTING TO A
	!HASH TABLE ENTRY.

	MAP BASE HASHPTR;

	REGISTER BASE ARY:EXPR;

	IF .HASHPTR[A1ARY] THEN
	BEGIN
		!ARGUMENT 1 OF THIS EXPRESSION IS AN ARRAY REF
		!NOTE THAT THIS MAY NOT BE ARG1 (HA1) IN THE
		!HASH TABLE

		!GET EXPRESSION ITSELF
		EXPR_.HASHPTR[LKER];

		!NOW CHECK TREE SHAPE
		IF .SHAPE EQL SKEW THEN
		BEGIN
			EXPR_.EXPR[ARG1PTR];
			!IT IS ARG2 OF THIS EXPR THAT IS
			!ARG1 OF THE EXPRESSION
			ARY_.EXPR[ARG2PTR];
			EXPR[ARG2PTR]_NEWCOPY(.ARY,.EXPR);
		END ELSE
		BEGIN
			ARY_.EXPR[ARG1PTR];
			EXPR[ARG1PTR]_NEWCOPY(.ARY,.EXPR);
		END;

		ARY[USECNT]_0;
	END;

	IF .HASHPTR[A2ARY] THEN
	BEGIN
		!ARGUEMNT 2 IS AN ARRAY REF

		EXPR_.HASHPTR[LKER];

		!NOW A SIDE TRIP FOR A FUNCTION REFERENCE
		IF .HASHPTR[OPRCLS] EQL FNCALL THEN
		BEGIN
			LOCAL ARGUMENTLIST AG;

			AG_.EXPR[ARG2PTR];
			ARY_.AG[1,ARGNPTR];
			AG[1,ARGNPTR]_NEWCOPY(.ARY,.EXPR);
		END ELSE
		BEGIN
			!DOES NOT MATTER IF IT IS STRAIGHT OR SKEW
			!OR UNARY
			ARY_.EXPR[ARG2PTR];
			EXPR[ARG2PTR]_NEWCOPY(.ARY,.EXPR);
		END;

		ARY[USECNT]_0;
	END;
END;

GLOBAL ROUTINE FNARRAY(EXPR)=
BEGIN
	!CALLED OUT OF REA TO HANDLE ARRAY REF SPECIAL CASE
	!UNDER A FUNCTION REF

	MAP BASE EXPR;

	REGISTER BASE TMP;
	REGISTER ARGUMENTLIST AG;

	EXTERNAL XPUNGE;

	!QUIT ON NON-LIBRARY
	IF .EXPR[OPERSP] NEQ LIBARY THEN RETURN;

	!LOOK AT ARG LIST

	AG_.EXPR[ARG2PTR];

	!QUIT IF NOT SINGLE ARG

	IF .AG[ARGCOUNT] NEQ 1 THEN RETURN;

	!NOW ARRAY REF PART

	TMP_.AG[1,ARGNPTR];

	IF .TMP[OPRCLS] EQL ARRAYREF THEN
	BEGIN
		!IF THE SUBSCRIPT IS A LEAF
		IF .TMP[A2VALFLG] THEN
		BEGIN
			!SET FLAG
			ARREFCMNSBFLG_1;
			!TRY TO ELIMINATE
			XPUNGE(.EXPR,FNARY);

			!TURN FLAG OFF
			ARREFCMNSBFLG_0;
		END;
	END ELSE
		IF .TMP[OPRCLS] EQL DATAOPR THEN
			XPUNGE(.EXPR,UNARY);
END;

END
ELUDOM