Google
 

Trailing-Edge - PDP-10 Archives - ap-c800d-sb - pmatch.mac
There are 7 other files named pmatch.mac in the archive. Click here to see a list.
; UPD ID= 1866 on 4/26/79 at 5:12 PM by W:<WRIGHT>

TITLE	PMATCH	- FOR COBOL VERSION 12
SUBTTL	PHASE O (OPTIMAZATION) PATTERN MATCHING MODULE



;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1977, 1979 BY DIGITAL EQUIPMENT CORPORATION

;AUTHOR: MICHAEL TIGHE (MFTT)

	TWOSEG
	RELOC	400000		;HI SEG PLEASE
	SEARCH	P,CHREQV
	SEARCH	OPCTAB		;OP CODE TABLE
	%%P==:%%P
	BIS==:BIS
	SALL

;*****************************************
;EDIT
;WHO	DATE		WHY
;---	----		----
;DAW	26-APR-79	[701] DON'T DO IMPROPER OPTIMIZATIONS -- FIX TO ROUTINE SAMACM
;DMN	16-MAR-79	[663] FIX SKIPA OPTIMIZATION IF PREV. INST. IS JRST .+3
;DMN	13-DEC-78	[616] FIX SUBI/ADDI OPTIMIZATION IN LINKAGE SECTION
;DMN	12-DEC-78	[614] DECREMENT TAG COUNT CORRECTLY FOR IF  D.P. TEST (THIS WAS IN .BWR FILE)
;DAW	 8-DEC-78	[607] FIX "?NPCIN BECAME NEGATIVE" WHEN DELETING CODE THAT CAN'T BE REACHED
;DAW	27-FEB-78	      MOVM OPTIMIZATION TO GET RID OF ASHC
;DAW	 1-SEP-77	      ADD TAG-RELATED OPTIMIZATIONS
;MFTT	23-AUG-77	      ORIGINAL VERSION OF PMATCH
;*****************************************


;	THIS MODULE CONTAINS THE MACRO DEFINITIONS AND ROUTINES
; TO EXAMINE THE INSTRUCTION POINTER TABLE (IPTAB) PUT TOGETHER
; BY THE MODULE COBOLO (PHASE O), AND TO EXAMINE AND MODIFY
; THE GENERATED CODE AS STORED IN THE INSTRUCTION BUFFER (INSTBF)
; WHICH IS MAINTAINED BY COBOLO.
;	THE TOP LEVEL ROUTINE (PMATCH) DISPATCHES ON THE OPCODE IF
; ANY PATTERNS EXIST THAT USE THAT OPCODE AS THE "KEY".


;**********************************
	ENTRY	PMATCH		;THE ROUTINE THAT DOES THE WORK.
;**********************************
;************** AC DEFINITIONS FOR THIS MODULE ********************
;USE DEFINITIONS IN P.MAC
	TA=TA
	TB=TB
	TC=TC
	TD=TD
	TE=TE
	PP=PP
;******************************

;EXTERNAL DECLARATIONS
EXTERN	DELINS		;THE ROUTINE IN COBOLO THAT REMOVES AN INSTRUCTION
			; FROM THE INSTBF
EXTERN	IPTAB		;THE INSTRUCTION POINTER TABLE.  IT CONTAINS
			; A CONDENSED DESCRIPTION OF THE INSTRUCTION
EXTERN	DRFTAG		;DE-REFERENCE A TAG. DECREMENTS THE TAG REFERENCE COUNT
			; AND SKIP RETURN IF IT REACHED ZERO
EXTERN	ADDWD		;GET ANOTHER INSTBF WORD FOR AN INSTRUCTION
			; (TO ADD AN INCREMENT)
EXTERN	COLLE1		;GARBAGE COLLECT ROUTINE, TO PUT ALL INSTRUCTIONS
			; IN INSTBF  (USED TO MOVE INSTRUCTION INFO FROM
			;OTEMP TO INSTBF, SO LATER OPTIMIZATIONS CAN USE
			;OTEMP).

EXTERN	AS.CNB,AS.DAT,AS.MSC,AS.PRO,AS.TAG,AS.DOT,AS.MS2

;FLAGS WE CAN USE IN RH OF "SW"
;NOTE: CAN USE 1000-400000
FTPAR==	400000		;JRST TARGET IS A PARAGRAPH
FDELI== 200000		; FLAG FOR REMEMBERING WE DELETED AN INSTRUCTION
SUBTTL DESCRIPTION OF HOW TO BUILD AN OPTIMIZATION ENTRY

;	IN THE MODULE CALLED OPCTAB.MAC THERE IS A LIST OF ALL
; THE OP CODES RECOGNIZED BY THE COBOL COMPILER.  EACH OP CODE IS
; FOLLOWED BY A LIST OF PROPERTIES.  ONE OF THESE IS THE NAME OF
; THE "OPTIMIZATION PATTERN RECOGNIZER" (OPPARE).   IF THIS FIELD IS
; BLANK, THERE ARE NO INTENDED OPTIMIZATIONS THAT ARE KEYED BY THIS
; OP CODE.  IF THIS FIELD IS NOT BLANK, IT CONTAINS THE ADDRESS OF
; THE OPPARE.  ALL OPPARES WILL BE CONTAINED IN THIS MODULE.
; THE MACRO CONTAINING THE TABLE IN OPCTAB.MAC WILL BE INVOKED
; IN THIS MODULE TO GIVE A TABLE CONTAINING THE OPPARES FOR 
; EACH OP CODE.  THE OPCTAB.MAC FILE IS COMMON TO CMNGEN AND PHASEG.
; EACH OPPARE WILL RESEMBLE A TABLE ENTRY, BUT WILL CONSIST OF
; MACROS THAT EXPAND TO CODE, SO THAT EACH OPPARE IS ACTUALLY
; A SUBROUTINE.  (IT RETURNS WITH POPJ.)  THE MACROS ARE DEFINED
; IN THIS MODULE.  FOLLOWING IS A DESCRIPTION OF AN OPPARE.


;	AN OPPARE CONSISTS OF A HEADER, AND A TRAILER, WITH
; PATTERN DESCRIPTORS IN BETWEEN.  EACH OPPARE CONTAINS A
; NEXT POINTER TO THE NEXT POSSIBLE PATTERN FOR THIS OP CODE,
; ASSUMING THIS PATTERN DOES NOT MATCH THE CODE WE ARE LOOKING
; AT.  THE HEADER CONSISTS OF THE WORD "PATTERN" FOLLOWED BY THE
; NAME OF THE PATTERN.  THIS NAME IS THE ONE USED IN THE OPCTAB.
; FOLLOWING THE NAME (ON THE SAME LINE) SHOULD BE THE NEXT
; POINTER.  THIS SHOULD BE THE NAME OF AN OPPARE OR NULL.
; A NULL NEXT POINTER MEANS NO MORE PATTERNS TO CHECK FOR.
;	THE NEXT ENTRY IN THE OPPARE IS AN OPTIONAL KEYWORD
; (NEW LINE) THAT STATES WHETHER OR NOT THE PREVIOUS INSTRUCTIONS
; MAY OR MAY NOT SKIP.  THE KEYWORD IS "NOPSKP" AND STANDS
; FOR "NO PREVIOUS SKIP".  THE PRESENCE OF THE KEYWORD 
; CAUSES THE PATTERN TO BE CHECKED TO BE SURE THAT NO PREVIOUS
; CODE CAN SKIP INTO THE MIDDLE OF THIS CODE.  IT IS NORMALLY
; USED TO ASSURE THAT THE MULTI-INSTRUCTION PATTERN YOU ARE
; LOOKING AT IS A CONTIGUOUS BLOCK, AND CAN BE OPTIMIZED WITHOUT
; SIDE-EFFECTS.
;	AFTER THE (OPTIONAL) "NOPSKP" COMES ENTRIES (ONE PER LINE)
; OF THE FORM "TEST" FOLLOWED BY THE INSTRUCTION LOCATION RELATIVE TO IPI
; AND THE INSTRUCTION TO TEST FOR.
; THE NUMBER OF THESE IS LIMITED ONLY BY THE SIZE OF
; THE IPTAB.  IT IS POSSIBLE TO OMIT ANY "TEST" ENTRIES IF THE
; PATTERN TO BE OPTIMIZED IS ONLY ONE INSTRUCTION, OR TOO OBSCURE
; TO BE TRUSTED TO OP-CODE MATCHING.
;	IF THE OPCODE IS ALLOWED TO BE ONE OF A NUMBER OF OPCODES
; (NOT MERELY ONE) USE THE "TESTN" MACRO FOLLOWED BY THE
; INDEX OF THE INSTRUCTION RELATIVE TO IPI, THEN THE LIST OF
; CHOICES (ENCLOSED IN ANGLE BBRACKETS).  THIS NUMBER IS NOT LIMITED.
;	AFTER THE "TEST" COMES ANY NUMBER OF "TESTMR" (TEST MORE)
; ENTRIES (ONE PER LINE).  THESE ARE FOLLOWED BY A ROUTINE NAME
; AND AN ARGUMENT TO THE ROUTINE.
; THE "TESTMR" ENTRY HAS THE EFFECT OF CALLING THE NAMED ROUTINE.
; THE ARGUMENT WILL BE MOVEI'D INTO "TA" BEFORE THE ROUTINE IS CALLED.
; THIS FUNCTIONALITY IS EXPLICITLY FOR CHECKING PARTS OF THE PATTERN
; NOT POSSIBLE THROUGH JUST THE "NOPSKP" AND "TEST" OPERATORS.
; THE NAMED ROUTINE IS EXPECTED TO MODIFY NOTHING, BUT TO ONLY
; CHECK FURTHER ELEMENTS OF THE PATTERN TO SEE IF IT PASSES THE
; PREREQUISITES FOR OPTIMIZATION.  THE ROUTINE MUST SKIP RETURN
; IF THE PATTERN MATCHES, AND NON-SKIP RETURN IF NO MATCH.
;	TO END THE PATTERN, THE LAST ENTRY MUST BE "DOIT"
; FOLLOWED (ONE LINE ENTRY) BY THE NAME OF A ROUTINE.  THAT ROUTINE
; GETS CALLED TO ACTUALLY MODIFY THE CODE IN THE INSTBF AND IPTAB
; TO DO THE OPTIMIZATION.  THAT ROUTINE MUST EXIT BY A POPJ.
;
;
; EXAMPLE: THE FOLLOWING IS A PATTERN RECOGNITION BLOCK FOR
; FINDING A SKIP INSTRUCTION FOLLOWED BY TWO JRSTS OR JUMPAS,
; THE FIRST OF WHICH ONLY JUMPS OVER THE SECOND.  NOTE THAT
; YOU GET HERE BECAUSE THE ENTRY IN THE OPCTAB FOR THAT
; SKIP INSTRUCTION SPECIFIED THIS OPPARE.  THE NEXT PATTERN
; TO BE LOOKED AT IF THIS ONE FAILS IS "NEXT1", AND THE NAME
; OF THE PATTERN IS "TWOJRST".
;
;		PATTERN TWOJRST, NEXT1
;		NOPSKP				;IF PREVIOUS SKIP CANT OPTIMIZE
;		TESTN	1,<JRST.,JUMPA.>
;		TESTN	2,<JRST.,JUMPA.>
;		TEST	3,TAG.			;MUST BE TAG FOR 1ST JRST
;		TESTMR	ISITTAG,1		;IS IT TAG FOR 1ST JRST
;		DOIT	REMOVEJRST		;GOTO ROUTINE TO TAKE OUT JRST
;
;	THE ISITTAG ROUTINE CRAWLS AROUND IN THE INSTBF FOR THE POINTERS
; ASSOCIATED WITH THIS PATTERN LOOKING TO BE SURE THAT THE FIRST JRST
; IS TO THE TAG AFTER THE SECOND JRST.  IF IT RETURNS SUCCESSFULLY,
; THE OPTIMIZER CAUSES THE REMOVEJRST ROUTINE TO BE CALLED TO TAKE AWAY
; THE SECOND JRST (OR ANY OTHER OPTIMIZATION).
;DEFINE THE MACROS FOR OPCTAB EXPANSION
DEFINE	%OPCT% (NAME,INTVAL,INTNAM,OPCODE,F1,F2,F3,F4,F5,SKPBIT,OPPARE,L,M,N),<
	XWD	SKPBIT,OPPARE		;THE TABLE ENTRIES
	INTNAM==INTVAL			;DEFINE INTERNAL CODES
	>
DEFINE	%OPCU% (NAME,INTVAL,INTNAM,OPCODE,F1,F2,F3,F4,F5,SKPBIT,OPPARE,L,M,N),<
	INTNAM==INTVAL			;DEFINE INTERNAL CODES
	>

	;NOW EXPAND THE TABLE. DO SO IN A MANNER TO
	; ALLOW DIRECT INDEXING INTO THE TABLE FROM
	; VARIOUS ROUTINES.
	INTERN	OPPART
	OPCTAB	OPPART			;THE NAME OF THE TABLE
	BLOCK	40			;OLD UN-USED UUO'S ARE BLANKED
	;REDEFINE THE MACROS BEFORE THE SECOND TABLE TO GET
	; THE LARGER NUMBERS FOR THE TESTING
DEFINE	%OPCT% (NAME,INTVAL,INTNAM,OPCODE,F1,F2,F3,F4,F5,SKPBIT,OPPARE,L,M,N),<
	XWD	SKPBIT,OPPARE		;THE TABLE ENTRIES
	INTNAM==INTVAL+200		;DEFINE INTERNAL CODES
	>
DEFINE	%OPCU% (NAME,INTVAL,INTNAM,OPCODE,F1,F2,F3,F4,F5,SKPBIT,OPPARE,L,M,N),<
	INTNAM==INTVAL+200		;DEFINE INTERNAL CODES
	>
	OPCTB2;				;NO TABLE NAME FOR THE SECOND TABLE
SUBTTL	MACRO DEFINITIONS FOR BUILDING THINGS IN THIS MODULE


;THE HEADER MACRO - DECLARING A PATTERN (AND ITS BROTHER)
DEFINE PATTERN (A,B),<
	IFB  <B>,<DEFINE %%GOTO,<POPJ PP,>	;IF NO NEXT, CAUSE RETURN
		DEFINE %GO2AD,<CPOPJ>>
	IFNB <B>,<DEFINE %%GOTO,<JRST B>	;IF NEXT, DEFINE IT
		DEFINE	%GO2AD,<B>>
	IFNB <A>,<
	A:>					;DECLARE PATTERN ADDRESS
>

;NOW DEFINE THE MACRO THAT CAUSES A CHECK FOR PREVIOUS
; SKIP INSTRUCTIONS
DEFINE NOPSKP,<
	PUSHJ	PP,	SKPTST		;CALL PRE-DEFINED ROUTINE
	%%GOTO				;IF SKIP, GO TO NEXT CASE
>		;END OF NOPSKP MACRO

;MACRO TO PRINTX WARNING IF THEIDX IS OUTSIDE OF LIMITS
DEFINE TSTLIM (THEIDX),<
IFL THEIDX,<
	.XXXX== -THEIDX
	IFL NBACK-.XXXX,<
 PRINTX ?A PATTERN LOOKS TOO FAR BACK!
	>
>
 IFG THEIDX,<
	IFL NFRONT-THEIDX, <
PRINTX ?A PATTERN LOOKS TOO FAR FORWARD!
	>
>
>;END TSTLIM MACRO
.XCREF .XXXX	;DON'T CROSS-REFERENCE THIS SYMBOL

;THE TEST MACRO.
DEFINE TEST (THEIDX,THEOPC),<
	TSTLIM	(THEIDX)		;MAKE SURE IT'S WITHIN THE LIMITS
	SKIPG	TA,	THEIDX(IPI)	;GET IPTAB ENT AND TEST IT
	%%GOTO				;NO MATCH; NOT THERE, OR DONT TOUCH
	LDB	TA,	[IP$OP TA]	;GET ACTUAL OP CODE
IFN THEOPC,<
	CAIE	TA,	THEOPC		;COMPARE AGAINST THE DESIRED
	%%GOTO				;NOT IT, GO HOME
>
IFE THEOPC,<
	JUMPN	TA,	%GO2AD
>
>		;END OF TEST MACRO


;THE TESTN MACRO.
DEFINE TESTN (THEIDX,THEOPS),<
	TSTLIM	(THEIDX)		;MAKE SURE IT'S WITHIN THE LIMITS
	SKIPG	TA,	THEIDX(IPI)	;GET IPTAB ENT AND TEST IT
	%%GOTO				;NO MATCH; NOT THERE, OR DONT TOUCH
	LDB	TA,	[IP$OP TA]	;GET ACTUAL OP CODE
	IRP(THEOPS),<
	CAIN	TA,	THEOPS		;CHECK AGAINST OPCODE
	CAIA				;IT IS THE OPCODE
	>		;END OF IRP
	%%GOTO				;NO MATCH
>		;END OF TESTN MACRO

;TEST2 IS A SPECIAL (BUT COMMON) CASE OF TESTN
DEFINE TEST2 (THEIDX,THEOP1,THEOP2),<
	TSTLIM	(THEIDX)		;MAKE SURE IT'S WITHIN THE LIMITS
	SKIPG	TA,	THEIDX(IPI)	;GET IPTAB ENT AND TEST IT
	%%GOTO				;NO MATCH; NOT THERE, OR DONT TOUCH
	LDB	TA,	[IP$OP TA]	;GET ACTUAL OP CODE
IFN THEOP1,<
	CAIE	TA,	THEOP1		;CHECK AGAINST OPCODE
	CAIN	TA,	THEOP2
	CAIA				;IT IS THE OPCODE
	%%GOTO				;NO MATCH
>
IFE THEOP1,<
	CAIE	TA,	THEOP2
	JUMPN	TA,	%GO2AD
>
>		;END OF TEST2 MACRO

;THE ISIZE MACRO.  CHECKS THAT THE INSTRUCTION AT THE INDEX
; TAKES ONLY ONE OR TWO WORDS IN THE INSTBF.  NECESSARY
; TO HELP SPOT EASIER PATTERN TO SOLVE.  TAKES INDEX OF INSTR
; FOLLOWED BY THE NUMBER OF WORDS IN INSTBF IT MUST BE.
; IF THAT NUMBER IS OTHER THAN ONE OR TWO, THE TEST WILL FAIL.
DEFINE	ISIZE (THEIDX,THESIZ),<
	TSTLIM	(THEIDX)			;WITHIN THE BUFFER LIMITS?
	LDB	TA,	[IP$WC <THEIDX(IPI)>]	;GET NUMBER OF WORDS IN INSTBF
IFN THESIZ-1,<
	CAIE	TA,	THESIZ			;COMPARE WITH DESIRED SIZE
	%%GOTO					;NOT RIGHT AMOUNT
>
IFE THESIZ-1,<
	SOJN	TA,	%GO2AD
>
>	;END OF ISIZE MACRO


;THE TESTMR (TEST MORE) MACRO.  CALLS A ROUTINE TO FURTHER INSPECT THE
; CODE PICTURE TO SEE IF OPTIMIZATIONS ARE POSSIBLE.  EXPECTS THE
; CALLED ROUTINE TO SKIP RETURN IF PATTERN STILL MATCHING.
;TAKES ONE ARGUMENT IN TA, SPECIFIED AFTER THE ROUTINE NAME WHEN
; THE MACRO IS USED.  THAT ARGUMENT IS AN INDEX INTO THE IPTAB.
DEFINE TESTMR (RUTINE,THEARG),<
	IFNB	<THEARG>,<
	TSTLIM	(THEARG)
	MOVEI	TA,	THEARG		;SET UP ARGUMENT IN TA
			>
	PUSHJ	PP,	RUTINE		;CALL THE ROUTINE WITH NO ADO.
	%%GOTO				;IF NO MATCH, THEN NO MATCH
>		;END OF TESTMR MACRO


;THE DOIT MACRO.  IT CAUSES CONTROL TO BE GIVEN TO THE ROUTINE
; THAT WILL PLAY WITH THE INSTBF TO GENERATE BETTER CODE.
; ONLY GETS EXECUTED WHEN THE PATTERN IS SUCCESSFULLY MATCHED.
DEFINE DOIT (RUTINE),<
	AOS		(PP)		;SUCCESSFUL MATCH, INCR RET ADR
 IFNB <RUTINE>,<
	PJRST		RUTINE		;TRANSFER TO FIX-UP ROUTINE
>>
SUBTTL	PMATCH - THE CONTROL ROUTINE FOR DOING THE WORK

PMATCH:
	;ALL THIS ROUTINE HAS TO DO IS LOOK AT THE CONTENTS
	; OF THE TABLE ENTRY POINTED AT BY IPI AND DISPATCH
	; TO THE APPROPRIATE ROUTINE WHO'S ADDRESS IS CONTAINED
	; IN OPPART.
	SKIPG	TA,	(IPI)		;SEE IF WE CAN TOUCH, LOAD AC
	POPJ	PP,			;NO CAN TOUCH, OR NOTHING THERE
	LDB	TA,	[IP$OP TA]	;GET HANDLE ON OP CODE BITS
	CAILE	TA,	XTND.		;MAKE SURE ITS A LEGAL ENTRY NUMBER
	 JRST		PMACH1		;OP CODE GREATER THAN LARGEST POSSIBLE
	HRRZ	TA,	OPPART(TA)	;GET TABLE ENTRY
	JUMPN	TA,	(TA)		;GO TO CHECKING CODE
	POPJ	PP,			;NO ENTRY, GO BACK TO CALLER
;HERE TO HANDLE OPTIMIZATIONS BASED ON THINGS OTHER THAN OP CODES

PMACH1:
IFN BIS,<
	CAIN	TA,%CNVD.		;"PUSHJ PP,CVTDB."?
	 JRST	CVTPAT			;YES
>;END IFN BIS
	CAIE	TA,%TAG.		;IS THIS A TAG?
	 POPJ	PP,			;NO

;DELETE TAG IF REF COUNT = 0
	HRRZ	TA,(IPI)	;GET INSTBF ADDR OF TAG
	HRRZ	TA,(TA)		;GET TAG FROM INSTBF
	ANDI	TA,77777	;GET TAG COUNT
	ADD	TA,TAGLOC##	;GET ADDRESS OF TAG IN TAGTAB
	LDB	TA,[POINT 15,(TA),17]	;GET THE REFERENCE COUNT OF THE TAG
	JUMPN	TA,PMACH2	;IF NON-ZERO FORGET IT
	MOVE	TA,IPI		;ALRIGHT! POINT TO IT
	AOS	(PP)
	PJRST	DELINS		;GO DELETE IT

;LOOK  FOR TAG: FOLLOWED BY "JRST", AND "TAG1:" FOLLOWED BY "TAG2:"

PMACH2:	MOVEI	TB,1(IPI)	;NEXT GUY
	LDB	TB,[IP$OP <(TB)>]
	CAIN	TB,%PROC.	;TAG:, PARA:?
	 JRST	TAGPRC		;YES
	CAIN	TB,%TAG.	;TAG1:, TAG2:?
	 JRST	TAGTAG		;YES
	CAIE	TB,JRST.	; NO-- TAG:, "JRST"?
	 POPJ	PP,		;NO, RETURN

;TAG FOLLOWED BY JRST. CHANGE TAGTAB ENTRY TO SAY THAT ALL
;REFERENCES TO TAG REALLY MEAN THE TARGET OF THE JRST.

	MOVE	TE,1(IPI)	;LOOK AT "JRST" ENTRY
	LDB	TC,[IP$WC TE]	;MAKE SURE THERE IS NO INCREMENT ON THE JRST
	SOJN	TC,CPOPJ	;THERE IS, FORGET IT
	HRRZ	TC,(TE)		;GET TC= TARGET OF "JRST"
	TRZ	TC,77777	;JUST SAVE ADDRESS TYPE
	CAIE	TC,AS.TAG	;IT MAY GO TO A TAG
	CAIN	TC,AS.PRO	;OR A PARAGRAPH
	 CAIA
	POPJ	PP,		;OTHERWISE FORGET IT
	CAIN	TC,AS.PRO	;IS IT A PARA?
	SWONS	FTPAR		;YES--SET FLAG
	SWOFF	FTPAR		;NO--CLEAR FLAG
	HRRZ	TC,(TE)		;OK, GET TARGET INTO TC
	MOVE	TD,(IPI)	;TD= TAG'S IPTAB ENTRY
	MOVE	TD,(TD)		;GET INSTBF WORD
	ANDI	TD,77777	;TD:= THIS TAG NUMBER

	ADD	TD,TAGLOC	;TD POINTS TO TAGTAB ENTRY FOR IT
	MOVE	TB,(TD)		;GET ENTRY
	TLO	TB,(1B0)	;MAKE INDIRECT
	HRR	TB,TC		;PUT TARGET OF "JRST" IN INDIRECT PLACE
	LDB	TE,[POINT 15,TB,17] ;GET REF COUNT
	TSWF	FTPAR		;SKIP IF NOT A PARAGRAPH
	 JRST	GOTRE		; JUMP
GOTTR1:	ANDI	TC,77777
	ADD	TC,TAGLOC##	;GET TARGET'S TAGLOC
	MOVE	DT,(TC)
	TLNN	DT,(1B0)
	 JRST	GOTTR2		;GOT TD= FINAL ENTRY
	TRC	DT,AS.PRO
	TRNE	DT,700000	;SKIP IF NOT A PARA
	 JRST	GOTRE
	HRRZ	TC,DT		;GET TAG
	JRST	GOTTR1		;BACK INCASE MORE INDIRECTING

GOTTR2:	LDB	DT,[POINT 15,DT,17] ;GET POINTER TAG'S REF COUNT
	ADD	DT,TE		;ADD OLD REF COUNT TO IT
	DPB	DT,[POINT 15,(TC),17] ;STORE NEW REF COUNT IN OTHER ENTRY

GOTRE:	SETZ	DT,
	DPB	DT,[POINT 15,TB,17] ; ZERO OUT THIS TAG'S REF COUNT
				;SO COBOLG WON'T PRINT IT
	MOVEM	TB,(TD)		;STORE NEW ENTRY FOR THIS TAG
	MOVE	TA,IPI		;NOW DELETE THE TAG
	AOS	(PP)		;REMEMBER WE DID SOMETHING USEFUL
	PUSHJ	PP,DELINS	;DELETE THE TAG

;NOW TEST FOR SPECIAL GO DEPENDING CASE OF

;	XJRST	ADDRESS-1
;	XJRST	ADDRESS-2
;	JRST	THIS-ADDRESS
;	<MORE CODE>

;WE CAN DELETE  <JRST THIS-ADDRESS> PLUS ALL FOLLOWING CODE UP TO
;THE NEXT LABEL

	MOVE	TA,-1(IPI)	;LOOK BACK 1
	MOVE	TB,-2(IPI)	;LOOK BACK 2
	LDB	TC,[IP$OP TA]
	LDB	TE,[IP$OP TB]
	CAIN	TC,XJRST.	;LOOK FOR XJRST'S
	CAIE	TE,XJRST.
	POPJ	PP,		;NO, JUST GIVE UP
	SOJA	IPI,JRSTXC	;POINT TO XJRST AND DELETE THE REST
SUBTTL	TAG FOLLOWED BY TAG OPTIMIZATION

;HERE IF TAG FOLLOWED BY TAG. DELETE THE 2ND TAG, CHANGE THE TAGTAB
;ENTRY TO POINT TO 1ST TAG, AND ADD 2ND TAG'S REF COUNT TO 1ST'S

TAGTAG:	AOS	(PP)		;REMEMBER WE DID SOMETHING
	MOVE	TB,(IPI)	;TB:= 1ST TAG'S IPTAB ENTRY
	MOVE	TA,1(IPI)
	MOVE	TC,(TA)		;TC:= 2ND TAG
	MOVEI	TA,1(IPI)	;DELETE 2ND TAG
	PUSH	PP,TC
	PUSHJ	PP,DELINS
	POP	PP,TC
	ANDI	TC,77777	;TC= 2ND TAG NUMBER
	ADD	TC,TAGLOC##	;POINT TO TAGTAB ENTRY FOR IT
	MOVE	TB,(TC)		;GET THE WORD
	LDB	TE,[POINT 15,TB,17] ;GET 2ND TAG REF COUNT
	HRLI	TB,(1B0)	;MARK IT AS HAVING SAME VALUE AS TAG IN RH
				; AND SET REF COUNT TO 0
	MOVE	TD,(IPI)	;GET 1ST TAG'S IPTAB ENTRY AGAIN
	HRRZ	TD,(TD)		;WHAT IS IT'S TAG NUMBER?
	ANDI	TD,77777
	HRR	TB,TD		;PUT IN RH OF TAGTAB ENTRY
	MOVEM	TB,(TC)
	ADD	TD,TAGLOC##	;POINT TO 1ST TAG'S TAGTAB ENTRY
	LDB	TB,[POINT 15,(TD),17] ;GET 1ST TAG'S REF COUNT
	ADD	TB,TE		;ADD 2ND'S
	DPB	TB,[POINT 15,(TD),17] ;STORE BACK IN 1ST'S ENTRY
	POPJ	PP,		;AND RETURN
SUBTTL	TAG FOLLOWED BY PROC OPTIMIZATION

;HERE IF WE HAVE
;	%TAG:
;	PARA-NAME:
;
; MAKE THE TAG POINT TO THE PARA-NAME
;
TAGPRC:	AOS	(PP)
	MOVE	TB,(IPI)	;GET TAG'S IPTAB ENTRY
	MOVE	TC,(TB)		;TC= THE TAG
	ANDI	TC,77777	; NUMBER
	ADD	TC,TAGLOC##
	MOVSI	TB,(1B0)	;MARK IT AS INDIRECT, AND SET REF COUNT TO 0
	HLLM	TB,(TC)
	MOVE	TB,1(IPI)	;POINT TO PARA-NAME
	HRRZ	TB,(TB)
	HRRM	TB,(TC)		;STORE AS POINTER IN TAGTAB ENTRY
	MOVEI	TA,(IPI)	;POINT TO THE TAG
	PJRST	DELINS		;AND GO DELETE IT
SUBTTL	AFTER "PUSHJ PP,CVTDB"

IFN BIS,<
; SINCE CVTDB RETURNS VALUES IN AC 7 & 10, THE RESULTS ARE USUALLY MOVED
; TO OTHER ACS AND MOVED TO MEMORY.
; RECOGNIZE THESE PATTERNS, AND GET RID OF THE EXTRA AC USAGE

CVTPAT:	MOVE	TB,1(IPI)	;NEXT INSTRUCTION IPTAB ENTRY
	LDB	TC,[IP$OP TB]	;OPCODE
	CAIN	TC,MOV		;MOVE?
	JRST	CVTMOV		;YES
	CAIE	TC,DMOVE.	;DMOVE?
	POPJ	PP,		;NO, FORGET IT
	MOVE	TC,(TB)		;OK, GET REAL INSTRUCTION
	HRRZ	TD,TC		;GET ADDRESS
	CAIE	TD,7		;AC7?
	POPJ	PP,		;NO
	LDB	TD,[IP$AC TB]	;GET AC OF INSTRUCTION


;IF THE AC IS USED AFTER THIS, SUBSTITUTE AC 7

	MOVE	TB,2(IPI)
	MOVEI	TE,7		;GET TE= 7 (TO DEPOSIT AC)
	LDB	TC,[IP$OP TB]
	CAIN	TC,DMOVE.
	JRST	CVPAT6		;PATTERN 6
	CAIE	TC,DADD.
	CAIN	TC,DSUB.
	JRST	CVPAT8		;PATTERN 8
	CAIN	TC,SETZ.
	JRST	CVPAT9		;PATTERN 9
	POPJ	PP,		;THAT'S ALL WE KNOW

CVTMOV:	MOVE	TC,(TB)		;OK, GET REAL INSTRUCTION
	HRRZ	TD,TC		;GET ADDRESS
	CAIE	TD,10		;AC10?
	 POPJ	PP,		;NO
	LDB	TD,[IP$AC TB]	;GET AC OF INSTRUCTION

;IF THE AC IS USED AFTER THIS, SUBSTITUTE AC 10

	MOVE	TB,2(IPI)
	MOVEI	TE,10		;GET TE= 10 (TO DEPOSIT AC)
	LDB	TC,[IP$OP TB]
	CAIN	TC,SETZ.
	 JRST	CVPAT1		;PATTERN 1
	CAIN	TC,MOVEM.
	 JRST	CVPAT2		;PATTERN 2
	CAIE	TC,SUBI.
	CAIN	TC,ADDI.
	 JRST	CVPAT3
	CAIE	TC,AD
	CAIN	TC,SUB.
	 JRST	CVPAT4		;PATTERN 4
	CAIN	TC,ADDM.
	 JRST	CVPAT5		;PATTERN 5
	CAIN	TC,IMUL.
	JRST	CVPAT7		;PATTERN 7
	POPJ	PP,		;THAT'S ALL WE KNOW

;PATTERN 1
;	MOVE	AC,10
;	SETZ	4,
;	MOVM	5,AC

CVPAT1:	MOVE	TB,3(IPI)
	LDB	TC,[IP$OP TB]
	CAIE	TC,MOVM.
	  POPJ	PP,		;NOPE
	HRRZ	TC,(TB)
	CAIE	TC,(TD)		;IS AC THE SAME?
	 POPJ	PP,		;NO!
	AOS	(PP)		;YES-- FIXUP
	HRRM	TE,(TB)		;MAKE IT "MOVM 5,10"
	MOVEI	TA,1(IPI)
	PJRST	DELINS		;DELETE THE "MOVE AC,10"


;PATTERN 2
;	MOVE	AC,10
;	MOVEM	AC,ADDR
;
; NOTE: CARE MUST BE TAKEN HERE. "SET A B UP BY C" (AMONG OTHER THINGS)
; MAY EXPECT AC0 TO CONTAIN THE RESULT, SO IF 0 IS USED,
; DON'T DO THE OPTIMIZATION UNLESS NEXT THING IS NEW PARA.

CVPAT2:	MOVE	TB,2(IPI)	;MAKE SURE AC IS THE SAME
	LDB	TC,[IP$AC TB]
	CAIE	TC,(TD)
	  POPJ	PP,		;NO
	LDB	TC,[IP$OP <3(IPI)>] ;GET NEXT OPCODE
	CAIN	TC,%PROC.	;IF NEW PARAGRAPH, WE KNOW IT'S OK
	 JRST	CVPT2A
	CAIE	TD,4		;ELSE ONLY ALLOW IT FOR AC 4
	 POPJ	PP,
CVPT2A:	AOS	(PP)		;OK!
	DPB	TE,[IP$AC <2(IPI)>] ;STORE NEW IPTAB ENTRY
	DPB	TE,[POINT 4,(TB),12] ;STORE IN AC FIELD ALSO
	MOVEI	TA,1(IPI)	;DELETE THE "MOVE"
	PUSHJ	PP,DELINS
				;...
;WE CAN NOW CHECK FOR FURTHER OPTIMIZATIONS
;EITHER COMMON SUBSCRIPTING
;OR
;	MOVEM	10,ADDR
;	MOVE	AC,ADDR
;	SUBI	AC,1
;REPLACE WITH
;	MOVEM	10,ADDR
;	SOS	AC,10

	PATTERN	,CVPCSS		;CHECK FOR POSSIBLE COMMON SUBSCRIPT CODE
	TEST	3,SUBI.		;TEST FOR SUBI
	MOVE	TA,2(IPI)	;POINT TO MOVE
	MOVE	TB,3(IPI)	;POINT TO SUBI
	LDB	TC,[IP$OP TA]	;GET OPCODE
	HRRZ	TE,(TB)		;GET CONST.
	CAIN	TC,MOV		;BETTER BE MOVE
	CAIE	TE,1		;AND SUBI AC,1
	%%GOTO			;NOT
	LDB	TC,[IP$AC TA]
	LDB	TE,[IP$AC TB]
	CAIE	TC,(TE)		;ACC THE SAME
	%%GOTO			;NO
	JUMPE	TC,%GO2AD	;YES, BUT ZERO NOT ALLOWED
	MOVE	TB,1(IPI)	;POINT TO MOVEM 10,ADDR
	HRRZ	TC,(TA)
	HRRZ	TE,(TB)
	CAIE	TC,(TE)		;ADDR THE SAME
	%%GOTO			;NO
	LDB	TE,[IP$WC TA]	;GET NO. OF WORDS
	MOVE	TC,1(TA)	;INCASE 2
	CAME	TC,1(TB)	;MATCH?
	SOJN	TE,%GO2AD	;NO, AND 2 WORDS REQUIRED

	MOVEI	TC,SOS.		;OK, CHANGE TO SOS AC,10
	MOVEI	TE,10
	DPB	TC,[IP$OP <2(IPI)>]	;CHANGE OPCODE
	DPB	TC,[POINT  8,(TA),8]	;AND CLEAR THE ASINC BIT
	HRRM	TE,(TA)		;CHANGE ADDRESS
	MOVEI	TE,1
	DPB	TE,[IP$WC <2(IPI)>]	;MAKE SURE ONLY ONE WORD
	MOVEI	TA,3(IPI)
	JRST	DELINS		;DELETE SUBI
;PATTERN 3
;	MOVE	AC,10
;	ADDI	AC,N
;	MOVEM	AC,ADDR

CVPAT3:	MOVE	TB,2(IPI)	;GET "ADDI" ENTRY
	LDB	TC,[IP$AC TB]
	CAIE	TC,(TD)		;SAME AC?
	  POPJ	PP,		;NO
	CAIE	TD,4		;ONLY AC 4 IS SAFE FOR THIS
	  POPJ	PP,		; (SEE NC202- "ADD A B TO C D ROUNDED")
	MOVE	TB,3(IPI)	;MAKE SURE WE GOT A MOVEM
	LDB	TC,[IP$OP TB]
	CAIE	TC,MOVEM.
	  POPJ	PP,		;NO
	LDB	TC,[IP$AC TB]
	CAIE	TC,(TD)		;SAME AC FOR MOVEM?
	  POPJ	PP,		;NO
	AOS	(PP)		;OK!
	DPB	TE,[IP$AC TB]	;STORE AC 10 FOR MOVEM
	DPB	TE,[POINT 4,(TB),12] ; IN REAL INSTRUCTION ALSO
	MOVE	TB,2(IPI)	;AND FOR THE ADDI/SUBI
	DPB	TE,[IP$AC TB]
	DPB	TE,[POINT 4,(TB),12]
	MOVEI	TA,1(IPI)
	PJRST	DELINS		;DELETE THE "MOVE"
;PATTERN 4
;	MOVE	AC,10
;	ADD	AC1,AC

CVPAT4:	MOVE	TB,2(IPI)
	HRRZ	TC,(TB)
	CAIE	TC,(TD)		;IS ADR OF "ADD" THE AC?
	 POPJ	PP,		;NO
	LDB	TA,[IP$AC TB]
	CAIN	TA,(TD)		;MAKE SURE "AC1" NOT EQUAL "AC"
	 POPJ	PP,
	AOS	(PP)		;SUCCESS!
	HRRM	TE,(TB)		;STORE AC10 AS ADDRESS OF THE "ADD"
	MOVEI	TA,1(IPI)	;AND DELETE THE "MOVE"
	PJRST	DELINS

;PATTERN 5
;	MOVE	AC,10
;	ADDM	AC,MEM
;PARA:	...

CVPAT5:	LDB	TB,[IP$OP <3(IPI)>] ; IS PARA: NEXT?
	CAIE	TB,PROC.
	 POPJ	PP,		;NO, CAN'T DO IT
	LDB	TB,[IP$AC <2(IPI)>] ; GET AC OF ADDM
	CAIE	TB,(TD)		;THE SAME?
	  POPJ	PP,		;NO
	AOS	(PP)		;YES!
	DPB	TE,[IP$AC <2(IPI)>] ;STORE AC10 IN ADDM IPTAB ENTRY
	MOVE	TD,2(IPI)
	DPB	TE,[POINT 4,(TD),12] ;AND IN INSTBF
	MOVEI	TA,1(IPI)	;THEN GO DELETE THE MOVE
	PJRST	DELINS

;PATTERN 6
;	DMOVE	AC,7
;	DMOVE	4,AC

CVPAT6:	HRRZ	TC,(TB)		;GET ADDRESS OF 2(IPI)
	CAIE	TC,(TD)		;DOES AC OF 1(IPI) = ADDRESS OF 2(IPI)
	POPJ	PP,		;NO!
	AOS	(PP)		;YES-- FIXUP
	HRRM	TE,(TB)		;MAKE IT "DMOVE 4,7"
	MOVEI	TA,1(IPI)
	PJRST	DELINS		;DELETE THE "DMOVE AC,7"
;PATTERN 7
;	MOVE	AC,10
;	IMUL	0,AC

CVPAT7:	MOVE	TB,2(IPI)
	HRRZ	TC,(TB)
	CAIE	TC,(TD)		;IS ADR OF "IMUL" THE AC?
	POPJ	PP,		;NO
	LDB	TA,[IP$AC TB]
	JUMPN	TA,CPOPJ	;MAKE SURE "AC1" = 0
	AOS	(PP)		;SUCCESS!
	HRRM	TE,(TB)		;STORE AC10 AS ADDRESS OF THE "IMUL"
	MOVEI	TA,1(IPI)	;AND DELETE THE "MOVE"
	PJRST	DELINS

;PATTERN 8
;	DMOVE	AC,7
;	DADD	AC1,AC

CVPAT8:	MOVE	TB,2(IPI)
	HRRZ	TC,(TB)
	CAIE	TC,(TD)		;IS ADR OF "DADD" THE AC?
	POPJ	PP,		;NO
	LDB	TA,[IP$AC TB]
	CAIN	TA,(TD)		;MAKE SURE "AC1" NOT EQUAL "AC"
	POPJ	PP,
	AOS	(PP)		;SUCCESS!
	HRRM	TE,(TB)		;STORE AC7 AS ADDRESS OF THE "DADD"
	MOVEI	TA,1(IPI)	;AND DELETE THE "DMOVE"
	PJRST	DELINS
;PATTERN 9
;	DMOVE	AC,7
;	SETZ	7,
;	MOVE	10,MEM
;	DMUL	AC,7
;
;REPLACE WITH
;
;	SETZ	AC,
;	MOVE	AC+1,MEM
;	DMUL	AC,7

CVPAT9:	LDB	TC,[IP$AC TB]	;GET AC FIELD OF SETZ
	MOVE	TB,4(IPI)	;POINT TO DMUL
	LDB	TA,[IP$OP TB]
	CAIN	TA,DMUL.	;MAKE SURE IT IS
	CAIE	TC,7		;SETZ 7,
	POPJ	PP,
	LDB	TC,[IP$AC TB]	;GET AC FIELD
	HRRZ	TA,(TB)		;GET ADDRES
	CAIN	TC,(TD)		;SAME AC?
	CAIE	TA,7		;IS IT THE RIGHT AC
	POPJ	PP,
	MOVE	TB,3(IPI)	;POINT TO MOVE
	LDB	TA,[IP$OP TB]
	LDB	TC,[IP$AC TB]	;GET AC FIELD
	CAIE	TA,MOV
	CAIN	TA,MOVEI.	;ONLY TWO POSSIBILITIES
	CAIE	TC,10		;AC10
	POPJ	PP,

;NOW FOR THE FIXUP
	AOS	(PP)		;SUCCESS
	MOVE	TB,2(IPI)
	DPB	TD,[IP$AC TB]	;STORE AC
	DPB	TD,[POINT 4,(TB),12]
	ADDI	TD,1		;AC+1
	MOVE	TB,3(IPI)
	DPB	TD,[IP$AC TB]	;AC+1
	DPB	TD,[POINT 4,(TB),12]
	MOVEI	TA,1(IPI)
	PJRST	DELINS		;DELETE DMOVE AC,7

;CHECK FOR COMMON SUBSCRIPT CODE
;THIS IS GENERATED BY MOVE A(I) TO B(I) WHERE I IS DISPLAY

;PATTERN
;	MOVE	5,%LIT
;	MOVEI	5,SIZE
;	MOVE	14,%LIT1
;	PUSHJ	17,CVDDB.
;	MOVEM	10,%TEMP	;RESULT OF PREVIOUS OPTIMIZATION
;
;	MOVE	5,%LIT
;	MOVEI	5,SIZE
;	MOVE	14,%LIT1
;	PUSHJ	17,CVTDB.
;
;DELETE THE SECOND PART
;

	PATTERN	CVPCSS
	TEST	5,%CNVD.	;TEST FOR "PUSHJ PP,CVTDB.""
	TEST	-3,MOV		;MAKE SURE OTHER END IS IN TABLE
	TESTMR	CVPSAM

;HERE FOR DELETION
	MOVEI	TA,5(IPI)	;PUSHJ	17,CVTDB.
	PUSHJ	PP,DELINS
	MOVEI	TA,4(IPI)	;MOVE	14,%LIT
	PUSHJ	PP,DELINS
	MOVEI	TA,3(IPI)	;MOVEI	4,SIZE
	PUSHJ	PP,DELINS
	MOVEI	TA,2(IPI)	;MOVE	5,%LIT
	PUSHJ	PP,DELINS

;NOW TEST FOR
;	MOVE	4,10
;	MOVEM	4,%TEMP+1
;AND REPLACE BY
;	MOVEM	10,%TEMP+1

	TEST	3,MOVEM.
	HRRZ	TA,2(IPI)	;SEE IF MOVE
	MOVE	TB,(TA)
	LDB	TC,[IP$AC <3(IPI)>]
	CAMN	TB,[<MOV>B26+AC4,,10]
	CAIE	TC,4		;MAKE SURE MOVEM 4,
	POPJ	PP,
	HRRZ	TA,3(IPI)
	DPB	TB,[IP$AC <3(IPI)>]
	DPB	TB,[POINT 4,(TA),12]
	MOVEI	TA,2(IPI)
	PUSHJ	PP,DELINS

;NOW FOR THE FINAL STEP
;THE PATTERN SHOULD BE THAT OF ADJPAT
;EXCEPT THAT THE TWO %TEMPS ARE NOT IDENTICAL
;THE TEST IS TO SEE IF THE ONE WE JUST STORED IS USED LATER
;AND IF SO REPLACE BE COMMON ONE
;WE ALSO NEED NOT STORE THE SECOND ONE IF THIS IS TRUE

	TEST	6,MOV		;MAKE SURE ITS IN THE TABLE
	HRRZ	TA,5(IPI)
	HLRZ	TA,(TA)		;GET OPCODE AC, OF PREV
	CAIE	TA,<ADJBP.-200>B26+AC5+ASINC	;THIS SHOULD BE SUFFICENT
	POPJ	PP,		;NOT THE EXPECTED PATTERN
	HRRZ	TA,2(IPI)	;MOVEM	10,%TEMP+N
	HRRZ	TB,6(IPI)	;MOVE	10,%TEMP+N
	MOVE	TC,(TA)
	TLC	TC,<<MOV>^!<MOVEM.>>B26
	CAME	TC,(TB)		;DOES IT MATCH
	POPJ	PP,
	MOVE	TC,1(TA)	;GET 2ND WORD
	CAME	TC,1(TB)	;ALSO MATCH?
	POPJ	PP,
	HRRZ	TA,1(IPI)	;GET ADDR. OF FIRST STORE
	MOVE	TC,(TA)		;SHOULD BE "MOVEM 10,%TEMP"
	TLC	TC,<<MOV>^!<MOVEM.>>B26
	CAME	TC,(TB)
	POPJ	PP,
	MOVE	TC,1(TA)	;GET OFFSET
	MOVEM	TC,1(TB)	;CHANGE IT
	MOVEI	TA,2(IPI)
	PJRST	DELINS		;DELETE "MOVEM 10,%TEMP+N"

CVPSAM:	HRRZ	TA,-2(IPI)	;POINT TO MOVEI 4,SIZE
	HRRZ	TB,3(IPI)	;...
	MOVE	TA,(TA)		;GET ACTUAL INST.
	HLRZ	TC,(TB)		;GET OPCODE+AC
	CAMN	TA,(TB)
	CAIE	TC,<MOVEI.>B26+AC4
	POPJ	PP,
	HRRZ	TA,-1(IPI)	;POINT TO MOVE 14,%LIT
	HRRZ	TB,4(IPI)	;...
	MOVE	TC,(TA)		;GET ACTUAL INST.
	HLRZ	TE,TC		;MIGHT BE MOVEI 14,CONST.
	CAME	TC,[<MOV>B26+AC14+ASINC,,AS.MSC]
	CAIN	TE,<MOVEI.>B26+AC14
	CAME	TC,(TB)
	POPJ	PP,
	MOVE	TC,1(TA)	;GET LITERAL
	CAIE	TE,<MOVEI.>B26+AC14
	CAMN	TC,1(TB)	;MAKE SURE SAME
	CAIA
	POPJ	PP,
	HRRZ	TA,-3(IPI)	;POINT TO MOVE 5,%LIT
	HRRZ	TB,2(IPI)	;...
	MOVE	TC,(TA)		;GET ACTUAL INST.
	CAMN	TC,(TB)
	CAME	TC,[<MOV>B26+AC5+ASINC,,AS.MSC]
	POPJ	PP,
	MOVE	TC,1(TA)	;GET LITERAL
	CAMN	TC,1(TB)	;MAKE SURE SAME
	AOS	(PP)		;OK
	POPJ	PP,

>;END IFN BIS (FOR CVTDB OPTIMIZATIONS)
SUBTTL	ROUTINES NEEDED FOR THE MACROS AND THE DRIVER

	;ROUTINE TO VERIFY THAT PREVIOUS INSTR IS NOT ANY
	; KIND OF SKIP INSTR THAT WILL CAUSE THE CODE PATTERN
	; TO NOT BE A BLOCK.
SKPTST:
		;SOME LIBOL CALLS
		; HAVE THREE RETURNS, SO THEY NEED
		; TO BE INCLUDED IN THIS TESTING ROUTINE
	SKIPG	TA,	-2(IPI)		;GET PREVIOUS INSTR FROM IPTAB
	JRST		SKPTS2		;IF NO-TOUCH, ITS NOT A SKIP
					;IF IPTAB ENT IS ZERO, THERE IS NO
					;INSTRUCTION THERE, SO IT WON'T SKIP
	TLNE	TA,	IP%SK2		;SKIP IF INSTR DOESNT SKIP 2
	POPJ	PP,			;GO HOME, CODE IS NOT OPTIMIZABLE
SKPTS2:	SKIPLE	TA,	-1(IPI)		;GET PREVIOUS INSTR
	TLNN	TA,	IP%SKP		;CHECK FOR ANY SKIP INSTRS
	AOS		(PP)		;INCREMENT RETURN ADDRESS
	POPJ	PP,			;RETURN.
SUBTTL	CONDITIONAL SKIP/JRST/INST. PATTERN

;HERE WE LOOK FOR ANY CONDITIONAL SKIP FOLLOWED BY JRST
; THE INTENT IS TO SEE IF THE JRST MERELY GOES AROUND THE
; NEXT INSTRUCTION.

	PATTERN CNDSKP		;CONDITIONAL SKIP PATTERN, NO BROTHER
	NOPSKP			;NO PREVIOUS SKIPS
	TEST	1,JRST.
	ISIZE	1,1		;THE JRST BETTER BE ONE WORD IN INSTBF
	TEST2	3,%TAG.,%PROC.	;EITHER ONE WILL DO

	LDB	TA,[IP$OP <2(IPI)>]
	CAILE	TA,XTND.	;IS IT A VALID INST.
	%%GOTO			;NO, TRY SOMETHING ELSE

	TESTMR	JRSTAG		;DOES JRST GOTO TAG
	DOIT	JRSTEL		;GOT ONE, ELIMINATE THE JRST

JRSTAG:	;SEE IF THE TAG IN THE JRST IS THE SAME AS THE
	; TAG AFTER THE NEXT INST.
	MOVE	TA,	1(IPI)		;GET IPTAB ENT FOR JRST
	LDB	TB,	[IP$WC TA]	;GET THE COUNT OF WORDS IN INSTBF
	SOJN	TB,	CPOPJ		;BETTER BE ONE
	HRRZ	TB,	(TA)		;GET THE TAG FROM INSTBF
	MOVE	TA,	3(IPI)		;GET IPTAB ENT OF THE TAG
	LDB	TC,	[IP$WC TA]	;GET WORD COUNT IN INSTBF
	SOJN	TC,	CPOPJ		;BETTER BE 1, IF NOT RETURN.
	HRRZ	TC,	(TA)		;GET THE TAG FROM INSTBF
	CAMN	TB,	TC		;ARE THE TAGS THE SAME?
	AOS		(PP)		;YEP, INCREMENT RETURN
	POPJ	PP,			;NOPE

JRSTEL:	;WE FOUND A COMPARE FOLLOWED BY JRST TO TAG FOLLOWED BY
	; A NON-SKIP INST. FOLLOWED BY THE SAME TAG.  SWAP THE SENSE OF THE
	; SKIP, AND REMOVE THE JRST.
	MOVE	TA,	IPI		;GET POINTER TO IPTAB
	ADDI	TA,	1		;GET THE POINTER TO THE JRST TO GO
	HRRZ	TB,	(TA)		;GET INSTBF ADDR OF JRST
	HRRZ	TB,	(TB)		;GET THE TAG ITSELF
	PUSH	PP,	TB		;SAVE TAG NAME
	PUSHJ	PP,	DELINS		;DELETE THE JRST
	LDB	TB,	[IP$OP <2(IPI)>]	;GET THE OP CODE
	POP	PP,	TA		;RESTORE TAG NAME
	CAIN	TB,	%PROC.		;DONT DEREFERENCE PROCEDURE NAMES
	JRST		RVRSKP		;REVERSE SKIP, TAG IS OK
	PUSHJ	PP,	DRFTAG		;DE-REFERENCE THE TAG
	JRST		RVRSKP		;NON-ZERO COUNT, ALL IS OK
	MOVEI	TA,	2(IPI)		;GET ADDRESS OF TAG LOC IN IPTAB
	PUSHJ	PP,	DELINS		;REMOVE FROM IPTAB TO ALLOW CASCADE

	;NOW REVERSE THE SENSE OF THE SKIP
RVRSKP:	LDB	TB,	[IP$OP <(IPI)>]	;GET THE OP CODE OF THE INSTR
	CAILE	TB,	SKIP.		;SEE IF A SKIP
	CAIL	TB,	SKIPA.		;...
	JRST	RVRCAM			;NO, TRY CAI OR CAM
	SUBI	TB,	SKIP.		;SUBTRACT BASE SO WE CAN COMPLEMENT
	TRC	TB,	7		;REVERSE SENSE
	ADDI	TB,	SKIP.		;ADD IN THE BASE ADDRESS
	JRST	RVRREP			;REPLACE OPCODE

RVRCAM:	CAIL	TB,	CAM.		;BESURE ITS A COMPARE
	CAILE	TB,	CAIN.		; IN THE PROPER RANGE
	JRST	RVRSER			;NOT A COMPARE THAT WE KNOW ABOUT
	SUBI	TB,	CAM.		;SUBTRACT BASE SO WE CAN COMPLEMENT
	TRC	TB,	16		;REVERSE SENSE
	ADDI	TB,	CAM.		;ADD IN THE BASE ADDRESS
RVRREP:	DPB	TB,	[IP$OP <(IPI)>]	;REFLECT CHANGE IN THE IPTAB
	HRRZ	TA,	(IPI)		;GET ADDRESS OF ENTRY IN INSTBF
	DPB	TB,	[POINT 7,(TA),8]	;PUT NEW OP CODE IN PLACE
	POPJ	PP,			;RETURN HOME


RVRSER:	;ERROR- THE OP CODE WAS NOT LEGITIMATE
	TTCALL	3,[ASCIZ/? COMPARE OPTIMIZATION DID NOT RECOGNIZE OP CODE
/]
	PJRST	KILL##
SUBTTL	MOVEI OPTIMIZATIONS

;  PATTERN TO OPTIMIZE
;	MOVEI	AC1,STUFF
;	ADD	AC,AC1
;  WHICH HAPPENS OFTEN IN SUBSCRIPTING, SUCH AS (A,2,B)

	PATTERN	MVIPAT,LODSTR	 ;HERE AFTER MOVEI SEEN
	NOPSKP			;NO PREVIOUS SKIPS, PLEASE
	TEST	1,AD		;ADD NEXT?
	PATTERN	,LKGPAT		;LOOK FOR LINKAGE SECTION PATTERN NEXT
	TESTMR	SAMAC		;IS AC1=AC1?
	DOIT	OPTMVI		;YES- FIX THIS

;ROUTINE TO CHECK FOR SAME AC IN MOVEI AND ADD ADDRESS
SAMAC:	MOVE	TA,(IPI)	;GET IPTAB ENTRY FOR MOVEI
	LDB	TE,[IP$AC TA]	;GET AC OF MOVEI
	MOVE	TB,1(IPI)	;GET IPTAB ENTRY FOR ADD
	LDB	TD,[IP$AC TB]	;GET AC OF ADD
	CAIE	TE,1(TD)	;IS AC+1 = AC1?
	 POPJ	PP,		;NO
	HRRZ	TC,(TB)		;WHAT HAVE WE HERE?
	CAIN	TC,AS.CNB
	MOVE	TC,1(TB)
	CAMN	TC,TE		;SAME AC?
	 AOS	(PP)		;YES
	POPJ	PP,		; NO

;DO MOVEI/ADD OPTIMIZATION
OPTMVI:	MOVE	TA,(IPI)
	HRRZ	TB,(TA)
	CAIN	TB,AS.CNB
	MOVE	TB,1(TA)
	JUMPE	TB,MOVI0	;MOVEI AC1,0 - GET RID OF BOTH INSTRUCTIONS

;GET RID OF MOVEI, CHANGE ADDRESS OF ADD TO MOVEI ADDRESS,
; CHANGE OPCODE TO ADDI

	LDB	TB,[IP$WC TA]	;# WORDS MOVEI TAKES UP
	MOVE	TA,1(IPI)
	LDB	TC,[IP$WC TA]	;# WORDS ADD TAKES UP
	MOVEI	TA,1(IPI)	; ADD A WORD TO ADD IF WE NEED TO
	CAILE	TB,(TC)		;SKIP IF ADD TAKES UP ENOUGH WORDS
	PUSHJ	PP,ADDWD	;NO--CALL ROUTINE TO FIX IT UP

;CHANGE OPCODE OF "ADD" TO "ADDI"
	MOVEI	TE,ADDI.	;GET "ADDI"
	DPB	TE,[IP$OP <1(IPI)>] ;STORE NEW OPCODE
	MOVE	TD,1(IPI)
	DPB	TE,[POINT 8,(TD),8] ;STORE OPCODE IN INSTBF ALSO

;SET WORD COUNT OF ADDI
	LDB	TE,[IP$WC <(IPI)>] ;GET WORD COUNT OF MOVEI
	DPB	TE,[IP$WC <1(IPI)>] ;SET WORD COUNT OF ADDI

;SET OR CLEAR INCREMENT FLAG
	MOVE	TA,(IPI)
	MOVE	TC,(TA)		;FIRST WORD OF MOVEI INSTRUCTION
	MOVE	TB,1(IPI)
	MOVE	TD,(TB)		;FIRST WORD OF ADDI INSTRUCTION
	HRR	TD,TC		;FIXUP ADDI
	TLO	TD,ASINC	;ASSUME INCREMENT
	TLNN	TC,ASINC	;SKIP IF TRUE
	TLZ	TD,ASINC	;NO-- TURN OFF IN ADDI THEN
	MOVEM	TD,(TB)		;STORE FIRST WORD
	TLNN	TD,ASINC	;WAS THERE AN INCREMENT?
	 JRST	OPMVI1		;YES--GO DELETE MOVEI NOW
	MOVE	TD,1(TA)	;GET 2ND WORD
	MOVEM	TD,1(TB)	;STORE "AS IS"
OPMVI1:	HRRZ	TA,IPI		;DELETE MOVEI
	PJRST	DELINS		;AND RETURN

;HERE TO DELETE BOTH INSTRUCTIONS
MOVI0:	MOVEI	TA,1(IPI)	;DELETE ADD
	PUSHJ	PP,DELINS
	MOVEI	TA,(IPI)	;AND MOVEI
	PJRST	DELINS
SUBTTL	LINKAGE SECTION OPTIMIZATION

;PATTERN
;	MOVEI	12,MEM
;	ADD	12,%PARAM+N
;	OP	AC,(12)
;
;REPLACE WITH
;
;	MOVE	12,%PARAM+N
;	OP	AC,MEM(12)
;
;NOTE WE HAVE ALREADY CHECKED FOR MOVEI AND ADD
;ALSO MEM MUST BE IN THE LINKAGE SECTION

	PATTERN	LKGPAT
	SKIPG	TA,2(IPI)	;MAKE SURE NEXT INST IS IN THE TABLE
	%%GOTO			;NO
	LDB	TA,[IP$OP <2(IPI)>]
	CAILE	TA,XTND.	;IS IT A VALID INST.
	%%GOTO			;NO
	MOVE	TA,0(IPI)	;MOVEI
	MOVE	TB,1(IPI)	;ADD
	LDB	TD,[IP$AC TA]
	LDB	TE,[IP$AC TB]
	CAIN	TD,12		;ARE BOTH ACC 12
	CAIE	TE,12		;...
	%%GOTO			;NO
	HRRZ	TA,(TA)		;GET ADDRESS OF MOVEI
	LDB	TE,[POINT 3,TA,20]	;GET CODE
	LDB	TD,[POINT 3,(TB),20]	;GET CODE FOR ADD
	CAIN	TD,AC.MSC##	;IS IT MISC. (TO BE FOLLOWED BY PARAM)
	CAIE	TE,AC.DAT##	;IS IT A DATA-NAME
	%%GOTO			;NO
	LDB	TD,[IP$WC TB]	;BETTER BE 2 WORDS
	SOJE	TD,%GO2AD	;NO
	LDB	TD,[POINT 3,1(TB),20]	;GET CODE
	CAIE	TD,AC.PAR##	;BETTER BE %PARAM
	%%GOTO			;NO
	PUSHJ	PP,LNKSET	;GET ADDRESS
	LDB	TE,DA.DFS##	;MAKE SURE NOT FILE TABLE
	JUMPN	TE,%GO2AD
	LDB	TE,DA.LKS##	;NOW MAKE SURE ITS IN LINKAGE SECTION
	JUMPE	TE,%GO2AD	;NO
				;YES, ...
	PATTERN	,LKGPT2		;POSSIBLE ALTERNATIVE AT THIS POINT
	MOVE	TE,2(IPI)	;GET ADDRESS OF LOAD/STORE
	MOVE	TE,(TE)		;GET INST.
	TLZ	TE,377760	;LEAVE INDIRECT AND INDEX FIELDS
	CAME	TE,[Z 0(12)]	;ONLY VALID ADDRESS
	%%GOTO
	DOIT			;FOUND IT

	MOVEI	TE,MOV
	DPB	TE,[IP$OP TB]	;CHANGE ADD TO MOVE
	DPB	TE,[POINT 7,(TB),8]
	MOVE	TA,0(IPI)	;GET MOVEI BACK
	MOVE	TB,2(IPI)	;LOAD/STORE
	HRRZ	TE,(TA)		;GET DATA-ITEM ADDRESS
	HRRM	TE,(TB)		;CHANGE LOAD/STORE INST.
	MOVEI	TA,0(IPI)	;NOW DELETE MOVEI
	PJRST	DELINS
;PATTERN
;	MOVEI	12,MEM
;	ADD	12,%PARAM+N
;	ASHC	AC,-^D35
;	OP	AC,(12)
;
;REPLACE WITH
;
;	ASHC	AC,-^D35
;	MOVE	12,%PARAM+N
;	OP	AC,MEM(12)
;
	PATTERN	LKGPT2
	MOVE	TE,2(IPI)	;GET ADDRESS
	MOVE	TD,1(TE)	;GET NEXT WORD
	MOVE	TE,(TE)		;GET INST
	CAMN	TE,[<ASHC.>B26,,AS.CNB]
	CAIE	TD,-^D35
	%%GOTO
	MOVE	TE,3(IPI)	;GET ADDRESS OF LOAD/STORE
	MOVE	TE,(TE)		;GET INST.
	TLZ	TE,377760	;LEAVE INDIRECT AND INDEX FIELDS
	CAME	TE,[Z 0(12)]	;ONLY VALID ADDRESS
	%%GOTO

	DOIT

	MOVEI	TE,MOV
	DPB	TE,[IP$OP TB]	;CHANGE ADD TO MOVE
	DPB	TE,[POINT 7,(TB),8]
	MOVE	TA,0(IPI)	;GET MOVEI BACK
	MOVE	TB,3(IPI)	;LOAD/STORE
	HRRZ	TE,(TA)		;GET DATA-ITEM ADDRESS
	HRRM	TE,(TB)		;CHANGE LOAD/STORE INST.
	MOVE	TE,1(IPI)	;TO MAKE LIFE EASIER LATER
	EXCH	TE,2(IPI)	;SWAP MOVE AND ASHC
	MOVEM	TE,1(IPI)	;...
	MOVEI	TA,0(IPI)	;NOW DELETE MOVEI
	PUSHJ	PP,DELINS

;NOW LOOK FOR POSSIBLE EXTRA OPTIMIZATION FROM ADD CONST. TO DATA-ITEM

;PATTERN
;	MOVE	12,%PARAM+N
;	OP	AC,MEM(12)
;	MOVEI	12,MEM
;	ADD	12,%PARAM+N
;	OP	AC,(12)
;
;REPLACE WITH
;
;	MOVE	12,%PARAM+N
;	OP	AC,MEM(12)
;	OP	AC,MEM(12)

	TEST	3,MOVEI.
	TEST	4,AD
	SKIPG	TA,5(IPI)	;MAKE SURE NEXT INST IS IN THE TABLE
	%%GOTO			;NO
	LDB	TA,[IP$OP <5(IPI)>]
	CAILE	TA,XTND.	;IS IT A VALID INST.
	%%GOTO			;NO
	MOVE	TA,3(IPI)	;MOVEI
	MOVE	TB,4(IPI)	;ADD
	LDB	TD,[IP$AC TA]
	LDB	TE,[IP$AC TB]
	CAIN	TD,12		;ARE BOTH ACC 12
	CAIE	TE,12		;...
	%%GOTO			;NO
	HRRZ	TA,(TA)		;GET ADDRESS OF MOVEI
	LDB	TE,[POINT 3,TA,20]	;GET CODE
	LDB	TD,[POINT 3,(TB),20]	;GET CODE FOR ADD
	CAIN	TD,AC.MSC##	;IS IT MISC. (TO BE FOLLOWED BY PARAM)
	CAIE	TE,AC.DAT##	;IS IT A DATA-NAME
	%%GOTO			;NO
	LDB	TD,[IP$WC TB]	;BETTER BE 2 WORDS
	SOJE	TD,%GO2AD	;NO
	HRRZ	TD,1(TB)	;GET ADDRESS (%PARAM+N)
	MOVE	TE,1(IPI)	;GET PREV LOAD OF 12
	CAME	TD,1(TE)	;IS IT THE SAME %PARAM?
	%%GOTO			;NO
	PUSHJ	PP,LNKSET	;GET ADDRESS
	LDB	TE,DA.DFS##	;MAKE SURE NOT FILE TABLE
	JUMPN	TE,%GO2AD
	LDB	TE,DA.LKS##	;NOW MAKE SURE ITS IN FILE SECTION
	JUMPE	TE,%GO2AD	;NO
	MOVE	TE,5(IPI)	;GET ADDRESS OF LOAD/STORE
	MOVE	TE,(TE)		;GET INST.
	TLZ	TE,377760	;LEAVE INDIRECT AND INDEX FIELDS
	CAME	TE,[Z 0(12)]	;ONLY VALID ADDRESS
	%%GOTO
	DOIT			;FOUND IT

	MOVE	TA,3(IPI)	;GET MOVEI BACK
	MOVE	TB,5(IPI)	;LOAD/STORE
	HRRZ	TE,(TA)		;GET DATA-ITEM ADDRESS
	HRRM	TE,(TB)		;CHANGE LOAD/STORE INST.
	MOVEI	TA,4(IPI)	;DELETE ADD
	PUSHJ	PP,DELINS
	MOVEI	TA,3(IPI)	;NOW DELETE MOVEI
	PJRST	DELINS
SUBTTL	ADDM OPTIMIZATION

;PATTERN:
;	ADDM AC,MEM
;	MOVE AC,MEM
;
;CHANGE TO:
;	ADDB AC,MEM

	PATTERN ADMPAT
	NOPSKP			;NO PREVIOUS SKIPS!
	TEST	1,MOV		;MOVE NEXT?
	TESTMR	SAMACM		;IS AC AND MEM THE SAME FOR BOTH?
	DOIT	OPTADM		;YES! FIX IT

SAMACM:	LDB	TA,[IP$AC <(IPI)>] ;GET AC OF ADDM
	LDB	TB,[IP$AC <1(IPI)>] ;AND AC OF MOVE
	CAME	TA,TB
	  POPJ	PP,		;DIFFERENT, FORGET IT
	HRRZ	TA,(IPI)	;TA POINTS TO ADDM
	HRRZ	TB,1(IPI)	;TB POINTS TO MOVE
	HRRZ	TC,(TA)
	HRRZ	TD,(TB)
	CAME	TC,TD		;ARE FIRST WORDS THE SAME?
	  POPJ	PP,		;NOPE
	LDB	TC,[IP$WC <(IPI)>] ; GET WORD COUNT
	SOJE	TC,[LDB TD,[IP$WC <1(IPI)>] ;[701] 1ST WORD COUNT IS 1--GET 2ND
		SOJE	TD,CPOPJ1  ;[701] IF BOTH 1, MATCH
		POPJ	PP,]	;[701] ELSE NO MATCH
	MOVE	TC,1(TA)	;NO--CHECK 2ND WORD ALSO
	MOVE	TD,1(TB)
	CAMN	TC,TD
CPOPJ1:	AOS	(PP)		;SKIP RETURN
CPOPJ:	POPJ	PP,

OPTADM:	MOVEI	TA,ADDB.	;GET ADDB INSTEAD OF ADDM
	DPB	TA,[IP$OP <(IPI)>] ;STORE IN ADDM INSTRUCTION
	HRRZ	TB,(IPI)
	DPB	TA,[POINT 7,(TB),8] ;STORE OPCODE
	MOVEI	TA,1(IPI)	;AND THEN DELETE THE MOVE
	PJRST	DELINS
SUBTTL	MOVE OPTIMIZATION

;PATTERN:
;	MOVE	AC,LIT+N
;	MOVE	AC+1,LIT+N+1
;
;CHANGE TO:
;	DMOVE	AC,LIT+N

;NOTE:	THIS CAN ONLY BE DONE IF BIS=1

IFN BIS,<
	PATTERN	MVEPAT,LODSTR	;IF NOT POSSIBLE, TRY MOVE/MOVEM OPTIMIZATION
	NOPSKP			;NO PREVIOUS SKIPS
	TEST	1,MOV		;NEXT GUY A MOVE
	TESTMR	ACAC1		;IS IT "MOVE AC" THEN "MOVE AC+1"
	TESTMR	ADRAD1		;IS IT ADDR THEN ADDR+1?
	DOIT	MVEDMV		;YES-- MAKE THE DMOVE

ACAC1:	LDB	TA,[IP$AC <(IPI)>]
	LDB	TB,[IP$AC <1(IPI)>]
	CAIN	TB,1(TA)	;AC+1?
	 AOS	(PP)		;YES
	POPJ	PP,		;NO

ADRAD1:	MOVE	TA,(IPI)	;GET 1ST GUY
	MOVE	TB,1(IPI)
	HRRZ	TC,(TA)
	HRRZ	TD,(TB)		;1ST HALF MUST BE THE SAME!
				; (INCREMENTS WILL BE DIFFERENT)
	CAME	TC,TD
	 POPJ	PP,
	LDB	TC,[IP$WC TA]	;# WDS IN FIRST GUY
	SETZ	TD,		;ASSUME 1 - GET 0 INCREMENT
	CAIN	TC,2
	MOVE	TD,1(TA)	;NO--GET INCREMENT
	TLNE	TD,-1		;NO NEG INCREMENTS, PLEASE
	 POPJ	PP,
	LDB	TC,[IP$WC TB]	;# WDS IN 2ND GUY
	CAIN	TC,1
	  POPJ	PP,		;MUST HAVE SOMETHING!
	MOVE	TB,1(TB)	;TB:= 2ND MOVE'S INCREMENT
	ADDI	TD,1
	CAMN	TD,TB		;IS 1ST ADDR ONE LESS THAN 2ND?
	 AOS	(PP)		;YES--SKIP
	POPJ	PP,

;OK TO DO OPTIMIZATION
MVEDMV:	MOVE	TA,(IPI)	;GET IPTAB WORD FOR 1ST MOVE
	MOVEI	TB,DMOVE.	;GET NEW OPCODE
	DPB	TB,[POINT 7,(TA),8] ;STORE IN INSTBF ENTRY
	DPB	TB,[IP$OP <(IPI)>] ;AND IN IPTAB ENTRY
	MOVEI	TA,1(IPI)	;POINT TO 2ND MOVE
	PJRST	DELINS		;DELETE IT & RETURN
>;END IFN BIS
SUBTTL	LOAD/STORE/LOAD
; CHECK FOR REDUNDANT LOADS AFTER THE FIRST

	PATTERN	LODSTR		;LOAD/STORE ATTEMPT
IFE BIS,<	SYN	LODSTR,MVEPAT >	;TRY LOAD/STORE OPTIMIZATION
	NOPSKP			;NO PREVIOUS SKIPS
	TESTN	1,<MOVEM.,DPB.,ADDM.,MOVMM.> ;STORES
	TESTMR	DLOADS		;DELETE REDUNDANT LOAD'S
	DOIT			;SKIP RETURN IF WE DELETED ANY

	TSWTZ	FDELI		;DID WE DELETE ANY?
	SOS	(PP)		;NO, DON'T SKIP RETURN
	POPJ	PP,

;DELETE SOME IF WE CAN
DLOADS:	AOS	(PP)		;MAKE SURE WE GET TO LODSTE
	MOVE	TA,(IPI)	;GET LOAD IPTAB ENTRY
	LDB	TE,[IP$WC TA]	;GET WORD COUNT
	MOVE	TD,(TA)		;TD= FIRST WORD
	SETZ	TC,		;ASSUME NO SECOND WORD
	CAIN	TE,2
	MOVE	TC,1(TA)	;NO- GET 2ND WORD
	MOVEM	TD,OTEMP##	;FIRST WORD IN OTEMP
	MOVEM	TC,OTEMP##+1
	LDB	TE,[IP$AC TA]	;TE:= AC OF LOAD
	MOVEI	TA,1(IPI)	;TA:= PTR TO STORE INSTRUCTION
	SWOFF	FDELI		;TURN ON IF WE DELETE ANYTHING

DLMVI1:	ADDI	TA,1		;POINT TO NEXT INSTRUCTION
	SKIPN	TB,(TA)		;GET IPTAB ENTRY IF ANY MORE
	 POPJ	PP,		;NO MORE, RETURN
	MOVE	TD,(TB)		;GET FIRST WORD
	CAME	TD,OTEMP##	;MATCH?
	 POPJ	PP,		;NO
	LDB	TC,[IP$WC TB]	;GET WORD COUNT
	CAIN	TC,1		;ONE?
	 JRST	DLMVI2		;YES- SKIP THIS
	MOVE	TD,1(TB)	;GET 2ND WORD
	CAME	TD,OTEMP+1	;MATCH ALSO?
	 POPJ	PP,		;NO
				;YES, ...
;WE HAVE FOUND A REDUNDANT LOAD!
DLMVI2:	PUSH	PP,TA
	PUSH	PP,TE		;SAVE AC ALSO
	PUSHJ	PP,DELINS	;DELETE THE LOAD INSTRUCTION
				; (EVERYTHING UNDER IT MOVES UP)
	POP	PP,TE		;RESTORE AC OF LOAD
	POP	PP,TA		;TA POINTS TO THE NEXT INSTRUCTION
	SWON	FDELI		;REMEMBER WE DELETED AN INSTRUCTION

;IS THIS NEXT THING A STORE ALSO?
	SKIPN	TB,(TA)
	 POPJ	PP,		;NOTHING THERE!
	LDB	TB,[IP$OP TB]
	CAIE	TB,MOVEM.
	CAIN	TB,DPB.
	 JRST	DLMVI1
	CAIE	TB,MOVMM.
	CAIN	TB,ADDM.
	 JRST	DLMVI1
	POPJ	PP,		;NOPE, HAVE TO STOP NOW
SUBTTL	MOVEM/MOVE OPTIMIZATION

;PATTERN:
;	MOVEM AC,THING
;	MOVE AC,THING
;
;CHANGE TO:
;	MOVEM AC,THING

	PATTERN MVMOPT		;SAW A MOVEM
	TEST	1,MOV		;NEXT THING A "MOVE"
	TESTMR	SAMACM		;AC AND ADDRESS MUST BE THE SAME
	DOIT			;DELETE THE MOVE

DEL1:	MOVEI	TA,1(IPI)	;POINT TO THE MOVE
	PJRST	DELINS		; GO DELETE IT & RETURN


SUBTTL	MOVMM / MOVM OPTIMIZATION

;PATTERN:
;	MOVMM AC,THING
;	MOVM AC,THING
;
;CHANGE TO:
;	MOVMM AC,THING
;	MOVM	AC,AC

	PATTERN MMMPAT		;SAW A MOVMM
	TEST2	1,MOV,MOVM.	;NEXT THING A "MOVE" OR "MOVM"
	TESTMR	SAMACM		;AC AND ADDRESS MUST BE THE SAME
	PATTERN	,MVMSAC		;TRY FOR MORE COMPLICATED TEST, BUT HERE IF WE FAIL
	TEST	-1,MOVM.	;SEE IF PREVIOUS REMOVED THE SIGN FOR US
	LDB	TE,[IP$AC <-1(IPI)>]
	LDB	TD,[IP$AC <(IPI)>]
	CAME	TE,TD		;SAME AC?
	%%GOTO			;NO, TOO BAD
	DOIT	DEL1		;YES, DELETE THE SECOND MOVM

;CHANGE MOVM TO MOVM AC,AC

MVMSAC:	LDB	TE,[IP$AC <1(IPI)>] ;GET AC OF MOVM
	HRRZ	TD,1(IPI)	;TD POINTS TO INSTBF ENTRY
	HRRM	TE,(TD)		; NEW ADDRESS IS = AC
	MOVSI	TE,ASINC	;TURN OFF INCREMENT IF ANY WAS THERE
	ANDCAM	TE,(TD)
	MOVEI	TE,1		;AND SET WORD COUNT TO 1
	DPB	TE,[IP$WC <1(IPI)>]
	PJRST	CPOPJ1		;DONE
SUBTTL	SKIPA/MOVE OPTIMIZATION

;OPTIMIZER PATTERN TO COMBINE SKIPA AND MOVE AC,FOO
; EXPECTS JRST BETWEEN SKIPA AND MOVE

	PATTERN SKPA,SKPA1	;FOUND A SKIPA INSTRUCTION
	TEST	1,JRST.		;AND A JRST
	TEST	2,MOV		;AND A MOVE TO AN AC OF A LITERAL
	TESTMR	ZEROAC		;GOTTA BE A ZERO AC IN THE INSTR
	DOIT	RMVMOV		;REMOVE THE MOVE INSTRUCTION

ZEROAC:	;THE AC OF THE SKIPA BETTER BE ZERO
	; AND THE AC OF THE MOVE BETTER BE NON-ZERO
	LDB	TA,	[IP$AC <(IPI)>]	;GET THE AC FIELD
	LDB	TB,	[IP$AC <2(IPI)>]	;GET AC OF THE MOVE
	SKIPN		TA		;TEST AC OF THE SKIPA
	SKIPN		TB		;TEST AC OF THE MOVE
	SKIPA				;SKIPA AC NOT ZERO OR MOVE AC IS ZERO
	AOS		(PP)		;INCREMENT RETURN
	POPJ	PP,			;GO HOME

RMVMOV:	;MAKE THE SKIPA ALSO DO THE MOVE TO THE AC.
	; EASIEST WAY TO DO THIS IS TO MAKE THE IPTAB ENTRIES
	; FOR THE MOVE AND SKIPA POINT TO THE OTHER'S PLACE IN
	; THE INSTBF.  THEN CHANGE THE MOVE OPCODE TO A SKIPA,
	; AND CAUSE THE MOVE TO BE DELETED (THUS ACTUALLY REMOVING
	; THE SKIPA FROM THE INSTBF).
	MOVE	TA,	(IPI)		;GET INSTBF WORD OF THE SKIPA
	EXCH	TA,	2(IPI)		;GET INSTBF WORD OF THE MOVE
	MOVEM	TA,	(IPI)		;PUT MOVE'S WORD IN SKIPA'S OLD PLACE

	MOVEI	TB,	SKIPA.		;GET OP CODE FOR SKIPA
	DPB	TB,	[POINT 7,(TA),8]	;AND PUT IN INSTBF OVER OLD MOVE
	DPB	TB,	[IP$OP <(IPI)>] ;AND STORE IN IPTAB ENTRY
	MOVSI	TB,	IP%SKA		;GET THE "SKIP ALWAYS" BIT
	IORM	TB,	(IPI)		;SET IN IPTAB ENTRY

	;[663] NOW WE MUST CHECK THAT THE PREVIOUS INSTRUCTION WAS NOT JRST .+3
	;[663] IF SO WE CHANGE IT TO JRST .+1 SINCE IT ALSO MUST DO THE MOVE

	MOVE	TA,-1(IPI)		;[663] LOOK BACKWARDS
IFN BIS,<
	DMOVE	TC,(TA)			;[663] PICK UP TWO WORDS
>
IFE BIS,<
	MOVE	TC,(TA)			;[663] THE SLOW WAY
	MOVE	TB,1(TA)		;[663] ...
>
	CAMN	TC,[<JRST.>B26+ASINC,,AS.MSC]	;[663] 
	CAIE	TB,AS.DOT+3		;[663] JRST .+3
	JRST	.+3			;[663] NO
	MOVEI	TB,AS.DOT+1		;[663] YES 
	MOVEM	TB,1(TA)		;[663] CHANGE TO JRST .+1

	MOVEI	TA,	2(IPI)		;GET ADDR IN IPTAB OF INSTR PAST JRST
					; (NOW A USELESS SKIPA)
	PJRST		DELINS		;AND REMOVE IT
SUBTTL	SKIPA/ANYTHING/JRST OPTIMIZATION

	PATTERN SKPA1,SKPA2		;NEXT SKIPA OPTIMIZATION
	TEST2	2,JRST.,XJRST.		;A "JRST" OR "XJRST"?
	TESTMR	ZROAC			;SKIPA AC BETTER BE ZERO
	TESTMR	ONEPC			;NEXT INSTRUCTION BETTER TAKE UP A PC
	TESTMR	NOTDOT			;CAN'T BE A "JRST .+N"
	DOIT	FXSKPA			;CHANGE SKIPA TO JRST

ZROAC:	LDB	TA,[IP$AC <(IPI)>]	;GET AC OF SKIPA
	JUMPE	TA,CPOPJ1		;IF NON-ZERO, DON'T SKIP RETURN
	POPJ	PP,

ONEPC:	LDB	TA,[IP$OP <1(IPI)>]	;GET NEXT GUY'S OPCODE
	CAILE	TA,XTND.		;SKIP IF AN OK INSTRUCTION
	 POPJ	PP,			;NO
	LDB	TA,[IP$SKP <1(IPI)>]	;GET COMBINED SKIP BITS
	JUMPE	TA,CPOPJ1		;IF ALL ZERO, RETURN "YES"
	POPJ	PP,			;ELSE NOT THE PATTERN

;SKIP IF TARGET OF JRST ISN'T ".+N" (WE CAN'T COPY THAT!)
NOTDOT:	LDB	TA,[IP$WC <2(IPI)>]	;GET WORD COUNT OF "JRST"
	CAIE	TA,2			;MUST CHECK IF IT'S 2
	JRST	CPOPJ1			;NO, NOT .+N
	HRRZ	TA,2(IPI)
	MOVE	TA,1(TA)		;GET 2ND WORD
	TRC	TA,AS.DOT
	TRNE	TA,700000		;SKIP IF WAS .+N
	AOS	(PP)			; IT WASN'T--RETURN "OK"
	POPJ	PP,

;PATTERN MATCHES. REPLACE "SKIPA" WITH THE "JRST".
FXSKPA:	LDB	TB,[IP$WC <(IPI)>] ;GET WORD COUNT OF THE SKIPA
	LDB	TC,[IP$WC <2(IPI)>] ;GET WORD COUNT OF THE "JRST"
	CAIL	TB,(TC)		;DO WE HAVE TO GET A WORD?
	 JRST	FSKPA1		;NO
	HRRZ	TA,IPI		;POINT TO "SKIPA"
	PUSHJ	PP,ADDWD	;GET A WORD
	LDB	TC,[IP$WC <2(IPI)>] ;RELOAD TC
FSKPA1:	HRRZ	TA,(IPI)	;GET POINTER TO "SKIPA"
	HLLZ	TB,2(IPI)	;GET LH OF "JRST" IPTAB WORD
	HLLM	TB,(IPI)	;PUT IN "SKIPA" PLACE
	HRRZ	TB,2(IPI)	;GET TB:= POINTER TO "JRST"
	MOVE	TD,(TB)		;GET 1ST WORD OF "JRST"
	MOVEM	TD,(TA)		;PUT IN SKIPA'S PLACE
	SOJLE	TC,FSKPA2	;[614] JUMP IF JUST ONE WORD
	MOVE	TD,1(TB)	;NO, GET 2ND WORD
	MOVEM	TD,1(TA)
FSKPA2:	LDB	TD,[POINT 3,(TB),20]	;[614] GET TARGET OF JRST
	CAIE	TD,AC.TAG##	;[614] IS IT A TAG?
	POPJ	PP,		;[614] NO
	HRRZ	TA,(TB)		;[614] YES, GET VALUE
	PJRST	REFTAG##	;[614] COUNT IT UP
SUBTTL	REFERENCES TO .+N FIXUP

;THIS IS DONE BEFORE ANY OTHER JUMPX OPTIMIZATIONS TO PREVENT
; PROBLEMS CAUSED BY CONDITIONAL JUMPS TO .+N

	PATTERN DOTREF,JUMPX	;PATTERN DOTREF, AFTER THAT DO JUMPX
	TESTMR	GOTOJ		;IS .+N A "JRST"?
	DOIT	DOTRFG		;YES- CHANGE ".+N" TO TARGET OF "JRST"

GOTOJ:	MOVE	TB,(IPI)	;GET IPTAB ENTRY FOR THIS JUMPX GUY
	MOVE	TC,(TB)		;GET 1ST WORD
	TRC	TC,AS.MSC
	TRNE	TC,-1		;MISC ADDRESS TYPE?
	 POPJ	PP,		;NO

	MOVE	TC,1(TB)	;GET NEXT WORD
	TRC	TC,AS.DOT
	TRNE	TC,700000
	 POPJ	PP,		;NOT AS.DOT

	HRRZ	TB,IPI
	ADD	TB,TC		;POINT TO .+N
	CAIL	TB,IPTAB1##	;IN THE BUFFER?
	 JRST	E$GOTJ		;? OPTIMIZER WILL PROBABLY NOT WORK THEN

	MOVE	TC,(TB)		;TC:= IPTAB ENTRY FOR THAT GUY
	LDB	TD,[IP$OP TC]
	CAIE	TD,JRST.	;IS THIS A "JRST"?
	 POPJ	PP,		;NO, DO NOTHING
	JRST	CPOPJ1		;YES


E$GOTJ:	TTCALL	3,[ASCIZ/? REFERENCE TO .+N WHERE N IS TOO LARGE
/]
	JRST	KILL##

;ROUTINE TO CHANGE IT

DOTRFG:	MOVE	TA,(IPI)
	MOVE	TA,1(TA)
	ANDI	TA,77777	;SAVE "N" OF .+N
	ADD	TA,IPI		;POINT TO IT
	MOVE	TB,(TA)
	LDB	TC,[IP$WC TB]	;GET WORD COUNT OF JRST
	CAIE	TC,1		;SKIP IF 1
	 JRST	DOTWC2		;TWO STILL
	DPB	TC,[IP$WC <(IPI)>] ; CHANGE JUMPX WORD COUNT TO 1
	HRRZ	TB,(TB)		;GET ADDRESS PART OF JRST
	MOVE	TC,(IPI)
	HRRM	TB,(TC)
	MOVSI	TB,ASINC
	ANDCAM	TB,(TC)		;TURN OFF INCREMENT BIT
	POPJ	PP,
DOTWC2:	HRRZ	TC,(TB)
	HRRZ	TD,(IPI)	;ADDRESS OF THE JRST
	HRRM	TC,(TD)
	MOVE	TC,1(TB)	;GET 2ND WORD
	MOVEM	TC,1(TD)	;STORE IT
	POPJ	PP,		;DONE
SUBTTL	JUMPX AC,ADDR OPTIMIZATION

;HERE WE LOOK FOR THE JUMPX AC,FOO/JRST FOO2/FOO: SEQUENCE
; WE REVERSE THE SENSE OF THE JUMPX AND GIVE IT THE OTHER
; TAG, THUS REMOVING AN INSTRUCTION AND A TAG.

	PATTERN	JUMPX		;PATTERN NAMED JUMPX, NO BROTHERS
	NOPSKP			;NO PREVIOUS SKIPS
	TEST2	2,%TAG.,%PROC.	;SEE IF THERE IS A TAG OR PROCEDURE NAME
	TEST	1,JRST.		;MAKE SURE JUMPX IS FOLLOWED BY A JRST
	ISIZE	0,1		;BE SURE JUMPX IS ONE WORD
	ISIZE	1,1		;MAKE SURE JRST AFTER JUMPX IS ONE WORD
	TESTMR	JMPXTG		;CALL COMMON ROUTINE TO SE IF SAME TAG
	DOIT	JUMPXC		;CHANGE THE JUMPX


JMPXTG:	;SEE IF THE TAG IN THE JUMPX IS THE SAME AS THE
	; TAG AFTER THE JRST
	HRRZ	TA,	(IPI)		;GET INSTBF ADDR OF JUMP INSTR
	HRRZ	TB,	(TA)		;GET TAG FROM JUMPX INSTR
	HRRZ	TA,	2(IPI)		;GET INSTBF ADDR OF TAG
	HRRZ	TC,	(TA)		;GET THE TAG FROM INSTBF
	CAMN	TB,	TC		;ARE THE TAGS THE SAME?
	AOS		(PP)		;YEP, INCREMENT RETURN
	POPJ	PP,			;NOPE


JUMPXC:	;CHANGE SENSE OF JUMPX AND GIVE IT OTHER LOC
	; ALSO REMOVE TAG IF TAGCOUNT GOES TO ZERO FOR THAT TAG
	MOVE	TA,	1(IPI)		;GET IPTAB ENT OF THE UNNECESSARY JRST
	HRRZ	TA,	(TA)		;GET TAG PART OF JRST
	PUSH	PP,	TA		;SAVE THE LOCATION THAT THE JRST WENT TO
	MOVEI	TA,	1(IPI)		;SET UP ADDR OF JRST TO GO AWAY
	PUSHJ	PP,	DELINS		;DELETE THE JRST

	LDB	TB,	[IP$OP <1(IPI)>]	;GET THE OP CODE OF TAG
	CAIN	TB,	%PROC.		;DONT DEREFERENCE PROCEDURE NAMES
	JRST		RVRJMP		;REVERSE JUMPX, TAG IS OK
	HRRZ	TA,	1(IPI)		;GET ADDR OF TAG NAME
	HRRZ	TA,	(TA)		;GET TAG
	PUSHJ	PP,	DRFTAG		;DE-REFERENCE THE TAG
	JRST		RVRJMP		;NON-ZERO COUNT, ALL IS OK
	MOVEI	TA,	1(IPI)		;GET ADDRESS OF TAG LOC IN IPTAB
	PUSHJ	PP,	DELINS		;REMOVE FROM IPTAB TO ALLOW CASCADE

RVRJMP:	;NOW REVERSE THE SENSE OF THE JUMPX
	;FIRST PUT THE NEW TAG IN RH OF INSTR
	HRRZ	TA,	(IPI)		;GET ADDR IN INSTBF OF JUMPX INSTR
	POP	PP,	TB		;GET BACK THE NEW JUMPX DESTINATION
	HRRM	TB,	(TA)		;PUT IT IN INSTBF

	LDB	TB,	[IP$OP <(IPI)>]	;GET THE OP CODE OF THE INSTR
	CAIL	TB,	JUMP.		;BESURE ITS A JUMP
	CAILE	TB,	JUMPN.		; IN THE PROPER RANGE
	JRST		RVRJER		;ITS NOT A JUMP THAT WE KNOW ABOUT
	SUBI	TB,	JUMP.		;SUBTRACT BASE SO WE CAN COMPLEMENT
	TRC	TB,	7		;REVERSE SENSE
	ADDI	TB,	JUMP.		;ADD IN THE BASE ADDRESS
	DPB	TB,	[IP$OP <(IPI)>]	;REFLECT CHANGE IN THE IPTAB
					;REMEMBER THAT TA HAS ADDR OF JUMPX IN INSTBF
	DPB	TB,	[POINT 7,(TA),8]	;PUT NEW OP CODE IN PLACE
	POPJ	PP,			;RETURN HOME

RVRJER:	;ERROR OF SOME SORT IN REVERSING SENSE OF JUMPX
	TTCALL 3,[ASCIZ/? JUMPX OPTIMIZATION DID NOT RECOGNIZE OP CODE
/]
	PJRST	KILL##
SUBTTL	CAIXX AC,0 OPTIMIZATIONS

;HERE WE LOOK AT THE ADDRESS PORTION OF THE CAI AND SEE IF ITS
; ZERO.  IF IT IS, WE KNOW WE CAN MAKE IT INTO A JUMPXX AC, ADDR
; WHEN THE CAI IS FOLLOWED BY A JRST.  THIS ALSO ALLOWS FURTHER
; OPTIMIZATIONS WHEN THE JRST IS OVER A SECOND JRST.

	PATTERN	CAIXX,CNDSKP	;CAIXX PATTERN, BROTHER IS CNDSKP
	NOPSKP			;NO PREVIOUS SKIPS (FOR SAFETY)
	ISIZE	0,1		;THE CAIXX BETTER BE ONE WORD FOR US TO DO IT
	TESTMR	ISIT0		;IS IT CAIXX AC,0
	TEST	1,JRST.		;IS IT FOLLOWED BY A JRST
	ISIZE	1,1		;BE SURE JRST IS ONE WORD IN INSTBF
	DOIT	CAIXXC		;CHANGE THE CAI TO A JUMP

ISIT0:	;SEE IF THE OPERAND HALF OF THE INSTR IS A ZERO
	HRRZ	TA,	(IPI)		;GET INSTBF ADDR
	LDB	TB,	[POINT 23,(TA),35]	;GET AC FIELD, INDIRECT BIT AND ADDR
	JUMPE	TB,	CPOPJ1		;INSTR IS COMPARE IMMEDIATE ZERO
	POPJ	PP,			;COMMON RETURN


CAIXXC:	;CHANGE THE COMPARE TO A JUMP
	; AND DELETE THE FOLLOWING JRST
	LDB	TA,	[IP$OP <(IPI)>]	;GET OP CODE OF THE CAI
	SUBI	TA,	CAM.		;SUBTRACT BASE
	LSH	TA,	-1		;DIVIDE BY TWO TO GET JUMP OFFSET
	TRC	TA,	7		;REVERSE SENSE OF SKIP
					; (SO THAT CORRECT PATH IS TAKEN)
	ADDI	TA,	JUMP.		;MAKE IT A JUMP OF THE SAME SORT
	DPB	TA,	[IP$OP <(IPI)>]	;UPDATE THE IPTAB
	HRRZ	TB,	(IPI)		;GET ADDR IN THE INSTBF
	DPB	TA,	[POINT 7,(TB),8]	;STORE JUMP OP CODE IN INSTBF
	HRRZ	TA,	1(IPI)		;GET ADDR OF THE JRST AFTER CAIX
	HRRZ	TA,	(TA)		;GET THE TAG THAT JRST WENT TO
	HRRM	TA,	(TB)		;STORE TAG IN OLD CAIX, NOW JUMPX

	MOVEI	TA,	1(IPI)		;NOW DELETE THE UNNEEDED JRST
	PJRST		DELINS		; AND GO HOME
SUBTTL	JRSTXX OPTIMIZATION.  REMOVE CODE THAT CANT BE REACHED.

;HERE WE LOOK FOR A JRST PRECEEDED BY A NON-SKIP INSTRUCTION
; AND FOLLOWED BY A NON-TAG.  THE INSTRUCTIONS FOLLOWING THE JRST
; CANNOT BE REACHED AND SO WILL BE REMOVED.  ATTENTION NEEDS TO BE
; PAID TO THE INSTRUCTION DELETED, FOR IF IT IS A JRST TO A TAG,
; THAT TAG NEEDS TO BE DE-REFERENCED.  THE ONLY INSTRUCTIONS THAT
; ACCESS TAGS ARE THE JUMPXX'S AND JRST.

	PATTERN	JRSTXX,JRSTZZ	;ALL OTHERS REQUIRE NO PREV SKIP
	NOPSKP			;NO PREVIOUS SKIPS

	PATTERN	,JRSTYY		;BROTHER IS JRSTYY
	TESTMR	NOPSK1		;NO PREVIOUS SKIPS OF SKIP3 VARIETY
	TESTMR	CANDEL,1	;CHECK THAT NEXT IS NOT TAG AND CAN BE DELETED
	DOIT	JRSTXC		;CHANGE THE JRSTS

CANDEL:	;CHECK THAT SPECIFIED IPTAB ENT IS NOT TAG
	; AND THAT IT IS THERE (NON-ZERO) AND TOUCHABLE
	HRRE	TA,	TA		;GET TA SET UP TO CORRECT FORM
	ADD	TA,	IPI		;GET INDEX INTO TABLE
	SKIPG	TA,	(TA)		;TEST FOR NON-ZERO OR TOUCHABLE
	POPJ	PP,			;ZERO, OR NO TOUCH, THUS NOT THERE
	LDB	TA,	[IP$OP TA]	;GET OP CODE OF ARGUMENT
	CAIE	TA,	%PROC.		;SEE IF PROCEDURE NAME
	CAIN	TA,	%TAG.		;SEE IF TAG NAME
	POPJ	PP,			;A TAG OR PROC, RETURN
	JRST	CPOPJ1			;NOT ONE OF THE TWO, INCR RETURN


NOTTAG:	;CHECK THAT SPECIFIED IPTAB ENT IS NOT TAG
	; AND THAT IT IS THERE (NON-ZERO)
	HRRE	TA,	TA		;GET TA SET UP TO CORRECT FORM
	ADD	TA,	IPI		;GET INDEX INTO TABLE
	SKIPN	TA,	(TA)		;TEST FOR NON-ZERO
	POPJ	PP,			;ZERO, THUS NOT THERE
	LDB	TA,	[IP$OP TA]	;GET OP CODE OF ARGUMENT
	CAIE	TA,	%TAG.		;SEE IF TAG NAME
	AOS	(PP)			;NOT A TAG, INCR RETURN
	POPJ	PP,			;A TAG, RETURN


NOPSK1:	;NO PREVIOUS SKIP OF SPECIAL VARIETY.
	; THE INSTRUCTION TWO BEFORE BETTER NOT BE A
	; "CAN SKIP 2".
	SKIPLE	TA,	-3(IPI)		;GET THE ENTRY, SKIP IF NO PROBLEM
	TLNN	TA,	IP%SK2		;SKIP IF INSTR CAN SKIP 2
	AOS		(PP)		;INCREMENT RETURN.  NO SKIP FOUND
	POPJ	PP,			;GO HOME


JRSTXC:	;DELETE FOLLOWING INSTRUCION AS UNNECESSARY
	; TAKE CARE TO CHECK THAT TAGS ARE DEREFERENCED

					;GET IPTAB ENT OF INSTR TO DELETE
	SKIPN	TA,	1(IPI)		; SKIP IF THERE IS AN INSTR
	POPJ	PP,			;NO MORE INSTRS TO DELETE, GO HOME
	LDB	TA,	[IP$OP TA]	;GET OP CODE OF INSTR BEING REMOVED
	CAIE	TA,	%TAG.		;FOUND TAG OR
	CAIN	TA,	%PROC.		; FOUND PROC,
	POPJ	PP,			; STOP DELETING

	CAIN	TA,	%HDR.		;[607] HEADER COULD BE START OF LITERALS
	 JRST		CHKSLT		;[607] GO CHECK IT OUT
	CAIL	TA,	JUMP.		;TEST FOR ONE OF THE RANGE OF TRANSFERS
	CAILE	TA,	JRST.		;
	JRST		JRSTDL		;JRSTXX DELETE INSTR (NO TAG TO WORRY)
	HRRZ	TA,	1(IPI)		;GET ADDR IN INSTBF
	HRRZ	TA,	(TA)		;GET THE TAG REFERENCED
	TRC	TA,	AS.TAG		;SET UP TO TEST IF FLAG
	TRNN	TA,	700000		;SKIP IF TAG
	PUSHJ	PP,	DRFTAG		;DE REFERENCE THE TAG
	  JFCL				;DONT CARE ABOUT SKIP RETURN
JRSTDL:	MOVEI	TA,	1(IPI)		;GET IPTAB ADDR OF INSTR TO DELETE
	PUSHJ	PP,	DELINS		;DELETE IT
	JRST		JRSTXC		;LOOK FOR MORE TO DELETE

CHKSLT:	HRRZ	TA,	1(IPI)		;[607] GET ADDRESS OF THIS THING
	MOVE	TB,	(TA)		;[607] GET FIRST WORD
	CAME	TB,[710001,,AS.MSC]	;[607]  RELOC?
	 JRST		JRSTDL		;[607] NO, JUST DELETE THIS THING
	POPJ	PP,			;[607] REACHED LITERALS--STOP DELETING
SUBTTL	JRST TAG OPTIMIZATION WHERE TAG IS .+1.

;HERE WE LOOK FOR A JRST FOLLOWED BY A TAG.  WE SEE IF THE TAGS ARE THE
; SAME.  IF SO, THE JRST CAN BE REMOVED.  WE ASSURE THAT NOBODY GETS
; HURT BY DEMANDING THAT THE FIRST JRST NOT BE TAGGED.

	PATTERN	JRSTYY,JRSTZZ		;JRST RECOGNITION PATTERN
	TEST2	1,%TAG.,%PROC.	;SEE IF NEXT IS TAG OR PARAGRAPH NAME
	ISIZE	0,1		;BE SURE THE JRST IS ONE WORD
	TESTMR	SAMTAG		;TEST THAT THE JRST IS TO THE TAG
	TESTMR	NOTTAG,-1	;CHECK THAT PREVIOUS IS NOT A TAG
	DOIT	JRSTYC		;CHANGE IT.


SAMTAG:	;TEST THAT THE TAG OF THE JRST IS THE SAME AS
	; TAG FOLLOWING
	HRRZ	TA,	(IPI)	;GET INSTBF ADDR
	HRRZ	TB,	1(IPI)	; OF THE JRST TAG AND THE TAG
	HRRZ	TA,	(TA)	;GET ACTUAL TAG FROM JRST
	HRRZ	TB,	(TB)	; AND FROM TAG IN INSTBF
	CAMN	TA,	TB	;COMPARE TO SEE IF EQUAL
	AOS		(PP)	;EQUAL, SKIP RETURN
	POPJ	PP,		;RETURN

JRSTYC:	;REMOVE THE JRST, AND DEREFERENCE THE TAG
	MOVE	TA,	IPI		;GET ADDR OF FIRST ENTRY
	PUSHJ	PP,	DELINS		;DELETE THAT INSTR
	LDB	TA,	[IP$OP <(IPI)>]	;GET OP CODE OF TAG
	CAIE	TA,	%TAG.		;SKIP IF TAG
	POPJ	PP,			;NOT TAG, ALL DONE
	HRRZ	TA,	(IPI)		;GET INSTBF ADDR OF TAG
	HRRZ	TA,	(TA)		;GET THE TAG
	PUSHJ	PP,	DRFTAG		;DEREFERENCE THE TAG
	POPJ	PP,			;IF NON-ZERO REFERENCE COUNT, RETURN
	MOVE	TA,	IPI		;DELETE THE TAG FROM BUFFER
	PJRST		DELINS		;AND RETURN TO CALLER
SUBTTL	JRST TAG WHERE TAG IS .+2, NON-SKIP, TAG, INSTRUCTION

;EXAMPLE PATTERN:
;	JRST TAG
;	JRST FOO
;TAG:	AOS/MOVE	MEM
;	..

;CHANGE TO:
;TAG:	AOSA/SKIPA	MEM
;	JRST FOO
; (MOVE UP TAG:, DELETE "JRST", DE-REF TAG, MOVE UP "AOS" & CHANGE TO "AOSA")


	PATTERN  JRSTZZ		;LAST "JRST" PATTERN
	TEST	1,JRST.		;IS NEXT A JRST?
	TEST	2,%TAG.		;IS NEXT A TAG
	TESTMR	JRSTCK		;DOES "JRST" GO TO THE TAG?
	TESTMR	MVAOS		;CAN WE MAKE INST AT .+3 SKIPPABLE?
	DOIT	JRSMA		; YES!

JRSMA:	LDB	TA,[IP$OP <3(IPI)>] ;WHICH OPCODE IS IT?
	SETZ	TE,
	 CAIN	TA,MOV
	MOVEI	TE,SKIPA.	;CHANGE MOV TO SKIPA.
	 CAIN	TA,AOS.
	MOVEI	TE,AOSA.	;CHANGE AOS TO AOSA
	JUMPE	TE,E$MVAO	;? DON'T KNOW ABOUT THIS PATTERN
	PUSH	PP,TE
	PUSHJ	PP,MOVTAG	;MOVE TAG STUFF
	POP	PP,TE

;HERE WITH NEW OPCODE TO STORE OVER THE OLD
JRSPUT:	DPB	TE,[IP$OP <1(IPI)>] ;STORE IN IPTAB
	HRRZ	TA,1(IPI)	;POINT TO INSTBF ENTRY
	DPB	TE,[POINT 7,(TA),8] ;STORE IN INSTBF ENTRY
	POPJ	PP,

MOVTAG:	MOVE	TA,2(IPI)	;GET IPTAB WORD FOR TAG
	EXCH	TA,(IPI)
	EXCH	TA,1(IPI)
	MOVEM	TA,2(IPI)	;MOVE EVERYTHING DOWN...

;NOW CODE LOOKS LIKE:
;	%TAG:
;	JRST %TAG
;	<NOSKIP>
;	AOS	MEM
	HRRZ	TA,1(IPI)
	HRRZ	TA,(TA)		;THIS TAG
	PUSHJ	PP,DRFTAG##
	 JFCL			;IF COUNT REACHES 0, TAG WILL BE DELETED
				; IN A CASCADE OPTIMIZATION

;SKPA2 OPTIMIZATION JOINS CODE HERE
; FOR SKIPA OPT. CODE NOW LOOKS LIKE:
;	%TAG:
;	SKIPA
;	<NOSKIP>
;	AOS	MEM
JOINJT:	MOVEI	TA,1(IPI)	;GET RID OF "JRST"
	PUSHJ	PP,DELINS
	MOVE	TA,2(IPI)	;POINT TO LAST INSTRUCTION
	EXCH	TA,1(IPI)
	MOVEM	TA,2(IPI)

;NOW CODE LOOKS LIKE:
;	%TAG:
;	AOS	MEM
;	<NOSKIP>
;
; LAST THING TO DO-- TURN ON SKIP BITS IN IPTAB ENTRY
	MOVSI	TA,IP%SKA	;IT SKIPS ALWAYS NOW
	IORM	TA,1(IPI)	;TURN ON IPTAB BITS
	POPJ	PP,		;NOW THE INSTRUCTION CAN BE CHANGED

;NOTSKP - SEE IF SPECIFIED INSTRUCTION SKIPS
NOTSKP:	HRRE	TA,TA
	ADD	TA,IPI		;GET INDEX INTO IPTAB
	SKIPG	TA,(TA)		;SKIP IF THERE (IF CAN'T TOUCH, IT MIGHT
	 POPJ	PP,		; BE FUNNY, SO DON'T MATCH IN THAT CASE EITHER)
	LDB	TA,[IP$SKP TA]	;GET SKIP BITS
	JUMPE	TA,CPOPJ1	;NONE ON, SKIP RETURN
	POPJ	PP,

;SKIP IF THING AT .+1 SKIPS
TAKPC1:	LDB	TA,[IP$OP <1(IPI)>]
	CAIE	TA,%TAG.
	CAIN	TA,%PROC.
	 POPJ	PP,
	JRST	CPOPJ1

;CHECK .+3 TO SEE IF THIS INSTRUCTION CAN BE CONVERTED INTO A SKIPPABLE
; KIND
MVAOS:	LDB	TA,[IP$OP <3(IPI)>]
	CAIN	TA,MOV
	 JRST	D3MOV
	CAIN	TA,AOS.
	 AOS	(PP)		;IT'S OK
	POPJ	PP,

D3MOV:	LDB	TA,[IP$AC <3(IPI)>] ;GET AC OF THE MOVE
	JUMPN	TA,CPOPJ1	;MUST BE NON-ZERO
	POPJ	PP,

JRSTCK:	MOVE	TA,(IPI)	;IPTAB ENTRY OF THE JRST
	LDB	TB,[IP$WC TA]
	SOJN	TB,CPOPJ	;WORD COUNT MUST BE 1
	HRRZ	TB,(TA)		;GET TARGET OF THE "JRST"
	MOVE	TA,2(IPI)
	HRRZ	TC,(TA)		;GET THE TAG FROM INSTBF
	CAME	TC,TB		;ARE THEY THE SAME?
	 POPJ	PP,		;NO
	ANDI	TC,77777
	ADD	TC,TAGLOC##	;POINT TO TAGTAB ENTRY
	SKIPL	(TC)		;NO INDIRECTING ALLOWED
	 AOS	(PP)		;ELSE OK
	POPJ	PP,

SUBTTL	SKIPA / NON-SKIP /TAG /INSTR.

;THIS PATTERN IS SIMILAR TO THE ONE ON THE PRECEEDING PAGE.
; THE ONLY DIFFERENCE IS INSTEAD OF A JRST %TAG AT .+2, WE HAVE
; A SKIPA.

	PATTERN	SKPA2
	TEST	2,%TAG.
	TESTMR	NOTSKP,1	;NEXT IS ANY NON-SKIP
	TESTMR	MVAOS		;MOVE OR AOS AT .+3?
	TESTMR	TAKPC1		;MAKE SURE THING AT .+1 TAKES UP A LOCATION
	DOIT	SKAMA		;OK


SKAMA:	LDB	TA,[IP$OP <3(IPI)>] ;WHAT IS THE INSTRUCTION TO MAKE SKPABLE?
	SETZ	TE,
	 CAIN	TA,MOV
	MOVEI	TE,SKIPA.
	CAIN	TA,AOS.
	MOVEI	TE,AOSA.
	JUMPE	TE,E$MVAO	;MVAOS SKIPPED FOR SOMETHING WE DON'T KNOW ABOUT
	PUSH	PP,TE		;SAVE NEW OPCODE
	MOVE	TA,2(IPI)	;GET IPTAB WORD FOR TAG
	EXCH	TA,(IPI)
	EXCH	TA,1(IPI)	;MOVE EVERYTHING DOWN..
	MOVEM	TA,2(IPI)
	PUSHJ	PP,JOINJT	;FINISH SHUFFLING OPCODES
	POP	PP,TE		;RESTORE OPCODE
	PJRST	JRSPUT		;STORE OPCODE FROM TE


E$MVAO:	TTCALL	3,[ASCIZ/? PMATCH @E$MVAO: INTERNAL COMPILER ERROR
/]
	JRST	KILL		;DIE OFF
SUBTTL	SOS OPTIMIZATIONS

; PATTERN:
;	SOSXX	AC,MEM
;	JRST	TAG
;	INSTR
;TAG:	...
;
; REPLACE WITH:
;	SOSNXX	AC,MEM
;	INSTR
;TAG:	...

SGPAT:	SKIPA	TB,[SOSLE.]
SGEPAT:	MOVEI	TB,SOSL.
	JRST	SOSPAT
SLPAT:	SKIPA	TB,[SOSGE.]
SLEPAT:	MOVEI	TB,SOSG.

SOSPAT:	MOVEM	TB,OTEMP##	;SAVE NEW OPCODE IF PATTERN MATCHES
	MOVE	TA,1(IPI)	;POINT TO NEXT INSTRUCTION
	LDB	TC,[IP$OP TA]	; MUST BE A "JRST"
	CAIE	TC,JRST.
	 POPJ	PP,
	HRRZ	TC,(TA)
	HRRZM	TC,OTEMP+1	;SAVE TARGET IN OTEMP+1
	LDB	TC,[IP$OP <2(IPI)>] ;THEN CAN BE ANYTHING EXCEPT A TAG
	CAIE	TC,%TAG.
	CAIN	TC,%PROC.	;OR PARA
	 POPJ	PP,
	LDB	TC,[IP$OP <3(IPI)>] ;AND NEXT GUY MUST BE
	CAIE	TC,%TAG.
	CAIN	TC,%PROC.
	 CAIA			;OH YEAH!
	  POPJ	PP,
	MOVE	TA,3(IPI)
	HRRZ	TC,(TA)
	CAME	TC,OTEMP+1	;SAME THING AS TARGET OF JRST ?
	 POPJ	PP,		;NO

	AOS	(PP)		;YES-- PATTERN MATCHES!
	MOVEI	TA,1(IPI)	;DELETE THE JRST
	PUSHJ	PP,DELINS
	HRRZ	TA,OTEMP+1
	TRC	TA,AS.TAG	;MAKE SURE IT'S A TAG
	TRNN	TA,700000	; BEFORE WE DE-REF IT
	PUSHJ	PP,DRFTAG	;DE-REFERENCE THE TAG
	 JFCL			; (IT WILL GET DELETED LATER)

	MOVE	TB,OTEMP	;GET NEW OPCODE TO STORE
	DPB	TB,[IP$OP <(IPI)>] ;STORE IN IPTAB ENTRY
	MOVE	TA,(IPI)
	DPB	TB,[POINT 7,(TA),8] ;AND IN INSTBF ENTRY
	POPJ	PP,		;DONE!
SUBTTL	SUBI/ADDI OPTIMIZATION

; THIS HAPPENS OCCASIONALLY IN SUBSCRIPTING A COMP-ITEM.
;THE SUBI AC,1 IS FOLLOWED BY ADDI AC,DATA-NAME.
;
;CHANGE TO:
;	ADDI AC,DATA-NAME - 1

	PATTERN SBIPAT,SBADPT	;SUBI PATTERN
	TEST	1,ADDI.		;FOLLOWED BY AN ADDI
	TESTMR	SBI1		; SUBI AC,1?
	LDB	TA,[IP$AC <(IPI)>]
	LDB	TB,[IP$AC <1(IPI)>]
	CAME	TA,TB		;SAME AC?
	 POPJ	PP,		;NO
	TESTMR	ADIOK		;IS ADDI ADDRESS OK TO CHANGE?
	DOIT	SBIOPT		;GO FIX ADDI, DELETE SUBI

;SKIP IF THIS INSTRUCTION'S ADDRESS IS CONSTANT "1"
SBI1:	MOVE	TA,(IPI)
	HRRZ	TB,(TA)		;GET ADDRESS
	CAIN	TB,1
	 AOS	(PP)		;IT IS 1, TAKE THE SKIP RETURN
	POPJ	PP,

ADIOK:	MOVE	TA,1(IPI)	;GET ADDI CODE
	HRRZ	TB,(TA)		;GET 1ST ADDRESS
	TRC	TB,AS.DAT	;A DATA NAME?
	TRNE	TB,700000
	 POPJ	PP,		;NO--DON'T TRY
	LDB	TE,[IP$WC TA]
	SOJE	TE,CPOPJ1	;IF NO INCREMENT, FINE
	MOVE	TB,1(TA)	;GET INCR. WORD
	CAIG	TB,77777	;BETTER BE A SMALL CONSTANT
	 AOS	(PP)		;YES--OK
	POPJ	PP,		;NO

SBIOPT:	MOVE	TA,1(IPI)	;TA IS IPTAB WORD FOR ADDI
	LDB	TB,[IP$WC TA] 	;GET WORD COUNT
	CAIN	TB,2		;DOES IT ALREADY HAVE AN INCREMENT?
	 JRST	SBIOP1		;YES-- SUBTRACT 1 FROM IT
	HRRZ	TA,(TA)		;GET ADDRESS
	PUSHJ	PP,LNKSET##
	LDB	TE,DA.LKS##	;SEE IF ITS IN LINKAGE SECTION
	JUMPN	TE,SBIOP3	;YES, BE VERY CAREFUL
SBIOP0:	MOVEI	TA,1(IPI)
	PUSHJ	PP,ADDWD	;GET AN INCREMENT WORD
	MOVE	TA,1(IPI)	;GET NEW IPTAB WORD FOR ADDI
	MOVSI	TB,-1		;GET A -1 INCREMENT
	MOVEM	TB,1(TA)	;PUT IT IN THE INCREMENT WORD
	MOVSI	TB,ASINC	;REMEMBER THE INCREMENT!
	IORM	TB,(TA)
SBIOPD:	MOVEI	TA,(IPI)
	PJRST	DELINS		;DELETE THE SUBI, THEN RETURN

SBIOP1:	MOVE	TB,1(TA)	;GET OLD INCREMENT WORD
	SOJE	TB,SBIOP2	;SUBTRACT 1, JUMP IF IT REACHED 0
	MOVEM	TB,1(TA)	;NO--STORE OLD ONE BACK
	JRST	SBIOPD		;DONE, GO DELETE THE SUBI

SBIOP2:	MOVEI	TE,1		;GET A SMALLER WORD COUNT
	DPB	TE,[IP$WC <1(IPI)>] ;STORE IN IPTAB
	MOVSI	TE,ASINC	;TURN OFF INC BIT
	ANDCAM	TE,(TA)		; IN INSTBF WORD
	SETZM	1(TA)		;STORE A 0 IN UNUSED WORD FOR THE HELL OF IT
	JRST	SBIOPD		;THEN GO DELETE THE SUBI

;HERE IF DATA NAME IS IN LINKAGE SECTION

SBIOP3:	LDB	TE,DA.LOC##	;GET THE RUN-TIME ADDRESS
	JUMPE	TE,SBIOP4	;OFFSET = 0
	SOJG	TE,SBIOP5	;OFFSET = 2 OR MORE
				;OFFSET = 1

;IF OFFSET IS 1 JUST DELETE SUBI AND ADDI AS NET RESULT IS 0
	MOVEI	TA,1(IPI)	
	PUSHJ	PP,DELINS	;DELETE ADDI
	MOVEI	TA,0(IPI)
	PJRST	DELINS		;DELETE SUBI

SBIOP4:	MOVEI	TA,1(IPI)	;DELETE THE ADDI
	PUSHJ	PP,DELINS
	JRST	SBLKPT		;TRY FOR MORE


;HERE IF OFFSET > 1

SBIOP5:	PUSHJ	PP,SBIOP0	;DELETE SUBI AC,1
;	JRST	SBLKPT		;TRY FOR MORE
;WE SHOULD NOW BE ABLE TO DO A FURTHER OPTIMIZATION

;PATTERN
;	SUBI	12,1
;	ADD	12,%PARAM+N
;	OP	AC,(12)
;
;REPLACE WITH
;
;	ADD	12,%PARAM+N
;	OP	AC,-1(12)

;CODE IS SIMILAR TO THAT AT LKGPAT

	PATTERN	SBLKPT
	TEST	1,AD
	SKIPG	TA,2(IPI)	;MAKE SURE NEXT INST IS IN THE TABLE
	POPJ	PP,		;NO
	LDB	TA,[IP$OP <2(IPI)>]
	CAILE	TA,XTND.	;IS IT A VALID INST.
	POPJ	PP,		;NO
	MOVE	TA,0(IPI)	;SUBI
	MOVE	TB,1(IPI)	;ADD
	LDB	TD,[IP$AC TA]
	LDB	TE,[IP$AC TB]
	CAIN	TD,12		;ARE BOTH ACC 12
	CAIE	TE,12		;...
	POPJ	PP,		;NO
	LDB	TD,[POINT 3,(TB),20]	;GET CODE FOR ADD
	CAIE	TD,AC.MSC##	;IS IT MISC. (TO BE FOLLOWED BY PARAM)
	POPJ	PP,		;NO
	LDB	TD,[IP$WC TB]	;BETTER BE 2 WORDS
	SOJE	TD,CPOPJ	;NO
	LDB	TD,[POINT 3,1(TB),20]	;GET CODE
	CAIE	TD,AC.PAR##	;BETTER BE %PARAM
	POPJ	PP,		;NO
	MOVE	TA,2(IPI)	;POINT TO <OP AC,(12)>
	MOVE	TE,(TA)		;GET INST.
	TLZ	TE,377760	;LEAVE INDIRECT AND INDEX FIELDS
	CAME	TE,[Z 0(12)]	;ONLY VALID ADDRESS
	POPJ	PP,		;NO
				;FOUND IT

	MOVEI	TA,2(IPI)	;POINT TO POINTER TO <OP AC,0(12)>
	PUSHJ	PP,ADDWD	;CONVERT TO 2 WORDS
	MOVE	TA,2(IPI)	;RELOAD ADDRESS
	MOVE	TB,(IPI)	;POINT TO ADDI OR SUBI
	HRRZ	TE,(TB)		;GET ADDRESS
	CAIE	TE,1		;WAS IT SUBI 1
	JRST	SBIOP6		;NO
	MOVE	TE,[ASINC,,AS.CNB]
	IORM	TE,0(TA)	;FIXUP INST
	MOVEI	TE,-1
	MOVEM	TE,1(TA)	;AND INCREMENT (I.E. -1)
	MOVEI	TA,0(IPI)	;NOW DELETE SUBI
	PJRST	DELINS

SBIOP6:	HRLI	TE,ASINC	;TWO WORDS  PLUS ADDRESS
	IORM	TE,0(TA)	;FIXUP INST
	MOVE	TE,1(TB)	;COPY SECOND WORD
	MOVEM	TE,1(TA)	;...
	MOVEI	TA,0(IPI)	;NOW DELETE ADDI
	PJRST	DELINS
;PATTERN
;	<NO PREV SKIP>
;	ADDI	AC,CONST-1
;	SUBI	AC,CONST-2
;
;REPLACE WITH
;	ADDI	AC,CONST-1 - CONST-2
;OR
;	SUBI	AC,CONST-2 - CONST-1

	PATTERN	SBADPT
	NOPSKP			;NO PREVIOUS SKIP
	TEST	1,ADDI.		;FOLLOWED BY ADDI
	LDB	TA,[IP$AC <(IPI)>]
	LDB	TB,[IP$AC <1(IPI)>]
	CAME	TA,TB		;SAME AC?
	%%GOTO			;NO
	MOVE	TA,0(IPI)	;GET SUBI
	MOVE	TB,1(IPI)	;GET ADDI
	LDB	TE,[IP$WC TA]
	SOJN	TE,%GO2AD	;GIVE UP IF NOT SIMPLE CONSTANT
	LDB	TE,[IP$WC TB]
	SOJN	TE,%GO2AD	;SAME FOR ADDI
	HRRZ	TC,(TA)		;GET ADDRESS
	HRRZ	TD,(TB)		;...
	TRNN	TC,700000	;MAKE SURE ITS A CONSTANT
	TRNE	TD,700000	;...
	%%GOTO			;NO
	DOIT			;OK, FOUND A MATCH

	SUB	TC,TD		;CONST-1 - CONST-2
	JUMPE	TC,SBAD0	;CONST-1 = CONST-2, DELETE BOTH
	JUMPL	TC,SBAD1	;CONST-1 < CONST-2
	HRRM	TC,(TA)		;STORE CONST-1 - CONST-2
	MOVEI	TA,1(IPI)
	PJRST	DELINS		;DELETE ADDI

SBAD0:	MOVEI	TA,1(IPI)
	PUSHJ	PP,DELINS	;DELETE ADDI
	MOVEI	TA,0(IPI)
	PJRST	DELINS		;DELETE SUBI

SBAD1:	MOVM	TC,TC		;GET CONST-2 - CONST-1
	HRRM	TC,(TB)		;STORE IT
	MOVEI	TA,0(IPI)
	PJRST	DELINS		;DELETE SUBI
SUBTTL	SKIPL OPTIMIZATION

; THIS OPTIMIZATION LOOKS FOR OBVIOUSLY UNNECESSARY CODE FOR "ROUNDING..".
;THE CODE IS UNNECESSARY IF THE RESULT IS GUARANTEED TO BE POSITIVE.

;PATTERN:
;	MOVM	0,DATA-1
;	MOVM	2,DATA-2
;	IMUL	0,2
;	SKIPL	0
;	SKIPA	4,%LIT+N
;	MOVN	4,%LIT+N
;	ADD	0,4
;
;REPLACE WITH:
;	MOVM	0,DATA-1
;	MOVM	2,DATA-2
;	IMUL	0,2 / ADD 0,2
;	ADD	0,%LIT+N

	PATTERN	SKLPAT,CNDSKP
	TEST2	-1,IMUL.,AD
	TEST	1,SKIPA.
	TEST	2,MOVN.
	TEST	3,AD
	TEST	-2,MOVM.
	TEST	-3,MOVM.
; (*) CLOSE ENOUGH
	DOIT

	MOVE	TA,1(IPI)	;TA= IPTAB WORD FOR SKIPA
	LDB	TB,[IP$WC TA]
	SETZ	TD,		;ASSUME NO INCREMENT
	HRRZ	TC,(TA)		;TC= 1ST PART OF ADDRESS
	CAIN	TB,2
	MOVE	TD,1(TA)	;TD= INCREMENT, IF ANY

	MOVEM	TC,OTEMP
	MOVEM	TD,OTEMP+1
;
; DELETE THE UNNECESSARY INSTRUCTIONS
;
	MOVEI	TA,2(IPI)
	PUSHJ	PP,DELINS
	MOVEI	TA,1(IPI)
	PUSHJ	PP,DELINS
	MOVEI	TA,(IPI)
	PUSHJ	PP,DELINS
;
; NOW, IPI POINTS TO THE "ADD"
;
	MOVEI	TA,(IPI)	;POINT TO THE "ADD"
	LDB	TB,[IP$WC <(IPI)>] ;GET WORD COUNT OF IT NOW
	CAIE	TB,2		;IF NOT 2
	SKIPN	OTEMP+1		; AND THERE IS AN INCREMENT
	 CAIA
	PUSHJ	PP,ADDWD	;GET ANOTHER WORD FOR IT
	MOVEI	TB,2		;GET A WORD COUNT
	SKIPN	OTEMP+1
	MOVEI	TB,1
	DPB	TB,[IP$WC <(IPI)>]  ;STORE IN IPTAB ENTRY
	MOVE	TA,(IPI)	;TA POINTS TO INSTRUCTION
	HRRZ	TC,OTEMP	;FIRST PART OF ADDRESS
	HRRM	TC,(TA)
	SOJE	TB,SKLA1	;GO FINISH IF WORD COUNT = 1
	MOVE	TC,OTEMP+1	;2ND PART OF ADDRESS
	MOVEM	TC,1(TA)
	MOVSI	TC,ASINC	;GET INCREMENT FLAG
	IORM	TC,(TA)		;STORE IT
	POPJ	PP,		;AND DONE

SKLA1:	MOVSI	TC,ASINC	;JUST ONE WORD, CLEAR INCR FLAG IF SET
	ANDCAM	TC,(TA)
	POPJ	PP,		;AND DONE
SUBTTL	HRRI 11,.+4 OPTIMIZATION

;THIS PATTERN IS GENERATED BY THE PERFORM VERB.
; WE WANT TO CATCH THE HRRI .+N THAT HAS A JRST AT .+N

	PATTERN	HRRIXX		;HRRI PATTERN, NO BROTHER
	TEST	1,PUSH.		;FOLLOWED BY A PUSH
	ISIZE	0,2		;BETTER BE TWO WORD HRRI (.+N)
	TESTMR	HRRICK		;CHECK THAT ITS A HRRI OF .+N
				; AND THAT THERE IS A JRST AT .+N
	DOIT	HRRIXC		;CHANGE THE CODE TO DO HRRI OF LABEL
				; AND REMOVE THE JRST

HRRICK:	;CHECK THAT THE HRRI IS OF .+N
	HRRZ	TB,	(IPI)		;GET INSTBF ADDR OF INSTRUCTION
	MOVE	TA,	(TB)		;GET FIRST WORD FROM BUFFER
	TLNN	TA,	ASINC		;SEE IF INCOMPLETE BIT IS SET FOR ENTRY
	POPJ	PP,			;RETURN IF NOT
	TRC	TA,	AS.MSC		;SEE IF MISC ENTRY
	TRNE	TA,	-1		; DO ACTUAL TEST
	POPJ	PP,			;NOT WHAT WE THINK, QUIT

	MOVE	TA,	1(TB)		;GET SECOND WORD FROM INSTBF
	TRC	TA,	AS.DOT		;SEE IF ITS A DOT PLUS INCR
	TRNE	TA,	700000		; DO ACTUAL TEST
	POPJ	PP,			;NOT DOT PLUS INCR, GO HOME
	ANDI	TA,	077777		;GET ONLY INCR BITS
	ADD	TA,	IPI		;GET IPTAB ADDR OF THE INSTR AT .+N
	SKIPG	TA,	(TA)		;GET ENTRY, TEST IF TOUCHABLE
	POPJ	PP,			;NOT, OR ITS ZERO
	LDB	TA,	[IP$OP TA]	;GET OP CODE OF THAT INSTR
	CAIN	TA,	JRST.		;SEE IF ITS A TRANSFER
	AOS		(PP)		;YEP, DO SKIP RETURN
	POPJ	PP,			;GO HOME

HRRIXC:	;THE TESTS HAVE PASSED FOR A HRRI .+N THAT CONTAINS A JRST.
	; MAKE THE HRRI TAKE THE JRST ADDRS AS ITS ADDRS
	HRRZ	TB,	(IPI)		;GET INSTBF ADDR OF THE HRRI
	HRRZ	TA,	1(TB)		;GET THE AS.DOT+N INTO AN AC
	ANDI	TA,	077777		;REMOVE FLAGS (THE AS.DOT)
	ADD	TA,	IPI		;GET IPTAB ADDR OF THE JRST
	LDB	TD,	[IP$WC <(TA)>]	;GET WORD COUNT OF THE JRST
	SOJN	TD,	HRRIXD		;SPECIAL CASE IF TOO LONG FOR EASE
	HRRZ	TC,	(TA)		;GET INSTBF ADDR OF THE JRST
	HRRZ	TC,	(TC)		;GET TAG (OR PROC) SPECIFIED IN JRST
	HRRM	TC,	(TB)		;PUT TAG IN RH OF THE HRRI
	HLRZ	TC,	(TB)		;GET THE OP CODE HALF OF THE HRRI
	TRZ	TC,	ASINC		;TURN OF THE INCOMPLETE FLAG
	HRLM	TC,	(TB)		;PUT THE OP CODE BACK IN INSTBF
	MOVEI	TB,	1		;GET NEW SIZE OF INSTBF ENT FOR HRRI
	DPB	TB,	[IP$WC <(IPI)>]	;PUT IT IN THE IPTAB
HRRICC:	;COMMON CODE
	; TA CONTAINS ADDR OF THE JRST THAT WE ARE GOING TO DELETE.
	; BEFORE DELETING IT, SEE IF INSTR BEFORE IS AN XJRST.
	; IF SO, WE CAN CHANGE IT TO A NORMAL JRST.
	SKIPG	TB,	-1(TA)		;GET IPTAB ENT OF INSTR BEFORE JRST
	PJRST		DELINS		;DO NOT TOUCH.  DELETE AND GO HOME
	LDB	TC,	[IP$OP TB]	;GET THE OP CODE
	CAIE	TC,	XJRST.		;SEE IF ITS A FUNNY JRST
	PJRST		DELINS		;NOPE,  DELETE AND GO HOME
	MOVEI	TC,	JRST.		;GET JRST OP CODE
	DPB	TC,	[IP$OP <-1(TA)>]	;PUT OVER THE OLD XJRST
	DPB	TC,	[POINT 7,(TB),8]	;PUT OP CODE INTO REAL INSTBF
	PJRST		DELINS		;DELETE UN-NECESSARY JRST AND GO HOME

HRRIXD:	;SPECIAL CASE FOR THE JRST THAT IS TWO WORDS
	; WE NEED TO DO SPECIAL FIXING.  INSTEAD OF THE ABOVE
	; CODE THAT PUTS THE TAG IN THE EXTRA WORD OF THE HRRI,
	; WE MOVE BOTH WORDS OF THE JRST TO THE HRRI.
	; UPON ENTRY TO THIS CODE:
	;	TA CONTAINS IPTAB ADDR OF JRST
	;	TB CONTAINS INSTBF ADDR OF HRRI
	HRRZ	TD,	(TA)		;GET INSTBF ADDR OF THE JRST
	HRRZ	TC,	(TD)		;GET FIRST PART OF JRST ADDR
	HRRM	TC,	(TB)		;PUT IN FIRST PART OF HRRI
	HRRZ	TC,	1(TD)		;GET SECOND HALF OF JRST ADDR
	HRRM	TC,	1(TB)		;PUT IN SECOND HALF OF HRRI
	JRST		HRRICC		;GO BACK TO COMMON CODE
SUBTTL	MOVM OPTIMIZATION

;CHECK FOR:
;	MOVM	AC,MEM
;	MOVE	AC1,AC
;	ASHC	AC1,-35
;
;CHANGE TO:
;	MOVM	AC,MEM
;	MOVE	AC1+1,AC
;	SETZ	AC1,

	PATTERN	MVMPAT,MVMADD	;MOVM PATTERNS
	TEST	1,MOV		;MOVE
	TEST	2,ASHC.		;ASHC.
	TESTMR	MVASHC		; DOES THIS MATCH?
	DOIT;			;YES

	MOVEI	TE,SETZ.	;GET NEW OPCODE
	DPB	TE,[IP$OP <1(IPI)>] ;CHANGE MOVE AC1,AC TO SETZ AC1,
	HRRZ	TD,1(IPI)
	DPB	TE,[POINT 7,(TD),8] ;STORE IN INSTRUCTION BUFFER TOO
	HLLZS	(TD)		;MAKE ADDRESS FIELD ZERO

;CHANGE ASHC AC1,-35 TO MOVE AC1+1,AC

	LDB	TE,[IP$AC <(IPI)>] ; GET "AC"
	HRRZ	TD,2(IPI)	;POINT TO REAL ASHC INSTRUCTION
	HRRM	TE,(TD)		;SET ADDRESS TO "AC"
	SETZM	1(TD)
	MOVSI	TE,ASINC	;TURN OFF INCREMENT BIT
	ANDCAM	TE,(TD)		; CAUSE THERE NO LONGER IS ONE
	MOVEI	TE,1		;NOW CHANGE WORD COUNT TO 1
	DPB	TE,[IP$WC <2(IPI)>]
	LDB	TE,[IP$AC <2(IPI)>] ;CHANGE AC1 TO AC1+1
	ADDI	TE,1
	DPB	TE,[IP$AC <2(IPI)>]
	DPB	TE,[POINT 4,(TD),12] ;CHANGE AC1 TO AC1+1
	MOVEI	TE,MOV		;AND, FINALLY, CHANGE OPCODE TO "MOV"
	DPB	TE,[IP$OP <2(IPI)>]
	DPB	TE,[POINT 7,(TD),8]
	MOVE	TE,1(IPI)	;GET THE "SETZ"
	EXCH	TE,2(IPI)	; CHANGE THE ORDER, SO THE "MOVE" IS FIRST
	MOVEM	TE,1(IPI)
	POPJ	PP,		;DONE-- RETURN
MVASHC:	LDB	TE,[IP$AC <(IPI)>] ;GET AC OF MOVM
	HRRZ	TD,1(IPI)	;TD POINTS TO ADDRESS OF MOVE
	HRRZ	TD,(TD)		;JUST GET RH
	CAIE	TE,(TD)		; MUST MATCH
	 POPJ	PP,		;NO, AC NOT THE SAME

	LDB	TE,[IP$AC <2(IPI)>] ;GET AC OF ASHC
	LDB	TD,[IP$AC <1(IPI)>] ;AND AC OF SETZ
	CAIE	TE,(TD)		;MUST MATCH
	 POPJ	PP,		;NO DICE

	HRRZ	TD,2(IPI)	;LOOK AT ADDRESS FIELD OF ASHC
	HRRZ	TE,(TD)		;FIRST MUST BE AS.CNB
	CAIE	TE,AS.CNB
	 POPJ	PP,
	HRRZ	TE,1(TD)	;GOOD. THEN MUST BE -35
	CAIN	TE,-^D35
	 AOS	(PP)		;I FOUND A MATCH!
	POPJ	PP,
;CHECK FOR
;	MOVEI	0,CONST.
;OR
;	MOVE	0,MEM1
;	MOVM	2,MEM
;	ADD	0,2
;
;CHANGE TO
;	MOVM	0,MEM
;	ADDI	0,CONST.
;OR
;	ADD	0,MEM1

	PATTERN	MVMADD,LODSTR	;MOVM PATTERN, IF IT FAILS, TRY LODSTR
	TEST2	-1,MOV,MOVEI.	;MOVE OR MOVEI
	TEST	1,AD		;ADD
	TESTMR	MVMACC		;CHECK ACCS ETC
	DOIT;			;YES, CHANGE

	LDB	TE,[IP$OP <-1(IPI)>]
	ADDI	TE,AD		;CHANGE MOVE TO ADD, MOVEI TO ADDI
	DPB	TE,[IP$OP <-1(IPI)>]	;STORE CHANGE
	HRRZ	TD,-1(IPI)
	DPB	TE,[POINT 7,(TD),8]
	SETZ	TE,		;ZERO ACCS FIELD
	DPB	TE,[IP$AC <(IPI)>]	;OF MOVM
	HRRZ	TD,(IPI)
	DPB	TE,[POINT 4,(TD),12]
	MOVE	TE,-1(IPI)	;CHANGE THE ORDER
	EXCH	TE,(IPI)
	MOVEM	TE,-1(IPI)
	HRRZI	TA,1(IPI)	;DELETE ADD
	PJRST	DELINS

MVMACC:	MOVE	TA,1(IPI)	;GET FULL ENTRY
	MOVE	TA,(TA)		;FIRST WORD ANYWAY
	CAME	TA,[<AD>B8+2]	;IS IT WHAT WE WANT?
	POPJ	PP,		;NO
	MOVE	TA,-1(IPI)	;CHECK OTHER ACCS JUST TO BE SURE
	LDB	TB,[IP$AC TA]
	JUMPN	TB,CPOPJ	;IT BETTER BE ZERO
	MOVE	TA,(IPI)
	LDB	TB,[IP$AC TA]
	CAIN	TB,2		;BETTER BE 2
	AOS	(PP)		;SUCCESS
	POPJ	PP,
	SUBTTL	MOVMS	PATTERNS

;PATTERN
;	MOVMS	MEM
;	AOS	MEM
;	INST
;	MOVM	2,MEM
;
;REPLACE WITH
;
;	MOVMS	MEM
;	AOS	2,MEM
;	INST

	PATTERM	MVMSPT
	TEST	1,AOS.
	TEST2	2,MOV,MOVM.
	TEST	3,MOVM.
	TESTMR	SAMACM		;TEST AC AND MEM OF MOVMS AND AOS
	TESTMR	MVMSAD
	DOIT	

;HERE TO DO REPLACEMENT

	LDB	TB,[IP$AC <3(IPI)>]	;GET ACC OF MOVM
	DPB	TB,[IP$AC <1(IPI)>]	;MOVE IT TO AOS
	HRRZ	TA,1(IPI)
	DPB	TB,[POINT 4,(TA),12]
	HRRZI	TA,3(IPI)
	PJRST	DELINS		;DELETE MOVM

MVMSAD:	LDB	TA,[IP$AC <3(IPI)>]
	JUMPE	TA,CPOPJ	;CAN'T CHANGE IN MOVM 0,
	HRRZ	TA,(IPI)	;TA POINTS TO MOVMS
	HRRZ	TB,3(IPI)	;TB POINTS TO MOVM
	HRRZ	TC,(TA)
	HRRZ	TD,(TB)
	CAME	TC,TD		;ARE FIRST WORDS THE SAME?
	POPJ	PP,		;NOPE
	LDB	TC,[IP$WC <(IPI)>] ; GET WORD COUNT
	SOJE	TC,CPOPJ1	;WORD COUNT IS 1 - MATCH
	MOVE	TC,1(TA)	;NO--CHECK 2ND WORD ALSO
	MOVE	TD,1(TB)
	CAMN	TC,TD
	AOS	(PP)		;SKIP RETURN
	POPJ	PP,
	SUBTTL	SETZ PATTERNS

;PATTERN
;	SETZM	MEM
;	MOVEI
;	SETZ	AC,
;
;REPLACE WITH
;
;	SETZB	AC,MEM
;	MOVEI

	PATTERN	STZPAT,STZMVM
	TEST	-2,SETZM.
	TEST2	-1,MOV,MOVEI.
	TESTMR	STZACC
	DOIT

;HERE FOR REPLACEMENT
	MOVEI	TB,SETZB.
	DPB	TB,[IP$OP <-2(IPI)>]
	HRRZ	TA,-2(IPI)
	DPB	TB,[POINT 7,(TA),8]
	LDB	TB,[IP$AC <(IPI)>]
	DPB	TB,[IP$AC <-2(IPI)>]
	DPB	TB,[POINT 4,(TA),12]
	MOVEI	TA,(IPI)
	PJRST	DELINS

STZACC:	MOVE	TA,-1(IPI)	;GET IPTAB ENTRY FOR MOVEI
	LDB	TE,[IP$AC TA]	;GET AC OF MOVEI
	MOVE	TB,(IPI)	;GET IPTAB ENTRY FOR SETZ
	LDB	TD,[IP$AC TB]	;GET AC OF SETZ
	CAIN	TE,(TD)		;SAME ACC?
	POPJ	PP,		;YES
	LDB	TE,[IP$OP TA]
	CAIE	TE,MOV		;CHECK A BIT MORE
	JRST	CPOPJ1		;NO, MOVEI IS OK
	HRRZ	TC,(TA)		;WHAT HAVE WE HERE?
	CAIN	TC,AS.CNB
	MOVE	TC,1(TB)
	CAMN	TC,TD		;SAME AC?
	AOS	(PP)		;NO
	POPJ	PP,		; YES
;PATTERN
;	MOVM	5,MEM
;	SETZ	4,
;	MOVM	5,5
;
;REPLACE WITH
;
;	MOVM	5,MEM
;	SETZ	4,

	PATTERN	STZMVM
	TEST	-1,MOVM.
	TEST	1,MOVM.
	TESTMR	STZAC5
	DOIT

;HERE TO DELETE INST AT 1(IPI)
	MOVEI	TA,1(IPI)
	PJRST	DELINS

STZAC5:	LDB	TE,[IP$AC <-1(IPI)>]
	LDB	TC,[IP$AC <1(IPI)>]
	CAMN	TE,TC
	CAIE	TE,5		;MUST BOTH BE 5
	POPJ	PP,
	MOVE	TA,1(IPI)
	HRRZ	TE,(TA)		;GET ADDRESS
	CAIN	TE,5
	AOS	(PP)		;OK
	POPJ	PP,
	SUBTTL	SETO PATTERNS

;PATTERN
;	SETOM	MEM
;	MOVEI
;	SETO	AC,
;
;REPLACE WITH
;
;	SETOB	AC,MEM
;	MOVEI

	PATTERN	STOPAT
	TEST	-2,SETOM.
	TEST2	-1,MOV,MOVEI.
	TESTMR	STZACC
	DOIT

;HERE FOR REPLACEMENT
	MOVEI	TB,SETOB.
	DPB	TB,[IP$OP <-2(IPI)>]
	HRRZ	TA,-2(IPI)
	DPB	TB,[POINT 7,(TA),8]
	LDB	TB,[IP$AC <(IPI)>]
	DPB	TB,[IP$AC <-2(IPI)>]
	DPB	TB,[POINT 4,(TA),12]
	MOVEI	TA,(IPI)
	PJRST	DELINS
	SUBTTL	ADJBP - COMMON SUBSCRIPT SUBEXPRESSIONS

;PATTERN
;	MOVE	5,MEM
;	SUBI	5,1
;	ADJBP	5,%LIT+M
;	MOVE	10,MEM
;	SUBI	10,1
;	ADJBP	10,%LIT+N
;
;REPLACE WITH
;
;	MOVE	5,MEM
;	SOS	10,5
;	ADJBP	5,%LIT+M
;	ADJBP	10,%LIT+N

	PATTERN	ADJPAT
IFE BIS,<	HALT>
IFN BIS,<
	TEST	3,ADJBP.
	TEST	-2,MOV
	TEST	1,MOV
	TESTMR	ADJBIN		;TEST FOR BINARY SUBSCRIPTS
	DOIT

;HERE TO DO REPLACEMENTS

	MOVE	TB,[<SOS.>B26+AC10,,5]	;SOS 10,5
	HRRZ	TA,-1(IPI)
	MOVEM	TB,(TA)		;REPLACE SUBI 5,1
	MOVEI	TB,SOS.
	DPB	TB,[IP$OP <-1(IPI)>]
	MOVEI	TB,10
	DPB	TB,[IP$AC <-1(IPI)>]
	MOVEI	TA,2(IPI)
	PUSHJ	PP,DELINS	;DELETE <SUBI 10,1>
	MOVEI	TA,1(IPI)
	PUSHJ	PP,DELINS	;DELETE <MOVE 10,MEM>
;A FURTHER OPTIMIZATION IS POSSIBLE IF THIS IS DISPLAY SUBSCRIPTS

;PATTERN
;	MOVEM	10,%TEMP
;	MOVE	5,%TEMP
;	SOS	10,5
;
;REPLACE WITH
;
;	MOVEM	10,%TEMP
;	SOS	5,10

	TEST	-3,MOVEM.	;MAKE SURE ITS IN THE BUFFER
	HRRZ	TA,-3(IPI)	;POINT TO MOVEM
	HRRZ	TB,-2(IPI)	;POINT TO MOVE
	MOVE	TC,(TB)		;GET MOVE
	TLC	TC,<<MOV>^!<MOVEM.>>B26+<<AC5>^!<AC10>>
	CAME	TC,(TA)		;FIRST WORD THE SAME
	POPJ	PP,
	MOVE	TC,1(TB)
	CAME	TC,1(TA)	;SECOND WORD
	POPJ	PP,
	HRRZ	TA,-1(IPI)	;OK, POINT TO SOS
	MOVE	TC,[<SOS.>B26+AC5,,10]
	MOVEM	TC,(TA)		;REPLACE 
	MOVEI	TA,-2(IPI)
	PJRST	DELINS		;DELETE MOVE 5,MEM

ADJBIN:	HRRZ	TA,-1(IPI)	;GET ADDRESS OF FIRST SUBI
	MOVE	TA,(TA)		;GET INST.
	CAME	TA,[<SUBI.>B26+AC5,,1]
	POPJ	PP,
	HRRZ	TA,2(IPI)	;GET ADDRESS OF SECOND SUBI
	MOVE	TA,(TA)		;GET INST.
	CAME	TA,[<SUBI.>B26+AC10,,1]
	POPJ	PP,
	LDB	TA,[IP$AC <(IPI)>] ;GET AC OF ADJBP
	LDB	TB,[IP$AC <-2(IPI)>] ;AND AC OF MOVE
	CAMN	TA,TB
	CAIE	TA,5		;AND BETTER BE AC5
	POPJ	PP,
	LDB	TA,[IP$AC <3(IPI)>] ;GET AC OF ADJBP
	LDB	TB,[IP$AC <1(IPI)>] ;AND AC OF MOVE
	CAMN	TA,TB
	CAIE	TA,10		;AND BETTER BE AC10
	POPJ	PP,
	HRRZ	TA,-2(IPI)	;TA POINTS TO MOVE 5,
	HRRZ	TB,1(IPI)	;TB POINTS TO MOVE 10,
	HRRZ	TC,(TA)
	HRRZ	TD,(TB)
	CAME	TC,TD		;ARE FIRST WORDS THE SAME?
	POPJ	PP,		;NOPE
	LDB	TC,[IP$WC <-2(IPI)>] ; GET WORD COUNT
	SOJE	TC,CPOPJ1	;WORD COUNT IS 1 - MATCH
	MOVE	TC,1(TA)	;NO--CHECK 2ND WORD ALSO
	CAMN	TC,1(TB)
	AOS	(PP)		;SKIP RETURN
	POPJ	PP,
	>
SUBTTL	IMULI OPTIMIZATIONS

;PATTERN
;	MOVEI	AC,C1
;	IMULI	AC,C2
;
;REPLACE BY
;
;	MOVEI	AC,C1*C2
;
;OR
;
;	HRLZI	AC,LHS(C1*C2)
;	HRRI	AC,RHS(C1*C2)

	PATTERN	IMIPAT
	TEST	-1,MOVEI.
	TESTMR	IMITS1		;SEE IF ACS SAME AND BOTH REF. A CONSTANT
	DOIT

;HERE FOR REPLACEMENTS

	HRRZ	TA,-1(IPI)	;GET ADDRESS OF MOVEI
	HRRZ	TB,(IPI)	;GET ADDRESS OF IMULI
	HRRZ	TC,(TA)		;GET MEM
	TRNE	TC,700000	;SMALL CONST?
	MOVE	TC,1(TA)	;NO, GET SECOND WORD
	HRRZ	TD,(TB)		;GET MEM
	TRNE	TD,700000	;SMALL CONST.?
	MOVE	TD,1(TB)	;NO
	IMUL	TC,TD		;MULTIPLY
	TLNE	TC,-1		;WILL IT STILL FIT IN HALF-WORD
	JRST	IMIST3		;NO, USE TWO INST.
	TRNE	TC,700000	;YES, IS IT SMALL?
	JRST	IMIST2		;NO
	HRRZ	TD,(TA)		;GET OLD VALUE
	TRNE	TD,700000	;WAS IT SMALL ALSO?
	JRST	IMIST1		;NO
	HRRM	TC,(TA)		;STORE NEW CONST.
IMIST0:	MOVEI	TA,(IPI)	;DELETE IMULI
	PJRST	DELINS

IMIST1:	HRRM	TC,1(TA)	;STORE NEW CONST.
	JRST	IMIST0

IMIST2:	MOVE	TD,(TA)		;GET OLD CONST.
	TRNE	TD,700000	;WAS IT ALSO LARGE
	JRST	IMIST1		;YES
	HRRI	TD,AS.CNB##	;MAKE IT SO
	TLO	TD,ASINC
	MOVEM	TD,OTEMP##	;STORE IN TEMP
	MOVEM	TC,OTEMP+1
	MOVEI	TA,OTEMP
	HRRM	TA,-1(IPI)	;CHANGE WHERE IT POINTS TO
	MOVEI	TC,2		;TWO WORDS NOW
	DPB	TC,[IP$WC <-1(IPI)>]
	PUSHJ	PP,IMIST0	;GO DELETE IMULI
	PJRST	COLLE1		;GARBAGE COLLECT TO CLEAR OTEMP

;THE CONSTANT IS BIGGER THAN A HALF WORD
;WE HAVE TO CHANGE BOTH INSTRUCTIONS, BUT THE SEQUENCE EXECUTES QUICKER

IMIST3:	MOVEI	TE,HRLZI.
	DPB	TE,[IP$OP <-1(IPI)>]
	DPB	TE,[POINT 7,(TA),8]
	MOVEI	TE,HRRI.
	DPB	TE,[IP$OP <(IPI)>]
	DPB	TE,[POINT 7,(TB),8]
	EXCH	TA,TB		;POINT TO 2ND INSTRUCTION
	PUSHJ	PP,IMIST4	;STORE RHS
	MOVE	TA,TB		;NOW FOR LHS
	HLRZ	TC,TC		;USE LHS=0 AS SIGNAL FOR WHICH HALF
	PUSHJ	PP,IMIST4	;STORE LHS
	PJRST	COLLE1

;HERE TO STORE CONST.
;ENTER WITH TA = N(IPI) N=-1, OR 0
;	    TC = CONST.

IMIST4:	TRNE	TC,700000	;YES, IS IT SMALL?
	JRST	IMIST6		;NO
	HRRZ	TD,(TA)		;GET OLD VALUE
	TRNE	TD,700000	;WAS IT SMALL ALSO?
	JRST	IMIST5		;NO
	HRRM	TC,(TA)		;STORE NEW CONST.
	POPJ	PP,

IMIST5:	HRRM	TC,1(TA)	;STORE NEW CONST.
	POPJ	PP,

IMIST6:	MOVE	TD,(TA)		;GET OLD CONST.
	TRNE	TD,700000	;WAS IT ALSO LARGE
	JRST	IMIST5		;YES
	HRRI	TD,AS.CNB##	;MAKE IT SO
	TLO	TD,ASINC
	TLNN	TC,-1		;LHS OR RHS?
	JRST	IMIST7		;LHS
	MOVEM	TD,OTEMP##	;STORE IN TEMP
	HRRZM	TC,OTEMP+1
	MOVEI	TA,OTEMP
	HRRM	TA,(IPI)	;CHANGE WHERE IT POINTS TO
	MOVEI	TE,2		;TWO WORDS NOW
	DPB	TE,[IP$WC <(IPI)>]
	POPJ	PP,

IMIST7:	MOVEM	TD,OTEMP+2	;STORE IN TEMP
	MOVEM	TC,OTEMP+3
	MOVEI	TA,OTEMP+2
	HRRM	TA,-1(IPI)	;CHANGE WHERE IT POINTS TO
	MOVEI	TE,2		;TWO WORDS NOW
	DPB	TE,[IP$WC <-1(IPI)>]
	POPJ	PP,

IMITS1:	LDB	TA,[IP$AC <-1(IPI)>] ;GET AC OF MOVEI
	LDB	TB,[IP$AC <(IPI)>] ;AND AC OF IMULI
	CAME	TA,TB
	POPJ	PP,		;DIFFERENT, FORGET IT
	HRRZ	TA,-1(IPI)	;TA POINTS TO MOVEI
	HRRZ	TB,(IPI)	;TB POINTS TO IMULI
	LDB	TC,[POINT 3,(TA),20]
	LDB	TD,[POINT 3,(TB),20]
	IMULI	TC,TD		;CHOICES ARE 0 OR 6
	CAIE	TC,AC.CNB*AC.CNB##
	JUMPN	TC,CPOPJ	;AC.CNS=0
	JRST	CPOPJ1		;OK


SUBTTL	MOVE AC,ADDR / MOVN AC,AC OPTIMIZATION

;PATTERN
;	MOVE	AC,ADDR
;	MOVN	AC,AC
;REPLACE WITH:
;	MOVN	AC,ADDR

	PATTERN	MOVNPT,LODSTR	;GO TO LODSTR NEXT
	TEST	-1,MOV
	TESTMR	NOPSM1		;NO PREVIOUS SKIPS OVER .-1
	TESTMR	ACACAC		;CHECK AC AND ADDR OF MOVN ARE THE SAME
				; ALSO AC OF MOVN = AC OF MOVE
	DOIT			;*** END OF PATTERN MATCH REQUIREMENTS ***

;HERE TO DO REPLACEMENT
; CHANGE OPCODE OF MOVE TO MOVN THEN DELETE THE MOVN

	MOVEI	TD,MOVN.
	DPB	TD,[IP$OP <-1(IPI)>]
	HRRZ	TA,-1(IPI)
	DPB	TD,[POINT 7,(TA),8]
	HRRZ	TA,IPI		;POINT TO THE ORIGINAL MOVN
	PJRST	DELINS		;DELETE IT, THEN RETURN

;ROUTINE TO SKIP IF THERE WEREN'T ANY PREVIOUS SKIPS OVER .-1
NOPSM1:	MOVEI	IPI,-1(IPI)	;RESET IPI TO .-1
	PUSHJ	PP,SKPTST	; DO A SKPTST
	AOJA	IPI,CPOPJ	; CAN'T MESS UP THIS CODE SEQUENCE!
	AOJA	IPI,CPOPJ1	;NO PREVIOUS SKIPS -- TAKE SKIP RETURN

;ROUTINE TO SKIP IF THIS INSTRUCTION IS OF THE FORM::
; OP AC,AC
; AND THE PREVIOUS IS OF THE FORM
; OP AC,ADDR  WITH AC SAME AS THIS INSTRUCTION'S.

ACACAC:	MOVE	TA,(IPI)	;GET IPTAB ENTRY FOR THIS INSTRUCTION
	MOVE	TB,-1(IPI)	;GET IPTAB ENTRY FOR .-1
	LDB	TC,[IP$AC TA]	;GET THIS AC
	LDB	TD,[IP$AC TB]	;GET LAST AC
	CAME	TC,TD		; MUST BE THE SAME
	 POPJ	PP,
	HRRZ	TA,(TA)		;GET ADDRESS FIELD OF THIS INSTRUCTION
	CAMN	TA,TC		; MUST BE = TO AC VALUE
	 AOS	(PP)		;YES, SKIP RETURN
	POPJ	PP,		; ELSE DON'T
SUBTTL	ASHC OPTIMIZATIONS

;PATTERN
;	MOVEI	AC,CONST.
;	ASHC	AC,-^D35
;REPLACE WITH
;	SETZ	AC,
;	MOVEI	AC+1,CONST.

	PATTERN	ASHCPT
	TEST2	-1,MOVEI.,MOVNI.
	MOVE	TA,-1(IPI)	;MOVEI
	MOVE	TB,0(IPI)	;ASHC
	LDB	TD,[IP$AC TA]
	LDB	TE,[IP$AC TB]
	CAME	TD,TE		;AC = AC?
	%%GOTO			;NO
	MOVE	TE,0(TB)	;
	MOVE	TD,1(TB)	;GET REAL ASHC INST.
	TLZ	TE,(Z 17,)	;CLEAR AC FIELD
	CAMN	TE,[<ASHC.>B26,,AS.CNB]
	CAIE	TD,-^D35
	%%GOTO			;WRONG ASHC
	DOIT			;OK, MODIFY THE CODE

	MOVSI	TE,(Z 1,)
	ADDM	TE,0(TA)	;CONVERT AC TO AC+1
	LDB	TE,[IP$OP TA]	;GET MOVEI OR MOVNI
	MOVEI	TD,SETZ.
	CAIE	TE,MOVEI.
	MOVEI	TD,SETO.	;MUST BE MOVNI
	DPB	TD,[IP$OP TB]	;CHANGE ASHC TO SETZ OR SETO
	DPB	TD,[POINT 7,(TB),8]
	HLLZS	(TB)		;NO ADDRESS EITHER
	MOVE	TE,-1(IPI)	;NOW SWAP ORDER
	EXCH	TE,0(IPI)	;SO SETZ IS BEFORE MOVEI
	MOVEM	TE,-1(IPI)	;SINCE IT IS MORE AESTHETIC
	POPJ	PP,		;RETURN
SUBTTL	FLTR OPTIMIZATION

;PATTERN
;	MOVEI	AC,CONST.
;	FLTR	AC,AC
;REPLACE WITH
;	MOVSI	AC,(FP-CONST.)

	PATTERN	FLTPAT
IFN BIS,<
	TEST2	-1,MOVEI.,MOVNI.
	MOVE	TA,-1(IPI)	;MOVEI
	MOVE	TB,0(IPI)	;FLTR
	LDB	TD,[IP$AC TA]
	LDB	TE,[IP$AC TB]
	CAME	TD,TE		;AC = AC?
	%%GOTO			;NO
	HRRZ	TE,(TB)		;MEM. OF FLTR
	CAME	TD,TE		;FLTR AC,AC
	%%GOTO			;NO
	HRRZ	TD,(TA)		;GET MEM. OF MOVEI
	TRNE	TD,700000	;SMALL CONST.?
	%%GOTO			;NO
	LDB	TC,[IP$OP TA]	;SEE IF MOVEI OR MOVNI
	CAIN	TC,MOVNI.
	MOVN	TD,TD		;IF MOVNI, NEGATE CONST.
	FLTR	TD,TD		;FLOAT IT
	TRNE	TD,-1		;FIT IN HALF WORD
	%%GOTO			;NO, LEAVE AS IS
	DOIT			;OK, MODIFY THE CODE

	MOVSM	TD,OTEMP+1	;PUT CONST IN RHS FOR MOVSI (CONST)
	MOVEI	TD,MOVSI.	;CHANGE TO MOVSI.
	DPB	TD,[IP$OP TA]	;CHANGE MOVEI TO MOVSI
	DPB	TD,[POINT 7,(TA),8]
	MOVE	TD,(TA)		;GET NEW MOVSI AC,
	HRRI	TD,AS.CNB	;MAKE IT A LARGE CONSTANT (IT ALWAYS WILL BE)
	TLO	TD,ASINC
	MOVEM	TD,OTEMP	;STORE NEW INST. IN TEMP
	MOVEI	TA,OTEMP
	HRRM	TA,-1(IPI)	;CHANGE WHERE IT POINTS TO
	MOVEI	TC,2		;TWO WORDS NOW
	DPB	TC,[IP$WC <-1(IPI)>]
	MOVEI	TA,(IPI)	;DELETE FLTR
	PUSHJ	PP,DELINS
	PJRST	COLLE1		;GARBAGE COLLECT TO CLEAR OTEMP
>
IFE BIS,<
	POPJ	PP,
>

	END	;THAT'S ALL FOLKS