Google
 

Trailing-Edge - PDP-10 Archives - bb-4157h-bm_fortran20_v10_16mt9 - fortran-compiler/cmpblo.bli
There are 12 other files named cmpblo.bli in the archive. Click here to see a list.
!COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1973, 1985
!ALL RIGHTS RESERVED.
!
!THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
!ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
!INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
!COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
!OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
!TRANSFERRED.
!
!THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
!AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
!CORPORATION.
!
!DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
!SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.

!AUTHOR: S. MURPHY/HPW/TFV/TJK

MODULE CMPBLO(SREG=#17,VREG=#15,FREG=#16,DREGS=4,RESERVE(0,1,2,3))=
BEGIN

GLOBAL BIND CMPBLV = #10^24 + 0^18 + #2227;	! Version Date: 21-Oct-83

%(

***** Begin Revision History *****

46	-----	-----	MAKE REGCANDIDATES TABLE INTO A LINKED
			LIST

47	-----	-----	MUST END A BASIC BLOCK WHEN HAVE A CALL
			INSIDE A LOGICAL IF

***** Begin Version 6 *****

48	761	TFV	1-Mar-80	-----
	Remove test for KA10FLG

***** Begin Version 7 *****

***** End V7 Development *****

2006	TJK	6-Oct-83
	Add call to ENDSMZTRIP in CMPBLOCK to determine if the current
	statement (pointed to by CSTMNT)  should end a basic block  by
	virtue of ending at least one DO-loop with the MAYBEZTRIP flag
	set.


***** Begin Version 10 *****

2227	TJK	21-Oct-83
	Rewrite main routine of CMPBLOCK to have it call ENDSBBLOCK to
	determine where  a  basic  block ends.   Also  added  external
	declaration for ENDSBBLOCK,  removed external declaration  for
	ENDSMZTRIP (now  called only  by ENDSBBLOCK),  and fixed  some
	comments.

***** End V10 Development *****

***** End Revision History *****

)%

SWITCHES NOLIST;

REQUIRE FIRST.BLI;
REQUIRE TABLES.BLI;

SWITCHES LIST;

FORWARD
	CMPBLOCK(0),
	SRCHREGCANDATE(1),
	ADDREGCANDATE(2),
	SAVREGCONTAINING(1);

EXTERNAL
	CGERR,		! Generates internal compiler errors
%2227%	CMSTMN,		! Performs complexity walk for current statement
	CORMAN,
%2227%	BASE CSTMNT,	! Pointer to current statement being processed
%2227%	ENDSBBLOCK,	! Checks if the current statement (pointed to
			! by CSTMNT) ends a basic block
%2227%	ISN,		! Internal sequence number of statement being processed
%2227%			! (this is used for error messages)
	SAVSPACE;

OWN BLKISN;	!SEQ NO OF CURRENT  STMNT WITHIN THE BASIC BLOCK

	%(***DEFINE THE TABLE THATS USED TO REMEMBER WHICH VARS/CONSTS
		HAVE THEIR VALS LEFT IN ACS BY THE EXECUTION OF STMNTS IN A
		GIVEN BASIC BLOCK
	*******)%
OWN REGLINK;		!POINTER TO REGCANDIDATES TABLES
			!ENTRIES
			!EACH ENTRY IS THREE WORDS
			!WITH A FORWARD AND BACKWARD LINK
			!IN THE FIRST WORD
			!LH OF REGLINK IS LAST
			!LINK
			!RH OF REGLINK IS FIRST LINK
GLOBAL ROUTINE CMPBLOCK =	![2227] Main routine rewritten in this edit

!++
! FUNCTIONAL DESCRIPTION:
!
!	This is the top level routine for the first pass of the  basic
!	block register allocator.  It causes  a complexity walk to  be
!	performed for every statement in a basic block.
!
!	This routine  is  called with  CSTMNT  pointing to  the  first
!	statement of a basic block.   It returns with CSTMNT  pointing
!	to the first statement of the next basic block.  If the end of
!	the program has been reached  it returns with CSTMNT equal  to
!	zero.   The  REGCANDIDATES  table  is  cleared  when  it   has
!	completed the pass over a basic block.
!
!	If the last statement of the  basic block was a DO  statement,
!	and if the  only reason  for terminating the  basic block  was
!	because of the  DO statement, and  if the DO-variable  doesn't
!	have the DBLFLG flag  set, then it  leaves the DO-variable  in
!	the REGCANDIDATES table  for consideration in  the next  basic
!	block.
!
!	The REGCANDIDATES table should be properly initialized for the
!	first  call  to  this  routine.   For  subsequent  calls,  the
!	REGCANDIDATES table  should  be in  the  state in  which  this
!	routine left it after processing the preceding basic block.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	CSTMNT	points to the first statement of the basic block to be
!		processed.
!
! IMPLICIT OUTPUTS:
!
!	BLKISN	is the  basic block  internal sequence  number of  the
!		current statement.
!
!	CSTMNT	points to the  next statement to  be processed.   Upon
!		return from this routine,  CSTMNT points to the  first
!		statement of  the next  basic  block to  be  processed
!		(unless we just processed the last basic block of  the
!		current program unit, in which case CSTMNT is zero).
!
!	ISN	is the internal sequence number of the statement being
!		processed (used for error messages).
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	NONE
!
!--


BEGIN
	LABEL BLOCK;		! Used to leave basic block processing loop
	REGISTER ENDVAL;	! Used to save value returned by ENDSBBLOCK

	ROUTINE CLRREGCANDIDATES=
	%(**********
		LOCAL ROUTINE TO CLEAR THE REGCADIDATES TABLE
	**********)%
	BEGIN
	LOCAL RGCTBLENTRY RGLST;	!PREVIOUS LINK
	LOCAL RGCTBLENTRY RGLNK;	!CURRENT LINK
	RGLNK_.REGLINK<RIGHT>;	!LOCATE FIRST LINK
	UNTIL .RGLNK EQL 0 DO
	BEGIN
		%(***WALK THRU ALL ENTRIES IN THE TABLE***)%
		LOCAL BASE SYMENTRY;	!LOCAL TO WORK IN
		IF (SYMENTRY_.RGLNK[RGVAR]) NEQ 0	!LOAD SYMBOL/CONST ADR
		THEN
		BEGIN
			%(***CLEAR THE FLAG IN THE SYMBOL
			     TABLE ENTRY THAT INDICATED THAT THE VARIABLE
			     WAS IN THE REGCANDIDATE TABLE***)%
			SYMENTRY[RGCANDFLG]_0
		END;
		RGLST_.RGLNK;		!REMEMBER NODE ADR
		RGLNK_.RGLNK[RGFOR];	!LOCATE NEXT ENTRY
		SAVSPACE(RGCENTSIZE,.RGLST)	!DELETE THE NODE
	END;
	REGLINK_0			!CLEAR THE POINTER
	END;	! of CLRREGCANDIDATES

	BLKISN = 1;	! First statement in basic block has block ISN of 1

	! Now perform the complexity walk  for each statement in  this
	! basic block.

BLOCK:	WHILE TRUE
	DO
	BEGIN	! For each statement in basic block

		ISN = .CSTMNT[SRCISN];	! ISN for the current statement

		CMSTMN();	! Do complexity walk for current stmnt

		! Check if the current statement is the last statement
		! of the basic block  by calling ENDSBBLOCK, and  save
		! the return value in ENDVAL.  If it's 0, we  continue
		! the basic block.  Otherwise  we end the basic  block
		! by leaving BLOCK; ENDVAL will be 1 for a normal  end
		! of the basic  block, and  2 if the  basic block  was
		! ended for the sole reason that CSTMNT points to a DO
		! statement.

		IF (ENDVAL = ENDSBBLOCK()) NEQ 0	! End of basic block?
		THEN LEAVE BLOCK;			! Yes, leave the loop

		! The current statement (pointed  to by CSTMNT)  isn't
		! the last statement of the basic block.

		CSTMNT = .CSTMNT[SRCLINK];	! Move to next statement
		BLKISN = .BLKISN+1;		! Bump basic block ISN

	END;	! For each statement in basic block

	! We're at the end of the basic block.  The last statement  of
	! the basic block has had the complexity walk performed on it,
	! and is pointed to by CSTMNT.  Also, ENDVAL is either 1 or 2;
	! 1 for a normal end  of the basic block,  and 2 if the  basic
	! block was ended for the sole reason that CSTMNT points to  a
	! DO statement.

	CLRREGCANDIDATES();	! Clear the REGCANDIDATES table

	! If we ended  the basic block  for the sole  reason that  the
	! current statement is a DO statement (i.e., ENDVAL is 2),  we
	! set up a REGCANDIDATES table entry for the DO-variable  (but
	! only if it's a single-word data type).

	IF .ENDVAL EQL 2		! Did BB end because of a DO?
	THEN
	BEGIN	! Special DO case

		REGISTER PEXPRNODE DOVAR;	! DOVAR points to the symbol
		DOVAR = .CSTMNT[DOSYM];		! node for the DO-variable

		! If the DO-variable is single-word, set up a
		! REGCANDIDATES entry.

		IF NOT .DOVAR[DBLFLG]		! Is DO-variable single-word?
		THEN ADDREGCANDATE(.DOVAR,.CSTMNT);	! Set up entry

	END;	! Special DO case

	CSTMNT = .CSTMNT[SRCLINK];	! Have CSTMNT point to the next stmnt
					! (i.e., the first stmnt of the next
					! basic block)

END;	! of CMPBLOCK
GLOBAL ROUTINE SRCHREGCANDATE(SYMENTRY)=
%(********
	THIS ROUTINE DETERMINES WHETHER THERE IS AN ENTRY IN THE REGCANDIDATES TABLE FOR
	THE SYMBOL/CONSTANT INDICATED BY THE PARAMETER "SYMENTRY".  IF THERE IS SUCH AN
	ENTRY, IT INDICATES THAT THAT VARIABLE/CONSTANT CAN POTENTIALLY HAVE BEEN LEFT
	IN A REGISTER BY SOME EARLIER STATEMENT IN THIS BASIC BLOCK.
	IF SUCH AN ENTRY IS FOUND, THIS ROUTINE RETURNS A POINTER TO THE PARENT NODE ABOVE
	THE ORIGINAL USE OF THE VARIABLE/CONSTANT (I.E. THE EXPRESSION OR STATEMENT NODE
	WHOSE EVALUATION LEFT THE VALUE OF THE VARIABLE/CONSTANT IN A REGISTER).  THIS
	POINTER IS CONTAINED IN THE REGCANDIDATES TABLE ENTRY.
	IF THE VARIABLE/CONSTANT INDICATED BY SYMENTRY COULD NOT HAVE BEEN PREVIOUSLY LEFT IN
	A REGISTER (I.E. THERE IS NO ENTRY FOR IT IN THE REGCANDIDATE TABLE), THIS ROUTINE
	RETURNS ZERO).
********)%
BEGIN
	MAP PEXPRNODE SYMENTRY;			!POINTER TO THE SYMBOL/CONSTANT TABLE ENTRY FOR THE
						!VARIABLE/CONSTANT BEING SEARCHED FOR

	LOCAL RGCTBLENTRY CREGCENTRY;		!POINTER TO THE ENTRY IN
						!THE REGCANDIDATES LIST
						!CURRENTLY BEING EXAMINED

	IF .SYMENTRY[OPRCLS] NEQ DATAOPR	!CAN ONLY HANDLE CONSTS AND VARS
	THEN RETURN 0;
	IF NOT .SYMENTRY[RGCANDFLG] 		!FLAG IN SYMBOL/CONSTANT TABLE ENTRIES THAT INDICATES
						!WHETHER THAT VARIABLE/CONSTANT MIGHT HAVE BEEN LEFT IN
						!A REGISTER (I.E. HAS A REGCANDIDATES TABLE ENTRY)
	THEN RETURN 0;

	%(***SEARCH THE REGCANDIDATES TABLE FOR THE ENTRY CORRESPONDING TO SYMENTRY.
		SEARCH IS DONE STARTING FROM THE LATEST ENTRY AND GOING BACKWARDS (SINCE
		THERE MAY BE MORE THAN ONE ENTRY FOR A GIVEN VARIABLE/CONSTANT IN THE
		TABLE-AND WE ALWAYS WANT THE LAST SUCH ENTRY).
	***)%
	CREGCENTRY_.REGLINK<LEFT>;		!POINTER TO LATEST ENTRY
	UNTIL .CREGCENTRY EQL 0 DO 
	BEGIN
		IF .CREGCENTRY[RGVAR] EQL .SYMENTRY !IF THIS ENTRY CORRESPONDS TO SYMENTRY
		THEN
		RETURN .CREGCENTRY[RGINITUSE];	!THEN RETURN A POINTER TO THE NODE WHOSE
						!EVALUATION LEFT THE VALUE OF THE VARIABLE
						!INDICATED IN A REGISTER.
		CREGCENTRY_.CREGCENTRY[RGBAK]
	END;

	%(***IF THE RGCANDFLG WAS SET IN THE SYMBOL TABLE ENTRY AND NO ENTRY WAS FOUND
		IN THE REGCANDIDATES TABLE, HAVE A COMPILER ERROR***)%
	CGERR();
END;						!END OF SRCHREGCANDIDATES
GLOBAL ROUTINE ADDREGCANDATE(SYMENTRY,USEPTR)=
%(**********
	THIS ROUTINE ADDS AN ENTRY TO THE REGCANDIDATES TABLE FOR THE USE OF
	THE VARIABLE/CONSTANT INDICATED BY THE SYMBOL/CONSTANT TABLE ENTRY
	"SYMENTRY" AT THE EXPRESSION/STATEMENT NODE POINTED TO BY "USEPTR".
	USEPTR IS ASSUMED TO POINT TO AN EXPRESSION/STATEMENT NODE WHOSE
	EVALUATION WILL LEAVE THE VALUE OF THAT VARIABLE/CONSTANT IN A REGISTER.
		IF THE REGCANDIDATES TABLE IS FULL, THIS ROUTINE OVERWRITES THE
	EARLIEST ENTRY IN THE TABLE.
**********)%
BEGIN
	LOCAL RGCTBLENTRY RGLNK;		!ENTRY TO CREATE
	LOCAL RGCTBLENTRY RGLST;		!LAST LINK
	MAP PEXPRNODE SYMENTRY;

	IF .SYMENTRY[OPRCLS] NEQ DATAOPR	!CAN ONLY HANDLE CONSTS AND VARS
	THEN RETURN;

	IF (RGLST_.REGLINK<LEFT>) NEQ 0 THEN
	IF .RGLST[RGVAR] EQL .SYMENTRY
	THEN
	BEGIN
		RETURN RGLST[RGINITUSE]_.USEPTR
	END;

	%(***SET UP NEW ENTRY***)%

	NAME<LEFT>_RGCENTSIZE+1;	!SET SIZE OF NODE
	RGLNK_CORMAN();			!ALLOCATE NODE
	IF .REGLINK EQL 0 THEN
	BEGIN
		%(***FIRST LINK***)%
		REGLINK<RIGHT>_REGLINK<LEFT>_.RGLNK;
		RGLNK[RGFOR]_RGLNK[RGBAK]_0
	END
	ELSE
	BEGIN
		%(***ADDITIONAL LINK***)%
		RGLST[RGFOR]_.RGLNK;		!LINK NODE TO END OF CHAIN
		RGLNK[RGBAK]_.RGLST;		!CREATE BACKWARD LINK
		REGLINK<LEFT>_.RGLNK;		!POINT TO LAST LINK
		RGLNK[RGFOR]_0			!MAKE SURE NO FORWARD LINK
	END;
	RGLNK[RGVAR]_.SYMENTRY;
	RGLNK[RGINITUSE]_.USEPTR;

	%(***SET SYMBOL TABLE FLAG INDICATING REGCANDIDATES LINK EXISTS***)%

	SYMENTRY[RGCANDFLG]_1;

	RETURN

END;						!END OF ADDREGCANDATE
GLOBAL ROUTINE SAVREGCONTAINING(SYMENTRY)=
%(********
	IF THE VARIABLE/CONSTANT INDICATED BY "SYMENTRY" (A POINTER TO A SYMBOL/CONSTANT TABLE ENTRY)
	COULD HAVE BEEN LEFT IN A REGISTER DURING THE EVALUATION OF SOME EXPRESSION/STATEMENT
	EARLIER IN THIS BASIC BLOCK, THIS ROUTINE SETS THE FLAG "SAVREGFLG" IN THAT EARLIER
	EXPRESSION/STATEMENT NODE-TO INDICATE THAT THE REGISTER CONTAINING THE VALUE
	OF THE ARGUMENT UNDER THAT NODE SHOULD BE PRESERVED.  THIS ROUTINE
	ALSO SETS THE "SONNXTUSE" FIELD OF THAT EXPRESSION/STATEMENT NODE TO
	INDICATE THE BLOCK-ISN OF THE STATEMENT BEING PROCESSED WHEN THIS ROUTINE
	WAS CALLED.  THE GLOBAL "BLKISN" IS ASSUMED TO BE SET TO THAT ISN.
		THIS ROUTINE RETURNS "TRUE" IF THE VARIABLE/CONSTANT COULD HAVE BEEN
	LEFT IN A REGISTER, "FALSE" IF NOT.
********)%
BEGIN
	EXTERNAL EXCHARGS;		!ROUTINE TO EXCHANGE THE 2 ARGS OF
					! AN OPERATOR IF POSSIBLE (FOR RELATIONALS,
					! IT REVERSES THE SENSE OF THE REL)
	EXTERNAL SRCHREGCANDATE;		!ROUTINE TO DETERMINE WHETHER A GIVEN VARIABLE/CONSTANT
						!COULD HAVE BEEN LEFT IN A REGISTER BY EXECUTION OF
						!A PREVIOUS STATEMENT.  RETURNS A POINTER TO THE
						!EXPRESSION/STATEMENT WHOSE EVALUATION LEAVES IT IN A NEG.
	OWN PEXPRNODE PREVREFERENCE;		!POINTER TO THE EXPRESSION/STATEMENT WHOSE EVALUATION
						!LEAVES SYMENTRY IN A REGISTER

	PREVREFERENCE_SRCHREGCANDATE(.SYMENTRY);

	IF .PREVREFERENCE EQL 0			!IF THE VARIABLE/CONSTANT COULD NOT HAVE BEEN LEFT IN
	THEN RETURN FALSE;			!A REGISTER, RETURN FALSE


	IF .PREVREFERENCE[SAVREGFLG]		!IF HAVE ALREADY DETERMINED THAT THIS REGISTER
	THEN RETURN TRUE;			!SHOULD BE PRESERVED, DO NOT ALTER ANYTHING


	IF .PREVREFERENCE[OPRCLS] EQL STATEMENT	!IF THE ORIGINAL REFERENCE WAS DIRECTLY UNDER
	THEN					!A STATEMENT NODE
	BEGIN
		%(****ASSIGNMENT STATEMENTS THAT WOULD HAVE BEEN COMPUTED TO MEMORY
			SHOULD BE COMPUTED TO "BOTH" IF THE VALUE OF THE LHS WILL BE
			USEFUL LATER
		****)%
		IF .PREVREFERENCE[SRCID] EQL ASGNID AND .PREVREFERENCE[MEMCMPFLG]
		THEN
		BEGIN
			REGISTER PEXPRNODE RHNODE;	!EXPRESSION ON RHS OF ASSIGNMENT STMNT
			RHNODE_.PREVREFERENCE[RHEXP];

			IF .RHNODE[SAVREGFLG]		!IF HAVE ALREADY DECIDED THAT SHOULD
							! SAVE THE OPERAND BEING ADDED(SUBTRACTED, ETC)
							! TO MEMORY, DONT CHANGE THE OPERATION
							! TO BE TO BOTH
			THEN RETURN FALSE;

			IF .RHNODE[OPRCLS] EQL SPECOP	!IF THE OPERATION IS A "SPECIALLY
							! OPTIMIZED OP", 							! WE CONT GENERATE OP TO BOTH
							! (THIS MAY CHANGE IN A LATER VERSION)
			THEN RETURN FALSE;


			IF .RHNODE[OPERATOR] EQL CMPMUL	!DO NOT HAVE COMPLEX MULTIPLY
				OR .RHNODE[OPERATOR] EQL CMPDIV	! AND DIVIDE TO BOTH ROUTINES
			THEN RETURN FALSE;



			PREVREFERENCE[OPTOBOTHFLG]_1; !SET FLAG FOR "OPERATION TO BOTH"
							!IN THE ASSIGNMENT STATEMENT
			RHNODE[OPTOBOTHFLG]_1;		!AND THE EXPRESSION ON THE RIGHT
								!HAND SIDE
		END

		ELSE
		IF .PREVREFERENCE[SRCID] EQL ENTRID	!IF PREV REF WAS ON THE PARAMETER
						! LIST OF THE SUBROUTINE ENTRY
			OR .PREVREFERENCE[SRCID] EQL SFNID !OR OF A STMNT FN

		THEN
		BEGIN
			REGISTER ARGUMENTLIST ARGLST;	!PTR TO THE ARGLIST AT THAT ENTRY
			IF (ARGLST_
				(IF .PREVREFERENCE[SRCID] EQL ENTRID
				THEN .PREVREFERENCE[ENTLIST]
				ELSE .PREVREFERENCE[SFNLIST])
			   ) EQL 0 THEN CGERR(); !IF THIS ENTRY HAD NO PARAMS

			%(***SEARCH THE PARAM LIST FOR THE ELEMENT THAT POINTS TO "SYMENTRY"***)%
			INCR I FROM 1 TO .ARGLST[ARGCOUNT]
			DO
			BEGIN
				IF .ARGLST[.I,ARGNPTR] EQL .SYMENTRY !IF THIS ARG LIST ENTRY
				THEN			! IS THE ONE FOR "SYMENTRY"
				BEGIN
					ARGLST[.I,ENTSAVREGFLG]_1;	!SET FLAG TO SAVE THIS
								! THIS PARAM IN A REG
					ARGLST[.I,ENTSONNXTUSE]_.BLKISN;  !LOC OF NEXT USE
					RETURN TRUE
				END
			END;
			CGERR()	!IF THE PARAM LIST AT THIS ENTRY DID NOT INCLUDE "SYMENTRY"
				! HAVE AN INTERNAL COMPILER BUG
		END;

		PREVREFERENCE[SRCSAVREGFLG]_1;	!SET FLAG TO "SAVE REGISTER HOLDING VAL OF SON"
		PREVREFERENCE[SRCSONNXTUSE]_.BLKISN; !"LOC OF NEXT USE OF SON" TO INDICATE ISN
							!OF STMNT BEING EXANIMED NOW

		RETURN TRUE
	END

	ELSE					!IF THE ORIGINAL REFERENCE WAS DIRECTLY UNDER AN EXPRESSION
	BEGIN
		%(***IF THE ORIGINAL USE WAS AS ARG1 OF AN OP TO MEMORY, BUT
			WE HAVE SINCE CHANGED THAT OPERATION TO BE PERFORMED TO BOTH,
			THEN THE VAL WONT HAVE BEEN LEFT IN A REG***)%
		IF .PREVREFERENCE[MEMCMPFLG] AND .PREVREFERENCE[OPTOBOTHFLG]
		THEN RETURN FALSE;

		%(***IF THE ORIGINAL USE WAS AS AN ARGUMENT OF A RELATIONAL, MAKE SURE THAT
			IT IS THE FIRST ARGUMENT OF THE RELATIONAL
		***)%
		IF .PREVREFERENCE[OPRCLS] EQL RELATIONAL
		THEN
		BEGIN
			IF .PREVREFERENCE[ARG1PTR] NEQ .SYMENTRY
			THEN
			BEGIN
				%(***IF ARG1 OF THE REL WAS A REAL IMMED CONST, DO NOT
					EXCHANGE THE ARGS (SINCE CANT DO COMPARE IMMED ON A REAL***)%
				IF .PREVREFERENCE[A1IMMEDFLG]
				THEN
				BEGIN
					REGISTER PEXPRNODE ARG1NODE;	!ARG1 UNDER THE REL
					ARG1NODE_.PREVREFERENCE[ARG1PTR];
					IF .ARG1NODE[VALTP1] NEQ INTEG1
					THEN RETURN FALSE	!CANT SAVE THE VAL OF ARG2
								! IN A REG
					ELSE  EXCHARGS(.PREVREFERENCE)
				END
				ELSE EXCHARGS(.PREVREFERENCE);

				%(***IF A2NEGFLG IS NOW SET (AS A RESULT OF EXCHANGING
					THE ARGS, GET RID OF A2NEGFLG BY:
						A.LT.-B = -A.GT.B
					ETC.  (CANNOT HANDLE A2NEGFLG ON A REL IN
					CODE GEN) 
				******)%
				IF .PREVREFERENCE[A2NEGFLG]
				THEN
				BEGIN
					PREVREFERENCE[A1NEGFLG]_NOT .PREVREFERENCE[A1NEGFLG];
					PREVREFERENCE[A2NEGFLG]_0;
					IF NOT EQREL(.PREVREFERENCE[OPERSP]) 
					THEN PREVREFERENCE[OPERSP]_REVREL(.PREVREFERENCE[OPERSP]);
				END;
			END
		END;


		PREVREFERENCE[SAVREGFLG]_1;	!SET FLAG TO "SAVE REG HOLDING VAL OF SON"
		PREVREFERENCE[SONNXTUSE]_.BLKISN;	!IN ORIGINAL REFERENCE, SET "LOC OF NEXT USE OF
						!SON" TO INDICATE ISN OF STMNT BEING EXAMINED
						!NOW


		RETURN TRUE
	END
END;						!END OF SAVREGCONTAINING
GLOBAL ROUTINE INITREGCANDIDATES=
%(**********
	ROUTINE TO INIT THE REGCANDIDATES TABLE THE FIRST TIME (WHEN
	NO ACTUAL SYMBOL TABLE ENTRIES ARE POINTED TO BY THE REGCANDIDATES
	TABLE ENTRIES - AND HENCE NO "RGCANDFLG"S MUST BE CLEARED).
	SIMPLY CLEARS THE TABLE
**********)%
BEGIN
	REGLINK_0		!CLEAR REGCANDIDATES TABLE POINTER
END;