📄 icopy.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
*/
/*
* icopy.c
*
* iteratively determine candidates for copy propagation, and
* then go through the blocks and replace as many copy statements
* as possible
*
*/
#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 CHASH DAGSIZE
extern int blocknum;
extern int *dfst;
extern BLOCKLIST **blockarray;
extern BYTE *temparray4;
extern int sourcebytes, pointer_count, source_count;
extern QUAD **defiarray;
extern unsigned char bittab[8];
extern QUAD **sourcearray;
extern int prm_debug;
static LIST3 **copyhash;
static QUAD **copyarray;
static int max_copies;
static int copy_count, copybytes;
static BYTE *temparray5;
#ifdef DUMP_GCSE_INFO
extern FILE *icdFile, *outputFile;
static void dump_copies(void)
{
int i;
char buf[256];
FILE *temp;
if (!icdFile)
return ;
temp = outputFile;
outputFile = icdFile;
fprintf(icdFile, "\n; Copies: %d\n", copy_count);
for (i = 0; i < copy_count; i++)
{
fprintf(icdFile, "; ");
put_code(copyarray[i]);
}
fprintf(icdFile, "\n; Sets:\n");
for (i = 0; i < blocknum; i++)
{
sprintf(buf, "; Gen block %d", i + 1);
dumpset(blockarray[i]->block->p_cgen, copyarray, buf, copy_count);
sprintf(buf, "; kill block %d", i + 1);
dumpset(blockarray[i]->block->p_ckill, copyarray, buf, copy_count);
sprintf(buf, "; in block %d", i + 1);
dumpset(blockarray[i]->block->p_cin, copyarray, buf, copy_count);
sprintf(buf, "; out block %d", i + 1);
dumpset(blockarray[i]->block->p_cout, copyarray, buf, copy_count);
}
outputFile = temp;
}
#endif
static int used(QUAD *match, QUAD *list)
{
SYM *sp;
if (list->dc.left && list->dc.left->mode != i_immed)
{
sp = varsp(list->dc.left->offset);
if (sp)
if (sp->imvalue == match->dc.left || sp->imvalue == match->ans)
return TRUE;
}
if (list->dc.right && list->dc.right->mode != i_immed)
{
sp = varsp(list->dc.right->offset);
if (sp)
if (sp->imvalue == match->dc.left || sp->imvalue == match->ans)
return TRUE;
}
if (list->ans && list->ans->mode == i_ind)
{
sp = varsp(list->ans->offset);
if (sp)
if (sp->imvalue == match->dc.left || sp->imvalue == match->ans)
return TRUE;
}
return FALSE;
}
//-------------------------------------------------------------------------
static void EnterCopy(QUAD *cp)
{
if (cp->ans->mode != i_direct || cp->dc.left->mode != i_direct)
return ;
if (cp->ans->size != cp->dc.left->size)
return ;
if (copy_count >= max_copies)
{
QUAD **newarray = oalloc(sizeof(QUAD*)*(max_copies += 256));
if (copy_count)
memcpy(copyarray, newarray, sizeof(QUAD*) * copy_count);
copyarray = newarray;
}
cp->copy = copy_count;
anshash(copyhash, cp->dc.left, (QUAD*)copy_count);
anshash(copyhash, cp->ans, (QUAD*)copy_count);
copyarray[copy_count++] = cp;
}
//-------------------------------------------------------------------------
static void CountCopies(void)
{
QUAD *list = blockarray[0]->block->head;
max_copies = copy_count = 0;
while (list)
{
if (list->dc.opcode == i_assn)
{
EnterCopy(list);
}
list = list->fwd;
}
}
//-------------------------------------------------------------------------
static void CreateBitmaps(void)
{
int i;
copybytes = (copy_count + 8) / 8;
if (copybytes % 4)
copybytes += 4-copybytes % 4;
for (i = 0; i < blocknum; i++)
{
blockarray[i]->block->p_cgen = oalloc(copybytes);
blockarray[i]->block->p_ckill = oalloc(copybytes);
blockarray[i]->block->p_cin = oalloc(copybytes);
blockarray[i]->block->p_cout = oalloc(copybytes);
}
temparray5 = oalloc(copybytes);
}
//-------------------------------------------------------------------------
static void CalculateCopyBasics(void)
{
int i;
QUAD *list;
BLOCK *l;
for (i = 0; i < blocknum; i++)
{
l = blockarray[i]->block;
list = l->head;
memcpy(temparray4, l->p_pin, sourcebytes *pointer_count);
while (list && list->back != l->tail)
{
switch (list->dc.opcode)
{
case i_assn:
if (list->ans->mode == i_direct && list->dc.left->mode ==
i_direct && list->ans->size == list->dc.left->size)
{
setbit(l->p_cgen, list->copy);
clearbit(l->p_ckill, list->copy);
}
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:
if (list->ans->mode == i_ind)
{
int ptr = findPointer(list->ans);
if (ptr < pointer_count)
{
if (isset(temparray4 + ptr * sourcebytes, 0))
{
memset(l->p_cgen, 0, copybytes);
memset(l->p_ckill, 0xff, copybytes);
}
else
for (i = 1; i < source_count; i++)
{
if (isset(temparray4 + ptr * sourcebytes, i))
{
int def2 = FindDefinition(i, list);
if (def2 == - 1)
DIAG(
"Calculate Copy Basics - could not find definition");
else
{
SYM *sp = varsp(defiarray[def2]
->dc.left->offset);
LIST *l1;
if (sp)
{
l1 = findans(copyhash, sp->imvalue);
while (l1)
{
clearbit(l->p_cgen, (int)l1
->data);
setbit(l->p_ckill, (int)l1
->data);
l1 = l1->link;
}
}
if (defiarray[def2]->dc.right)
{
sp = varsp(defiarray[def2]
->dc.right->offset);
if (sp)
{
l1 = findans(copyhash, sp
->imvalue);
while (l1)
{
clearbit(l->p_cgen, (int)l1
->data);
setbit(l->p_ckill, (int)l1
->data);
l1 = l1->link;
}
}
}
}
}
}
}
}
else if (list->ans->mode == i_direct)
{
LIST *l1 = findans(copyhash, list->ans);
while (l1)
{
if (list->dc.opcode != i_assn || list->copy != (int)
l1->data)
{
clearbit(l->p_cgen, (int)l1->data);
setbit(l->p_ckill, (int)l1->data);
}
l1 = l1->link;
}
}
break;
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:
break;
case i_parm:
if (list->dc.left->mode == i_direct)
{
SYM *sp = varsp(list->dc.left->offset);
if (sp)
{
int ptr = findPointer(list->dc.left);
if (ptr < pointer_count)
{
if (isset(temparray4, 0))
{
memset(l->p_cgen, 0, copybytes);
memset(l->p_ckill, 0xff, copybytes);
}
else
{
for (i = 1; i < source_count; i++)
{
if (isset(temparray4 + ptr *
sourcebytes, i))
{
int def2 = FindDefinition(i, list);
if (def2 == - 1)
DIAG(
"Calculate Copy Basics - could not find definition");
else
{
SYM *sp = varsp(defiarray[def2]
->dc.left->offset);
LIST *l1;
if (sp)
{
l1 = findans(copyhash, sp
->imvalue);
while (l1)
{
clearbit(l->p_cgen,
(int)l1->data);
setbit(l->p_ckill, (int)
l1->data);
l1 = l1->link;
}
}
if (defiarray[def2]->dc.right)
{
sp = varsp(defiarray[def2]
->dc.right->offset);
if (sp)
{
l1 = findans(copyhash,
sp->imvalue);
while (l1)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -