mirror of
https://git.wuffs.org/MWCC
synced 2025-12-20 02:15:45 +00:00
move lots of source files around to match their actual placement in the original tree
This commit is contained in:
36
compiler_and_linker/FrontEnd/Optimizer/BitVector.h
Normal file
36
compiler_and_linker/FrontEnd/Optimizer/BitVector.h
Normal 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
|
||||
1432
compiler_and_linker/FrontEnd/Optimizer/IROUseDef.c
Normal file
1432
compiler_and_linker/FrontEnd/Optimizer/IROUseDef.c
Normal file
File diff suppressed because it is too large
Load Diff
48
compiler_and_linker/FrontEnd/Optimizer/IROUseDef.h
Normal file
48
compiler_and_linker/FrontEnd/Optimizer/IROUseDef.h
Normal 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
|
||||
400
compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.c
Normal file
400
compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.c
Normal 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;
|
||||
}
|
||||
30
compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.h
Normal file
30
compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.h
Normal 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
|
||||
112
compiler_and_linker/FrontEnd/Optimizer/IroBitVect.c
Normal file
112
compiler_and_linker/FrontEnd/Optimizer/IroBitVect.c
Normal 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;
|
||||
}
|
||||
1038
compiler_and_linker/FrontEnd/Optimizer/IroCSE.c
Normal file
1038
compiler_and_linker/FrontEnd/Optimizer/IroCSE.c
Normal file
File diff suppressed because it is too large
Load Diff
45
compiler_and_linker/FrontEnd/Optimizer/IroCSE.h
Normal file
45
compiler_and_linker/FrontEnd/Optimizer/IroCSE.h
Normal 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
|
||||
660
compiler_and_linker/FrontEnd/Optimizer/IroDump.c
Normal file
660
compiler_and_linker/FrontEnd/Optimizer/IroDump.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
27
compiler_and_linker/FrontEnd/Optimizer/IroDump.h
Normal file
27
compiler_and_linker/FrontEnd/Optimizer/IroDump.h
Normal 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
|
||||
560
compiler_and_linker/FrontEnd/Optimizer/IroEmptyLoop.c
Normal file
560
compiler_and_linker/FrontEnd/Optimizer/IroEmptyLoop.c
Normal 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;
|
||||
}
|
||||
|
||||
8
compiler_and_linker/FrontEnd/Optimizer/IroEmptyLoop.h
Normal file
8
compiler_and_linker/FrontEnd/Optimizer/IroEmptyLoop.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef COMPILER_IROEMPTYLOOP_H
|
||||
#define COMPILER_IROEMPTYLOOP_H
|
||||
|
||||
#include "IrOptimizer.h"
|
||||
|
||||
extern void IRO_FindEmptyLoops(void);
|
||||
|
||||
#endif
|
||||
914
compiler_and_linker/FrontEnd/Optimizer/IroEval.c
Normal file
914
compiler_and_linker/FrontEnd/Optimizer/IroEval.c
Normal 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;
|
||||
}
|
||||
14
compiler_and_linker/FrontEnd/Optimizer/IroEval.h
Normal file
14
compiler_and_linker/FrontEnd/Optimizer/IroEval.h
Normal 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
|
||||
1531
compiler_and_linker/FrontEnd/Optimizer/IroExprRegeneration.c
Normal file
1531
compiler_and_linker/FrontEnd/Optimizer/IroExprRegeneration.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
#ifndef COMPILER_IROEXPRREGENERATION_H
|
||||
#define COMPILER_IROEXPRREGENERATION_H
|
||||
|
||||
#include "IrOptimizer.h"
|
||||
|
||||
extern void IRO_RegenerateExpressions(void);
|
||||
|
||||
#endif
|
||||
439
compiler_and_linker/FrontEnd/Optimizer/IroFlowgraph.c
Normal file
439
compiler_and_linker/FrontEnd/Optimizer/IroFlowgraph.c
Normal 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;
|
||||
}
|
||||
97
compiler_and_linker/FrontEnd/Optimizer/IroFlowgraph.h
Normal file
97
compiler_and_linker/FrontEnd/Optimizer/IroFlowgraph.h
Normal 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
|
||||
267
compiler_and_linker/FrontEnd/Optimizer/IroJump.c
Normal file
267
compiler_and_linker/FrontEnd/Optimizer/IroJump.c
Normal 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;
|
||||
}
|
||||
12
compiler_and_linker/FrontEnd/Optimizer/IroJump.h
Normal file
12
compiler_and_linker/FrontEnd/Optimizer/IroJump.h
Normal 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
|
||||
1797
compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c
Normal file
1797
compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c
Normal file
File diff suppressed because it is too large
Load Diff
165
compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.h
Normal file
165
compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.h
Normal 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
|
||||
2324
compiler_and_linker/FrontEnd/Optimizer/IroLoop.c
Normal file
2324
compiler_and_linker/FrontEnd/Optimizer/IroLoop.c
Normal file
File diff suppressed because it is too large
Load Diff
111
compiler_and_linker/FrontEnd/Optimizer/IroLoop.h
Normal file
111
compiler_and_linker/FrontEnd/Optimizer/IroLoop.h
Normal 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
|
||||
564
compiler_and_linker/FrontEnd/Optimizer/IroMalloc.c
Normal file
564
compiler_and_linker/FrontEnd/Optimizer/IroMalloc.c
Normal 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;
|
||||
}
|
||||
|
||||
15
compiler_and_linker/FrontEnd/Optimizer/IroMalloc.h
Normal file
15
compiler_and_linker/FrontEnd/Optimizer/IroMalloc.h
Normal 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
|
||||
5734
compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.c
Normal file
5734
compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.c
Normal file
File diff suppressed because it is too large
Load Diff
25
compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.h
Normal file
25
compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.h
Normal 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
|
||||
2736
compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysisADTs.c
Normal file
2736
compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysisADTs.c
Normal file
File diff suppressed because it is too large
Load Diff
593
compiler_and_linker/FrontEnd/Optimizer/IroPropagate.c
Normal file
593
compiler_and_linker/FrontEnd/Optimizer/IroPropagate.c
Normal 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();
|
||||
}
|
||||
|
||||
35
compiler_and_linker/FrontEnd/Optimizer/IroPropagate.h
Normal file
35
compiler_and_linker/FrontEnd/Optimizer/IroPropagate.h
Normal 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
|
||||
774
compiler_and_linker/FrontEnd/Optimizer/IroRangePropagation.c
Normal file
774
compiler_and_linker/FrontEnd/Optimizer/IroRangePropagation.c
Normal 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;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef COMPILER_IRORANGEPROPAGATION_H
|
||||
#define COMPILER_IRORANGEPROPAGATION_H
|
||||
|
||||
#include "IrOptimizer.h"
|
||||
|
||||
extern Boolean IRO_RangePropagateInFNode(void);
|
||||
|
||||
#endif
|
||||
160
compiler_and_linker/FrontEnd/Optimizer/IroSubable.c
Normal file
160
compiler_and_linker/FrontEnd/Optimizer/IroSubable.c
Normal 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)
|
||||
);
|
||||
}
|
||||
10
compiler_and_linker/FrontEnd/Optimizer/IroSubable.h
Normal file
10
compiler_and_linker/FrontEnd/Optimizer/IroSubable.h
Normal 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
|
||||
2794
compiler_and_linker/FrontEnd/Optimizer/IroTransform.c
Normal file
2794
compiler_and_linker/FrontEnd/Optimizer/IroTransform.c
Normal file
File diff suppressed because it is too large
Load Diff
13
compiler_and_linker/FrontEnd/Optimizer/IroTransform.h
Normal file
13
compiler_and_linker/FrontEnd/Optimizer/IroTransform.h
Normal 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
|
||||
2305
compiler_and_linker/FrontEnd/Optimizer/IroUnrollLoop.c
Normal file
2305
compiler_and_linker/FrontEnd/Optimizer/IroUnrollLoop.c
Normal file
File diff suppressed because it is too large
Load Diff
23
compiler_and_linker/FrontEnd/Optimizer/IroUnrollLoop.h
Normal file
23
compiler_and_linker/FrontEnd/Optimizer/IroUnrollLoop.h
Normal 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
|
||||
1262
compiler_and_linker/FrontEnd/Optimizer/IroUtil.c
Normal file
1262
compiler_and_linker/FrontEnd/Optimizer/IroUtil.c
Normal file
File diff suppressed because it is too large
Load Diff
127
compiler_and_linker/FrontEnd/Optimizer/IroUtil.h
Normal file
127
compiler_and_linker/FrontEnd/Optimizer/IroUtil.h
Normal 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
|
||||
1430
compiler_and_linker/FrontEnd/Optimizer/IroVars.c
Normal file
1430
compiler_and_linker/FrontEnd/Optimizer/IroVars.c
Normal file
File diff suppressed because it is too large
Load Diff
51
compiler_and_linker/FrontEnd/Optimizer/IroVars.h
Normal file
51
compiler_and_linker/FrontEnd/Optimizer/IroVars.h
Normal 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
|
||||
Reference in New Issue
Block a user