Google
 

Trailing-Edge - PDP-10 Archives - BB-4157D-BM - sources/p2s2.bli
There are 12 other files named p2s2.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/MD/DCE/JNG
MODULE	P2S2(SREG=#17,VREG=#15,FREG=#16,DREGS=4,RESERVE(0,1,2,3),GLOROUTINES) =
BEGIN

GLOBAL BIND P2S2V = 5^24 + 1^18 + 56;	!VERSION DATE: 18-AUG-77

%(
REVISION HISTORY

47	-----	-----	FOLD EXPONENTIATIONS WHICH
			REQUIRE FEWER THAN 8 MULTIPLIES INTO THE SPECIAL
			OPERATOR EXPCIOP
			ELIMINATE SQROP, CUBOP, P4OP
48	-----	-----	FIX INTEGC AND CREATION OF SPECIAL OP EXPCIOP

49	-----	-----	DO DP EXPONENS TO INTEGER POWERS IN LINE ON KI10
50	-----	-----	MAKE "CNTMPY" A GLOBAL ROUTINE
51	331	17091	FIX TAKNEGARG FOR OPERATOR EXPCIOP
			RAISE TO AN ODD POWER CANNOT ABSORB NEG
52	345	17554	ABSORB NEG CORRECTLY FOR EVEN EXPONENTIATION
53	430	18876	ABSORB NEG IN ARITHMETIC IF CORRECTLY

	BEGIN VERSION 5A, 7-NOV-76

54	530	21606	DO NOT ALLOW FSC ON DOUBLE PRECISION NUMBERS
55	553	21826	BE CAREFUL COLLAPSING AN AND NODE WITH TRUE AS ARG
56	610	23333	FIX EDIT 52 (MUST TEST OPERCLAS TOO)
)%

	EXTERNAL
		CANONICALIZE,CGERR,MAKEPR,C1H,C1L,C2H,C2L,COPRIX,CNSTCM,
		KBOOLBASE,KTYPCB,SPKABA,CNSTCMB,TBLSEARCH,
		SKERR;
	FORWARD
		TAKNEGARG(1),SETNEG(2),DNEGCNST(1),NEGOFNOT(1),NOTOFNEG(1), BLCMB(3), 
		ARCMB(4),CMBEQLARGS(1),FOLDLIF(0),FOLDAIF(0);


	EXTERNAL
		P2SKBL,P2SKREL,P2SKFN,P2SKARITH,P2SKLTP,P2SKLARR,
		P2SKNEGNOT;


EXTERNAL NEGFLG,NOTFLG;

EXTERNAL P2SKL1DISP;

EXTERNAL SETPVAL;
EXTERNAL KDNEGB;

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



%(***************************************************************************
	THIS MODULE CONTAINS ROUTINES USED BY PHASE 2 SKELETON.
***************************************************************************)%



GLOBAL ROUTINE TAKNOTARG(PNODE)=
%(***************************************************************************
	THIS ROUTINE RETURNS "TRUE" IFF THE NODE POINTED TO BY PNODE CAN
	ABSORB A "NOT" ON ITS ARGS AS "A1NOTFLG" OR "A2NOTFLG"
***************************************************************************)%
BEGIN
	MAP PEXPRNODE PNODE;

	%(***WHETHER OR NOT A NODE CAN ABSORB A NOT FROM BELOW DEPENDS ON ITS OPRCLS**)%
	RETURN
	(
		CASE .PNODE[OPRCLS] OF SET
		TRUE;			!BOOLEAN NODES ABSORB NOT ON SONS
		FALSE;		!SHOULD NEVER SEE A DATA NODE AS A "PARENT"
		FALSE;		!RELATIONALS CANNOT ABSORB 'NOT' FROM SONS
					! (NOTE HOWEVER THAT THEY DO ABSORB 'NOT' PROPAGATED
					! DOWN FROM ABOVE THEM
		FALSE;		!NOT ON AN ARG TO A FN CALL CANNOT BE ABSORBED
		FALSE;		!ARITHMETIC NODES DO NOT ABSORB NOT
		BEGIN			!TYPE-CONV NODES ABSORB NOT EXCEPT
			IF NOCNV(PNODE)	! FOR THOSE THAT DONT ACTUALLY
			THEN TAKNOTARG(.PNODE[PARENT])
			ELSE TRUE		! GENERATE ANY CODE
		END;
		TRUE;			!ARRAY-REF NODES ABSORB NOT ON THE ADDR CALC
		TRUE;			!COMMON SUBEXPR NODES ABSORB NOT
		TRUE;			!NEG/NOT NODES ABSORN NOT
		TRUE;			!THE SPECIAL-CASE OPERATORS ABSORB NOT
		FALSE;		!FIELD-REF - NOT IN RELEASE 1
		FALSE;		!STORECLS - SHOULD NOT OCCUR IN P2S
		FALSE;		!REGCONTENTS - NOT ABOVE NEG/NOT
		FALSE;		!LABOP
		BEGIN			!STATEMENT - FOR ASSIGNMENT AND LOGICAL IF,
					! PARENT CAN ABSORN NOT, OTHERWISE IT CANT
			IF .PNODE[SRCID] EQL ASGNID OR .PNODE[SRCID] EQL IFLID
			THEN TRUE
			ELSE FALSE
		END;
		FALSE;		!IOLSCLS - CANNOT PROPAGATE
		FALSE;		!INLINFN - CANNOT PROPAGATE FOR ALL OF
					! THEM, SO DONT BOTHER
		TES
	)
END;


GLOBAL ROUTINE TAKNEGARG(PNODE)=
%(***************************************************************************
	THIS ROUTINE RETURNS "TRUE" IFF THE NODE PNODE  CAN ABSORB A
	NEG ON ITS ARG(S) AS "A1NEGFLG" OR "A2NEGFLG".
***************************************************************************)%
BEGIN
	MAP PEXPRNODE PNODE;

	%(***WHETHER OR NOT A NODE CAN ABSORB A NEG FROM BELOW DEPENDS ON ITS OPRCLS***)%
	RETURN
	(
		CASE .PNODE[OPRCLS] OF SET
		FALSE;			!BOOLEANS DO NOT ABSORB NEG
		FALSE;			!DATA ITEM (SHOULD NEVER OCCUR)
		TRUE;			!RELATIONALS DO ABSORB NEG
		FALSE;			!NEG ON ARG TO A FN CALL CANNOT BE ABSORBED
		BEGIN			!ARITH NODES EXCEPT FOR EXPONEN ABSRB NEG
			IF .PNODE[OPERSP] EQL EXPONOP
			THEN FALSE
			ELSE TRUE
		END;
		BEGIN
			IF NOCNV(PNODE)	!FOR TYPE-CNV NODES THAT GENERATE NO CODE
			THEN TAKNEGARG(.PNODE[PARENT])	!WILL HAVE TO PASS THE NEG UP AN
							! ADDITIONAL LEVEL
			ELSE TRUE	!OTHER TYPE-CNV NODES DO ABSORB NEG FROM BELOW
		END;
		TRUE;			!ARRAYREF NODES ABSORB NEG FROM ADDR CALC
		TRUE;			!COMMON SUBEXPR NODES ABSORB NEG
		TRUE;			!NEG/NOT NODES ABSORB NEG
%**;[331],TAKNEGARG,MD,14-NOV-75%
%**;[331],CHANGE @ LINE 3267  CASE P2MUL...%
		BEGIN			![331] SPECOP ABSORB NEG EXCEPT
			IF .PNODE[OPERSP] EQL EXPCIOP	![331] FOR RAISE
			AND .PNODE[ARG2PTR]	![331] TO AN ODD POWER
			THEN FALSE		![331]
			ELSE TRUE		![331]
		END;				![331]
		FALSE;			!FIELD-REF - NOT IN RELEASE 1
		FALSE;			!STORECLS NODES DO NOT ABSORB NEG (SHOULD NOT OCCUR IN P2S)
		FALSE;			!REGCONTENTS - NEVER OCCURS ABOVE NEG
		FALSE;			!LABOP - NEVER OCCURS
		BEGIN			!STATEMENT - ASSIGNMENT AND ARITH-IF ABSORB NEG
			IF .PNODE[SRCID] EQL ASGNID
				OR .PNODE[SRCID] EQL IFAID
			THEN TRUE
			ELSE FALSE
		END;
		FALSE;			!IOLSCLS - CANNOT PROPAGATE NEG UP
		FALSE;			!INLINFN - CANNOT ALWAYS PROPAGATE NEG UP- SO
					! DONT BOTHER
		TES      
	)
END;


GLOBAL ROUTINE SETNEG(PNODE,ARG1FLG)=
%(***************************************************************************
	IF THE NODE "PNODE" CANNOT ABSORB A NEGATE FROM ITS ARGS AS A1NEGFLG/A2NEGFLG
	THEN THIS ROUTINE RETURNS FALSE.
	IF "PNODE" CAN ABSORB A NEGATE FROM ITS ARGS, THEN THIS ROUTINE
	COMPLEMENTS EITHER A1NEGFLG (IF "ARG1FLG" IS TRUE) OR A2NEGFLG (IF
	"ARG1FLG" IS FALSE) IN PNODE AND RETURNS TRUE
***************************************************************************)%
BEGIN
	MAP PEXPRNODE PNODE;

	IF TAKNEGARG(.PNODE)
	THEN
	BEGIN
		%(***IF PNODE CAN ABSORB NEG FROM ITS ARGS***)%
!**;[430] Change @ 3301 in SETNEG	JNG	20-Aug-76
%[430]%		IF .ARG1FLG OR (.PNODE[OPRCLS] EQL STATEMENT AND .PNODE[SRCID] EQL IFAID)
%[430]%			! ARITHMETIC IF STATEMENT NODES ALWAYS USE THE A1????? FLAGS
		THEN
		BEGIN
			IF .PNODE[A1NOTFLG] THEN RETURN FALSE;
	!**;[610], SETNEG @3325, DCE, 18-AUG-77
	!**;[610], SIMPLY ABSORB THE NEG FOR EVEN EXPONENTIATION
	%[610]%		IF .PNODE[OPR1] NEQ EXPCIF THEN
			 PNODE[A1NEGFLG]_NOT .PNODE[A1NEGFLG]
		END
		ELSE
		BEGIN
			IF .PNODE[A2NOTFLG] THEN RETURN FALSE;
			 PNODE[A2NEGFLG]_NOT .PNODE[A2NEGFLG];
		END;

		RETURN TRUE
	END
	ELSE
	RETURN FALSE
END;



GLOBAL ROUTINE DNEGCNST(CNNODE)=
%(***************************************************************************
	ROUTINE TO TAKE THE NEGATIVE OF A DOUBLE-PREC CONSTANT.
	RETURNS  A PTR TO THE CONSTANT TABLE ENTRY FOR THE NEW CONSTANT.
***************************************************************************)%
BEGIN
	MAP PEXPRNODE CNNODE;

	%(***SET UP GLOBALS USED BY THE ASSEMBLY LANG CONSTANT FOLDING
		ROUTINE*****)%
	C1H_.CNNODE[CONST1];
	C1L_.CNNODE[CONST2];
	COPRIX_KDNEGB+.CKA10FLG;

	CNSTCM();

	RETURN MAKECNST(.CNNODE[VALTYPE],.C2H,.C2L);
END;


GLOBAL ROUTINE NOTOFNEG(CNODE)=
%(***************************************************************************
	IN PHASE 2 SKELETON WHEN WERE TRYING TO PROPAGATE A NOT DOWN OVER A NEG
	AS IN NOT(-X), CALL THIS ROUTINE
	CALLED WITH THE ARG CNODE A PTR TO THE 'NEG' NODE;
		WITH NOTFLG KNOWN TO BE SET
	IF X IS A CONSTANT, CREATE A NEW CONSTANT FOR NOT(-X)
	OTHERWISE, SINCE CANNOT PROPAGATE NOT ACROSS NEGATE, PROPAGATE
	THE NOT BACK UP AND ATTEMPT TO PROPAGATE THE NEG DOWN.
	IF THE NEG CANNOT BE PROPAGATED DOWN, MUST LEAVE THE NEG NODE IN THE
	TREE (IN ALL OTHER CASES, NEG NODES ARE ELIMINATED
	FROM THE TREE)
***************************************************************************)%
BEGIN
	MAP PEXPRNODE CNODE;
	LOCAL PEXPRNODE ARGNODE;

	ARGNODE_.CNODE[ARG2PTR];

	IF .CNODE[A2VALFLG]
	THEN

	%(****IF THE ARG UNDER CNODE IS A LEAF****)%
	BEGIN

		IF .ARGNODE[OPR1] EQL CONSTFL
		THEN
		%(***IF THE ARG IS A CONSTANT, CAN ELIMINATE BOTH THE NEG AND
			THE NOT - BY CREATING A NEW CONSTANT***)%
		BEGIN
			NOTFLG_FALSE;
			%(***SET THE VAL-FLAG IN THE PARENT OF THE NEG NODE***)%
			SETPVAL(.CNODE);
			RETURN NTNGCNST(ARGNODE);
		END

		ELSE
		%(***IF THE ARG IS A LEAF, BUT NOT A CONSTANT, CANNOT
			PROPAGATE THE NEG DOWN AND HENCE MUST LEAVE THE NEG
			NODE IN THE TREE******)%
		RETURN .CNODE;

	END

	ELSE
	%(***IF THE ARG UNDER THE NEGATE NODE IS NOT A LEAF, ATTEMPT TO PROPAGATE
		THE NEG DOWN OVER IT (BUT DO NOT PROPAGATE THE NOT)***)%
	BEGIN
		NOTFLG_FALSE;
		NEGFLG_NOT .NEGFLG;
		ARGNODE_(.P2SKL1DISP[.ARGNODE[OPRCLS]])(.ARGNODE);
		IF .NEGFLG
		THEN
		%(***IF COULD NOT PROPAGATE THE NEGATE, MUST LEAVE THE NEGATE NODE
			IN THE TREE***)%
		BEGIN
			NEGFLG_FALSE;
			CNODE[ARG2PTR]_.ARGNODE;
			NOTFLG_TRUE;			!PROPAGATE THE NOT BACK UP
			RETURN .CNODE;
		END

		ELSE
		BEGIN
			NOTFLG_TRUE;
			%(***IF ARE REPLACING THE 'NEG' NODE BY A LEAF, SET THE VALFLG
				IN THE PARENT OF THE NEG NODE***)%
			IF .ARGNODE[OPRCLS] EQL DATAOPR OR .ARGNODE[OPRCLS] EQL REGCONTENTS 
			THEN SETPVAL(.CNODE)
			ELSE
			ARGNODE[PARENT]_.CNODE[PARENT];
			RETURN .ARGNODE;
		END;
	END;
END;


GLOBAL ROUTINE NEGOFNOT(CNODE)=
%(***************************************************************************
	IN PHASE 2 SKELETON WHEN WERE TRYING TO PROPAGATE A NEG DOWN OVER A NOT
	AS IN -(NOT X), CALL THIS ROUTINE 
	CALLED WITH THE ARG CNODE A PTR TO THE 'NOT' NODE;
		WITH NEGFLG KNOWN TO BE SET
	IF X IS A CONSTANT, CREATE A NEW CONSTANT FOR-(NOT X)
	OTHERWISE, SINCE CANNOT PROPAGATE NEGATE ACROSS NOT, PROPAGATE
	THE NEG BACK UP AND ATTEMPT TO PROPAGATE THE NOT DOWN.
	IF THE NOT CANNOT BE PROPAGATED DOWN, MUST LEAVE THE NOT NODE IN THE
	TREE (IN ALL OTHER CASES, NOT NODES ARE ELIMINATED
	FROM THE TREE)
***************************************************************************)%
BEGIN
	MAP PEXPRNODE CNODE;
	LOCAL PEXPRNODE ARGNODE;

	ARGNODE_.CNODE[ARG2PTR];

	IF .CNODE[A2VALFLG]
	THEN

	%(****IF THE ARG UNDER CNODE IS A LEAF****)%
	BEGIN

		IF .ARGNODE[OPR1] EQL CONSTFL
		THEN
		%(***IF THE ARG IS A CONSTANT, CAN ELIMINATE BOTH THE NEG AND
			THE NOT - BY CREATING A NEW CONSTANT***)%
		BEGIN
			NEGFLG_FALSE;
			%(***SET THE VAL FLAG IN THE PARENT OF THE "NOT"***)%
			SETPVAL(.CNODE);
			RETURN NGNTCNST(ARGNODE);
		END

		ELSE
		%(***IF THE ARG IS A LEAF, BUT NOT A CONSTANT, CANNOT
			PROPAGATE THE NOT DOWN AND HENCE MUST LEAVE THE NOT
			NODE IN THE TREE******)%
		RETURN .CNODE;

	END

	ELSE
	%(***IF THE ARG UNDER THE NOT IS NOT A LEAF, ATTEMPT TO PROPAGATE
		THE NOT DOWN OVER IT (BUT DO NOT PROPAGATE THE NEGATE)***)%
	BEGIN
		NEGFLG_FALSE;
		NOTFLG_NOT .NOTFLG;
		ARGNODE_(.P2SKL1DISP[.ARGNODE[OPRCLS]])(.ARGNODE);
		IF .NOTFLG
		THEN
		%(***IF COULD NOT PROPAGATE THE NOT, MUST LEAVE THE NOT NODE
			IN THE TREE***)%
		BEGIN
			NOTFLG_FALSE;
			CNODE[ARG2PTR]_.ARGNODE;
			NEGFLG_TRUE;			!PROPAGATE THE NEG BACK UP
			RETURN .CNODE;
		END

		ELSE
		BEGIN
			NEGFLG_TRUE;
			%(***IF THE NOT NODE IS BEING REPLACED BY A LEAF, SET THE VAL-FLAG
				IN THE PARENT****)%
			IF .ARGNODE[OPRCLS] EQL DATAOPR OR .ARGNODE[OPRCLS] EQL REGCONTENTS
			THEN SETPVAL(.CNODE)
			ELSE
			ARGNODE[PARENT]_.CNODE[PARENT];
			RETURN .ARGNODE;
		END;
	END;
END;

GLOBAL ROUTINE BLCMB(CNODE,CNARGNODE,VARGNODE)=
%(***************************************************************************
	ROUTINE TO CHECK FOR
		TRUE AND A = A
		FALSE AND A = FALSE
		TRUE OR A = TRUE
		FALSE OR A = A
		TRUE EQV A = A
		FALSE EQV A = NOT A
		TRUE XOR A = NOT A
		FALSE XOR A = A
	CALLED WITH THE ARGS
		CNODE - THE PARENT NODE TO BE CHECKED
		CNARGNODE - ARG KNOWN TO BE A CONSTANT
		VARGNODE - ARG KNOWN TO BE A VARIABLE
	IF THE VALUE OF CNARGNODE IS TRUE OR FALSE, REPLACES CNODE BY
	THE VALUE INDICATED ABOVE.
***************************************************************************)%
BEGIN
	MAP PEXPRNODE CNODE:CNARGNODE:VARGNODE;
	OWN PEXPRNODE OLDCNODE;

	%(***A CONSTANT MUST HAVE VALTYPE CONTROL,LOGICAL, OR INTEGER TO BE 'TRUE' OR 'FALSE'****)%
	IF .CNARGNODE[VALTP1] NEQ INTEG1
	THEN RETURN .CNODE;

	OLDCNODE_.CNODE;

	IF .CNARGNODE[CONST2] EQL TRUE
	THEN
	%(***IF CONSTANT ARG IS "TRUE"*******)%
	BEGIN

		CASE .CNODE[OPERSP] OF SET

		%(***FOR AND***)%
		CNODE_.VARGNODE;

		%(***FOR OR***)%
		CNODE_.CNARGNODE;

		%(***FOR EQV***)%
		CNODE_.VARGNODE;

		%(***FOR XOR***)%
		%(****TRUE XOR A=NOT A****)%
		%(******(IN ORDER TO PASS A "NOT" BACK UP IN THE TREE WOULD HAVE TO
			FIRST EXAMINE THE OPRCLS OF THE PARENT. SINCE THIS IS A RARE CASE,
			DONT BOTHER)****)%
		BEGIN
		END

		TES;
	END

	ELSE
	IF .CNARGNODE[CONST2] EQL FALSE
	THEN
	%(***IF CONSTANT ARG IS FALSE***)%
	BEGIN
		CASE .CNODE[OPERSP] OF SET

		%(***FOR AND***)%
		CNODE_.CNARGNODE;

		%(***FOR OR*****)%
		CNODE_.VARGNODE;

		%(***FOR EQV****)%
		%(****FALSE EQV A = NOT A****)%
		%(******(IN ORDER TO PASS A "NOT" BACK UP IN THE TREE WOULD HAVE TO
			FIRST EXAMINE THE OPRCLS OF THE PARENT. SINCE THIS IS A RARE CASE,
			DONT BOTHER)****)%
		BEGIN
		END;

		%(***FOR XOR*****)%
		CNODE_.VARGNODE

		TES;

	END;


	%(***IF HAVE REPLACED THE OLD CNODE BY "VARGNODE" AND THERE WAS A "NOTFLG"
		SET IN THE OLD CNODE OVER "VARGNODE", MUST SET THAT FLAG IN THE
		NEW PARENT OF VARGNODE****)%
	IF .CNODE EQL .VARGNODE
	THEN 
	BEGIN		OWN VNOTFLG;

	!**;[553], BLCMB @3607, DCE, 22-MAR-77
	!**;[553], IF TYPE CONVERSION NODE IS BEING PROMOTED, WE MUST
	!**;[553], TAKE INTO CONSIDERATION THE FACT THAT IT MAY HAVE TO
	!**;[553], GENERATE CODE NOW WHERE IT DIDN'T USED TO...
	%[553]%	IF .CNODE[OPRCLS] EQL TYPECNV THEN CNODE[NOCNVFLG]_0;
		VNOTFLG_(IF .VARGNODE EQL .OLDCNODE[ARG1PTR]
			THEN .OLDCNODE[A1NOTFLG]
			ELSE .OLDCNODE[A2NOTFLG]);
		IF .VNOTFLG
		THEN
		BEGIN
			IF TAKNOTARG(.OLDCNODE[PARENT])	!IF THE NOT CAN BE PROPAGATED
			THEN				! BACK UP TO THE NEW PARENT OF VARGNODE
			NOTFLG_NOT .NOTFLG		! THEN WILL DO SO
			ELSE				!IF CANNOT
			RETURN .OLDCNODE		! THEN GIVE UP ON THIS OPTIM
		END
	END;


	%(***IF HAVE THE OLD CNODE BY A VARIABLE OR CONSTANT, SET THE VALFLG IN ITS
		PARENT.
		IF HAVE REPLACED IT BY AN EXPRESSION, SET THE PARENT PTR OF THE
		EXPRESSION.
	*********)%
	IF .CNODE[OPRCLS] EQL DATAOPR OR .CNODE[OPRCLS] EQL REGCONTENTS
	THEN
	SETPVAL(.OLDCNODE)
	ELSE
	CNODE[PARENT]_.OLDCNODE[PARENT];

	RETURN .CNODE;

END;



GLOBAL ROUTINE ARCMB(CNODE,CNARGNODE,VARGNODE,ARG1CFLG)=
%(****************************************************************************
	THIS ROUTINE IS CALLED DURING PHASE 2 SKEL WHEN ONE OF THE
	ARGS OF AN ARITHMETIC OPERATOR IS A CONSTANT
	IT COLLAPSES
		0 + A = A
		0 - A = -A
		0 * A = 0
		0/A = 0
		A ** 0 = 1 (CANNOT OPTIMIZE 0**A BECAUSE A MIGHT BE 0 AT RUN TIME)
		1 * A = A
		A / 1 = A
		1 ** A  = 1
		A ** 1 = A
	IT ALSO TRANSFORMS MULTIPLICATION AND DIVISION BY A POWER
	OF 2 INTO THE OPERATION "P2MUL" (IE THE MULT/DIV NODE IN
	THE TREE IS CHANGED TO A "P2MUL" NODE); AND MULT BY
	A POWER OF 2 PLUS ONE TO A "P2PL1MUL"

	CALLED WITH THE ARGS
		CNODE - PTR TO THE NODE FOR THE ARITH OPERATION
		CNARGNODE - PTR TO THE CONSTANT ARG
		VARGNODE - PTR TO THE VARIABLE ARG
		ARG1CFLG - FLAG FOR "CONSTANT ARG IS THE 1ST ONE"
***************************************************************************)%
BEGIN
	EXTERNAL KDPINT;		!TO PERFORM IDINT FUNCTION
	EXTERNAL KADPRN;	!TO ROUND NUMBERS TO KA10 PRECISION
	LABEL P2OPTIM;
	EXTERNAL PROPNEG;
	OWN PEXPRNODE OLDCNODE;		!KEEP PTR TO THE ORIGINAL NODE WERE CALLED WITH


	MAP PEXPRNODE CNODE:CNARGNODE:VARGNODE;
	OWN NEGVARFLG;				!THIS FLAG IS SET IFF THE NEGFLG
						! FOR THE VARIABLE ARG IS SET IN CNODE
	OWN INTEGFLG;				!THIS FLAG IS SET IF THE VALTP1
						! FIELD OF THE CONSTANT IS "INTEG1"
	OWN KH,KL;				!THE CONSTANT STORED IN "CNARGNODE"
						! FOR KA10 DP AND REAL (WHICH ARE
						! UNROUNDED UNTIL FINAL OUTPUT
						! THESE 2 WDS CONTAIN THE ROUNDED FORM
	OWN ONEFLG:MONEFLG;			!THESE FLAGS ARE SET IFF THE CONSTANT ARG IS 1
						! OR -1 RESPECTIVELY

	BIND F1 =#201400000000;		!FLOATING POINT 1
	BIND F2=#202400000000;		!FLOATING POINT 2
	BIND F3=#202600000000;		!FLOATING POINT 3
	BIND F4=#203400000000;		!FLOATING POINT 4
	BIND FM1 =#576400000000;		!FLOATING POINT -1
	BIND F5 =#203500000000;			!FLOATING PT 5
	MACRO RLP2M =#400000000$;		!MASK FOR A (JUSTIFIED) REAL POWER OF 2
	MACRO MANTMSK=#000777777777$;		!MASK TO GET THE MANTISSA OF A FLOATING PT NUMBER




	%(***DEFINE MACROS AND ROUTINES TO TEST PROPERTIES OF CONSTANTS ***)%

	%(****TO TEST FOR A CONSTANT EQUAL TO 0***)%
	MACRO ZERCNST=
		.KH EQL 0 AND .KL EQL 0$;

	%(***TO COUNT THE # OF MULTIPLIES REQUIRED TO REACH
	    A SPECIFIED POWER***)%

	GLOBAL ROUTINE CNTMPY(POWER)=
	BEGIN
	LOCAL BASE NUMOP;
	NUMOP_0;
	IF .POWER NEQ 0 THEN
	WHILE .POWER NEQ 1 DO
	BEGIN
		NUMOP_.NUMOP+1+.POWER<0,1>;	!COUNT # OF MULTIPLIES
		POWER_.POWER^(-1)		!SHIFT OUT A POWER
	END;
	RETURN .NUMOP
	END;

	%(****TO TEST FOR A CONSTANT EQUAL TO 1***)%

	ROUTINE ONECNST = 
	BEGIN
		IF .INTEGFLG
		THEN 
		.KL EQL 1
		ELSE
		.KH EQL F1 AND .KL EQL 0
	END;
	
	%(***TO TEST FOR A CONSTANT EQUAL TO -1*****)%
	ROUTINE MONECNST=
	BEGIN
		IF .INTEGFLG
		THEN 
		.KL EQL -1
		ELSE
		.KH EQL FM1 AND .KL EQL 0
	END;



	%(****TO TEST FOR A CONSTANT WHICH IS EQUAL TO AN INTEGER (IE EITHER AN INTEGER OR
		A REAL WHICH IS EQUAL TO AN INTEGER*****)%
	ROUTINE INTEGC=
	BEGIN
		IF .INTEGFLG THEN 1 ELSE
		BEGIN
			LOCAL EXP;
			EXP_.KH<27,8>;		!LOAD EXPONENT
			IF .KH LSS 0 THEN EXP_.EXP XOR #377;	!MAKE POSITIVE
			EXP_.EXP - #200;	!CONVERT TO REAL EXPONENT
			IF .EXP LEQ 0 OR .EXP GTR 35 THEN 0 ELSE
			BEGIN
				MACHOP LSHC=#246;
				REGISTER CN[2];
				CN[0]_.KH;
				CN[1]_.KL^1;
				LSHC(CN,.EXP+9);
				.CN[0] EQL 0 AND .CN[1] EQL 0
			END
		END
	END;


	%(***TO TEST FOR A CONSTANT EQUAL TO A POWER OF 2 (OR MINUS A POWER OF 2)*********)%
	ROUTINE POWEROF2 =
	BEGIN
		IF .INTEGFLG
		THEN
		%(***FOR A POSITIVE INTEGER I - I IS A POWER OF 2 IFF IT HAS NO BITS IN
			COMMON WITH (I-1)****)%
		BEGIN
			REGISTER RT;
			RT_.KL;
			IF .RT LSS 0 THEN RT_-.RT;
			(.RT AND (.RT-1)) EQL 0
		END

		ELSE
		%(***FOR REAL, DOUBLE-PREC, AND COMPLEX - 1ST WD SHOULD
			HAVE MANTISSA=400000000  2ND WD SHOULD BE 0*******)%
		(.KH AND MANTMSK) EQL RLP2M AND .KL EQL 0
	END;

	%(****TO DETERMINE THE VALUE OF N FOR A CONSTANT KNOWN TO BE EQUAL TO 2**N *****)%
	ROUTINE P2VAL =
	BEGIN
		IF .INTEGFLG
		THEN
		35-FIRSTONE( ABS(.KL))
		ELSE
		ABS(.KH)^(-27) -128 - 1		!EXPONENT OF THE REAL NUMBER
								! MINUS 1
	END;


	%(*****TO TEST FOR A CONSTANT EQUAL TO A POWER OF 2 PLUS 1 (OR MINUS (A POWER OF 2 PLUS 1))***)%
	ROUTINE P2PLUS1=
	BEGIN
		IF .INTEGFLG
		THEN
		%(****FOR A POSITIVE INTEGER I - I-1 IS A POWER OF 2
			IFF I-1 HAS NO BITS IN COMMON WITH I-2****)%
		BEGIN
			REGISTER RT;
			RT_.KL;
			IF .RT LSS 0 THEN RT_-.RT;
			((.RT-1) AND (.RT-2)) EQL 0
		END

		ELSE
		%(****FOR A REAL,DOUBLE-PREC,OR COMPLEX********)%
		BEGIN
			REGISTER RT;
			IF .KL NEQ 0 
			THEN FALSE			!(IGNORE DOUBLE-PREC CASES
							! GREATER THAN 2**27)

			ELSE
			BEGIN
				RT_ABS(.KH) FSBR F1;		!FLOATING PT VAL FOR THIS
									! NUMBER MINUS 1
				 (.RT AND MANTMSK) EQL RLP2M
					AND (.RT GTR 0)
			END
		END
	END;

	%(***TO DETERMINE THE VALUE OF N FOR A CONSTANT KNOWN TO BE 2**N + 1 ******)%
	ROUTINE P2VL1 =
	BEGIN
		REGISTER RT;
		IF .INTEGFLG
		THEN
		35-FIRSTONE( ABS(.KL)- 1)
		ELSE
		BEGIN
			RT_ABS(.KH) FSBR F1;		!MUST SUBTRACT 1 BEFORE LOOK AT EXPONENT
						! IN ORDER TO CORRECTLY HANDLE 1.5,1.25,...
			(.RT)^(-27) - 128 - 1 	!EXPONENT MINUS 1
		END
	END;


	ROUTINE RETURNNEGV(CNODE,VARGNODE)=
	%(**************************************
		ROUTINE TO CAUSE CNODE TO BE REPLACED BY THE NEGATIVE OF
		VARGNODE (WHICH ONE WANTS TO DO FOR:
			(-1)*V
			(-V)**1
			V/(-1)
		FIRST TRIES TO PROPAGATE THE NEG DOWN OVER V. IF IT FAILS
		AT THAT, THEN IF A NEG CAN BE PROPAGATED BACK UP THE TREE
		DOES THAT.
	***************************************)%
	BEGIN
		MAP PEXPRNODE CNODE:VARGNODE;
		EXTERNAL PROPNEG,TAKNEGARG,MAKPR1;

		IF .VARGNODE[OPR1] EQL CONSTFL	!IF THE ARG IS A CONSTANT,
		THEN RETURN NEGCNST(VARGNODE)	! THEN CAN SIMPLY NEGATE IT

		ELSE
		IF PROPNEG(.VARGNODE)	!IF ARE SUCCESSFUL IN PROPAGATING THE NEG
		THEN RETURN .VARGNODE	! OVER THE VARIABLE ARG, CAN JUST RETURN
					! THE VARIABLE ARG
		ELSE
		IF .NOTFLG		!IF THERE IS A NOTFLG BEING PROPAGATED
		THEN RETURN .CNODE	!CANT PROPAGATE ANEG BACK UP

		ELSE
		IF TAKNEGARG(.CNODE[PARENT])	!IF PARENT OF CNODE CAN HAVE A
		THEN				! NEG PROPAGATED INTO IT
		BEGIN
			NEGFLG_NOT .NEGFLG;
			RETURN .VARGNODE
		END
		ELSE
		%(***OTHERWISE, INSERT A NEGATE NODE INTO THE TREE ABOVE VARGNODE***)%
		RETURN MAKPR1(.CNODE[PARENT],NEGNOT,NEGOP,.CNODE[VALTYPE],0,.VARGNODE)
	END;



	%(*********START OF ROUTINE********************************************)%


	OLDCNODE_.CNODE;


	%(***SET A FLAG INDICATING WHETHER THE CONSTANT IS INTEGER OR OCTAL/LOGICAL***)%
	INTEGFLG_(.CNARGNODE[VALTP1] EQL INTEG1);

	%(***SET THE VARIABLES KH AND KL TO THE 2 WDS OF THE CONSTANT WHOSE
		PROPERTIES ARE TO BE EXAMINED. IF ARE COMPILING  ON THE
		KA10, THEN DOUBLE-PREC AND REAL CONSTANTS ARE NOT ROUNDED
		UNTIL THE END OF COMPILATION. HENCE MUST ROUND THEM IN ORDER
		TO TEST THEIR PROPERTIES***)%
	IF .KA10FLG AND (.CNARGNODE[VALTYPE] EQL REAL OR .CNARGNODE[VALTYPE] EQL DOUBLPREC)
	THEN
	BEGIN
		C1H_.CNARGNODE[CONST1];
		C1L_.CNARGNODE[CONST2];
		COPRIX_KADPRN;
		CNSTCM();
		KH_.C2H;
		KL_.C2L;
	END
	ELSE
	BEGIN
		KH_.CNARGNODE[CONST1];
		KL_.CNARGNODE[CONST2];
	END;


	%(***SET THE FLAG NEGVARFLG IFF THE NEG FLAG IS SET FOR THE VARIABLE ARG***)%
	NEGVARFLG_ (IF .ARG1CFLG
			THEN .CNODE[A2NEGFLG]
			ELSE .CNODE[A1NEGFLG]);


	
	%(***IF CONSTANT ARG IS 0, COLLAPS