oscar64/oscar64/InterCode.cpp

3591 lines
82 KiB
C++

#include "InterCode.h"
#include "InterCode.h"
#include <stdio.h>
#include <math.h>
#include <crtdbg.h>
ValueSet::ValueSet(void)
{
mSize = 32;
mNum = 0;
mInstructions = new InterInstructionPtr[mSize];
}
ValueSet::ValueSet(const ValueSet& values)
{
int i;
mSize = values.mSize;
mNum = values.mNum;
mInstructions = new InterInstructionPtr[mSize];
for (i = 0; i < mNum; i++)
mInstructions[i] = values.mInstructions[i];
}
ValueSet::~ValueSet(void)
{
delete[] mInstructions;
}
void ValueSet::FlushAll(void)
{
mNum = 0;
}
void ValueSet::FlushCallAliases(void)
{
int i;
i = 0;
while (i < mNum)
{
if ((mInstructions[i]->mCode == IC_LOAD || mInstructions[i]->mCode == IC_STORE) && mInstructions[i]->mMemory != IM_PARAM && mInstructions[i]->mMemory != IM_LOCAL)
{
//
// potential alias load
//
mNum--;
if (i < mNum)
{
mInstructions[i] = mInstructions[mNum];
}
}
else
i++;
}
}
static __int64 ConstantFolding(InterOperator oper, __int64 val1, __int64 val2)
{
switch (oper)
{
case IA_ADD:
return val1 + val2;
break;
case IA_SUB:
return val1 - val2;
break;
case IA_MUL:
return val1 * val2;
break;
case IA_DIVU:
return (unsigned __int64)val1 / (unsigned __int64)val2;
break;
case IA_DIVS:
return val1 / val2;
break;
case IA_MODU:
return (unsigned __int64)val1 % (unsigned __int64)val2;
break;
case IA_MODS:
return val1 % val2;
break;
case IA_OR:
return val1 | val2;
break;
case IA_AND:
return val1 & val2;
break;
case IA_XOR:
return val1 ^ val2;
break;
case IA_NEG:
return -val1;
break;
case IA_NOT:
return ~val1;
break;
case IA_SHL:
return val1 << val2;
break;
case IA_SHR:
return (unsigned __int64)val1 >> (unsigned __int64)val2;
break;
case IA_SAR:
return val1 >> val2;
break;
case IA_CMPEQ:
return val1 == val2 ? 1 : 0;
break;
case IA_CMPNE:
return val1 != val2 ? 1 : 0;
break;
case IA_CMPGES:
return val1 >= val2 ? 1 : 0;
break;
case IA_CMPLES:
return val1 <= val2 ? 1 : 0;
break;
case IA_CMPGS:
return val1 > val2 ? 1 : 0;
break;
case IA_CMPLS:
return val1 < val2 ? 1 : 0;
break;
case IA_CMPGEU:
return (unsigned __int64)val1 >= (unsigned __int64)val2 ? 1 : 0;
break;
case IA_CMPLEU:
return (unsigned __int64)val1 <= (unsigned __int64)val2 ? 1 : 0;
break;
case IA_CMPGU:
return (unsigned __int64)val1 > (unsigned __int64)val2 ? 1 : 0;
break;
case IA_CMPLU:
return (unsigned __int64)val1 < (unsigned __int64)val2 ? 1 : 0;
break;
default:
return 0;
}
}
static __int64 ConstantRelationalFolding(InterOperator oper, double val1, double val2)
{
switch (oper)
{
case IA_CMPEQ:
return val1 == val2 ? 1 : 0;
break;
case IA_CMPNE:
return val1 != val2 ? 1 : 0;
break;
case IA_CMPGES:
case IA_CMPGEU:
return val1 >= val2 ? 1 : 0;
break;
case IA_CMPLES:
case IA_CMPLEU:
return val1 <= val2 ? 1 : 0;
break;
case IA_CMPGS:
case IA_CMPGU:
return val1 > val2 ? 1 : 0;
break;
case IA_CMPLS:
case IA_CMPLU:
return val1 < val2 ? 1 : 0;
break;
default:
return 0;
}
}
static double ConstantFolding(InterOperator oper, double val1, double val2 = 0.0)
{
switch (oper)
{
case IA_ADD:
return val1 + val2;
break;
case IA_SUB:
return val1 - val2;
break;
case IA_MUL:
return val1 * val2;
break;
case IA_DIVU:
case IA_DIVS:
return val1 / val2;
break;
case IA_NEG:
return -val1;
break;
case IA_ABS:
return fabs(val1);
break;
case IA_FLOOR:
return floor(val1);
break;
case IA_CEIL:
return ceil(val1);
break;
default:
return 0;
}
}
void ValueSet::InsertValue(InterInstruction& ins)
{
InterInstructionPtr* nins;
int i;
if (mNum == mSize)
{
mSize *= 2;
nins = new InterInstructionPtr[mSize];
for (i = 0; i < mNum; i++)
nins[i] = mInstructions[i];
delete[] mInstructions;
mInstructions = nins;
}
mInstructions[mNum++] = &ins;
}
static bool MemPtrRange(const InterInstruction* ins, const GrowingInstructionPtrArray& tvalue, InterMemory& mem, int& vindex, int& offset)
{
while (ins && ins->mMemory == IM_INDIRECT && ins->mCode == IC_LEA)
ins = tvalue[ins->mSTemp[1]];
if (ins && (ins->mCode == IC_CONSTANT || ins->mCode == IC_LEA))
{
mem = ins->mMemory;
vindex = ins->mVarIndex;
offset = ins->mIntValue;
return true;
}
else
return false;
}
static bool MemRange(const InterInstruction * ins, const GrowingInstructionPtrArray& tvalue, InterMemory& mem, int& vindex, int& offset)
{
if (ins->mMemory == IM_INDIRECT)
{
if (ins->mCode == IC_LOAD)
return MemPtrRange(tvalue[ins->mSTemp[0]], tvalue, mem, vindex, offset);
else
return MemPtrRange(tvalue[ins->mSTemp[1]], tvalue, mem, vindex, offset);
}
if (ins)
{
mem = ins->mMemory;
vindex = ins->mVarIndex;
offset = ins->mIntValue;
return true;
}
else
return false;
}
static bool StoreAliasing(const InterInstruction * lins, const InterInstruction* sins, const GrowingInstructionPtrArray& tvalue, const NumberSet& aliasedLocals)
{
InterMemory lmem, smem;
int lvindex, svindex;
int loffset, soffset;
if (MemRange(lins, tvalue, lmem, lvindex, loffset) && MemRange(sins, tvalue, smem, svindex, soffset))
{
if (smem == lmem && svindex == lvindex)
{
if (soffset + sins->mOperandSize >= loffset && loffset + lins->mOperandSize >= soffset)
return true;
}
return false;
}
if (lmem == IM_LOCAL)
return aliasedLocals[lvindex];
return true;
}
void ValueSet::UpdateValue(InterInstruction& ins, const GrowingInstructionPtrArray& tvalue, const NumberSet& aliasedLocals)
{
int i, value, temp;
temp = ins.mTTemp;
if (temp >= 0)
{
i = 0;
while (i < mNum)
{
if (temp == mInstructions[i]->mTTemp ||
temp == mInstructions[i]->mSTemp[0] ||
temp == mInstructions[i]->mSTemp[1] ||
temp == mInstructions[i]->mSTemp[2])
{
mNum--;
if (i < mNum)
mInstructions[i] = mInstructions[mNum];
}
else
i++;
}
}
for (i = 0; i < 3; i++)
{
temp = ins.mSTemp[i];
if (temp >= 0 && tvalue[temp])
{
ins.mSTemp[i] = tvalue[temp]->mTTemp;
}
}
switch (ins.mCode)
{
case IC_LOAD:
i = 0;
while (i < mNum &&
(mInstructions[i]->mCode != IC_LOAD ||
mInstructions[i]->mSTemp[0] != ins.mSTemp[0] ||
mInstructions[i]->mOperandSize != ins.mOperandSize))
{
i++;
}
if (i < mNum)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = mInstructions[i]->mTTemp;
ins.mSType[0] = mInstructions[i]->mTType;
assert(ins.mSTemp[0] >= 0);
}
else
{
i = 0;
while (i < mNum &&
(mInstructions[i]->mCode != IC_STORE ||
mInstructions[i]->mSTemp[1] != ins.mSTemp[0] ||
mInstructions[i]->mOperandSize != ins.mOperandSize))
{
i++;
}
if (i < mNum)
{
if (mInstructions[i]->mSTemp[0] < 0)
{
ins.mCode = IC_CONSTANT;
ins.mSTemp[0] = -1;
ins.mSType[0] = mInstructions[i]->mSType[0];
ins.mIntValue = mInstructions[i]->mSIntConst[0];
}
else
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = mInstructions[i]->mSTemp[0];
ins.mSType[0] = mInstructions[i]->mSType[0];
assert(ins.mSTemp[0] >= 0);
}
}
else
{
InsertValue(ins);
}
}
break;
case IC_STORE:
i = 0;
while (i < mNum)
{
if ((mInstructions[i]->mCode == IC_LOAD || mInstructions[i]->mCode == IC_STORE) && StoreAliasing(mInstructions[i], &ins, tvalue, aliasedLocals))
{
mNum--;
if (mNum > 0)
mInstructions[i] = mInstructions[mNum];
}
else
i++;
}
InsertValue(ins);
break;
case IC_COPY:
i = 0;
while (i < mNum)
{
if ((mInstructions[i]->mCode == IC_LOAD || mInstructions[i]->mCode == IC_STORE) && StoreAliasing(mInstructions[i], &ins, tvalue, aliasedLocals))
{
mNum--;
if (mNum > 0)
mInstructions[i] = mInstructions[mNum];
}
else
i++;
}
break;
case IC_CONSTANT:
switch (ins.mTType)
{
case IT_FLOAT:
i = 0;
while (i < mNum &&
(mInstructions[i]->mCode != IC_CONSTANT ||
mInstructions[i]->mTType != ins.mTType ||
mInstructions[i]->mFloatValue != ins.mFloatValue))
{
i++;
}
break;
case IT_POINTER:
i = 0;
while (i < mNum &&
(mInstructions[i]->mCode != IC_CONSTANT ||
mInstructions[i]->mTType != ins.mTType ||
mInstructions[i]->mIntValue != ins.mIntValue ||
mInstructions[i]->mMemory != ins.mMemory ||
mInstructions[i]->mVarIndex != ins.mVarIndex))
{
i++;
}
break;
default:
i = 0;
while (i < mNum &&
(mInstructions[i]->mCode != IC_CONSTANT ||
mInstructions[i]->mTType != ins.mTType ||
mInstructions[i]->mIntValue != ins.mIntValue))
{
i++;
}
}
if (i < mNum)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = mInstructions[i]->mTTemp;
ins.mSType[0] = mInstructions[i]->mTType;
assert(ins.mSTemp[0] >= 0);
}
else
{
InsertValue(ins);
}
break;
case IC_LEA:
i = 0;
while (i < mNum &&
(mInstructions[i]->mCode != IC_LEA ||
mInstructions[i]->mSTemp[0] != ins.mSTemp[0] ||
mInstructions[i]->mSTemp[1] != ins.mSTemp[1]))
{
i++;
}
if (i < mNum)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = mInstructions[i]->mTTemp;
ins.mSType[0] = mInstructions[i]->mTType;
ins.mSTemp[1] = -1;
assert(ins.mSTemp[0] >= 0);
}
else
{
InsertValue(ins);
}
break;
case IC_BINARY_OPERATOR:
switch (ins.mSType[0])
{
case IT_FLOAT:
if (ins.mSTemp[1] >= 0 && tvalue[ins.mSTemp[1]] && tvalue[ins.mSTemp[1]]->mCode == IC_CONSTANT &&
ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mCode = IC_CONSTANT;
ins.mFloatValue = ConstantFolding(ins.mOperator, tvalue[ins.mSTemp[1]]->mFloatValue, tvalue[ins.mSTemp[0]]->mFloatValue);
ins.mSTemp[0] = -1;
ins.mSTemp[1] = -1;
i = 0;
while (i < mNum &&
(mInstructions[i]->mCode != IC_CONSTANT ||
mInstructions[i]->mTType != ins.mTType ||
mInstructions[i]->mFloatValue != ins.mFloatValue))
{
i++;
}
if (i < mNum)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = mInstructions[i]->mTTemp;
ins.mSType[0] = mInstructions[i]->mTType;
assert(ins.mSTemp[0] >= 0);
}
else
{
InsertValue(ins);
}
}
else
{
i = 0;
while (i < mNum &&
(mInstructions[i]->mCode != IC_BINARY_OPERATOR ||
mInstructions[i]->mOperator != ins.mOperator ||
mInstructions[i]->mSTemp[0] != ins.mSTemp[0] ||
mInstructions[i]->mSTemp[1] != ins.mSTemp[1]))
{
i++;
}
if (i < mNum)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = mInstructions[i]->mTTemp;
ins.mSType[0] = mInstructions[i]->mTType;
ins.mSTemp[1] = -1;
assert(ins.mSTemp[0] >= 0);
}
else
{
InsertValue(ins);
}
}
break;
case IT_POINTER:
break;
default:
if (ins.mSTemp[1] >= 0 && tvalue[ins.mSTemp[1]] && tvalue[ins.mSTemp[1]]->mCode == IC_CONSTANT &&
ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mCode = IC_CONSTANT;
ins.mIntValue = ConstantFolding(ins.mOperator, tvalue[ins.mSTemp[1]]->mIntValue, tvalue[ins.mSTemp[0]]->mIntValue);
ins.mSTemp[0] = -1;
ins.mSTemp[1] = -1;
UpdateValue(ins, tvalue, aliasedLocals);
return;
}
if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
if ((ins.mOperator == IA_ADD || ins.mOperator == IA_SUB ||
ins.mOperator == IA_OR || ins.mOperator == IA_XOR ||
ins.mOperator == IA_SHL || ins.mOperator == IA_SHR || ins.mOperator == IA_SAR) && tvalue[ins.mSTemp[0]]->mIntValue == 0 ||
(ins.mOperator == IA_MUL || ins.mOperator == IA_DIVU || ins.mOperator == IA_DIVS) && tvalue[ins.mSTemp[0]]->mIntValue == 1 ||
(ins.mOperator == IA_AND) && tvalue[ins.mSTemp[0]]->mIntValue == -1)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = ins.mSTemp[1];
ins.mSType[0] = ins.mSType[1];
ins.mSTemp[1] = -1;
assert(ins.mSTemp[0] >= 0);
UpdateValue(ins, tvalue, aliasedLocals);
return;
}
else if ((ins.mOperator == IA_MUL || ins.mOperator == IA_AND) && tvalue[ins.mSTemp[0]]->mIntValue == 0)
{
ins.mCode = IC_CONSTANT;
ins.mIntValue = 0;
ins.mSTemp[0] = -1;
ins.mSTemp[1] = -1;
UpdateValue(ins, tvalue, aliasedLocals);
return;
}
}
else if (ins.mSTemp[1] >= 0 && tvalue[ins.mSTemp[1]] && tvalue[ins.mSTemp[1]]->mCode == IC_CONSTANT)
{
if ((ins.mOperator == IA_ADD || ins.mOperator == IA_OR || ins.mOperator == IA_XOR) && tvalue[ins.mSTemp[1]]->mIntValue == 0 ||
(ins.mOperator == IA_MUL) && tvalue[ins.mSTemp[1]]->mIntValue == 1 ||
(ins.mOperator == IA_AND) && tvalue[ins.mSTemp[1]]->mIntValue == -1)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[1] = -1;
assert(ins.mSTemp[0] >= 0);
UpdateValue(ins, tvalue, aliasedLocals);
return;
}
else if ((ins.mOperator == IA_MUL || ins.mOperator == IA_AND ||
ins.mOperator == IA_SHL || ins.mOperator == IA_SHR || ins.mOperator == IA_SAR) && tvalue[ins.mSTemp[1]]->mIntValue == 0)
{
ins.mCode = IC_CONSTANT;
ins.mIntValue = 0;
ins.mSTemp[0] = -1;
ins.mSTemp[1] = -1;
UpdateValue(ins, tvalue, aliasedLocals);
return;
}
else if (ins.mOperator == IA_SUB && tvalue[ins.mSTemp[1]]->mIntValue == 0)
{
ins.mCode = IC_UNARY_OPERATOR;
ins.mOperator = IA_NEG;
ins.mSTemp[1] = -1;
UpdateValue(ins, tvalue, aliasedLocals);
return;
}
}
else if (ins.mSTemp[0] == ins.mSTemp[1])
{
if (ins.mOperator == IA_SUB || ins.mOperator == IA_XOR)
{
ins.mCode = IC_CONSTANT;
ins.mIntValue = 0;
ins.mSTemp[0] = -1;
ins.mSTemp[1] = -1;
UpdateValue(ins, tvalue, aliasedLocals);
return;
}
else if (ins.mOperator == IA_AND || ins.mOperator == IA_OR)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[1] = -1;
assert(ins.mSTemp[0] >= 0);
UpdateValue(ins, tvalue, aliasedLocals);
return;
}
}
i = 0;
while (i < mNum &&
(mInstructions[i]->mCode != IC_BINARY_OPERATOR ||
mInstructions[i]->mOperator != ins.mOperator ||
mInstructions[i]->mSTemp[0] != ins.mSTemp[0] ||
mInstructions[i]->mSTemp[1] != ins.mSTemp[1]))
{
i++;
}
if (i < mNum)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = mInstructions[i]->mTTemp;
ins.mSType[0] = mInstructions[i]->mTType;
ins.mSTemp[1] = -1;
assert(ins.mSTemp[0] >= 0);
}
else
{
InsertValue(ins);
}
break;
}
break;
case IC_CONVERSION_OPERATOR:
if (ins.mOperator == IA_INT2FLOAT)
{
if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mCode = IC_CONSTANT;
ins.mFloatValue = (double)(tvalue[ins.mSTemp[0]]->mIntValue);
ins.mSTemp[0] = -1;
i = 0;
while (i < mNum &&
(mInstructions[i]->mCode != IC_CONSTANT ||
mInstructions[i]->mTType != ins.mTType ||
mInstructions[i]->mFloatValue != ins.mFloatValue))
{
i++;
}
if (i < mNum)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = mInstructions[i]->mTTemp;
ins.mSType[0] = mInstructions[i]->mTType;
assert(ins.mSTemp[0] >= 0);
}
else
{
InsertValue(ins);
}
}
else
{
i = 0;
while (i < mNum &&
(mInstructions[i]->mCode != IC_CONVERSION_OPERATOR ||
mInstructions[i]->mOperator != ins.mOperator ||
mInstructions[i]->mSTemp[0] != ins.mSTemp[0]))
{
i++;
}
if (i < mNum)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = mInstructions[i]->mTTemp;
ins.mSType[0] = mInstructions[i]->mTType;
ins.mSTemp[1] = -1;
assert(ins.mSTemp[0] >= 0);
}
else
{
InsertValue(ins);
}
}
}
else if (ins.mOperator == IA_FLOAT2INT)
{
}
break;
case IC_UNARY_OPERATOR:
switch (ins.mSType[0])
{
case IT_FLOAT:
if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mCode = IC_CONSTANT;
ins.mFloatValue = ConstantFolding(ins.mOperator, tvalue[ins.mSTemp[0]]->mFloatValue);
ins.mSTemp[0] = -1;
i = 0;
while (i < mNum &&
(mInstructions[i]->mCode != IC_CONSTANT ||
mInstructions[i]->mTType != ins.mTType ||
mInstructions[i]->mFloatValue != ins.mFloatValue))
{
i++;
}
if (i < mNum)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = mInstructions[i]->mTTemp;
ins.mSType[0] = mInstructions[i]->mTType;
assert(ins.mSTemp[0] >= 0);
}
else
{
InsertValue(ins);
}
}
else
{
i = 0;
while (i < mNum &&
(mInstructions[i]->mCode != IC_UNARY_OPERATOR ||
mInstructions[i]->mOperator != ins.mOperator ||
mInstructions[i]->mSTemp[0] != ins.mSTemp[0]))
{
i++;
}
if (i < mNum)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = mInstructions[i]->mTTemp;
ins.mSType[0] = mInstructions[i]->mTType;
ins.mSTemp[1] = -1;
assert(ins.mSTemp[0] >= 0);
}
else
{
InsertValue(ins);
}
}
break;
case IT_POINTER:
break;
default:
if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mCode = IC_CONSTANT;
ins.mIntValue = ConstantFolding(ins.mOperator, tvalue[ins.mSTemp[0]]->mIntValue);
ins.mSTemp[0] = -1;
i = 0;
while (i < mNum &&
(mInstructions[i]->mCode != IC_CONSTANT ||
mInstructions[i]->mTType != ins.mTType ||
mInstructions[i]->mIntValue != ins.mIntValue))
{
i++;
}
if (i < mNum)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = mInstructions[i]->mTTemp;
ins.mSType[0] = mInstructions[i]->mTType;
assert(ins.mSTemp[0] >= 0);
}
else
{
InsertValue(ins);
}
}
else
{
i = 0;
while (i < mNum &&
(mInstructions[i]->mCode != IC_UNARY_OPERATOR ||
mInstructions[i]->mOperator != ins.mOperator ||
mInstructions[i]->mSTemp[0] != ins.mSTemp[0]))
{
i++;
}
if (i < mNum)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = mInstructions[i]->mTTemp;
ins.mSType[0] = mInstructions[i]->mTType;
assert(ins.mSTemp[0] >= 0);
}
else
{
InsertValue(ins);
}
}
break;
}
break;
case IC_RELATIONAL_OPERATOR:
switch (ins.mSType[1])
{
case IT_FLOAT:
if (ins.mSTemp[1] >= 0 && tvalue[ins.mSTemp[1]] && tvalue[ins.mSTemp[1]]->mCode == IC_CONSTANT &&
ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mCode = IC_CONSTANT;
ins.mIntValue = ConstantRelationalFolding(ins.mOperator, tvalue[ins.mSTemp[1]]->mFloatValue, tvalue[ins.mSTemp[0]]->mFloatValue);
ins.mSTemp[0] = -1;
ins.mSTemp[1] = -1;
UpdateValue(ins, tvalue, aliasedLocals);
}
break;
case IT_POINTER:
break;
default:
if (ins.mSTemp[1] >= 0 && tvalue[ins.mSTemp[1]] && tvalue[ins.mSTemp[1]]->mCode == IC_CONSTANT &&
ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mCode = IC_CONSTANT;
ins.mIntValue = ConstantFolding(ins.mOperator, tvalue[ins.mSTemp[1]]->mIntValue, tvalue[ins.mSTemp[0]]->mIntValue);
ins.mSTemp[0] = -1;
ins.mSTemp[1] = -1;
UpdateValue(ins, tvalue, aliasedLocals);
}
else if (ins.mSTemp[1] == ins.mSTemp[0])
{
ins.mCode = IC_CONSTANT;
switch (ins.mOperator)
{
case IA_CMPEQ:
case IA_CMPGES:
case IA_CMPLES:
case IA_CMPGEU:
case IA_CMPLEU:
ins.mIntValue = 1;
break;
case IA_CMPNE:
case IA_CMPGS:
case IA_CMPLS:
case IA_CMPGU:
case IA_CMPLU:
ins.mIntValue = 0;
break;
}
ins.mSTemp[0] = -1;
ins.mSTemp[1] = -1;
UpdateValue(ins, tvalue, aliasedLocals);
}
break;
}
break;
case IC_CALL:
case IC_JSR:
FlushCallAliases();
break;
}
}
InterInstruction::InterInstruction(void)
{
mCode = IC_NONE;
mTType = IT_NONE;
mSType[0] = IT_NONE;
mSType[1] = IT_NONE;
mSType[2] = IT_NONE;
mTTemp = INVALID_TEMPORARY;
mSTemp[0] = INVALID_TEMPORARY;
mSTemp[1] = INVALID_TEMPORARY;
mSTemp[2] = INVALID_TEMPORARY;
}
void InterInstruction::SetCode(const Location& loc, InterCode code)
{
this->mCode = code;
this->mLocation = loc;
}
static bool TypeInteger(InterType t)
{
return t == IT_UNSIGNED || t == IT_SIGNED || t == IT_BOOL || t == IT_POINTER;
}
static bool TypeCompatible(InterType t1, InterType t2)
{
return t1 == t2 || TypeInteger(t1) && TypeInteger(t2);
}
static bool TypeArithmetic(InterType t)
{
return t == IT_UNSIGNED || t == IT_SIGNED || t == IT_BOOL || t == IT_FLOAT;
}
static InterType TypeCheckArithmecitResult(InterType t1, InterType t2)
{
if (t1 == IT_FLOAT && t2 == IT_FLOAT)
return IT_FLOAT;
else if (TypeInteger(t1) && TypeInteger(t2))
return IT_SIGNED;
else
throw InterCodeTypeMismatchException();
}
static void TypeCheckAssign(InterType& t, InterType s)
{
if (s == IT_NONE)
throw InterCodeUninitializedException();
else if (t == IT_NONE)
t = s;
else if (!TypeCompatible(t, s))
throw InterCodeTypeMismatchException();
}
static void FilterTempUseUsage(NumberSet& requiredTemps, NumberSet& providedTemps, int temp)
{
if (temp >= 0)
{
if (!providedTemps[temp]) requiredTemps += temp;
}
}
static void FilterTempDefineUsage(NumberSet& requiredTemps, NumberSet& providedTemps, int temp)
{
if (temp >= 0)
{
providedTemps += temp;
}
}
void InterInstruction::CollectLocalAddressTemps(GrowingIntArray& localTable)
{
if (mCode == IC_CONSTANT)
{
if (mTType == IT_POINTER && mMemory == IM_LOCAL)
localTable[mTTemp] = mVarIndex;
}
else if (mCode == IC_LEA)
{
if (mMemory == IM_LOCAL)
localTable[mTTemp] = localTable[mSTemp[1]];
}
else if (mCode == IC_LOAD_TEMPORARY)
{
localTable[mTTemp] = localTable[mSTemp[0]];
}
}
void InterInstruction::MarkAliasedLocalTemps(const GrowingIntArray& localTable, NumberSet& aliasedLocals)
{
if (mCode == IC_STORE)
{
int l = localTable[mSTemp[0]];
if (l >= 0)
aliasedLocals += l;
}
}
void InterInstruction::FilterTempUsage(NumberSet& requiredTemps, NumberSet& providedTemps)
{
FilterTempUseUsage(requiredTemps, providedTemps, mSTemp[0]);
FilterTempUseUsage(requiredTemps, providedTemps, mSTemp[1]);
FilterTempUseUsage(requiredTemps, providedTemps, mSTemp[2]);
FilterTempDefineUsage(requiredTemps, providedTemps, mTTemp);
}
void InterInstruction::FilterVarsUsage(const GrowingVariableArray& localVars, NumberSet& requiredVars, NumberSet& providedVars)
{
if (mCode == IC_LOAD && mMemory == IM_LOCAL)
{
assert(mSTemp[0] < 0);
if (!providedVars[mVarIndex])
requiredVars += mVarIndex;
}
else if (mCode == IC_STORE && mMemory == IM_LOCAL)
{
assert(mSTemp[1] < 0);
if (!providedVars[mVarIndex] && (mSIntConst[1] != 0 || mOperandSize != localVars[mVarIndex].mSize))
requiredVars += mVarIndex;
providedVars += mVarIndex;
}
}
static void PerformTempUseForwarding(int& temp, TempForwardingTable& forwardingTable)
{
if (temp >= 0)
temp = forwardingTable[temp];
}
static void PerformTempDefineForwarding(int temp, TempForwardingTable& forwardingTable)
{
if (temp >= 0)
{
forwardingTable.Destroy(temp);
}
}
void InterInstruction::PerformTempForwarding(TempForwardingTable& forwardingTable)
{
PerformTempUseForwarding(mSTemp[0], forwardingTable);
PerformTempUseForwarding(mSTemp[1], forwardingTable);
PerformTempUseForwarding(mSTemp[2], forwardingTable);
PerformTempDefineForwarding(mTTemp, forwardingTable);
if (mCode == IC_LOAD_TEMPORARY && mTTemp != mSTemp[0])
{
forwardingTable.Build(mTTemp, mSTemp[0]);
}
}
bool HasSideEffect(InterCode code)
{
return code == IC_CALL || code == IC_JSR;
}
bool InterInstruction::RemoveUnusedResultInstructions(InterInstruction* pre, NumberSet& requiredTemps, int numStaticTemps)
{
bool changed = false;
if (pre && mCode == IC_LOAD_TEMPORARY && pre->mTTemp == mSTemp[0] && !requiredTemps[mSTemp[0]] && pre->mTTemp >= numStaticTemps)
{
// previous instruction produced result, but it is not needed here
pre->mTTemp = mTTemp;
mCode = IC_NONE;
mTTemp = -1;
mSTemp[0] = -1;
mSTemp[1] = -1;
mSTemp[2] = -1;
changed = true;
}
else if (mTTemp != -1)
{
if (!requiredTemps[mTTemp] && mTTemp >= numStaticTemps)
{
if (!HasSideEffect(mCode))
{
mCode = IC_NONE;
mTTemp = -1;
mSTemp[0] = -1;
mSTemp[1] = -1;
mSTemp[2] = -1;
changed = true;
}
else
{
mTTemp = -1;
changed = true;
}
}
else
requiredTemps -= mTTemp;
}
if (mSTemp[0] >= 0) mSFinal[0] = !requiredTemps[mSTemp[0]] && mSTemp[0] >= numStaticTemps;
if (mSTemp[1] >= 0) mSFinal[1] = !requiredTemps[mSTemp[1]] && mSTemp[1] >= numStaticTemps;
if (mSTemp[2] >= 0) mSFinal[2] = !requiredTemps[mSTemp[2]] && mSTemp[2] >= numStaticTemps;
if (mSTemp[0] >= 0) requiredTemps += mSTemp[0];
if (mSTemp[1] >= 0) requiredTemps += mSTemp[1];
if (mSTemp[2] >= 0) requiredTemps += mSTemp[2];
return changed;
}
bool InterInstruction::RemoveUnusedStoreInstructions(const GrowingVariableArray& localVars, InterInstruction* pre, NumberSet& requiredTemps)
{
bool changed = false;
if (mCode == IC_LOAD)
{
if (mMemory == IM_LOCAL)
{
requiredTemps += mVarIndex;
}
}
else if (mCode == IC_STORE)
{
if (mMemory == IM_LOCAL)
{
if (localVars[mVarIndex].mAliased)
;
else if (requiredTemps[mVarIndex])
{
if (mSIntConst[1] == 0 && mOperandSize == localVars[mVarIndex].mSize)
requiredTemps -= mVarIndex;
}
else
{
mCode = IC_NONE;
changed = true;
}
}
}
return changed;
}
static void DestroySourceValues(int temp, GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid)
{
int i, j;
const InterInstruction* ins;
if (temp >= 0)
{
i = 0;
while (i < tvalid.Num())
{
j = tvalid.Element(i);
ins = tvalue[j];
if (ins->mSTemp[0] == temp || ins->mSTemp[1] == temp || ins->mSTemp[2] == temp)
{
tvalue[j] = NULL;
tvalid -= j;
}
else
i++;
}
}
}
void InterInstruction::PerformValueForwarding(GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid)
{
DestroySourceValues(mTTemp, tvalue, tvalid);
if (mCode == IC_LOAD_TEMPORARY)
{
if (tvalue[mSTemp[0]])
{
tvalue[mTTemp] = tvalue[mSTemp[0]];
tvalid += mTTemp;
}
}
else
{
if (mTTemp >= 0)
{
tvalue[mTTemp] = this;
tvalid += mTTemp;
}
}
}
void InterInstruction::LocalRenameRegister(GrowingIntArray& renameTable, int& num, int fixed)
{
if (mSTemp[0] >= 0) mSTemp[0] = renameTable[mSTemp[0]];
if (mSTemp[1] >= 0) mSTemp[1] = renameTable[mSTemp[1]];
if (mSTemp[2] >= 0) mSTemp[2] = renameTable[mSTemp[2]];
if (mTTemp >= fixed)
{
renameTable[mTTemp] = num;
mTTemp = num++;
}
}
void InterInstruction::GlobalRenameRegister(const GrowingIntArray& renameTable, GrowingTypeArray& temporaries)
{
if (mSTemp[0] >= 0) mSTemp[0] = renameTable[mSTemp[0]];
if (mSTemp[1] >= 0) mSTemp[1] = renameTable[mSTemp[1]];
if (mSTemp[2] >= 0) mSTemp[2] = renameTable[mSTemp[2]];
if (mTTemp >= 0)
{
mTTemp = renameTable[mTTemp];
temporaries[mTTemp] = mTType;
}
}
static void UpdateCollisionSet(NumberSet& liveTemps, NumberSet* collisionSets, int temp)
{
int i;
if (temp >= 0 && !liveTemps[temp])
{
for (i = 0; i < liveTemps.Size(); i++)
{
if (liveTemps[i])
{
collisionSets[i] += temp;
collisionSets[temp] += i;
}
}
liveTemps += temp;
}
}
void InterInstruction::BuildCollisionTable(NumberSet& liveTemps, NumberSet* collisionSets)
{
if (mTTemp >= 0)
{
// if (!liveTemps[ttemp]) __asm int 3
liveTemps -= mTTemp;
}
UpdateCollisionSet(liveTemps, collisionSets, mSTemp[0]);
UpdateCollisionSet(liveTemps, collisionSets, mSTemp[1]);
UpdateCollisionSet(liveTemps, collisionSets, mSTemp[2]);
}
void InterInstruction::ReduceTemporaries(const GrowingIntArray& renameTable, GrowingTypeArray& temporaries)
{
if (mSTemp[0] >= 0) mSTemp[0] = renameTable[mSTemp[0]];
if (mSTemp[1] >= 0) mSTemp[1] = renameTable[mSTemp[1]];
if (mSTemp[2] >= 0) mSTemp[2] = renameTable[mSTemp[2]];
if (mTTemp >= 0)
{
mTTemp = renameTable[mTTemp];
temporaries[mTTemp] = mTType;
}
}
void InterInstruction::CollectActiveTemporaries(FastNumberSet& set)
{
if (mTTemp >= 0) set += mTTemp;
if (mSTemp[0] >= 0) set += mSTemp[0];
if (mSTemp[1] >= 0) set += mSTemp[1];
if (mSTemp[2] >= 0) set += mSTemp[2];
}
void InterInstruction::ShrinkActiveTemporaries(FastNumberSet& set, GrowingTypeArray& temporaries)
{
if (mTTemp >= 0)
{
mTTemp = set.Index(mTTemp);
temporaries[mTTemp] = mTType;
}
if (mSTemp[0] >= 0) mSTemp[0] = set.Index(mSTemp[0]);
if (mSTemp[1] >= 0) mSTemp[1] = set.Index(mSTemp[1]);
if (mSTemp[2] >= 0) mSTemp[2] = set.Index(mSTemp[2]);
}
void InterInstruction::CollectSimpleLocals(FastNumberSet& complexLocals, FastNumberSet& simpleLocals, GrowingTypeArray& localTypes)
{
switch (mCode)
{
case IC_LOAD:
if (mMemory == IM_LOCAL && mSTemp[0] < 0)
{
localTypes[mVarIndex] = mTType;
if (mOperandSize == 2)
simpleLocals += mVarIndex;
else
complexLocals += mVarIndex;
}
break;
case IC_STORE:
if (mMemory == IM_LOCAL && mSTemp[1] < 0)
{
localTypes[mVarIndex] = mSType[0];
if (mOperandSize == 2)
simpleLocals += mVarIndex;
else
complexLocals += mVarIndex;
}
break;
case IC_LEA:
if (mMemory == IM_LOCAL && mSTemp[1] < 0)
complexLocals += mVarIndex;
break;
case IC_CONSTANT:
if (mTType == IT_POINTER && mMemory == IM_LOCAL)
complexLocals += mVarIndex;
break;
}
}
void InterInstruction::SimpleLocalToTemp(int vindex, int temp)
{
switch (mCode)
{
case IC_LOAD:
if (mMemory == IM_LOCAL && mSTemp[0] < 0 && vindex == this->mVarIndex)
{
mCode = IC_LOAD_TEMPORARY;
mSTemp[0] = temp;
mSType[0] = mTType;
assert(mSTemp[0] >= 0);
}
break;
case IC_STORE:
if (mMemory == IM_LOCAL && mSTemp[1] < 0 && vindex == this->mVarIndex)
{
if (mSTemp[0] < 0)
{
mCode = IC_CONSTANT;
mIntValue = mSIntConst[0];
}
else
{
mCode = IC_LOAD_TEMPORARY;
assert(mSTemp[0] >= 0);
}
mTTemp = temp;
mTType = mSType[0];
}
break;
}
}
void InterInstruction::Disassemble(FILE* file)
{
if (this->mCode != IC_NONE)
{
static char memchars[] = "NPLGFPITA";
fprintf(file, "\t");
switch (this->mCode)
{
case IC_LOAD_TEMPORARY:
case IC_STORE_TEMPORARY:
fprintf(file, "MOVE");
break;
case IC_BINARY_OPERATOR:
fprintf(file, "BINOP");
break;
case IC_UNARY_OPERATOR:
fprintf(file, "UNOP");
break;
case IC_RELATIONAL_OPERATOR:
fprintf(file, "RELOP");
break;
case IC_CONVERSION_OPERATOR:
fprintf(file, "CONV");
break;
case IC_STORE:
fprintf(file, "STORE%c%d", memchars[mMemory], mOperandSize);
break;
case IC_LOAD:
fprintf(file, "LOAD%c%d", memchars[mMemory], mOperandSize);
break;
case IC_COPY:
fprintf(file, "COPY%c", memchars[mMemory]);
break;
case IC_LEA:
fprintf(file, "LEA%c", memchars[mMemory]);
break;
case IC_TYPECAST:
fprintf(file, "CAST");
break;
case IC_CONSTANT:
fprintf(file, "CONST");
break;
case IC_BRANCH:
fprintf(file, "BRANCH");
break;
case IC_JUMP:
fprintf(file, "JUMP");
break;
case IC_PUSH_FRAME:
fprintf(file, "PUSHF\t%d", int(mIntValue));
break;
case IC_POP_FRAME:
fprintf(file, "POPF\t%d", int(mIntValue));
break;
case IC_CALL:
fprintf(file, "CALL");
break;
case IC_JSR:
fprintf(file, "JSR");
break;
case IC_RETURN_VALUE:
fprintf(file, "RETV");
break;
case IC_RETURN_STRUCT:
fprintf(file, "RETS");
break;
case IC_RETURN:
fprintf(file, "RET");
break;
}
static char typechars[] = "NUSFPB";
fprintf(file, "\t");
if (mTTemp >= 0) fprintf(file, "R%d(%c)", mTTemp, typechars[mTType]);
fprintf(file, "\t<-\t");
if (mSTemp[2] >= 0) fprintf(file, "R%d(%c%c), ", mSTemp[2], typechars[mSType[2]], mSFinal[2] ? 'F' : '-');
if (mSTemp[1] >= 0) fprintf(file, "R%d(%c%c), ", mSTemp[1], typechars[mSType[1]], mSFinal[1] ? 'F' : '-');
if (mSTemp[0] >= 0) fprintf(file, "R%d(%c%c)", mSTemp[0], typechars[mSType[0]], mSFinal[0] ? 'F' : '-');
if (this->mCode == IC_CONSTANT)
{
if (mTType == IT_POINTER)
fprintf(file, "C%d", mOperandSize);
else if (mTType == IT_FLOAT)
fprintf(file, "C%f", mFloatValue);
else
fprintf(file, "C%I64d", mIntValue);
}
fprintf(file, "\n");
}
}
InterCodeBasicBlock::InterCodeBasicBlock(void)
: mInstructions(InterInstruction()), mEntryRenameTable(-1), mExitRenameTable(-1)
{
}
InterCodeBasicBlock::~InterCodeBasicBlock(void)
{
}
void InterCodeBasicBlock::Append(InterInstruction & code)
{
this->mInstructions.Push(code);
}
void InterCodeBasicBlock::Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlock* falseJump)
{
this->mTrueJump = trueJump;
this->mFalseJump = falseJump;
this->mNumEntries = 0;
}
void InterCodeBasicBlock::CollectEntries(void)
{
mNumEntries++;
if (!mVisited)
{
mVisited = true;
if (mTrueJump) mTrueJump->CollectEntries();
if (mFalseJump) mFalseJump->CollectEntries();
}
}
void InterCodeBasicBlock::GenerateTraces(void)
{
int i;
if (!mVisited)
{
mVisited = true;
for (;;)
{
if (mTrueJump && mTrueJump->mInstructions.Size() == 1 && mTrueJump->mInstructions[0].mCode == IC_JUMP)
{
mTrueJump->mNumEntries--;
mTrueJump = mTrueJump->mTrueJump;
if (mTrueJump)
mTrueJump->mNumEntries++;
}
else if (mFalseJump && mFalseJump->mInstructions.Size() == 1 && mFalseJump->mInstructions[0].mCode == IC_JUMP)
{
mFalseJump->mNumEntries--;
mFalseJump = mFalseJump->mTrueJump;
if (mFalseJump)
mFalseJump->mNumEntries++;
}
else if (mTrueJump && !mFalseJump && ((mTrueJump->mInstructions.Size() < 10 && mTrueJump->mInstructions.Size() > 1) || mTrueJump->mNumEntries == 1))
{
mTrueJump->mNumEntries--;
mInstructions.Pop();
for (i = 0; i < mTrueJump->mInstructions.Size(); i++)
mInstructions.Push(mTrueJump->mInstructions[i]);
mFalseJump = mTrueJump->mFalseJump;
mTrueJump = mTrueJump->mTrueJump;
if (mTrueJump)
mTrueJump->mNumEntries++;
if (mFalseJump)
mFalseJump->mNumEntries++;
}
else
break;
}
if (mTrueJump) mTrueJump->GenerateTraces();
if (mFalseJump) mFalseJump->GenerateTraces();
}
}
static bool IsSimpleAddressMultiply(int val)
{
switch (val)
{
case 1: // SHR 3
case 2: // SHR 2
case 4: // SHR 1
case 8:
case 16: // * 2
case 32: // * 4
case 64: // * 8
case 128: // LEA r * 2, * 8
case 192: // LEA r, r * 2, * 8
case 256: // LEA r * 4, * 8
case 512: // LEA r * 8, * 8
return true;
}
return false;
}
static void OptimizeAddress(InterInstruction& ins, const GrowingInstructionPtrArray& tvalue, int offset)
{
ins.mSIntConst[offset] = 0;
if (ins.mSTemp[offset] >= 0 && tvalue[ins.mSTemp[offset]])
{
if (tvalue[ins.mSTemp[offset]]->mCode == IC_CONSTANT)
{
ins.mSIntConst[offset] = tvalue[ins.mSTemp[offset]]->mIntValue;
ins.mVarIndex = tvalue[ins.mSTemp[offset]]->mVarIndex;
ins.mMemory = tvalue[ins.mSTemp[offset]]->mMemory;
ins.mSTemp[offset] = -1;
}
}
}
void InterCodeBasicBlock::CheckValueUsage(InterInstruction& ins, const GrowingInstructionPtrArray& tvalue)
{
switch (ins.mCode)
{
case IC_CALL:
case IC_JSR:
if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mMemory = tvalue[ins.mSTemp[0]]->mMemory;
ins.mVarIndex = tvalue[ins.mSTemp[0]]->mVarIndex;
ins.mOperandSize = tvalue[ins.mSTemp[0]]->mOperandSize;
ins.mSIntConst[0] = tvalue[ins.mSTemp[0]]->mIntValue;
ins.mSTemp[0] = -1;
}
break;
case IC_LOAD_TEMPORARY:
if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
switch (ins.mSType[0])
{
case IT_FLOAT:
ins.mCode = IC_CONSTANT;
ins.mFloatValue = tvalue[ins.mSTemp[0]]->mFloatValue;
ins.mSTemp[0] = -1;
break;
case IT_POINTER:
ins.mCode = IC_CONSTANT;
ins.mMemory = tvalue[ins.mSTemp[0]]->mMemory;
ins.mVarIndex = tvalue[ins.mSTemp[0]]->mVarIndex;
ins.mIntValue = tvalue[ins.mSTemp[0]]->mIntValue;
ins.mOperandSize = tvalue[ins.mSTemp[0]]->mOperandSize;
ins.mSTemp[0] = -1;
break;
default:
ins.mCode = IC_CONSTANT;
ins.mIntValue = tvalue[ins.mSTemp[0]]->mIntValue;
ins.mSTemp[0] = -1;
break;
}
}
break;
case IC_LOAD:
OptimizeAddress(ins, tvalue, 0);
break;
case IC_STORE:
if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
switch (ins.mSType[0])
{
case IT_FLOAT:
ins.mSFloatConst[0] = tvalue[ins.mSTemp[0]]->mFloatValue;
ins.mSTemp[0] = -1;
break;
case IT_POINTER:
break;
default:
if (ins.mSType[0] == IT_UNSIGNED)
ins.mSIntConst[0] = unsigned short (tvalue[ins.mSTemp[0]]->mIntValue);
else
ins.mSIntConst[0] = tvalue[ins.mSTemp[0]]->mIntValue;
ins.mSTemp[0] = -1;
break;
}
}
OptimizeAddress(ins, tvalue, 1);
break;
case IC_LEA:
if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
if (ins.mSTemp[1] >= 0 && tvalue[ins.mSTemp[1]] && tvalue[ins.mSTemp[1]]->mCode == IC_CONSTANT)
{
ins.mCode = IC_CONSTANT;
ins.mTType = IT_POINTER;
ins.mMemory = tvalue[ins.mSTemp[1]]->mMemory;
ins.mVarIndex = tvalue[ins.mSTemp[1]]->mVarIndex;
ins.mIntValue = tvalue[ins.mSTemp[1]]->mIntValue + tvalue[ins.mSTemp[0]]->mIntValue;
ins.mSTemp[0] = -1;
ins.mSTemp[1] = -1;
}
else if (tvalue[ins.mSTemp[0]]->mIntValue == 0)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSType[0] = ins.mSType[1];
ins.mSTemp[0] = ins.mSTemp[1];
ins.mSTemp[1] = -1;
assert(ins.mSTemp[0] >= 0);
}
}
break;
case IC_TYPECAST:
if (ins.mSType[0] == ins.mTType)
{
ins.mCode = IC_LOAD_TEMPORARY;
assert(ins.mSTemp[0] >= 0);
}
else if ((ins.mSType[0] == IT_SIGNED || ins.mSType[0] == IT_UNSIGNED) && ins.mTType == IT_POINTER)
{
if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mCode = IC_CONSTANT;
ins.mTType = IT_POINTER;
ins.mMemory = IM_ABSOLUTE;
ins.mVarIndex = 0;
ins.mIntValue = tvalue[ins.mSTemp[0]]->mIntValue;
ins.mSTemp[0] = -1;
}
}
break;
case IC_RETURN_VALUE:
if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
switch (ins.mSType[0])
{
case IT_FLOAT:
break;
case IT_POINTER:
break;
default:
if (ins.mSType[0] == IT_UNSIGNED)
ins.mSIntConst[0] = unsigned short(tvalue[ins.mSTemp[0]]->mIntValue);
else
ins.mSIntConst[0] = tvalue[ins.mSTemp[0]]->mIntValue;
ins.mSTemp[0] = -1;
break;
}
}
break;
case IC_BINARY_OPERATOR:
switch (ins.mSType[0])
{
case IT_FLOAT:
if (ins.mSTemp[1] >= 0 && tvalue[ins.mSTemp[1]] && tvalue[ins.mSTemp[1]]->mCode == IC_CONSTANT)
{
if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mCode = IC_CONSTANT;
ins.mFloatValue = ConstantFolding(ins.mOperator, tvalue[ins.mSTemp[1]]->mFloatValue, tvalue[ins.mSTemp[0]]->mFloatValue);
ins.mSTemp[0] = -1;
ins.mSTemp[1] = -1;
}
else
{
ins.mSFloatConst[1] = tvalue[ins.mSTemp[1]]->mFloatValue;
ins.mSTemp[1] = -1;
if (ins.mOperator == IA_ADD && ins.mSFloatConst[1] == 0)
{
ins.mCode = IC_LOAD_TEMPORARY;
assert(ins.mSTemp[0] >= 0);
}
else if (ins.mOperator == IA_MUL)
{
if (ins.mSFloatConst[1] == 1.0)
{
ins.mCode = IC_LOAD_TEMPORARY;
assert(ins.mSTemp[0] >= 0);
}
else if (ins.mSFloatConst[1] == 0.0)
{
ins.mCode = IC_CONSTANT;
ins.mFloatValue = 0.0;
ins.mSTemp[0] = -1;
ins.mSTemp[1] = -1;
}
else if (ins.mSFloatConst[1] == 2.0)
{
ins.mOperator = IA_ADD;
ins.mSTemp[1] = ins.mSTemp[0];
assert(ins.mSTemp[0] >= 0);
}
}
}
}
else if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mSFloatConst[0] = tvalue[ins.mSTemp[0]]->mFloatValue;
ins.mSTemp[0] = -1;
if (ins.mOperator == IA_ADD && ins.mSFloatConst[0] == 0)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = ins.mSTemp[1];
ins.mSTemp[1] = -1;
assert(ins.mSTemp[0] >= 0);
}
else if (ins.mOperator == IA_MUL)
{
if (ins.mSFloatConst[0] == 1.0)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = ins.mSTemp[1];
ins.mSTemp[1] = -1;
assert(ins.mSTemp[0] >= 0);
}
else if (ins.mSFloatConst[0] == 0.0)
{
ins.mCode = IC_CONSTANT;
ins.mFloatValue = 0.0;
ins.mSTemp[0] = -1;
ins.mSTemp[1] = -1;
}
else if (ins.mSFloatConst[0] == 2.0)
{
ins.mOperator = IA_ADD;
ins.mSTemp[0] = ins.mSTemp[1];
assert(ins.mSTemp[0] >= 0);
}
}
}
break;
case IT_POINTER:
break;
default:
if (ins.mSTemp[1] >= 0 && tvalue[ins.mSTemp[1]] && tvalue[ins.mSTemp[1]]->mCode == IC_CONSTANT)
{
if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mCode = IC_CONSTANT;
ins.mIntValue = ConstantFolding(ins.mOperator, tvalue[ins.mSTemp[1]]->mIntValue, tvalue[ins.mSTemp[0]]->mIntValue);
ins.mSTemp[0] = -1;
ins.mSTemp[1] = -1;
}
else
{
ins.mSIntConst[1] = tvalue[ins.mSTemp[1]]->mIntValue;
ins.mSTemp[1] = -1;
#if 1
if (ins.mOperator == IA_ADD && ins.mSIntConst[1] == 0)
{
ins.mCode = IC_LOAD_TEMPORARY;
assert(ins.mSTemp[0] >= 0);
}
else if (ins.mOperator == IA_MUL)
{
if (ins.mSIntConst[1] == 1)
{
ins.mCode = IC_LOAD_TEMPORARY;
assert(ins.mSTemp[0] >= 0);
}
else if (ins.mSIntConst[1] == 2)
{
ins.mOperator = IA_SHL;
ins.mSTemp[1] = ins.mSTemp[0];
ins.mSType[1] = ins.mSType[0];
ins.mSTemp[0] = -1;
ins.mSIntConst[0] = 1;
}
else if (ins.mSIntConst[1] == 4)
{
ins.mOperator = IA_SHL;
ins.mSTemp[1] = ins.mSTemp[0];
ins.mSType[1] = ins.mSType[0];
ins.mSTemp[0] = -1;
ins.mSIntConst[0] = 2;
}
else if (ins.mSIntConst[1] == 8)
{
ins.mOperator = IA_SHL;
ins.mSTemp[1] = ins.mSTemp[0];
ins.mSType[1] = ins.mSType[0];
ins.mSTemp[0] = -1;
ins.mSIntConst[0] = 3;
}
}
#endif
}
}
else if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mSIntConst[0] = tvalue[ins.mSTemp[0]]->mIntValue;
ins.mSTemp[0] = -1;
if (ins.mOperator == IA_ADD && ins.mSIntConst[0] == 0)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = ins.mSTemp[1];
ins.mSTemp[1] = -1;
assert(ins.mSTemp[0] >= 0);
}
else if (ins.mOperator == IA_MUL)
{
if (ins.mSIntConst[0] == 1)
{
ins.mCode = IC_LOAD_TEMPORARY;
ins.mSTemp[0] = ins.mSTemp[1];
ins.mSTemp[1] = -1;
assert(ins.mSTemp[0] >= 0);
}
else if (ins.mSIntConst[0] == 2)
{
ins.mOperator = IA_SHL;
ins.mSIntConst[0] = 1;
}
else if (ins.mSIntConst[0] == 4)
{
ins.mOperator = IA_SHL;
ins.mSIntConst[0] = 2;
}
else if (ins.mSIntConst[0] == 8)
{
ins.mOperator = IA_SHL;
ins.mSIntConst[0] = 3;
}
}
}
if (ins.mSTemp[1] < 0 && ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_BINARY_OPERATOR)
{
InterInstruction* pins = tvalue[ins.mSTemp[0]];
if (ins.mOperator == pins->mOperator && (ins.mOperator == IA_ADD || ins.mOperator == IA_MUL || ins.mOperator == IA_AND || ins.mOperator == IA_OR))
{
if (pins->mSTemp[1] < 0)
{
ins.mSIntConst[1] = ConstantFolding(ins.mOperator, ins.mSIntConst[1], pins->mSIntConst[1]);
ins.mSTemp[0] = pins->mSTemp[0];
}
else if (pins->mSTemp[0] < 0)
{
ins.mSIntConst[1] = ConstantFolding(ins.mOperator, ins.mSIntConst[1], pins->mSIntConst[0]);
ins.mSTemp[0] = pins->mSTemp[1];
}
}
}
else if (ins.mSTemp[0] < 0 && ins.mSTemp[1] >= 0 && tvalue[ins.mSTemp[1]] && tvalue[ins.mSTemp[1]]->mCode == IC_BINARY_OPERATOR)
{
InterInstruction* pins = tvalue[ins.mSTemp[1]];
if (ins.mOperator == pins->mOperator && (ins.mOperator == IA_ADD || ins.mOperator == IA_MUL || ins.mOperator == IA_AND || ins.mOperator == IA_OR))
{
if (pins->mSTemp[1] < 0)
{
ins.mSIntConst[0] = ConstantFolding(ins.mOperator, ins.mSIntConst[0], pins->mSIntConst[1]);
ins.mSTemp[1] = pins->mSTemp[0];
}
else if (pins->mSTemp[0] < 0)
{
ins.mSIntConst[0] = ConstantFolding(ins.mOperator, ins.mSIntConst[0], pins->mSIntConst[0]);
ins.mSTemp[1] = pins->mSTemp[1];
}
}
else if (ins.mOperator == IA_SHL && (pins->mOperator == IA_SHR || pins->mOperator == IA_SAR) && pins->mSTemp[0] < 0 && ins.mSIntConst[0] == pins->mSIntConst[0])
{
ins.mOperator = IA_AND;
ins.mSIntConst[0] = -1LL << ins.mSIntConst[0];
ins.mSTemp[1] = pins->mSTemp[1];
}
}
break;
}
break;
case IC_UNARY_OPERATOR:
switch (ins.mSType[0])
{
case IT_FLOAT:
if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mCode = IC_CONSTANT;
ins.mFloatValue = ConstantFolding(ins.mOperator, tvalue[ins.mSTemp[0]]->mFloatValue);
ins.mSTemp[0] = -1;
}
break;
case IT_POINTER:
break;
default:
break;
}
break;
case IC_RELATIONAL_OPERATOR:
switch (ins.mSType[1])
{
case IT_FLOAT:
if (ins.mSTemp[1] >= 0 && tvalue[ins.mSTemp[1]] && tvalue[ins.mSTemp[1]]->mCode == IC_CONSTANT &&
ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mCode = IC_CONSTANT;
ins.mIntValue = ConstantRelationalFolding(ins.mOperator, tvalue[ins.mSTemp[1]]->mFloatValue, tvalue[ins.mSTemp[0]]->mFloatValue);
ins.mTType = IT_SIGNED;
ins.mSTemp[0] = -1;
ins.mSTemp[1] = -1;
}
else
{
if (ins.mSTemp[1] >= 0 && tvalue[ins.mSTemp[1]] && tvalue[ins.mSTemp[1]]->mCode == IC_CONSTANT)
{
ins.mSFloatConst[1] = tvalue[ins.mSTemp[1]]->mFloatValue;
ins.mSTemp[1] = -1;
}
else if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mSFloatConst[0] = tvalue[ins.mSTemp[0]]->mFloatValue;
ins.mSTemp[0] = -1;
}
}
break;
case IT_POINTER:
if (ins.mOperator == IA_CMPEQ || ins.mOperator == IA_CMPNE)
{
if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mOperandSize = tvalue[ins.mSTemp[0]]->mOperandSize;
ins.mSTemp[0] = -1;
}
else if (ins.mSTemp[1] >= 0 && tvalue[ins.mSTemp[1]] && tvalue[ins.mSTemp[1]]->mCode == IC_CONSTANT)
{
ins.mOperandSize = tvalue[ins.mSTemp[1]]->mOperandSize;
ins.mSTemp[1] = -1;
}
}
break;
default:
if (ins.mSTemp[1] >= 0 && tvalue[ins.mSTemp[1]] && tvalue[ins.mSTemp[1]]->mCode == IC_CONSTANT &&
ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mCode = IC_CONSTANT;
ins.mIntValue = ConstantFolding(ins.mOperator, tvalue[ins.mSTemp[1]]->mIntValue, tvalue[ins.mSTemp[0]]->mIntValue);
ins.mSTemp[0] = -1;
ins.mSTemp[1] = -1;
}
else
{
if (ins.mSTemp[1] >= 0 && tvalue[ins.mSTemp[1]] && tvalue[ins.mSTemp[1]]->mCode == IC_CONSTANT)
{
ins.mSIntConst[1] = tvalue[ins.mSTemp[1]]->mIntValue;
ins.mSTemp[1] = -1;
}
else if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mSIntConst[0] = tvalue[ins.mSTemp[0]]->mIntValue;
ins.mSTemp[0] = -1;
}
}
break;
}
break;
case IC_BRANCH:
if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT)
{
ins.mSIntConst[0] = tvalue[ins.mSTemp[0]]->mIntValue;
ins.mSTemp[0] = -1;
}
break;
}
}
void InterCodeBasicBlock::CollectLocalAddressTemps(GrowingIntArray& localTable)
{
int i;
if (!mVisited)
{
mVisited = true;
for (i = 0; i < mInstructions.Size(); i++)
mInstructions[i].CollectLocalAddressTemps(localTable);
if (mTrueJump) mTrueJump->CollectLocalAddressTemps(localTable);
if (mFalseJump) mFalseJump->CollectLocalAddressTemps(localTable);
}
}
void InterCodeBasicBlock::MarkAliasedLocalTemps(const GrowingIntArray& localTable, NumberSet& aliasedLocals)
{
int i;
if (!mVisited)
{
mVisited = true;
for (i = 0; i < mInstructions.Size(); i++)
mInstructions[i].MarkAliasedLocalTemps(localTable, aliasedLocals);
if (mTrueJump) mTrueJump->MarkAliasedLocalTemps(localTable, aliasedLocals);
if (mFalseJump) mFalseJump->MarkAliasedLocalTemps(localTable, aliasedLocals);
}
}
void InterCodeBasicBlock::BuildLocalTempSets(int num, int numFixed)
{
int i;
if (!mVisited)
{
mVisited = true;
mLocalRequiredTemps = NumberSet(num);
mLocalProvidedTemps = NumberSet(num);
mEntryRequiredTemps = NumberSet(num);
mEntryProvidedTemps = NumberSet(num);
mExitRequiredTemps = NumberSet(num);
exitProvidedTemps = NumberSet(num);
for (i = 0; i < mInstructions.Size(); i++)
{
mInstructions[i].FilterTempUsage(mLocalRequiredTemps, mLocalProvidedTemps);
}
mEntryRequiredTemps = mLocalRequiredTemps;
exitProvidedTemps = mLocalProvidedTemps;
for (i = 0; i < numFixed; i++)
{
mEntryRequiredTemps += i;
exitProvidedTemps += i;
}
if (mTrueJump) mTrueJump->BuildLocalTempSets(num, numFixed);
if (mFalseJump) mFalseJump->BuildLocalTempSets(num, numFixed);
}
}
void InterCodeBasicBlock::BuildGlobalProvidedTempSet(NumberSet fromProvidedTemps)
{
if (!mVisited || !(fromProvidedTemps <= mEntryProvidedTemps))
{
mEntryProvidedTemps |= fromProvidedTemps;
fromProvidedTemps |= exitProvidedTemps;
mVisited = true;
if (mTrueJump) mTrueJump->BuildGlobalProvidedTempSet(fromProvidedTemps);
if (mFalseJump) mFalseJump->BuildGlobalProvidedTempSet(fromProvidedTemps);
}
}
void InterCodeBasicBlock::PerformTempForwarding(TempForwardingTable& forwardingTable)
{
int i;
if (!mVisited)
{
mVisited = true;
TempForwardingTable localForwardingTable(forwardingTable);
if (mNumEntries > 1)
localForwardingTable.Reset();
for (i = 0; i < mInstructions.Size(); i++)
{
mInstructions[i].PerformTempForwarding(localForwardingTable);
}
if (mTrueJump) mTrueJump->PerformTempForwarding(localForwardingTable);
if (mFalseJump) mFalseJump->PerformTempForwarding(localForwardingTable);
}
}
bool InterCodeBasicBlock::BuildGlobalRequiredTempSet(NumberSet& fromRequiredTemps)
{
bool revisit = false;
int i;
if (!mVisited)
{
mVisited = true;
NumberSet newRequiredTemps(mExitRequiredTemps);
if (mTrueJump && mTrueJump->BuildGlobalRequiredTempSet(newRequiredTemps)) revisit = true;
if (mFalseJump && mFalseJump->BuildGlobalRequiredTempSet(newRequiredTemps)) revisit = true;
if (!(newRequiredTemps <= mExitRequiredTemps))
{
revisit = true;
mExitRequiredTemps = newRequiredTemps;
newRequiredTemps -= mLocalProvidedTemps;
mEntryRequiredTemps |= newRequiredTemps;
}
}
fromRequiredTemps |= mEntryRequiredTemps;
return revisit;
}
bool InterCodeBasicBlock::RemoveUnusedResultInstructions(int numStaticTemps)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
NumberSet requiredTemps(mExitRequiredTemps);
int i;
for (i = 0; i < numStaticTemps; i++)
requiredTemps += i;
for (i = mInstructions.Size() - 1; i > 0; i--)
{
if (mInstructions[i].RemoveUnusedResultInstructions(&(mInstructions[i - 1]), requiredTemps, numStaticTemps))
changed = true;
}
if (mInstructions[0].RemoveUnusedResultInstructions(NULL, requiredTemps, numStaticTemps))
changed = true;
if (mTrueJump)
{
if (mTrueJump->RemoveUnusedResultInstructions(numStaticTemps))
changed = true;
}
if (mFalseJump)
{
if (mFalseJump->RemoveUnusedResultInstructions(numStaticTemps))
changed = true;
}
}
return changed;
}
void InterCodeBasicBlock::BuildLocalVariableSets(const GrowingVariableArray& localVars)
{
int i;
if (!mVisited)
{
mVisited = true;
mLocalRequiredVars = NumberSet(localVars.Size());
mLocalProvidedVars = NumberSet(localVars.Size());
mEntryRequiredVars = NumberSet(localVars.Size());
mEntryProvidedVars = NumberSet(localVars.Size());
mExitRequiredVars = NumberSet(localVars.Size());
mExitProvidedVars = NumberSet(localVars.Size());
for (i = 0; i < mInstructions.Size(); i++)
{
mInstructions[i].FilterVarsUsage(localVars, mLocalRequiredVars, mLocalProvidedVars);
}
mEntryRequiredVars = mLocalRequiredVars;
mExitProvidedVars = mLocalProvidedVars;
if (mTrueJump) mTrueJump->BuildLocalVariableSets(localVars);
if (mFalseJump) mFalseJump->BuildLocalVariableSets(localVars);
}
}
void InterCodeBasicBlock::BuildGlobalProvidedVariableSet(const GrowingVariableArray& localVars, NumberSet fromProvidedVars)
{
if (!mVisited || !(fromProvidedVars <= mEntryProvidedVars))
{
mEntryProvidedVars |= fromProvidedVars;
fromProvidedVars |= mExitProvidedVars;
mVisited = true;
if (mTrueJump) mTrueJump->BuildGlobalProvidedVariableSet(localVars, fromProvidedVars);
if (mFalseJump) mFalseJump->BuildGlobalProvidedVariableSet(localVars, fromProvidedVars);
}
}
bool InterCodeBasicBlock::BuildGlobalRequiredVariableSet(const GrowingVariableArray& localVars, NumberSet& fromRequiredVars)
{
bool revisit = false;
int i;
if (!mVisited)
{
mVisited = true;
NumberSet newRequiredVars(mExitRequiredVars);
if (mTrueJump && mTrueJump->BuildGlobalRequiredVariableSet(localVars, newRequiredVars)) revisit = true;
if (mFalseJump && mFalseJump->BuildGlobalRequiredVariableSet(localVars, newRequiredVars)) revisit = true;
if (!(newRequiredVars <= mExitRequiredVars))
{
revisit = true;
mExitRequiredVars = newRequiredVars;
newRequiredVars -= mLocalProvidedVars;
mEntryRequiredVars |= newRequiredVars;
}
}
fromRequiredVars |= mEntryRequiredVars;
return revisit;
}
bool InterCodeBasicBlock::RemoveUnusedStoreInstructions(const GrowingVariableArray& localVars)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
NumberSet requiredVars(mExitRequiredVars);
int i;
for (i = mInstructions.Size() - 1; i > 0; i--)
{
if (mInstructions[i].RemoveUnusedStoreInstructions(localVars, &(mInstructions[i - 1]), requiredVars))
changed = true;
}
if (mInstructions[0].RemoveUnusedStoreInstructions(localVars, nullptr, requiredVars))
changed = true;
if (mTrueJump)
{
if (mTrueJump->RemoveUnusedStoreInstructions(localVars))
changed = true;
}
if (mFalseJump)
{
if (mFalseJump->RemoveUnusedStoreInstructions(localVars))
changed = true;
}
}
return changed;
}
void InterCodeBasicBlock::PerformValueForwarding(const GrowingInstructionPtrArray& tvalue, const ValueSet& values, FastNumberSet& tvalid, const NumberSet& aliasedLocals)
{
int i;
if (!mVisited)
{
GrowingInstructionPtrArray ltvalue(tvalue);
ValueSet lvalues(values);
mVisited = true;
tvalid.Clear();
if (mNumEntries != 1)
{
lvalues.FlushAll();
ltvalue.Clear();
}
else
{
for (i = 0; i < ltvalue.Size(); i++)
{
if (ltvalue[i])
tvalid += i;
}
}
for (i = 0; i < mInstructions.Size(); i++)
{
lvalues.UpdateValue(mInstructions[i], ltvalue, aliasedLocals);
mInstructions[i].PerformValueForwarding(ltvalue, tvalid);
}
if (mTrueJump) mTrueJump->PerformValueForwarding(ltvalue, lvalues, tvalid, aliasedLocals);
if (mFalseJump) mFalseJump->PerformValueForwarding(ltvalue, lvalues, tvalid, aliasedLocals);
}
}
void InterCodeBasicBlock::PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid)
{
int i;
if (!mVisited)
{
mVisited = true;
GrowingInstructionPtrArray ltvalue(tvalue);
tvalid.Clear();
if (mNumEntries != 1)
ltvalue.Clear();
else
{
for (i = 0; i < tvalue.Size(); i++)
{
if (ltvalue[i])
tvalid += i;
}
}
for (i = 0; i < mInstructions.Size(); i++)
{
CheckValueUsage(mInstructions[i], ltvalue);
mInstructions[i].PerformValueForwarding(ltvalue, tvalid);
}
if (mTrueJump) mTrueJump->PerformMachineSpecificValueUsageCheck(ltvalue, tvalid);
if (mFalseJump) mFalseJump->PerformMachineSpecificValueUsageCheck(ltvalue, tvalid);
}
}
static void Union(GrowingIntArray& table, int i, int j)
{
int k, l;
k = table[j];
while (j != k)
{
l = table[k];
table[j] = l;
j = k; k = l;
}
table[j] = table[i];
}
static int Find(GrowingIntArray& table, int i)
{
int j, k, l;
j = i;
k = table[j];
while (j != k)
{
l = table[k];
table[j] = l;
j = k; k = l;
}
return j;
}
void InterCodeBasicBlock::LocalRenameRegister(const GrowingIntArray& renameTable, int& num, int fixed)
{
int i;
if (!mVisited)
{
mVisited = true;
mEntryRenameTable.SetSize(renameTable.Size());
mExitRenameTable.SetSize(renameTable.Size());
for (i = 0; i < renameTable.Size(); i++)
{
if (i < fixed)
{
mEntryRenameTable[i] = i;
mExitRenameTable[i] = i;
}
else if (mEntryRequiredTemps[i])
{
mEntryRenameTable[i] = renameTable[i];
mExitRenameTable[i] = renameTable[i];
}
else
{
mEntryRenameTable[i] = -1;
mExitRenameTable[i] = -1;
}
}
for (i = 0; i < mInstructions.Size(); i++)
{
mInstructions[i].LocalRenameRegister(mExitRenameTable, num, fixed);
}
if (mTrueJump) mTrueJump->LocalRenameRegister(mExitRenameTable, num, fixed);
if (mFalseJump) mFalseJump->LocalRenameRegister(mExitRenameTable, num, fixed);
}
}
void InterCodeBasicBlock::BuildGlobalRenameRegisterTable(const GrowingIntArray& renameTable, GrowingIntArray& globalRenameTable)
{
int i;
for (i = 0; i < renameTable.Size(); i++)
{
if (renameTable[i] >= 0 && mEntryRenameTable[i] >= 0 && renameTable[i] != mEntryRenameTable[i])
{
Union(globalRenameTable, renameTable[i], mEntryRenameTable[i]);
}
}
if (!mVisited)
{
mVisited = true;
if (mTrueJump) mTrueJump->BuildGlobalRenameRegisterTable(mExitRenameTable, globalRenameTable);
if (mFalseJump) mFalseJump->BuildGlobalRenameRegisterTable(mExitRenameTable, globalRenameTable);
}
}
void InterCodeBasicBlock::GlobalRenameRegister(const GrowingIntArray& renameTable, GrowingTypeArray& temporaries)
{
int i;
if (!mVisited)
{
mVisited = true;
for (i = 0; i < mInstructions.Size(); i++)
{
mInstructions[i].GlobalRenameRegister(renameTable, temporaries);
}
if (mTrueJump) mTrueJump->GlobalRenameRegister(renameTable, temporaries);
if (mFalseJump) mFalseJump->GlobalRenameRegister(renameTable, temporaries);
}
}
void InterCodeBasicBlock::BuildCollisionTable(NumberSet* collisionSets)
{
if (!mVisited)
{
mVisited = true;
NumberSet requiredTemps(mExitRequiredTemps);
int i, j;
for (i = 0; i < mExitRequiredTemps.Size(); i++)
{
if (mExitRequiredTemps[i])
{
for (j = 0; j < mExitRequiredTemps.Size(); j++)
{
if (mExitRequiredTemps[j])
{
collisionSets[i] += j;
}
}
}
}
for (i = mInstructions.Size() - 1; i >= 0; i--)
{
mInstructions[i].BuildCollisionTable(requiredTemps, collisionSets);
}
if (mTrueJump) mTrueJump->BuildCollisionTable(collisionSets);
if (mFalseJump) mFalseJump->BuildCollisionTable(collisionSets);
}
}
void InterCodeBasicBlock::ReduceTemporaries(const GrowingIntArray& renameTable, GrowingTypeArray& temporaries)
{
int i;
if (!mVisited)
{
mVisited = true;
for (i = 0; i < mInstructions.Size(); i++)
{
mInstructions[i].ReduceTemporaries(renameTable, temporaries);
}
if (mTrueJump) mTrueJump->ReduceTemporaries(renameTable, temporaries);
if (mFalseJump) mFalseJump->ReduceTemporaries(renameTable, temporaries);
}
}
static void UseGlobal(GrowingVariableArray& globalVars, int index)
{
if (!globalVars[index].mUsed)
{
globalVars[index].mUsed = true;
for (int i = 0; i < globalVars[index].mNumReferences; i++)
{
if (!globalVars[index].mReferences[i].mFunction)
UseGlobal(globalVars, globalVars[index].mReferences[i].mIndex);
}
}
}
void InterCodeModule::UseGlobal(int index)
{
if (!mGlobalVars[index].mUsed)
{
mGlobalVars[index].mUsed = true;
for (int i = 0; i < mGlobalVars[index].mNumReferences; i++)
{
if (!mGlobalVars[index].mReferences[i].mFunction)
UseGlobal( mGlobalVars[index].mReferences[i].mIndex);
}
}
}
void InterCodeBasicBlock::MapVariables(GrowingVariableArray& globalVars, GrowingVariableArray& localVars)
{
int i;
if (!mVisited)
{
mVisited = true;
for (i = 0; i < mInstructions.Size(); i++)
{
bool found = false;
switch (mInstructions[i].mCode)
{
case IC_CONSTANT:
if (mInstructions[i].mTType != IT_POINTER)
break;
case IC_STORE:
case IC_LOAD:
case IC_JSR:
if (mInstructions[i].mMemory == IM_GLOBAL)
{
UseGlobal(globalVars, mInstructions[i].mVarIndex);
}
else if (mInstructions[i].mMemory == IM_LOCAL)
{
localVars[mInstructions[i].mVarIndex].mUsed = true;
}
break;
}
}
if (mTrueJump) mTrueJump->MapVariables(globalVars, localVars);
if (mFalseJump) mFalseJump->MapVariables(globalVars, localVars);
}
}
void InterCodeBasicBlock::CollectOuterFrame(int level, int& size)
{
int i;
if (!mVisited)
{
mVisited = true;
for (i = 0; i < mInstructions.Size(); i++)
{
if (mInstructions[i].mCode == IC_PUSH_FRAME)
{
level++;
if (level == 1)
{
if (mInstructions[i].mIntValue > size)
size = mInstructions[i].mIntValue;
mInstructions[i].mCode = IC_NONE;
}
}
else if (mInstructions[i].mCode == IC_POP_FRAME)
{
if (level == 1)
{
mInstructions[i].mCode = IC_NONE;
}
level--;
}
}
if (mTrueJump) mTrueJump->CollectOuterFrame(level, size);
if (mFalseJump) mFalseJump->CollectOuterFrame(level, size);
}
}
bool InterCodeBasicBlock::IsLeafProcedure(void)
{
int i;
if (!mVisited)
{
mVisited = true;
for (i = 0; i < mInstructions.Size(); i++)
if (mInstructions[i].mCode == IC_CALL || mInstructions[i].mCode == IC_JSR)
return false;
if (mTrueJump && !mTrueJump->IsLeafProcedure())
return false;
if (mFalseJump && !mFalseJump->IsLeafProcedure())
return false;
}
return true;
}
static bool CanBypassLoad(const InterInstruction& lins, const InterInstruction& bins)
{
// Check ambiguity
if (bins.mCode == IC_STORE || bins.mCode == IC_COPY)
return false;
// Side effects
if (bins.mCode == IC_CALL || bins.mCode == IC_JSR)
return false;
// True data dependency
if (lins.mTTemp == bins.mSTemp[0] || lins.mTTemp == bins.mSTemp[1] || lins.mTTemp == bins.mSTemp[2])
return false;
// False data dependency
if (lins.mSTemp[0] >= 0 && lins.mSTemp[0] == bins.mTTemp)
return false;
return true;
}
static bool CanBypassStore(const InterInstruction& sins, const InterInstruction& bins)
{
if (bins.mCode == IC_COPY || bins.mCode == IC_PUSH_FRAME)
return false;
// Check ambiguity
if (bins.mCode == IC_STORE || bins.mCode == IC_LOAD)
{
if (sins.mMemory == IM_LOCAL)
{
if (bins.mMemory == IM_PARAM || bins.mMemory == IM_GLOBAL)
;
else if (bins.mMemory == IM_LOCAL)
{
if (bins.mVarIndex == sins.mVarIndex)
return false;
}
else
return false;
}
else
return false;
}
if (sins.mMemory == IM_FRAME && (bins.mCode == IC_PUSH_FRAME || bins.mCode == IC_POP_FRAME))
return false;
// Side effects
if (bins.mCode == IC_CALL || bins.mCode == IC_JSR)
return false;
// True data dependency
if (bins.mTTemp >= 0 && (bins.mTTemp == sins.mSTemp[0] || bins.mTTemp == sins.mSTemp[1]))
return false;
return true;
}
void InterCodeBasicBlock::PeepholeOptimization(void)
{
int i;
if (!mVisited)
{
mVisited = true;
// shorten lifespan
int i = mInstructions.Size() - 2;
while (i >= 0)
{
// move loads down
if (mInstructions[i].mCode == IC_LOAD)
{
InterInstruction ins(mInstructions[i]);
int j = i;
while (j + 2 < mInstructions.Size() && CanBypassLoad(ins, mInstructions[j + 1]))
{
mInstructions[j] = mInstructions[j + 1];
j++;
}
if (i != j)
mInstructions[j] = ins;
}
i--;
}
i = 0;
while (i < mInstructions.Size())
{
// move stores up
if (mInstructions[i].mCode == IC_STORE)
{
InterInstruction ins(mInstructions[i]);
int j = i;
while (j > 0 && CanBypassStore(ins, mInstructions[j - 1]))
{
mInstructions[j] = mInstructions[j - 1];
j--;
}
if (i != j)
mInstructions[j] = ins;
}
i++;
}
bool changed;
do
{
int j = 0;
for (i = 0; i < mInstructions.Size(); i++)
{
if (mInstructions[i].mCode != IC_NONE)
{
mInstructions[j++] = mInstructions[i];
}
}
mInstructions.SetSize(j);
changed = false;
for (i = 0; i < mInstructions.Size(); i++)
{
if (i + 2 < mInstructions.Size())
{
if (mInstructions[i + 0].mTTemp >= 0 &&
mInstructions[i + 1].mCode == IC_LOAD_TEMPORARY && mInstructions[i + 1].mSTemp[0] == mInstructions[i].mTTemp &&
(mInstructions[i + 2].mCode == IC_RELATIONAL_OPERATOR || mInstructions[i + 2].mCode == IC_BINARY_OPERATOR) && mInstructions[i + 2].mSTemp[0] == mInstructions[i].mTTemp && mInstructions[i + 2].mSFinal[0])
{
mInstructions[i + 0].mTTemp = mInstructions[i + 1].mTTemp;
mInstructions[i + 1].mCode = IC_NONE;
mInstructions[i + 2].mSTemp[0] = mInstructions[i + 1].mTTemp;
mInstructions[i + 2].mSFinal[0] = false;
changed = true;
}
else if (mInstructions[i + 0].mTTemp >= 0 &&
mInstructions[i + 1].mCode == IC_LOAD_TEMPORARY && mInstructions[i + 1].mSTemp[0] == mInstructions[i].mTTemp &&
(mInstructions[i + 2].mCode == IC_RELATIONAL_OPERATOR || mInstructions[i + 2].mCode == IC_BINARY_OPERATOR) && mInstructions[i + 2].mSTemp[1] == mInstructions[i].mTTemp && mInstructions[i + 2].mSFinal[1])
{
mInstructions[i + 0].mTTemp = mInstructions[i + 1].mTTemp;
mInstructions[i + 1].mCode = IC_NONE;
mInstructions[i + 2].mSTemp[1] = mInstructions[i + 1].mTTemp;
mInstructions[i + 2].mSFinal[1] = false;
changed = true;
}
else if (
mInstructions[i + 0].mCode == IC_BINARY_OPERATOR && mInstructions[i + 0].mOperator == IA_SAR && mInstructions[i + 0].mSTemp[0] < 0 &&
mInstructions[i + 1].mCode == IC_BINARY_OPERATOR && mInstructions[i + 1].mOperator == IA_MUL && mInstructions[i + 1].mSTemp[0] < 0 &&
mInstructions[i + 1].mSTemp[1] == mInstructions[i + 0].mTTemp && mInstructions[i + 1].mSFinal[1] &&
(mInstructions[i + 1].mSIntConst[0] & (1LL << mInstructions[i + 0].mSIntConst[0])) == 0)
{
int shift = mInstructions[i + 0].mSIntConst[0];
mInstructions[i + 1].mSIntConst[0] >>= shift;
mInstructions[i + 0].mOperator = IA_AND;
mInstructions[i + 0].mSIntConst[0] = ~((1LL << shift) - 1);
}
else if (
mInstructions[i + 0].mCode == IC_BINARY_OPERATOR && mInstructions[i + 0].mOperator == IA_SAR && mInstructions[i + 0].mSTemp[0] < 0 &&
mInstructions[i + 1].mCode == IC_BINARY_OPERATOR && mInstructions[i + 1].mOperator == IA_MUL && mInstructions[i + 1].mSTemp[1] < 0 &&
mInstructions[i + 1].mSTemp[0] == mInstructions[i + 0].mTTemp && mInstructions[i + 1].mSFinal[0] &&
(mInstructions[i + 1].mSIntConst[1] & (1LL << mInstructions[i + 0].mSIntConst[0])) == 0)
{
int shift = mInstructions[i + 0].mSIntConst[0];
mInstructions[i + 1].mSIntConst[1] >>= shift;
mInstructions[i + 0].mOperator = IA_AND;
mInstructions[i + 0].mSIntConst[0] = ~((1LL << shift) - 1);
}
// Postincrement artifact
if (mInstructions[i + 0].mCode == IC_LOAD_TEMPORARY && mInstructions[i + 1].mCode == IC_BINARY_OPERATOR &&
mInstructions[i + 1].mSTemp[0] < 0 &&
mInstructions[i + 0].mSTemp[0] == mInstructions[i + 1].mSTemp[1] &&
mInstructions[i + 0].mSTemp[0] == mInstructions[i + 1].mTTemp)
{
InterInstruction ins = mInstructions[i + 1];
int ttemp = mInstructions[i + 1].mTTemp;
int k = i + 1;
while (k + 2 < mInstructions.Size() &&
mInstructions[k + 1].mSTemp[0] != ttemp &&
mInstructions[k + 1].mSTemp[1] != ttemp &&
mInstructions[k + 1].mSTemp[2] != ttemp &&
mInstructions[k + 1].mTTemp != ttemp)
{
mInstructions[k] = mInstructions[k + 1];
k++;
}
if (k > i + 1)
{
mInstructions[k] = ins;
changed = true;
}
}
}
}
} while (changed);
if (mTrueJump) mTrueJump->PeepholeOptimization();
if (mFalseJump) mFalseJump->PeepholeOptimization();
}
}
void InterCodeBasicBlock::CollectVariables(GrowingVariableArray& globalVars, GrowingVariableArray& localVars)
{
int i;
if (!mVisited)
{
mVisited = true;
for (i = 0; i < mInstructions.Size(); i++)
{
bool found = false;
switch (mInstructions[i].mCode)
{
case IC_STORE:
case IC_LOAD:
case IC_CONSTANT:
case IC_JSR:
if (mInstructions[i].mMemory == IM_LOCAL)
{
int size = mInstructions[i].mOperandSize + mInstructions[i].mIntValue;
if (size > localVars[mInstructions[i].mVarIndex].mSize)
localVars[mInstructions[i].mVarIndex].mSize = size;
if (mInstructions[i].mCode == IC_CONSTANT)
localVars[mInstructions[i].mVarIndex].mAliased = true;
}
break;
}
}
if (mTrueJump) mTrueJump->CollectVariables(globalVars, localVars);
if (mFalseJump) mFalseJump->CollectVariables(globalVars, localVars);
}
}
void InterCodeBasicBlock::CollectSimpleLocals(FastNumberSet& complexLocals, FastNumberSet& simpleLocals, GrowingTypeArray& localTypes)
{
int i;
if (!mVisited)
{
mVisited = true;
for (i = 0; i < mInstructions.Size(); i++)
{
mInstructions[i].CollectSimpleLocals(complexLocals, simpleLocals, localTypes);
}
if (mTrueJump) mTrueJump->CollectSimpleLocals(complexLocals, simpleLocals, localTypes);
if (mFalseJump) mFalseJump->CollectSimpleLocals(complexLocals, simpleLocals, localTypes);
}
}
void InterCodeBasicBlock::SimpleLocalToTemp(int vindex, int temp)
{
int i;
if (!mVisited)
{
mVisited = true;
for (i = 0; i < mInstructions.Size(); i++)
{
mInstructions[i].SimpleLocalToTemp(vindex, temp);
}
if (mTrueJump) mTrueJump->SimpleLocalToTemp(vindex, temp);
if (mFalseJump) mFalseJump->SimpleLocalToTemp(vindex, temp);
}
}
void InterCodeBasicBlock::CollectActiveTemporaries(FastNumberSet& set)
{
int i;
if (!mVisited)
{
mVisited = true;
for (i = 0; i < mInstructions.Size(); i++)
{
mInstructions[i].CollectActiveTemporaries(set);
}
if (mTrueJump) mTrueJump->CollectActiveTemporaries(set);
if (mFalseJump) mFalseJump->CollectActiveTemporaries(set);
}
}
void InterCodeBasicBlock::ShrinkActiveTemporaries(FastNumberSet& set, GrowingTypeArray& temporaries)
{
int i;
if (!mVisited)
{
mVisited = true;
for (i = 0; i < mInstructions.Size(); i++)
{
mInstructions[i].ShrinkActiveTemporaries(set, temporaries);
}
if (mTrueJump) mTrueJump->ShrinkActiveTemporaries(set, temporaries);
if (mFalseJump) mFalseJump->ShrinkActiveTemporaries(set, temporaries);
}
}
void InterCodeBasicBlock::Disassemble(FILE* file, bool dumpSets)
{
int i;
if (!mVisited)
{
mVisited = true;
fprintf(file, "L%d: (%d)\n", mIndex, mNumEntries);
if (dumpSets)
{
fprintf(file, "Entry required temps : ");
for (i = 0; i < mEntryRequiredTemps.Size(); i++)
{
if (mEntryRequiredTemps[i])
fprintf(file, "#");
else
fprintf(file, "-");
}
fprintf(file, "\n\n");
}
for (i = 0; i < mInstructions.Size(); i++)
{
if (mInstructions[i].mCode != IT_NONE)
{
fprintf(file, "%04x\t", i);
mInstructions[i].Disassemble(file);
}
}
if (mTrueJump) fprintf(file, "\t\t==> %d\n", mTrueJump->mIndex);
if (mFalseJump) fprintf(file, "\t\t==> %d\n", mFalseJump->mIndex);
if (mTrueJump) mTrueJump->Disassemble(file, dumpSets);
if (mFalseJump) mFalseJump->Disassemble(file, dumpSets);
}
}
InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & location, const Ident* ident)
: mTemporaries(IT_NONE), mBlocks(nullptr), mLocation(location), mTempOffset(-1),
mRenameTable(-1), mRenameUnionTable(-1), mGlobalRenameTable(-1),
mValueForwardingTable(NULL), mLocalVars(InterVariable()), mModule(mod),
mIdent(ident), mNativeProcedure(false), mLeafProcedure(false)
{
mID = mModule->mProcedures.Size();
mModule->mProcedures.Push(this);
}
InterCodeProcedure::~InterCodeProcedure(void)
{
}
void InterCodeProcedure::ResetVisited(void)
{
int i;
for (i = 0; i < mBlocks.Size(); i++)
mBlocks[i]->mVisited = false;
}
void InterCodeProcedure::Append(InterCodeBasicBlock* block)
{
block->mIndex = mBlocks.Size();
mBlocks.Push(block);
}
int InterCodeProcedure::AddTemporary(InterType type)
{
int temp = mTemporaries.Size();
mTemporaries.Push(type);
return temp;
}
void InterCodeProcedure::DisassembleDebug(const char* name)
{
Disassemble(name);
}
void InterCodeProcedure::BuildTraces(void)
{
// Count number of entries
//
ResetVisited();
for (int i = 0; i < mBlocks.Size(); i++)
mBlocks[i]->mNumEntries = 0;
mBlocks[0]->CollectEntries();
//
// Build traces
//
ResetVisited();
mBlocks[0]->GenerateTraces();
ResetVisited();
for (int i = 0; i < mBlocks.Size(); i++)
mBlocks[i]->mNumEntries = 0;
mBlocks[0]->CollectEntries();
DisassembleDebug("BuildTraces");
}
void InterCodeProcedure::BuildDataFlowSets(void)
{
int numTemps = mTemporaries.Size();
//
// Build set with local provided/required temporaries
//
ResetVisited();
mBlocks[0]->BuildLocalTempSets(numTemps, numFixedTemporaries);
//
// Build set of globaly provided temporaries
//
ResetVisited();
mBlocks[0]->BuildGlobalProvidedTempSet(NumberSet(numTemps));
//
// Build set of globaly required temporaries, might need
// multiple iterations until it stabilizes
//
NumberSet totalRequired(numTemps);
do {
ResetVisited();
} while (mBlocks[0]->BuildGlobalRequiredTempSet(totalRequired));
}
void InterCodeProcedure::RenameTemporaries(void)
{
int numTemps = mTemporaries.Size();
//
// Now we can rename temporaries to remove false dependencies
//
mRenameTable.SetSize(numTemps, true);
int i, j, numRename;
numRename = numFixedTemporaries;
for (i = 0; i < numRename; i++)
mRenameTable[i] = i;
//
// First localy rename all temporaries
//
ResetVisited();
mBlocks[0]->LocalRenameRegister(mRenameTable, numRename, numFixedTemporaries);
DisassembleDebug("local renamed temps");
//
// Build a union find data structure for rename merging, this
// merges renames temporaries back, that have been renamed differently
// on separate paths.
//
mRenameUnionTable.SetSize(numRename);
for (i = 0; i < numRename; i++)
mRenameUnionTable[i] = i;
//
// Build global rename table using a union/find algorithm
//
mRenameTable.SetSize(numTemps, true);
ResetVisited();
mBlocks[0]->BuildGlobalRenameRegisterTable(mRenameTable, mRenameUnionTable);
//
// Now calculate the global temporary IDs for all local ids
//
int numRenamedTemps;
mGlobalRenameTable.SetSize(numRename, true);
for (i = 0; i < numFixedTemporaries; i++)
mGlobalRenameTable[i] = i;
numRenamedTemps = numFixedTemporaries;
for (i = numFixedTemporaries; i < numRename; i++)
{
j = Find(mRenameUnionTable, i);
if (mGlobalRenameTable[j] < 0)
mGlobalRenameTable[j] = numRenamedTemps++;
mGlobalRenameTable[i] = mGlobalRenameTable[j];
}
mTemporaries.SetSize(numRenamedTemps);
//
// Set global temporary IDs
//
ResetVisited();
mBlocks[0]->GlobalRenameRegister(mGlobalRenameTable, mTemporaries);
numTemps = numRenamedTemps;
DisassembleDebug("global renamed temps");
}
void InterCodeProcedure::TempForwarding(void)
{
int numTemps = mTemporaries.Size();
ValueSet valueSet;
FastNumberSet tvalidSet(numTemps);
//
// Now remove needless temporary moves, that apear due to
// stack evaluation
//
mTempForwardingTable.SetSize(numTemps);
mTempForwardingTable.Reset();
ResetVisited();
mBlocks[0]->PerformTempForwarding(mTempForwardingTable);
DisassembleDebug("temp forwarding");
}
void InterCodeProcedure::RemoveUnusedInstructions(void)
{
int numTemps = mTemporaries.Size();
do {
ResetVisited();
mBlocks[0]->BuildLocalTempSets(numTemps, numFixedTemporaries);
ResetVisited();
mBlocks[0]->BuildGlobalProvidedTempSet(NumberSet(numTemps));
NumberSet totalRequired2(numTemps);
do {
ResetVisited();
} while (mBlocks[0]->BuildGlobalRequiredTempSet(totalRequired2));
ResetVisited();
} while (mBlocks[0]->RemoveUnusedResultInstructions(numFixedTemporaries));
}
void InterCodeProcedure::Close(void)
{
int i, j, k, start;
GrowingTypeArray tstack(IT_NONE);
_CrtCheckMemory();
numFixedTemporaries = 0;
DisassembleDebug("start");
BuildTraces();
ResetVisited();
mLeafProcedure = mBlocks[0]->IsLeafProcedure();
if (!mLeafProcedure)
{
int size = 0;
ResetVisited();
mBlocks[0]->CollectOuterFrame(0, size);
mCommonFrameSize = size;
}
else
mCommonFrameSize = 0;
BuildDataFlowSets();
RenameTemporaries();
TempForwarding();
int numTemps = mTemporaries.Size();
//
// Find all local variables that are never aliased
//
GrowingIntArray localTable(-1);
ResetVisited();
mBlocks[0]->CollectLocalAddressTemps(localTable);
int nlocals = 0;
for (int i = 0; i < localTable.Size(); i++)
if (localTable[i] + 1 > nlocals)
nlocals = localTable[i] + 1;
mLocalAliasedSet.Reset(nlocals);
ResetVisited();
mBlocks[0]->MarkAliasedLocalTemps(localTable, mLocalAliasedSet);
//
// Now forward constant values
//
ValueSet valueSet;
FastNumberSet tvalidSet(numTemps);
mValueForwardingTable.SetSize(numTemps, true);
ResetVisited();
mBlocks[0]->PerformValueForwarding(mValueForwardingTable, valueSet, tvalidSet, mLocalAliasedSet);
DisassembleDebug("value forwarding");
mValueForwardingTable.Clear();
ResetVisited();
mBlocks[0]->PerformMachineSpecificValueUsageCheck(mValueForwardingTable, tvalidSet);
DisassembleDebug("machine value forwarding");
//
// Now remove needless temporary moves, that apear due to
// stack evaluation
//
mTempForwardingTable.Reset();
mTempForwardingTable.SetSize(numTemps);
ResetVisited();
mBlocks[0]->PerformTempForwarding(mTempForwardingTable);
DisassembleDebug("temp forwarding 2");
//
// Now remove unused instructions
//
do {
ResetVisited();
mBlocks[0]->BuildLocalTempSets(numTemps, numFixedTemporaries);
ResetVisited();
mBlocks[0]->BuildGlobalProvidedTempSet(NumberSet(numTemps));
NumberSet totalRequired2(numTemps);
do {
ResetVisited();
} while (mBlocks[0]->BuildGlobalRequiredTempSet(totalRequired2));
ResetVisited();
} while (mBlocks[0]->RemoveUnusedResultInstructions(numFixedTemporaries));
DisassembleDebug("removed unused instructions");
ResetVisited();
mBlocks[0]->CollectVariables(mModule->mGlobalVars, mLocalVars);
if (mLocalVars.Size() > 0)
{
for (int i = 0; i < mLocalVars.Size(); i++)
{
if (mLocalAliasedSet[i])
mLocalVars[i].mAliased = true;
}
//
// Now remove unused stores
//
do {
ResetVisited();
mBlocks[0]->BuildLocalVariableSets(mLocalVars);
ResetVisited();
mBlocks[0]->BuildGlobalProvidedVariableSet(mLocalVars, NumberSet(mLocalVars.Size()));
NumberSet totalRequired2(mLocalVars.Size());
do {
ResetVisited();
} while (mBlocks[0]->BuildGlobalRequiredVariableSet(mLocalVars, totalRequired2));
ResetVisited();
} while (mBlocks[0]->RemoveUnusedStoreInstructions(mLocalVars));
DisassembleDebug("removed unused local stores");
}
//
// Promote local variables to temporaries
//
FastNumberSet simpleLocals(nlocals), complexLocals(nlocals);
GrowingTypeArray localTypes(IT_NONE);
ResetVisited();
mBlocks[0]->CollectSimpleLocals(complexLocals, simpleLocals, localTypes);
for (int i = 0; i < simpleLocals.Num(); i++)
{
int vi = simpleLocals.Element(i);
if (!complexLocals[vi])
{
ResetVisited();
mBlocks[0]->SimpleLocalToTemp(vi, AddTemporary(localTypes[vi]));
}
}
DisassembleDebug("local variables to temps");
BuildTraces();
BuildDataFlowSets();
RenameTemporaries();
TempForwarding();
//
// Now remove unused instructions
//
RemoveUnusedInstructions();
DisassembleDebug("removed unused instructions 2");
ResetVisited();
mBlocks[0]->PeepholeOptimization();
TempForwarding();
RemoveUnusedInstructions();
DisassembleDebug("Peephole optimized");
FastNumberSet activeSet(numTemps);
//
// And remove unused temporaries
//
for (i = 0; i < numFixedTemporaries; i++)
activeSet += i;
ResetVisited();
mBlocks[0]->CollectActiveTemporaries(activeSet);
mTemporaries.SetSize(activeSet.Num());
ResetVisited();
mBlocks[0]->ShrinkActiveTemporaries(activeSet, mTemporaries);
MapVariables();
DisassembleDebug("mapped variabled");
_CrtCheckMemory();
}
void InterCodeProcedure::MapVariables(void)
{
ResetVisited();
mBlocks[0]->MapVariables(mModule->mGlobalVars, mLocalVars);
mLocalSize = 0;
for (int i = 0; i < mLocalVars.Size(); i++)
{
if (mLocalVars[i].mUsed)
{
mLocalVars[i].mOffset = mLocalSize;
mLocalSize += mLocalVars[i].mSize;
}
}
}
void InterCodeProcedure::ReduceTemporaries(void)
{
NumberSet* collisionSet;
int i, j, numRenamedTemps;
int numTemps = mTemporaries.Size();
ResetVisited();
mBlocks[0]->BuildLocalTempSets(numTemps, numFixedTemporaries);
ResetVisited();
mBlocks[0]->BuildGlobalProvidedTempSet(NumberSet(numTemps));
NumberSet totalRequired2(numTemps);
do {
ResetVisited();
} while (mBlocks[0]->BuildGlobalRequiredTempSet(totalRequired2));
collisionSet = new NumberSet[numTemps];
for (i = 0; i < numTemps; i++)
collisionSet[i].Reset(numTemps);
ResetVisited();
mBlocks[0]->BuildCollisionTable(collisionSet);
mRenameTable.SetSize(numTemps, true);
for (i = 0; i < numFixedTemporaries; i++)
mRenameTable[i] = i;
numRenamedTemps = numFixedTemporaries;
NumberSet usedTemps(numTemps);
for (i = numFixedTemporaries; i < numTemps; i++)
{
usedTemps.Clear();
for (j = numFixedTemporaries; j < numTemps; j++)
{
if (mRenameTable[j] >= 0 && (collisionSet[i][j] || !TypeCompatible(mTemporaries[j], mTemporaries[i])))
{
usedTemps += mRenameTable[j];
}
}
j = numFixedTemporaries;
while (usedTemps[j])
j++;
mRenameTable[i] = j;
if (j >= numRenamedTemps) numRenamedTemps = j + 1;
}
mTemporaries.SetSize(numRenamedTemps);
ResetVisited();
mBlocks[0]->GlobalRenameRegister(mRenameTable, mTemporaries);
delete[] collisionSet;
ResetVisited();
mBlocks[0]->BuildLocalTempSets(numRenamedTemps, numFixedTemporaries);
ResetVisited();
mBlocks[0]->BuildGlobalProvidedTempSet(NumberSet(numRenamedTemps));
NumberSet totalRequired3(numRenamedTemps);
do {
ResetVisited();
} while (mBlocks[0]->BuildGlobalRequiredTempSet(totalRequired3));
mTempOffset.SetSize(0);
int offset = 0;
if (!mLeafProcedure)
offset += 16;
for (int i = 0; i < mTemporaries.Size(); i++)
{
mTempOffset.Push(offset);
switch (mTemporaries[i])
{
case IT_FLOAT:
offset += 4;
break;
default:
offset += 2;
break;
}
}
mTempSize = offset;
}
void InterCodeProcedure::Disassemble(const char* name, bool dumpSets)
{
FILE* file;
static bool initial = true;
if (!initial)
{
fopen_s(&file, "r:\\cldiss.txt", "a");
}
else
{
fopen_s(&file, "r:\\cldiss.txt", "w");
initial = false;
}
if (file)
{
fprintf(file, "--------------------------------------------------------------------\n");
fprintf(file, "%s : %s:%d\n", name, mLocation.mFileName, mLocation.mLine);
ResetVisited();
mBlocks[0]->Disassemble(file, dumpSets);
fclose(file);
}
}
InterCodeModule::InterCodeModule(void)
: mGlobalVars(InterVariable()), mProcedures(nullptr)
{
}
InterCodeModule::~InterCodeModule(void)
{
}