/* src/vm/jit/ifconv/ifconv.c - if-conversion

   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
   J. Wenninger, Institut f. Computersprachen - TU Wien

   This file is part of CACAO.

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2, or (at
   your option) any later version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301, USA.

   $Id: stack.c 4455 2006-02-06 01:02:59Z edwin $

*/


#include "config.h"

#include <assert.h>

#include "vm/types.h"

#include "vm/jit/codegen-common.h"
#include "vm/jit/jit.h"
#include "vm/jit/reg.h"
#include "vm/jit/show.h"

#include "vmcore/method.h"


/* patterns for a total number of 3 instructions ******************************/

#define IFCONV_PATTERN_3_SIZE    sizeof(ifconv_pattern_3) / (sizeof(s4) * 3 * 2)

static s4 ifconv_pattern_3[][2][3] = {
	/* PATTERN 1 */

	{
		{
			ICMD_ICONST,
			ICMD_GOTO,

			ICMD_ICONST,
		},
		{
			ICMD_ICONST,
			ICMD_NOP,

			ICMD_ICONST,
		}
	},
};


/* patterns for a total number of 4 instructions ******************************/

#define IFCONV_PATTERN_4_SIZE    sizeof(ifconv_pattern_4) / (sizeof(s4) * 4 * 2)

static s4 ifconv_pattern_4[][2][4] = {
	/* PATTERN 1 */

	{
		{
			ICMD_ICONST,
			ICMD_IRETURN,

			ICMD_ICONST,
			ICMD_IRETURN
		},
		{
			ICMD_ICONST,
			ICMD_NOP,

			ICMD_ICONST,
			ICMD_IRETURN
		}
	},
};


/* ifconv_condition_complement *************************************************

   Table of conditions and their complement.  Index with:

   (ICMD_IFxx - ICMD_IFEQ)

   ATTENTION: Don't change order!  It depends on the Java bytecode opcode!

*******************************************************************************/

static s4 ifconv_condition_complement[6] = {
	/* !ICMD_IFEQ */    ICMD_IFNE,
	/* !ICMD_IFNE */    ICMD_IFEQ,
	/* !ICMD_IFLT */    ICMD_IFGE,
	/* !ICMD_IFGE */    ICMD_IFLT,
	/* !ICMD_IFGT */    ICMD_IFLE,
	/* !ICMD_IFLE */    ICMD_IFGT,
};


/* ifconv_static ***************************************************************

   Does if-conversion with static data based on pattern matching.

*******************************************************************************/

static void check(jitdata *jd, basicblock *bptr);

bool ifconv_static(jitdata *jd)
{
	methodinfo  *m;
	basicblock  *bptr;
	instruction *iptr;
	instruction *tiptr;
	s4           bcount;
	s4           icount;
	s4          *pattern;
	s4           patternsize;
	s4          *p;
	u2           opcode;
	u2           condition;
	u2           complement;
	s4           i;
	s4           j;

	/* get required compiler data */

	m  = jd->m;

	/* iterate over all basic blocks */

	bptr   = jd->basicblocks;
	bcount = jd->basicblockcount;

	for (; bcount >= 0; bcount--, bptr++) {
		/* Deleted basic blocks are just skipped. */

		if (bptr->flags == BBDELETED)
			continue;

		/* We need at least 3 basic blocks including the current one. */

		if (bcount < 3)
			continue;

		/* Only look at the last instruction of the current basic
		   block.  All conditional branch instructions are suitable
		   for if-conversion. */

		iptr   = bptr->iinstr + bptr->icount - 1;

		switch (iptr->opc) {
		case ICMD_IFNULL:
		case ICMD_IFNONNULL:

		case ICMD_IF_ICMPEQ:
		case ICMD_IF_ICMPNE:
		case ICMD_IF_ICMPLT:
		case ICMD_IF_ICMPGE:
		case ICMD_IF_ICMPGT:
		case ICMD_IF_ICMPLE:

		case ICMD_IFEQ:
		case ICMD_IFNE:
		case ICMD_IFLT:
		case ICMD_IFGE:
		case ICMD_IFGT:
		case ICMD_IFLE:

		case ICMD_LCMP:

		case ICMD_IF_LEQ:
		case ICMD_IF_LNE:
		case ICMD_IF_LLT:
		case ICMD_IF_LGE:
		case ICMD_IF_LGT:
		case ICMD_IF_LLE:

		case ICMD_IF_LCMPEQ:
		case ICMD_IF_LCMPNE:
		case ICMD_IF_LCMPLT:
		case ICMD_IF_LCMPGE:
		case ICMD_IF_LCMPGT:
		case ICMD_IF_LCMPLE:

		case ICMD_IF_ACMPEQ:
		case ICMD_IF_ACMPNE:
			/* basic blocks can only have 1 predecessor */

			if ((bptr[1].predecessorcount != 1) ||
				(bptr[2].predecessorcount != 1))
				break;

			check(jd, bptr);

			/* only use a fixed size of instructions */

			icount = bptr[1].icount + bptr[2].icount;

			/* we only convert less than or equal 4 instructions */

			if (icount > 4)
				break;

			/* check which pattern to use */

			switch (icount) {
			case 2:
				/* just skip basic blocks with length 1 */

				pattern     = NULL;
				patternsize = 0;
				break;

			case 3:
				pattern     = (s4 *) ifconv_pattern_3;
				patternsize = IFCONV_PATTERN_3_SIZE;
				break;

			case 4:
				pattern     = (s4 *) ifconv_pattern_4;
				patternsize = IFCONV_PATTERN_4_SIZE;
				break;

			default:
				/* keep compiler happy */

				pattern     = NULL;

				/* that should not happen */

				assert(0);
			}

			/* Iterate over all patterns of the given pattern. */

			for (i = 0; i < patternsize; i++) {
				/* Check the first and the second basic block at the
				   same time.  The instructions _MUST NOT_ be
				   reordered in the array before. */

				tiptr = bptr[1].iinstr;

				for (j = 0; j < icount; j++, tiptr++) {
					/* get the opcode */

					p = pattern + (icount * 2 * i) + (icount * 0) + j;

					opcode = *p;

					if (tiptr->opc != opcode)
						goto nomatch;
				}

				/* found a matching pattern */

#if !defined(NDEBUG)
				method_println(m);
#if 0
				show_basicblock(jd, &bptr[0]);
				show_basicblock(jd, &bptr[1]);
				show_basicblock(jd, &bptr[2]);
				show_basicblock(jd, &bptr[3]);
#endif
#endif

				/* check the condition */

				switch (iptr->opc) {
				case ICMD_IFEQ:
				case ICMD_IF_ICMPEQ:
				case ICMD_IF_LEQ:
				case ICMD_IF_LCMPEQ:
				case ICMD_IF_ACMPEQ:
				case ICMD_IFNULL:
					condition = ICMD_IFEQ;
					break;

				case ICMD_IFNE:
				case ICMD_IF_ICMPNE:
				case ICMD_IF_LNE:
				case ICMD_IF_LCMPNE:
				case ICMD_IF_ACMPNE:
				case ICMD_IFNONNULL:
					condition = ICMD_IFNE;
					break;

				case ICMD_IFLT:
				case ICMD_IF_ICMPLT:
				case ICMD_IF_LLT:
				case ICMD_IF_LCMPLT:
					condition = ICMD_IFLT;
					break;

				case ICMD_IFGE:
				case ICMD_IF_ICMPGE:
				case ICMD_IF_LGE:
				case ICMD_IF_LCMPGE:
					condition = ICMD_IFGE;
					break;

				case ICMD_IFGT:
				case ICMD_IF_ICMPGT:
				case ICMD_IF_LGT:
				case ICMD_IF_LCMPGT:
					condition = ICMD_IFGT;
					break;

				case ICMD_IFLE:
				case ICMD_IF_ICMPLE:
				case ICMD_IF_LLE:
				case ICMD_IF_LCMPLE:
					condition = ICMD_IFLE;
					break;

				case ICMD_LCMP:
					assert(0);

				default:
					/* keep compiler happy */

					condition = 0;

					assert(0);
				}

				/* get the condition array index */

				complement = ifconv_condition_complement[condition - ICMD_IFEQ];
	
				/* Set the new instructions, first basic block 1... */

				tiptr = bptr[1].iinstr;
				j = 0;

				for (; j < bptr[1].icount; j++, tiptr++) {
					/* get the replacing opcode */

					p = pattern + (icount * 2 * i) + (icount * 1) + j;

					opcode = *p;

					/* If we add a NOP, skip the current instruction
					   and set the stack of the next instruction
					   to the previous one. */

					if (opcode == ICMD_NOP) {
						tiptr[1].dst = tiptr[-1].dst;
					}

					/* For the first basic block we have to set the
					   complementary condition. */

/* 					tiptr->opc = opcode | (complement << 8); */
					tiptr->opc = opcode;
				}

				/* ...then basic block 2.  We split this step, as we
				   have to set different conditions in the blocks. */

				for (; j < bptr[1].icount + bptr[2].icount; j++, tiptr++) {
					p = pattern + (icount * 2 * i) + (icount * 1) + j;

					/* For the first basic block we have to set the
					   complementary condition. */

					tiptr->opc = *p | (condition << 8);

					/* if we add a NOP, set the stacks correctly */

					if (tiptr->opc == ICMD_NOP) {
						assert(0);
					}
				}

				/* tag the conditional branch instruction as conditional */

				iptr->opc |= condition << 8;

				/* add the instructions to the current basic block */

				bptr->icount += icount;

#if !defined(NDEBUG)
				method_println(m);
#if 0
				show_basicblock(jd, &bptr[0]);
#endif
#endif

				/* delete the 2 following basic blocks */

				bptr[1].flags = BBDELETED;
				bptr[2].flags = BBDELETED;
				bptr[1].icount = 0;
				bptr[2].icount = 0;

				/* we had a match, exit this iteration */

				break;

			nomatch:
				;
			}
		}
	}

	/* everything's ok */

	return true;
}

static void check(jitdata *jd, basicblock *bptr)
{
	methodinfo *m;
	int pattern = 0;

	/* get required compiler data */

	m  = jd->m;

	/*
	  generated by jikes.

	  java.lang.reflect.Modifier.isPublic(I)Z

	  [            ] L000(5 - 0) flags=1:
	  [         i00]     0 (line:   227)  ICONST          0 (0x00000000)
	  [     l00 i00]     1 (line:   227)  ILOAD           0
	  [     r15 i00]     2 (line:   227)  IANDCONST       1 (0x00000001)
	  [     r15 i00]     3 (line:   227)  NOP            
	  [         i00]     4 (line:   227)  IFEQ            0 (0x00000000) L002

	  [         i00] L001(2 - 1) flags=1:
	  [            ]     0 (line:   227)  POP            
	  [         i00]     1 (line:   227)  ICONST          1 (0x00000001)

	  [         i00] L002(1 - 2) flags=1:
	  [            ]     0 (line:   227)  IRETURN        
	*/
								
	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_POP) &&
		(bptr[1].iinstr[1].opc == ICMD_ICONST))
		{
			pattern = 1;
		}

	/*
	  generated by ecj.

	  java.util.Hashtable.isEmpty()Z PUBLIC SYNCHRONIZED

	  [    ] L000(3 - 0) flags=1:
	  [ l00]     0 (line:   292)  ALOAD           0
	  [ rdi]     1 (line:   292)  GETFIELD        36, java.util.Hashtable.size (type I
	  )
	  [    ]     2 (line:   292)  IFNE            0 (0x00000000) L002

	  [    ] L001(2 - 1) flags=1:
	  [ rdi]     0 (line:   292)  ICONST          1 (0x00000001)
	  [    ]     1 (line:   292)  IRETURN        

	  [    ] L002(2 - 1) flags=1:
	  [ rdi]     0 (line:   292)  ICONST          0 (0x00000000)
	  [    ]     1 (line:   292)  IRETURN        
	*/

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_ICONST) &&
		(bptr[1].iinstr[1].opc == ICMD_IRETURN) &&

		(bptr[2].icount == 2) &&
		(bptr[2].iinstr[0].opc == ICMD_ICONST) &&
		(bptr[2].iinstr[1].opc == ICMD_IRETURN))
		{
			pattern = 2;
		}

	/*
	  this seems to be the most common and simplest if, check for all types
	*/

	/* xCONST */

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_ICONST) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_ICONST))
		{
			pattern = 3;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_LCONST) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_LCONST))
		{
			pattern = 4;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_ACONST) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_ACONST))
		{
			pattern = 5;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_FCONST) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_FCONST))
		{
			pattern = 6;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_DCONST) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_DCONST))
		{
			pattern = 7;
		}

	/* xLOAD */


	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_ILOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_ILOAD))
		{
			pattern = 8;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_LLOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_LLOAD))
		{
			pattern = 9;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_ALOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_ALOAD))
		{
			pattern = 10;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_FLOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_FLOAD))
		{
			pattern = 11;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_DLOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_DLOAD))
		{
			pattern = 12;
		}

	/* xCONST, GOTO - xLOAD */

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_ICONST) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_ILOAD))
		{
			pattern = 13;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_LCONST) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_LLOAD))
		{
			pattern = 14;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_ACONST) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_ALOAD))
		{
			pattern = 15;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_FCONST) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_FLOAD))
		{
			pattern = 16;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_DCONST) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_DLOAD))
		{
			pattern = 17;
		}

	/* xLOAD, GOTO - xCONST */

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_ILOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_ICONST))
		{
			pattern = 18;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_LLOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_LCONST))
		{
			pattern = 19;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_ALOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_ACONST))
		{
			pattern = 20;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_FLOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_FCONST))
		{
			pattern = 21;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_DLOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_DCONST))
		{
			pattern = 22;
		}

	/*
	  check for different ISTORE destinations or handle them properly
	*/

	if ((bptr[1].icount == 3) &&
		(bptr[1].iinstr[0].opc == ICMD_ICONST) &&
		(bptr[1].iinstr[1].opc == ICMD_ISTORE) &&
		(bptr[1].iinstr[2].opc == ICMD_GOTO) &&

		(bptr[2].icount == 2) &&
		(bptr[2].iinstr[0].opc == ICMD_ICONST) &&
		(bptr[2].iinstr[1].opc == ICMD_ISTORE))
		{
			pattern = 23;
		}

	if ((bptr[1].icount == 3) &&
		(bptr[1].iinstr[0].opc == ICMD_ILOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_ISTORE) &&
		(bptr[1].iinstr[2].opc == ICMD_GOTO) &&

		(bptr[2].icount == 2) &&
		(bptr[2].iinstr[0].opc == ICMD_ILOAD) &&
		(bptr[2].iinstr[1].opc == ICMD_ISTORE))
		{
			pattern = 24;
		}

	if ((bptr[1].icount == 3) &&
		(bptr[1].iinstr[0].opc == ICMD_ICONST) &&
		(bptr[1].iinstr[1].opc == ICMD_ISTORE) &&
		(bptr[1].iinstr[2].opc == ICMD_GOTO) &&

		(bptr[2].icount == 2) &&
		(bptr[2].iinstr[0].opc == ICMD_ILOAD) &&
		(bptr[2].iinstr[1].opc == ICMD_ISTORE))
		{
			pattern = 25;
		}


	/* ALOAD, GETFIELD - ALOAD, GETFIELD */

	if ((bptr[1].icount == 3) &&
		(bptr[1].iinstr[0].opc == ICMD_ALOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GETFIELD) &&
		(bptr[1].iinstr[2].opc == ICMD_GOTO) &&

		(bptr[2].icount == 2) &&
		(bptr[2].iinstr[0].opc == ICMD_ALOAD) &&
		(bptr[2].iinstr[1].opc == ICMD_GETFIELD))
		{
			pattern = 26;
		}


	/* ALOAD, ICONST, PUTFIELD - ALOAD, ICONST, PUTFIELD */

	if ((bptr[1].icount == 4) &&
		(bptr[1].iinstr[0].opc == ICMD_ALOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_ICONST) &&
		(bptr[1].iinstr[2].opc == ICMD_PUTFIELD) &&
		(bptr[1].iinstr[3].opc == ICMD_GOTO) &&

		(bptr[2].icount == 3) &&
		(bptr[2].iinstr[0].opc == ICMD_ALOAD) &&
		(bptr[2].iinstr[1].opc == ICMD_ICONST) &&
		(bptr[2].iinstr[2].opc == ICMD_PUTFIELD)
		)
		{
			pattern = 27;
		}

	if ((bptr[1].icount == 4) &&
		(bptr[1].iinstr[0].opc == ICMD_ALOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GETFIELD) &&
		(bptr[1].iinstr[2].opc == ICMD_ASTORE) &&
		(bptr[1].iinstr[3].opc == ICMD_GOTO) &&

		(bptr[2].icount == 3) &&
		(bptr[2].iinstr[0].opc == ICMD_ALOAD) &&
		(bptr[2].iinstr[1].opc == ICMD_GETFIELD) &&
		(bptr[2].iinstr[2].opc == ICMD_ASTORE)
		)
		{
			pattern = 28;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_GETSTATIC) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_GETSTATIC))
		{
			pattern = 29;
		}

	if ((bptr[1].icount == 3) &&
		(bptr[1].iinstr[0].opc == ICMD_GETSTATIC) &&
		(bptr[1].iinstr[1].opc == ICMD_ASTORE) &&
		(bptr[1].iinstr[2].opc == ICMD_GOTO) &&

		(bptr[2].icount == 2) &&
		(bptr[2].iinstr[0].opc == ICMD_GETSTATIC) &&
		(bptr[2].iinstr[1].opc == ICMD_ASTORE))
		{
			pattern = 30;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_GETSTATIC) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_ALOAD))
		{
			pattern = 31;
		}

	if ((bptr[1].icount == 2) &&
		(bptr[1].iinstr[0].opc == ICMD_ALOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_GETSTATIC))
		{
			pattern = 32;
		}


	if ((bptr[1].icount == 3) &&
		(bptr[1].iinstr[0].opc == ICMD_ALOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GETFIELD) &&
		(bptr[1].iinstr[2].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_ICONST))
		{
			pattern = 33;
		}

	if ((bptr[1].icount == 3) &&
		(bptr[1].iinstr[0].opc == ICMD_ALOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GETFIELD) &&
		(bptr[1].iinstr[2].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_LCONST))
		{
			pattern = 34;
		}

	if ((bptr[1].icount == 3) &&
		(bptr[1].iinstr[0].opc == ICMD_ALOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GETFIELD) &&
		(bptr[1].iinstr[2].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_ACONST))
		{
			pattern = 35;
		}

	if ((bptr[1].icount == 3) &&
		(bptr[1].iinstr[0].opc == ICMD_ALOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GETFIELD) &&
		(bptr[1].iinstr[2].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_ILOAD))
		{
			pattern = 36;
		}

	if ((bptr[1].icount == 3) &&
		(bptr[1].iinstr[0].opc == ICMD_ALOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GETFIELD) &&
		(bptr[1].iinstr[2].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_LLOAD))
		{
			pattern = 37;
		}

	if ((bptr[1].icount == 3) &&
		(bptr[1].iinstr[0].opc == ICMD_ALOAD) &&
		(bptr[1].iinstr[1].opc == ICMD_GETFIELD) &&
		(bptr[1].iinstr[2].opc == ICMD_GOTO) &&

		(bptr[2].icount == 1) &&
		(bptr[2].iinstr[0].opc == ICMD_ALOAD))
		{
			pattern = 38;
		}

	/*

	CHECK 3   : (BB:   0) IFEQ            javax.swing.plaf.basic.BasicInternalFrameTitlePane.paintTitleBackground(Ljava/awt/Graphics;)V PROTECTED
	[ ?   ?   ?   ?   ?  ] L001(instruction count: 4, predecessors: 1):
	[ ?   ?   ?   ?   ?  ]     0 (line:   909)  ALOAD           0
	[ ?   ?   ?   ?   ?  ]     1 (line:   909)  GETFIELD        (NOT RESOLVED), javax.swing.plaf.basic.BasicInternalFrameTitlePane.selectedTitleColor (type Ljava/awt/Color;)
	[ ?   ?   ?   ?   ?  ]     2 (line:   909)  ASTORE          4
	[ ?   ?   ?   ?   ?  ]     3 (line:   909)  GOTO            op1=41
	[ ?   ?   ?   ?   ?  ] L002(instruction count: 3, predecessors: 1):
	[ ?   ?   ?   ?   ?  ]     0 (line:   911)  ALOAD           0
	[ ?   ?   ?   ?   ?  ]     1 (line:   911)  GETFIELD        (NOT RESOLVED), javax.swing.plaf.basic.BasicInternalFrameTitlePane.notSelectedTitleColor (type Ljava/awt/Color;)
	[ ?   ?   ?   ?   ?  ]     2 (line:   911)  ASTORE          4


	CHECK 3   : (BB:   3) IFEQ            javax.swing.plaf.basic.BasicTreeUI$MouseHandler.mousePressed(Ljava/awt/event/MouseEvent;)V PUBLIC
	[ ?   ?   ?   ?   ?  ] L004(instruction count: 4, predecessors: 1):
	[ ?   ?   ?   ?   ?  ]     0 (line:  2244)  ACONST          0x3602d30, String = "Tree.openIcon"
	[ ?   ?   ?   ?   ?  ]     1 (line:  2244)  INVOKESTATIC    (NOT RESOLVED) javax.swing.UIManager.getIcon(Ljava/lang/Object;)Ljavax/swing/Icon;
	[ ?   ?   ?   ?   ?  ]     2 (line:  2244)  ASTORE          8
	[ ?   ?   ?   ?   ?  ]     3 (line:  2244)  GOTO            op1=155
	[ ?   ?   ?   ?   ?  ] L005(instruction count: 3, predecessors: 1):
	[ ?   ?   ?   ?   ?  ]     0 (line:  2246)  ACONST          0x3602e00, String = "Tree.closedIcon"
	[ ?   ?   ?   ?   ?  ]     1 (line:  2246)  INVOKESTATIC    (NOT RESOLVED) javax.swing.UIManager.getIcon(Ljava/lang/Object;)Ljavax/swing/Icon;
	[ ?   ?   ?   ?   ?  ]     2 (line:  2246)  ASTORE          8


	CHECK 3   : (BB:   2) IFEQ            javax.naming.CompoundName.initializeSyntax()V PRIVATE FINAL
	[ ?   ?   ?   ?  ] L003(instruction count: 4, predecessors: 1):
	[ ?   ?   ?   ?  ]     0 (line:   445)  ALOAD           0
	[ ?   ?   ?   ?  ]     1 (line:   445)  ICONST          1 (0x00000001)
	[ ?   ?   ?   ?  ]     2 (line:   445)  PUTFIELD        (NOT RESOLVED), javax.naming.CompoundName.direction (type I)
	[ ?   ?   ?   ?  ]     3 (line:   445)  GOTO            op1=51
	[ ?   ?   ?   ?  ] L004(instruction count: 3, predecessors: 1):
	[ ?   ?   ?   ?  ]     0 (line:   449)  ALOAD           0
	[ ?   ?   ?   ?  ]     1 (line:   449)  ICONST          0 (0x00000000)
	[ ?   ?   ?   ?  ]     2 (line:   449)  PUTFIELD        (NOT RESOLVED), javax.naming.CompoundName.direction (type I)


	CHECK 3   : (BB:  15) IFNE            java.awt.Scrollbar.setValues(IIII)V PUBLIC SYNCHRONIZED
	[ ?   ?   ?   ?   ?  ] L016(instruction count: 4, predecessors: 1):
	[ ?   ?   ?   ?   ?  ]     0 (line:   371)  ALOAD           0
	[ ?   ?   ?   ?   ?  ]     1 (line:   371)  ICONST          1 (0x00000001)
	[ ?   ?   ?   ?   ?  ]     2 (line:   371)  PUTFIELD        (NOT RESOLVED), java.awt.Scrollbar.lineIncrement (type I)
	[ ?   ?   ?   ?   ?  ]     3 (line:   371)  GOTO            op1=152
	[ ?   ?   ?   ?   ?  ] L017(instruction count: 3, predecessors: 1):
	[ ?   ?   ?   ?   ?  ]     0 (line:   373)  ALOAD           0
	[ ?   ?   ?   ?   ?  ]     1 (line:   373)  ILOAD           6
	[ ?   ?   ?   ?   ?  ]     2 (line:   373)  PUTFIELD        (NOT RESOLVED), java.awt.Scrollbar.lineIncrement (type I)


	CHECK 3   : (BB:   1) IFEQ            javax.swing.JInternalFrame.setIcon(Z)V PUBLIC
	[ ?   ?   ?   ?  ] L002(instruction count: 4, predecessors: 1):
	[ ?   ?   ?   ?  ]     0 (line:  1395)  ALOAD           0
	[ ?   ?   ?   ?  ]     1 (line:  1395)  ICONST          25552 (0x000063d0)
	[ ?   ?   ?   ?  ]     2 (line:  1395)  INVOKEVIRTUAL   (NOT RESOLVED) javax.swing.JInternalFrame.fireInternalFrameEvent(I)V
	[ ?   ?   ?   ?  ]     3 (line:  1395)  GOTO            op1=61
	[ ?   ?   ?   ?  ] L003(instruction count: 3, predecessors: 1):
	[ ?   ?   ?   ?  ]     0 (line:  1397)  ALOAD           0
	[ ?   ?   ?   ?  ]     1 (line:  1397)  ICONST          25553 (0x000063d1)
	[ ?   ?   ?   ?  ]     2 (line:  1397)  INVOKEVIRTUAL   (NOT RESOLVED) javax.swing.JInternalFrame.fireInternalFrameEvent(I)V

	*/

#if !defined(NDEBUG)
	if (pattern != 0) {
		printf("PATTERN %02d: (BB: %3d) ", pattern, jd->basicblockcount - bptr->nr);
		method_println(m);

		/* 								if (pattern == 27) { */
		/* 									show_basicblock(m, cd, &bptr[1]); */
		/* 									show_basicblock(m, cd, &bptr[2]); */
		/* 								} */

		fflush(stdout);

	} else {
		if ((bptr[1].icount == 2) &&
			(bptr[2].icount == 1) &&

			(bptr[1].iinstr[1].opc == ICMD_GOTO))
			{
				printf("CHECK 1   : (BB: %3d) ", jd->basicblockcount - bptr->nr);
				method_println(m);
#if 0
				show_basicblock(jd, &bptr[1]);
				show_basicblock(jd, &bptr[2]);
#endif
				fflush(stdout);
			}

		if ((bptr[1].icount == 3) &&
			(bptr[2].icount == 2) &&

			(bptr[1].iinstr[2].opc == ICMD_GOTO))
			{
				printf("CHECK 2   : (BB: %3d) ", jd->basicblockcount - bptr->nr);
				method_println(m);
#if 0
				show_basicblock(jd, &bptr[1]);
				show_basicblock(jd, &bptr[2]);
#endif
				fflush(stdout);
			}

		if ((bptr[1].icount == 4) &&
			(bptr[2].icount == 3) &&

			(bptr[1].iinstr[3].opc == ICMD_GOTO))
			{
				printf("CHECK 3   : (BB: %3d) ", jd->basicblockcount - bptr->nr);
				method_println(m);
#if 0
				show_basicblock(jd, &bptr[1]);
				show_basicblock(jd, &bptr[2]);
#endif
				fflush(stdout);
			}

		if ((bptr[1].icount == 3) &&
			(bptr[2].icount == 1) &&

			(bptr[1].iinstr[2].opc == ICMD_GOTO))
			{
				printf("CHECK 4   : (BB: %3d) ", jd->basicblockcount - bptr->nr);
				method_println(m);
#if 0
				show_basicblock(jd, &bptr[1]);
				show_basicblock(jd, &bptr[2]);
#endif
				fflush(stdout);
			}
	}
#endif /* !defined(NDEBUG) */
}


/*
 * These are local overrides for various environment variables in Emacs.
 * Please do not remove this and leave it at the end of the file, where
 * Emacs will automagically detect them.
 * ---------------------------------------------------------------------
 * Local variables:
 * mode: c
 * indent-tabs-mode: t
 * c-basic-offset: 4
 * tab-width: 4
 * End:
 * vim:noexpandtab:sw=4:ts=4:
 */
