fis-gtm/sr_port/jmp_opto.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
}