Add intermediat code select operator

This commit is contained in:
drmortalwombat 2022-07-02 14:53:00 +02:00
parent ba661759fb
commit bcc59a9afb
11 changed files with 538 additions and 135 deletions

View File

@ -192,6 +192,21 @@ The character map for string and char constants can be changed with a pragma to
The compiler can be provided with additional information using the built in function __assume(cond). This can be useful to mark unreachable code using __assume(false) for e.g. the default of a switch statement. Another good option is to limit the value range of arguments to allow the compiler using byte operations without the need for integer promotion. The compiler can be provided with additional information using the built in function __assume(cond). This can be useful to mark unreachable code using __assume(false) for e.g. the default of a switch statement. Another good option is to limit the value range of arguments to allow the compiler using byte operations without the need for integer promotion.
### Loop unrolling
Loop unrolling on 6502 is hard to decide for the compiler. Memory is usually scarce, so it only does it in realy obvious cases (and in less obbious cases for O3). On the other hand unrolling is required to get good performance in e.g. scrolling code. Therefore the compiler offers an unrolling pragma, that can be used to specifiy the amount of unrolling either as a number or "full" for complete.
The following code scrolls the screen to the left, and completely unrolls the inner vertical loop.
for(char x=0; x<39; x++)
{
#pragma unroll(full)
for(char y=0; y<25; y++)
screen[y][x] = screen[y][x + 1];
}
### Marking functions as native ### Marking functions as native
Routines can be marked to be compiled to 6502 machine code with the native pragma: Routines can be marked to be compiled to 6502 machine code with the native pragma:

View File

@ -23,6 +23,7 @@ enum ErrorID
EWARN_NOT_INTERRUPT_SAFE, EWARN_NOT_INTERRUPT_SAFE,
EWARN_BOOL_SHORTCUT, EWARN_BOOL_SHORTCUT,
EWARN_OPTIMIZER_LOCKED, EWARN_OPTIMIZER_LOCKED,
EWARN_LOOP_UNROLL_IGNORED,
EERR_GENERIC = 3000, EERR_GENERIC = 3000,
EERR_FILE_NOT_FOUND, EERR_FILE_NOT_FOUND,

View File

@ -2787,6 +2787,7 @@ bool InterInstruction::RemoveUnusedResultInstructions(InterInstruction* pre, Num
{ {
// previous instruction produced result, but it is not needed here // previous instruction produced result, but it is not needed here
pre->mDst.mTemp = mDst.mTemp; pre->mDst.mTemp = mDst.mTemp;
pre->mSingleAssignment = mSingleAssignment;
mCode = IC_NONE; mCode = IC_NONE;
mDst.mTemp = -1; mDst.mTemp = -1;
@ -3513,6 +3514,9 @@ void InterInstruction::Disassemble(FILE* file)
case IC_TYPECAST: case IC_TYPECAST:
fprintf(file, "CAST"); fprintf(file, "CAST");
break; break;
case IC_SELECT:
fprintf(file, "SELECT");
break;
case IC_CONSTANT: case IC_CONSTANT:
fprintf(file, "CONST"); fprintf(file, "CONST");
break; break;
@ -4100,6 +4104,16 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
} }
break; break;
case IC_SELECT:
for(int i=0; i<3; i++)
{
if (ins->mSrc[i].mTemp >= 0 && tvalue[ins->mSrc[i].mTemp] && tvalue[ins->mSrc[i].mTemp]->mCode == IC_CONSTANT)
{
ins->mSrc[i] = tvalue[ins->mSrc[i].mTemp]->mConst;
ins->mSrc[i].mTemp = -1;
}
}
break;
case IC_RETURN_VALUE: case IC_RETURN_VALUE:
if (ins->mSrc[0].mTemp >= 0 && tvalue[ins->mSrc[0].mTemp] && tvalue[ins->mSrc[0].mTemp]->mCode == IC_CONSTANT) if (ins->mSrc[0].mTemp >= 0 && tvalue[ins->mSrc[0].mTemp] && tvalue[ins->mSrc[0].mTemp]->mCode == IC_CONSTANT)
{ {
@ -5238,6 +5252,10 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
case IC_LOAD_TEMPORARY: case IC_LOAD_TEMPORARY:
vr = ins->mSrc[0].mRange; vr = ins->mSrc[0].mRange;
break; break;
case IC_SELECT:
vr = ins->mSrc[1].mRange;
vr.Merge(ins->mSrc[0].mRange, false, false);
break;
case IC_UNARY_OPERATOR: case IC_UNARY_OPERATOR:
{ {
switch (ins->mOperator) switch (ins->mOperator)
@ -6911,7 +6929,7 @@ bool InterCodeBasicBlock::MergeIndexedLoadStore(const GrowingInstructionPtrArra
mInstructions[j] = ins; mInstructions[j] = ins;
} }
} }
#if 1
for (int i = 0; i < mInstructions.Size(); i++) for (int i = 0; i < mInstructions.Size(); i++)
{ {
InterInstruction* ins = mInstructions[i]; InterInstruction* ins = mInstructions[i];
@ -6943,7 +6961,7 @@ bool InterCodeBasicBlock::MergeIndexedLoadStore(const GrowingInstructionPtrArra
} }
} }
if (bins != lins && ins->mSrc[pi].mIntConst + lins->mSrc[1].mIntConst - bins->mSrc[1].mIntConst < 252) if (bins != lins && ins->mSrc[pi].mIntConst + lins->mSrc[1].mIntConst - bins->mSrc[1].mIntConst < 252 && ins->mSrc[pi].mIntConst + lins->mSrc[1].mIntConst - bins->mSrc[1].mIntConst >= 0)
{ {
ins->mSrc[pi].mTemp = bins->mDst.mTemp; ins->mSrc[pi].mTemp = bins->mDst.mTemp;
ins->mSrc[pi].mIntConst += lins->mSrc[1].mIntConst - bins->mSrc[1].mIntConst; ins->mSrc[pi].mIntConst += lins->mSrc[1].mIntConst - bins->mSrc[1].mIntConst;
@ -6969,6 +6987,7 @@ bool InterCodeBasicBlock::MergeIndexedLoadStore(const GrowingInstructionPtrArra
ltvalue[dtemp] = ins; ltvalue[dtemp] = ins;
} }
} }
#endif
if (mTrueJump && mTrueJump->MergeIndexedLoadStore(ltvalue)) if (mTrueJump && mTrueJump->MergeIndexedLoadStore(ltvalue))
changed = true; changed = true;
@ -7238,7 +7257,7 @@ bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArra
{ {
InterInstruction* pins = ltvalue[ins->mSrc[1].mTemp]; InterInstruction* pins = ltvalue[ins->mSrc[1].mTemp];
if (pins->mCode == IC_LEA && pins->mSrc[0].mTemp < 0) if (pins->mCode == IC_LEA && pins->mSrc[0].mTemp < 0 && ins->mSrc[1].mIntConst + pins->mSrc[0].mIntConst >= 0)
{ {
ins->mSrc[1].Forward(pins->mSrc[1]); ins->mSrc[1].Forward(pins->mSrc[1]);
pins->mSrc[1].mFinal = false; pins->mSrc[1].mFinal = false;
@ -7254,7 +7273,7 @@ bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArra
{ {
InterInstruction* pins = ltvalue[ins->mSrc[0].mTemp]; InterInstruction* pins = ltvalue[ins->mSrc[0].mTemp];
if (pins->mCode == IC_LEA && pins->mSrc[0].mTemp < 0) if (pins->mCode == IC_LEA && pins->mSrc[0].mTemp < 0 && ins->mSrc[0].mIntConst + pins->mSrc[0].mIntConst >= 0)
{ {
ins->mSrc[0].Forward(pins->mSrc[1]); ins->mSrc[0].Forward(pins->mSrc[1]);
pins->mSrc[1].mFinal = false; pins->mSrc[1].mFinal = false;
@ -8426,6 +8445,51 @@ bool InterCodeBasicBlock::ForwardDiamondMovedTemp(void)
{ {
if (tblock->mNumEntries == 1 && fblock->mNumEntries == 2) if (tblock->mNumEntries == 1 && fblock->mNumEntries == 2)
{ {
if (tblock->mInstructions.Size() == 2 && tblock->mInstructions[0]->mCode == IC_LEA && tblock->mInstructions[0]->mSrc[0].mTemp < 0 && tblock->mInstructions[0]->mSrc[1].mTemp >= 0)
{
InterInstruction* lins = tblock->mInstructions[0];
// Single "lea temp, imm" in diamond
int i = mInstructions.Size();
while (i > 0 && mInstructions[i - 1]->mDst.mTemp != lins->mSrc[1].mTemp)
i--;
if (i > 0)
{
i--;
InterInstruction* tins = mInstructions[i];
if (mInstructions[i]->mCode == IC_LOAD_TEMPORARY)
{
int offset = 0;
bool fail = false;
for (int j = i + 1; j < mInstructions.Size(); j++)
{
if (mInstructions[j]->mDst.mTemp == tins->mSrc[0].mTemp)
{
if (mInstructions[j]->mCode == IC_LEA && mInstructions[j]->mSrc[1].mTemp == tins->mSrc[0].mTemp && mInstructions[j]->mSrc[0].mTemp < 0)
{
offset += mInstructions[j]->mSrc[0].mIntConst;
}
else
fail = true;
}
}
if (!fail)
{
mExitRequiredTemps += tins->mSrc[0].mTemp;
tblock->mEntryRequiredTemps += tins->mSrc[0].mTemp;
lins->mSrc[1].mTemp = tins->mSrc[0].mTemp;
lins->mSrc[0].mIntConst -= offset;
changed = true;
}
}
}
}
for (int i = mInstructions.Size() - 1; i >= 0; i--) for (int i = mInstructions.Size() - 1; i >= 0; i--)
{ {
InterInstruction* mins = mInstructions[i]; InterInstruction* mins = mInstructions[i];
@ -8792,6 +8856,91 @@ bool InterCodeBasicBlock::IsLeafProcedure(void)
} }
void InterCodeBasicBlock::ExpandSelect(InterCodeProcedure* proc)
{
if (!mVisited)
{
mVisited = true;
int i = 0;
while (i < mInstructions.Size() && mInstructions[i]->mCode != IC_SELECT)
i++;
if (i < mInstructions.Size())
{
InterInstruction* sins = mInstructions[i];
InterCodeBasicBlock* tblock = new InterCodeBasicBlock();
proc->Append(tblock);
InterCodeBasicBlock* fblock = new InterCodeBasicBlock();
proc->Append(fblock);
InterCodeBasicBlock* eblock = new InterCodeBasicBlock();
proc->Append(eblock);
for (int j = i + 1; j < mInstructions.Size(); j++)
eblock->mInstructions.Push(mInstructions[j]);
eblock->Close(mTrueJump, mFalseJump);
mInstructions.SetSize(i);
InterInstruction* bins = new InterInstruction();
bins->mCode = IC_BRANCH;
bins->mSrc[0] = sins->mSrc[2];
mInstructions.Push(bins);
InterInstruction* tins = new InterInstruction();
if (sins->mSrc[1].mTemp < 0)
{
tins->mCode = IC_CONSTANT;
tins->mConst = sins->mSrc[1];
}
else
{
tins->mCode = IC_LOAD_TEMPORARY;
tins->mSrc[0] = sins->mSrc[1];
}
tins->mDst = sins->mDst;
InterInstruction* fins = new InterInstruction();
if (sins->mSrc[0].mTemp < 0)
{
fins->mCode = IC_CONSTANT;
fins->mConst = sins->mSrc[0];
}
else
{
fins->mCode = IC_LOAD_TEMPORARY;
fins->mSrc[0] = sins->mSrc[0];
}
fins->mDst = sins->mDst;
tblock->mInstructions.Push(tins);
InterInstruction* jins = new InterInstruction();
jins->mCode = IC_JUMP;
tblock->mInstructions.Push(jins);
tblock->Close(eblock, nullptr);
fblock->mInstructions.Push(fins);
jins = new InterInstruction();
jins->mCode = IC_JUMP;
fblock->mInstructions.Push(jins);
fblock->Close(eblock, nullptr);
mTrueJump = tblock;
mFalseJump = fblock;
}
if (mTrueJump)
mTrueJump->ExpandSelect(proc);
if (mFalseJump)
mFalseJump->ExpandSelect(proc);
}
}
void InterCodeBasicBlock::SplitBranches(InterCodeProcedure* proc) void InterCodeBasicBlock::SplitBranches(InterCodeProcedure* proc)
{ {
if (!mVisited) if (!mVisited)
@ -9893,6 +10042,7 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
} while (changed); } while (changed);
GrowingArray<InterInstructionPtr> indexins(nullptr); GrowingArray<InterInstructionPtr> indexins(nullptr);
GrowingArray<InterInstructionPtr> pindexins(nullptr);
int j = 0; int j = 0;
for (int i = 0; i < mInstructions.Size(); i++) for (int i = 0; i < mInstructions.Size(); i++)
@ -10028,6 +10178,27 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
} }
else if (ins->mCode == IC_LEA && (ins->mSrc[1].mTemp < 0 || dep[ins->mSrc[1].mTemp] == DEP_UNKNOWN || dep[ins->mSrc[1].mTemp] == DEP_DEFINED) && dep[ins->mSrc[0].mTemp] == DEP_INDEX_DERIVED) else if (ins->mCode == IC_LEA && (ins->mSrc[1].mTemp < 0 || dep[ins->mSrc[1].mTemp] == DEP_UNKNOWN || dep[ins->mSrc[1].mTemp] == DEP_DEFINED) && dep[ins->mSrc[0].mTemp] == DEP_INDEX_DERIVED)
{ {
#if 1
int k = 0;
while (k < pindexins.Size() && !(
ins->mSrc[0].mTemp == pindexins[k]->mSrc[0].mTemp &&
ins->mSrc[1].mTemp == pindexins[k]->mSrc[1].mTemp &&
ins->mSrc[1].mMemory == pindexins[k]->mSrc[1].mMemory &&
ins->mSrc[1].mVarIndex == pindexins[k]->mSrc[1].mVarIndex))
k++;
if (k < pindexins.Size() && ins->mSrc[1].mIntConst >= pindexins[k]->mSrc[1].mIntConst)
{
ins->mSrc[0].mTemp = -1;
ins->mSrc[0].mIntConst = ins->mSrc[1].mIntConst - pindexins[k]->mSrc[1].mIntConst;
ins->mSrc[1].mTemp = pindexins[k]->mDst.mTemp;
ins->mSrc[1].mMemory = IM_INDIRECT;
ins->mSrc[1].mIntConst = 0;
mInstructions[j++] = ins;
}
else
#endif
{
indexStep[ins->mDst.mTemp] = indexStep[ins->mSrc[0].mTemp]; indexStep[ins->mDst.mTemp] = indexStep[ins->mSrc[0].mTemp];
indexBase[ins->mDst.mTemp] = 0; indexBase[ins->mDst.mTemp] = 0;
@ -10053,10 +10224,14 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
dins->mSrc[1].mIntConst = 0; dins->mSrc[1].mIntConst = 0;
dins->mSrc[0].mType = IT_INT16; dins->mSrc[0].mType = IT_INT16;
dins->mSrc[0].mTemp = -1; dins->mSrc[0].mTemp = -1;
dins->mSrc[0].mIntConst = - indexStep[ins->mSrc[0].mTemp]; dins->mSrc[0].mIntConst = -indexStep[ins->mSrc[0].mTemp];
tailBlock->mInstructions.Insert(0, dins); tailBlock->mInstructions.Insert(0, dins);
} }
indexins.Push(ains); indexins.Push(ains);
if (indexStep[ins->mSrc[0].mTemp] > 1)
pindexins.Push(ins);
}
} }
} }
else if (ins->mDst.mTemp >= 0 && dep[ins->mDst.mTemp] == DEP_INDEX_EXTENDED) else if (ins->mDst.mTemp >= 0 && dep[ins->mDst.mTemp] == DEP_INDEX_EXTENDED)
@ -10130,6 +10305,7 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
{ {
int dt = ins->mDst.mTemp, st = ins->mSrc[0].mTemp; int dt = ins->mDst.mTemp, st = ins->mSrc[0].mTemp;
int toffset = 0;
int j = i + 1; int j = i + 1;
while (j < mInstructions.Size()) while (j < mInstructions.Size())
{ {
@ -10140,7 +10316,12 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
else if (cins->mCode == IC_LOAD_TEMPORARY && cins->mSrc[0].mTemp == st && cins->mSrc[0].mFinal) else if (cins->mCode == IC_LOAD_TEMPORARY && cins->mSrc[0].mTemp == st && cins->mSrc[0].mFinal)
st = cins->mDst.mTemp; st = cins->mDst.mTemp;
else if (cins->mDst.mTemp == st) else if (cins->mDst.mTemp == st)
{
if (cins->mCode == IC_LEA && cins->mSrc[1].mTemp == st && cins->mSrc[0].mTemp < 0)
toffset += cins->mSrc[0].mIntConst;
else
break; break;
}
j++; j++;
} }
@ -10148,6 +10329,18 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
if (j == mInstructions.Size()) if (j == mInstructions.Size())
{ {
ins->mSrc[0].mTemp = st; ins->mSrc[0].mTemp = st;
if (toffset != 0)
{
if (ins->mDst.mType == IT_POINTER)
{
ins->mCode = IC_LEA;
ins->mNumOperands = 2;
ins->mSrc[1] = ins->mSrc[0];
ins->mSrc[0].mTemp = -1;
ins->mSrc[0].mType = IT_INT16;
ins->mSrc[0].mIntConst = -toffset;
}
}
tailBlock->mInstructions.Insert(0, ins); tailBlock->mInstructions.Insert(0, ins);
mInstructions.Remove(i); mInstructions.Remove(i);
} }
@ -10700,6 +10893,7 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati
mInstructions[i + 0]->mDst.mTemp = mInstructions[i + 1]->mDst.mTemp; mInstructions[i + 0]->mDst.mTemp = mInstructions[i + 1]->mDst.mTemp;
mInstructions[i + 1]->mDst.mTemp = mInstructions[i + 1]->mSrc[0].mTemp; mInstructions[i + 1]->mDst.mTemp = mInstructions[i + 1]->mSrc[0].mTemp;
mInstructions[i + 1]->mSrc[0].mTemp = mInstructions[i + 0]->mDst.mTemp; mInstructions[i + 1]->mSrc[0].mTemp = mInstructions[i + 0]->mDst.mTemp;
mInstructions[i + 0]->mSingleAssignment = mInstructions[i + 1]->mSingleAssignment;
changed = true; changed = true;
} }
#endif #endif
@ -11293,7 +11487,7 @@ void InterCodeProcedure::DisassembleDebug(const char* name)
void InterCodeProcedure::BuildTraces(bool expand, bool dominators, bool compact) void InterCodeProcedure::BuildTraces(bool expand, bool dominators, bool compact)
{ {
// Count number of entries // Count number of entries
// //
ResetVisited(); ResetVisited();
for (int i = 0; i < mBlocks.Size(); i++) for (int i = 0; i < mBlocks.Size(); i++)
{ {
@ -11702,6 +11896,11 @@ void InterCodeProcedure::MergeIndexedLoadStore(void)
ResetVisited(); ResetVisited();
} while (mEntryBlock->MergeIndexedLoadStore(silvalues)); } while (mEntryBlock->MergeIndexedLoadStore(silvalues));
BuildDataFlowSets();
TempForwarding();
RemoveUnusedInstructions();
DisassembleDebug("MergeIndexedLoadStore"); DisassembleDebug("MergeIndexedLoadStore");
} }
@ -11743,6 +11942,25 @@ void InterCodeProcedure::SimplifyIntegerNumeric(FastNumberSet& activeSet)
DisassembleDebug("SimplifyIntegerNumeric"); DisassembleDebug("SimplifyIntegerNumeric");
} }
void InterCodeProcedure::ExpandSelect(void)
{
#if 1
ResetVisited();
mEntryBlock->ExpandSelect(this);
ResetVisited();
for (int i = 0; i < mBlocks.Size(); i++)
mBlocks[i]->mNumEntries = 0;
mEntryBlock->CollectEntries();
ResetEntryBlocks();
ResetVisited();
mEntryBlock->CollectEntryBlocks(nullptr);
DisassembleDebug("ExpandSelect");
#endif
}
void InterCodeProcedure::EliminateAliasValues() void InterCodeProcedure::EliminateAliasValues()
{ {
GrowingInstructionPtrArray eivalues(nullptr); GrowingInstructionPtrArray eivalues(nullptr);
@ -11970,6 +12188,12 @@ void InterCodeProcedure::Close(void)
#endif #endif
CheckUsedDefinedTemps(); CheckUsedDefinedTemps();
ExpandSelect();
BuildDataFlowSets();
CheckUsedDefinedTemps();
SingleAssignmentForwarding(); SingleAssignmentForwarding();
CheckUsedDefinedTemps(); CheckUsedDefinedTemps();

View File

@ -36,6 +36,7 @@ enum InterCode
IC_RETURN, IC_RETURN,
IC_ASSEMBLER, IC_ASSEMBLER,
IC_JUMPF, IC_JUMPF,
IC_SELECT,
IC_UNREACHABLE IC_UNREACHABLE
}; };
@ -478,6 +479,8 @@ public:
InterCodeBasicBlock* BuildLoopPrefix(InterCodeProcedure * proc); InterCodeBasicBlock* BuildLoopPrefix(InterCodeProcedure * proc);
void BuildLoopSuffix(InterCodeProcedure* proc); void BuildLoopSuffix(InterCodeProcedure* proc);
void ExpandSelect(InterCodeProcedure* proc);
void SplitBranches(InterCodeProcedure* proc); void SplitBranches(InterCodeProcedure* proc);
void FollowJumps(void); void FollowJumps(void);
@ -567,6 +570,7 @@ protected:
void MergeIndexedLoadStore(void); void MergeIndexedLoadStore(void);
void EliminateAliasValues(); void EliminateAliasValues();
void LoadStoreForwarding(InterMemory paramMemory); void LoadStoreForwarding(InterMemory paramMemory);
void ExpandSelect(void);
void MergeBasicBlocks(void); void MergeBasicBlocks(void);
void CheckUsedDefinedTemps(void); void CheckUsedDefinedTemps(void);

View File

@ -2849,7 +2849,100 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
case EX_CONDITIONAL: case EX_CONDITIONAL:
{ {
InterInstruction * jins0 = new InterInstruction(); #if 1
if ((exp->mRight->mLeft->mType == EX_CONSTANT || exp->mRight->mLeft->mType == EX_VARIABLE) &&
(exp->mRight->mRight->mType == EX_CONSTANT || exp->mRight->mRight->mType == EX_VARIABLE))
{
ExValue vc = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper);
vl = TranslateExpression(procType, proc, block, exp->mRight->mLeft, breakBlock, continueBlock, inlineMapper);
vr = TranslateExpression(procType, proc, block, exp->mRight->mRight, breakBlock, continueBlock, inlineMapper);
vc = Dereference(proc, block, vc);
vl = Dereference(proc, block, vl);
vr = Dereference(proc, block, vr);
int ttemp;
InterType ttype, stypel, styper;
stypel = InterTypeOf(vl.mType);
styper = InterTypeOf(vr.mType);
Declaration* dtype;
if (stypel == IT_POINTER || styper == IT_POINTER)
{
if (vl.mType->mType == DT_TYPE_ARRAY)
vl = Dereference(proc, block, vl, 1);
else
vl = Dereference(proc, block, vl);
if (vr.mType->mType == DT_TYPE_ARRAY)
vr = Dereference(proc, block, vr, 1);
else
vr = Dereference(proc, block, vr);
if (vl.mType->mBase->IsSubType(vr.mType->mBase))
dtype = vr.mType;
else if (vr.mType->mBase->IsSubType(vl.mType->mBase))
dtype = vl.mType;
else
{
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible conditional types");
dtype = vl.mType;
}
Declaration* ntype = new Declaration(dtype->mLocation, DT_TYPE_POINTER);
ntype->mBase = dtype->mBase;
dtype = ntype;
ttype = IT_POINTER;
}
else
{
if (stypel == styper)
{
ttype = stypel;
dtype = vl.mType;
}
else if (stypel > styper)
{
ttype = stypel;
dtype = vl.mType;
vr = CoerceType(proc, block, vr, dtype);
}
else
{
ttype = styper;
dtype = vr.mType;
vl = CoerceType(proc, block, vl, dtype);
}
}
vc = CoerceType(proc, block, vc, TheBoolTypeDeclaration);
ttemp = proc->AddTemporary(ttype);
InterInstruction* sins = new InterInstruction();
sins->mCode = IC_SELECT;
sins->mSrc[2].mType = InterTypeOf(vc.mType);
sins->mSrc[2].mTemp = vc.mTemp;
sins->mSrc[1].mType = ttype;
sins->mSrc[1].mTemp = vl.mTemp;
sins->mSrc[0].mType = ttype;
sins->mSrc[0].mTemp = vr.mTemp;
sins->mDst.mType = ttype;
sins->mDst.mTemp = ttemp;
block->Append(sins);
return ExValue(dtype, ttemp);
}
else
#endif
{
InterInstruction* jins0 = new InterInstruction();
jins0->mCode = IC_JUMP; jins0->mCode = IC_JUMP;
InterInstruction* jins1 = new InterInstruction(); InterInstruction* jins1 = new InterInstruction();
jins1->mCode = IC_JUMP; jins1->mCode = IC_JUMP;
@ -2929,7 +3022,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
ttemp = proc->AddTemporary(ttype); ttemp = proc->AddTemporary(ttype);
InterInstruction * rins = new InterInstruction(); InterInstruction* rins = new InterInstruction();
rins->mCode = IC_LOAD_TEMPORARY; rins->mCode = IC_LOAD_TEMPORARY;
rins->mSrc[0].mType = ttype; rins->mSrc[0].mType = ttype;
rins->mSrc[0].mTemp = vr.mTemp; rins->mSrc[0].mTemp = vr.mTemp;
@ -2937,7 +3030,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
rins->mDst.mTemp = ttemp; rins->mDst.mTemp = ttemp;
fblock->Append(rins); fblock->Append(rins);
InterInstruction * lins = new InterInstruction(); InterInstruction* lins = new InterInstruction();
lins->mCode = IC_LOAD_TEMPORARY; lins->mCode = IC_LOAD_TEMPORARY;
lins->mSrc[0].mType = ttype; lins->mSrc[0].mType = ttype;
lins->mSrc[0].mTemp = vl.mTemp; lins->mSrc[0].mTemp = vl.mTemp;
@ -2954,6 +3047,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
block = eblock; block = eblock;
return ExValue(dtype, ttemp); return ExValue(dtype, ttemp);
}
break; break;
} }

View File

@ -11503,8 +11503,24 @@ bool NativeCodeBasicBlock::OptimizeXYPairUsage(void)
j++; j++;
if (j + 1 == mIns.Size() || !(mIns[j].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_Y))) if (j + 1 == mIns.Size() || !(mIns[j].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_Y)))
{ {
bool tox = ins.mType == ASMIT_LDY, toy = ins.mType == ASMIT_LDX;
for (int k = i; k <= j; k++) for (int k = i; k <= j; k++)
{
if (mIns[k].ChangesXReg())
tox = false;
if (mIns[k].ChangesYReg())
toy = false;
if (tox)
mIns[k].ReplaceYRegWithXReg();
else if (toy)
mIns[k].ReplaceXRegWithYReg();
else
mIns[k].SwapXYReg(); mIns[k].SwapXYReg();
}
CheckLive();
changed = true; changed = true;
} }
} }
@ -11915,6 +11931,49 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
break; break;
} }
#endif #endif
#if 1
if (i + 4 < mIns.Size() &&
(mIns[i + 0].mType == ASMIT_CPX || mIns[i + 0].mType == ASMIT_CPY) && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0x01 &&
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0x00 &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0xff &&
mIns[i + 3].mType == ASMIT_AND && mIns[i + 3].mMode == ASMIM_IMMEDIATE &&
mIns[i + 4].mType == ASMIT_EOR && mIns[i + 4].mMode == ASMIM_IMMEDIATE)
{
char veq = mIns[i + 3].mAddress ^ mIns[i + 4].mAddress, vne = mIns[i + 4].mAddress;
changed = true;
NativeCodeBasicBlock* eblock = proc->AllocateBlock();
NativeCodeBasicBlock* neblock = proc->AllocateBlock();
NativeCodeBasicBlock* rblock = proc->AllocateBlock();
rblock->mTrueJump = mTrueJump;
rblock->mFalseJump = mFalseJump;
rblock->mBranch = mBranch;
for (int j = i + 5; j < mIns.Size(); j++)
rblock->mIns.Push(mIns[j]);
mIns.SetSize(i + 1);
if (mIns[i + 0].mType == ASMIT_CPX)
mIns[i + 0].mType = ASMIT_TXA;
else if (mIns[i + 0].mType == ASMIT_CPY)
mIns[i + 0].mType = ASMIT_TYA;
mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 0].mLive |= LIVE_CPU_REG_Z;
mTrueJump = neblock;
mFalseJump = eblock;
mBranch = ASMIT_BNE;
if (veq != 0)
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, veq));
neblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, vne));
eblock->Close(rblock, nullptr, ASMIT_JMP);
neblock->Close(rblock, nullptr, ASMIT_JMP);
break;
}
#endif
#if 1 #if 1
if (i + 4 < mIns.Size() && if (i + 4 < mIns.Size() &&
mIns[i + 0].ChangesAccuAndFlag() && mIns[i + 0].ChangesAccuAndFlag() &&
@ -20950,7 +21009,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
#if 1 #if 1
// replace zero page down // replace zero page down
for (int i = 1; i + 1 < mIns.Size(); i++) for (int i = 0; i + 1 < mIns.Size(); i++)
{ {
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) && (mIns[i + 0].mLive & LIVE_MEM)) if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) && (mIns[i + 0].mLive & LIVE_MEM))
{ {
@ -24463,7 +24522,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
progress = true; progress = true;
} }
} }
#if 1
if (i + 1 < mIns.Size() && mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && mIns[i + 1].mMode == ASMIM_INDIRECT_Y && !(mIns[i + 1].mLive & (LIVE_MEM | LIVE_CPU_REG_Y))) if (i + 1 < mIns.Size() && mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && mIns[i + 1].mMode == ASMIM_INDIRECT_Y && !(mIns[i + 1].mLive & (LIVE_MEM | LIVE_CPU_REG_Y)))
{ {
int apos, breg; int apos, breg;
@ -24473,7 +24532,8 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
progress = true; progress = true;
} }
} }
#endif
#if 1
if (mIns[i + 0].mMode == ASMIM_INDIRECT_Y && (mIns[i + 0].mFlags & NCIF_YZERO)) if (mIns[i + 0].mMode == ASMIM_INDIRECT_Y && (mIns[i + 0].mFlags & NCIF_YZERO))
{ {
int apos, breg; int apos, breg;
@ -24483,6 +24543,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
progress = true; progress = true;
} }
} }
#endif
#endif #endif

View File

@ -2171,7 +2171,7 @@ Expression* Parser::ParseStatement(void)
conditionExp->mRight->mDecValue->mInteger = endValue; conditionExp->mRight->mDecValue->mInteger = endValue;
Expression * unrollBody = new Expression(mScanner->mLocation, EX_SEQUENCE); Expression* unrollBody = new Expression(mScanner->mLocation, EX_SEQUENCE);
unrollBody->mLeft = bodyExp; unrollBody->mLeft = bodyExp;
Expression* bexp = unrollBody; Expression* bexp = unrollBody;
if (endValue > startValue) if (endValue > startValue)
@ -2206,7 +2206,11 @@ Expression* Parser::ParseStatement(void)
bodyExp = unrollBody; bodyExp = unrollBody;
} }
else
mErrors->Error(exp->mLocation, EWARN_LOOP_UNROLL_IGNORED, "Loop unroll ignored, bounds and step not integer");
} }
else
mErrors->Error(exp->mLocation, EWARN_LOOP_UNROLL_IGNORED, "Loop unroll ignored, bounds and step not const");
} }
exp->mLeft->mRight = initExp; exp->mLeft->mRight = initExp;

View File

@ -74,7 +74,7 @@ int main2(int argc, const char** argv)
#else #else
strcpy(strProductName, "oscar64"); strcpy(strProductName, "oscar64");
strcpy(strProductVersion, "1.7.140"); strcpy(strProductVersion, "1.7.141");
#ifdef __APPLE__ #ifdef __APPLE__
uint32_t length = sizeof(basePath); uint32_t length = sizeof(basePath);

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,7,140,0 FILEVERSION 1,7,141,0
PRODUCTVERSION 1,7,140,0 PRODUCTVERSION 1,7,141,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -43,12 +43,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "oscar64" VALUE "CompanyName", "oscar64"
VALUE "FileDescription", "oscar64 compiler" VALUE "FileDescription", "oscar64 compiler"
VALUE "FileVersion", "1.7.140.0" VALUE "FileVersion", "1.7.141.0"
VALUE "InternalName", "oscar64.exe" VALUE "InternalName", "oscar64.exe"
VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "oscar64.exe" VALUE "OriginalFilename", "oscar64.exe"
VALUE "ProductName", "oscar64" VALUE "ProductName", "oscar64"
VALUE "ProductVersion", "1.7.140.0" VALUE "ProductVersion", "1.7.141.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -4153,15 +4153,15 @@
{ {
"Name" = "8:Microsoft Visual Studio" "Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64" "ProductName" = "8:oscar64"
"ProductCode" = "8:{4AC1A78B-6BCA-4D2F-A54D-DEA5F627B017}" "ProductCode" = "8:{AAAF5F55-0261-47DA-B051-EF84642395A5}"
"PackageCode" = "8:{ED70C89A-F338-434F-9FB2-90C1BD8EB020}" "PackageCode" = "8:{A7501921-EE58-422B-AEE2-4491A2249AC0}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0" "AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE" "RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE" "RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE" "InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:1.7.140" "ProductVersion" = "8:1.7.141"
"Manufacturer" = "8:oscar64" "Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:" "ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:" "ARPHELPLINK" = "8:"

View File

@ -46,7 +46,7 @@ void expand(char c, byte f)
byte * fp = font + 8 * c; byte * fp = font + 8 * c;
// Unroll eight times for each byte in glyph data // Unroll eight times for each byte in glyph data
// #pragma unroll(full) //#pragma unroll(full)
for(char y=0; y<8; y++) for(char y=0; y<8; y++)
{ {
char t = (fp[y] & f) ? 160 : 32; char t = (fp[y] & f) ? 160 : 32;