📄 igcse.c
字号:
/*
Copyright 1994-2003 Free Software Foundation, Inc.
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 of the License, 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., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
This program is derived from the cc68k complier by
Matthew Brandt (mattb@walkingdog.net)
You may contact the author of this derivative at:
mailto::camille@bluegrass.net
or by snail mail at:
David Lindauer
850 Washburn Ave Apt 99
Louisville, KY 40222
*/
/*
* igcse.c
*
* Go through the block list replacing common subexpressions with copy
* statements
*
*/
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <limits.h>
#include "utype.h"
#include "cmdline.h"
#include "lists.h"
#include "expr.h"
#include "c.h"
#include "iexpr.h"
#include "iopt.h"
#include "diag.h"
#define AHASH DAGSIZE
extern int *dfst;
extern int blocknum;
extern BLOCKLIST **blockarray;
extern unsigned char bittab[8];
extern BYTE *temparray4;
extern int sourcebytes, pointer_count, source_count;
extern IMODE **pointerarray;
extern QUAD **sourcearray;
extern int tempnum;
static QUAD **availarray;
static int avail_count, avail_bytes, max_avail;
static QUAD **csearray;
static int cse_max, cse_count;
static LIST3 **availhash, **availhash2;
static int csesize = - 1000, csexit;
static SYM **tempindexarray;
#ifdef DUMP_GCSE_INFO
extern FILE *icdFile, *outputFile;
static void dump_avail(void)
{
int i;
char buf[256];
FILE *temp;
if (!icdFile)
return ;
temp = outputFile;
outputFile = icdFile;
fprintf(icdFile, "\n; Available Expressions: %d\n", avail_count);
for (i = 0; i < avail_count; i++)
{
fprintf(icdFile, "; ");
put_code(availarray[i]);
}
fprintf(icdFile, "\n; Sets:\n");
for (i = 0; i < blocknum; i++)
{
sprintf(buf, "; Avail Gen block %d", i + 1);
dumpset(blockarray[i]->block->p_agen, availarray, buf, avail_count);
sprintf(buf, "; Avail kill block %d", i + 1);
dumpset(blockarray[i]->block->p_akill, availarray, buf, avail_count)
;
sprintf(buf, "; Avail in block %d", i + 1);
dumpset(blockarray[i]->block->p_ain, availarray, buf, avail_count);
sprintf(buf, "; Avail out block %d", i + 1);
dumpset(blockarray[i]->block->p_aout, availarray, buf, avail_count);
}
outputFile = temp;
}
#endif
static int CacheAvail(QUAD *var)
{
LIST *l = oalloc(sizeof(LIST));
int hash;
l->data = var;
hash = dhash(var, sizeof(struct _basic_dag));
l->link = availhash2[hash];
availhash2[hash] = l;
}
//-------------------------------------------------------------------------
static QUAD *FindAvail(QUAD *var)
{
LIST *l;
int hash = dhash(var, sizeof(struct _basic_dag));
l = availhash2[hash];
while (l)
{
if (!memcmp(var, l->data, sizeof(struct _basic_dag)))
return l->data;
l = l->link;
} return 0;
}
//-------------------------------------------------------------------------
static void enter_avail(QUAD *var)
{
QUAD *l;
if (var->dc.opcode == i_assn && var->dc.left->mode == i_immed &&
(isfloatconst(var->dc.left->offset->nodetype) || isintconst(var
->dc.left->offset->nodetype)))
return ;
if (var->available)
return ;
l = FindAvail(var);
if (l)
{
SYM *sp;
var->available = l->available;
sp = varsp(var->ans->offset);
if (sp->storage_class == sc_temp)
{
int hash = dhash(var, sizeof(struct _basic_dag));
LIST *l = availhash2[hash];
while (l)
{
if (!memcmp(l->data, var, sizeof(struct _basic_dag)))
{
SYM *sp1 = varsp(((QUAD*)l->data)->ans->offset);
if (sp1->storage_class == sc_temp && !sp1->iglobal && !sp1
->ipointerindx)
{
tempindexarray[sp->value.i] = sp1;
return ;
}
}
l = l->link;
}
}
CacheAvail(var);
return ;
}
if (avail_count >= max_avail)
{
QUAD **newarray = oalloc(sizeof(QUAD*)*(max_avail += 256));
if (availarray)
memcpy(newarray, availarray, (max_avail - 256) *sizeof(QUAD*));
availarray = newarray;
}
var->available = avail_count + 1;
availarray[avail_count++] = var;
anshash(availhash, var->dc.left, (QUAD*)avail_count);
anshash(availhash, var->dc.right, (QUAD*)avail_count);
CacheAvail(var);
}
//-------------------------------------------------------------------------
static void ReplaceOneTemp(IMODE **v)
{
SYM *sp;
if (! *v)
return ;
sp = varsp((*v)->offset);
if (sp)
if (sp->storage_class == sc_temp)
{
if (sp = tempindexarray[sp->value.i])
{
if ((*v)->mode == i_ind)
{
if (sp->imind == 0)
{
sp->imind == xalloc(sizeof(IMODE));
sp->imind->mode == i_ind;
sp->imind->offset = makenode(en_tempref, sp, 0);
sp->imind->size = (*v)->size;
}
*v = sp->imind;
}
else if ((*v)->mode == i_direct)
{
if (sp->imvalue == 0)
{
sp->imvalue == xalloc(sizeof(IMODE));
sp->imvalue->mode == i_direct;
sp->imvalue->offset = makenode(en_tempref, sp, 0);
sp->imvalue->size = (*v)->size;
}
*v = sp->imvalue;
}
}
}
}
//-------------------------------------------------------------------------
static void ReplaceTemps(QUAD *list)
{
ReplaceOneTemp(&list->ans);
ReplaceOneTemp(&list->dc.left);
ReplaceOneTemp(&list->dc.right);
}
//-------------------------------------------------------------------------
static void CountAvail(void)
{
int block = 0, i, j, k;
avail_count = 0;
availarray = 0;
max_avail = 0;
for (i = 0; i < blocknum; i++)
{
BLOCK *l = blockarray[i]->block;
QUAD *head = l->head;
memcpy(temparray4, l->p_pin, sourcebytes *pointer_count);
while (head && head->back != l->tail)
{
switch (head->dc.opcode)
{
case i_add:
case i_sub:
case i_udiv:
case i_umod:
case i_sdiv:
case i_smod:
case i_umul:
case i_smul:
case i_lsl:
case i_lsr:
case i_asl:
case i_asr:
case i_neg:
case i_not:
case i_and:
case i_or:
case i_eor:
case i_setne:
case i_sete:
case i_setc:
case i_seta:
case i_setnc:
case i_setbe:
case i_setl:
case i_setg:
case i_setle:
case i_setge:
case i_assn:
ReplaceTemps(head);
enter_avail(head);
// FALL THROUGH
case i_coswitch:
case i_jc:
case i_ja:
case i_je:
case i_jnc:
case i_jbe:
case i_jne:
case i_jl:
case i_jg:
case i_jle:
case i_jge:
case i_parm:
ReplaceTemps(head);
break;
case i_gosub:
l->callcount++;
break;
}
ptrindex(head, l, temparray4);
head = head->fwd;
}
}
}
//-------------------------------------------------------------------------
static void CreateAvailBitArrays(void)
{
int i;
avail_bytes = (avail_count + 8) / 8;
if (avail_bytes % 4)
avail_bytes += 4-avail_bytes % 4;
for (i = 0; i < blocknum; i++)
{
blockarray[i]->block->p_agen = oalloc(avail_bytes);
blockarray[i]->block->p_akill = oalloc(avail_bytes);
blockarray[i]->block->p_ain = oalloc(avail_bytes);
blockarray[i]->block->p_aout = oalloc(avail_bytes);
}
}
//-------------------------------------------------------------------------
int isvolatile(QUAD *item)
{
if (item->dc.left && item->dc.left->offset && (item->dc.left->offset
->cflags &DF_VOL))
return 1;
if (item->dc.right && item->dc.right->offset && (item->dc.right->offset
->cflags &DF_VOL))
return 1;
return 0;
}
//-------------------------------------------------------------------------
static void CalculateAvailBasics(void)
{
int i, j, k, left, right, ans;
int ptr, ptr2, gencount, pgen, pagen, def2;
int left1, right1, ans1;
LIST *l1;
for (i = 0; i < blocknum; i++)
{
BLOCK *l = blockarray[i]->block;
QUAD *list = l->head;
memcpy(temparray4, l->p_pin, sourcebytes *pointer_count);
while (list && list->back != l->tail)
{
int skipptr = FALSE;
ptr = INT_MAX;
gencount = 0;
pgen = - 1;
switch (list->dc.opcode)
{
case i_assn:
if (list->ans == list->dc.left)
{
list->fwd->back = list->back;
list->back->fwd = list->fwd;
skipptr = TRUE;
break;
}
case i_add:
case i_sub:
case i_udiv:
case i_umod:
case i_sdiv:
case i_smod:
case i_umul:
case i_smul:
case i_lsl:
case i_lsr:
case i_asl:
case i_asr:
case i_neg:
case i_not:
case i_and:
case i_or:
case i_eor:
case i_setne:
case i_sete:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -