2022-12-14 00:16:59 +00:00
|
|
|
#include "compiler/IroPropagate.h"
|
|
|
|
#include "compiler/IroCSE.h"
|
|
|
|
#include "compiler/IroDump.h"
|
|
|
|
#include "compiler/IroEval.h"
|
|
|
|
#include "compiler/IroFlowgraph.h"
|
|
|
|
#include "compiler/IroLinearForm.h"
|
|
|
|
#include "compiler/IROUseDef.h"
|
|
|
|
#include "compiler/IroUtil.h"
|
|
|
|
#include "compiler/IroVars.h"
|
|
|
|
#include "compiler/objects.h"
|
|
|
|
#include "compiler/CExpr.h"
|
|
|
|
#include "compiler/CompilerTools.h"
|
|
|
|
#include "compiler/CParser.h"
|
|
|
|
#include "compiler/InlineAsm.h"
|
|
|
|
#include "compiler/InlineAsmPPC.h"
|
|
|
|
|
|
|
|
IROAssign *IRO_FirstAssign;
|
|
|
|
IROAssign *IRO_LastAssign;
|
|
|
|
SInt32 IRO_NumAssign;
|
|
|
|
|
|
|
|
static Boolean VarIsUsedInOtherFNodes(VarRecord *var, IRONode *node) {
|
|
|
|
if (var->defs && var->uses) {
|
|
|
|
IROUse *use;
|
|
|
|
IRODef *def = NULL;
|
|
|
|
for (use = var->uses; use; use = use->varnext) {
|
|
|
|
if (!def && use->node == node && use->linear && !(use->linear->flags & IROLF_Assigned)) {
|
|
|
|
for (def = var->defs; def; def = def->varnext) {
|
|
|
|
if (Bv_IsBitSet(def->index, use->x18))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def) {
|
|
|
|
for (use = var->uses; use; use = use->varnext) {
|
|
|
|
if (use->node != node && use->linear && !(use->linear->flags & IROLF_Assigned)) {
|
|
|
|
if (Bv_IsBitSet(def->index, use->x18))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
IROLinear *linear;
|
|
|
|
IRONode *scan;
|
|
|
|
for (scan = IRO_FirstNode; scan; scan = scan->nextnode) {
|
|
|
|
if (scan != node) {
|
|
|
|
linear = scan->first;
|
|
|
|
while (1) {
|
|
|
|
if (!linear)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) {
|
|
|
|
if (IRO_FindVar(linear->u.diadic.left->u.node->data.objref, 0, 1) == var)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (linear == scan->last)
|
|
|
|
break;
|
|
|
|
linear = linear->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
IRO_CheckForUserBreak();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void GetExprUses(IROLinear *linear, Boolean isFirst) {
|
|
|
|
if (isFirst && 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))) {
|
|
|
|
VarRecord *var = IRO_FindVar(obj, 0, 1);
|
|
|
|
if (var)
|
|
|
|
Bv_SetBit(var->index, IRO_VarKills);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void GetExprKills(IROLinear *linear, Boolean isFirst) {
|
|
|
|
if (isFirst)
|
|
|
|
IRO_GetKills(linear);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void CheckUnorderedRegionForDefs(IROLinear *linear, BitVector *a, BitVector *b, Boolean *flag) {
|
|
|
|
Bv_Clear(a);
|
|
|
|
Bv_Clear(IRO_VarKills);
|
|
|
|
IRO_WalkTree(linear, GetExprKills);
|
|
|
|
Bv_Or(IRO_VarKills, a);
|
|
|
|
if (Bv_BitsInCommon(a, b))
|
|
|
|
*flag = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void CheckUnorderedRegionsForDefs(IROLinear *linear1, IROLinear *linear2, BitVector *a, BitVector *b, Boolean *flag) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
switch (linear1->type) {
|
|
|
|
case IROLinearOp2Arg:
|
|
|
|
if (linear1->nodetype == ELAND) break;
|
|
|
|
if (linear1->nodetype == ELOR) break;
|
|
|
|
if (linear1->nodetype == ECOMMA) break;
|
|
|
|
if (linear1->u.diadic.left != linear2)
|
|
|
|
CheckUnorderedRegionForDefs(linear1->u.diadic.left, a, b, flag);
|
|
|
|
if (linear1->u.diadic.right != linear2)
|
|
|
|
CheckUnorderedRegionForDefs(linear1->u.diadic.right, a, b, flag);
|
|
|
|
break;
|
|
|
|
case IROLinearFunccall:
|
|
|
|
if (linear1->u.funccall.linear8 != linear2)
|
|
|
|
CheckUnorderedRegionForDefs(linear1->u.funccall.linear8, a, b, flag);
|
|
|
|
for (i = 0; !*flag && i < linear1->u.funccall.argCount; i++) {
|
|
|
|
if (linear1->u.funccall.args[i] != linear2)
|
|
|
|
CheckUnorderedRegionForDefs(linear1->u.funccall.args[i], a, b, flag);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Boolean PropagationHasDefsInUnorderedRegions(IROLinear *a, IROLinear *b) {
|
|
|
|
Boolean flag;
|
|
|
|
IROLinear *father;
|
|
|
|
BitVector *bv1;
|
|
|
|
BitVector *bv2;
|
|
|
|
VarRecord *var;
|
|
|
|
|
|
|
|
flag = 0;
|
|
|
|
if ((father = IRO_LocateFather(a))) {
|
|
|
|
Bv_AllocVector(&bv1, IRO_NumVars + 1);
|
|
|
|
Bv_AllocVector(&bv2, IRO_NumVars + 1);
|
|
|
|
Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
|
|
|
|
IRO_WalkTree(b, GetExprUses);
|
|
|
|
Bv_Or(IRO_VarKills, bv2);
|
|
|
|
var = IRO_FindVar(a->u.diadic.left->u.node->data.objref, 0, 1);
|
|
|
|
Bv_SetBit(var->index, bv2);
|
|
|
|
while (father && !flag) {
|
|
|
|
CheckUnorderedRegionsForDefs(father, a, bv1, bv2, &flag);
|
|
|
|
a = father;
|
|
|
|
father = IRO_LocateFather(father);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return flag;
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRO_IsRegable(Object *obj) {
|
|
|
|
if (obj->datatype == DLOCAL && obj->u.var.info)
|
|
|
|
return obj->u.var.info->noregister == 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Boolean IsPropagatable(IROLinear *linear) {
|
|
|
|
Object *obj;
|
|
|
|
Object *obj2;
|
|
|
|
|
|
|
|
if (IS_LINEAR_DIADIC(linear, EASS) && (obj = IRO_IsVariable(linear->u.diadic.left)) && obj->type == linear->rtype && !is_volatile_object(obj)) {
|
|
|
|
if (linear->u.diadic.left->flags & IROLF_BitfieldIndirect) {
|
|
|
|
if (!IRO_IsConstant(linear->u.diadic.right))
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IRO_IsConstant(linear->u.diadic.right))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if ((obj2 = IRO_IsVariable(linear->u.diadic.right)) && !is_volatile_object(obj2) && IRO_TypesEqual(obj->type, linear->rtype)) {
|
|
|
|
if (!Inline_IsObjectData(linear->u.diadic.right->u.monadic->u.node->data.objref)) {
|
|
|
|
if (IRO_IsRegable(obj) && !IRO_IsRegable(obj2))
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Boolean IsIntGenKillCandidate(IROLinear *linear) {
|
|
|
|
if (linear->type == IROLinearFunccall)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (IRO_IsAssignOp[linear->nodetype] && (linear->type == IROLinearOp1Arg || linear->type == IROLinearOp2Arg))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (linear->type == IROLinearAsm)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Boolean IsPropagatableExpr(IROLinear *linear, IROList *list) {
|
|
|
|
Object *obj;
|
|
|
|
if (IS_LINEAR_DIADIC(linear, EASS) && !(linear->flags & IROLF_Reffed)) {
|
|
|
|
if ((obj = IRO_IsVariable(linear->u.diadic.left)) && !is_volatile_object(obj) && !(linear->u.diadic.left->flags & IROLF_BitfieldIndirect)) {
|
|
|
|
if (!IRO_IsRegable(obj))
|
|
|
|
return 0;
|
|
|
|
if (IS_LINEAR_ENODE(linear->u.diadic.right, ESTRINGCONST))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
IRO_FindDepends(linear->u.diadic.right);
|
|
|
|
if (!IRO_NotSubable)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ClearAvailibilityOnNode(IRONode *node, UInt32 bit) {
|
|
|
|
IRONode *scan;
|
|
|
|
|
|
|
|
for (scan = node->nextnode; scan; scan = scan->nextnode)
|
|
|
|
Bv_ClearBit(bit, scan->x16);
|
|
|
|
}
|
|
|
|
|
|
|
|
Boolean IRO_CopyAndConstantPropagation(void) {
|
|
|
|
IROAssign *ass2;
|
|
|
|
IROAssign *ass;
|
|
|
|
IROLinear *linear;
|
|
|
|
IRONode *node;
|
|
|
|
VarRecord *var;
|
|
|
|
BitVector *bv;
|
|
|
|
Boolean flag;
|
|
|
|
Boolean result;
|
|
|
|
|
|
|
|
IRO_FirstAssign = NULL;
|
|
|
|
IRO_NumAssign = 0;
|
|
|
|
result = 0;
|
|
|
|
|
|
|
|
for (node = IRO_FirstNode; node; node = node->nextnode) {
|
|
|
|
linear = node->first;
|
|
|
|
while (1) {
|
|
|
|
if (!linear)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (IsPropagatable(linear) && (var = IRO_FindAssigned(linear))) {
|
|
|
|
IROAssign *newass;
|
|
|
|
IRO_Dump("Found propagatable assignment at: %d\n", linear->index);
|
|
|
|
newass = oalloc(sizeof(IROAssign));
|
|
|
|
newass->linear = linear;
|
|
|
|
newass->next = NULL;
|
|
|
|
newass->index = ++IRO_NumAssign;
|
|
|
|
newass->varIndex = var->index;
|
|
|
|
newass->linear2 = linear->u.diadic.right;
|
|
|
|
newass->var = NULL;
|
|
|
|
newass->varObj = IRO_IsVariable(linear->u.diadic.right);
|
|
|
|
newass->node = node;
|
|
|
|
if (newass->varObj)
|
|
|
|
newass->var = IRO_FindVar(newass->varObj, 0, 1);
|
|
|
|
if (!IRO_FirstAssign)
|
|
|
|
IRO_FirstAssign = newass;
|
|
|
|
else
|
|
|
|
IRO_LastAssign->next = newass;
|
|
|
|
IRO_LastAssign = newass;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (linear == node->last)
|
|
|
|
break;
|
|
|
|
linear = linear->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
IRO_CheckForUserBreak();
|
|
|
|
|
|
|
|
node = IRO_FirstNode;
|
|
|
|
ass = IRO_FirstAssign;
|
|
|
|
Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
|
|
|
|
while (node) {
|
|
|
|
Bv_AllocVector(&node->x16, IRO_NumAssign);
|
|
|
|
if (node != IRO_FirstNode)
|
|
|
|
Bv_Set(node->x16);
|
|
|
|
Bv_AllocVector(&node->x22, IRO_NumAssign);
|
|
|
|
Bv_AllocVector(&node->x1E, IRO_NumAssign);
|
|
|
|
Bv_AllocVector(&node->x2A, IRO_NumAssign);
|
|
|
|
node->x1A = NULL;
|
|
|
|
|
|
|
|
linear = node->first;
|
|
|
|
while (1) {
|
|
|
|
if (!linear)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (IsIntGenKillCandidate(linear)) {
|
|
|
|
//IROAssign *ass2;
|
|
|
|
Bv_Clear(IRO_VarKills);
|
|
|
|
IRO_GetKills(linear);
|
|
|
|
|
|
|
|
for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) {
|
|
|
|
if (Bv_IsBitSet(ass2->varIndex, IRO_VarKills)) {
|
|
|
|
Bv_SetBit(ass2->index, node->x22);
|
|
|
|
Bv_ClearBit(ass2->index, node->x1E);
|
|
|
|
}
|
|
|
|
if (ass2->var && Bv_IsBitSet(ass2->var->index, IRO_VarKills)) {
|
|
|
|
Bv_SetBit(ass2->index, node->x22);
|
|
|
|
Bv_ClearBit(ass2->index, node->x1E);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while (ass && ass->linear == linear) {
|
|
|
|
Bv_SetBit(ass->index, node->x1E);
|
|
|
|
ass = ass->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (linear == node->last)
|
|
|
|
break;
|
|
|
|
linear = linear->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
Bv_Copy(node->x16, node->x2A);
|
|
|
|
Bv_Minus(node->x22, node->x2A);
|
|
|
|
Bv_Or(node->x1E, node->x2A);
|
|
|
|
node = node->nextnode;
|
|
|
|
}
|
|
|
|
|
|
|
|
IRO_CheckForUserBreak();
|
|
|
|
|
|
|
|
Bv_AllocVector(&bv, IRO_NumAssign);
|
|
|
|
do {
|
|
|
|
flag = 0;
|
|
|
|
for (node = IRO_FirstNode; node; node = node->nextnode) {
|
|
|
|
if (node == IRO_FirstNode) {
|
|
|
|
Bv_Clear(bv);
|
|
|
|
} else {
|
|
|
|
UInt16 i;
|
|
|
|
Bv_Set(bv);
|
|
|
|
for (i = 0; i < node->numpred; i++)
|
|
|
|
Bv_And(IRO_NodeTable[node->pred[i]]->x2A, bv);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Bv_Compare(bv, node->x16)) {
|
|
|
|
flag = 1;
|
|
|
|
Bv_Copy(bv, node->x16);
|
|
|
|
}
|
|
|
|
|
|
|
|
Bv_Copy(node->x16, node->x2A);
|
|
|
|
Bv_Minus(node->x22, node->x2A);
|
|
|
|
Bv_Or(node->x1E, node->x2A);
|
|
|
|
}
|
|
|
|
} while (flag);
|
|
|
|
|
|
|
|
IRO_CheckForUserBreak();
|
|
|
|
|
|
|
|
node = IRO_FirstNode;
|
|
|
|
ass = IRO_FirstAssign;
|
|
|
|
while (node) {
|
|
|
|
IRO_Avail = node->x16;
|
|
|
|
linear = node->first;
|
|
|
|
while (1) {
|
|
|
|
if (!linear)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) {
|
|
|
|
if ((var = IRO_FindVar(linear->u.diadic.left->u.node->data.objref, 0, 1))) {
|
|
|
|
//IROAssign *ass2;
|
|
|
|
for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) {
|
|
|
|
if (
|
|
|
|
ass2->varIndex == var->index &&
|
|
|
|
Bv_IsBitSet(ass2->index, IRO_Avail) &&
|
|
|
|
(IRO_IsConstant(ass2->linear2) || node->loopdepth <= ass2->node->loopdepth) &&
|
|
|
|
!PropagationHasDefsInUnorderedRegions(linear, ass2->linear2)
|
|
|
|
) {
|
|
|
|
if (ass2->linear2->type == IROLinearOperand && IRO_is_CPtypeequal(linear->rtype, ass2->linear->u.diadic.left->rtype)) {
|
|
|
|
ENode *enode = IRO_NewENode(ass2->linear2->u.node->type);
|
|
|
|
*enode = *ass2->linear2->u.node;
|
|
|
|
if (enode->type == EINTCONST) {
|
|
|
|
if (linear->flags & IROLF_BitfieldIndirect) {
|
|
|
|
IRO_TruncateBitfieldValueToType(&enode->data.intval, linear->rtype, var->x1A);
|
|
|
|
enode->rtype = linear->rtype;
|
|
|
|
result = 1;
|
|
|
|
} else {
|
|
|
|
IRO_TruncateValueToType(&enode->data.intval, linear->rtype);
|
|
|
|
enode->rtype = linear->rtype;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
linear->u.monadic->type = IROLinearNop;
|
|
|
|
linear->type = IROLinearOperand;
|
|
|
|
linear->u.node = enode;
|
|
|
|
} else if (ass2->varObj && IRO_is_CPtypeequal(linear->rtype, ass2->linear->rtype)) {
|
|
|
|
linear->u.diadic.left->u.node = create_objectrefnode(ass2->varObj);
|
|
|
|
if (ass2->linear2->flags & IROLF_BitfieldIndirect)
|
|
|
|
linear->flags |= IROLF_BitfieldIndirect;
|
|
|
|
}
|
|
|
|
IRO_Dump("Found propagation at %d from %d\n", linear->index, ass2->linear->index);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (linear->type == IROLinearAsm) {
|
|
|
|
IAEffects effects;
|
|
|
|
int i;
|
|
|
|
CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects);
|
|
|
|
|
|
|
|
for (i = 0; i < effects.numoperands; i++) {
|
|
|
|
if (effects.operands[i].type == IAEffect_0 && effects.operands[i].offset == 0 && effects.operands[i].object->type->size == effects.operands[i].size) {
|
|
|
|
if ((var = IRO_FindVar(effects.operands[i].object, 0, 1))) {
|
|
|
|
//IROAssign *ass2;
|
|
|
|
for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) {
|
|
|
|
if (ass2->varIndex == var->index && Bv_IsBitSet(ass2->index, IRO_Avail) && ass2->linear->rtype->size == effects.operands[i].size) {
|
|
|
|
ENode *enode;
|
2022-12-29 12:32:55 +00:00
|
|
|
if (ass2->varObj)
|
2022-12-14 00:16:59 +00:00
|
|
|
enode = create_objectrefnode(ass2->varObj);
|
2022-12-29 12:32:55 +00:00
|
|
|
else if (ass2->linear2->type == IROLinearOperand)
|
2022-12-14 00:16:59 +00:00
|
|
|
enode = ass2->linear2->u.node;
|
2022-12-29 12:32:55 +00:00
|
|
|
else
|
|
|
|
CError_FATAL(768);
|
2022-12-14 00:16:59 +00:00
|
|
|
CodeGen_PropagateIntoAsm(linear->u.asm_stmt, effects.operands[i].object, enode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsIntGenKillCandidate(linear)) {
|
|
|
|
//IROAssign *ass2;
|
|
|
|
Bv_Clear(IRO_VarKills);
|
|
|
|
IRO_GetKills(linear);
|
|
|
|
|
|
|
|
for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) {
|
|
|
|
if (Bv_IsBitSet(ass2->varIndex, IRO_VarKills)) {
|
|
|
|
Bv_ClearBit(ass2->index, IRO_Avail);
|
|
|
|
}
|
|
|
|
if (ass2->var && Bv_IsBitSet(ass2->var->index, IRO_VarKills)) {
|
|
|
|
Bv_ClearBit(ass2->index, IRO_Avail);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while (ass && ass->linear == linear) {
|
|
|
|
Bv_SetBit(ass->index, IRO_Avail);
|
|
|
|
ass = ass->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (linear == node->last)
|
|
|
|
break;
|
|
|
|
linear = linear->next;
|
|
|
|
}
|
|
|
|
node = node->nextnode;
|
|
|
|
}
|
|
|
|
|
|
|
|
IRO_CheckForUserBreak();
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void IRO_ExpressionPropagation(void) {
|
|
|
|
IRONode *node;
|
|
|
|
IROLinear *linear;
|
|
|
|
Object *obj;
|
|
|
|
VarRecord *var;
|
|
|
|
IROAssign *ass;
|
|
|
|
|
|
|
|
for (node = IRO_FirstNode; node; node = node->nextnode) {
|
|
|
|
IRO_FirstAssign = NULL;
|
|
|
|
IRO_LastAssign = NULL;
|
|
|
|
IRO_NumAssign = 0;
|
|
|
|
|
|
|
|
linear = node->first;
|
|
|
|
while (1) {
|
|
|
|
IROList list;
|
|
|
|
if (!linear)
|
|
|
|
break;
|
|
|
|
|
|
|
|
IRO_InitList(&list);
|
|
|
|
if (IsPropagatableExpr(linear, &list)) {
|
|
|
|
if ((var = IRO_FindAssigned(linear))) {
|
|
|
|
IRO_Dump("Found propagatable expression assignment at: %d\n", linear->index);
|
|
|
|
ass = oalloc(sizeof(IROAssign));
|
|
|
|
ass->linear = linear;
|
|
|
|
ass->next = NULL;
|
|
|
|
ass->index = ++IRO_NumAssign;
|
|
|
|
ass->varIndex = var->index;
|
|
|
|
ass->linear2 = linear->u.diadic.right;
|
|
|
|
ass->x20 = 0;
|
|
|
|
ass->node = node;
|
|
|
|
IRO_FindDepends(linear->u.diadic.right);
|
|
|
|
ass->depends = IRO_Depends;
|
|
|
|
if (!IRO_FirstAssign) {
|
|
|
|
IRO_FirstAssign = ass;
|
|
|
|
ass->prev = NULL;
|
|
|
|
} else {
|
|
|
|
IRO_LastAssign->next = ass;
|
|
|
|
ass->prev = IRO_LastAssign;
|
|
|
|
}
|
|
|
|
IRO_LastAssign = ass;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) {
|
|
|
|
if ((var = IRO_FindVar(linear->u.monadic->u.node->data.objref, 0, 1))) {
|
|
|
|
for (ass = IRO_LastAssign; ass; ass = ass->prev) {
|
|
|
|
if (ass->varIndex == var->index)
|
|
|
|
ass->x20++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (linear == node->last)
|
|
|
|
break;
|
|
|
|
linear = linear->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
Bv_AllocVector(&IRO_Avail, IRO_NumAssign);
|
|
|
|
|
|
|
|
linear = node->first;
|
|
|
|
while (1) {
|
|
|
|
if (!linear)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) {
|
|
|
|
if ((var = IRO_FindVar(linear->u.monadic->u.node->data.objref, 0, 1))) {
|
|
|
|
for (ass = IRO_LastAssign; ass; ass = ass->next) {
|
|
|
|
if (ass->varIndex == var->index && Bv_IsBitSet(ass->index, IRO_Avail) && !PropagationHasDefsInUnorderedRegions(linear, ass->linear2)) {
|
|
|
|
if (ass->linear2->type == IROLinearOperand && IRO_is_CPtypeequal(linear->rtype, ass->linear->u.diadic.left->rtype)) {
|
|
|
|
ENode *enode = IRO_NewENode(ass->linear2->u.node->type);
|
|
|
|
*enode = *ass->linear2->u.node;
|
|
|
|
if (enode->type == EINTCONST) {
|
|
|
|
IRO_TruncateValueToType(&enode->data.intval, linear->rtype);
|
|
|
|
enode->rtype = linear->rtype;
|
|
|
|
} else if (enode->type == EOBJREF) {
|
|
|
|
IROLinear *tmp = IRO_LocateFather(linear);
|
|
|
|
if (tmp && (tmp->flags & IROLF_Assigned))
|
|
|
|
linear->flags |= IROLF_Assigned;
|
|
|
|
}
|
|
|
|
linear->u.monadic->type = IROLinearNop;
|
|
|
|
linear->type = IROLinearOperand;
|
|
|
|
linear->u.node = enode;
|
|
|
|
} else if (IRO_IsVariable(ass->linear2) && IRO_is_CPtypeequal(linear->rtype, ass->linear->rtype)) {
|
|
|
|
linear->u.monadic->u.node = create_objectrefnode(ass->linear2->u.monadic->u.node->data.objref);
|
|
|
|
if (ass->linear2->flags & IROLF_BitfieldIndirect)
|
|
|
|
linear->flags |= IROLF_BitfieldIndirect;
|
|
|
|
} else if (IRO_is_CPtypeequal(linear->rtype, ass->linear->rtype) && ass->x20 == 1 && !VarIsUsedInOtherFNodes(var, node)) {
|
|
|
|
IROList list;
|
|
|
|
IRO_InitList(&list);
|
|
|
|
IRO_DuplicateExpr(ass->linear->u.diadic.right, &list);
|
|
|
|
if (IS_TYPE_FLOAT(ass->linear->rtype)) {
|
|
|
|
IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg);
|
|
|
|
tmp->index = ++IRO_NumLinear;
|
|
|
|
tmp->rtype = ass->linear->rtype;
|
|
|
|
tmp->nodetype = ETYPCON;
|
|
|
|
tmp->nodeflags = ENODE_FLAG_80;
|
|
|
|
tmp->u.monadic = list.tail;
|
|
|
|
IRO_AddToList(tmp, &list);
|
|
|
|
}
|
|
|
|
IRO_PasteAfter(list.head, list.tail, linear);
|
|
|
|
IRO_LocateFather_Cut_And_Paste(linear, list.tail);
|
|
|
|
linear = list.tail;
|
|
|
|
}
|
|
|
|
IRO_Dump("Found expression propagation at %d from %d\n", linear->index, ass->linear->index);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (linear->type != IROLinearNop && IsIntGenKillCandidate(linear)) {
|
|
|
|
Bv_Clear(IRO_VarKills);
|
|
|
|
IRO_GetKills(linear);
|
|
|
|
for (ass = IRO_FirstAssign; ass; ass = ass->next) {
|
|
|
|
if (Bv_IsBitSet(ass->varIndex, IRO_VarKills))
|
|
|
|
Bv_ClearBit(ass->index, IRO_Avail);
|
|
|
|
if ((obj = IRO_IsVariable(ass->linear->u.diadic.right))) {
|
|
|
|
if ((var = IRO_FindVar(obj, 0, 1))) {
|
|
|
|
if (Bv_IsBitSet(var->index, IRO_VarKills))
|
|
|
|
Bv_ClearBit(ass->index, IRO_Avail);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
IROList list;
|
|
|
|
IRO_InitList(&list);
|
|
|
|
IRO_Depends = ass->depends;
|
|
|
|
IRO_FindDepends_NoAlloc(ass->linear->u.diadic.right);
|
|
|
|
if (Bv_BitsInCommon(IRO_VarKills, ass->depends))
|
|
|
|
Bv_ClearBit(ass->index, IRO_Avail);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ass = IRO_FirstAssign; ass; ass = ass->next) {
|
|
|
|
IRO_Depends = ass->depends;
|
|
|
|
IRO_FindDepends_NoAlloc(ass->linear->u.diadic.right);
|
|
|
|
if (ass->linear == linear && !Bv_IsBitSet(ass->varIndex, ass->depends))
|
|
|
|
Bv_SetBit(ass->index, IRO_Avail);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (linear == node->last)
|
|
|
|
break;
|
|
|
|
linear = linear->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
IRO_CheckForUserBreak();
|
|
|
|
}
|
|
|
|
|