351 lines
11 KiB
C
351 lines
11 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2001, 2010 Fidelity Information Services, Inc *
|
|
* *
|
|
* This source code contains the intellectual property *
|
|
* of its copyright holder(s), and is made available *
|
|
* under a license. If you do not know the terms of *
|
|
* the license, please stop and do not read further. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
#include "mdef.h"
|
|
|
|
#include "gtm_stdio.h"
|
|
|
|
#include "compiler.h"
|
|
#include "opcode.h"
|
|
#include "mdq.h"
|
|
#include "jmp_opto.h"
|
|
#include "gtmdbglvl.h"
|
|
#include "cdbg_dump.h"
|
|
|
|
#define JOPT_NO_OPT 1
|
|
#define JOPT_REP_JMP 2
|
|
#define JOPT_REF_NXT_TRP 3
|
|
|
|
#define PTR_NOT_DEFINED 0
|
|
#define IND_NOT_DEFINED ((unsigned char)-2)
|
|
#define NO_ENTRY ((unsigned char)-1)
|
|
|
|
#define NUM_JO_TBL_ELE 11
|
|
typedef struct
|
|
{ unsigned int opcode;
|
|
unsigned int index;
|
|
unsigned int opto_flag[NUM_JO_TBL_ELE];
|
|
}jump_opto_struct;
|
|
|
|
LITREF octabstruct oc_tab[]; /* op-code table */
|
|
GBLREF triple t_orig; /* head of triples */
|
|
GBLREF uint4 gtmDebugLevel;
|
|
const static readonly jump_opto_struct jump_opto_table[NUM_JO_TBL_ELE] =
|
|
{
|
|
{ OC_JMP, /* opcode */
|
|
0, /* index */
|
|
{
|
|
JOPT_REP_JMP, /* OC_JMP */ JOPT_NO_OPT, /* OC_JMPTSET */
|
|
JOPT_NO_OPT, /* OC_JMPTCLR */ JOPT_NO_OPT, /* OC_JMPEQU */
|
|
JOPT_NO_OPT, /* OC_JMPNEQ */ JOPT_NO_OPT, /* OC_JMPGTR */
|
|
JOPT_NO_OPT, /* OC_JMPLEQ */ JOPT_NO_OPT, /* OC_JMPLSS */
|
|
JOPT_NO_OPT, /* OC_JMPGEQ */ JOPT_NO_OPT, /* HALT */
|
|
JOPT_NO_OPT /* RET */
|
|
}
|
|
},
|
|
{ OC_JMPTSET, /* opcode */
|
|
1, /* index */
|
|
{
|
|
JOPT_REP_JMP, /* OC_JMP */ JOPT_REP_JMP, /* OC_JMPTSET */
|
|
JOPT_REF_NXT_TRP, /* OC_JMPTCLR */ JOPT_NO_OPT, /* OC_JMPEQU */
|
|
JOPT_NO_OPT, /* OC_JMPNEQ */ JOPT_NO_OPT, /* OC_JMPGTR */
|
|
JOPT_NO_OPT, /* OC_JMPLEQ */ JOPT_NO_OPT, /* OC_JMPLSS */
|
|
JOPT_NO_OPT, /* OC_JMPGEQ */ JOPT_NO_OPT, /* HALT */
|
|
JOPT_NO_OPT /* RET */
|
|
}
|
|
},
|
|
{ OC_JMPTCLR, /* opcode */
|
|
2, /* index */
|
|
{
|
|
JOPT_REP_JMP, /* OC_JMP */ JOPT_REF_NXT_TRP, /* OC_JMPTSET */
|
|
JOPT_REP_JMP, /* OC_JMPTCLR */ JOPT_NO_OPT, /* OC_JMPEQU */
|
|
JOPT_NO_OPT, /* OC_JMPNEQ */ JOPT_NO_OPT, /* OC_JMPGTR */
|
|
JOPT_NO_OPT, /* OC_JMPLEQ */ JOPT_NO_OPT, /* OC_JMPLSS */
|
|
JOPT_NO_OPT, /* OC_JMPGEQ */ JOPT_NO_OPT, /* HALT */
|
|
JOPT_NO_OPT /* RET */
|
|
}
|
|
},
|
|
{ OC_JMPEQU, /* opcode */
|
|
3, /* index */
|
|
{
|
|
JOPT_REP_JMP, /* OC_JMP */ JOPT_NO_OPT, /* OC_JMPTSET */
|
|
JOPT_NO_OPT, /* OC_JMPTCLR */ JOPT_REP_JMP, /* OC_JMPEQU */
|
|
JOPT_REF_NXT_TRP, /* OC_JMPNEQ */ JOPT_REF_NXT_TRP, /* OC_JMPGTR */
|
|
JOPT_NO_OPT, /* OC_JMPLEQ */ JOPT_REF_NXT_TRP, /* OC_JMPLSS */
|
|
JOPT_NO_OPT, /* OC_JMPGEQ */ JOPT_NO_OPT, /* HALT */
|
|
JOPT_NO_OPT /* RET */
|
|
}
|
|
},
|
|
{ OC_JMPNEQ, /* opcode */
|
|
4, /* index */
|
|
{
|
|
JOPT_REP_JMP, /* OC_JMP */ JOPT_NO_OPT, /* OC_JMPTSET */
|
|
JOPT_NO_OPT, /* OC_JMPTCLR */ JOPT_REF_NXT_TRP, /* OC_JMPEQU */
|
|
JOPT_REP_JMP, /* OC_JMPNEQ */ JOPT_NO_OPT, /* OC_JMPGTR */
|
|
JOPT_NO_OPT, /* OC_JMPLEQ */ JOPT_NO_OPT, /* OC_JMPLSS */
|
|
JOPT_NO_OPT, /* OC_JMPGEQ */ JOPT_NO_OPT, /* HALT */
|
|
JOPT_NO_OPT /* RET */
|
|
}
|
|
},
|
|
{ OC_JMPGTR, /* opcode */
|
|
5, /* index */
|
|
{
|
|
JOPT_REP_JMP, /* OC_JMP */ JOPT_NO_OPT, /* OC_JMPTSET */
|
|
JOPT_NO_OPT, /* OC_JMPTCLR */ JOPT_REF_NXT_TRP, /* OC_JMPEQU */
|
|
JOPT_REP_JMP, /* OC_JMPNEQ */ JOPT_REP_JMP, /* OC_JMPGTR */
|
|
JOPT_REF_NXT_TRP, /* OC_JMPLEQ */ JOPT_REF_NXT_TRP, /* OC_JMPLSS */
|
|
JOPT_NO_OPT, /* OC_JMPGEQ */ JOPT_NO_OPT, /* HALT */
|
|
JOPT_NO_OPT /* RET */
|
|
}
|
|
},
|
|
{ OC_JMPLEQ, /* opcode */
|
|
6, /* index */
|
|
{
|
|
JOPT_REP_JMP, /* OC_JMP */ JOPT_NO_OPT, /* OC_JMPTSET */
|
|
JOPT_NO_OPT, /* OC_JMPTCLR */ JOPT_NO_OPT, /* OC_JMPEQU */
|
|
JOPT_NO_OPT, /* OC_JMPNEQ */ JOPT_REF_NXT_TRP, /* OC_JMPGTR */
|
|
JOPT_REP_JMP, /* OC_JMPLEQ */ JOPT_NO_OPT, /* OC_JMPLSS */
|
|
JOPT_NO_OPT, /* OC_JMPGEQ */ JOPT_NO_OPT, /* HALT */
|
|
JOPT_NO_OPT /* RET */
|
|
}
|
|
},
|
|
{ OC_JMPLSS, /* opcode */
|
|
7, /* index */
|
|
{
|
|
JOPT_REP_JMP, /* OC_JMP */ JOPT_NO_OPT, /* OC_JMPTSET */
|
|
JOPT_NO_OPT, /* OC_JMPTCLR */ JOPT_REF_NXT_TRP, /* OC_JMPEQU */
|
|
JOPT_REP_JMP, /* OC_JMPNEQ */ JOPT_REF_NXT_TRP, /* OC_JMPGTR */
|
|
JOPT_REP_JMP, /* OC_JMPLEQ */ JOPT_REP_JMP, /* OC_JMPLSS */
|
|
JOPT_REF_NXT_TRP, /* OC_JMPGEQ */ JOPT_NO_OPT, /* HALT */
|
|
JOPT_NO_OPT /* RET */
|
|
}
|
|
},
|
|
{ OC_JMPGEQ, /* opcode */
|
|
8, /* index */
|
|
{
|
|
JOPT_REP_JMP, /* OC_JMP */ JOPT_NO_OPT, /* OC_JMPTSET */
|
|
JOPT_NO_OPT, /* OC_JMPTCLR */ JOPT_NO_OPT, /* OC_JMPEQU */
|
|
JOPT_NO_OPT, /* OC_JMPNEQ */ JOPT_NO_OPT, /* OC_JMPGTR */
|
|
JOPT_NO_OPT, /* OC_JMPLEQ */ JOPT_REF_NXT_TRP, /* OC_JMPLSS */
|
|
JOPT_REP_JMP, /* OC_JMPGEQ */ JOPT_NO_OPT, /* HALT */
|
|
JOPT_NO_OPT /* RET */
|
|
}
|
|
},
|
|
{ OC_HALT, /* opcode */
|
|
9, /* index */
|
|
{
|
|
JOPT_NO_OPT, /* OC_JMP */ JOPT_NO_OPT, /* OC_JMPTSET */
|
|
JOPT_NO_OPT, /* OC_JMPTCLR */ JOPT_NO_OPT, /* OC_JMPEQU */
|
|
JOPT_NO_OPT, /* OC_JMPNEQ */ JOPT_NO_OPT, /* OC_JMPGTR */
|
|
JOPT_NO_OPT, /* OC_JMPLEQ */ JOPT_NO_OPT, /* OC_JMPLSS */
|
|
JOPT_NO_OPT, /* OC_JMPGEQ */ JOPT_NO_OPT, /* HALT */
|
|
JOPT_NO_OPT /* RET */
|
|
}
|
|
},
|
|
{ OC_RET, /* opcode */
|
|
10, /* index */
|
|
{
|
|
JOPT_NO_OPT, /* OC_JMP */ JOPT_NO_OPT, /* OC_JMPTSET */
|
|
JOPT_NO_OPT, /* OC_JMPTCLR */ JOPT_NO_OPT, /* OC_JMPEQU */
|
|
JOPT_NO_OPT, /* OC_JMPNEQ */ JOPT_NO_OPT, /* OC_JMPGTR */
|
|
JOPT_NO_OPT, /* OC_JMPLEQ */ JOPT_NO_OPT, /* OC_JMPLSS */
|
|
JOPT_NO_OPT, /* OC_JMPGEQ */ JOPT_NO_OPT, /* HALT */
|
|
JOPT_NO_OPT /* RET */
|
|
}
|
|
}
|
|
};
|
|
static unsigned int *jo_ptr_ray[OPCODE_COUNT];
|
|
static unsigned int jo_ind_ray[OPCODE_COUNT];
|
|
|
|
static void jo_get_ptrs(unsigned int op)
|
|
{
|
|
const jump_opto_struct *j, *j_top;
|
|
|
|
for (j = &jump_opto_table[0], j_top = j + NUM_JO_TBL_ELE; j < j_top; j++)
|
|
{
|
|
if (j->opcode == op)
|
|
{
|
|
jo_ind_ray[op] = j->index;
|
|
jo_ptr_ray[op] = (unsigned int *)&j->opto_flag[0];
|
|
return;
|
|
}
|
|
}
|
|
jo_ind_ray[op] = NO_ENTRY;
|
|
jo_ptr_ray[op] = (unsigned int *)NO_ENTRY;
|
|
}
|
|
|
|
const static readonly oprtype null_operand;
|
|
|
|
/************************************************************************************************************
|
|
NOTE: We may which to modify the lookup method at some point in the future. B. Shear suggests nested switch
|
|
statements. Another option is to do the lookup each time.
|
|
***********************************************************************************************************/
|
|
|
|
void jmp_opto(void)
|
|
{
|
|
unsigned int i, *p, **clrp1, **clrtop1, *clrp2, *clrtop2;
|
|
tbp *b;
|
|
triple *cur_trip, *terminal_trip, *ref_trip, *jump_trip, *next_trip, *ct;
|
|
void get_jo_ptrs();
|
|
|
|
# ifdef DEBUG
|
|
/* If debug and compiler debugging is enabled, run through the triples again to show where we are jus
|
|
* before we modify them.
|
|
*/
|
|
if (gtmDebugLevel & GDL_DebugCompiler)
|
|
{
|
|
PRINTF(" \n\n\n\n************************************ Begin jmp_opto scan *****************************\n");
|
|
}
|
|
# endif
|
|
|
|
for (clrp1 = &jo_ptr_ray[0], clrtop1 = clrp1 + OPCODE_COUNT; clrp1 < clrtop1; clrp1++)
|
|
*clrp1 = (unsigned int *)NO_ENTRY;
|
|
for (clrp2 = &jo_ind_ray[0], clrtop2 = clrp2 + OPCODE_COUNT; clrp2 < clrtop2; clrp2++)
|
|
*clrp2 = NO_ENTRY;
|
|
|
|
dqloop(&t_orig, exorder, cur_trip)
|
|
{
|
|
if (OC_GVSAVTARG == cur_trip->opcode)
|
|
{
|
|
for (next_trip = cur_trip->exorder.fl;
|
|
oc_tab[next_trip->opcode].octype & OCT_CGSKIP;
|
|
next_trip = next_trip->exorder.fl)
|
|
;
|
|
|
|
if (OC_GVRECTARG == next_trip->opcode
|
|
&& next_trip->operand[0].oprval.tref == cur_trip
|
|
&& next_trip->jmplist.que.fl == &(next_trip->jmplist))
|
|
{
|
|
COMPDBG(PRINTF("jmp_opto: NOOPing OC_GVRECTARG opcode at triple addres 0x"lvaddr"\n", next_trip););
|
|
next_trip->opcode = OC_NOOP;
|
|
next_trip->operand[0].oprclass = next_trip->operand[1].oprclass = 0;
|
|
}
|
|
continue;
|
|
}
|
|
if ((oc_tab[cur_trip->opcode].octype & OCT_JUMP) &&
|
|
(OC_CALL != cur_trip->opcode) && (OC_CALLSP != cur_trip->opcode))
|
|
{
|
|
assert(OPCODE_COUNT > cur_trip->opcode);
|
|
if (PTR_NOT_DEFINED == (p = jo_ptr_ray[cur_trip->opcode])) /* note assignment */
|
|
{
|
|
jo_get_ptrs(cur_trip->opcode);
|
|
p = jo_ptr_ray[cur_trip->opcode];
|
|
}
|
|
assert(TJMP_REF == cur_trip->operand[0].oprclass);
|
|
jump_trip = cur_trip->operand[0].oprval.tref;
|
|
if (IND_NOT_DEFINED == (i = jo_ind_ray[jump_trip->opcode])) /* note assignment */
|
|
{
|
|
jo_get_ptrs(jump_trip->opcode);
|
|
i = jo_ind_ray[jump_trip->opcode];
|
|
}
|
|
|
|
while ((IND_NOT_DEFINED != i) && (NO_ENTRY != i))
|
|
{
|
|
switch(p[i])
|
|
{
|
|
case JOPT_NO_OPT:
|
|
i = NO_ENTRY;
|
|
break;
|
|
case JOPT_REF_NXT_TRP:
|
|
if (cur_trip->src.line == jump_trip->src.line)
|
|
{
|
|
dqloop(&jump_trip->jmplist, que, b)
|
|
{
|
|
if (b->bpt = cur_trip)
|
|
{
|
|
dqdel(b, que);
|
|
break;
|
|
}
|
|
}
|
|
dqins(&jump_trip->exorder.fl->jmplist, que, b);
|
|
|
|
cur_trip->operand[0].oprval.tref = jump_trip->exorder.fl;
|
|
jump_trip = cur_trip->operand[0].oprval.tref;
|
|
if (IND_NOT_DEFINED == (i = jo_ind_ray[jump_trip->opcode])) /* assignmnt */
|
|
{
|
|
jo_get_ptrs(jump_trip->opcode);
|
|
i = jo_ind_ray[jump_trip->opcode];
|
|
}
|
|
COMPDBG(PRINTF("jmp_opto: JOPT_REF_NXT_TRP optimization on triple "
|
|
"0x"lvaddr"\n", cur_trip););
|
|
} else
|
|
i = NO_ENTRY;
|
|
break;
|
|
case JOPT_REP_JMP:
|
|
if (cur_trip->src.line == jump_trip->src.line)
|
|
{
|
|
assert(TJMP_REF == jump_trip->operand[0].oprclass);
|
|
dqloop(&jump_trip->jmplist, que, b)
|
|
{
|
|
if (b->bpt = cur_trip)
|
|
{
|
|
dqdel(b, que);
|
|
break;
|
|
}
|
|
}
|
|
dqins(&jump_trip->operand[0].oprval.tref->jmplist, que, b);
|
|
|
|
cur_trip->operand[0] = jump_trip->operand[0];
|
|
jump_trip = cur_trip->operand[0].oprval.tref;
|
|
if (IND_NOT_DEFINED == (i = jo_ind_ray[jump_trip->opcode])) /* assgnmnt */
|
|
{
|
|
jo_get_ptrs(jump_trip->opcode);
|
|
i = jo_ind_ray[jump_trip->opcode];
|
|
}
|
|
COMPDBG(PRINTF("jmp_opto: JOPT_REP_JMP optimization on triple "
|
|
"0x"lvaddr"\n", cur_trip););
|
|
} else
|
|
i = NO_ENTRY;
|
|
break;
|
|
default:
|
|
GTMASSERT;
|
|
break;
|
|
} /* switch */
|
|
} /* while */
|
|
|
|
terminal_trip = cur_trip->exorder.fl;
|
|
while ((oc_tab[cur_trip->opcode].octype & OCT_JUMP)
|
|
&& (OC_CALL != cur_trip->opcode) && (OC_CALLSP != cur_trip->opcode)
|
|
&& (TJMP_REF == cur_trip->operand[0].oprclass))
|
|
{
|
|
for ((ref_trip = cur_trip->operand[0].oprval.tref);
|
|
(oc_tab[ref_trip->opcode].octype & OCT_CGSKIP);
|
|
(ref_trip = ref_trip->exorder.fl))
|
|
;
|
|
|
|
if (ref_trip == terminal_trip)
|
|
{
|
|
cur_trip->opcode = OC_NOOP;
|
|
cur_trip->operand[0] = null_operand;
|
|
COMPDBG(PRINTF("jmp_opto: Triple removed at address 0x"lvaddr"\n", cur_trip););
|
|
cur_trip = cur_trip->exorder.bl;
|
|
} else
|
|
break;
|
|
}
|
|
cur_trip = terminal_trip->exorder.bl;
|
|
} /* if */
|
|
} /* dqloop */
|
|
|
|
# ifdef DEBUG
|
|
/* If debug and compiler debugging is enabled, run through the triples again to show what we
|
|
* have done to them..
|
|
*/
|
|
if (gtmDebugLevel & GDL_DebugCompiler)
|
|
{
|
|
dqloop(&t_orig, exorder, ct)
|
|
{
|
|
PRINTF("\n ************************ Triple Start **********************\n");
|
|
cdbg_dump_triple(ct, 0);
|
|
}
|
|
}
|
|
# endif
|
|
}
|