summaryrefslogtreecommitdiff
path: root/compiler_and_linker/FrontEnd/Optimizer/IROUseDef.c
diff options
context:
space:
mode:
Diffstat (limited to 'compiler_and_linker/FrontEnd/Optimizer/IROUseDef.c')
-rw-r--r--compiler_and_linker/FrontEnd/Optimizer/IROUseDef.c1432
1 files changed, 1432 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/Optimizer/IROUseDef.c b/compiler_and_linker/FrontEnd/Optimizer/IROUseDef.c
new file mode 100644
index 0000000..ba3f817
--- /dev/null
+++ b/compiler_and_linker/FrontEnd/Optimizer/IROUseDef.c
@@ -0,0 +1,1432 @@
+#include "IROUseDef.h"
+#include "IroDump.h"
+#include "IroVars.h"
+#include "IroFlowgraph.h"
+#include "IroLinearForm.h"
+#include "IroMalloc.h"
+#include "IroPointerAnalysis.h"
+#include "IroTransform.h"
+#include "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:
+ 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:
+ CError_FATAL(491);
+ }
+ } else {
+ 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;
+ CError_ASSERT(1422, obj != NULL);
+ var = IRO_FindVar(obj, 1, 1);
+ 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;
+ 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);
+ 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;
+
+ if (nd->type == IROLinearOp2Arg)
+ nd = nd->u.diadic.left;
+ else if (nd->type == IROLinearOp1Arg)
+ nd = nd->u.monadic;
+ else
+ CError_FATAL(2338);
+
+ 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
+ )
+ CError_FATAL(2459);
+
+ assigned->u.node->data.objref = to;
+}
+
+static void ReplaceUsed(IROLinear *nd, Object *from, Object *to) {
+ CError_ASSERT(2482, nd->type == IROLinearOperand && nd->u.node->type == EOBJREF);
+
+ if (nd->u.node->data.objref == from)
+ nd->u.node->data.objref = to;
+ 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();
+}