MWCC/compiler_and_linker/unsorted/IROUseDef.c

1433 lines
50 KiB
C
Raw Normal View History

#include "compiler/IROUseDef.h"
#include "compiler/IRODump.h"
#include "compiler/IROVars.h"
#include "compiler/IroFlowgraph.h"
#include "compiler/IroLinearForm.h"
#include "compiler/IroMalloc.h"
#include "compiler/IroPointerAnalysis.h"
#include "compiler/IroTransform.h"
#include "compiler/IroUtil.h"
#include "compiler/CompilerTools.h"
#include "compiler/CError.h"
#include "compiler/CFunc.h"
#include "compiler/CInt64.h"
#include "compiler/CMachine.h"
#include "compiler/CParser.h"
#include "compiler/objects.h"
#include "compiler/types.h"
#include "compiler/InlineAsm.h"
#include "compiler/InlineAsmPPC.h"
ENodeType IRO_NonAssignmentOp[MAXEXPR];
typedef CInt64 (*AssignmentFoldingFunc)(CInt64, CInt64);
static AssignmentFoldingFunc AssignmentFoldingFunction[MAXEXPR];
static SInt32 NumDefs;
static IRODef *FirstDef;
static IRODef *LastDef;
static SInt32 NumUses;
static BitVector *Reaches;
static BitVector *MightReachAnyUse;
static BitVector *alldefs;
static BitVector *alluses;
static BitVector *defset;
static BitVector *useset;
IROUse *IRO_FirstVarUse;
IROUse *IRO_LastVarUse;
// forward decls
static void AddDefToRange(IRODef *def);
static void MakeDef(VarRecord *var, IROLinear *linear, IRONode *node, Boolean flag) {
IRODef *def = oalloc(sizeof(IRODef));
def->index = NumDefs++;
def->node = node;
def->linear = linear;
def->var = var;
def->globalnext = NULL;
def->x18 = 0;
def->x1A = Inline_IsObjectData(var->object);
def->x1B = var->xB;
def->x1C = flag;
def->x1D = 0;
if (FirstDef)
LastDef->globalnext = def;
else
FirstDef = def;
LastDef = def;
def->varnext = var->defs;
var->defs = def;
}
static void MakeUse(VarRecord *var, IROLinear *linear, IRONode *node) {
IROUse *use = oalloc(sizeof(IROUse));
use->index = NumUses++;
use->node = node;
use->linear = linear;
use->var = var;
use->globalnext = NULL;
use->x1C = 0;
if (IRO_FirstVarUse)
IRO_LastVarUse->globalnext = use;
else
IRO_FirstVarUse = use;
IRO_LastVarUse = use;
use->varnext = var->uses;
var->uses = use;
}
static void FindDefsAndUses(void) {
VarRecord *var;
IROLinear *linear;
IRONode *node;
NumDefs = 0;
NumUses = 0;
IRO_FirstVarUse = NULL;
FirstDef = NULL;
for (var = IRO_FirstVar; var; var = var->next) {
var->defs = NULL;
var->uses = NULL;
var->xC = 0;
}
for (node = IRO_FirstNode; node; node = node->nextnode) {
for (linear = node->first; linear; linear = linear->next) {
if (IS_LINEAR_ENODE(linear, EOBJREF)) {
Object *obj = linear->u.node->data.objref;
if ((linear->flags & IROLF_Ind) && (!(linear->flags & IROLF_Assigned) || (linear->flags & IROLF_Used))) {
if ((var = IRO_FindVar(obj, 0, 1)))
MakeUse(var, linear, node);
}
}
if (IRO_IsAssignment(linear) && (var = IRO_FindAssigned(linear))) {
MakeDef(
var,
linear,
node,
(linear->rtype->size == var->object->type->size) && !IRO_IsBitField
);
}
if (linear->type == IROLinearAsm) {
IAEffects effects;
int i;
CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects);
for (i = 0; i < effects.numoperands; i++) {
var = IRO_FindVar(effects.operands[i].object, 0, 1);
switch (effects.operands[i].type) {
case IAEffect_0:
MakeUse(var, linear, node);
break;
case IAEffect_1:
MakeDef(
var,
linear,
node,
(effects.operands[i].offset == 0) && (effects.operands[i].size == var->object->type->size)
);
break;
case IAEffect_2:
MakeDef(var, linear, node, 0);
break;
case IAEffect_4:
MakeUse(var, linear, node);
MakeDef(
var,
linear,
node,
(effects.operands[i].offset == 0) && (effects.operands[i].size == var->object->type->size)
);
break;
}
}
}
if (linear == node->last)
break;
}
}
for (var = IRO_FirstVar; var; var = var->next)
MakeDef(var, NULL, NULL, 1);
}
static void MarkUses(Object *obj) {
VarRecord *var;
IRODef *def;
if ((var = IRO_FindVar(obj, 0, 1))) {
for (def = var->defs; def; def = def->varnext) {
if (Bv_IsBitSet(def->index, Reaches)) {
Bv_SetBit(def->index, MightReachAnyUse);
def->x18++;
}
}
var->xC = 1;
}
}
static Boolean IsIncOrDec(IROLinear *linear) {
switch (linear->type) {
case IROLinearOp1Arg:
if (linear->nodetype == EPOSTINC || linear->nodetype == EPOSTDEC || linear->nodetype == EPREINC || linear->nodetype == EPREDEC) {
if (!(linear->u.monadic->flags & IROLF_BitfieldIndirect))
return 1;
}
break;
case IROLinearOp2Arg:
if (linear->nodetype == EADDASS || linear->nodetype == ESUBASS) {
if (IRO_IsIntConstant(linear->u.diadic.right) && !(linear->u.diadic.left->flags & IROLF_BitfieldIndirect))
return 1;
}
break;
}
return 0;
}
static Boolean IsOtherSelfAssignment(IROLinear *linear) {
switch (linear->type) {
case IROLinearOp2Arg:
switch (linear->nodetype) {
case EMULASS:
case EDIVASS:
case ESHLASS:
case ESHRASS:
case EANDASS:
case EXORASS:
case EORASS:
if (IRO_IsIntConstant(linear->u.diadic.right))
return 1;
break;
}
break;
}
return 0;
}
CInt64 IRO_GetSelfAssignmentVal(IROLinear *linear) {
CInt64 result;
if (linear->type == IROLinearOp1Arg) {
switch (linear->nodetype) {
case EPOSTINC:
case EPREINC:
CInt64_SetLong(&result, 1);
break;
case EPOSTDEC:
case EPREDEC:
CInt64_SetLong(&result, -1);
break;
default:
2022-12-29 12:32:55 +00:00
CError_FATAL(445);
}
if (IS_TYPE_POINTER_ONLY(linear->rtype)) {
CInt64 mul;
CInt64_SetLong(&mul, TPTR_TARGET(linear->rtype)->size);
result = CInt64_Mul(result, mul);
}
} else if (linear->type == IROLinearOp2Arg) {
switch (linear->nodetype) {
case EMULASS:
case EDIVASS:
case EMODASS:
case EADDASS:
case ESHLASS:
case ESHRASS:
case EANDASS:
case EXORASS:
case EORASS:
result = linear->u.diadic.right->u.node->data.intval;
break;
case ESUBASS:
result = linear->u.diadic.right->u.node->data.intval;
result = CInt64_Neg(result);
break;
default:
2022-12-29 12:32:55 +00:00
CError_FATAL(491);
}
} else {
2022-12-29 12:32:55 +00:00
CError_FATAL(496);
}
return result;
}
static void UpdateUse(IROLinear *linear, CInt64 val, Type *type) {
IROLinear *father;
IROLinear *repl;
IROLinear *newdiadic;
if ((father = IRO_LocateFather(linear))) {
switch (father->type) {
case IROLinearOp1Arg:
switch (father->nodetype) {
case EPOSTINC:
case EPOSTDEC:
case EPREINC:
case EPREDEC:
val = CInt64_Add(val, IRO_GetSelfAssignmentVal(father));
father->nodetype = EADDASS;
father->type = IROLinearOp2Arg;
repl = IRO_NewIntConst(val, type);
father->u.diadic.right = repl;
IRO_PasteAfter(repl, repl, linear);
return;
}
break;
case IROLinearOp2Arg:
if (IRO_IsIntConstant(father->u.diadic.right)) {
switch (father->nodetype) {
case EADD:
case EADDASS:
father->u.diadic.right->u.node->data.intval = CInt64_Add(
father->u.diadic.right->u.node->data.intval, val);
return;
case ESUB:
case ESUBASS:
father->u.diadic.right->u.node->data.intval = CInt64_Sub(
father->u.diadic.right->u.node->data.intval, val);
return;
}
}
break;
}
}
repl = IRO_NewIntConst(val, type);
newdiadic = IRO_NewLinear(IROLinearOp2Arg);
newdiadic->index = ++IRO_NumLinear;
newdiadic->nodetype = EADD;
newdiadic->u.diadic.left = linear;
newdiadic->u.diadic.right = repl;
newdiadic->rtype = linear->rtype;
repl->next = newdiadic;
IRO_LocateFather_Cut_And_Paste_Without_Nopping(linear, newdiadic);
IRO_PasteAfter(repl, newdiadic, linear);
}
void IRO_InitializeNonAssignmentOpArray(void) {
int i;
for (i = 0; i < MAXEXPR; i++)
IRO_NonAssignmentOp[i] = MAXEXPR;
IRO_NonAssignmentOp[EPOSTINC] = MAXEXPR;
IRO_NonAssignmentOp[EPOSTDEC] = MAXEXPR;
IRO_NonAssignmentOp[EPREINC] = MAXEXPR;
IRO_NonAssignmentOp[EPREDEC] = MAXEXPR;
IRO_NonAssignmentOp[EINDIRECT] = MAXEXPR;
IRO_NonAssignmentOp[EMONMIN] = MAXEXPR;
IRO_NonAssignmentOp[EBINNOT] = MAXEXPR;
IRO_NonAssignmentOp[ELOGNOT] = MAXEXPR;
IRO_NonAssignmentOp[EFORCELOAD] = MAXEXPR;
IRO_NonAssignmentOp[EMUL] = MAXEXPR;
IRO_NonAssignmentOp[EMULV] = MAXEXPR;
IRO_NonAssignmentOp[EDIV] = MAXEXPR;
IRO_NonAssignmentOp[EMODULO] = MAXEXPR;
IRO_NonAssignmentOp[EADDV] = MAXEXPR;
IRO_NonAssignmentOp[ESUBV] = MAXEXPR;
IRO_NonAssignmentOp[EADD] = MAXEXPR;
IRO_NonAssignmentOp[ESUB] = MAXEXPR;
IRO_NonAssignmentOp[ESHL] = MAXEXPR;
IRO_NonAssignmentOp[ESHR] = MAXEXPR;
IRO_NonAssignmentOp[ELESS] = MAXEXPR;
IRO_NonAssignmentOp[EGREATER] = MAXEXPR;
IRO_NonAssignmentOp[ELESSEQU] = MAXEXPR;
IRO_NonAssignmentOp[EGREATEREQU] = MAXEXPR;
IRO_NonAssignmentOp[EEQU] = MAXEXPR;
IRO_NonAssignmentOp[ENOTEQU] = MAXEXPR;
IRO_NonAssignmentOp[EAND] = MAXEXPR;
IRO_NonAssignmentOp[EXOR] = MAXEXPR;
IRO_NonAssignmentOp[EOR] = MAXEXPR;
IRO_NonAssignmentOp[ELAND] = MAXEXPR;
IRO_NonAssignmentOp[ELOR] = MAXEXPR;
IRO_NonAssignmentOp[EASS] = MAXEXPR;
IRO_NonAssignmentOp[EMULASS] = EMUL;
IRO_NonAssignmentOp[EDIVASS] = EDIV;
IRO_NonAssignmentOp[EMODASS] = EMODULO;
IRO_NonAssignmentOp[EADDASS] = EADD;
IRO_NonAssignmentOp[ESUBASS] = ESUB;
IRO_NonAssignmentOp[ESHLASS] = ESHL;
IRO_NonAssignmentOp[ESHRASS] = ESHR;
IRO_NonAssignmentOp[EANDASS] = EAND;
IRO_NonAssignmentOp[EXORASS] = EXOR;
IRO_NonAssignmentOp[EORASS] = EOR;
IRO_NonAssignmentOp[ECOMMA] = MAXEXPR;
IRO_NonAssignmentOp[EPMODULO] = MAXEXPR;
IRO_NonAssignmentOp[EROTL] = MAXEXPR;
IRO_NonAssignmentOp[EROTR] = MAXEXPR;
IRO_NonAssignmentOp[EBCLR] = MAXEXPR;
IRO_NonAssignmentOp[EBTST] = MAXEXPR;
IRO_NonAssignmentOp[EBSET] = MAXEXPR;
IRO_NonAssignmentOp[ETYPCON] = MAXEXPR;
IRO_NonAssignmentOp[EBITFIELD] = MAXEXPR;
IRO_NonAssignmentOp[EINTCONST] = MAXEXPR;
IRO_NonAssignmentOp[EFLOATCONST] = MAXEXPR;
IRO_NonAssignmentOp[ESTRINGCONST] = MAXEXPR;
IRO_NonAssignmentOp[ECOND] = MAXEXPR;
IRO_NonAssignmentOp[EFUNCCALL] = MAXEXPR;
IRO_NonAssignmentOp[EFUNCCALLP] = MAXEXPR;
IRO_NonAssignmentOp[EOBJREF] = MAXEXPR;
IRO_NonAssignmentOp[EMFPOINTER] = MAXEXPR;
IRO_NonAssignmentOp[ENULLCHECK] = MAXEXPR;
IRO_NonAssignmentOp[EPRECOMP] = MAXEXPR;
IRO_NonAssignmentOp[ETEMP] = MAXEXPR;
IRO_NonAssignmentOp[EARGOBJ] = MAXEXPR;
IRO_NonAssignmentOp[ELOCOBJ] = MAXEXPR;
IRO_NonAssignmentOp[ELABEL] = MAXEXPR;
IRO_NonAssignmentOp[ESETCONST] = MAXEXPR;
IRO_NonAssignmentOp[ENEWEXCEPTION] = MAXEXPR;
IRO_NonAssignmentOp[ENEWEXCEPTIONARRAY] = MAXEXPR;
IRO_NonAssignmentOp[EOBJLIST] = MAXEXPR;
IRO_NonAssignmentOp[EMEMBER] = MAXEXPR;
IRO_NonAssignmentOp[ETEMPLDEP] = MAXEXPR;
IRO_NonAssignmentOp[EINSTRUCTION] = MAXEXPR;
IRO_NonAssignmentOp[EDEFINE] = MAXEXPR;
IRO_NonAssignmentOp[EREUSE] = MAXEXPR;
IRO_NonAssignmentOp[EASSBLK] = MAXEXPR;
IRO_NonAssignmentOp[EVECTOR128CONST] = MAXEXPR;
IRO_NonAssignmentOp[ECONDASS] = MAXEXPR;
}
void IRO_InitializeAssignmentFoldingFunctionArray(void) {
int i;
for (i = 0; i < MAXEXPR; i++)
AssignmentFoldingFunction[i] = NULL;
AssignmentFoldingFunction[EPOSTINC] = NULL;
AssignmentFoldingFunction[EPOSTDEC] = NULL;
AssignmentFoldingFunction[EPREINC] = NULL;
AssignmentFoldingFunction[EPREDEC] = NULL;
AssignmentFoldingFunction[EINDIRECT] = NULL;
AssignmentFoldingFunction[EMONMIN] = NULL;
AssignmentFoldingFunction[EBINNOT] = NULL;
AssignmentFoldingFunction[ELOGNOT] = NULL;
AssignmentFoldingFunction[EFORCELOAD] = NULL;
AssignmentFoldingFunction[EMUL] = NULL;
AssignmentFoldingFunction[EMULV] = NULL;
AssignmentFoldingFunction[EDIV] = NULL;
AssignmentFoldingFunction[EMODULO] = NULL;
AssignmentFoldingFunction[EADDV] = NULL;
AssignmentFoldingFunction[ESUBV] = NULL;
AssignmentFoldingFunction[EADD] = NULL;
AssignmentFoldingFunction[ESUB] = NULL;
AssignmentFoldingFunction[ESHL] = NULL;
AssignmentFoldingFunction[ESHR] = NULL;
AssignmentFoldingFunction[ELESS] = NULL;
AssignmentFoldingFunction[EGREATER] = NULL;
AssignmentFoldingFunction[ELESSEQU] = NULL;
AssignmentFoldingFunction[EGREATEREQU] = NULL;
AssignmentFoldingFunction[EEQU] = NULL;
AssignmentFoldingFunction[ENOTEQU] = NULL;
AssignmentFoldingFunction[EAND] = NULL;
AssignmentFoldingFunction[EXOR] = NULL;
AssignmentFoldingFunction[EOR] = NULL;
AssignmentFoldingFunction[ELAND] = NULL;
AssignmentFoldingFunction[ELOR] = NULL;
AssignmentFoldingFunction[EASS] = NULL;
AssignmentFoldingFunction[EMULASS] = CInt64_Mul;
AssignmentFoldingFunction[EDIVASS] = CInt64_Mul;
AssignmentFoldingFunction[EMODASS] = NULL;
AssignmentFoldingFunction[EADDASS] = CInt64_Add;
AssignmentFoldingFunction[ESUBASS] = CInt64_Add;
AssignmentFoldingFunction[ESHLASS] = CInt64_Add;
AssignmentFoldingFunction[ESHRASS] = CInt64_Add;
AssignmentFoldingFunction[EANDASS] = CInt64_And;
AssignmentFoldingFunction[EXORASS] = CInt64_Xor;
AssignmentFoldingFunction[EORASS] = CInt64_Or;
AssignmentFoldingFunction[ECOMMA] = NULL;
AssignmentFoldingFunction[EPMODULO] = NULL;
AssignmentFoldingFunction[EROTL] = NULL;
AssignmentFoldingFunction[EROTR] = NULL;
AssignmentFoldingFunction[EBCLR] = NULL;
AssignmentFoldingFunction[EBTST] = NULL;
AssignmentFoldingFunction[EBSET] = NULL;
AssignmentFoldingFunction[ETYPCON] = NULL;
AssignmentFoldingFunction[EBITFIELD] = NULL;
AssignmentFoldingFunction[EINTCONST] = NULL;
AssignmentFoldingFunction[EFLOATCONST] = NULL;
AssignmentFoldingFunction[ESTRINGCONST] = NULL;
AssignmentFoldingFunction[ECOND] = NULL;
AssignmentFoldingFunction[EFUNCCALL] = NULL;
AssignmentFoldingFunction[EFUNCCALLP] = NULL;
AssignmentFoldingFunction[EOBJREF] = NULL;
AssignmentFoldingFunction[EMFPOINTER] = NULL;
AssignmentFoldingFunction[ENULLCHECK] = NULL;
AssignmentFoldingFunction[EPRECOMP] = NULL;
AssignmentFoldingFunction[ETEMP] = NULL;
AssignmentFoldingFunction[EARGOBJ] = NULL;
AssignmentFoldingFunction[ELOCOBJ] = NULL;
AssignmentFoldingFunction[ELABEL] = NULL;
AssignmentFoldingFunction[ESETCONST] = NULL;
AssignmentFoldingFunction[ENEWEXCEPTION] = NULL;
AssignmentFoldingFunction[ENEWEXCEPTIONARRAY] = NULL;
AssignmentFoldingFunction[EOBJLIST] = NULL;
AssignmentFoldingFunction[EMEMBER] = NULL;
AssignmentFoldingFunction[ETEMPLDEP] = NULL;
AssignmentFoldingFunction[EINSTRUCTION] = NULL;
AssignmentFoldingFunction[EDEFINE] = NULL;
AssignmentFoldingFunction[EREUSE] = NULL;
AssignmentFoldingFunction[EASSBLK] = NULL;
AssignmentFoldingFunction[EVECTOR128CONST] = NULL;
AssignmentFoldingFunction[ECONDASS] = NULL;
}
static void UpdateUseForOtherSelfAssignment(IROLinear *a, IROLinear *b, Type *type) {
CInt64 val;
IROLinear *father;
IROLinear *repl;
IROLinear *newdiadic;
val = IRO_GetSelfAssignmentVal(b);
if ((father = IRO_LocateFather(a)) && father->type == IROLinearOp2Arg && IRO_IsIntConstant(father->u.diadic.right)) {
CInt64 var_30 = father->u.diadic.right->u.node->data.intval;
if (AssignmentFoldingFunction[b->nodetype] && ((father->nodetype == b->nodetype) || (father->nodetype == IRO_NonAssignmentOp[b->nodetype]))) {
CInt64 v;
CInt64 folded;
CInt64_SetLong(&v, b->rtype->size * 8);
folded = AssignmentFoldingFunction[b->nodetype](var_30, val);
if (b->nodetype == ESHRASS && !is_unsigned(b->rtype)) {
if (CInt64_LessU(var_30, v) && CInt64_LessU(val, v)) {
if (CInt64_GreaterEqualU(folded, v))
folded = CInt64_Sub(v, cint64_one);
father->u.diadic.right->u.node->data.intval = folded;
return;
}
} else {
father->u.diadic.right->u.node->data.intval = folded;
return;
}
} else {
switch (b->nodetype) {
case EMULASS:
if (father->nodetype == ESHL || father->nodetype == ESHLASS) {
SInt32 powvalue;
if (IRO_IsPow2(b->u.diadic.right, &powvalue)) {
if (powvalue > 0) {
CInt64 v;
CInt64_SetLong(&v, powvalue);
father->u.diadic.right->u.node->data.intval = CInt64_Add(v, var_30);
}
} else {
father->nodetype = (father->nodetype == ESHL) ? EMUL : EMULASS;
var_30 = CInt64_Shl(cint64_one, var_30);
father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val);
}
return;
}
break;
case EDIVASS:
if ((father->nodetype == ESHR || father->nodetype == ESHRASS) && is_unsigned(father->rtype)) {
SInt32 powvalue;
if (IRO_IsPow2(b->u.diadic.right, &powvalue)) {
if (powvalue > 0) {
CInt64 v;
CInt64_SetLong(&v, powvalue);
father->u.diadic.right->u.node->data.intval = CInt64_Add(v, var_30);
}
} else {
father->nodetype = (father->nodetype == ESHR) ? EDIV : EDIVASS;
var_30 = CInt64_Shl(cint64_one, var_30);
father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val);
}
return;
}
break;
case ESHLASS:
if (father->nodetype == EMUL || father->nodetype == EMULASS) {
SInt32 powvalue;
if (IRO_IsPow2(father->u.diadic.right, &powvalue)) {
if (powvalue > 0) {
CInt64 v;
father->nodetype = (father->nodetype == EMUL) ? ESHL : ESHLASS;
CInt64_SetLong(&v, powvalue);
father->u.diadic.right->u.node->data.intval = CInt64_Add(v, val);
}
} else {
val = CInt64_Shl(cint64_one, val);
father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val);
}
return;
} else if (father->nodetype == ESHR || father->nodetype == ESHRASS) {
if (CInt64_Equal(var_30, val) && is_unsigned(father->rtype)) {
father->nodetype = (father->nodetype == ESHR) ? EAND : EANDASS;
if (father->rtype->size < 8) {
CInt64 v;
CInt64_SetLong(&v, 64 - (father->rtype->size * 8));
val = CInt64_Add(val, v);
}
father->u.diadic.right->u.node->data.intval = CInt64_ShrU(cint64_negone, val);
return;
}
}
break;
case ESHRASS:
if ((father->nodetype == EDIV || father->nodetype == EDIVASS) && is_unsigned(father->rtype)) {
SInt32 powvalue;
if (IRO_IsPow2(father->u.diadic.right, &powvalue)) {
if (powvalue > 0) {
CInt64 v;
father->nodetype = (father->nodetype == EDIV) ? ESHR : ESHRASS;
CInt64_SetLong(&v, powvalue);
father->u.diadic.right->u.node->data.intval = CInt64_Add(v, val);
}
} else {
val = CInt64_Shl(cint64_one, val);
father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val);
}
return;
} else if (father->nodetype == ESHL || father->nodetype == ESHLASS) {
if (CInt64_Equal(var_30, val)) {
father->nodetype = (father->nodetype == ESHL) ? EAND : EANDASS;
father->u.diadic.right->u.node->data.intval = CInt64_Shl(cint64_negone, val);
return;
}
}
break;
}
}
}
repl = IRO_NewIntConst(val, type);
newdiadic = IRO_NewLinear(IROLinearOp2Arg);
newdiadic->index = ++IRO_NumLinear;
newdiadic->nodetype = IRO_NonAssignmentOp[b->nodetype];
newdiadic->u.diadic.left = a;
newdiadic->u.diadic.right = repl;
newdiadic->rtype = a->rtype;
repl->next = newdiadic;
IRO_LocateFather_Cut_And_Paste_Without_Nopping(a, newdiadic);
IRO_PasteAfter(repl, newdiadic, a);
}
static Boolean PropagateIncsAndDecs(void) {
IRODef *def;
Boolean result;
result = 0;
def = FirstDef;
while (def) {
if (
def->linear &&
def->x1C &&
IsIncOrDec(def->linear) &&
!(def->linear->flags & IROLF_Reffed) &&
(IS_TYPE_INT_OR_ENUM(def->linear->rtype) || IS_TYPE_POINTER_ONLY(def->linear->rtype)) &&
IRO_TypesEqual(def->linear->rtype, def->var->object->type) &&
!is_volatile_object(def->var->object)
) {
IROUse *use;
IROUse *use2;
IROLinear *father;
CInt64 val;
SInt32 i;
Type *type;
for (use = def->var->uses, i = 0; use; use = use->varnext) {
if (Bv_IsBitSet(def->index, use->x18)) {
if (
use->x1C == 1 &&
use->linear->type == IROLinearOperand &&
(father = IRO_LocateFather(use->linear)) &&
IRO_IsVariable(father) &&
IRO_TypesEqual(def->linear->rtype, father->rtype)
) {
if (use->linear->flags & IROLF_Assigned) {
if (!((father = IRO_LocateFather(father)) && IsIncOrDec(father) && !(father->flags & IROLF_Reffed)))
goto nextDef;
}
i++;
} else {
goto nextDef;
}
}
}
if (i == def->x18) {
for (use = def->var->uses; use; use = use->varnext) {
if (Bv_IsBitSet(def->index, use->x18)) {
IRO_Dump("Propagating inc/dec from %d to %d\n", def->linear->index, use->linear->index);
father = IRO_LocateFather(use->linear);
val = IRO_GetSelfAssignmentVal(def->linear);
type = def->linear->rtype;
if (IS_TYPE_POINTER_ONLY(def->linear->rtype))
type = TYPE(&stunsignedlong);
UpdateUse(father, val, type);
result = 1;
for (use2 = def->var->uses; use2; use2 = use2->varnext) {
if (use2->linear == def->linear->u.monadic->u.diadic.left) {
use->x1C = use2->x1C;
Bv_Copy(use2->x18, use->x18);
break;
}
}
}
}
def->x18 = 0;
IRO_NopNonSideEffects(def->linear, -1);
def->linear->type = IROLinearNop;
IRO_Dump("Removing deadddd assignment %d\n", def->linear->index);
}
}
nextDef:
def = def->globalnext;
}
return result;
}
static Boolean PropagateOtherSelfAssignments(void) {
IRODef *def;
Boolean result;
result = 0;
def = FirstDef;
while (def) {
if (
def->linear &&
def->x1C &&
IsOtherSelfAssignment(def->linear) &&
!(def->linear->flags & IROLF_Reffed) &&
IS_TYPE_INT_OR_ENUM(def->linear->rtype) &&
IRO_TypesEqual(def->linear->rtype, def->var->object->type) &&
!is_volatile_object(def->var->object)
)
{
IROUse *use;
IROUse *use2;
IROLinear *father;
SInt32 i;
Type *type;
for (use = def->var->uses, i = 0; use; use = use->varnext) {
if (Bv_IsBitSet(def->index, use->x18)) {
if (
use->x1C == 1 &&
use->linear->type == IROLinearOperand &&
(father = IRO_LocateFather(use->linear)) &&
IRO_IsVariable(father) &&
IRO_TypesEqual(def->linear->rtype, father->rtype)
) {
if (use->linear->flags & IROLF_Assigned) {
if (!((father = IRO_LocateFather(father)) && IsOtherSelfAssignment(father) && (father->nodetype == def->linear->nodetype) && !(father->flags & IROLF_Reffed)))
goto nextDef;
}
i++;
} else {
goto nextDef;
}
}
}
if (i == def->x18) {
for (use = def->var->uses; use; use = use->varnext) {
if (Bv_IsBitSet(def->index, use->x18)) {
IRO_Dump("Propagating self assignment from %d to %d\n", def->linear->index, use->linear->index);
father = IRO_LocateFather(use->linear);
UpdateUseForOtherSelfAssignment(father, def->linear, def->linear->rtype);
result = 1;
for (use2 = def->var->uses; use2; use2 = use2->varnext) {
if (use2->linear == def->linear->u.monadic->u.diadic.left) {
use->x1C = use2->x1C;
Bv_Copy(use2->x18, use->x18);
break;
}
}
}
}
def->x18 = 0;
IRO_NopNonSideEffects(def->linear, -1);
def->linear->type = IROLinearNop;
IRO_Dump("Removing deadddd assignment %d\n", def->linear->index);
}
}
nextDef:
def = def->globalnext;
}
return result;
}
static void MarkUsesByIndirect(IROLinear *linear, BitVector *a, BitVector *b) {
IROListNode *list;
IROLinear *nd;
Object *obj;
VarRecord *var;
Boolean foundObjRef;
IROListNode *scan;
IRODef *def;
Boolean found;
found = 0;
if (linear && copts.opt_pointer_analysis && linear->pointsToFunction && FunctionName) {
IROListNode *resultList;
resultList = NULL;
PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, linear, &resultList);
if ((list = resultList)) {
for (scan = list; scan; scan = scan->nextList) {
if (!scan->list.head || !scan->list.tail) {
found = 1;
break;
}
foundObjRef = 0;
for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) {
if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
foundObjRef = 1;
break;
}
}
if (!foundObjRef) {
found = 1;
break;
}
}
if (!found) {
while (list) {
for (nd = list->list.head; nd != list->list.tail->next; nd = nd->next) {
if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
obj = nd->u.node->data.objref;
2022-12-29 12:32:55 +00:00
CError_ASSERT(1422, obj != NULL);
var = IRO_FindVar(obj, 1, 1);
2022-12-29 12:32:55 +00:00
CError_ASSERT(1424, var != NULL);
for (def = var->defs; def; def = def->varnext) {
if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) {
def->x18++;
Bv_SetBit(def->index, MightReachAnyUse);
}
}
}
}
list = list->nextList;
}
}
while (resultList) {
IROListNode *next = resultList->nextList;
IRO_free(resultList);
resultList = next;
}
} else {
found = 1;
}
} else {
found = 1;
}
if (found) {
Bv_Copy(Reaches, a);
Bv_And(b, a);
Bv_Or(a, MightReachAnyUse);
for (def = FirstDef; def; def = def->globalnext) {
if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches)))
def->x18++;
}
}
}
static void MarkUsesByFunctionCall(IROLinear *linear, BitVector *a, BitVector *b) {
ObjectList *olist;
IROLinear *funcnd;
IROListNode *list;
IROLinear *nd;
Object *obj;
VarRecord *var;
Boolean foundObjRef;
IROListNode *scan;
IRODef *def;
Boolean found;
found = 0;
if ((funcnd = linear->u.funccall.linear8) && copts.opt_pointer_analysis && funcnd->pointsToFunction && FunctionName) {
IROListNode *resultList;
ObjectList *depsList;
resultList = NULL;
PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, funcnd, &resultList);
if (resultList) {
for (scan = resultList; scan; scan = scan->nextList) {
if (!scan->list.head || !scan->list.tail) {
found = 1;
break;
}
foundObjRef = 0;
for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) {
if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
foundObjRef = 1;
obj = nd->u.node->data.objref;
2022-12-29 12:32:55 +00:00
CError_ASSERT(1522, obj != NULL);
depsList = NULL;
PointerAnalysis_GetFunctionDependencies(obj, linear, &depsList);
for (olist = depsList; olist; olist = olist->next) {
if (!olist->object) {
found = 1;
break;
}
}
while (depsList) {
olist = depsList->next;
IRO_free(depsList);
depsList = olist;
}
if (found)
break;
}
}
if (!foundObjRef)
found = 1;
if (found)
break;
}
if (!found) {
for (list = resultList; list; list = list->nextList) {
for (nd = list->list.head; nd != list->list.tail->next; nd = nd->next) {
if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
obj = nd->u.node->data.objref;
depsList = NULL;
PointerAnalysis_GetFunctionDependencies(obj, linear, &depsList);
for (olist = depsList; olist; olist = olist->next) {
var = IRO_FindVar(olist->object, 1, 1);
2022-12-29 12:32:55 +00:00
CError_ASSERT(1573, var != NULL);
for (def = var->defs; def; def = def->varnext) {
if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) {
def->x18++;
Bv_SetBit(def->index, MightReachAnyUse);
}
}
}
while (depsList) {
olist = depsList->next;
IRO_free(depsList);
depsList = olist;
}
}
}
}
}
while (resultList) {
IROListNode *next = resultList->nextList;
IRO_free(resultList);
resultList = next;
}
} else {
found = 1;
}
} else {
found = 1;
}
if (found) {
Bv_Copy(Reaches, a);
Bv_And(b, a);
Bv_Or(a, MightReachAnyUse);
for (def = FirstDef; def; def = def->globalnext) {
if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches)))
def->x18++;
}
}
if (linear->stmt && IRO_FunctionCallMightThrowException(linear))
IRO_WalkExcActions(linear->stmt->dobjstack, MarkUses);
}
static Boolean UseOfVarIsInsideASimpleDefOfVar(IROUse *use) {
VarRecord *var;
VarRecord *varAss;
IROLinear *nd;
IROLinear *nd2;
if ((var = use->var)) {
if ((nd = use->linear) && (nd->flags & IROLF_4000))
return 0;
while (nd && (nd->flags & IROLF_Reffed))
nd = nd->next;
if (
nd &&
IRO_IsAssignment(nd) &&
(varAss = IRO_FindAssigned(nd)) &&
varAss == var &&
!IRO_HasSideEffect((nd->type == IROLinearOp1Arg) ? nd->u.monadic : nd->u.diadic.left) &&
(!(nd2 = (nd->type == IROLinearOp1Arg) ? NULL : nd->u.diadic.right) || !IRO_HasSideEffect(nd2))
) {
return 1;
}
}
return 0;
}
static Boolean AllLoopDefUsesAreInSimpleLoopDefs(IRODef *def) {
VarRecord *var;
IRODef *scan;
IROUse *use;
if ((var = def->var)) {
for (scan = var->defs; scan; scan = scan->varnext) {
if (scan->node && scan->node->loopdepth) {
for (use = var->uses; use; use = use->varnext) {
if (Bv_IsBitSet(scan->index, use->x18)) {
if (!use->node || !use->node->loopdepth || !UseOfVarIsInsideASimpleDefOfVar(use))
return 0;
}
}
}
}
return 1;
} else {
return 0;
}
}
static void MarkRemovableLoopDefs(void) {
IRODef *def;
IRODef *scan;
for (def = FirstDef; def; def = def->globalnext) {
if (!def->x1A && !def->x1B && def->node && def->node->loopdepth && !def->x1D &&
AllLoopDefUsesAreInSimpleLoopDefs(def) && def->var) {
for (scan = def->var->defs; scan; scan = scan->varnext) {
if (scan->node && scan->node->loopdepth)
scan->x1D = 1;
}
}
}
}
static Boolean EliminateReffedDeadStore(IRODef *def) {
Boolean isPostIncOrDec;
IROLinear *nd;
Boolean result;
nd = def->linear;
isPostIncOrDec = (nd->type == IROLinearOp1Arg) && (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC);
result = IRO_LocateFather(nd) != NULL;
if (result && IRO_IsAssignment(nd) && IRO_IsModifyOp[nd->nodetype])
result = IRO_TransformSelfAssignmentToAssignment(nd);
result = result && (nd->type == IROLinearOp2Arg) && (nd->nodetype == EASS);
if (result) {
def->x18 = 0;
IRO_Dump("Removing referenced dead assignment %d\n", nd->index);
if (isPostIncOrDec) {
IRO_NopNonSideEffects(nd->u.diadic.right, 0);
nd->type = IROLinearNop;
IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, nd->u.diadic.left);
} else {
IRO_NopNonSideEffects(nd->u.diadic.left, 0);
nd->type = IROLinearNop;
IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, nd->u.diadic.right);
}
}
return result;
}
Boolean IRO_UseDef(Boolean optDeadAssignments, Boolean optPropagation) {
Boolean result;
IRODef *gdef;
IROUse *guse;
IRODef *def;
IROUse *use;
IRONode *node;
IROLinear *nd;
VarRecord *var;
Boolean flag;
BitVector *bv3;
BitVector *bv2;
BitVector *bv;
int i;
FindDefsAndUses();
IRO_CheckForUserBreak();
for (use = IRO_FirstVarUse; use; use = use->globalnext)
Bv_AllocVector(&use->x18, NumDefs);
Bv_AllocVector(&MightReachAnyUse, NumDefs);
Bv_AllocVector(&bv, NumDefs);
IRO_CheckForUserBreak();
for (def = FirstDef; def; def = def->globalnext) {
if (def->x1A || def->x1B)
Bv_SetBit(def->index, bv);
}
Bv_AllocVector(&bv2, NumDefs);
gdef = FirstDef;
for (node = IRO_FirstNode; node; node = node->nextnode) {
Bv_AllocVector(&node->x16, NumDefs);
Bv_AllocVector(&node->x1E, NumDefs);
Bv_AllocVector(&node->x22, NumDefs);
Bv_AllocVector(&node->x1A, NumDefs);
for (nd = node->first; nd; nd = nd->next) {
while (gdef && gdef->linear == nd) {
Bv_SetBit(gdef->index, node->x1E);
if (gdef->x1C) {
for (def = gdef->var->defs; def; def = def->varnext) {
if (def != gdef) {
Bv_SetBit(def->index, node->x22);
Bv_ClearBit(def->index, node->x1E);
}
}
}
gdef = gdef->globalnext;
}
if (nd == node->last)
break;
}
if (node->numpred)
Bv_Set(node->x16);
Bv_Copy(node->x1E, node->x1A);
IRO_CheckForUserBreak();
}
Bv_AllocVector(&bv3, NumDefs);
do {
flag = 0;
for (node = IRO_FirstNode; node; node = node->nextnode) {
Bv_Clear(node->x16);
if (node->numpred) {
for (i = 0; i < node->numpred; i++)
Bv_Or(IRO_NodeTable[node->pred[i]]->x1A, node->x16);
} else if (node == IRO_FirstNode) {
for (var = IRO_FirstVar; var; var = var->next)
Bv_SetBit(var->defs->index, node->x16);
}
Bv_Copy(node->x16, bv3);
Bv_Minus(node->x22, bv3);
Bv_Or(node->x1E, bv3);
if (!Bv_Compare(bv3, node->x1A)) {
Bv_Copy(bv3, node->x1A);
flag = 1;
}
}
IRO_CheckForUserBreak();
} while (flag);
gdef = FirstDef;
guse = IRO_FirstVarUse;
Bv_AllocVector(&Reaches, NumDefs);
for (node = IRO_FirstNode; node; node = node->nextnode) {
Bv_Copy(node->x16, Reaches);
nd = node->first;
while (1) {
while (guse && guse->linear == nd) {
for (def = guse->var->defs; def; def = def->varnext) {
if (Bv_IsBitSet(def->index, Reaches)) {
Bv_SetBit(def->index, guse->x18);
Bv_SetBit(def->index, MightReachAnyUse);
def->x18++;
guse->x1C++;
}
}
guse = guse->globalnext;
}
if (nd->type == IROLinearFunccall) {
MarkUsesByFunctionCall(nd, bv2, bv);
} else if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT && !IRO_IsVariable(nd)) {
MarkUsesByIndirect(nd, bv2, bv);
} else if ((nd->type == IROLinearFunccall) ||
(nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT && !IRO_IsVariable(nd))) {
Bv_Copy(Reaches, bv2);
Bv_And(bv, bv2);
Bv_Or(bv2, MightReachAnyUse);
for (def = FirstDef; def; def = def->globalnext) {
if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches)))
def->x18++;
}
if (nd->type == IROLinearFunccall && nd->stmt && IRO_FunctionCallMightThrowException(nd))
IRO_WalkExcActions(nd->stmt->dobjstack, MarkUses);
}
if (nd->type == IROLinearAsm) {
IAEffects effects;
CodeGen_GetAsmEffects(nd->u.asm_stmt, &effects);
if (effects.x2) {
Bv_Copy(Reaches, bv2);
Bv_And(bv, bv2);
Bv_Or(bv2, MightReachAnyUse);
}
}
if (nd->type == IROLinearReturn || nd->type == IROLinearEnd) {
for (def = FirstDef; def; def = def->globalnext) {
if (def->x1A && Bv_IsBitSet(def->index, Reaches)) {
Bv_SetBit(def->index, MightReachAnyUse);
def->x18++;
}
}
}
while (gdef && gdef->linear == nd) {
if (gdef->x1C) {
for (def = gdef->var->defs; def; def = def->varnext)
Bv_ClearBit(def->index, Reaches);
}
Bv_SetBit(gdef->index, Reaches);
gdef = gdef->globalnext;
}
if (nd == node->last)
break;
nd = nd->next;
}
}
IRO_CheckForUserBreak();
result = 0;
if (optDeadAssignments) {
MarkRemovableLoopDefs();
for (def = FirstDef; def; def = def->globalnext) {
if (def->linear &&
(!Bv_IsBitSet(def->index, MightReachAnyUse) || def->x1D) &&
(copts.opt_pointer_analysis || !def->x1B) &&
def->linear->type != IROLinearAsm &&
(!def->linear->rtype || !CParser_IsVolatile(def->linear->rtype, def->linear->nodeflags & ENODE_FLAG_QUALS)) &&
!is_volatile_object(def->var->object)
) {
if (!(def->linear->flags & IROLF_Reffed)) {
def->x18 = 0;
IRO_NopNonSideEffects(def->linear, -1);
def->linear->type = IROLinearNop;
IRO_Dump("Removing dead assignment %d\n", def->linear->index);
result = 1;
} else {
result = EliminateReffedDeadStore(def);
}
}
}
}
IRO_CheckForUserBreak();
if (optPropagation) {
while (1) {
if (PropagateIncsAndDecs() || PropagateOtherSelfAssignments())
result = 1;
else
break;
}
}
IRO_CheckForUserBreak();
return result;
}
static IROLinear *GetOperand(IROLinear *nd) {
IROLinear *inner;
if (nd->type == IROLinearOperand)
return nd;
if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD) {
inner = GetOperand(nd->u.diadic.left);
if (!inner)
inner = GetOperand(nd->u.diadic.right);
return inner;
}
return NULL;
}
static IROLinear *GetAssigned(IROLinear *nd) {
if (!nd)
return NULL;
2022-12-29 12:32:55 +00:00
if (nd->type == IROLinearOp2Arg)
nd = nd->u.diadic.left;
2022-12-29 12:32:55 +00:00
else if (nd->type == IROLinearOp1Arg)
nd = nd->u.monadic;
2022-12-29 12:32:55 +00:00
else
CError_FATAL(2338);
2022-12-29 12:32:55 +00:00
if (nd->type != IROLinearOp1Arg || nd->nodetype != EINDIRECT)
CError_FATAL(2351);
nd = nd->u.monadic;
if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD)
nd = GetOperand(nd);
return nd;
}
static void AddUseToRange(IROUse *use) {
IRODef *def;
Bv_SetBit(use->index, useset);
Bv_ClearBit(use->index, alluses);
for (def = use->var->defs; def; def = def->varnext) {
if (Bv_IsBitSet(def->index, alldefs) && (Bv_IsBitSet(def->index, use->x18) || GetAssigned(def->linear) == use->linear))
AddDefToRange(def);
}
}
static void AddDefToRange(IRODef *def) {
IROUse *use;
IROLinear *assigned;
Bv_SetBit(def->index, defset);
Bv_ClearBit(def->index, alldefs);
for (use = def->var->uses, assigned = GetAssigned(def->linear); use; use = use->varnext) {
if (Bv_IsBitSet(use->index, alluses) && (Bv_IsBitSet(def->index, use->x18) || assigned == use->linear))
AddUseToRange(use);
}
}
static void ReplaceAssigned(IROLinear *nd, Object *from, Object *to) {
IROLinear *assigned;
if (
!(assigned = GetAssigned(nd)) ||
assigned->type != IROLinearOperand ||
assigned->u.node->type != EOBJREF ||
assigned->u.node->data.objref != from
2022-12-29 12:32:55 +00:00
)
CError_FATAL(2459);
assigned->u.node->data.objref = to;
}
static void ReplaceUsed(IROLinear *nd, Object *from, Object *to) {
2022-12-29 12:32:55 +00:00
CError_ASSERT(2482, nd->type == IROLinearOperand && nd->u.node->type == EOBJREF);
2022-12-29 12:32:55 +00:00
if (nd->u.node->data.objref == from)
nd->u.node->data.objref = to;
2022-12-29 12:32:55 +00:00
else if (nd->u.node->data.objref != to)
CError_FATAL(2494);
}
static void SplitOffRange(VarRecord *var) {
Object *newObj;
IRODef *def;
IROUse *use;
IRO_Dump("Splitting range for variable: %d\n", var->index);
IRO_DumpBits("Def set: ", defset);
IRO_DumpBits("Use set: ", useset);
IRO_DumpBits("All defs: ", alldefs);
IRO_DumpBits("All uses: ", alluses);
newObj = create_temp_object(var->object->type);
IRO_FindVar(newObj, 1, 1);
for (def = var->defs; def; def = def->varnext) {
if (Bv_IsBitSet(def->index, defset) && def->linear)
ReplaceAssigned(def->linear, var->object, newObj);
}
for (use = var->uses; use; use = use->varnext) {
if (Bv_IsBitSet(use->index, useset))
ReplaceUsed(use->linear, var->object, newObj);
}
}
void IRO_SplitLifetimes(void) {
VarRecord *var;
SInt32 numVars;
IRODef *def;
IROUse *use;
Boolean flag;
Bv_AllocVector(&alldefs, NumDefs);
Bv_AllocVector(&alluses, NumUses);
Bv_AllocVector(&defset, NumDefs);
Bv_AllocVector(&useset, NumUses);
var = IRO_FirstVar;
numVars = IRO_NumVars;
while (var && var->index <= numVars) {
if (var->object->datatype == DLOCAL && !is_volatile_object(var->object) && !var->xC && !var->xB && !var->x1E) {
Bv_Clear(alldefs);
Bv_Clear(alluses);
for (def = var->defs; def; def = def->varnext) {
if (def->linear && def->linear->type == IROLinearAsm)
goto skipThisVar;
Bv_SetBit(def->index, alldefs);
}
for (use = var->uses; use; use = use->varnext) {
if (use->linear && use->linear->type == IROLinearAsm)
goto skipThisVar;
Bv_SetBit(use->index, alluses);
}
flag = 1;
while (1) {
Bv_Clear(defset);
Bv_Clear(useset);
def = var->defs;
while (def && !Bv_IsBitSet(def->index, alldefs))
def = def->varnext;
if (!def)
break;
AddDefToRange(def);
if (Bv_IsEmpty(alldefs))
break;
if (!flag)
SplitOffRange(var);
flag = 0;
}
}
skipThisVar:
var = var->next;
}
IRO_CheckForUserBreak();
}