Optimize inline pointer parameters

This commit is contained in:
drmortalwombat 2021-11-05 08:46:59 +01:00
parent d51a30ed2e
commit a8ed15d67b
11 changed files with 677 additions and 105 deletions

1
.gitignore vendored
View File

@ -341,3 +341,4 @@ ASALocalRun/
*.lbl
make/oscar64
*.int
*.bcs

View File

@ -920,6 +920,39 @@ inp_load_addr_8:
#pragma bytecode(BC_LOAD_ABS_8, inp_load_abs_8)
#pragma bytecode(BC_LOAD_ADDR_8, inp_load_abs_8.inp_load_addr_8)
__asm inp_load_abs_u8
{
lda (ip), y
sta addr
iny
lda (ip), y
sta addr + 1
iny
lda (ip), y
tax
sty tmpy
ldy #0
L0:
lda (addr), y
sta $00, x
lda #0
sta $01, x
ldy tmpy
iny
jmp startup.exec
inp_load_addr_u8:
lda (ip), y
tax
iny
lda (ip), y
sty tmpy
tay
jmp L0
}
#pragma bytecode(BC_LOAD_ABS_U8, inp_load_abs_u8)
#pragma bytecode(BC_LOAD_ADDR_U8, inp_load_abs_u8.inp_load_addr_u8)
__asm inp_load_abs_16
{
@ -1142,6 +1175,25 @@ __asm inp_lea_abs_index
#pragma bytecode(BC_LEA_ABS_INDEX, inp_lea_abs_index)
__asm inp_lea_abs_index_u8
{
lda (ip), y
tax
iny
clc
lda $00, x
adc (ip), y
sta addr
iny
lda #$00
adc (ip), y
sta addr + 1
iny
jmp startup.exec
}
#pragma bytecode(BC_LEA_ABS_INDEX_U8, inp_lea_abs_index_u8)
__asm inp_load_local_16
{
lda (ip), y

View File

@ -23,6 +23,7 @@ enum ByteCode
BC_STORE_REG_32,
BC_LOAD_ABS_8,
BC_LOAD_ABS_U8,
BC_LOAD_ABS_16,
BC_LOAD_ABS_32,
@ -32,6 +33,7 @@ enum ByteCode
BC_LEA_ABS,
BC_LEA_ABS_INDEX,
BC_LEA_ABS_INDEX_U8,
BC_LOAD_LOCAL_8,
BC_LOAD_LOCAL_16,
@ -50,6 +52,7 @@ enum ByteCode
BC_LEA_FRAME,
BC_LOAD_ADDR_8,
BC_LOAD_ADDR_U8,
BC_LOAD_ADDR_16,
BC_LOAD_ADDR_32,

View File

@ -277,6 +277,25 @@ public:
Grow(size, clear);
}
void Reserve(int to)
{
if (to > range)
{
range = to;
T* a2 = new T[range];
if (to > size)
for (int i = 0; i < size; i++) a2[i] = array[i];
else
for (int i = 0; i < to; i++) a2[i] = array[i];
delete[] array;
array = a2;
for (int i = size; i < range; i++) array[i] = empty;
}
}
void Clear(void)
{
Grow(size, true);

View File

@ -1,6 +1,171 @@
#include "ByteCodeGenerator.h"
#include "Assembler.h"
static const char* ByteCodeNames[] = {
"NOP",
"EXIT",
"CONST_8",
"CONST_P8",
"CONST_N8",
"CONST_16",
"CONST_32",
"LOAD_REG_8",
"STORE_REG_8",
"LOAD_REG_16",
"STORE_REG_16",
"ADDR_REG",
"LOAD_REG_32",
"STORE_REG_32",
"LOAD_ABS_8",
"LOAD_ABS_U8",
"LOAD_ABS_16",
"LOAD_ABS_32",
"STORE_ABS_8",
"STORE_ABS_16",
"STORE_ABS_32",
"LEA_ABS",
"LEA_ABS_INDEX",
"LEA_ABS_INDEX_U8",
"LOAD_LOCAL_8",
"LOAD_LOCAL_16",
"LOAD_LOCAL_32",
"STORE_LOCAL_8",
"STORE_LOCAL_16",
"STORE_LOCAL_32",
"LEA_LOCAL",
"STORE_FRAME_8",
"STORE_FRAME_16",
"STORE_FRAME_32",
"LEA_FRAME",
"LOAD_ADDR_8",
"LOAD_ADDR_U8",
"LOAD_ADDR_16",
"LOAD_ADDR_32",
"STORE_ADDR_8",
"STORE_ADDR_16",
"STORE_ADDR_32",
"BINOP_ADDR_16",
"BINOP_SUBR_16",
"BINOP_ANDR_16",
"BINOP_ORR_16",
"BINOP_XORR_16",
"BINOP_MULR_16",
"BINOP_DIVR_U16",
"BINOP_MODR_U16",
"BINOP_DIVR_I16",
"BINOP_MODR_I16",
"BINOP_SHLR_16",
"BINOP_SHRR_U16",
"BINOP_SHRR_I16",
"BINOP_ADDI_16",
"BINOP_SUBI_16",
"BINOP_ANDI_16",
"BINOP_ORI_16",
"BINOP_MULI8_16",
"BINOP_ADDI_8",
"BINOP_ANDI_8",
"BINOP_ORI_8",
"BINOP_SHLI_16",
"BINOP_SHRI_U16",
"BINOP_SHRI_I16",
"BINOP_CMPUR_16",
"BINOP_CMPSR_16",
"BINOP_CMPUI_16",
"BINOP_CMPSI_16",
"BINOP_CMPUR_8",
"BINOP_CMPSR_8",
"BINOP_CMPUI_8",
"BINOP_CMPSI_8",
"OP_NEGATE_16",
"OP_INVERT_16",
"BINOP_ADD_F32",
"BINOP_SUB_F32",
"BINOP_MUL_F32",
"BINOP_DIV_F32",
"BINOP_CMP_F32",
"OP_NEGATE_F32",
"OP_ABS_F32",
"OP_FLOOR_F32",
"OP_CEIL_F32",
"CONV_U16_F32",
"CONV_I16_F32",
"CONV_F32_U16",
"CONV_F32_I16",
"CONV_I8_I16",
"JUMPS",
"BRANCHS_EQ",
"BRANCHS_NE",
"BRANCHS_GT",
"BRANCHS_GE",
"BRANCHS_LT",
"BRANCHS_LE",
"JUMPF",
"BRANCHF_EQ",
"BRANCHF_NE",
"BRANCHF_GT",
"BRANCHF_GE",
"BRANCHF_LT",
"BRANCHF_LE",
"SET_EQ",
"SET_NE",
"SET_GT",
"SET_GE",
"SET_LT",
"SET_LE",
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
"NATIVE",
"ENTER",
"RETURN",
"CALL",
"PUSH_FRAME",
"POP_FRAME",
"JSR",
"COPY",
"COPY_LONG",
"STRCPY",
"EXTRT"
};
static ByteCode StoreTypedTmpCodes[] = {
BC_NOP,
BC_STORE_REG_8,
@ -70,6 +235,11 @@ bool ByteCodeInstruction::ChangesAccu(void) const
return ChangesRegister(BC_REG_ACCU);
}
bool ByteCodeInstruction::UsesAccu(void) const
{
return UsesRegister(BC_REG_ACCU);
}
bool ByteCodeInstruction::ChangesAddr(void) const
{
return ChangesRegister(BC_REG_ADDR);
@ -166,6 +336,76 @@ bool ByteCodeInstruction::StoresRegister(uint32 reg) const
}
bool ByteCodeInstruction::UsesRegister(uint32 reg) const
{
if (StoresRegister(reg))
return true;
if (mRegister == reg)
{
if (mCode == BC_LOAD_REG_8 || mCode == BC_LOAD_REG_16 || mCode == BC_LOAD_REG_32 || mCode == BC_ADDR_REG || mCode == BC_LEA_ABS_INDEX || mCode == BC_LEA_ABS_INDEX_U8)
return true;
if (mCode >= BC_BINOP_ADDI_16 && mCode <= BC_BINOP_ORI_8)
return true;
if (mCode >= BC_BINOP_ADDR_16 && mCode <= BC_BINOP_SHRR_I16)
return true;
if (mCode == BC_BINOP_CMPUR_16 || mCode == BC_BINOP_CMPSR_16)
return true;
if (mCode == BC_BINOP_CMPUR_8 || mCode == BC_BINOP_CMPSR_8)
return true;
if (mCode >= BC_BINOP_ADD_F32 && mCode <= BC_BINOP_CMP_F32)
return true;
if (mCode >= BC_BINOP_ADD_L32 && mCode <= BC_BINOP_CMP_S32)
return true;
}
if (reg == BC_REG_ACCU)
{
if (mCode == BC_STORE_REG_8 || mCode == BC_STORE_REG_16 || mCode == BC_STORE_REG_32)
return true;
if (mCode >= BC_BINOP_ADDR_16 && mCode <= BC_BINOP_SHRR_I16)
return true;
if (mCode >= BC_BINOP_CMPUR_16 && mCode <= BC_BINOP_CMPSI_16)
return true;
if (mCode >= BC_BINOP_CMPUR_8 && mCode <= BC_BINOP_CMPSI_8)
return true;
if (mCode >= BC_OP_NEGATE_16 && mCode <= BC_OP_INVERT_16)
return true;
if (mCode >= BC_BINOP_ADD_F32 && mCode <= BC_OP_CEIL_F32)
return true;
if (mCode >= BC_CONV_U16_F32 && mCode <= BC_CONV_F32_I16)
return true;
if (mCode >= BC_BINOP_SHLI_16 && mCode <= BC_BINOP_SHRI_I16)
return true;
if (mCode >= BC_SET_EQ && mCode <= BC_SET_LE)
return true;
if (mCode >= BC_CONV_I16_I32 && mCode <= BC_BINOP_CMP_S32)
return true;
}
if (reg == BC_REG_ADDR)
{
if (mCode >= BC_LOAD_ADDR_8 && mCode <= BC_LOAD_ADDR_32)
return true;
if (mCode >= BC_LOAD_ADDR_8 && mCode <= BC_STORE_ADDR_32)
return true;
if (mCode == BC_JSR || mCode == BC_CALL)
return true;
}
return false;
}
bool ByteCodeInstruction::ChangesRegister(uint32 reg) const
{
if (mRegister == reg)
@ -222,7 +462,7 @@ bool ByteCodeInstruction::ChangesRegister(uint32 reg) const
return true;
if (mCode == BC_JSR || mCode == BC_CALL)
return true;
if (mCode == BC_LEA_ABS_INDEX)
if (mCode == BC_LEA_ABS_INDEX || mCode == BC_LEA_ABS_INDEX_U8)
return true;
}
@ -288,6 +528,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl
break;
case BC_LOAD_ABS_8:
case BC_LOAD_ABS_U8:
case BC_LOAD_ABS_16:
case BC_LOAD_ABS_32:
case BC_STORE_ABS_8:
@ -312,6 +553,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl
case BC_LEA_ABS:
case BC_LEA_ABS_INDEX:
case BC_LEA_ABS_INDEX_U8:
block->PutCode(generator, mCode); block->PutByte(mRegister);
if (mRelocate)
{
@ -497,6 +739,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl
} break;
case BC_LOAD_ADDR_8:
case BC_LOAD_ADDR_U8:
case BC_LOAD_ADDR_16:
case BC_LOAD_ADDR_32:
case BC_STORE_ADDR_8:
@ -594,7 +837,7 @@ void ByteCodeBasicBlock::PutBytes(const uint8* code, int num)
void ByteCodeBasicBlock::PutCode(ByteCodeGenerator* generator, ByteCode code)
{
PutByte(uint8(code) * 2);
generator->mByteCodeUsed[code] = true;
generator->mByteCodeUsed[code]++;
}
int ByteCodeBasicBlock::PutBranch(ByteCodeGenerator* generator, ByteCode code, int offset)
@ -623,6 +866,7 @@ ByteCodeBasicBlock::ByteCodeBasicBlock(void)
mAssembled = false;
mKnownShortBranch = false;
mBypassed = false;
mExitLive = 0;
}
void ByteCodeBasicBlock::IntConstToAccu(int64 val)
@ -3482,6 +3726,8 @@ bool ByteCodeBasicBlock::SameTail(ByteCodeInstruction& ins)
return false;
}
static const uint32 LIVE_ACCU = 0x00000001;
bool ByteCodeBasicBlock::JoinTailCodeSequences(void)
{
bool changed = false;
@ -3512,6 +3758,7 @@ bool ByteCodeBasicBlock::JoinTailCodeSequences(void)
{
ByteCodeBasicBlock* b = mEntryBlocks[i];
b->mIns.SetSize(b->mIns.Size() - 1);
b->mExitLive = LIVE_ACCU;
}
changed = true;
}
@ -3530,7 +3777,6 @@ bool ByteCodeBasicBlock::JoinTailCodeSequences(void)
return changed;
}
bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
{
bool changed = false;
@ -3561,7 +3807,26 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
}
mIns.SetSize(j);
int accuTemp = -1, addrTemp = -1;
// mark accu live
uint32 live = mExitLive;
if (mBranch != BC_JUMPS && mBranch != BC_NOP)
live |= LIVE_ACCU;
for (int i = mIns.Size() - 1; i >= 0; i--)
{
mIns[i].mLive = live;
if (mIns[i].ChangesAccu())
live &= ~LIVE_ACCU;
if (mIns[i].UsesAccu())
live |= LIVE_ACCU;
}
// assert(!(live & LIVE_ACCU));
int accuTemp = -1, addrTemp = -1, accuVal = 0;
bool accuConst = false;
for (int i = 0; i < mIns.Size(); i++)
{
@ -3569,19 +3834,6 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
if (i + 3 < mIns.Size())
{
if (
mIns[i + 0].mCode == BC_LEA_ABS && mIns[i + 0].mRegister == BC_REG_ACCU &&
mIns[i + 1].mCode == BC_BINOP_ADDR_16 &&
mIns[i + 2].mCode == BC_ADDR_REG && mIns[i + 2].mRegister == BC_REG_ACCU &&
mIns[i + 3].ChangesAccu())
{
mIns[i + 0].mCode = BC_LEA_ABS_INDEX;
mIns[i + 0].mRegister = mIns[i + 1].mRegister;
mIns[i + 0].mRegisterFinal = mIns[i + 1].mRegisterFinal;
mIns[i + 1].mCode = BC_NOP;
mIns[i + 2].mCode = BC_NOP;
progress = true;
}
else if (
mIns[i + 0].mCode == BC_LOAD_REG_8 &&
mIns[i + 1].mCode == BC_STORE_REG_16 &&
mIns[i + 2].IsIntegerConst() && mIns[i + 2].mRegister == BC_REG_ACCU &&
@ -3592,6 +3844,22 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
mIns[i + 3].mRegister = mIns[i + 0].mRegister;
progress = true;
}
else if (
mIns[i + 0].mCode == BC_LOAD_REG_8 &&
mIns[i + 1].mCode == BC_LEA_ABS && mIns[i + 1].mRegister != BC_REG_ACCU &&
mIns[i + 2].mCode == BC_BINOP_ADDR_16 && mIns[i + 2].mRegister == mIns[i + 1].mRegister && mIns[i + 2].mRegisterFinal &&
mIns[i + 3].mCode == BC_ADDR_REG && mIns[i + 3].mRegister == BC_REG_ACCU && !(mIns[i + 3].mLive & LIVE_ACCU))
{
mIns[i + 1].mCode = BC_LEA_ABS_INDEX_U8;
mIns[i + 1].mRegister = mIns[i + 0].mRegister;
mIns[i + 1].mRegisterFinal = mIns[i + 0].mRegisterFinal;
mIns[i + 1].mLive &= ~LIVE_ACCU;
mIns[i + 0].mCode = BC_NOP;
mIns[i + 2].mCode = BC_NOP;
mIns[i + 3].mCode = BC_NOP;
progress = true;
}
}
#endif
#if 1
@ -3764,6 +4032,16 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
mIns[i + 1].mCode = BC_NOP;
progress = true;
}
else if (
mIns[i + 0].mCode == BC_STORE_REG_16 &&
mIns[i + 1].mCode == BC_LOAD_REG_8 && mIns[i + 0].mRegister == mIns[i + 1].mRegister &&
mIns[i + 2].mCode == BC_STORE_REG_8)
{
if (mIns[i + 1].mRegisterFinal)
mIns[i + 0].mCode = BC_NOP;
mIns[i + 1].mCode = BC_NOP;
progress = true;
}
#if 1
else if (
mIns[i + 0].mCode == BC_STORE_REG_16 &&
@ -3775,6 +4053,32 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
progress = true;
}
#endif
else if (
mIns[i + 0].mCode == BC_LEA_ABS && mIns[i + 0].mRegister == BC_REG_ACCU &&
mIns[i + 1].mCode == BC_BINOP_ADDR_16 &&
mIns[i + 2].mCode == BC_ADDR_REG && mIns[i + 2].mRegister == BC_REG_ACCU && !(mIns[i + 2].mLive & LIVE_ACCU))
{
mIns[i + 0].mCode = BC_LEA_ABS_INDEX;
mIns[i + 0].mRegister = mIns[i + 1].mRegister;
mIns[i + 0].mRegisterFinal = mIns[i + 1].mRegisterFinal;
mIns[i + 0].mLive &= ~LIVE_ACCU;
mIns[i + 1].mCode = BC_NOP;
mIns[i + 2].mCode = BC_NOP;
progress = true;
}
else if (
mIns[i + 0].mCode == BC_LOAD_REG_8 &&
mIns[i + 1].mCode == BC_STORE_REG_16 &&
mIns[i + 2].mCode == BC_LEA_ABS_INDEX && mIns[i + 2].mRegister == mIns[i + 1].mRegister && !(mIns[i + 2].mLive & LIVE_ACCU) && mIns[i + 2].mRegisterFinal)
{
mIns[i + 2].mCode = BC_LEA_ABS_INDEX_U8;
mIns[i + 2].mRegister = mIns[i + 0].mRegister;
mIns[i + 2].mRegisterFinal = mIns[i + 0].mRegisterFinal;
mIns[i + 0].mCode = BC_NOP;
mIns[i + 1].mCode = BC_NOP;
progress = true;
}
}
#endif
#if 1
@ -3888,6 +4192,22 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
progress = true;
}
#endif
#if 1
else if (mIns[i + 1].mCode == BC_LOAD_REG_8 && mIns[i + 0].mCode == BC_LOAD_ADDR_8 && mIns[i + 1].mRegisterFinal && mIns[i + 0].mRegister == mIns[i + 1].mRegister)
{
mIns[i + 0].mCode = BC_LOAD_ADDR_U8;
mIns[i + 0].mRegister = BC_REG_ACCU;
mIns[i + 1].mCode = BC_NOP;
progress = true;
}
else if (mIns[i + 1].mCode == BC_LOAD_REG_8 && mIns[i + 0].mCode == BC_LOAD_ABS_8 && mIns[i + 1].mRegisterFinal && mIns[i + 0].mRegister == mIns[i + 1].mRegister)
{
mIns[i + 0].mCode = BC_LOAD_ABS_U8;
mIns[i + 0].mRegister = BC_REG_ACCU;
mIns[i + 1].mCode = BC_NOP;
progress = true;
}
#endif
#if 0
else if ((mIns[i].mCode == BC_LOAD_LOCAL_16 || mIns[i].mCode == BC_LOAD_ABS_16) && mIns[i + 1].mCode == BC_ADDR_REG && mIns[i].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal)
{
@ -3911,8 +4231,39 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
progress = true;
}
if (accuConst && !mIns[i].mRelocate && mIns[i].mRegister == BC_REG_ACCU)
{
switch (mIns[i].mCode)
{
case BC_CONST_16:
if ((mIns[i].mValue & 0xffff) == (accuVal & 0xffff))
{
mIns[i].mCode = BC_NOP;
progress = true;
}
break;
case BC_CONST_32:
if (mIns[i].mValue == accuVal)
{
mIns[i].mCode = BC_NOP;
progress = true;
}
break;
case BC_CONST_8:
if ((mIns[i].mValue & 0xff) == (accuVal & 0xffff))
{
mIns[i].mCode = BC_NOP;
progress = true;
}
break;
}
}
if (mIns[i].ChangesAccu())
{
accuTemp = -1;
accuConst = false;
}
if (mIns[i].ChangesAddr())
addrTemp = -1;
if (accuTemp != -1 && mIns[i].ChangesRegister(accuTemp))
@ -3924,6 +4275,25 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
accuTemp = mIns[i].mRegister;
if (mIns[i].mCode == BC_ADDR_REG && mIns[i].mRegister != BC_REG_ACCU)
addrTemp = mIns[i].mRegister;
if (mIns[i].mRegister == BC_REG_ACCU && !mIns[i].mRelocate)
{
switch (mIns[i].mCode)
{
case BC_CONST_16:
accuVal = mIns[i].mValue & 0xffff;
accuConst = true;
break;
case BC_CONST_32:
accuVal = mIns[i].mValue;
accuConst = true;
break;
case BC_CONST_8:
accuVal = mIns[i].mValue & 0xff;
accuConst = true;
break;
}
}
}
if (progress)
@ -4294,16 +4664,37 @@ ByteCodeGenerator::ByteCodeGenerator(Errors* errors, Linker* linker)
{
for (int i = 0; i < 128; i++)
{
mByteCodeUsed[i] = false;
mByteCodeUsed[i] = 0;
mExtByteCodes[i] = nullptr;
}
mByteCodeUsed[BC_LEA_ABS] = true;
mByteCodeUsed[BC_CALL] = true;
mByteCodeUsed[BC_EXIT] = true;
mByteCodeUsed[BC_NATIVE] = true;
mByteCodeUsed[BC_LEA_ABS] = 1;
mByteCodeUsed[BC_CALL] = 1;
mByteCodeUsed[BC_EXIT] = 1;
mByteCodeUsed[BC_NATIVE] = 1;
assert(sizeof(ByteCodeNames) == 128 * sizeof(char*));
}
ByteCodeGenerator::~ByteCodeGenerator(void)
{
}
bool ByteCodeGenerator::WriteByteCodeStats(const char* filename)
{
FILE* file;
fopen_s(&file, filename, "w");
if (file)
{
for (int i = 0; i < 128; i++)
{
if (mByteCodeUsed[i] > 0)
fprintf(file, "BC %s : %d\n", ByteCodeNames[i], mByteCodeUsed[i]);
}
fclose(file);
return true;
}
return false;
}

View File

@ -24,6 +24,7 @@ enum ByteCode
BC_STORE_REG_32,
BC_LOAD_ABS_8,
BC_LOAD_ABS_U8,
BC_LOAD_ABS_16,
BC_LOAD_ABS_32,
@ -33,6 +34,7 @@ enum ByteCode
BC_LEA_ABS,
BC_LEA_ABS_INDEX,
BC_LEA_ABS_INDEX_U8,
BC_LOAD_LOCAL_8,
BC_LOAD_LOCAL_16,
@ -51,6 +53,7 @@ enum ByteCode
BC_LEA_FRAME,
BC_LOAD_ADDR_8,
BC_LOAD_ADDR_U8,
BC_LOAD_ADDR_16,
BC_LOAD_ADDR_32,
@ -198,11 +201,16 @@ public:
bool mRelocate, mRegisterFinal;
LinkerObject* mLinkerObject;
const char* mRuntime;
uint32 mLive;
bool IsStore(void) const;
bool ChangesAccu(void) const;
bool ChangesAddr(void) const;
bool ChangesRegister(uint32 reg) const;
bool UsesAccu(void) const;
bool UsesRegister(uint32 reg) const;
bool LoadsRegister(uint32 reg) const;
bool StoresRegister(uint32 reg) const;
bool IsLocalStore(void) const;
@ -233,6 +241,7 @@ public:
int mOffset, mSize;
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mVisited;
uint32 mExitLive;
ByteCodeBasicBlock(void);
@ -316,10 +325,8 @@ public:
Errors* mErrors;
Linker* mLinker;
bool mByteCodeUsed[128];
uint32 mByteCodeUsed[128];
LinkerObject* mExtByteCodes[128];
void WriteBasicHeader(void);
void WriteByteCodeHeader(void);
void SetBasicEntry(int index);
bool WriteByteCodeStats(const char* filename);
};

View File

@ -282,7 +282,7 @@ bool Compiler::GenerateCode(void)
for (int i = 0; i < 128; i++)
{
if (mByteCodeGenerator->mByteCodeUsed[i])
if (mByteCodeGenerator->mByteCodeUsed[i] > 0)
{
Declaration* bcdec = mCompilationUnits->mByteCodes[i];
if (bcdec)
@ -338,7 +338,7 @@ bool Compiler::GenerateCode(void)
bool Compiler::WriteOutputFile(const char* targetPath)
{
char prgPath[200], mapPath[200], asmPath[200], lblPath[200], crtPath[200], intPath[200];
char prgPath[200], mapPath[200], asmPath[200], lblPath[200], crtPath[200], intPath[200], bcsPath[200];
strcpy_s(prgPath, targetPath);
int i = strlen(prgPath);
@ -351,6 +351,7 @@ bool Compiler::WriteOutputFile(const char* targetPath)
strcpy_s(lblPath, prgPath);
strcpy_s(crtPath, prgPath);
strcpy_s(intPath, prgPath);
strcpy_s(bcsPath, prgPath);
strcat_s(prgPath, "prg");
strcat_s(mapPath, "map");
@ -358,6 +359,7 @@ bool Compiler::WriteOutputFile(const char* targetPath)
strcat_s(lblPath, "lbl");
strcat_s(crtPath, "crt");
strcat_s(intPath, "int");
strcat_s(bcsPath, "bcs");
if (mCompilerOptions & COPT_TARGET_PRG)
{
@ -383,6 +385,12 @@ bool Compiler::WriteOutputFile(const char* targetPath)
printf("Writing <%s>\n", intPath);
mInterCodeModule->Disassemble(intPath);
if (!(mCompilerOptions & COPT_NATIVE))
{
printf("Writing <%s>\n", bcsPath);
mByteCodeGenerator->WriteByteCodeStats(bcsPath);
}
return true;
}

View File

@ -143,6 +143,10 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int star
fprintf(file, "MOVB\t%s, %s", TempName(memory[start + i + 2], tbuffer, proc), AddrName(uint16(memory[start + i + 0] + 256 * memory[start + i + 1]), abuffer, linker));
i += 3;
break;
case BC_LOAD_ABS_U8:
fprintf(file, "MOVUB\t%s, %s", TempName(memory[start + i + 2], tbuffer, proc), AddrName(uint16(memory[start + i + 0] + 256 * memory[start + i + 1]), abuffer, linker));
i += 3;
break;
case BC_LOAD_ABS_16:
fprintf(file, "MOV\t%s, %s", TempName(memory[start + i + 2], tbuffer, proc), AddrName(uint16(memory[start + i + 0] + 256 * memory[start + i + 1]), abuffer, linker));
i += 3;
@ -162,6 +166,11 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int star
i += 3;
break;
case BC_LEA_ABS_INDEX_U8:
fprintf(file, "LEAXB\tADDR, %s + %s", AddrName(uint16(memory[start + i + 1] + 256 * memory[start + i + 2]), abuffer, linker), TempName(memory[start + i + 0], tbuffer, proc));
i += 3;
break;
case BC_STORE_ABS_8:
fprintf(file, "MOVB\t%s, %s", AddrName(uint16(memory[start + i + 0] + 256 * memory[start + i + 1]), abuffer, linker), TempName(memory[start + i + 2], tbuffer, proc));
i += 3;
@ -540,6 +549,10 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int star
fprintf(file, "MOVB\t%s, %d(ADDR)", TempName(memory[start + i + 0], tbuffer, proc), memory[start + i + 1]);
i += 2;
break;
case BC_LOAD_ADDR_U8:
fprintf(file, "MOVUB\t%s, %d(ADDR)", TempName(memory[start + i + 0], tbuffer, proc), memory[start + i + 1]);
i += 2;
break;
case BC_LOAD_ADDR_16:
fprintf(file, "MOV\t%s, %d(ADDR)", TempName(memory[start + i + 0], tbuffer, proc), memory[start + i + 1]);
i += 2;

View File

@ -1569,9 +1569,12 @@ void InterInstruction::MarkAliasedLocalTemps(const GrowingIntArray& localTable,
void InterInstruction::FilterTempUsage(NumberSet& requiredTemps, NumberSet& providedTemps)
{
for(int i=0; i<mNumOperands; i++)
FilterTempUseUsage(requiredTemps, providedTemps, mSrc[i].mTemp);
FilterTempDefineUsage(requiredTemps, providedTemps, mDst.mTemp);
if (mCode != IC_NONE)
{
for (int i = 0; i < mNumOperands; i++)
FilterTempUseUsage(requiredTemps, providedTemps, mSrc[i].mTemp);
FilterTempDefineUsage(requiredTemps, providedTemps, mDst.mTemp);
}
}
void InterInstruction::FilterStaticVarsUsage(const GrowingVariableArray& staticVars, NumberSet& requiredVars, NumberSet& providedVars)
@ -1716,9 +1719,12 @@ bool InterInstruction::PropagateConstTemps(const GrowingInstructionPtrArray& cte
void InterInstruction::PerformTempForwarding(TempForwardingTable& forwardingTable)
{
for(int i=0; i<mNumOperands; i++)
PerformTempUseForwarding(mSrc[i].mTemp, forwardingTable);
PerformTempDefineForwarding(mDst.mTemp, forwardingTable);
if (mCode != IC_NONE)
{
for (int i = 0; i < mNumOperands; i++)
PerformTempUseForwarding(mSrc[i].mTemp, forwardingTable);
PerformTempDefineForwarding(mDst.mTemp, forwardingTable);
}
if (mCode == IC_LOAD_TEMPORARY && mDst.mTemp != mSrc[0].mTemp)
{
forwardingTable.Build(mDst.mTemp, mSrc[0].mTemp);
@ -1823,6 +1829,7 @@ bool InterInstruction::RemoveUnusedStoreInstructions(const GrowingVariableArray&
}
else
{
mSrc[0].mTemp = -1;
mCode = IC_NONE;
changed = true;
}
@ -1838,6 +1845,7 @@ bool InterInstruction::RemoveUnusedStoreInstructions(const GrowingVariableArray&
}
else
{
mSrc[0].mTemp = -1;
mCode = IC_NONE;
changed = true;
}
@ -1877,6 +1885,7 @@ bool InterInstruction::RemoveUnusedStaticStoreInstructions(const GrowingVariable
}
else if (!mVolatile)
{
mSrc[0].mTemp = -1;
mCode = IC_NONE;
changed = true;
}
@ -4104,6 +4113,7 @@ void InterCodeBasicBlock::RemoveNonRelevantStatics(void)
{
if (!(ins->mSrc[1].mLinkerObject->mFlags & LOBJF_RELEVANT) && (ins->mSrc[1].mLinkerObject->mType == LOT_BSS || ins->mSrc[1].mLinkerObject->mType == LOT_DATA))
{
ins->mSrc[0].mTemp = -1;
ins->mCode = IC_NONE;
}
}
@ -5378,50 +5388,53 @@ void InterCodeProcedure::Close(void)
}
//
// Promote local variables to temporaries
//
FastNumberSet simpleLocals(nlocals), complexLocals(nlocals);
GrowingTypeArray localTypes(IT_NONE);
FastNumberSet simpleParams(nparams), complexParams(nparams);
GrowingTypeArray paramTypes(IT_NONE);
ResetVisited();
mEntryBlock->CollectSimpleLocals(complexLocals, simpleLocals, localTypes, complexParams, simpleParams, paramTypes);
for (int i = 0; i < simpleLocals.Num(); i++)
for (int j = 0; j < 2; j++)
{
int vi = simpleLocals.Element(i);
if (!complexLocals[vi])
//
// Promote local variables to temporaries
//
FastNumberSet simpleLocals(nlocals), complexLocals(nlocals);
GrowingTypeArray localTypes(IT_NONE);
FastNumberSet simpleParams(nparams), complexParams(nparams);
GrowingTypeArray paramTypes(IT_NONE);
ResetVisited();
mEntryBlock->CollectSimpleLocals(complexLocals, simpleLocals, localTypes, complexParams, simpleParams, paramTypes);
for (int i = 0; i < simpleLocals.Num(); i++)
{
ResetVisited();
mEntryBlock->SimpleLocalToTemp(vi, AddTemporary(localTypes[vi]));
int vi = simpleLocals.Element(i);
if (!complexLocals[vi])
{
ResetVisited();
mEntryBlock->SimpleLocalToTemp(vi, AddTemporary(localTypes[vi]));
}
}
}
DisassembleDebug("local variables to temps");
DisassembleDebug("local variables to temps");
BuildTraces(false);
BuildTraces(false);
BuildDataFlowSets();
BuildDataFlowSets();
RenameTemporaries();
RenameTemporaries();
do {
TempForwarding();
} while (GlobalConstantPropagation());
//
// Now remove unused instructions
//
RemoveUnusedInstructions();
DisassembleDebug("removed unused instructions 2");
do {
TempForwarding();
} while (GlobalConstantPropagation());
//
// Now remove unused instructions
//
RemoveUnusedInstructions();
DisassembleDebug("removed unused instructions 2");
TempForwarding();
}
BuildDominators();
DisassembleDebug("added dominators");

View File

@ -6830,9 +6830,11 @@ void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
// if the global variable is smaller than 256 bytes, we can safely ignore the upper byte?
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[1].mIntConst, ins->mSrc[1].mLinkerObject, NCIF_UPPER));
#if 1
if (ins->mSrc[1].mLinkerObject->mSize < 256)
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0));
else
#endif
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
}
@ -8065,6 +8067,37 @@ bool NativeCodeBasicBlock::MoveStoreHighByteDown(int at)
return false;
}
bool NativeCodeBasicBlock::MoveAddHighByteDown(int at)
{
int i = at + 4;
while (i + 1 < mIns.Size())
{
if (mIns[i].mLive & LIVE_CPU_REG_C)
return false;
if (mIns[i].ChangesZeroPage(mIns[at + 1].mAddress) || mIns[i].ChangesZeroPage(mIns[at + 3].mAddress))
return false;
if (mIns[i].UsesZeroPage(mIns[at + 3].mAddress))
return false;
if (!(mIns[i].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
{
mIns.Insert(i + 1, mIns[at + 3]);
mIns.Insert(i + 1, mIns[at + 2]);
mIns.Insert(i + 1, mIns[at + 1]);
mIns[at + 1].mType = ASMIT_NOP; mIns[at + 1].mMode = ASMIM_IMPLIED; // LDA U
mIns[at + 2].mType = ASMIT_NOP; mIns[at + 2].mMode = ASMIM_IMPLIED; // ADC #
mIns[at + 3].mType = ASMIT_NOP; mIns[at + 3].mMode = ASMIM_IMPLIED; // STA T
return true;
}
i++;
}
return false;
}
bool NativeCodeBasicBlock::MoveLoadStoreUp(int at)
{
int j = at;
@ -8169,14 +8202,15 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data)
AsmInsType carryop;
// Check load and commutative with current accu value
#if 1
if (i + 1 < mIns.Size() && mIns[i].mType == ASMIT_LDA && mIns[i + 1].IsCommutative() && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mValue == mIns[i + 1].mAddress)
{
mIns[i].mType = mIns[i + 1].mType;
mIns[i + 1].mType = ASMIT_NOP;
mIns[i + 1].mMode = ASMIM_IMPLIED;
changed = true;
}
#endif
if (mIns[i].ValueForwarding(mNDataSet, carryop))
changed = true;
if (carryop != ASMIT_NOP)
@ -9001,11 +9035,37 @@ void NativeCodeBasicBlock::BlockSizeReduction(void)
}
bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
bool NativeCodeBasicBlock::RemoveNops(void)
{
bool changed = false;
int i = 0;
int j = 0;
while (i < mIns.Size())
{
if (mIns[i].mType == ASMIT_NOP)
;
else
{
if (i != j)
mIns[j] = mIns[i];
j++;
}
i++;
}
if (j != i)
changed = true;
mIns.SetSize(j);
mIns.Reserve(2 * j);
return changed;
}
bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
{
if (!mVisited)
{
bool changed = false;
bool changed = RemoveNops();
mVisited = true;
@ -9084,6 +9144,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
NativeCodeInstruction ins = mIns[i];
mIns[i] = mIns[i + 1];
mIns[i + 1] = ins;
mIns[i + 1].mLive |= mIns[i].mLive;
}
}
}
@ -9101,49 +9162,50 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
}
}
#endif
// move high byte load down, if low byte is immediatedly needed afterwards
for (int i = 0; i + 4 < mIns.Size(); i++)
#if 1
if (pass > 1)
{
if (mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 1].mType == ASMIT_LDY && mIns[i + 1].mMode == ASMIM_IMMEDIATE &&
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_INDIRECT_Y && mIns[i + 2].mAddress != mIns[i + 3].mAddress && mIns[i + 2].mAddress + 1 != mIns[i + 3].mAddress &&
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress != mIns[i + 0].mAddress &&
mIns[i + 4].mType == ASMIT_LDA && mIns[i + 4].mMode == ASMIM_ZERO_PAGE && mIns[i + 4].mAddress == mIns[i + 0].mAddress && !(mIns[i + 4].mLive & LIVE_CPU_REG_Z))
// move high byte load down, if low byte is immediatedly needed afterwards
for (int i = 0; i + 4 < mIns.Size(); i++)
{
if (MoveStoreHighByteDown(i))
changed = true;
if (mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 1].mType == ASMIT_LDY && mIns[i + 1].mMode == ASMIM_IMMEDIATE &&
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_INDIRECT_Y && mIns[i + 2].mAddress != mIns[i + 3].mAddress && mIns[i + 2].mAddress + 1 != mIns[i + 3].mAddress &&
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress != mIns[i + 0].mAddress &&
mIns[i + 4].mType == ASMIT_LDA && mIns[i + 4].mMode == ASMIM_ZERO_PAGE && mIns[i + 4].mAddress == mIns[i + 0].mAddress && !(mIns[i + 4].mLive & LIVE_CPU_REG_Z))
{
if (MoveStoreHighByteDown(i))
changed = true;
}
}
for (int i = 0; i + 4 < mIns.Size(); i++)
{
if (mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress != mIns[i + 0].mAddress &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE &&
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress != mIns[i + 0].mAddress &&
mIns[i + 4].mType == ASMIT_LDA && mIns[i + 4].mMode == ASMIM_ZERO_PAGE && mIns[i + 4].mAddress == mIns[i + 0].mAddress && !(mIns[i + 4].mLive & LIVE_CPU_REG_Z))
{
if (MoveAddHighByteDown(i))
changed = true;
}
}
}
#endif
bool progress = false;
do {
progress = false;
int i = 0;
int j = 0;
while (i < mIns.Size())
{
if (mIns[i].mType == ASMIT_NOP)
;
else
{
if (i != j)
mIns[j] = mIns[i];
j++;
}
i++;
}
if (j != i)
changed = true;
mIns.SetSize(j);
changed = RemoveNops();
// Replace (a & 0x80) != 0 with bpl/bmi
int sz = mIns.Size();
if (sz > 1 &&
mIns[sz - 2].ChangesAccuAndFlag() &&
mIns[sz - 1].mType == ASMIT_AND && mIns[sz - 1].mMode == ASMIM_IMMEDIATE && mIns[sz - 1].mAddress == 0x80 && !(mIns[i].mLive & LIVE_CPU_REG_A))
mIns[sz - 1].mType == ASMIT_AND && mIns[sz - 1].mMode == ASMIM_IMMEDIATE && mIns[sz - 1].mAddress == 0x80 && !(mIns[sz - 1].mLive & LIVE_CPU_REG_A))
{
if (mBranch == ASMIT_BEQ)
{
@ -9282,6 +9344,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
}
else if (mIns[i].mType == ASMIT_STA && mIns[i + 1].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == mIns[i + 1].mAddress && (mIns[i + 1].mLive & LIVE_CPU_REG_Z) == 0)
{
mIns[i + 1].mLive |= LIVE_CPU_REG_A;
mIns[i + 1].mType = ASMIT_NOP;
progress = true;
}
@ -9999,9 +10062,9 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
} while (progress);
if (this->mTrueJump && this->mTrueJump->PeepHoleOptimizer())
if (this->mTrueJump && this->mTrueJump->PeepHoleOptimizer(pass))
changed = true;
if (this->mFalseJump && this->mFalseJump->PeepHoleOptimizer())
if (this->mFalseJump && this->mFalseJump->PeepHoleOptimizer(pass))
changed = true;
return changed;
@ -10623,7 +10686,7 @@ void NativeCodeProcedure::Optimize(void)
} while (changed);
#endif
ResetVisited();
if (mEntryBlock->PeepHoleOptimizer())
if (mEntryBlock->PeepHoleOptimizer(step))
changed = true;
ResetVisited();

View File

@ -120,7 +120,8 @@ public:
void Assemble(void);
void Close(NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock* falseJump, AsmInsType branch);
bool PeepHoleOptimizer(void);
bool RemoveNops(void);
bool PeepHoleOptimizer(int pass);
void BlockSizeReduction(void);
bool OptimizeSimpleLoop(NativeCodeProcedure* proc);
bool OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCodeBasicBlock* head, NativeCodeBasicBlock* tail, GrowingArray<NativeCodeBasicBlock*>& blocks);
@ -179,6 +180,7 @@ public:
bool FindGlobalAddressSumY(int at, int reg, bool direct, int& apos, const NativeCodeInstruction * & ains, const NativeCodeInstruction*& iins, uint32 & flags);
bool MoveStoreXUp(int at);
bool MoveStoreHighByteDown(int at);
bool MoveAddHighByteDown(int at);
bool ValueForwarding(const NativeRegisterDataSet& data);