move lots of source files around to match their actual placement in the original tree

This commit is contained in:
Ash Wolf
2023-01-26 11:30:47 +00:00
parent fc0c4c0df7
commit 094b96ca1d
120 changed files with 400 additions and 392 deletions

View File

@@ -0,0 +1,36 @@
#ifndef COMPILER_IROBITVECT_H
#define COMPILER_IROBITVECT_H
#include "compiler/common.h"
#include "compiler/CError.h"
typedef struct BitVector {
UInt32 size;
UInt32 data[0];
} BitVector;
extern void Bv_AllocVector(BitVector **bv, UInt32 size);
extern void Bv_AllocVectorLocal(BitVector **bv, UInt32 size);
extern void Bv_ClearBit(UInt32 bit, BitVector *bv);
extern void Bv_And(const BitVector *a, BitVector *b);
extern void Bv_Or(const BitVector *a, BitVector *b);
extern Boolean Bv_BitsInCommon(const BitVector *a, const BitVector *b);
extern Boolean Bv_Compare(const BitVector *a, const BitVector *b);
extern void Bv_Minus(const BitVector *a, BitVector *b);
extern void Bv_Copy(const BitVector *src, BitVector *dst);
extern void Bv_Clear(BitVector *bv);
extern void Bv_Set(BitVector *bv);
extern Boolean Bv_IsSubset(const BitVector *a, const BitVector *b);
extern Boolean Bv_IsEmpty(const BitVector *bv);
CW_INLINE void Bv_SetBit(UInt32 bit, BitVector *bv) {
if ((bit / 32) < bv->size) {
bv->data[bit / 32] |= 1 << (bit & 31);
} else {
CError_FATAL(56);
}
}
#define Bv_IsBitSet(_bit, _bv) ( (((_bit) >> 5) < (_bv)->size) && ((_bv)->data[(_bit) >> 5] & (1 << ((_bit) & 31))) )
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,48 @@
#ifndef COMPILER_IROUSEDEF_H
#define COMPILER_IROUSEDEF_H
#include "IrOptimizer.h"
#include "BitVector.h"
#include "compiler/enode.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
struct IROUse {
SInt32 index;
IRONode *node;
IROLinear *linear;
VarRecord *var;
IROUse *globalnext;
IROUse *varnext;
BitVector *x18;
UInt16 x1C;
};
struct IRODef {
SInt32 index;
IRONode *node;
IROLinear *linear;
VarRecord *var;
IRODef *globalnext;
IRODef *varnext;
UInt16 x18;
Boolean x1A;
Boolean x1B;
Boolean x1C;
Boolean x1D;
};
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern ENodeType IRO_NonAssignmentOp[MAXEXPR];
extern IROUse *IRO_FirstVarUse;
extern IROUse *IRO_LastVarUse;
extern CInt64 IRO_GetSelfAssignmentVal(IROLinear *linear);
extern void IRO_InitializeNonAssignmentOpArray(void);
extern void IRO_InitializeAssignmentFoldingFunctionArray(void);
extern Boolean IRO_UseDef(Boolean optDeadAssignments, Boolean optPropagation);
extern void IRO_SplitLifetimes(void);
#endif

View File

@@ -0,0 +1,400 @@
#include "IrOptimizer.h"
#include "compiler/CError.h"
#include "compiler/CParser.h"
#include "compiler/InlineAsmPPC.h"
#include "IroCSE.h"
#include "IroDump.h"
#include "IroEval.h"
#include "IroFlowgraph.h"
#include "IroLinearForm.h"
#include "IroSubable.h"
#include "IroTransform.h"
#include "IROUseDef.h"
#include "IroUtil.h"
#include "IroVars.h"
#include "compiler/objects.h"
#include "IroPropagate.h"
#include "IroPointerAnalysis.h"
#include "IroJump.h"
#include "IroRangePropagation.h"
#include "IroEmptyLoop.h"
#include "IroUnrollLoop.h"
#include "IroLoop.h"
#include "IroExprRegeneration.h"
Boolean DoScalarize;
Boolean DoLinearize;
Boolean EarlyReturn;
Boolean IRO_CPFirstTime;
Boolean VectorPhaseCalledFromUnroll;
Boolean IRO_Log;
static Boolean stIsSetup;
static void CountRefToObject(Object *object, int depth) {
static unsigned short LoopUsage[] = {1, 4, 16, 64};
if (depth > 3)
depth = 3;
object->u.var.info->usage += LoopUsage[depth];
object->u.var.info->used = 1;
}
static void CountARef(IROLinear *node, int depth) {
Object *object;
object = node->u.node->data.objref;
CError_ASSERT(78, object->datatype != DALIAS);
if (object->datatype == DLOCAL && object->u.var.info) {
CountRefToObject(object, depth);
if ((node->flags & IROLF_Used) && (node->flags & IROLF_Assigned))
CountRefToObject(object, depth);
if (!(node->flags & IROLF_Immind) && !object->u.var.info->noregister)
object->u.var.info->noregister = 2;
}
}
static void CountDoubleInd(IROLinear *node, int depth) {
if (IRO_IsVariable(node)) {
CountARef(node->u.monadic, depth);
} else if (node->type == IROLinearOp2Arg) {
if (node->nodetype == EADD) {
CountDoubleInd(node->u.diadic.left, depth);
CountDoubleInd(node->u.diadic.right, depth);
} else if (IRO_IsAddressMultiply(node)) {
if (IRO_IsVariable(node->u.diadic.left))
CountARef(node->u.diadic.left->u.monadic, depth);
}
}
}
static void CountUsage(void) {
IRONode *fnode = IRO_FirstNode;
IROLinear *node;
if (IRO_FirstNode) {
for (; fnode; fnode = fnode->nextnode) {
for (node = fnode->first; node; node = node->next) {
if (IS_LINEAR_ENODE(node, EOBJREF))
CountARef(node, fnode->loopdepth);
else if (IS_LINEAR_MONADIC(node, EINDIRECT))
CountDoubleInd(node->u.monadic, fnode->loopdepth);
if (node->type == IROLinearAsm) {
IAEffects effects;
int i;
CodeGen_GetAsmEffects(node->u.asm_stmt, &effects);
for (i = 0; i < effects.numoperands; i++) {
Object *object = effects.operands[i].object;
if (object->datatype == DLOCAL && object->u.var.info) {
CountRefToObject(object, fnode->loopdepth);
if (effects.operands[i].type == IAOpnd_3 && !object->u.var.info->noregister)
object->u.var.info->noregister = 2;
}
}
}
if (node == fnode->last)
break;
}
}
} else {
for (node = IRO_FirstLinear; node; node = node->next) {
if (IS_LINEAR_ENODE(node, EOBJREF))
CountARef(node, 0);
else if (IS_LINEAR_MONADIC(node, EINDIRECT))
CountDoubleInd(node->u.monadic, 0);
}
}
IRO_CheckForUserBreak();
}
Statement *IRO_Optimizer(Object *func, Statement *statements) {
Boolean changed;
int pass;
int passCount;
CError_ASSERT(234, stIsSetup);
#ifdef CW_ENABLE_IRO_DEBUG
if (copts.debuglisting)
IRO_Log = 1;
#endif
DisableDueToAsm = 0;
FunctionName = func;
DoScalarize = 1;
DoLinearize = 1;
EarlyReturn = 0;
IRO_Depends = NULL;
LoopOptimizerRun = 0;
IRO_IsLeafFunction = 1;
IRO_FunctionHasReturn = 0;
IRO_SetupForUserBreakChecking();
IRO_Dump("Starting function %s\n", func ? func->name->name : "Init-code");
IRO_Dump("--------------------------------------------------------------------------------\n");
if (DoLinearize)
IRO_PreLinearize(statements);
if (copts.optimizationlevel > 0)
IRO_TransformTree(statements);
VectorPhaseCalledFromUnroll = 0;
IRO_Linearize(statements);
CurStat = NULL;
IRO_FirstExpr = NULL;
IRO_LastExpr = NULL;
IRO_FirstAssign = NULL;
IRO_LastAssign = NULL;
IRO_FirstVarUse = NULL;
IRO_LastVarUse = NULL;
IRO_FirstNode = NULL;
IRO_LastNode = NULL;
if (copts.optimizationlevel > 0)
IRO_DoTransformations();
IRO_BuildFlowgraph(IRO_FirstLinear);
IRO_DumpAfterPhase("IRO_BuildflowGraph", 0);
IRO_FindAllVars();
IRO_CheckInit();
if (!DisableDueToAsm && copts.optimizationlevel > 0 && copts.opt_pointer_analysis && func) {
IRO_AnalyzePointers(func);
if (copts.propagation && IRO_EvaluateDefinitePointers(func)) {
IRO_UpdateFlagsOnInts();
IRO_UpdateVars();
IRO_DumpAfterPhase("IRO_EvaluateDefinitePointers", 0);
}
}
if (copts.optimizationlevel > 0) {
changed = IRO_EvaluateConditionals();
if (!DisableDueToAsm) {
changed |= IRO_RemoveUnreachable();
IRO_DumpAfterPhase("IRO_RemoveUnreachable", 0);
}
changed |= IRO_RemoveRedundantJumps();
IRO_DumpAfterPhase("IRO_RemoveRedundantJumps", 0);
if (!DisableDueToAsm) {
changed |= IRO_RemoveLabels();
IRO_DumpAfterPhase("IRO_RemoveLabels()", 0);
}
if (changed) {
IRO_BuildFlowgraph(IRO_FirstLinear);
IRO_DumpAfterPhase("IRO_BuildflowGraph--1", 0);
}
}
if (!DisableDueToAsm && copts.optimizationlevel > 0) {
passCount = copts.multiplepasses ? 2 : 1;
IRO_CPFirstTime = 1;
for (pass = 0; pass < passCount; pass++) {
IRO_Dump("*****************\n");
IRO_Dump("Dumps for pass=%d\n", pass);
IRO_Dump("*****************\n");
if (DoScalarize)
IRO_ScalarizeClassDataMembers();
IRO_DumpAfterPhase("IRO_ScalarizeClassDataMembers", 0);
if (copts.propagation) {
IRO_CopyAndConstantPropagation();
IRO_CPFirstTime = 0;
IRO_ExpressionPropagation();
IRO_DumpAfterPhase("Copy and constant propagation", 0);
IRO_RangePropagateInFNode();
IRO_DumpAfterPhase("IRO_RangePropagateInFNode", 0);
IRO_UpdateFlagsOnInts();
}
IRO_DumpAfterPhase("IRO_ExpressionPropagation", 0);
if (copts.deadstore || copts.propagation)
IRO_UseDef(copts.deadstore, copts.propagation);
IRO_DumpAfterPhase("after IRO_UseDef", 0);
IRO_UpdateVars();
IRO_ConstantFolding();
IRO_DumpAfterPhase("IRO_ConstantFolding", 0);
IRO_EvaluateConditionals();
IRO_RemoveUnreachable();
IRO_SimplifyConditionals();
if (pass == 1 && copts.optimizationlevel > 2) {
IRO_RenumberInts();
IRO_DumpAfterPhase("Before IRO_FindEmptyLoops", 0);
IRO_FindEmptyLoops();
IRO_DumpAfterPhase("After IRO_FindEmptyLoops", 0);
IRO_RenumberInts();
}
if (copts.unrolling && !copts.optimizesize && pass == 0) {
IRO_DumpAfterPhase("Before IRO_LoopUnroller", 0);
IRO_LoopUnroller();
IRO_DumpAfterPhase("After IRO_LoopUnroller", 0);
IRO_RenumberInts();
}
VectorPhaseCalledFromUnroll = 0;
if (pass == 0 && (copts.loopinvariants || copts.strengthreduction)) {
IRO_DumpAfterPhase("Before IRO_FindLoops", 0);
IRO_FindLoops();
LoopOptimizerRun = 1;
IRO_SetLoopDepth();
}
IRO_DumpAfterPhase("After IRO_FindLoops", 0);
if (copts.propagation) {
IRO_CopyAndConstantPropagation();
IRO_ConstantFolding();
IRO_EvaluateConditionals();
}
IRO_DumpAfterPhase("Second pass:IRO_CopyAndConstantPropagation, IRO_ConstantFolding, IRO_EvaluateConditionals", 0);
if (copts.commonsubs)
IRO_FindExpressions(NULL, 0);
if (copts.commonsubs) {
IRO_ComputeAvail();
IRO_CommonSubs();
}
IRO_DumpAfterPhase("IRO_CommonSubs", 0);
IRO_UpdateFlagsOnInts();
IRO_UpdateVars();
IRO_DoTransformations();
IRO_ConstantFolding();
do {
IRO_UpdateFlagsOnInts();
if (copts.deadcode)
IRO_RemoveUnreachable();
IRO_DumpAfterPhase("IRO_RemoveUnreachable", 0);
changed = IRO_RemoveRedundantJumps();
IRO_DumpAfterPhase("IRO_RemoveRedundantJumps", 0);
changed |= IRO_RemoveLabels();
IRO_DumpAfterPhase("IRO_RemoveLabels", 0);
changed |= IRO_DoJumpChaining();
IRO_DumpAfterPhase("IRO_DoJumpChaining", 0);
if (copts.propagation) {
IRO_RenumberInts();
IRO_DumpAfterPhase("Before IRO_CopyAndConstantPropagation", 0);
changed |= IRO_CopyAndConstantPropagation();
IRO_DumpAfterPhase("After IRO_CopyAndConstantPropagation", 0);
IRO_ConstantFolding();
}
if (copts.deadstore || copts.propagation)
changed |= IRO_UseDef(copts.deadstore, copts.propagation);
IRO_DumpAfterPhase("IRO_UseDef", 0);
changed |= IRO_EvaluateConditionals();
IRO_DumpAfterPhase("IRO_EvaluateConditionals", 0);
} while (changed);
}
if (copts.lifetimes) {
IRO_UseDef(0, 0);
IRO_SplitLifetimes();
}
IRO_DoTransformations();
IRO_DumpAfterPhase("Before RebuildCondExpressions", 0);
}
IRO_RenumberInts();
IRO_DumpAfterPhase("before IRO_RewriteBitFieldTemps", 0);
IRO_RewriteBitFieldTemps();
IRO_DumpAfterPhase("After IRO_RewriteBitFieldTemps", 0);
CountUsage();
if (!DisableDueToAsm) {
IRO_RegenerateExpressions();
IRO_DumpAfterPhase("IRO_RegenerateExpressions", 0);
}
IRO_DumpAfterPhase("After IRO_Optimizer", 0);
statements = IRO_Delinearize(IRO_FirstNode, NULL);
IRO_ZapVarPtrs();
freeoheap();
return statements;
}
void IRO_Setup(void) {
static Boolean ENodeArraysHaveBeenInitialized;
if (!stIsSetup) {
IRO_Log = 0;
IRO_SetupDump();
if (!ENodeArraysHaveBeenInitialized) {
IRO_InitializeNodeNamesArray();
IRO_InitializeIsAssociativeENodeTypeArray();
IRO_InitializeIsSubableOpArray();
IRO_InitializeAssignmentOpArray();
IRO_InitializeComplementaryOpArray();
IRO_InitializeComplementaryOpLogicalArray();
IRO_InitializeNonAssignmentOpArray();
IRO_InitializeAssignmentFoldingFunctionArray();
IRO_InitializeIRO_IsModifyOpArray();
IRO_InitializeIRO_IsAssignOpArray();
ENodeArraysHaveBeenInitialized = 1;
}
stIsSetup = 1;
}
}
void IRO_Cleanup(void) {
if (stIsSetup) {
IRO_CleanupDump();
stIsSetup = 0;
}
}
void CodeGen_UpdateOptimizerOptions(void) {
Boolean flag;
flag = copts.optimizationlevel >= 1;
copts.deadcode = flag;
flag = copts.optimizationlevel >= 2;
copts.propagation = flag;
copts.commonsubs = flag;
flag = copts.optimizationlevel >= 3;
copts.vectorizeloops = flag;
copts.unrolling = flag;
copts.deadstore = flag;
copts.lifetimes = flag;
copts.strengthreduction = flag;
copts.loopinvariants = flag;
flag = copts.optimizationlevel >= 4;
copts.multiplepasses = flag;
}

View File

@@ -0,0 +1,30 @@
#ifndef COMPILER_IROPTIMIZER_H
#define COMPILER_IROPTIMIZER_H
#include "compiler/common.h"
typedef struct IROAddrRecord IROAddrRecord;
typedef struct IROAssign IROAssign;
typedef struct IRODef IRODef;
typedef struct IROElmList IROElmList;
typedef struct IROExpr IROExpr;
typedef struct IROLinear IROLinear;
typedef struct IROList IROList;
typedef struct IROListNode IROListNode;
typedef struct IROLoop IROLoop;
typedef struct IRONode IRONode;
typedef struct IROUse IROUse;
extern Boolean DoScalarize;
extern Boolean DoLinearize;
extern Boolean EarlyReturn;
extern Boolean IRO_CPFirstTime;
extern Boolean VectorPhaseCalledFromUnroll;
extern Boolean IRO_Log;
extern Statement *IRO_Optimizer(Object *func, Statement *statements);
extern void IRO_Setup(void);
extern void IRO_Cleanup(void);
extern void CodeGen_UpdateOptimizerOptions(void);
#endif

View File

@@ -0,0 +1,112 @@
#include "BitVector.h"
#include "compiler/CompilerTools.h"
void Bv_AllocVector(BitVector **bv, UInt32 size) {
UInt32 long_size = (size / 32) + 1;
*bv = oalloc(sizeof(BitVector) + sizeof(UInt32) * long_size);
(*bv)->size = long_size;
Bv_Clear(*bv);
}
void Bv_AllocVectorLocal(BitVector **bv, UInt32 size) {
UInt32 long_size = (size / 32) + 1;
*bv = lalloc(sizeof(BitVector) + sizeof(UInt32) * long_size);
(*bv)->size = long_size;
Bv_Clear(*bv);
}
void Bv_ClearBit(UInt32 bit, BitVector *bv) {
if ((bit / 32) < bv->size)
bv->data[bit / 32] &= ~(1 << (bit & 31));
else
CError_FATAL(73);
}
void Bv_And(const BitVector *a, BitVector *b) {
UInt32 i;
for (i = 0; i < b->size; i++)
b->data[i] &= a->data[i];
}
void Bv_Or(const BitVector *a, BitVector *b) {
UInt32 i, len;
len = a->size;
if (b->size < len)
len = b->size;
for (i = 0; i < len; i++) {
b->data[i] |= a->data[i];
}
}
Boolean Bv_BitsInCommon(const BitVector *a, const BitVector *b) {
UInt32 len;
UInt32 i;
len = a->size;
if (b->size < len)
len = b->size;
for (i = 0; i < len; i++) {
if (a->data[i] & b->data[i])
return 1;
}
return 0;
}
Boolean Bv_Compare(const BitVector *a, const BitVector *b) {
UInt32 i;
for (i = 0; i < a->size; i++) {
if (a->data[i] != b->data[i])
return 0;
}
return 1;
}
void Bv_Minus(const BitVector *a, BitVector *b) {
UInt32 i;
for (i = 0; i < b->size; i++)
b->data[i] &= ~a->data[i];
}
void Bv_Copy(const BitVector *src, BitVector *dst) {
memcpy(dst->data, src->data, sizeof(UInt32) * dst->size);
}
void Bv_Clear(BitVector *bv) {
memset(bv->data, 0, sizeof(UInt32) * bv->size);
}
void Bv_Set(BitVector *bv) {
memset(bv->data, 0xFF, sizeof(UInt32) * bv->size);
}
Boolean Bv_IsSubset(const BitVector *a, const BitVector *b) {
UInt32 i;
for (i = 0; i < a->size; i++) {
if (b->size < i) {
if (a->data[i])
return 0;
} else {
if (a->data[i] & ~(b->data[i]))
return 0;
}
}
return 1;
}
Boolean Bv_IsEmpty(const BitVector *bv) {
UInt32 i;
for (i = 0; i < bv->size; i++) {
if (bv->data[i])
return 0;
}
return 1;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
#ifndef COMPILER_IROCSE_H
#define COMPILER_IROCSE_H
#include "IrOptimizer.h"
#include "BitVector.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
struct IROExpr {
Boolean x0;
UInt16 index;
IROLinear *linear;
Object *x8;
IRONode *node;
BitVector *depends;
IROExpr *x14;
Boolean couldError;
Boolean notSubable;
IROLinear *x1A;
VarRecord *x1E;
IROLinear *x22;
IROExpr *next;
};
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern BitVector *IRO_Depends;
extern Boolean IRO_NotSubable;
extern Boolean IRO_IsVolatile;
extern Boolean IRO_CouldError;
extern IROExpr *IRO_FirstExpr;
extern IROExpr *IRO_LastExpr;
extern SInt32 IRO_NumExprs;
extern void IRO_FindDepends_NoAlloc(IROLinear *linear);
extern void IRO_FindDepends(IROLinear *linear);
extern void IRO_FindExpressions(BitVector *bv, Boolean flag);
extern void IRO_RemoveExpr(IROExpr *expr);
extern void IRO_ComputeAvail(void);
extern void IRO_CommonSubs(void);
extern void IRO_GenerateTopLevelExprsForSubableOperands(void);
#endif

View File

@@ -0,0 +1,660 @@
#include "IroDump.h"
#include "IroCSE.h"
#include "IroFlowgraph.h"
#include "IroLinearForm.h"
#include "IroPropagate.h"
#include "IroUtil.h"
#include "IroVars.h"
#include "compiler/CFunc.h"
#include "compiler/CInt64.h"
#include "compiler/CParser.h"
#include "compiler/objects.h"
static FILE *DumpFile;
static char *nodenames[MAXEXPR];
char *IRO_NodeName(ENodeType nodetype) {
return nodenames[nodetype];
}
void IRO_InitializeNodeNamesArray(void) {
int i;
for (i = 0; i < MAXEXPR; i++)
nodenames[i] = "";
nodenames[EPOSTINC] = "EPOSTINC";
nodenames[EPOSTDEC] = "EPOSTDEC";
nodenames[EPREINC] = "EPREINC";
nodenames[EPREDEC] = "EPREDEC";
nodenames[EINDIRECT] = "EINDIRECT";
nodenames[EMONMIN] = "EMONMIN";
nodenames[EBINNOT] = "EBINNOT";
nodenames[ELOGNOT] = "ELOGNOT";
nodenames[EFORCELOAD] = "EFORCELOAD";
nodenames[EMUL] = "EMUL";
nodenames[EMULV] = "EMULV";
nodenames[EDIV] = "EDIV";
nodenames[EMODULO] = "EMODULO";
nodenames[EADDV] = "EADDV";
nodenames[ESUBV] = "ESUBV";
nodenames[EADD] = "EADD";
nodenames[ESUB] = "ESUB";
nodenames[ESHL] = "ESHL";
nodenames[ESHR] = "ESHR";
nodenames[ELESS] = "ELESS";
nodenames[EGREATER] = "EGREATER";
nodenames[ELESSEQU] = "ELESSEQU";
nodenames[EGREATEREQU] = "EGREATEREQU";
nodenames[EEQU] = "EEQU";
nodenames[ENOTEQU] = "ENOTEQU";
nodenames[EAND] = "EAND";
nodenames[EXOR] = "EXOR";
nodenames[EOR] = "EOR";
nodenames[ELAND] = "ELAND";
nodenames[ELOR] = "ELOR";
nodenames[EASS] = "EASS";
nodenames[EMULASS] = "EMULASS";
nodenames[EDIVASS] = "EDIVASS";
nodenames[EMODASS] = "EMODASS";
nodenames[EADDASS] = "EADDASS";
nodenames[ESUBASS] = "ESUBASS";
nodenames[ESHLASS] = "ESHLASS";
nodenames[ESHRASS] = "ESHRASS";
nodenames[EANDASS] = "EANDASS";
nodenames[EXORASS] = "EXORASS";
nodenames[EORASS] = "EORASS";
nodenames[ECOMMA] = "ECOMMA";
nodenames[EPMODULO] = "EPMODULO";
nodenames[EROTL] = "EROTL";
nodenames[EROTR] = "EROTR";
nodenames[EBCLR] = "EBCLR";
nodenames[EBTST] = "EBTST";
nodenames[EBSET] = "EBSET";
nodenames[ETYPCON] = "ETYPCON";
nodenames[EBITFIELD] = "EBITFIELD";
nodenames[EINTCONST] = "EINTCONST";
nodenames[EFLOATCONST] = "EFLOATCONST";
nodenames[ESTRINGCONST] = "ESTRINGCONST";
nodenames[ECOND] = "ECOND";
nodenames[EFUNCCALL] = "EFUNCCALL";
nodenames[EFUNCCALLP] = "EFUNCCALLP";
nodenames[EOBJREF] = "EOBJREF";
nodenames[EMFPOINTER] = "EMFPOINTER";
nodenames[ENULLCHECK] = "ENULLCHECK";
nodenames[EPRECOMP] = "EPRECOMP";
nodenames[ETEMP] = "ETEMP";
nodenames[EARGOBJ] = "EARGOBJ";
nodenames[ELOCOBJ] = "ELOCOBJ";
nodenames[ELABEL] = "ELABEL";
nodenames[ESETCONST] = "ESETCONST";
nodenames[ENEWEXCEPTION] = "ENEWEXCEPTION";
nodenames[ENEWEXCEPTIONARRAY] = "ENEWEXCEPTIONARRAY";
nodenames[EOBJLIST] = "EOBJLIST";
nodenames[EMEMBER] = "EMEMBER";
nodenames[ETEMPLDEP] = "ETEMPLDEP";
nodenames[EINSTRUCTION] = "EINSTRUCTION";
nodenames[EDEFINE] = "EDEFINE";
nodenames[EREUSE] = "EREUSE";
nodenames[EASSBLK] = "EASSBLK";
nodenames[EVECTOR128CONST] = "EVECTOR128CONST";
nodenames[ECONDASS] = "ECONDASS";
}
static void DumpENode(ENode *enode) {
char buf[64];
if (IRO_Log) {
switch (enode->type) {
case EOBJREF:
fprintf(DumpFile, "%s", enode->data.objref->name->name);
break;
case EINTCONST:
CInt64_PrintDec(buf, enode->data.intval);
fprintf(DumpFile, "%s", buf);
break;
case EFLOATCONST:
fprintf(DumpFile, "%g", enode->data.floatval.value);
break;
case EVECTOR128CONST:
fprintf(DumpFile, "%.8lX%.8lX%.8lX%.8lX",
enode->data.vector128val.ul[0],
enode->data.vector128val.ul[1],
enode->data.vector128val.ul[2],
enode->data.vector128val.ul[3]
);
break;
}
}
}
static void DumpLinearNode(IROLinear *linear) {
int i;
if (IRO_Log) {
fprintf(DumpFile, "%4d: ", linear->index);
switch (linear->type) {
case IROLinearNop:
fprintf(DumpFile, "Nop");
break;
case IROLinearOperand:
fprintf(DumpFile, "Operand ");
DumpENode(linear->u.node);
break;
case IROLinearOp1Arg:
fprintf(DumpFile, "%s %d", nodenames[linear->nodetype], linear->u.monadic->index);
break;
case IROLinearOp2Arg:
fprintf(DumpFile, "%s %d %d", nodenames[linear->nodetype], linear->u.diadic.left->index, linear->u.diadic.right->index);
break;
case IROLinearGoto:
fprintf(DumpFile, "Goto %s", linear->u.label.label->name->name);
break;
case IROLinearIf:
fprintf(DumpFile, "If %d %s", linear->u.label.x4->index, linear->u.label.label->name->name);
break;
case IROLinearIfNot:
fprintf(DumpFile, "IfNot %d %s", linear->u.label.x4->index, linear->u.label.label->name->name);
break;
case IROLinearReturn:
fprintf(DumpFile, "Return ");
if (linear->u.monadic)
fprintf(DumpFile, "%d", linear->u.monadic->index);
break;
case IROLinearLabel:
fprintf(DumpFile, "Label %s", linear->u.label.label->name->name);
break;
case IROLinearSwitch:
fprintf(DumpFile, "Switch %d", linear->u.swtch.x4->index);
break;
case IROLinearOp3Arg:
fprintf(DumpFile, "%s %d %d %d",
nodenames[linear->nodetype],
linear->u.args3.a->index,
linear->u.args3.b->index,
linear->u.args3.c->index);
break;
case IROLinearFunccall:
fprintf(DumpFile, "Funccall %d(", linear->u.funccall.linear8->index);
for (i = 0; i < linear->u.funccall.argCount; i++) {
fprintf(DumpFile, "%d", linear->u.funccall.args[i]->index);
if (i < (linear->u.funccall.argCount - 1))
fprintf(DumpFile, ",");
}
fprintf(DumpFile, ")");
break;
case IROLinearBeginCatch:
fprintf(DumpFile, "BeginCatch %d", linear->u.ctch.linear->index);
break;
case IROLinearEndCatch:
fprintf(DumpFile, "EndCatch %d", linear->u.monadic->index);
break;
case IROLinearEndCatchDtor:
fprintf(DumpFile, "EndCatchDtor %d", linear->u.monadic->index);
break;
case IROLinearEnd:
fprintf(DumpFile, "End");
break;
}
if (linear->flags & IROLF_Assigned) fprintf(DumpFile, " <assigned>");
if (linear->flags & IROLF_Used) fprintf(DumpFile, " <used>");
if (linear->flags & IROLF_Ind) fprintf(DumpFile, " <ind>");
if (linear->flags & IROLF_Subs) fprintf(DumpFile, " <subs>");
if (linear->flags & IROLF_LoopInvariant) fprintf(DumpFile, " <loop invariant>");
if (linear->flags & IROLF_BeginLoop) fprintf(DumpFile, " <begin loop>");
if (linear->flags & IROLF_EndLoop) fprintf(DumpFile, " <end loop>");
if (linear->flags & IROLF_Ris) fprintf(DumpFile, " <ris>");
if (linear->flags & IROLF_Immind) fprintf(DumpFile, " <immind>");
if (linear->flags & IROLF_Reffed) fprintf(DumpFile, " <reffed>");
if (linear->flags & IROLF_VecOp) fprintf(DumpFile, " <vec op>");
if (linear->flags & IROLF_VecOpBase) fprintf(DumpFile, " <vec op_base>");
if (linear->flags & IROLF_CounterLoop) fprintf(DumpFile, " <counter loop>");
if (linear->flags & IROLF_BitfieldIndirect) fprintf(DumpFile, " <bitfield_indirect>");
if (linear->flags & IROLF_CouldError) fprintf(DumpFile, " <could_error>");
if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS))
fprintf(DumpFile, " <volatile>");
if (IS_LINEAR_ENODE(linear, EOBJREF)) {
VarRecord *var = IRO_FindVar(linear->u.node->data.objref, 0, 1);
if (var && is_volatile_object(var->object))
fprintf(DumpFile, " <volatile obj>");
}
fprintf(DumpFile, "\n");
}
}
static void DumpAct(IROLinear *linear, Boolean isFirst) {
if (!isFirst)
DumpLinearNode(linear);
}
void IRO_DumpIntTree(IROLinear *linear) {
IRO_WalkTree(linear, DumpAct);
}
void IRO_DumpLinearList(IROLinear *linear) {
if (!IRO_Log)
return;
while (linear) {
DumpLinearNode(linear);
linear = linear->next;
}
fprintf(DumpFile, "\n");
}
static void DumpList(int num, UInt16 *list) {
int i;
if (IRO_Log) {
for (i = 0; i < num; i++)
fprintf(DumpFile, "%d ", list[i]);
fprintf(DumpFile, "\n");
}
}
void IRO_DumpBits(char *name, BitVector *bv) {
SInt32 i;
SInt32 rangeStart;
Boolean inRange = 0;
Boolean isFirst = 1;
if (!IRO_Log)
return;
fprintf(DumpFile, name);
if (!bv) {
fprintf(DumpFile, "NULL");
} else {
for (i = 0; i < (bv->size * 32); i++) {
if (Bv_IsBitSet(i, bv)) {
if (!inRange) {
if (!isFirst)
fputc(',', DumpFile);
isFirst = 0;
fprintf(DumpFile, "%d", i);
inRange = 1;
rangeStart = i;
}
} else {
if (inRange) {
inRange = 0;
if (i != (rangeStart + 1))
fprintf(DumpFile, "-%d", i - 1);
}
}
}
if (inRange && i != (rangeStart + 1))
fprintf(DumpFile, "-%d", i - 1);
}
fprintf(DumpFile, "\n");
}
void IRO_DumpAfterPhase(char *str, Boolean flag) {
#ifdef CW_ENABLE_IRO_DEBUG
if (copts.debuglisting)
flag = 1;
#endif
if (flag) {
IRO_Dump("Dumping function %s after %s \n", FunctionName ? FunctionName->name->name : "Init-code", str);
IRO_Dump("--------------------------------------------------------------------------------\n");
IRO_DumpFlowgraph();
}
}
void IRO_LogForFunction(char *name) {
if (FunctionName) {
if (!strcmp(FunctionName->name->name, name))
IRO_Log = 1;
else
IRO_Log = 0;
}
}
void IRO_DumpFlowgraph(void) {
IRONode *node;
IROLinear *linear;
if (IRO_Log && DumpFile) {
fprintf(DumpFile, "\nFlowgraph\n");
for (node = IRO_FirstNode; node; node = node->nextnode) {
fprintf(DumpFile, "Flowgraph node %d First=%d, Last=%d\n", node->index, node->first->index, node->last->index);
fprintf(DumpFile, "Succ = ");
DumpList(node->numsucc, node->succ);
fprintf(DumpFile, "Pred = ");
DumpList(node->numpred, node->pred);
fprintf(DumpFile, "MustReach = %d, MustReach1=%d\n", node->mustreach, node->mustreach1);
fprintf(DumpFile, "LoopDepth = %d\n", node->loopdepth);
IRO_DumpBits("Dom: ", node->dom);
if ((linear = node->first)) {
while (1) {
DumpLinearNode(linear);
if (linear == node->last)
break;
linear = linear->next;
}
}
fprintf(DumpFile, "\n\n");
}
fprintf(DumpFile, "\n");
fflush(DumpFile);
}
}
void IRO_DumpNode(IRONode *node) {
IROLinear *linear;
if (IRO_Log) {
if (!DumpFile)
return;
while (node) {
fprintf(DumpFile, "Flowgraph node %d First=%d, Last=%d\n", node->index, node->first->index,
node->last->index);
fprintf(DumpFile, "Succ = ");
DumpList(node->numsucc, node->succ);
fprintf(DumpFile, "Pred = ");
DumpList(node->numpred, node->pred);
fprintf(DumpFile, "MustReach = %d MustReach1 = %d\n", node->mustreach, node->mustreach1);
fprintf(DumpFile, "LoopDepth = %d\n", node->loopdepth);
IRO_DumpBits("Dom: ", node->dom);
if ((linear = node->first)) {
while (1) {
DumpLinearNode(linear);
if (linear == node->last)
break;
linear = linear->next;
}
}
fprintf(DumpFile, "\n\n");
node = node->nextnode;
}
fprintf(DumpFile, "\n");
fflush(DumpFile);
}
}
void IRO_DumpAssignments(void) {
IROAssign *assign;
if (IRO_Log) {
fprintf(DumpFile, "\nAssignments\n\n");
for (assign = IRO_FirstAssign; assign; assign = assign->next) {
fprintf(DumpFile, "%5d ", assign->index);
DumpLinearNode(assign->linear);
fprintf(DumpFile, "\n");
}
fprintf(DumpFile, "\n");
}
}
void IRO_DumpVars(void) {
VarRecord *var;
if (IRO_Log) {
fprintf(DumpFile, "\nVariables\n");
for (var = IRO_FirstVar; var; var = var->next) {
fprintf(DumpFile, "%5d %s %s\n", var->index, var->object->name->name, var->xB ? "<addressed>" : "");
}
fprintf(DumpFile, "\n");
}
}
void IRO_DumpDf(void) {
IRONode *node;
if (IRO_Log) {
for (node = IRO_FirstNode; node; node = node->nextnode) {
fprintf(DumpFile, "Node %d\n", node->index);
if (node->x16) IRO_DumpBits("In: ", node->x16);
if (node->x1E) IRO_DumpBits("Gen: ", node->x1E);
if (node->x22) IRO_DumpBits("Kill: ", node->x22);
if (node->x1A) IRO_DumpBits("Out: ", node->x1A);
if (node->x2A) IRO_DumpBits("AA: ", node->x2A);
fprintf(DumpFile, "\n");
}
fprintf(DumpFile, "\n");
}
}
void IRO_DumpExprs(void) {
IROExpr *expr;
if (IRO_Log) {
fprintf(DumpFile, "Expressions\n\n");
for (expr = IRO_FirstExpr; expr; expr = expr->next) {
fprintf(DumpFile, "%4d: %d FN:%d CE:%d NS:%d ", expr->index, expr->linear->index, expr->node->index, expr->couldError, expr->notSubable);
IRO_DumpBits("Depends: ", expr->depends);
fprintf(DumpFile, "\n");
}
fprintf(DumpFile, "\n");
}
}
void IRO_SetupDump(void) {
#ifdef CW_ENABLE_IRO_DEBUG
IRO_Log = 1;
#endif
if (IRO_Log) {
if ((DumpFile = fopen("OPT.LOG", "wt")) == NULL)
IRO_Log = 0;
}
}
void IRO_CleanupDump(void) {
if (DumpFile)
fclose(DumpFile);
}
void IRO_Dump(char *format, ...) {
va_list va;
if (IRO_Log) {
va_start(va, format);
vfprintf(DumpFile, format, va);
va_end(va);
}
}
void IRO_DumpAddr(IROAddrRecord *rec) {
IROElmList *list;
if (IRO_Log && DumpFile) {
fprintf(DumpFile, "\n");
fprintf(DumpFile, "Address :\n");
IRO_DumpIntTree(rec->linear);
fprintf(DumpFile, "\n");
fprintf(DumpFile, "BaseTerms:\n");
for (list = rec->objRefs; list; list = list->next) {
IRO_DumpIntTree(list->element);
fprintf(DumpFile, "\n");
}
fprintf(DumpFile, "VarTerms:\n");
for (list = rec->misc; list; list = list->next) {
IRO_DumpIntTree(list->element);
fprintf(DumpFile, "\n");
}
fprintf(DumpFile, "ConstTerms:\n");
for (list = rec->ints; list; list = list->next) {
IRO_DumpIntTree(list->element);
fprintf(DumpFile, "\n");
}
}
}
static void IRO_DumpType(Type *type) {
char buf[256];
IRO_SpellType(type, buf);
fprintf(DumpFile, " (%s)", buf);
}
void IRO_SpellType(Type *type, char *buf) {
char mybuf[256];
char mybuf2[256];
switch (type->type) {
case TYPEVOID:
strcpy(buf, "void");
break;
case TYPEINT:
switch (TYPE_INTEGRAL(type)->integral) {
case IT_BOOL:
strcpy(buf, "bool");
break;
case IT_CHAR:
strcpy(buf, "char");
break;
case IT_WCHAR_T:
strcpy(buf, "wchar_t");
break;
case IT_SCHAR:
strcpy(buf, "signed char");
break;
case IT_UCHAR:
strcpy(buf, "unsigned char");
break;
case IT_SHORT:
strcpy(buf, "short");
break;
case IT_USHORT:
strcpy(buf, "unsigned short");
break;
case IT_INT:
strcpy(buf, "int");
break;
case IT_UINT:
strcpy(buf, "unsigned int");
break;
case IT_LONG:
strcpy(buf, "long");
break;
case IT_ULONG:
strcpy(buf, "unsigned long");
break;
case IT_LONGLONG:
strcpy(buf, "long long");
break;
case IT_ULONGLONG:
strcpy(buf, "unsigned long long");
break;
}
break;
case TYPEFLOAT:
switch (TYPE_INTEGRAL(type)->integral) {
case IT_FLOAT:
strcpy(buf, "float");
break;
case IT_SHORTDOUBLE:
strcpy(buf, "short double");
break;
case IT_DOUBLE:
strcpy(buf, "double");
break;
case IT_LONGDOUBLE:
strcpy(buf, "long double");
break;
}
break;
case TYPEENUM:
strcpy(buf, "enum ");
if (TYPE_ENUM(type)->enumname)
strcat(buf, TYPE_ENUM(type)->enumname->name);
break;
case TYPESTRUCT:
if (IS_TYPESTRUCT_VECTOR(TYPE_STRUCT(type))) {
switch (TYPE_STRUCT(type)->stype) {
case STRUCT_VECTOR_UCHAR:
strcpy(buf, "vector unsigned char ");
break;
case STRUCT_VECTOR_SCHAR:
strcpy(buf, "vector signed char ");
break;
case STRUCT_VECTOR_BCHAR:
strcpy(buf, "vector bool char ");
break;
case STRUCT_VECTOR_USHORT:
strcpy(buf, "vector unsigned short ");
break;
case STRUCT_VECTOR_SSHORT:
strcpy(buf, "vector signed short ");
break;
case STRUCT_VECTOR_BSHORT:
strcpy(buf, "vector bool short ");
break;
case STRUCT_VECTOR_UINT:
strcpy(buf, "vector unsigned long ");
break;
case STRUCT_VECTOR_SINT:
strcpy(buf, "vector signed long ");
break;
case STRUCT_VECTOR_BINT:
strcpy(buf, "vector bool long ");
break;
case STRUCT_VECTOR_FLOAT:
strcpy(buf, "vector float ");
break;
case STRUCT_VECTOR_PIXEL:
strcpy(buf, "vector pixel ");
break;
}
} else {
strcpy(buf, "struct ");
}
if (TYPE_STRUCT(type)->name)
strcat(buf, TYPE_STRUCT(type)->name->name);
break;
case TYPECLASS:
strcpy(buf, "class ");
if (TYPE_CLASS(type)->classname)
strcat(buf, TYPE_CLASS(type)->classname->name);
break;
case TYPEFUNC:
IRO_SpellType(TYPE_FUNC(type)->functype, mybuf);
strcpy(buf, "freturns(");
strcat(buf, mybuf);
strcat(buf, ")");
break;
case TYPEBITFIELD:
IRO_SpellType(TYPE_BITFIELD(type)->bitfieldtype, mybuf);
sprintf(buf, "bitfield(%s){%d:%d}", mybuf, TYPE_BITFIELD(type)->offset, TYPE_BITFIELD(type)->bitlength);
break;
case TYPELABEL:
strcpy(buf, "label");
break;
case TYPEPOINTER:
IRO_SpellType(TPTR_TARGET(type), mybuf);
strcpy(buf, "pointer(");
strcat(buf, mybuf);
strcat(buf, ")");
break;
case TYPEARRAY:
IRO_SpellType(TPTR_TARGET(type), mybuf);
strcpy(buf, "array(");
strcat(buf, mybuf);
strcat(buf, ")");
break;
case TYPEMEMBERPOINTER:
IRO_SpellType(TYPE_MEMBER_POINTER(type)->ty2, mybuf);
IRO_SpellType(TYPE_MEMBER_POINTER(type)->ty1, mybuf2);
strcpy(buf, "memberpointer(");
strcat(buf, mybuf);
strcat(buf, ",");
strcat(buf, mybuf2);
strcat(buf, ")");
break;
}
}

View File

@@ -0,0 +1,27 @@
#ifndef COMPILER_IRODUMP_H
#define COMPILER_IRODUMP_H
#include "IrOptimizer.h"
#include "BitVector.h"
#include "compiler/enode.h"
extern char *IRO_NodeName(ENodeType nodetype);
extern void IRO_InitializeNodeNamesArray(void);
extern void IRO_DumpIntTree(IROLinear *linear);
extern void IRO_DumpLinearList(IROLinear *linear);
extern void IRO_DumpBits(char *name, BitVector *bv);
extern void IRO_DumpAfterPhase(char *str, Boolean flag);
extern void IRO_LogForFunction(char *name);
extern void IRO_DumpFlowgraph(void);
extern void IRO_DumpNode(IRONode *node);
extern void IRO_DumpAssignments(void);
extern void IRO_DumpVars(void);
extern void IRO_DumpDf(void);
extern void IRO_DumpExprs(void);
extern void IRO_SetupDump(void);
extern void IRO_CleanupDump(void);
extern void IRO_Dump(char *format, ...);
extern void IRO_DumpAddr(IROAddrRecord *rec);
extern void IRO_SpellType(Type *type, char *buf);
#endif

View File

@@ -0,0 +1,560 @@
#include "IroEmptyLoop.h"
#include "IroDump.h"
#include "IroFlowgraph.h"
#include "IroLinearForm.h"
#include "IroLoop.h"
#include "IroUtil.h"
#include "IroVars.h"
#include "compiler/CInt64.h"
// forward decls
static Boolean EmptyLoop(IRONode *fnode);
static int CanRemoveRedundantLoop(IROLoop *loop);
static int CanRemoveRedundantLoop1(IROLoop *loop);
static int RedundantLoopCheck(IROLoop *loop);
static int CheckStepOverFlow1_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2);
static int CheckStepOverFlow2_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2);
void IRO_FindEmptyLoops(void) {
IRONode *fnode;
IRONode *pred;
UInt16 i;
UInt16 x;
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
x = 0;
for (i = 0; i < fnode->numpred; i++) {
pred = IRO_NodeTable[fnode->pred[i]];
if (Bv_IsBitSet(fnode->index, pred->dom)) {
if (!x) {
Bv_AllocVector(&InLoop, IRO_NumNodes + 1);
Bv_Clear(InLoop);
Bv_SetBit(fnode->index, InLoop);
}
x = 1;
Bv_SetBit(pred->index, InLoop);
if (pred != fnode)
AddPreds(pred);
}
}
if (x) {
IRO_Dump("IRO_FindEmptyLoops:Found loop with header %d\n", fnode->index);
IRO_DumpBits("Loop includes: ", InLoop);
EmptyLoop(fnode);
IRO_UpdateFlagsOnInts();
}
}
IRO_CheckForUserBreak();
}
static Boolean EmptyLoop(IRONode *fnode) {
VarRecord *var;
IRONode *bestpred;
IRONode *pred;
UInt16 i;
int flag2;
IRONode *r24;
Boolean flag;
int counter;
int j;
IRONode *succ;
IRONode *bestsucc;
int counter2;
UInt32 counter3;
IROLoop *loop;
IRONode *r21;
IRONode *r20;
IROLinear *constnd;
Type *type20;
ENode *enode;
IROLinear *save;
flag = 0;
counter = 0;
LoopNode = fnode;
FindMustReach();
for (var = IRO_FirstVar; var; var = var->next)
var->xA = 1;
ComputeLoopKills();
ComputeLoopInvariance();
ComputeLoopInduction();
LoopNode = fnode;
ConditionalHeaderAtBottom = 0;
bestpred = NULL;
flag2 = 0;
for (i = 0; i < LoopNode->numpred; i++) {
pred = IRO_NodeTable[LoopNode->pred[i]];
if (!Bv_IsBitSet(pred->index, InLoop)) {
flag2 = 1;
if (pred->nextnode == fnode) {
CError_ASSERT(173, !bestpred || pred == bestpred);
bestpred = pred;
}
}
}
if (!flag2) {
IRO_Dump("No predecessor outside the loop\n");
return 0;
}
bestsucc = NULL;
for (i = 0; i < LoopNode->numsucc; i++) {
succ = IRO_NodeTable[LoopNode->succ[i]];
if (Bv_IsBitSet(succ->index, InLoop)) {
bestsucc = succ;
counter++;
}
}
if (LoopNode == bestsucc && counter == 1)
flag = 1;
if (LoopNode->last->type != IROLinearIf || LoopNode->last->type != IROLinearIfNot || flag) {
counter2 = 0;
for (j = 0; j < LoopNode->numpred; j++) {
if (Bv_IsBitSet(IRO_NodeTable[LoopNode->pred[j]]->index, InLoop)) {
r21 = IRO_NodeTable[LoopNode->pred[j]];
counter2++;
}
}
r24 = NULL;
counter3 = 0;
for (j = 0; j < LoopNode->numpred; j++) {
if (!Bv_IsBitSet(IRO_NodeTable[LoopNode->pred[j]]->index, InLoop)) {
r24 = IRO_NodeTable[LoopNode->pred[j]];
counter3++;
}
}
if (counter2 == 1 && counter3 == 1) {
if (r21->last->type == IROLinearIf) {
if ((Bv_IsBitSet(LoopNode->nextnode->index, InLoop) && !Bv_IsBitSet(r21->nextnode->index, InLoop)) || flag) {
IRO_Dump("Standard while loop layout\n");
loop = ExtractLoopInfo(r21);
if (flag)
loop->flags |= LoopFlags_20000;
FindAssignmenttoInductionVar(loop, r24);
r20 = r24;
while (r20 && !loop->nd14 && r20->numpred == 1 && IRO_NodeTable[r20->pred[0]]->numsucc == 1) {
FindAssignmenttoInductionVar(loop, IRO_NodeTable[r20->pred[0]]);
r20 = IRO_NodeTable[r20->pred[0]];
}
if (CanRemoveRedundantLoop(loop)) {
IRO_Dump("EmptyLoop: # of iterations =%" PRId32 ", FinalStoreVal=%" PRId32 "\n", CInt64_GetULong(&loop->x28), CInt64_GetULong(&loop->x30));
IRO_NopOut(r21->last->u.label.x4);
r21->last->type = IROLinearNop;
type20 = loop->induction->nd->rtype;
constnd = IRO_NewLinear(IROLinearOperand);
constnd->index = ++IRO_NumLinear;
enode = IRO_NewENode(EINTCONST);
enode->rtype = type20;
enode->data.intval = loop->x30;
constnd->u.node = enode;
constnd->rtype = type20;
if (loop->induction->nd->type == IROLinearOp1Arg) {
save = loop->induction->nd->u.monadic;
loop->induction->nd->type = IROLinearOp2Arg;
loop->induction->nd->nodetype = EASS;
loop->induction->nd->u.diadic.left = save;
loop->induction->nd->u.diadic.right = constnd;
IRO_Paste(constnd, constnd, loop->induction->nd);
} else if (loop->induction->nd->type == IROLinearOp2Arg) {
loop->induction->nd->nodetype = EASS;
IRO_NopOut(loop->induction->nd->u.diadic.right);
loop->induction->nd->u.diadic.right = constnd;
IRO_Paste(constnd, constnd, loop->induction->nd);
}
} else if (CanRemoveRedundantLoop1(loop)) {
IRO_Dump("EmptyLoop: self recursive dowhile(--n ) loop\n");
r21->last->type = IROLinearNop;
type20 = loop->induction->nd->rtype;
constnd = IRO_NewLinear(IROLinearOperand);
constnd->index = ++IRO_NumLinear;
enode = IRO_NewENode(EINTCONST);
enode->rtype = type20;
enode->data.intval = cint64_zero;
constnd->u.node = enode;
constnd->rtype = type20;
save = loop->induction->nd->u.monadic;
loop->induction->nd->type = IROLinearOp2Arg;
loop->induction->nd->nodetype = EASS;
loop->induction->nd->u.diadic.left = save;
loop->induction->nd->u.diadic.right = constnd;
IRO_Paste(constnd, constnd, loop->induction->nd);
}
} else {
IRO_Dump("NonStandard while loop layout\n");
}
} else {
IRO_Dump("NonStandard while loop layout\n");
}
} else {
IRO_Dump("Cannot handle Do While Loop with multiple tails\n");
}
}
return 0;
}
static int CanRemoveRedundantLoop(IROLoop *loop) {
IROLinear *inner;
if (loop->flags & LoopFlags_10000) {
IRO_Dump("CanRemoveRedundantLoop:No because detection of dowhile(n--) loop not supported\n");
return 0;
}
if (loop->flags & LP_LOOP_HAS_ASM) {
IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_ASM \n");
return 0;
}
if (loop->flags & LP_IFEXPR_NON_CANONICAL) {
IRO_Dump("CanRemoveRedundantLoop:No due to LP_IFEXPR_NON_CANONICAL \n");
return 0;
}
if (loop->flags & LP_LOOP_HAS_CALLS) {
IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_CALLS \n");
return 0;
}
if (loop->flags & LP_LOOP_HAS_CNTRLFLOW) {
IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_CNTRLFLOW \n");
return 0;
}
if (loop->flags & LP_INDUCTION_NOT_FOUND) {
IRO_Dump("CanRemoveRedundantLoop:No due to LP_INDUCTION_NOT_FOUND \n");
return 0;
}
if (loop->flags & LP_HAS_MULTIPLE_INDUCTIONS) {
IRO_Dump("CanRemoveRedundantLoop:No due to LP_HAS_MULTIPLE_INDUCTIONS \n");
return 0;
}
if (loop->flags & LP_LOOP_HDR_HAS_SIDEEFFECTS) {
IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HDR_HAS_SIDEEFFECTS \n");
return 0;
}
if (!(loop->flags & LoopFlags_200)) {
IRO_Dump("CanRemoveRedundantLoop:No because header does not follow induction update \n");
return 0;
}
if (!(loop->flags & LoopFlags_10000)) {
inner = loop->nd18->u.diadic.right;
if (!IRO_IsIntConstant(inner) && !(inner->flags & IROLF_LoopInvariant)) {
IRO_Dump("CanRemoveRedundantLoop:No because Loop Upper Bound is Variant in the loop\n");
return 0;
}
if (!loop->nd14) {
IRO_Dump("CanRemoveRedundantLoop:No because there is no initialization of loop index in PreHeader\n");
return 0;
}
if (!IRO_IsVariable(loop->nd14->u.diadic.left)) {
IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction stored thru pointer\n");
return 0;
}
if (!IRO_IsUnsignedType(loop->nd14->rtype)) {
if (IRO_IsIntConstant(loop->nd14->u.diadic.right)) {
if (!CInt64_GreaterEqual(loop->nd14->u.diadic.right->u.node->data.intval, cint64_zero)) {
IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction is signed but < 0\n");
return 0;
}
} else {
IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction is signed and not constant\n");
return 0;
}
}
if (!(loop->flags & LP_LOOP_STEP_ISPOS) && !(loop->flags & LP_LOOP_STEP_ISNEG)) {
IRO_Dump("CanRemoveRedundantLoop:No because LP_LOOP_STEP_ISPOS/LP_LOOP_STEP_ISNEG is not set\n");
return 0;
}
if ((loop->flags & LP_LOOP_STEP_ISPOS) && CheckStepOverFlow1_EmptyLoop(loop, &loop->x28, &loop->x30)) {
IRO_Dump("CanRemoveRedundantLoop:No because Final Value of indution will overflow\n");
return 0;
}
if ((loop->flags & LP_LOOP_STEP_ISNEG) && CheckStepOverFlow2_EmptyLoop(loop, &loop->x28, &loop->x30)) {
IRO_Dump("CanRemoveRedundantLoop:No because Final Value of indution will overflow\n");
return 0;
}
}
return RedundantLoopCheck(loop) != 0;
}
static int CanRemoveRedundantLoop1(IROLoop *loop) {
if ((loop->flags & LoopFlags_10000) && (loop->flags & LoopFlags_20000)) {
if (loop->flags & LP_LOOP_HAS_ASM) {
IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_ASM \n");
return 0;
}
if (loop->flags & LP_IFEXPR_NON_CANONICAL) {
IRO_Dump("CanRemoveRedundantLoop1:No due to LP_IFEXPR_NON_CANONICAL \n");
return 0;
}
if (loop->flags & LP_LOOP_HAS_CALLS) {
IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_CALLS \n");
return 0;
}
if (loop->flags & LP_LOOP_HAS_CNTRLFLOW) {
IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_CNTRLFLOW \n");
return 0;
}
if (loop->flags & LP_INDUCTION_NOT_FOUND) {
IRO_Dump("CanRemoveRedundantLoop1:No due to LP_INDUCTION_NOT_FOUND \n");
return 0;
}
if (loop->flags & LP_HAS_MULTIPLE_INDUCTIONS) {
IRO_Dump("CanRemoveRedundantLoop1:No due to LP_HAS_MULTIPLE_INDUCTIONS \n");
return 0;
}
if (loop->flags & LP_LOOP_HDR_HAS_SIDEEFFECTS) {
IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HDR_HAS_SIDEEFFECTS \n");
return 0;
}
if (!(loop->flags & LoopFlags_200)) {
IRO_Dump("CanRemoveRedundantLoop1:No because header does not follow induction update \n");
return 0;
}
if (loop->induction->nd->type == IROLinearOp1Arg && loop->induction->nd->nodetype == EPREDEC) {
if (IRO_IsUnsignedType(loop->induction->nd->rtype))
return 1;
IRO_Dump("CanRemoveRedundantLoop1:No because induction not of the right type \n");
return 0;
}
IRO_Dump("CanRemoveRedundantLoop1:No because induction operator not a predec \n");
return 0;
} else {
return 0;
}
}
static int RedundantLoopCheck(IROLoop *loop) {
IRONode *fnode;
IROLinear *nd;
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
if (Bv_IsBitSet(fnode->index, InLoop) && fnode != loop->fnode && (nd = fnode->first)) {
while (1) {
if ((nd->index < loop->index20 || nd->index > loop->index24) && nd->type != IROLinearNop && nd->type != IROLinearLabel) {
if (IS_LINEAR_DIADIC(nd, EASS)) {
if (!(nd->flags & IROLF_Reffed)) {
if (IS_LINEAR_MONADIC(nd->u.diadic.left, EINDIRECT)) {
if (nd->u.diadic.left->rtype && CParser_IsVolatile(nd->u.diadic.left->rtype, nd->u.diadic.left->nodeflags & ENODE_FLAG_QUALS)) {
IRO_Dump(" EASS at %d fail as store to volatile memory \n", nd->index);
return 0;
}
if ((nd->u.diadic.left->u.monadic->flags & IROLF_LoopInvariant) && (nd->u.diadic.right->flags & IROLF_LoopInvariant)) {
IRO_Dump(" EASS at %d pass\n", nd->index);
} else {
IRO_Dump(" EASS at %d fail, either LHS address or RHS is variant \n", nd->index);
return 0;
}
} else {
IRO_Dump("Found EASS nodes whose lhs root is not a EINDIRECT node\n");
return 0;
}
} else {
IRO_Dump("Found EASS node that is referenced i.e embedded assignment\n");
return 0;
}
} else {
if (!(nd->flags & IROLF_Reffed)) {
IRO_Dump("Found non EASS top level node in the loop\n");
return 0;
}
}
}
if (nd == fnode->last)
break;
nd = nd->next;
}
}
}
return 1;
}
static int CheckStepOverFlow1_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2) {
Boolean isUnsigned;
IROLinear *nd2;
IROLinear *nd1;
CInt64 nd2value;
CInt64 nd1value;
CInt64 addConst;
CInt64 work;
CInt64 neg1;
nd2 = loop->nd14->u.diadic.right;
nd1 = loop->nd18->u.diadic.right;
isUnsigned = IRO_IsUnsignedType(loop->nd18->u.diadic.right->rtype);
if (IRO_IsIntConstant(nd2) && IRO_IsIntConstant(nd1)) {
nd2value = nd2->u.node->data.intval;
nd1value = nd1->u.node->data.intval;
if (isUnsigned) {
if (CInt64_LessEqualU(nd1value, nd2value))
return 1;
} else {
if (CInt64_LessEqual(nd1value, nd2value))
return 1;
}
CInt64_SetLong(&addConst, loop->induction->addConst);
CInt64_SetLong(&neg1, -1);
*val1 = CInt64_Sub(nd1value, nd2value);
*val1 = CInt64_Add(*val1, addConst);
if (IS_LINEAR_DIADIC(loop->nd18, ELESS))
*val1 = CInt64_Add(*val1, neg1);
CError_ASSERT(855, !CInt64_IsZero(&addConst));
if (isUnsigned)
*val1 = CInt64_DivU(*val1, addConst);
else
*val1 = CInt64_Div(*val1, addConst);
if (CInt64_Equal(*val1, cint64_zero))
return 1;
if (isUnsigned) {
if (CInt64_LessEqualU(*val1, cint64_zero))
CError_FATAL(877);
} else {
if (CInt64_LessEqual(*val1, cint64_zero))
CError_FATAL(886);
}
if (isUnsigned) {
*val2 = CInt64_MulU(*val1, addConst);
*val2 = CInt64_Add(*val2, nd2value);
} else {
*val2 = CInt64_Mul(*val1, addConst);
*val2 = CInt64_Add(*val2, nd2value);
}
} else {
return 1;
}
CInt64_SetLong(&addConst, loop->induction->addConst);
work = CInt64_Add(nd1value, addConst);
if (isUnsigned) {
if (CInt64_LessU(work, nd1value))
return 1;
} else {
if (CInt64_Less(work, nd1value))
return 1;
}
return 0;
}
static int CheckStepOverFlow2_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2) {
Boolean isUnsigned;
IROLinear *nd2;
IROLinear *nd1;
CInt64 nd2value;
CInt64 nd1value;
CInt64 addConst;
CInt64 work;
CInt64 neg1;
nd1 = loop->nd14->u.diadic.right;
nd2 = loop->nd18->u.diadic.right;
isUnsigned = IRO_IsUnsignedType(loop->nd18->u.diadic.right->rtype);
if (IRO_IsIntConstant(nd2) && IRO_IsIntConstant(nd1)) {
nd2value = nd2->u.node->data.intval;
nd1value = nd1->u.node->data.intval;
if (isUnsigned) {
if (CInt64_LessEqualU(nd1value, nd2value))
return 1;
} else {
if (CInt64_LessEqual(nd1value, nd2value))
return 1;
}
CInt64_SetLong(&addConst, loop->induction->addConst);
CInt64_SetLong(&neg1, -1);
*val1 = CInt64_Sub(nd1value, nd2value);
*val1 = CInt64_Add(*val1, addConst);
if (IS_LINEAR_DIADIC(loop->nd18, EGREATER))
*val1 = CInt64_Add(*val1, neg1);
CError_ASSERT(995, !CInt64_IsZero(&addConst));
if (isUnsigned)
*val1 = CInt64_DivU(*val1, addConst);
else
*val1 = CInt64_Div(*val1, addConst);
if (CInt64_Equal(*val1, cint64_zero))
return 1;
if (isUnsigned) {
if (CInt64_LessEqualU(*val1, cint64_zero))
return 0;
} else {
if (CInt64_LessEqual(*val1, cint64_zero))
return 0;
}
if (isUnsigned) {
*val2 = CInt64_MulU(*val1, addConst);
*val2 = CInt64_Sub(nd1value, *val2);
} else {
*val2 = CInt64_Mul(*val1, addConst);
*val2 = CInt64_Sub(nd1value, *val2);
}
} else {
return 1;
}
CInt64_SetLong(&addConst, loop->induction->addConst);
work = CInt64_Sub(nd2value, addConst);
if (isUnsigned) {
if (CInt64_GreaterU(work, nd2value))
return 1;
} else {
if (CInt64_Greater(work, nd1value))
return 1;
}
return 0;
}

View File

@@ -0,0 +1,8 @@
#ifndef COMPILER_IROEMPTYLOOP_H
#define COMPILER_IROEMPTYLOOP_H
#include "IrOptimizer.h"
extern void IRO_FindEmptyLoops(void);
#endif

View File

@@ -0,0 +1,914 @@
#include "IroEval.h"
#include "compiler/CInt64.h"
#include "compiler/CMachine.h"
#include "compiler/CParser.h"
#include "IroFlowgraph.h"
#include "IroLinearForm.h"
#include "IroMalloc.h"
#include "IroPointerAnalysis.h"
#include "IroUtil.h"
#include "IroVars.h"
#include "compiler/enode.h"
#include "compiler/objects.h"
#include "compiler/types.h"
static Boolean IsAssociativeENodeType[MAXEXPR];
void IRO_InitializeIsAssociativeENodeTypeArray(void) {
int i;
for (i = 0; i < MAXEXPR; i++)
IsAssociativeENodeType[i] = 0;
IsAssociativeENodeType[EPOSTINC] = 0;
IsAssociativeENodeType[EPOSTDEC] = 0;
IsAssociativeENodeType[EPREINC] = 0;
IsAssociativeENodeType[EPREDEC] = 0;
IsAssociativeENodeType[EINDIRECT] = 0;
IsAssociativeENodeType[EMONMIN] = 0;
IsAssociativeENodeType[EBINNOT] = 0;
IsAssociativeENodeType[ELOGNOT] = 0;
IsAssociativeENodeType[EFORCELOAD] = 0;
IsAssociativeENodeType[EMUL] = 1;
IsAssociativeENodeType[EMULV] = 1;
IsAssociativeENodeType[EDIV] = 0;
IsAssociativeENodeType[EMODULO] = 0;
IsAssociativeENodeType[EADDV] = 1;
IsAssociativeENodeType[ESUBV] = 0;
IsAssociativeENodeType[EADD] = 1;
IsAssociativeENodeType[ESUB] = 0;
IsAssociativeENodeType[ESHL] = 0;
IsAssociativeENodeType[ESHR] = 0;
IsAssociativeENodeType[ELESS] = 0;
IsAssociativeENodeType[EGREATER] = 0;
IsAssociativeENodeType[ELESSEQU] = 0;
IsAssociativeENodeType[EGREATEREQU] = 0;
IsAssociativeENodeType[EEQU] = 0;
IsAssociativeENodeType[ENOTEQU] = 0;
IsAssociativeENodeType[EAND] = 1;
IsAssociativeENodeType[EXOR] = 1;
IsAssociativeENodeType[EOR] = 1;
IsAssociativeENodeType[ELAND] = 0;
IsAssociativeENodeType[ELOR] = 0;
IsAssociativeENodeType[EASS] = 0;
IsAssociativeENodeType[EMULASS] = 0;
IsAssociativeENodeType[EDIVASS] = 0;
IsAssociativeENodeType[EMODASS] = 0;
IsAssociativeENodeType[EADDASS] = 0;
IsAssociativeENodeType[ESUBASS] = 0;
IsAssociativeENodeType[ESHLASS] = 0;
IsAssociativeENodeType[ESHRASS] = 0;
IsAssociativeENodeType[EANDASS] = 0;
IsAssociativeENodeType[EXORASS] = 0;
IsAssociativeENodeType[EORASS] = 0;
IsAssociativeENodeType[ECOMMA] = 0;
IsAssociativeENodeType[EPMODULO] = 0;
IsAssociativeENodeType[EROTL] = 0;
IsAssociativeENodeType[EROTR] = 0;
IsAssociativeENodeType[EBCLR] = 0;
IsAssociativeENodeType[EBTST] = 0;
IsAssociativeENodeType[EBSET] = 0;
IsAssociativeENodeType[ETYPCON] = 0;
IsAssociativeENodeType[EBITFIELD] = 0;
IsAssociativeENodeType[EINTCONST] = 0;
IsAssociativeENodeType[EFLOATCONST] = 0;
IsAssociativeENodeType[ESTRINGCONST] = 0;
IsAssociativeENodeType[ECOND] = 0;
IsAssociativeENodeType[EFUNCCALL] = 0;
IsAssociativeENodeType[EFUNCCALLP] = 0;
IsAssociativeENodeType[EOBJREF] = 0;
IsAssociativeENodeType[EMFPOINTER] = 0;
IsAssociativeENodeType[ENULLCHECK] = 0;
IsAssociativeENodeType[EPRECOMP] = 0;
IsAssociativeENodeType[ETEMP] = 0;
IsAssociativeENodeType[EARGOBJ] = 0;
IsAssociativeENodeType[ELOCOBJ] = 0;
IsAssociativeENodeType[ELABEL] = 0;
IsAssociativeENodeType[ESETCONST] = 0;
IsAssociativeENodeType[ENEWEXCEPTION] = 0;
IsAssociativeENodeType[ENEWEXCEPTIONARRAY] = 0;
IsAssociativeENodeType[EOBJLIST] = 0;
IsAssociativeENodeType[EMEMBER] = 0;
IsAssociativeENodeType[ETEMPLDEP] = 0;
IsAssociativeENodeType[EINSTRUCTION] = 0;
IsAssociativeENodeType[EDEFINE] = 0;
IsAssociativeENodeType[EREUSE] = 0;
IsAssociativeENodeType[EASSBLK] = 0;
IsAssociativeENodeType[EVECTOR128CONST] = 0;
IsAssociativeENodeType[ECONDASS] = 0;
}
void IRO_TruncateValueToType(CInt64 *val, Type *type) {
if (IRO_IsUnsignedType(type)) {
switch (type->size) {
case 1:
CInt64_ConvertUInt8(val);
break;
case 2:
CInt64_ConvertUInt16(val);
break;
case 4:
CInt64_ConvertUInt32(val);
break;
}
} else {
switch (type->size) {
case 1:
CInt64_ConvertInt8(val);
break;
case 2:
CInt64_ConvertInt16(val);
break;
case 4:
CInt64_ConvertInt32(val);
break;
}
}
}
void IRO_TruncateBitfieldValueToType(CInt64 *val, Type *type, Type *type2) {
UInt32 limit;
UInt32 i;
UInt32 j;
CInt64 work;
work = cint64_zero;
limit = TYPE_BITFIELD(type2)->bitlength;
for (i = 0; i < limit; i++)
work = CInt64_Or(work, CInt64_Shl(cint64_one, IRO_MakeULong(i)));
*val = CInt64_And(*val, work);
if (!IRO_IsUnsignedType(type)) {
work = cint64_zero;
for (j = 0; j <= (i - 1); j++) {
if (j == (i - 1))
work = CInt64_Or(work, CInt64_Shl(cint64_one, IRO_MakeULong(j)));
}
if (CInt64_NotEqual(CInt64_And(work, *val), cint64_zero)) {
for (j = i - 1; j < 64; j++)
*val = CInt64_Or(*val, CInt64_Shl(cint64_one, IRO_MakeULong(j)));
}
}
IRO_TruncateValueToType(val, type);
}
void IRO_ConstantFolding(void) {
IROLinear *nd;
ENode *expr;
int isCompare;
int flag;
CInt64 val;
for (nd = IRO_FirstLinear; nd; nd = nd->next) {
switch (nd->type) {
case IROLinearOp1Arg:
if (IRO_IsIntConstant(nd->u.monadic)) {
expr = NULL;
flag = 0;
val = nd->u.monadic->u.node->data.intval;
if (nd->nodetype == ETYPCON && IS_TYPE_FLOAT(nd->rtype)) {
expr = IRO_NewENode(EFLOATCONST);
if (!IRO_IsUnsignedType(nd->u.monadic->rtype))
expr->data.floatval.value = CInt64_ConvertToLongDouble(&val);
else
expr->data.floatval.value = CInt64_ConvertUToLongDouble(&val);
expr->rtype = nd->rtype;
} else {
switch (nd->nodetype) {
case ETYPCON:
flag = 1;
break;
case ELOGNOT:
val = CInt64_Not(val);
flag = 1;
break;
case EBINNOT:
val = CInt64_Inv(val);
flag = 1;
break;
case EMONMIN:
val = CInt64_Neg(val);
flag = 1;
break;
}
if (flag) {
IRO_TruncateValueToType(&val, nd->rtype);
expr = IRO_NewENode(EINTCONST);
expr->rtype = nd->rtype;
expr->data.intval = val;
}
}
if (expr) {
nd->u.monadic->type = IROLinearNop;
nd->type = IROLinearOperand;
nd->u.node = expr;
}
}
break;
case IROLinearOp2Arg:
if (IRO_IsIntConstant(nd->u.diadic.left) && !IRO_IsIntConstant(nd->u.diadic.right) && IsAssociativeENodeType[nd->nodetype]) {
IROLinear *tmp = nd->u.diadic.right;
nd->u.diadic.right = nd->u.diadic.left;
nd->u.diadic.left = tmp;
}
if (IRO_IsIntConstant(nd->u.diadic.right) && nd->nodetype == ESUB) {
nd->nodetype = EADD;
if (IRO_IsIntConstant(nd->u.diadic.right)) {
CInt64 v;
v = CInt64_Neg(nd->u.diadic.right->u.node->data.intval);
nd->u.diadic.right->u.node->data.intval = v;
} else {
Float f;
f = CMach_CalcFloatMonadic(
nd->u.diadic.right->rtype,
'-',
nd->u.diadic.right->u.node->data.floatval);
nd->u.diadic.right->u.node->data.floatval = f;
}
}
if (
IRO_IsIntConstant(nd->u.diadic.right) &&
IsAssociativeENodeType[nd->nodetype] &&
nd->u.diadic.left->type == IROLinearOp2Arg &&
nd->u.diadic.left->nodetype == nd->nodetype &&
nd->u.diadic.left->rtype == nd->rtype &&
IRO_IsIntConstant(nd->u.diadic.left->u.diadic.right) &&
nd->u.diadic.left->u.diadic.right->rtype == nd->u.diadic.right->rtype
)
{
IROLinear *tmp = nd->u.diadic.left;
nd->u.diadic.left = tmp->u.diadic.left;
tmp->u.diadic.left = tmp->u.diadic.right;
tmp->u.diadic.right = nd->u.diadic.right;
tmp->rtype = tmp->u.diadic.left->rtype;
nd->u.diadic.right = tmp;
nd = tmp;
}
if (IRO_IsIntConstant(nd->u.diadic.left) && IRO_IsIntConstant(nd->u.diadic.right)) {
CInt64 val1 = nd->u.diadic.left->u.node->data.intval;
CInt64 val2 = nd->u.diadic.right->u.node->data.intval;
flag = 0;
switch (nd->nodetype) {
case EADD:
val = CInt64_Add(val1, val2);
flag = 1;
break;
case ESUB:
val = CInt64_Sub(val1, val2);
flag = 1;
break;
case EMUL:
if (IRO_IsUnsignedType(nd->rtype))
val = CInt64_MulU(val1, val2);
else
val = CInt64_Mul(val1, val2);
flag = 1;
break;
case EDIV:
if (!CInt64_IsZero(&val2)) {
if (IRO_IsUnsignedType(nd->rtype))
val = CInt64_DivU(val1, val2);
else
val = CInt64_Div(val1, val2);
flag = 1;
}
break;
case EMODULO:
if (!CInt64_IsZero(&val2)) {
if (IRO_IsUnsignedType(nd->rtype))
val = CInt64_ModU(val1, val2);
else
val = CInt64_Mod(val1, val2);
flag = 1;
}
break;
case ESHL:
val = CInt64_Shl(val1, val2);
flag = 1;
break;
case ESHR:
if (IRO_IsUnsignedType(nd->rtype))
val = CInt64_ShrU(val1, val2);
else
val = CInt64_Shr(val1, val2);
flag = 1;
break;
case EAND:
val = CInt64_And(val1, val2);
flag = 1;
break;
case EOR:
val = CInt64_Or(val1, val2);
flag = 1;
break;
case EXOR:
val = CInt64_Xor(val1, val2);
flag = 1;
break;
case ELESS:
if (IRO_IsUnsignedType(nd->u.diadic.left->rtype))
CInt64_SetULong(&val, CInt64_LessU(val1, val2));
else
CInt64_SetULong(&val, CInt64_Less(val1, val2));
flag = 1;
break;
case EGREATER:
if (IRO_IsUnsignedType(nd->u.diadic.left->rtype))
CInt64_SetULong(&val, CInt64_GreaterU(val1, val2));
else
CInt64_SetULong(&val, CInt64_Greater(val1, val2));
flag = 1;
break;
case ELESSEQU:
if (IRO_IsUnsignedType(nd->u.diadic.left->rtype))
CInt64_SetULong(&val, CInt64_LessEqualU(val1, val2));
else
CInt64_SetULong(&val, CInt64_LessEqual(val1, val2));
flag = 1;
break;
case EGREATEREQU:
if (IRO_IsUnsignedType(nd->u.diadic.left->rtype))
CInt64_SetULong(&val, CInt64_GreaterEqualU(val1, val2));
else
CInt64_SetULong(&val, CInt64_GreaterEqual(val1, val2));
flag = 1;
break;
case EEQU:
CInt64_SetULong(&val, CInt64_Equal(val1, val2));
flag = 1;
break;
case ENOTEQU:
CInt64_SetULong(&val, CInt64_NotEqual(val1, val2));
flag = 1;
break;
}
if (flag) {
IRO_TruncateValueToType(&val, nd->rtype);
expr = IRO_NewENode(EINTCONST);
expr->rtype = nd->rtype;
expr->data.intval = val;
nd->u.diadic.left->type = IROLinearNop;
nd->u.diadic.right->type = IROLinearNop;
nd->type = IROLinearOperand;
nd->u.node = expr;
}
}
if (IRO_IsFloatConstant(nd->u.diadic.left) && IRO_IsFloatConstant(nd->u.diadic.right)) {
Float fval1 = nd->u.diadic.left->u.node->data.floatval;
Float fval2 = nd->u.diadic.right->u.node->data.floatval;
Float fval;
flag = 0;
isCompare = 0;
switch (nd->nodetype) {
case EADD:
fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '+', fval2);
flag = 1;
break;
case ESUB:
fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '-', fval2);
flag = 1;
break;
case EMUL:
fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '*', fval2);
flag = 1;
break;
case EDIV:
fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '/', fval2);
flag = 1;
break;
case ELESS:
CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, '<', fval2));
flag = 1;
isCompare = 1;
break;
case EGREATER:
CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, '>', fval2));
flag = 1;
isCompare = 1;
break;
case ELESSEQU:
CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_LESS_EQUAL, fval2));
flag = 1;
isCompare = 1;
break;
case EGREATEREQU:
CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_GREATER_EQUAL, fval2));
flag = 1;
isCompare = 1;
break;
case EEQU:
CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_LOGICAL_EQ, fval2));
flag = 1;
isCompare = 1;
break;
case ENOTEQU:
CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_LOGICAL_NE, fval2));
flag = 1;
isCompare = 1;
break;
}
if (flag) {
if (isCompare) {
IRO_TruncateValueToType(&val, nd->rtype);
expr = IRO_NewENode(EINTCONST);
expr->rtype = nd->rtype;
expr->data.intval = val;
nd->u.diadic.left->type = IROLinearNop;
nd->u.diadic.right->type = IROLinearNop;
nd->type = IROLinearOperand;
nd->u.node = expr;
} else {
expr = IRO_NewENode(EFLOATCONST);
expr->rtype = nd->rtype;
expr->data.floatval = fval;
nd->u.diadic.left->type = IROLinearNop;
nd->u.diadic.right->type = IROLinearNop;
nd->type = IROLinearOperand;
nd->u.node = expr;
}
}
}
break;
}
}
IRO_CheckForUserBreak();
}
Boolean IRO_EvaluateConditionals(void) {
IRONode *fnode;
IROLinear *nd;
Boolean changed = 0;
SwitchInfo *switchInfo;
SwitchCase *swcase;
char found;
CInt64 val;
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
nd = fnode->last;
switch (nd->type) {
case IROLinearIf:
case IROLinearIfNot:
if (IRO_IsIntConstant(nd->u.label.x4)) {
Boolean isZero = CInt64_IsZero(&nd->u.label.x4->u.node->data.intval);
IRO_NopOut(nd->u.label.x4);
if ((isZero == 0) == (nd->type == IROLinearIf))
nd->type = IROLinearGoto;
else
nd->type = IROLinearNop;
changed = 1;
}
break;
case IROLinearSwitch:
if (IRO_IsIntConstant(nd->u.swtch.x4)) {
val = nd->u.swtch.x4->u.node->data.intval;
switchInfo = nd->u.swtch.info;
swcase = switchInfo->cases;
IRO_NopOut(nd->u.swtch.x4);
nd->type = IROLinearGoto;
found = 0;
while (swcase) {
if (CInt64_GreaterEqual(val, swcase->min) && CInt64_LessEqual(val, swcase->max)) {
found = 1;
nd->u.label.label = swcase->label;
break;
}
swcase = swcase->next;
}
if (!found)
nd->u.label.label = switchInfo->defaultlabel;
changed = 1;
}
break;
}
}
if (changed) {
IRO_ComputeSuccPred();
IRO_ComputeDom();
}
IRO_CheckForUserBreak();
return changed;
}
static int EEquConst(IROLinear *nd) {
return nd && (nd->nodetype == EEQU) && IRO_IsIntConstant(nd->u.diadic.right);
}
static Object *VEquConst(IROLinear *nd) {
if (EEquConst(nd))
return IRO_IsVariable(nd->u.diadic.left);
else
return NULL;
}
static int IsConsecutive(CInt64 a, CInt64 b) {
CInt64 diff;
if (!CInt64_Equal(a, cint64_min) && !CInt64_Equal(b, cint64_min)) {
diff = CInt64_Sub(b, a);
return CInt64_Equal(diff, cint64_one) || CInt64_Equal(diff, cint64_negone);
}
return 0;
}
static IROLinear *findLabel(CLabel *label) {
IROLinear *nd;
for (nd = IRO_FirstLinear; nd; nd = nd->next) {
if (nd->type == IROLinearLabel && nd->u.label.label == label)
break;
}
return nd;
}
static IROLinear *leftLeaveOf(IROLinear *nd) {
switch (nd->type) {
case IROLinearOp1Arg:
return leftLeaveOf(nd->u.monadic);
case IROLinearOp2Arg:
return leftLeaveOf(nd->u.diadic.left);
case IROLinearOperand:
return nd;
default:
return NULL;
}
}
static int checkNode(IRONode *fnode) {
IROLinear *nd;
if (fnode->numpred <= 1) {
nd = fnode->first;
while (nd != fnode->last && (nd->type == IROLinearNop || nd->type == IROLinearLabel))
nd = nd->next;
if (nd == leftLeaveOf(fnode->last->u.label.x4))
return 1;
}
return 0;
}
static int checkLabel(CLabel *label, IRONode *fnode) {
switch (fnode->last->type) {
case IROLinearIf:
if (label == fnode->last->u.label.label)
return 1;
break;
}
return 0;
}
static Object *checkExpr(Object *a, IROLinear *nd) {
Object *b = VEquConst(nd);
if ((!a || a == b) && !IRO_HasSideEffect(nd))
return b;
return NULL;
}
static int checkStruct(IRONode *fnode1, IRONode *fnode2) {
CLabel *label;
Object *var;
if (fnode1 == fnode2)
return (int) checkExpr(NULL, fnode1->last->u.label.x4);
label = fnode1->last->u.label.label;
var = IRO_IsVariable(fnode1->last->u.label.x4->u.monadic);
return checkNode(fnode2) && checkLabel(label, fnode2) && checkExpr(var, fnode2->last->u.label.x4);
}
typedef struct ReduceInfo {
int x0;
int x4;
Object *x8;
IRONode *fnode;
struct ReduceInfo *next;
CInt64 val;
} ReduceInfo;
static int MarkPattern1(ReduceInfo *info1, ReduceInfo *info2, CInt64 *val) {
ReduceInfo *scan;
if (!info2)
return 0;
if (info2->x0)
return MarkPattern1(info1, info2->next, val);
for (scan = info1; scan; scan = scan->next) {
if (scan->x0 == 2) {
if (CInt64_Equal(info2->val, scan->val)) {
IRO_NopOut(scan->fnode->last);
IRO_NopOut(scan->fnode->last->u.label.x4); // right union?
scan->x0 = -1;
return MarkPattern1(info1, info2->next, val);
}
if (IsConsecutive(info2->val, scan->val)) {
info2->x0 = 2;
if (CInt64_Greater(*val, scan->val))
*val = scan->val;
if (CInt64_Greater(*val, info2->val))
*val = info2->val;
MarkPattern1(scan->next, info2, val);
MarkPattern1(info1, info1->next, val);
return 1;
}
}
}
return MarkPattern1(info1, info2->next, val);
}
static int DoReducible1(ReduceInfo *info, CInt64 val) {
ReduceInfo *last;
ReduceInfo *scan;
IROLinear *right;
IROLinear *left;
IROLinear *typconRight;
IROLinear *typconLeft;
IROLinear *cond;
int count;
count = 0;
for (scan = info; scan; scan = scan->next) {
if (scan->x0 == 2) {
last = scan;
count++;
}
}
if (!count)
return 0;
for (scan = info; scan != last; scan = scan->next) {
if (scan->x0 == 2) {
scan->x0 = -1;
IRO_NopOut(scan->fnode->last);
IRO_NopOut(scan->fnode->last->u.label.x4);
}
}
last->x0 = -1;
cond = last->fnode->last;
cond->u.label.x4->nodetype = ELESSEQU;
CInt64_SetULong(&cond->u.label.x4->u.diadic.right->u.node->data.intval, count - 1);
typconLeft = IRO_NewLinear(IROLinearOp1Arg);
typconLeft->nodetype = ETYPCON;
typconLeft->rtype = IRO_UnsignedType(cond->u.label.x4->u.diadic.left->rtype);
typconLeft->index = ++IRO_NumLinear;
typconRight = IRO_NewLinear(IROLinearOp1Arg);
*typconRight = *typconLeft;
typconRight->index = ++IRO_NumLinear;
left = IRO_NewLinear(IROLinearOp2Arg);
left->nodetype = EADD;
left->rtype = cond->u.label.x4->u.diadic.left->rtype;
left->index = ++IRO_NumLinear;
right = IRO_NewLinear(IROLinearOperand);
right->nodetype = EINTCONST;
right->rtype = cond->u.label.x4->u.diadic.left->rtype;
right->index = ++IRO_NumLinear;
right->u.node = IRO_NewENode(EINTCONST);
right->u.node->data.intval = CInt64_Neg(val);
right->u.node->rtype = right->rtype;
typconLeft->next = cond->u.label.x4->u.diadic.left->next;
cond->u.label.x4->u.diadic.left->next = right;
right->next = left;
left->next = typconLeft;
typconRight->next = cond->u.label.x4->u.diadic.right->next;
cond->u.label.x4->u.diadic.right->next = typconRight;
typconLeft->u.monadic = left;
left->u.diadic.left = cond->u.label.x4->u.diadic.left;
left->u.diadic.right = right;
cond->u.label.x4->u.diadic.left = typconLeft;
typconRight->u.monadic = cond->u.label.x4->u.diadic.right;
cond->u.label.x4->u.diadic.right = typconRight;
return count;
};
static int ReducePattern1(IRONode *startnode, IRONode *endnode) {
ReduceInfo *infos;
ReduceInfo *info;
int changed = 0;
int count;
IRONode *fnode;
int i;
int j;
CInt64 val;
if (startnode == endnode)
return 0;
count = 0;
for (fnode = startnode; fnode != endnode; fnode = fnode->nextnode)
count++;
infos = oalloc(sizeof(ReduceInfo) * ++count);
fnode = startnode;
for (i = 0; i < count; i++) {
infos[i].x0 = 0;
infos[i].x4 = 0;
infos[i].fnode = fnode;
infos[i].next = NULL;
infos[i].x8 = VEquConst(fnode->last->u.label.x4);
if (infos[i].x8) {
infos[i].val = fnode->last->u.label.x4->u.diadic.right->u.node->data.intval;
infos[i].x4 = 1;
}
fnode = fnode->nextnode;
}
for (j = 0; j < count; j++) {
if (infos[j].x4 == 1 && infos[j].x8) {
infos[j].x4 = -1;
info = &infos[j];
for (i = j + 1; i < count; i++) {
if (infos[j].x8 == infos[i].x8) {
info->next = &infos[i];
info = &infos[i];
infos[i].x4 = 0;
}
}
}
}
for (j = 0; j < count; j++) {
if (infos[j].x4 == -1) {
for (info = &infos[j]; info; info = info->next) {
if (info->x0 == 0) {
info->x0 = 2;
val = info->val;
if (MarkPattern1(&infos[j], info->next, &val)) {
changed = 1;
DoReducible1(&infos[j], val);
} else {
info->x0 = -1;
}
}
}
}
}
return changed;
}
static int ReduceConsecutiveIf(IRONode *startnode, IRONode *endnode) {
IRONode *node31;
IRONode *node30;
int changed = 0;
while (startnode != endnode) {
if (checkStruct(startnode, startnode))
break;
startnode = startnode->nextnode;
}
node31 = startnode;
if (startnode != endnode) {
node30 = startnode;
node31 = startnode->nextnode;
while (node31 != endnode) {
if (checkStruct(startnode, node31)) {
node30 = node31;
node31 = node31->nextnode;
} else {
node31 = node30;
break;
}
}
if (node31 == endnode && !checkStruct(startnode, node31))
node31 = node30;
if (startnode != node31 && ReducePattern1(startnode, node31))
changed = 1;
if (node31 != endnode)
node31 = node31->nextnode;
}
if (node31 != endnode && ReduceConsecutiveIf(node31, endnode))
changed = 1;
return changed;
}
int IRO_SimplifyConditionals(void) {
IRONode *fnode;
IRONode *start;
IRONode *end;
int changed = 0;
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
if (fnode->last->type == IROLinearIf) {
start = end = fnode;
while (fnode->nextnode && fnode->nextnode->last->type == IROLinearIf) {
end = fnode = fnode->nextnode;
}
if (start != end && ReduceConsecutiveIf(start, end))
changed = 1;
}
}
if (changed) {
IRO_ComputeSuccPred();
IRO_ComputeDom();
}
IRO_CheckForUserBreak();
return changed;
}
Boolean IRO_EvaluateDefinitePointers(Object *func) {
IROLinear *nd;
Boolean result; // r29
Boolean changed; // r28
Boolean changed2; // r26
IROLinear *nd2; // r25
IROListNode *scan; // r25
IROListNode *list;
if (!copts.opt_pointer_analysis)
return 0;
result = 0;
do {
changed = 0;
for (nd = IRO_FirstLinear; nd; nd = nd->next) {
if (
nd->type == IROLinearOp1Arg &&
nd->nodetype == EINDIRECT &&
!(nd->flags & IROLF_Assigned) &&
nd->pointsToFunction &&
!IRO_HasSideEffect(nd) &&
PointerAnalysis_IsLinearNodePointerExprDefinite(func, nd)
)
{
list = NULL;
PointerAnalysis_LookupLinearNodePointerExpr(func, nd, &list);
if (list) {
if (list->list.head && list->list.tail && !list->nextList) {
changed2 = IRO_LocateFather_Cut_And_Paste(nd, list->list.tail) != NULL;
if (changed2) {
IRO_PasteAfter(list->list.head, list->list.tail, nd);
for (nd2 = list->list.head; nd2 != list->list.tail->next; nd2 = nd2->next) {
if (nd2->type == IROLinearOperand && nd2->u.node->type == EOBJREF) {
if (nd2->u.node->data.objref->datatype == DDATA || nd2->u.node->data.objref->datatype == DLOCAL)
IRO_FindVar(nd2->u.node->data.objref, 1, 1);
else
nd2->u.node->data.objref->varptr = NULL;
}
}
}
changed |= changed2;
}
while (list) {
scan = list->nextList;
IRO_free(list);
list = scan;
}
}
}
}
result |= changed;
IRO_CheckForUserBreak();
} while (changed);
return result;
}

View File

@@ -0,0 +1,14 @@
#ifndef COMPILER_IROEVAL_H
#define COMPILER_IROEVAL_H
#include "IrOptimizer.h"
extern void IRO_InitializeIsAssociativeENodeTypeArray(void);
extern void IRO_TruncateValueToType(CInt64 *val, Type *type);
extern void IRO_TruncateBitfieldValueToType(CInt64 *val, Type *type, Type *type2);
extern void IRO_ConstantFolding(void);
extern Boolean IRO_EvaluateConditionals(void);
extern int IRO_SimplifyConditionals(void);
extern Boolean IRO_EvaluateDefinitePointers(Object *func);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
#ifndef COMPILER_IROEXPRREGENERATION_H
#define COMPILER_IROEXPRREGENERATION_H
#include "IrOptimizer.h"
extern void IRO_RegenerateExpressions(void);
#endif

View File

@@ -0,0 +1,439 @@
#include "IroFlowgraph.h"
#include "IroCSE.h"
#include "IroLinearForm.h"
#include "IroPropagate.h"
#include "IROUseDef.h"
#include "IroUtil.h"
#include "compiler/CError.h"
#include "compiler/CFunc.h"
#include "compiler/CompilerTools.h"
#include "compiler/Exceptions.h"
#include "compiler/InlineAsmPPC.h"
UInt16 IRO_NumNodes;
IRONode *IRO_FirstNode;
IRONode *IRO_LastNode;
IRONode *IRO_EndNode;
IRONode **IRO_NodeTable;
BitVector *IRO_VarKills;
BitVector *IRO_Avail;
BitVector *IRO_FuncKills;
BitVector *IRO_ExprKills;
static IRONode *StartNode(IROLinear *linear) {
IRONode *node = oalloc(sizeof(IRONode));
node->index = IRO_NumNodes;
node->numsucc = 0;
node->succ = NULL;
node->numpred = 0;
node->pred = NULL;
node->first = linear;
node->last = linear;
node->x16 = NULL;
node->x1A = NULL;
node->x1E = NULL;
node->x22 = NULL;
node->x26 = 0;
node->x2A = NULL;
node->dom = NULL;
node->nextnode = NULL;
node->x36 = 0;
node->x37 = 0;
node->mustreach = 0;
node->x39 = 0;
node->loopdepth = 0;
node->x3C = 0;
node->addressed = NULL;
IRO_NumNodes++;
if (!IRO_FirstNode)
IRO_FirstNode = node;
else
IRO_LastNode->nextnode = node;
IRO_LastNode = node;
return node;
}
static void AddSucc(IRONode *a, IRONode *b) {
a->succ[a->numsucc++] = b->index;
b->numpred++;
}
static void AddLabelSucc(IRONode *node, CLabel *label) {
IRONode *targetnode = (IRONode *) label->stmt;
if (targetnode) {
AddSucc(node, targetnode);
targetnode->x39 = 1;
} else {
CError_FATAL(126);
}
}
static void AddSwitchSucc(IRONode *node) {
SwitchInfo *info = node->last->u.swtch.info;
SwitchCase *curcase = info->cases;
SInt32 i = 1;
while (curcase) {
curcase = curcase->next;
i++;
}
node->succ = oalloc(sizeof(UInt16) * i);
for (curcase = info->cases; curcase; curcase = curcase->next)
AddLabelSucc(node, curcase->label);
AddLabelSucc(node, info->defaultlabel);
}
static void AddPred(UInt32 a, UInt16 b) {
IRONode *node = IRO_NodeTable[a];
node->pred[node->numpred++] = b;
}
void IRO_ComputeSuccPred(void) {
CLabel *label;
IRONode *node;
SInt32 count;
IROLinear *linear;
ExceptionAction *action;
IAEffects effects;
UInt16 i;
for (label = Labels; label; label = label->next)
label->stmt = NULL;
for (node = IRO_FirstNode; node; node = node->nextnode) {
node->x39 = 0;
node->numsucc = 0;
node->numpred = 0;
node->x36 = 0;
node->x37 = 0;
if (node->first && node->first->type == IROLinearLabel)
node->first->u.label.label->stmt = (Statement *) node;
}
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (!node->first) {
if (node->nextnode) {
node->succ = oalloc(sizeof(UInt16));
AddSucc(node, node->nextnode);
}
} else {
linear = node->last;
next_linear:
switch (linear->type) {
case IROLinearReturn:
case IROLinearEnd:
break;
case IROLinearGoto:
node->succ = oalloc(sizeof(UInt16));
AddLabelSucc(node, linear->u.label.label);
break;
case IROLinearIf:
case IROLinearIfNot:
node->succ = oalloc(sizeof(UInt16) * 2);
AddSucc(node, node->nextnode);
AddLabelSucc(node, linear->u.label.label);
break;
case IROLinearSwitch:
AddSwitchSucc(node);
break;
case IROLinearFunccall:
count = 1;
if (IRO_FunctionCallMightThrowException(linear)) {
for (action = linear->stmt->dobjstack; action; action = action->prev) {
if (action->type == EAT_CATCHBLOCK || action->type == EAT_SPECIFICATION)
count++;
}
}
node->succ = oalloc(sizeof(UInt16) * count);
AddSucc(node, node->nextnode);
if (IRO_FunctionCallMightThrowException(linear)) {
for (action = linear->stmt->dobjstack; action; action = action->prev) {
if (action->type == EAT_CATCHBLOCK)
AddLabelSucc(node, action->data.catch_block.catch_label);
else if (action->type == EAT_SPECIFICATION)
AddLabelSucc(node, action->data.specification.unexp_label);
}
}
break;
case IROLinearAsm:
CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects);
node->succ = oalloc(sizeof(UInt16) * (!effects.x5 + effects.numlabels));
if (!effects.x5)
AddSucc(node, node->nextnode);
for (i = 0; i < effects.numlabels; i++)
AddLabelSucc(node, effects.labels[i]);
break;
case IROLinearOp2Arg:
if (linear->nodetype == ECOMMA) {
linear = linear->u.diadic.right;
goto next_linear;
}
default:
if (node->nextnode) {
node->succ = oalloc(sizeof(UInt16));
AddSucc(node, node->nextnode);
}
}
}
}
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (node->numpred)
node->pred = oalloc(sizeof(UInt16) * node->numpred);
else
node->pred = NULL;
node->numpred = 0;
}
for (node = IRO_FirstNode; node; node = node->nextnode) {
for (i = 0; i < node->numsucc; i++)
AddPred(node->succ[i], node->index);
}
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (node->first && node->first->type == IROLinearLabel) {
IROLinear *linear = node->first;
do {
if (linear->type == IROLinearBeginCatch || linear->type == IROLinearEndCatch || linear->type == IROLinearEndCatchDtor) {
node->x39 = 1;
break;
}
} while (linear != node->last && (linear = linear->next));
}
}
}
void IRO_ComputeDom(void) {
IRONode *node;
BitVector *bv;
SInt32 i;
int repeat;
Bv_AllocVector(&IRO_FirstNode->dom, IRO_NumNodes);
Bv_SetBit(IRO_FirstNode->index, IRO_FirstNode->dom);
for (node = IRO_FirstNode->nextnode; node; node = node->nextnode) {
Bv_AllocVector(&node->dom, IRO_NumNodes);
Bv_Set(node->dom);
}
Bv_AllocVector(&bv, IRO_NumNodes);
do {
repeat = 0;
for (node = IRO_FirstNode->nextnode; node; node = node->nextnode) {
if (node->numpred) {
Bv_Set(bv);
for (i = 0; i < node->numpred; i++) {
Bv_And(IRO_NodeTable[node->pred[i]]->dom, bv);
}
Bv_SetBit(node->index, bv);
} else {
Bv_Clear(bv);
Bv_SetBit(node->index, bv);
}
if (!Bv_Compare(bv, node->dom)) {
Bv_Copy(bv, node->dom);
repeat = 1;
}
}
} while (repeat);
}
void IRO_BuildFlowgraph(IROLinear *linear) {
IROLinear *scan;
CLabel *label;
ExceptionAction *action;
IAEffects effects;
IRONode *node;
SInt32 i;
int flag;
for (label = Labels; label; label = label->next)
label->stmt = NULL;
scan = linear;
IRO_NumNodes = 0;
IRO_FirstNode = IRO_LastNode = IRO_EndNode = NULL;
while (scan) {
StartNode(scan);
if (scan->type == IROLinearLabel)
scan->u.label.label->stmt = (Statement *) IRO_LastNode;
flag = 0;
while (!flag && scan->next && !(scan->next->flags & IROLF_1)) {
switch (scan->type) {
case IROLinearGoto:
case IROLinearReturn:
case IROLinearEntry:
case IROLinearExit:
case IROLinearEnd:
flag = 1;
break;
case IROLinearIf:
case IROLinearIfNot:
case IROLinearSwitch:
flag = 1;
skip:
if (scan->next->type == IROLinearLabel) {
IROLinear *nw = IRO_NewLinear(IROLinearNop);
nw->index = ++IRO_NumLinear;
nw->next = scan->next;
scan->next = nw;
}
break;
case IROLinearFunccall:
if (IRO_FunctionCallMightThrowException(scan)) {
for (action = scan->stmt->dobjstack; action; action = action->prev) {
if (action->type == EAT_CATCHBLOCK || action->type == EAT_SPECIFICATION) {
flag = 1;
goto skip;
}
}
}
break;
case IROLinearAsm:
CodeGen_GetAsmEffects(scan->u.asm_stmt, &effects);
if (effects.numlabels)
flag = 1;
break;
}
if (!flag)
scan = scan->next;
}
if (scan->type == IROLinearEnd)
IRO_EndNode = IRO_LastNode;
IRO_LastNode->last = scan;
scan = scan->next;
}
IRO_NodeTable = oalloc(IRO_NumNodes * sizeof(IRONode *));
memset(IRO_NodeTable, 0, IRO_NumNodes * sizeof(IRONode *));
for (node = IRO_FirstNode, i = 0; node; node = node->nextnode)
IRO_NodeTable[i++] = node;
IRO_ComputeSuccPred();
IRO_ComputeDom();
IRO_CheckForUserBreak();
}
IRONode *IRO_NewFlowGraphNode(void) {
IRONode *node = oalloc(sizeof(IRONode));
memset(node, 0, sizeof(IRONode));
node->index = IRO_NumNodes;
IRO_NumNodes++;
node->nextnode = NULL;
return node;
}
IRONode *IRO_MergeFlowGraphNodes(IRONode *a, IRONode *b) {
IRONode *succ;
Boolean found;
UInt32 i;
UInt32 j;
UInt32 k;
if (a->nextnode == b && a->last && b->first && a->last->next == b->first) {
if (b->first->type == IROLinearLabel)
IRO_NopOut(b->first);
a->nextnode = b->nextnode;
a->last = b->last;
for (i = 0; i < a->numsucc; i++) {
if (b->index == a->succ[i]) {
for (j = i; j < a->numsucc; j++) {
if ((j + 1) < a->numsucc)
a->succ[j] = a->succ[j + 1];
else
a->succ[j] = 0;
}
a->numsucc--;
break;
}
}
for (i = 0; i < b->numsucc; i++) {
succ = IRO_NodeTable[b->succ[i]];
for (j = 0; j < a->numsucc; j++) {
if (b->succ[i] == a->succ[j])
break;
}
if (j == a->numsucc) {
AddSucc(a, IRO_NodeTable[b->succ[i]]);
succ->numpred--;
}
found = 0;
for (j = 0; j < succ->numpred; j++) {
if (a->index == succ->pred[j]) {
found = 1;
break;
}
}
for (j = 0; j < succ->numpred; j++) {
if (b->index == succ->pred[j]) {
if (!found) {
succ->pred[j] = a->index;
} else {
for (k = j; k < succ->numpred; k++) {
if ((k + 1) < succ->numpred)
succ->pred[k] = succ->pred[k + 1];
else
succ->pred[k] = 0;
}
succ->numpred--;
}
break;
}
}
}
b->numsucc = b->numpred = 0;
b->first = b->last = NULL;
b->nextnode = NULL;
b->x36 = 0;
b->x37 = 0;
b->mustreach = 0;
b->x39 = 0;
b->loopdepth = 0;
if (IRO_LastNode == b)
IRO_LastNode = a;
if (IRO_FirstExpr && IRO_LastExpr) {
IROExpr *expr;
for (expr = IRO_FirstExpr; expr && expr != IRO_LastExpr->next; expr = expr->next) {
if (expr->node == b)
expr->node = a;
}
}
if (IRO_FirstAssign && IRO_LastAssign) {
IROAssign *assign;
for (assign = IRO_FirstAssign; assign && assign != IRO_LastAssign->next; assign = assign->next) {
if (assign->node == b)
assign->node = a;
}
}
if (IRO_FirstVarUse && IRO_LastVarUse) {
IROUse *use;
for (use = IRO_FirstVarUse; use && use != IRO_LastVarUse->globalnext; use = use->globalnext) {
if (use->node == b)
use->node = a;
}
}
IRO_NodeTable[b->index] = NULL;
return a;
}
return NULL;
}

View File

@@ -0,0 +1,97 @@
#ifndef COMPILER_IROFLOWGRAPH_H
#define COMPILER_IROFLOWGRAPH_H
#include "IrOptimizer.h"
#include "BitVector.h"
#include "compiler/CError.h"
#include "compiler/CompilerTools.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
struct IRONode {
UInt16 index;
UInt16 numsucc;
UInt16 *succ;
UInt16 numpred;
UInt16 *pred;
IROLinear *first;
IROLinear *last;
BitVector *x16; // In
BitVector *x1A; // Out
BitVector *x1E; // Gen
BitVector *x22; // Kill
UInt32 x26;
BitVector *x2A; // AA
BitVector *dom;
IRONode *nextnode;
Boolean x36;
Boolean x37;
Boolean mustreach;
Boolean x39;
UInt16 loopdepth;
Boolean x3C;
struct ObjectSet *addressed;
Boolean mustreach1;
};
typedef struct IRONodes {
UInt16 *indices;
UInt16 num;
UInt16 base;
} IRONodes;
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern UInt16 IRO_NumNodes;
extern IRONode *IRO_FirstNode;
extern IRONode *IRO_LastNode;
extern IRONode *IRO_EndNode;
extern IRONode **IRO_NodeTable;
extern BitVector *IRO_VarKills;
extern BitVector *IRO_Avail;
extern BitVector *IRO_FuncKills;
extern BitVector *IRO_ExprKills;
extern void IRO_ComputeSuccPred(void);
extern void IRO_ComputeDom(void);
extern void IRO_BuildFlowgraph(IROLinear *linear);
extern IRONode *IRO_NewFlowGraphNode(void);
extern IRONode *IRO_MergeFlowGraphNodes(IRONode *a, IRONode *b);
CW_INLINE void IROFlowgraph_sub_4C2140(IRONodes *nodes) {
nodes->indices = oalloc(sizeof(UInt16) * IRO_NumNodes);
nodes->num = 0;
nodes->base = 0;
}
CW_INLINE void IROFlowgraph_sub_4C20E0(IRONodes *nodes) {
}
CW_INLINE UInt16 IROFlowgraph_sub_4C2040(IRONodes *nodes) {
return nodes->num;
}
CW_INLINE UInt16 IROFlowgraph_sub_4C2100(IRONodes *nodes) {
UInt16 result = -1;
if (nodes->num) {
result = nodes->indices[nodes->base];
nodes->base = (nodes->base + 1) % IRO_NumNodes;
nodes->num--;
}
return result;
}
CW_INLINE void IROFlowgraph_sub_4C3880(IRONodes *nodes, UInt16 index) {
if (nodes->num < IRO_NumNodes) {
nodes->indices[(nodes->base + nodes->num) % IRO_NumNodes] = index;
nodes->num++;
} else {
CError_FATAL(93);
}
}
#endif

View File

@@ -0,0 +1,267 @@
#include "IroJump.h"
#include "IroDump.h"
#include "IroFlowgraph.h"
#include "IroLinearForm.h"
#include "IroUtil.h"
#include "compiler/CFunc.h"
#include "compiler/Exceptions.h"
static Boolean CheckChain(CLabel **labelptr) {
IRONode *node;
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (node->first && node->first->type == IROLinearLabel && node->first->u.label.label == *labelptr) {
IROLinear *linear;
CLabel *lab;
for (linear = node->first->next, lab = NULL; linear && (linear->type == IROLinearLabel || linear->type == IROLinearNop); linear = linear->next) {
if (linear->type == IROLinearLabel)
lab = linear->u.label.label;
}
if (linear->type == IROLinearGoto && *labelptr != linear->u.label.label) {
*labelptr = linear->u.label.label;
IRO_Dump("Chaining goto at %d\n", linear->index);
return 1;
}
if (lab && *labelptr != lab)
*labelptr = lab;
return 0;
}
}
return 0;
}
Boolean IRO_DoJumpChaining(void) {
IRONode *node;
IROLinear *linear;
Boolean flag;
SwitchInfo *info;
SwitchCase *curcase;
Boolean result;
result = 0;
do {
flag = 0;
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (node->first) {
linear = node->last;
switch (linear->type) {
case IROLinearGoto:
if (CheckChain(&linear->u.label.label))
flag = 1;
break;
case IROLinearIf:
case IROLinearIfNot:
if (CheckChain(&linear->u.label.label))
flag = 1;
break;
case IROLinearSwitch:
info = linear->u.swtch.info;
for (curcase = info->cases; curcase; curcase = curcase->next) {
if (CheckChain(&curcase->label))
flag = 1;
}
if (CheckChain(&info->defaultlabel))
flag = 1;
break;
}
}
}
result |= flag;
IRO_CheckForUserBreak();
} while (flag);
return result;
}
void IRO_MakeReachable(IRONode *node) {
UInt16 i;
Boolean flag;
node->x36 = 1;
do {
flag = 0;
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (node->x36 && !node->x37) {
for (i = 0; i < node->numsucc; i++) {
if (!IRO_NodeTable[node->succ[i]]->x36) {
flag = 1;
IRO_NodeTable[node->succ[i]]->x36 = 1;
}
}
node->x37 = 1;
}
}
} while (flag);
}
Boolean IRO_RemoveUnreachable(void) {
IRONode *node2;
IRONode *node1;
IROLinear *scan;
IROLinear *linear;
Boolean result;
ExceptionAction **actptr;
ExceptionAction *act;
result = 0;
IRO_ComputeSuccPred();
IRO_MakeReachable(IRO_FirstNode);
node1 = IRO_FirstNode;
for (node2 = IRO_FirstNode->nextnode; node2; node2 = node2->nextnode) {
if (node2->first && !node2->x36) {
IRO_Dump("Removing unreachable code at: %d\n", node2->index);
node1->nextnode = node2->nextnode;
node1->last->next = node2->last->next;
result = 1;
for (linear = node2->first; linear && linear->type == IROLinearLabel && linear != node2->last->next; linear = linear->next) {
for (scan = IRO_FirstLinear; scan; scan = scan->next) {
if (scan->stmt)
scan->stmt->marked = 0;
}
for (scan = IRO_FirstLinear; scan; scan = scan->next) {
if (scan->stmt && !scan->stmt->marked) {
scan->stmt->marked = 1;
for (actptr = &scan->stmt->dobjstack; (act = *actptr); actptr = &act->prev) {
if (
(act->type == EAT_CATCHBLOCK && act->data.catch_block.catch_label == linear->u.label.label) ||
(act->type == EAT_SPECIFICATION && act->data.specification.unexp_label == linear->u.label.label)) {
*actptr = act->prev;
}
}
}
}
}
if (node2 == IRO_LastNode)
IRO_LastNode = node1;
} else {
node1 = node2;
}
}
if (result) {
IRO_ComputeSuccPred();
IRO_ComputeDom();
}
IRO_CheckForUserBreak();
return result;
}
Boolean IRO_RemoveRedundantJumps(void) {
IRONode *node;
IROLinear *linear;
IROLinear *scan;
IROLinear *scan2;
SwitchInfo *info;
SwitchCase *curcase;
Boolean result;
result = 0;
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (node->first) {
linear = node->last;
switch (linear->type) {
case IROLinearGoto:
scan = linear->next;
while (scan && ((scan->type == IROLinearNop) || (scan->type == IROLinearLabel && scan->u.label.label != linear->u.label.label)))
scan = scan->next;
while (1) {
if (!scan) break;
if (scan->type != IROLinearLabel) break;
if (scan->u.label.label == linear->u.label.label) {
IRO_Dump("Removing goto next at %d\n", linear->index);
linear->type = IROLinearNop;
result = 1;
break;
}
scan = scan->next;
}
break;
case IROLinearIf:
case IROLinearIfNot:
scan = linear->next;
while (scan && scan->type == IROLinearNop)
scan = scan->next;
if (scan && scan->type == IROLinearGoto) {
scan2 = scan->next;
while (scan2 && ((scan2->type == IROLinearNop) || (scan2->type == IROLinearLabel && scan2->u.label.label != linear->u.label.label)))
scan2 = scan2->next;
if (scan2 && scan2->type == IROLinearLabel && scan2->u.label.label == linear->u.label.label) {
if (linear->type == IROLinearIf)
linear->type = IROLinearIfNot;
else
linear->type = IROLinearIf;
linear->u.label.label = scan->u.label.label;
scan->type = IROLinearNop;
IRO_Dump("Removing branch around goto at %d\n", linear->index);
result = 1;
}
}
scan2 = linear->next;
while (scan2 && ((scan2->type == IROLinearNop) || (scan2->type == IROLinearLabel && scan2->u.label.label != linear->u.label.label)))
scan2 = scan2->next;
while (1) {
if (!scan2) break;
if (scan2->type != IROLinearLabel) break;
if (scan2->u.label.label == linear->u.label.label) {
IRO_Dump("Removing If/IfNot_Goto next at %d\n", linear->index);
linear->type = IROLinearNop;
IRO_CheckSideEffect(linear->u.label.x4);
result = 1;
break;
}
scan2 = scan2->next;
}
break;
case IROLinearSwitch:
info = linear->u.swtch.info;
curcase = info->cases;
while (curcase && curcase->label == info->defaultlabel)
curcase = curcase->next;
if (!curcase) {
IRO_Dump("Removing Switch next at %d\n", linear->index);
IRO_CheckSideEffect(linear->u.swtch.x4);
linear->type = IROLinearGoto;
linear->u.label.label = info->defaultlabel;
result = 1;
}
break;
}
}
}
if (result) {
IRO_ComputeSuccPred();
IRO_ComputeDom();
}
IRO_CheckForUserBreak();
return result;
}
Boolean IRO_RemoveLabels(void) {
Boolean result;
IRONode *node;
result = 0;
IRO_ComputeSuccPred();
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (node->first && node->first->type == IROLinearLabel && !node->x39) {
node->first->type = IROLinearNop;
node->first->flags &= ~IROLF_1;
result = 1;
}
}
IRO_CheckForUserBreak();
return result;
}

View File

@@ -0,0 +1,12 @@
#ifndef COMPILER_IROJUMP_H
#define COMPILER_IROJUMP_H
#include "IrOptimizer.h"
extern Boolean IRO_DoJumpChaining(void);
extern void IRO_MakeReachable(IRONode *node);
extern Boolean IRO_RemoveUnreachable(void);
extern Boolean IRO_RemoveRedundantJumps(void);
extern Boolean IRO_RemoveLabels(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,165 @@
#ifndef COMPILER_IROLINEARFORM_H
#define COMPILER_IROLINEARFORM_H
#include "IrOptimizer.h"
#include "compiler/Switch.h"
#include "compiler/enode.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct IROLinearIRSave {
IROLinear *firstLinear;
IROLinear *lastLinear;
UInt32 numLinear;
Statement *curStat;
Boolean disableDueToAsm;
Boolean isLeafFunction;
Boolean functionHasReturn;
void *nullCheckList;
Statement *currStmt;
Statement *prevStmt;
} IROLinearIRSave;
typedef enum IROLinearType {
IROLinearNop,
IROLinearOperand,
IROLinearOp1Arg,
IROLinearOp2Arg,
IROLinearGoto,
IROLinearIf,
IROLinearIfNot,
IROLinearReturn,
IROLinearLabel,
IROLinearSwitch,
IROLinearOp3Arg,
IROLinearFunccall,
IROLinearEntry,
IROLinearExit,
IROLinearBeginCatch,
IROLinearEndCatch,
IROLinearEndCatchDtor,
IROLinearAsm,
IROLinear18,
IROLinear19,
IROLinearEnd
} IROLinearType;
enum {
IROLF_1 = 0x1,
IROLF_Reffed = 0x2,
IROLF_Assigned = 0x4,
IROLF_8 = 0x8,
IROLF_Used = 0x10,
IROLF_Ind = 0x20,
IROLF_Subs = 0x40,
IROLF_80 = 0x80,
IROLF_LoopInvariant = 0x100,
IROLF_BeginLoop = 0x200,
IROLF_EndLoop = 0x400,
IROLF_Ris = 0x800,
IROLF_Immind = 0x1000,
IROLF_VecOp = 0x2000,
IROLF_4000 = 0x4000,
IROLF_8000 = 0x8000,
IROLF_VecOpBase = 0x10000,
IROLF_20000 = 0x20000,
IROLF_CounterLoop = 0x40000,
IROLF_BitfieldIndirect = 0x80000,
IROLF_CouldError = 0x100000
};
// actual name is LinearNode as per mwccppc v8
struct IROLinear {
IROLinearType type;
ENodeType nodetype;
SInt32 flags;
UInt16 nodeflags;
unsigned short index;
Statement *stmt;
Type *rtype;
IROExpr *expr;
struct ERange *x16;
PointsToFunction *pointsToFunction;
Boolean x1E;
union {
struct {
void *data1;
void *data2;
void *data3;
void *data4;
void *data5;
} idk;
// Operand
ENode *node;
// Op1Arg
IROLinear *monadic;
// Op2Arg
struct {
IROLinear *left;
IROLinear *right;
} diadic;
// Op3Arg
struct {
IROLinear *a;
IROLinear *b;
IROLinear *c;
} args3;
// Funccall
struct {
char ispascal;
short argCount;
IROLinear **args;
IROLinear *linear8; // funcref
TypeFunc *functype;
struct LocationSetSet *returnedLocs;
} funccall;
// Asm
Statement *asm_stmt;
// If, IfNot, Goto, Label
struct {
CLabel *label;
IROLinear *x4; // if,ifnot only??
} label;
struct {
SwitchInfo *info;
IROLinear *x4;
} swtch;
// BeginCatch, EndCatch, EndCatchDtor
struct {
IROLinear *linear;
int x4;
int x8;
} ctch;
} u;
IROLinear *next;
};
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern IROLinear *IRO_FirstLinear;
extern IROLinear *IRO_LastLinear;
extern UInt32 IRO_NumLinear;
extern Statement *CurStat;
extern IROLinear *IRO_NewLinear(IROLinearType type);
extern void IRO_PreLinearize(Statement *stmt);
extern void IRO_Linearize(Statement *stmt);
extern ENode *IRO_NewENode(ENodeType nodetype);
extern Statement *IRO_Delinearize(IRONode *node, IROLinear *linear);
extern void IRO_RenumberInts(void);
extern void IRO_UpdateFlagsOnInts(void);
extern void IRO_SaveLinearIR(IROLinearIRSave *save);
extern void IRO_RestoreLinearIR(IROLinearIRSave *save);
#define IS_LINEAR_ENODE(_linear, _nodetype) ( ((_linear)->type == IROLinearOperand) && ((_linear)->u.node->type) == (_nodetype) )
#define IS_LINEAR_MONADIC(_linear, _nodetype) ( ((_linear)->type == IROLinearOp1Arg) && ((_linear)->nodetype) == (_nodetype) )
#define IS_LINEAR_MONADIC_2(_linear, _nodetype1, _nodetype2) ( ((_linear)->type == IROLinearOp1Arg) && (((_linear)->nodetype) == (_nodetype1) || ((_linear)->nodetype) == (_nodetype2)) )
#define IS_LINEAR_DIADIC(_linear, _nodetype) ( ((_linear)->type == IROLinearOp2Arg) && ((_linear)->nodetype) == (_nodetype) )
#define IS_LINEAR_DIADIC_2(_linear, _nodetype1, _nodetype2) ( ((_linear)->type == IROLinearOp2Arg) && (((_linear)->nodetype) == (_nodetype1) || ((_linear)->nodetype) == (_nodetype2)) )
#define IS_LINEAR_DIADIC_3(_linear, _nodetype1, _nodetype2, _nodetype3) ( ((_linear)->type == IROLinearOp2Arg) && (((_linear)->nodetype) == (_nodetype1) || ((_linear)->nodetype) == (_nodetype2) || ((_linear)->nodetype) == (_nodetype3)) )
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,111 @@
#ifndef COMPILER_IROLOOP_H
#define COMPILER_IROLOOP_H
#include "IrOptimizer.h"
#include "BitVector.h"
typedef enum IROLoopIndFlags {
LoopInd_HasMod = 1,
LoopInd_HasDiv = 2,
LoopInd_4 = 4,
LoopInd_8 = 8
} IROLoopIndFlags;
typedef enum IROLoopFlags {
LoopFlags_1 = 1, // LP_INDUCTION_AT_LEFT
LP_LOOP_HAS_CALLS = 2,
LP_LOOP_HAS_CNTRLFLOW = 4,
LoopFlags_8 = 8, // LP_HAS_NONASSIGN
LP_INDUCTION_NOT_FOUND = 0x10,
LP_IFEXPR_NON_CANONICAL = 0x20,
LP_HAS_MULTIPLE_INDUCTIONS = 0x40,
LP_LOOP_HDR_HAS_SIDEEFFECTS = 0x80,
LP_LOOP_STEP_ISADD = 0x100,
LoopFlags_200 = 0x200, // LP_HEADER_FOLLOWS_UPDATE?
LP_LOOP_STEP_ISPOS = 0x400,
LoopFlags_800 = 0x800, // LP_IND_USED_IN_LOOP
LoopFlags_1000 = 0x1000, // LP_HAS_MULTIPLE_EXITS
LoopFlags_2000 = 0x2000, // inverse of LP_LOOP_STEP_ISADD?
LP_LOOP_STEP_ISNEG = 0x4000,
LP_LOOP_HAS_ASM = 0x8000,
LoopFlags_10000 = 0x10000, // LP_WHILE_LOOP
LoopFlags_20000 = 0x20000, // maybe LP_RECURSIVE_LOOP?
LoopFlags_40000 = 0x40000 // LP_IS_REDUCTION_CAND
} IROLoopFlags;
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct IROLoopInd {
IROLoopIndFlags flags;
VarRecord *var;
IRONode *fnode;
IROLinear *nd;
SInt32 addConst;
IROLinear *addNode;
struct IROLoopInd *next;
} IROLoopInd;
struct IROLoop {
SInt32 flags;
IRONode *fnode;
int x8;
IRONode *xC;
IRONode *x10;
IROLinear *nd14; // assignment expression that sets the initial value of induction
IROLinear *nd18; // ifexpr?
IROLoopInd *induction;
int index20;
int index24;
CInt64 x28;
CInt64 x30;
int sizeBySomeMeasurement;
};
typedef enum IROLoopMemRefFlags {
LoopMemRef_1 = 1,
LoopMemRef_2 = 2,
LoopMemRef_4 = 4,
LoopMemRef_8 = 8,
LoopMemRef_10 = 0x10
} IROLoopMemRefFlags;
typedef struct IROLoopMemRef {
IROLoopMemRefFlags flags;
IROLinear *nd;
IROElmList *list;
IROAddrRecord *rec;
struct IROLoopMemRef *next;
} IROLoopMemRef;
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern IRONode *LoopNode;
extern Boolean ConditionalHeaderAtBottom;
extern IROLoopInd *FirstInd;
extern BitVector *InLoop;
extern IROList IRO_InitLList;
extern BitVector *InLoop_Exits;
extern BitVector *InLoop_Tails;
extern UInt32 LoopExitNumber;
extern UInt32 LoopTailNum;
extern IRONode *LoopExitSuccessor;
extern IRONode *LoopTail;
extern IROLoopMemRef *IRO_LoopMemRefFirst;
extern IROLoopMemRef *IRO_LoopMemRefCurrent;
extern void FindMustReach(void);
extern void FindMustReach1(IRONode *checkfnode);
extern void AddPreds(IRONode *fnode);
extern void IncLoopDepth(void);
extern void IRO_SetLoopDepth(void);
extern void IRO_FindLoops(void);
extern void ComputeLoopKills(void);
extern void ComputeLoopInvariance(void);
extern void ComputeLoopInduction(void);
extern void FindAssignmenttoInductionVar(IROLoop *loop, IRONode *fnode);
extern IROLoop *ExtractLoopInfo(IRONode *fnode);
extern CLabel *BuildLabel(IROList *list);
#endif

View File

@@ -0,0 +1,564 @@
#include "IroMalloc.h"
#include "compiler/CompilerTools.h"
#define FLAGMASK 0xF
typedef struct Block {
struct Block *prev;
struct Block *next;
void *x8;
void *xC;
size_t remain;
size_t x14;
} Block;
typedef struct SubBlockBase {
size_t x0;
Block *block;
} SubBlockBase;
typedef struct SubBlock {
size_t x0;
Block *block;
struct SubBlock *x8;
struct SubBlock *xC;
} SubBlock;
typedef struct SubBlockTail {
size_t x0copy;
} SubBlockTail;
typedef struct BlockTail {
size_t x14copy;
SubBlock *unk;
} BlockTail;
typedef struct FixStart {
struct FixBlock *a;
struct FixSubBlock *b;
long count;
} FixStart;
typedef struct FixBlock {
struct FixBlock *prev;
struct FixBlock *next;
size_t entrysize;
} FixBlock;
typedef struct FixSubBlockBase {
FixBlock *fixblock;
} FixSubBlockBase;
typedef struct FixSubBlock {
FixBlock *fixblock;
struct FixSubBlock *next;
} FixSubBlock;
static const size_t fix_pool_sizes[] = {0xC, 0x1C, 0x2C, 0x4C};
static Block *start_;
static FixStart fix_start[4];
static int initialized;
// forward decls
static void Block_link(Block *block, SubBlock *subblock);
static void Block_unlink(Block *block, SubBlock *subblock);
static void SubBlock_construct(SubBlock *subblock, size_t size, Block *block, int flag1, int flag2);
static SubBlock *SubBlock_split(SubBlock *subblock, size_t pos);
static SubBlock *SubBlock_merge_prev(SubBlock *subblock, SubBlock **sbptr);
static void SubBlock_merge_next(SubBlock *subblock, SubBlock **sbptr);
#define BLOCK_TAIL(block) ((BlockTail *) ((long) (block) + ((block)->x14 & ~FLAGMASK) - sizeof(BlockTail)))
#define BUF_LOCATOR(buf) (*((size_t *) ((long) (buf) - sizeof(size_t))))
#define SBB_BLOCK(sbb) ((Block *) ((long) ((sbb)->block) & ~1))
#define BUF_IS_VAR(buf) (BUF_LOCATOR(buf) & 1)
#define VARBUF_SBB(buf) ((SubBlockBase *) ((long) (buf) - sizeof(SubBlockBase)))
#define VARBUF_SB(buf) ((SubBlock *) ((long) (buf) - sizeof(SubBlockBase)))
#define VARBUF_BLOCKSIZE(buf) (VARBUF_SBB(buf)->x0 & ~FLAGMASK)
#define VARBUF_SIZE(buf) (((VARBUF_SBB(buf)->x0 & ~FLAGMASK) - sizeof(SubBlockBase)))
#define VARBUF_BLOCK(buf) SBB_BLOCK(VARBUF_SBB(buf))
#define FIXBUF_SIZE(buf) (((FixBlock *) BUF_LOCATOR(buf))->entrysize)
#define BUF_SIZE(buf) BUF_IS_VAR(buf) ? VARBUF_SIZE(buf) : FIXBUF_SIZE(buf)
static void Block_construct(Block *block, size_t size) {
SubBlock *subblock;
block->x14 = size | 3;
((BlockTail *) ((long) block + size - sizeof(BlockTail)))->x14copy = block->x14;
subblock = (SubBlock *) (block + 1);
SubBlock_construct(subblock, size - sizeof(Block) - sizeof(BlockTail), block, 0, 0);
block->remain = size - sizeof(Block) - sizeof(BlockTail);
BLOCK_TAIL(block)->unk = NULL;
Block_link(block, subblock);
}
static SubBlock *Block_subBlock(Block *block, size_t size) {
SubBlock *subblock;
size_t check;
size_t best;
if (!BLOCK_TAIL(block)->unk)
return NULL;
subblock = BLOCK_TAIL(block)->unk;
best = subblock->x0 & ~FLAGMASK;
check = subblock->x0 & ~FLAGMASK;
while (check < size) {
subblock = subblock->xC;
check = subblock->x0 & ~FLAGMASK;
if (best < check)
best = check;
if (subblock == BLOCK_TAIL(block)->unk) {
block->remain = best;
return NULL;
}
}
if ((check - size) >= 0x60)
SubBlock_split(subblock, size);
BLOCK_TAIL(block)->unk = subblock->xC;
Block_unlink(block, subblock);
return subblock;
}
static void Block_link(Block *block, SubBlock *subblock) {
size_t size;
SubBlock **sbptr;
size = subblock->x0 & ~FLAGMASK;
subblock->x0 &= ~2;
((SubBlock *) ((long) subblock + size))->x0 &= ~4;
((SubBlockTail *) ((long) subblock + size - sizeof(SubBlockTail)))->x0copy = size;
sbptr = &BLOCK_TAIL(block)->unk;
if (*sbptr) {
subblock->x8 = (*sbptr)->x8;
subblock->x8->xC = subblock;
subblock->xC = *sbptr;
(*sbptr)->x8 = subblock;
*sbptr = subblock;
*sbptr = SubBlock_merge_prev(*sbptr, sbptr);
SubBlock_merge_next(*sbptr, sbptr);
} else {
*sbptr = subblock;
subblock->x8 = subblock;
subblock->xC = subblock;
}
if (block->remain < ((*sbptr)->x0 & ~FLAGMASK))
block->remain = (*sbptr)->x0 & ~FLAGMASK;
}
static void Block_unlink(Block *block, SubBlock *subblock) {
size_t size;
SubBlock **sbptr;
size = subblock->x0 & ~FLAGMASK;
subblock->x0 |= 2;
((SubBlock *) ((long) subblock + size))->x0 |= 4;
sbptr = &BLOCK_TAIL(block)->unk;
if (*sbptr == subblock)
*sbptr = subblock->xC;
if (*sbptr == subblock) {
*sbptr = NULL;
block->remain = 0;
} else {
subblock->xC->x8 = subblock->x8;
subblock->x8->xC = subblock->xC;
}
}
static void SubBlock_construct(SubBlock *subblock, size_t size, Block *block, int flag1, int flag2) {
subblock->block = (Block *) ((long) block | 1);
subblock->x0 = size;
if (flag1)
subblock->x0 |= 4;
if (flag2) {
subblock->x0 |= 2;
((SubBlock *) (((long) subblock) + size))->x0 |= 4;
} else {
((SubBlockTail *) (((long) subblock) + size - sizeof(SubBlockTail)))->x0copy = size;
}
}
static SubBlock *SubBlock_split(SubBlock *subblock, size_t pos) {
size_t oldsize;
int flag;
SubBlock *splitright;
Block *block;
oldsize = subblock->x0 & ~FLAGMASK;
flag = !(subblock->x0 & 2);
splitright = (SubBlock *) ((long) subblock + pos);
block = (Block *) ((long) subblock->block & ~1);
SubBlock_construct(subblock, pos, block, subblock->x0 & 4, !flag);
SubBlock_construct(splitright, oldsize - pos, block, !flag, !flag);
if (flag) {
splitright->xC = subblock->xC;
splitright->xC->x8 = splitright;
splitright->x8 = subblock;
subblock->xC = splitright;
}
return splitright;
}
static SubBlock *SubBlock_merge_prev(SubBlock *subblock, SubBlock **sbptr) {
size_t prevsize;
SubBlock *prevblock;
if (!(subblock->x0 & 4)) {
prevsize = ((SubBlockTail *) ((long) subblock - sizeof(SubBlockTail)))->x0copy;
if (prevsize & 2)
return subblock;
prevblock = (SubBlock *) ((long) subblock - prevsize);
prevblock->x0 = prevblock->x0 & FLAGMASK;
prevblock->x0 |= (prevsize + (subblock->x0 & ~FLAGMASK)) & ~FLAGMASK;
if (!(prevblock->x0 & 2))
((SubBlockTail *) ((long) prevblock + prevsize + (subblock->x0 & ~FLAGMASK) - sizeof(SubBlockTail)))->x0copy = prevsize + (subblock->x0 & ~FLAGMASK);
if (*sbptr == subblock)
*sbptr = (*sbptr)->xC;
subblock->xC->x8 = subblock->x8;
subblock->xC->x8->xC = subblock->xC;
return prevblock;
}
return subblock;
}
static void SubBlock_merge_next(SubBlock *subblock, SubBlock **sbptr) {
SubBlock *nextblock;
size_t nextsize;
nextblock = (SubBlock *) ((long) subblock + (subblock->x0 & ~FLAGMASK));
if (!(nextblock->x0 & 2)) {
nextsize = (subblock->x0 & ~FLAGMASK) + (nextblock->x0 & ~FLAGMASK);
subblock->x0 = subblock->x0 & FLAGMASK;
subblock->x0 |= nextsize & ~FLAGMASK;
if (!(subblock->x0 & 2))
((SubBlockTail *) ((long) subblock + nextsize - sizeof(SubBlockTail)))->x0copy = nextsize;
if (!(subblock->x0 & 2))
((SubBlock *) ((long) subblock + nextsize))->x0 &= ~4;
else
((SubBlock *) ((long) subblock + nextsize))->x0 |= 4;
if (*sbptr == nextblock)
*sbptr = (*sbptr)->xC;
if (*sbptr == nextblock)
*sbptr = NULL;
nextblock->xC->x8 = nextblock->x8;
nextblock->x8->xC = nextblock->xC;
}
}
static void link_block(Block *block) {
if (start_) {
block->prev = start_->prev;
block->prev->next = block;
block->next = start_;
start_->prev = block;
start_ = block;
} else {
start_ = block;
block->prev = block;
block->next = block;
}
}
static Block *unlink_block(Block *block) {
Block *newblock;
newblock = block->next;
if (newblock == block)
newblock = NULL;
if (start_ == block)
start_ = newblock;
if (newblock) {
newblock->prev = block->prev;
newblock->prev->next = newblock;
}
block->prev = block->next = NULL;
return newblock;
}
static Block *link_new_block(size_t size) {
Block *block;
size = (size + 0x1000 + sizeof(Block) + sizeof(BlockTail) - 1) & ~0xFFF;
if (size < 0x10000)
size = 0x10000;
if (!(block = galloc(size)))
return NULL;
Block_construct(block, size);
link_block(block);
return block;
}
static void *allocate_from_var_pools(size_t size) {
Block *block;
SubBlock *subblock;
size = (size + sizeof(Block) - 1) & ~0xF;
if (size < 0x60)
size = 0x60;
block = start_ ? start_ : link_new_block(size);
if (!block)
return NULL;
do {
if (size <= block->remain) {
if ((subblock = Block_subBlock(block, size))) {
start_ = block;
goto allocated;
}
}
} while ((block = block->next) != start_);
block = link_new_block(size);
if (!block)
return NULL;
subblock = Block_subBlock(block, size);
allocated:
return (SubBlockBase *) subblock + 1;
}
static void deallocate_from_var_pools(void *buf) {
Block *block;
SubBlock *subblock;
int flag;
subblock = (SubBlock *) ((long) buf - sizeof(SubBlockBase));
block = (Block *) ((long) subblock->block & ~1);
Block_link(block, subblock);
flag = 0;
subblock = (SubBlock *) (block + 1);
if (!(subblock->x0 & 2)) {
if ((subblock->x0 & ~FLAGMASK) == ((block->x14 & ~FLAGMASK) - sizeof(Block) - sizeof(BlockTail)))
flag = 1;
}
if (flag)
unlink_block(block);
}
static void FixBlock_construct(FixBlock *fixblock, FixBlock *prev, FixBlock *next, int poolIndex, void *buffer, size_t buffersize) {
size_t entrysize;
size_t entrycount;
size_t i;
FixSubBlock *fsb;
FixSubBlock *fsbnext;
fixblock->prev = prev;
fixblock->next = next;
fixblock->entrysize = fix_pool_sizes[poolIndex];
entrysize = fix_pool_sizes[poolIndex] + sizeof(void *);
entrycount = (buffersize / entrysize);
fsb = buffer;
for (i = 0; i < (entrycount - 1); i++) {
fsbnext = (FixSubBlock *) ((long) fsb + entrysize);
fsb->fixblock = fixblock;
fsb->next = fsbnext;
fsb = fsbnext;
}
fsb->fixblock = fixblock;
fsb->next = fix_start[poolIndex].b;
fix_start[poolIndex].b = buffer;
}
static void *allocate_from_fixed_pools(size_t size) {
int poolIndex;
FixSubBlock *fsb;
poolIndex = 0;
while (size > fix_pool_sizes[poolIndex])
poolIndex++;
if (!fix_start[poolIndex].b) {
void *buf;
size_t bufsize;
buf = allocate_from_var_pools(4000);
if (!buf)
return NULL;
bufsize = !BUF_IS_VAR(buf) ? FIXBUF_SIZE(buf) : VARBUF_SIZE(buf);
FixBlock_construct(
buf, NULL, fix_start[poolIndex].a, poolIndex,
((FixBlock *) buf) + 1,
bufsize - sizeof(FixBlock)
);
fix_start[poolIndex].a = buf;
}
fsb = fix_start[poolIndex].b;
fix_start[poolIndex].b = fsb->next;
fix_start[poolIndex].count++;
return ((FixSubBlockBase *) fsb) + 1;
}
static void deallocate_from_fixed_pools(void *buf, size_t size) {
int poolIndex;
FixBlock *fixblock;
FixBlock *nextfb;
FixSubBlock *fsb;
poolIndex = 0;
while (size > fix_pool_sizes[poolIndex])
poolIndex++;
fsb = (FixSubBlock *) ((long) buf - sizeof(FixSubBlockBase));
fsb->next = fix_start[poolIndex].b;
fix_start[poolIndex].b = fsb;
if (--fix_start[poolIndex].count == 0) {
fixblock = fix_start[poolIndex].a;
while (fixblock) {
nextfb = fixblock->next;
deallocate_from_var_pools(fixblock);
fixblock = nextfb;
}
fix_start[poolIndex].a = NULL;
fix_start[poolIndex].b = NULL;
}
}
size_t IRO_msize(void *buf) {
return BUF_SIZE(buf);
}
void *IRO_malloc(size_t size) {
if (!size)
return NULL;
if (size <= 0x4C)
return allocate_from_fixed_pools(size);
else
return allocate_from_var_pools(size);
}
void IRO_free(void *buf) {
if (buf) {
size_t size = !BUF_IS_VAR(buf) ? FIXBUF_SIZE(buf) : VARBUF_SIZE(buf);
if (size <= 0x4C)
deallocate_from_fixed_pools(buf, size);
else
deallocate_from_var_pools(buf);
}
}
void *IRO_realloc(void *buf, size_t newsize) {
size_t oldsize;
size_t newblocksize;
void *newbuf;
if (!buf)
return IRO_malloc(newsize);
if (!newsize) {
IRO_free(buf);
return NULL;
}
oldsize = !BUF_IS_VAR(buf) ? FIXBUF_SIZE(buf) : VARBUF_SIZE(buf);
if (newsize > oldsize) {
if (BUF_IS_VAR(buf)) {
newblocksize = (newsize + sizeof(Block) - 1) & ~FLAGMASK;
if (newblocksize < 0x60)
newblocksize = 0x60;
SubBlock_merge_next(VARBUF_SB(buf), &BLOCK_TAIL(VARBUF_BLOCK(buf))->unk);
if (VARBUF_BLOCKSIZE(buf) >= newblocksize) {
if ((VARBUF_BLOCKSIZE(buf) - newblocksize) >= 0x60) {
Block_link(VARBUF_BLOCK(buf), SubBlock_split(VARBUF_SB(buf), newblocksize));
}
return buf;
}
}
newbuf = IRO_malloc(newsize);
if (!newbuf)
return NULL;
memcpy(newbuf, buf, oldsize);
IRO_free(buf);
return newbuf;
}
if (BUF_IS_VAR(buf)) {
newsize = (newsize + sizeof(Block) - 1) & ~FLAGMASK;
if (newsize < 0x60)
newsize = 0x60;
if ((VARBUF_BLOCKSIZE(buf) - newsize) >= 0x60) {
Block_link(VARBUF_BLOCK(buf), SubBlock_split(VARBUF_SB(buf), newsize));
}
}
return buf;
}
void *IRO_calloc(size_t a, size_t b) {
void *buf;
size_t len = b * a;
buf = IRO_malloc(len);
if (buf)
memset(buf, 0, len);
return buf;
}
void IRO_pool_free_all(void) {
int i;
Block *block;
if ((block = start_)) {
do {
block = block->next;
} while (block != start_);
start_ = NULL;
for (i = 0; i < 4; i++) {
fix_start[i].a = NULL;
fix_start[i].b = NULL;
fix_start[i].count = 0;
}
}
}
void IRO_InitializeAllocator(void) {
if (!initialized) {
int i;
for (i = 0; i < 4; i++) {
fix_start[i].a = NULL;
fix_start[i].b = NULL;
fix_start[i].count = 0;
}
start_ = NULL;
initialized = 1;
}
}
void IRO_TerminateAllocator(void) {
initialized = 0;
}

View File

@@ -0,0 +1,15 @@
#ifndef COMPILER_IROMALLOC_H
#define COMPILER_IROMALLOC_H
#include "IrOptimizer.h"
extern size_t IRO_msize(void *buf);
extern void *IRO_malloc(size_t size);
extern void IRO_free(void *buf);
extern void *IRO_realloc(void *buf, size_t newsize);
extern void *IRO_calloc(size_t a, size_t b);
extern void IRO_pool_free_all(void);
extern void IRO_InitializeAllocator(void);
extern void IRO_TerminateAllocator(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,25 @@
#ifndef COMPILER_IROPOINTERANALYSIS_H
#define COMPILER_IROPOINTERANALYSIS_H
#include "IrOptimizer.h"
extern void PointerAnalysis_Setup(void);
extern void PointerAnalysis_Cleanup(void);
extern void IRO_AnalyzePointers(Object *function);
extern Boolean PointerAnalysis_TwoLinearNodePointerExprsMightAlias(Object *proc, IROLinear *nd1, IROLinear *nd2);
extern Boolean PointerAnalysis_TwoENodePointerExprsMightAlias(Object *proc, ENode *nd1, ENode *nd2);
extern Boolean PointerAnalysis_IsLinearNodePointerExprDefinite(Object *proc, IROLinear *nd);
extern Boolean PointerAnalysis_IsENodePointerExprDefinite(Object *proc, ENode *nd);
extern Boolean PointerAnalysis_IsVariableValueDefinite(Object *proc, VarRecord *var, PointsToFunction *pointsTo);
extern void PointerAnalysis_LookupLinearNodePointerExpr(Object *proc, IROLinear *indirect, IROListNode **list);
extern void PointerAnalysis_LookupENodePointerExpr(Object *proc, ENode *indirect, ENodeList **list);
extern void PointerAnalysis_LookupVariableIntoLinearNodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, IROListNode **list);
extern void PointerAnalysis_LookupVariableIntoENodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, ENodeList **list);
extern void PointerAnalysis_GetFunctionKills(Object *proc, IROLinear *funccall, ObjectList **list);
extern void PointerAnalysis_GetFunctionDependencies(Object *proc, IROLinear *funccall, ObjectList **list);
extern void PointerAnalysis_PragmaMode(void);
extern void PointerAnalysis_ParseEntryPointsToSpecifier(DeclInfo *di);
extern void PointerAnalysis_ParseExitPointsToSpecifier(DeclInfo *di);
extern void PointerAnalysis_ParseFunctionModifiesSpecifier(DeclInfo *di);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,593 @@
#include "IroPropagate.h"
#include "IroCSE.h"
#include "IroDump.h"
#include "IroEval.h"
#include "IroFlowgraph.h"
#include "IroLinearForm.h"
#include "IROUseDef.h"
#include "IroUtil.h"
#include "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;
if (ass2->varObj)
enode = create_objectrefnode(ass2->varObj);
else if (ass2->linear2->type == IROLinearOperand)
enode = ass2->linear2->u.node;
else
CError_FATAL(768);
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_FirstAssign; 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();
}

View File

@@ -0,0 +1,35 @@
#ifndef COMPILER_IROPROPAGATE_H
#define COMPILER_IROPROPAGATE_H
#include "IrOptimizer.h"
#include "BitVector.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
struct IROAssign {
IROLinear *linear;
UInt16 index;
UInt16 varIndex;
IROLinear *linear2;
BitVector *depends;
Object *varObj;
VarRecord *var;
IROAssign *next;
IROAssign *prev;
UInt16 x20;
IRONode *node;
};
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern IROAssign *IRO_FirstAssign;
extern IROAssign *IRO_LastAssign;
extern SInt32 IRO_NumAssign;
extern int IRO_IsRegable(Object *obj);
extern Boolean IRO_CopyAndConstantPropagation(void);
extern void IRO_ExpressionPropagation(void);
#endif

View File

@@ -0,0 +1,774 @@
#include "IroRangePropagation.h"
#include "IroDump.h"
#include "IroFlowgraph.h"
#include "IroLinearForm.h"
#include "IroMalloc.h"
#include "IroPointerAnalysis.h"
#include "IroUtil.h"
#include "IroVars.h"
#include "compiler/CInt64.h"
#include "compiler/objects.h"
#include "compiler/types.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef enum ERangeType {
ERangeType0,
ERangeType1,
ERangeType2,
ERangeType3
} ERangeType;
typedef struct ERange {
ERangeType type;
CInt64 upper;
CInt64 lower;
} ERange;
typedef struct ERecord {
Object *object;
ERange *range;
struct ERecord *next;
} ERecord;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static ERecord *ERangeFirst;
static ERecord *ERangeLast;
static ERange *ERnewERange(ERangeType type) {
ERange *range;
range = oalloc(sizeof(ERange));
range->type = type;
return range;
}
static ERecord *ERnewRecord(Object *object, ERange *range) {
ERecord *record;
record = oalloc(sizeof(ERecord));
record->object = object;
record->range = range;
record->next = ERangeFirst;
ERangeFirst = record;
if (!ERangeLast)
ERangeLast = record;
return record;
}
static ERecord *ERecordFound(Object *obj) {
ERecord *scan;
scan = ERangeFirst;
while (scan && obj != scan->object)
scan = scan->next;
return scan;
}
static Boolean EREandHasNoUse(ERange *range, CInt64 val) {
UInt16 i;
CInt64 v11;
CInt64 work;
i = 0;
work = range->upper;
while (CInt64_NotEqual(work = CInt64_ShrU(work, cint64_one), cint64_zero))
i++;
if (CInt64_NotEqual(range->upper, cint64_zero))
i++;
CInt64_SetULong(&work, i);
v11 = CInt64_Sub(CInt64_Shl(cint64_one, work), cint64_one);
if (CInt64_NotEqual(cint64_zero, CInt64_And(CInt64_Inv(val), v11)))
return 0;
else
return 1;
}
static void ERcheckOverflow(ERange *range, Type *type) {
CInt64 typeSize;
CInt64 work;
CInt64 work2;
CInt64 value3;
if (!range)
return;
if (!IS_TYPE_INT(type)) {
range->type = ERangeType3;
return;
}
CInt64_SetLong(&typeSize, type->size);
CInt64_SetLong(&value3, 3);
if (IRO_IsUnsignedType(type)) {
if (type->size < 8) {
work = CInt64_Sub(CInt64_Shl(cint64_one, CInt64_Shl(typeSize, value3)), cint64_one);
if (CInt64_GreaterU(range->upper, work))
range->type = ERangeType3;
} else {
range->type = ERangeType3;
}
} else {
if (type->size < 8) {
work = CInt64_Sub(CInt64_Shl(cint64_one, CInt64_Sub(CInt64_Shl(typeSize, value3), cint64_one)), cint64_one);
work2 = CInt64_Shl(cint64_negone, CInt64_Sub(CInt64_Shl(typeSize, value3), cint64_one));
if (CInt64_Greater(range->upper, work) || CInt64_Less(range->lower, work2))
range->type = ERangeType3;
} else {
range->type = ERangeType3;
}
}
}
static void ERinvalidAll(void) {
ERecord *record;
for (record = ERangeFirst; record; record = record->next)
record->range->type = ERangeType3;
}
static void SetRangesForKillsByIndirectAssignment(IROLinear *nd) {
IROListNode *list;
IROListNode *scan;
IROLinear *inner;
Boolean failed;
IROListNode *resultList;
IROLinear *scannd;
Boolean foundObjRef;
ERecord *record;
ERange *range;
IROListNode *next;
Object *obj;
IROLinear *analysend;
Object *proc;
failed = 0;
if (nd->type == IROLinearOp2Arg)
inner = nd->u.diadic.left;
else
inner = nd->u.monadic;
if (
inner &&
inner->type == IROLinearOp1Arg &&
inner->nodetype == EINDIRECT &&
(analysend = inner->u.monadic) &&
copts.opt_pointer_analysis &&
analysend->pointsToFunction &&
(proc = FunctionName)
) {
resultList = NULL;
PointerAnalysis_LookupLinearNodePointerExpr(proc, analysend, &resultList);
if ((list = resultList)) {
for (scan = list; scan; scan = scan->nextList) {
if (!scan->list.head || !scan->list.tail) {
failed = 1;
break;
}
foundObjRef = 0;
for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) {
if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) {
foundObjRef = 1;
break;
}
}
if (!foundObjRef) {
failed = 1;
break;
}
}
if (!failed) {
for (; list; list = list->nextList) {
for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) {
if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) {
obj = scannd->u.node->data.objref;
CError_ASSERT(302, obj != NULL);
range = nd->x16;
if (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC)
range = inner->x16;
record = ERecordFound(obj);
if (!record)
ERnewRecord(obj, range);
else
record->range = range;
}
}
}
}
while (resultList) {
next = resultList->nextList;
IRO_free(resultList);
resultList = next;
}
} else {
failed = 1;
}
} else {
failed = 1;
}
if (failed) {
ERinvalidAll();
nd->x16 = ERnewERange(ERangeType3);
}
}
static void InvalidateRangesForKillsByFunctionCall(IROLinear *nd) {
IROListNode *scan;
IROLinear *scannd;
Boolean failed;
Boolean foundObjRef;
IROListNode *list;
IROListNode *resultList;
ERecord *record;
IROListNode *next;
Object *obj;
IROLinear *analysend;
Object *proc;
ObjectList *olist;
ObjectList *killList;
failed = 0;
if (
(analysend = nd->u.funccall.linear8) &&
copts.opt_pointer_analysis &&
analysend->pointsToFunction &&
(proc = FunctionName)
) {
resultList = NULL;
PointerAnalysis_LookupLinearNodePointerExpr(proc, analysend, &resultList);
if (resultList) {
for (scan = resultList; scan; scan = scan->nextList) {
if (!scan->list.head || !scan->list.tail) {
failed = 1;
break;
}
foundObjRef = 0;
for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) {
if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) {
foundObjRef = 1;
obj = scannd->u.node->data.objref;
CError_ASSERT(385, obj != NULL);
killList = NULL;
PointerAnalysis_GetFunctionKills(obj, nd, &killList);
for (olist = killList; olist; olist = olist->next) {
if (!olist->object) {
failed = 1;
break;
}
}
while (killList) {
olist = killList->next;
IRO_free(killList);
killList = olist;
}
if (failed)
break;
}
}
if (!foundObjRef)
failed = 1;
if (failed)
break;
}
if (!failed) {
for (list = resultList; list; list = list->nextList) {
for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) {
if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) {
obj = scannd->u.node->data.objref;
killList = NULL;
PointerAnalysis_GetFunctionKills(obj, nd, &killList);
for (olist = killList; olist; olist = olist->next) {
if ((record = ERecordFound(olist->object)))
record->range->type = ERangeType3;
}
while (killList) {
olist = killList->next;
IRO_free(killList);
killList = olist;
}
}
}
}
}
while (resultList) {
next = resultList->nextList;
IRO_free(resultList);
resultList = next;
}
} else {
failed = 1;
}
} else {
failed = 1;
}
if (failed)
ERinvalidAll();
}
static void ERfoldOperand(IROLinear *nd) {
switch (nd->u.node->type) {
case EOBJREF:
nd->x16 = NULL;
break;
case EINTCONST:
nd->x16 = ERnewERange(ERangeType0);
nd->x16->upper = nd->x16->lower = nd->u.node->data.intval;
break;
case EFLOATCONST:
case ESTRINGCONST:
nd->x16 = ERnewERange(ERangeType0);
break;
}
}
static Boolean ERfoldExpr(IROLinear *nd) {
ERecord *record;
ERange *range;
IROLinear *tmp;
IROLinear *inner;
Object *obj;
switch (nd->nodetype) {
case EINDIRECT:
inner = nd->u.monadic;
if (IS_TYPE_INT(nd->rtype)) {
if (inner->type == IROLinearOperand && inner->u.node->type == EOBJREF) {
if (!inner->x16 && (obj = inner->u.node->data.objref)) {
if ((record = ERecordFound(obj))) {
inner->x16 = ERnewERange(ERangeType3);
*inner->x16 = *record->range;
} else {
inner->x16 = ERnewERange(ERangeType3);
inner->x16->upper = cint64_max;
inner->x16->lower = cint64_min;
ERnewRecord(obj, inner->x16);
}
}
nd->x16 = inner->x16;
} else {
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
}
} else {
if (inner->type == IROLinearOperand && inner->u.node->type == EOBJREF && !inner->x16)
inner->x16 = ERnewERange(ERangeType3);
nd->x16 = ERnewERange(ERangeType3);
}
break;
case EAND:
case EANDASS:
if (IRO_IsIntConstant(nd->u.diadic.right)) {
CInt64 val = nd->u.diadic.right->u.node->data.intval;
nd->x16 = ERnewERange(ERangeType1);
nd->x16->upper = val;
nd->x16->lower = cint64_zero;
if (
(range = nd->u.diadic.left->x16) &&
range->type != ERangeType3 &&
CInt64_LessEqualU(range->upper, val) &&
CInt64_LessEqualU(range->lower, val) &&
EREandHasNoUse(range, val) &&
!IRO_HasSideEffect(nd->u.diadic.left)
) {
IRO_Dump("eliminating redundant EAND %" PRId32 "; upperBound==0x%x, lowerBound==0x%x, Constant==0x%x\n",
nd->index,
CInt64_GetULong(&range->upper),
CInt64_GetULong(&range->upper),
CInt64_GetULong(&val)
);
IRO_NopOut(nd->u.diadic.right);
nd->type = IROLinearNop;
nd->expr = NULL;
tmp = nd->u.diadic.left;
nd->u.diadic.left = nd->u.diadic.right;
if (!IRO_LocateFather_Cut_And_Paste(nd, tmp)) {
tmp->flags &= ~IROLF_Reffed;
if (IRO_IsVariable(tmp))
IRO_NopOut(tmp);
}
}
} else {
if (nd->u.diadic.right->x16) {
nd->x16 = ERnewERange(ERangeType3);
*nd->x16 = *nd->u.diadic.right->x16;
}
}
ERcheckOverflow(nd->x16, nd->rtype);
break;
case ELOGNOT:
case ELESS:
case EGREATER:
case ELESSEQU:
case EGREATEREQU:
case EEQU:
case ENOTEQU:
case ELAND:
case ELOR:
nd->x16 = ERnewERange(ERangeType1);
nd->x16->upper = cint64_one;
nd->x16->lower = cint64_zero;
ERcheckOverflow(nd->x16, nd->rtype);
break;
case EBINNOT:
case EFORCELOAD:
case EXOR:
case EOR:
case EXORASS:
case EORASS:
case ECOMMA:
case ETYPCON:
case EBITFIELD:
case ECOND:
case ENULLCHECK:
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
break;
case EASS:
if (IS_TYPE_INT(nd->rtype))
nd->x16 = nd->u.diadic.right->x16;
break;
case EMUL:
case EMULV:
case EMULASS:
if (IS_TYPE_INT(nd->rtype)) {
if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 &&
nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) {
nd->x16 = ERnewERange(ERangeType2);
if (IRO_IsUnsignedType(nd->rtype)) {
nd->x16->upper = CInt64_MulU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper);
nd->x16->lower = CInt64_MulU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower);
} else {
nd->x16->upper = CInt64_Mul(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper);
nd->x16->lower = CInt64_Mul(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower);
}
} else {
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
}
}
ERcheckOverflow(nd->x16, nd->rtype);
break;
case EDIV:
case EDIVASS:
if (IS_TYPE_INT(nd->rtype)) {
if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 &&
nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) {
nd->x16 = ERnewERange(ERangeType2);
if (!CInt64_IsZero(&nd->u.diadic.right->x16->lower) && !CInt64_IsZero(&nd->u.diadic.right->x16->upper)) {
if (IRO_IsUnsignedType(nd->rtype)) {
nd->x16->upper = CInt64_DivU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower);
nd->x16->lower = CInt64_DivU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper);
} else {
nd->x16->upper = CInt64_Div(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower);
nd->x16->lower = CInt64_Div(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper);
}
} else {
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
}
} else {
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
}
}
ERcheckOverflow(nd->x16, nd->rtype);
break;
case EMODULO:
case EMODASS:
if (IS_TYPE_INT(nd->rtype)) {
if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 &&
nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) {
nd->x16 = ERnewERange(ERangeType2);
if (!CInt64_IsZero(&nd->u.diadic.right->x16->lower) && !CInt64_IsZero(&nd->u.diadic.right->x16->upper)) {
if (IRO_IsUnsignedType(nd->rtype)) {
nd->x16->upper = CInt64_ModU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower);
nd->x16->lower = CInt64_ModU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper);
} else {
nd->x16->upper = CInt64_Mod(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower);
nd->x16->lower = CInt64_Mod(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper);
}
} else {
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
}
} else {
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
}
}
ERcheckOverflow(nd->x16, nd->rtype);
break;
case EADDV:
case EADD:
case EADDASS:
if (IS_TYPE_INT(nd->rtype)) {
if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 &&
nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) {
nd->x16 = ERnewERange(ERangeType2);
nd->x16->upper = CInt64_Add(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper);
nd->x16->lower = CInt64_Add(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower);
} else {
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
}
}
ERcheckOverflow(nd->x16, nd->rtype);
break;
case ESUBV:
case ESUB:
case ESUBASS:
if (IS_TYPE_INT(nd->rtype)) {
if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 &&
nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) {
nd->x16 = ERnewERange(ERangeType2);
nd->x16->upper = CInt64_Sub(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower);
nd->x16->lower = CInt64_Sub(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper);
} else {
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
}
}
ERcheckOverflow(nd->x16, nd->rtype);
break;
case ESHL:
case ESHLASS:
if (IS_TYPE_INT(nd->rtype)) {
if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 &&
nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) {
nd->x16 = ERnewERange(ERangeType2);
nd->x16->upper = CInt64_Shl(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper);
nd->x16->lower = CInt64_Shl(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower);
} else {
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
}
}
ERcheckOverflow(nd->x16, nd->rtype);
break;
case ESHR:
case ESHRASS:
if (IS_TYPE_INT(nd->rtype)) {
if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 &&
nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) {
nd->x16 = ERnewERange(ERangeType2);
if (IRO_IsUnsignedType(nd->rtype)) {
nd->x16->upper = CInt64_ShrU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower);
nd->x16->lower = CInt64_ShrU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper);
} else {
nd->x16->upper = CInt64_Shr(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower);
nd->x16->lower = CInt64_Shr(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper);
}
} else {
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
}
}
ERcheckOverflow(nd->x16, nd->rtype);
break;
case EPOSTINC:
if (IS_TYPE_INT(nd->rtype)) {
if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) {
nd->x16 = ERnewERange(ERangeType2);
range = nd->u.monadic->x16;
*nd->x16 = *range;
range->upper = CInt64_Add(range->upper, cint64_one);
range->lower = CInt64_Add(range->lower, cint64_one);
} else {
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
}
}
ERcheckOverflow(nd->x16, nd->rtype);
break;
case EPOSTDEC:
if (IS_TYPE_INT(nd->rtype)) {
if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) {
nd->x16 = ERnewERange(ERangeType2);
range = nd->u.monadic->x16;
*nd->x16 = *range;
range->upper = CInt64_Sub(range->upper, cint64_one);
range->lower = CInt64_Sub(range->lower, cint64_one);
} else {
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
}
}
ERcheckOverflow(nd->x16, nd->rtype);
break;
case EPREINC:
if (IS_TYPE_INT(nd->rtype)) {
if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) {
nd->x16 = ERnewERange(ERangeType2);
range = nd->u.monadic->x16;
nd->x16->upper = CInt64_Add(range->upper, cint64_one);
nd->x16->lower = CInt64_Add(range->lower, cint64_one);
} else {
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
}
}
ERcheckOverflow(nd->x16, nd->rtype);
break;
case EPREDEC:
if (IS_TYPE_INT(nd->rtype)) {
if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) {
nd->x16 = ERnewERange(ERangeType2);
range = nd->u.monadic->x16;
nd->x16->upper = CInt64_Sub(range->upper, cint64_one);
nd->x16->lower = CInt64_Sub(range->lower, cint64_one);
} else {
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
}
}
ERcheckOverflow(nd->x16, nd->rtype);
break;
case EMONMIN:
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
break;
case EPMODULO:
case EROTL:
case EROTR:
case EBCLR:
case EBTST:
case EBSET:
nd->x16 = ERnewERange(ERangeType3);
nd->x16->upper = cint64_max;
nd->x16->lower = cint64_min;
break;
default:
ERcheckOverflow(nd->x16, nd->rtype);
break;
}
if (
(nd->type == IROLinearOp1Arg || nd->type == IROLinearOp2Arg) &&
IRO_IsAssignOp[nd->nodetype] &&
nd->x16 &&
IS_TYPE_INT(nd->rtype)
) {
IROLinear *x = NULL;
if (nd->type == IROLinearOp2Arg)
x = nd->u.diadic.left;
else if (nd->type == IROLinearOp1Arg)
x = nd->u.monadic;
if (x->type == IROLinearOp1Arg &&
x->nodetype == EINDIRECT &&
(x->u.monadic->nodetype == EINDIRECT || x->u.monadic->nodetype == EADD)) {
SetRangesForKillsByIndirectAssignment(nd);
} else {
obj = NULL;
if (x)
obj = IRO_IsVariable(x);
if (!obj)
return 0;
range = nd->x16;
if (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC)
range = x->x16;
record = ERecordFound(obj);
if (!record)
ERnewRecord(obj, range);
else
record->range = range;
}
}
return nd->x16 != NULL;
}
static Boolean ERfoldLinear(IROLinear *nd) {
nd->x16 = 0;
switch (nd->type) {
case IROLinearNop:
case IROLinearEnd:
break;
case IROLinearOperand:
ERfoldOperand(nd);
break;
case IROLinearOp1Arg:
case IROLinearOp2Arg:
ERfoldExpr(nd);
break;
case IROLinearFunccall:
InvalidateRangesForKillsByFunctionCall(nd);
break;
case IROLinearAsm:
ERinvalidAll();
break;
}
return 0;
}
Boolean IRO_RangePropagateInFNode(void) {
IRONode *fnode;
IROLinear *nd;
Boolean result;
result = 0;
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
ERangeFirst = ERangeLast = NULL;
for (nd = fnode->first; nd != fnode->last; nd = nd->next)
ERfoldLinear(nd);
if (ERfoldLinear(nd))
result = 1;
}
if (result) {
IRO_ComputeSuccPred();
IRO_ComputeDom();
}
IRO_CheckForUserBreak();
return result;
}

View File

@@ -0,0 +1,8 @@
#ifndef COMPILER_IRORANGEPROPAGATION_H
#define COMPILER_IRORANGEPROPAGATION_H
#include "IrOptimizer.h"
extern Boolean IRO_RangePropagateInFNode(void);
#endif

View File

@@ -0,0 +1,160 @@
#include "IroSubable.h"
#include "IroLinearForm.h"
#include "IroPropagate.h"
#include "IroUtil.h"
#include "compiler/enode.h"
#include "compiler/objects.h"
#include "compiler/types.h"
static Boolean IsSubableOp[MAXEXPR];
void IRO_InitializeIsSubableOpArray(void) {
int i;
for (i = 0; i < MAXEXPR; i++)
IsSubableOp[i] = 0;
IsSubableOp[EPOSTINC] = 0;
IsSubableOp[EPOSTDEC] = 0;
IsSubableOp[EPREINC] = 0;
IsSubableOp[EPREDEC] = 0;
IsSubableOp[EINDIRECT] = 0;
IsSubableOp[EMONMIN] = 1;
IsSubableOp[EBINNOT] = 1;
IsSubableOp[ELOGNOT] = 1;
IsSubableOp[EFORCELOAD] = 0;
IsSubableOp[EMUL] = 1;
IsSubableOp[EMULV] = 1;
IsSubableOp[EDIV] = 1;
IsSubableOp[EMODULO] = 1;
IsSubableOp[EADDV] = 1;
IsSubableOp[ESUBV] = 1;
IsSubableOp[EADD] = 1;
IsSubableOp[ESUB] = 1;
IsSubableOp[ESHL] = 1;
IsSubableOp[ESHR] = 1;
IsSubableOp[ELESS] = 0;
IsSubableOp[EGREATER] = 0;
IsSubableOp[ELESSEQU] = 0;
IsSubableOp[EGREATEREQU] = 0;
IsSubableOp[EEQU] = 0;
IsSubableOp[ENOTEQU] = 0;
IsSubableOp[EAND] = 1;
IsSubableOp[EXOR] = 1;
IsSubableOp[EOR] = 1;
IsSubableOp[ELAND] = 0;
IsSubableOp[ELOR] = 0;
IsSubableOp[EASS] = 0;
IsSubableOp[EMULASS] = 0;
IsSubableOp[EDIVASS] = 0;
IsSubableOp[EMODASS] = 0;
IsSubableOp[EADDASS] = 0;
IsSubableOp[ESUBASS] = 0;
IsSubableOp[ESHLASS] = 0;
IsSubableOp[ESHRASS] = 0;
IsSubableOp[EANDASS] = 0;
IsSubableOp[EXORASS] = 0;
IsSubableOp[EORASS] = 0;
IsSubableOp[ECOMMA] = 0;
IsSubableOp[EPMODULO] = 0;
IsSubableOp[EROTL] = 0;
IsSubableOp[EROTR] = 0;
IsSubableOp[EBCLR] = 0;
IsSubableOp[EBTST] = 0;
IsSubableOp[EBSET] = 0;
IsSubableOp[ETYPCON] = 0;
IsSubableOp[EBITFIELD] = 0;
IsSubableOp[EINTCONST] = 0;
IsSubableOp[EFLOATCONST] = 0;
IsSubableOp[ESTRINGCONST] = 0;
IsSubableOp[ECOND] = 0;
IsSubableOp[EFUNCCALL] = 0;
IsSubableOp[EFUNCCALLP] = 0;
IsSubableOp[EOBJREF] = 0;
IsSubableOp[EMFPOINTER] = 0;
IsSubableOp[ENULLCHECK] = 0;
IsSubableOp[EPRECOMP] = 0;
IsSubableOp[ETEMP] = 0;
IsSubableOp[EARGOBJ] = 0;
IsSubableOp[ELOCOBJ] = 0;
IsSubableOp[ELABEL] = 0;
IsSubableOp[ESETCONST] = 0;
IsSubableOp[ENEWEXCEPTION] = 0;
IsSubableOp[ENEWEXCEPTIONARRAY] = 0;
IsSubableOp[EOBJLIST] = 0;
IsSubableOp[EMEMBER] = 0;
IsSubableOp[ETEMPLDEP] = 0;
IsSubableOp[EINSTRUCTION] = 0;
IsSubableOp[EDEFINE] = 0;
IsSubableOp[EREUSE] = 0;
IsSubableOp[EASSBLK] = 0;
IsSubableOp[EVECTOR128CONST] = 0;
IsSubableOp[ECONDASS] = 0;
}
static int IsSubscript(IROLinear *nd) {
return 0;
}
Boolean IRO_IsSubableExpression(IROLinear *nd) {
Object *varobj;
Boolean result;
switch (nd->type) {
case IROLinearOp2Arg:
if (nd->nodetype == EADD || nd->nodetype == ESUB) {
if (
IRO_IsConstant(nd->u.diadic.right) &&
(varobj = IRO_IsVariable(nd->u.diadic.left)) &&
varobj->datatype == DLOCAL &&
varobj->u.var.info &&
!varobj->u.var.info->noregister)
return 0;
}
result = IsSubableOp[nd->nodetype] && !IsSubscript(nd);
return result;
case IROLinearOp1Arg:
if (IsSubableOp[nd->nodetype] && !IsSubscript(nd))
return 1;
if (nd->nodetype == EINDIRECT && !(nd->flags & IROLF_Assigned)) {
if (nd->flags & IROLF_Ind) {
nd = nd->u.monadic;
if (nd->type == IROLinearOperand &&
nd->u.node->type == EOBJREF &&
nd->u.node->data.objref->datatype == DLOCAL &&
nd->u.node->data.objref->u.var.info &&
!nd->u.node->data.objref->u.var.info->noregister
)
return 0;
return 1;
}
if (IRO_IsVariable(nd) && IRO_IsRegable(nd->u.monadic->u.node->data.objref))
return 0;
return 1;
} else if (nd->nodetype == ETYPCON && IS_TYPE_INT(nd->rtype) && nd->rtype->size >= nd->u.monadic->rtype->size) {
return 1;
} else {
return 0;
}
case IROLinearOperand:
default:
return 0;
}
}
Boolean IRO_IsVectorTempCandidate(IROLinear *nd) {
return
(
nd->type == IROLinearOp1Arg ||
nd->type == IROLinearOp2Arg ||
nd->type == IROLinearOp3Arg ||
nd->type == IROLinearOperand ||
nd->type == IROLinearFunccall
) && (
(nd->flags & IROLF_LoopInvariant) &&
!(nd->flags & IROLF_Ind)
);
}

View File

@@ -0,0 +1,10 @@
#ifndef COMPILER_IROSUBABLE_H
#define COMPILER_IROSUBABLE_H
#include "IrOptimizer.h"
extern void IRO_InitializeIsSubableOpArray(void);
extern Boolean IRO_IsSubableExpression(IROLinear *nd);
extern Boolean IRO_IsVectorTempCandidate(IROLinear *nd);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
#ifndef COMPILER_IROTRANSFORM_H
#define COMPILER_IROTRANSFORM_H
#include "IrOptimizer.h"
extern void IRO_InitializeAssignmentOpArray(void);
extern void IRO_InitializeComplementaryOpArray(void);
extern void IRO_InitializeComplementaryOpLogicalArray(void);
extern void IRO_DoTransformations(void);
extern Boolean IRO_TransformSelfAssignmentToAssignment(IROLinear *nd);
extern void IRO_TransformTree(Statement *statements);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
#ifndef COMPILER_IROUNROLLLOOP_H
#define COMPILER_IROUNROLLLOOP_H
#include "IrOptimizer.h"
#include "IroLinearForm.h"
extern void IRO_LoopUnroller(void);
extern void IRO_IterateForLoopBody(IRONode *start, IRONode *end, IROLoop *loop, IROLinear *destnode, SInt32 addConst, CInt64 *val, Boolean funkyFlag);
extern void IRO_LinearizeForLoopPostLoop(IRONode *fnode1, IRONode *fnode2, IROLoop *loop, IRONode *fnode3, UInt32 unrollFactor);
extern IROLinear *BuildEarlyLoopExitTest(IROLinearType type, IROList *list);
extern IROLinear *BuildLoopExitTest(IROLinearType type, IROList *list);
extern int IsIterationCountConstant(IROLoop *loop, CInt64 *pval);
extern void NoOpBlock(IRONode *fnode);
extern void IRO_TestConstantIterationCount(IROLoop *loop, CInt64 *iterCount, SInt32 vectorStride, UInt32 *unrollFactor, SInt32 *leftOver, UInt32 *needOrigLoop, UInt32 *needUnrollBodyTest, UInt32 *resetUnrolledFinalValue);
extern IROLinear *BuildOrigIterationCount(IROList *list, IROLoop *loop);
extern IROLinear *BuildNewFinalvalue(IROLinear *iterCount, UInt32 unrollFactor, IROList *list, IROLoop *loop);
extern void BuildUnrolledBodyEntryTest(IROList *list, IROLinear *iterCount, UInt32 unrollFactor, CLabel *label);
extern void ChangeInductionReference(IROLinear *first, IROLinear *last, CInt64 val, IROLoop *loop);
extern IROLinear *UpdateInductionIncrement(IROLoop *loop, SInt32 value, IROLinear *before);
extern void GenInitialAssignment(IROLoop *loop, Object *var, IROList *list);
extern void GenNewInduction(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,127 @@
#ifndef COMPILER_IROUTIL_H
#define COMPILER_IROUTIL_H
#include "IrOptimizer.h"
#include "compiler/CInt64.h"
#include "compiler/CParser.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
struct IROList {
IROLinear *head;
IROLinear *tail;
};
struct IROListNode {
IROList list;
IROListNode *nextList;
};
struct IROElmList {
void *element;
IROElmList *next;
};
struct IROAddrRecord {
IROLinear *linear;
unsigned short numObjRefs;
IROElmList *objRefs;
unsigned short numMisc;
IROElmList *misc;
unsigned short numInts;
IROElmList *ints;
int x16;
};
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern Object *FunctionName;
extern Boolean IRO_IsLeafFunction;
extern Boolean IRO_FunctionHasReturn;
extern Boolean DisableDueToAsm;
extern Boolean LoopOptimizerRun;
extern Object *IRO_IsVariable(IROLinear *linear);
extern Boolean IRO_IsConstant(IROLinear *linear);
extern Boolean IRO_IsPow2(IROLinear *linear, SInt32 *powvalue);
extern Boolean IRO_IsIntConstant(IROLinear *linear);
extern Boolean IRO_IsFloatConstant(IROLinear *linear);
extern Boolean IRO_IsVector128Constant(IROLinear *linear);
extern Boolean IRO_IsAssignment(IROLinear *linear);
extern Boolean IRO_TypesEqual(Type *a, Type *b);
extern Type *IRO_UnsignedType(Type *type);
extern Type *IRO_SignedType(Type *type);
extern Boolean IRO_is_CPtypeequal(Type *a, Type *b);
extern Boolean IRO_ExprsSame(IROLinear *a, IROLinear *b);
extern CLabel *IRO_NewLabel(void);
extern Boolean IRO_ExprsSameSemantically(IROLinear *a, IROLinear *b);
extern IROLinear *IRO_FindPrecedAfter(IROLinear *a, IROLinear *iter);
extern IROLinear *IRO_FindPreced(IROLinear *a);
extern IROLinear *IRO_FindFirst(IROLinear *linear);
extern void IRO_CutAndPasteAfter(IROLinear *a, IROLinear *b, IROLinear *c);
extern Boolean IRO_IsConstantZero(IROLinear *linear);
extern Boolean IRO_IsConstantOne(IROLinear *linear);
extern Boolean IRO_IsConstantNegativeOne(IROLinear *linear);
extern void IRO_NopOut(IROLinear *linear);
extern void IRO_NopNonSideEffects(IROLinear *linear, SInt32 level);
extern void IRO_BuildList(IROLinear *linear, Boolean isEntry);
typedef void (*IROWalkTreeFunc)(IROLinear *linear, Boolean isEntry);
extern void IRO_WalkTree(IROLinear *linear, IROWalkTreeFunc func);
extern void IRO_WalkTreeToPropagateFlags(IROLinear *linear, IROWalkTreeFunc func);
extern void IRO_WalkInts(IROLinear *a, IROLinear *b, IROWalkTreeFunc func);
extern void IRO_Cut(IROLinear *a, IROLinear *b);
extern void IRO_Paste(IROLinear *a, IROLinear *b, IROLinear *c);
extern void IRO_PasteAfter(IROLinear *a, IROLinear *b, IROLinear *c);
extern void IRO_ClipExpr(IROExpr *expr);
extern void IRO_ClipExprTree(IROLinear *linear);
extern void IRO_MoveExpression(IROExpr *expr, IROLinear *linear);
extern void IRO_InitList(IROList *list);
extern void IRO_AddToList(IROLinear *linear, IROList *list);
extern IROLinear *IRO_FindLabelNode(CLabel *label, IROLinear *linear);
extern void IRO_DuplicateExprRange(IROLinear *start, IROLinear *end, IROList *list);
extern IROLinear *IRO_DuplicateExpr(IROLinear *linear, IROList *list);
extern IROLinear *IRO_TempReference(Object *obj, IROList *list);
extern IROLinear *IRO_LocateFather(IROLinear *linear);
extern IROLinear *IRO_LocateFather_Cut_And_Paste(IROLinear *a, IROLinear *b);
extern IROLinear *IRO_LocateFather_Cut_And_Paste_Without_Nopping(IROLinear *a, IROLinear *b);
extern void IRO_ReplaceReference(IROLinear *a, Object *obj, IROLinear *b);
extern void IRO_ReplaceReferenceWithNode(IROLinear *a, IROLinear *b);
extern VarRecord *IRO_GetTemp(IROExpr *expr);
extern IROLinear *IRO_AssignToTemp(IROExpr *expr);
extern IROLinear *IRO_FindStart(IROLinear *linear);
extern void IRO_DeleteCommaNode(IROLinear *linear, IROExpr *expr);
extern void IRO_RemoveCommaNodeFromIR(void);
extern IROAddrRecord *IRO_InitAddrRecordPointer(IROLinear *linear);
extern IROLinear *IRO_HasSideEffect(IROLinear *linear);
extern IROLinear *IRO_CheckSideEffect(IROLinear *linear);
typedef void (*WalkObjFunc)(Object *obj);
extern void IRO_WalkExcActions(ExceptionAction *action, WalkObjFunc func);
extern Boolean IRO_FunctionCallMightThrowException(IROLinear *linear);
extern IROLinear *IRO_NewIntConst(CInt64 val, Type *type);
extern IROLinear *IRO_NewFloatConst(const Float val, Type *type);
extern Boolean IRO_IsAddressMultiply(IROLinear *linear);
extern void IRO_SetupForUserBreakChecking(void);
extern void IRO_CheckForUserBreak(void);
// TODO is this elsewhere?
CW_INLINE Boolean IRO_IsUnsignedType(Type *type) {
return is_unsigned(type);
}
// 4B4D40
CW_INLINE CInt64 IRO_MakeULong(UInt32 i) {
CInt64 val;
CInt64_SetULong(&val, i);
return val;
}
// 4BAAA0
CW_INLINE CInt64 IRO_MakeLong(SInt32 i) {
CInt64 val;
CInt64_SetLong(&val, i);
return val;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
#ifndef COMPILER_IROVARS_H
#define COMPILER_IROVARS_H
#include "IrOptimizer.h"
#include "compiler/enode.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
struct VarRecord {
UInt16 index;
Object *object;
int x6;
Boolean xA;
Boolean xB;
Boolean xC;
VarRecord *next;
IRODef *defs;
IROUse *uses;
Type *x1A; // bitfield-related
IROLinear *x1E;
};
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern VarRecord *IRO_FirstVar;
extern VarRecord *IRO_LastVar;
extern SInt32 IRO_NumVars;
extern Boolean IRO_IsBitField;
extern SInt32 IRO_BaseTerms;
extern SInt32 IRO_VarTerms;
extern Boolean IRO_IsModifyOp[MAXEXPR];
extern Boolean IRO_IsAssignOp[MAXEXPR];
extern void IRO_InitializeIRO_IsModifyOpArray(void);
extern void IRO_InitializeIRO_IsAssignOpArray(void);
extern VarRecord *IRO_FindVar(Object *object, Boolean flag1, Boolean flag2);
extern void IRO_FindAllVars(void);
extern void IRO_ZapVarPtrs(void);
extern void IRO_UpdateVars(void);
extern void IRO_AddElmToList(IROLinear *linear, IROElmList **list);
extern void IRO_DecomposeAddressExpression(IROLinear *linear, IROAddrRecord *rec);
extern void IRO_DecomposeAddressExpression_Cheap(IROLinear *linear);
extern VarRecord *IRO_FindAssigned(IROLinear *linear);
extern void IRO_GetKills(IROLinear *linear);
extern void IRO_CheckInit(void);
extern void IRO_RewriteBitFieldTemps(void);
extern void IRO_ScalarizeClassDataMembers(void);
#endif