Reverse integer range limit calculation

This commit is contained in:
drmortalwombat 2022-04-15 11:06:49 +02:00
parent 8f32b87b18
commit 72d2fc1fac
13 changed files with 241 additions and 56 deletions

View File

@ -0,0 +1,22 @@
int a[10];
int get(int i)
{
return a[i];
}
void put(int i, int x)
{
a[i] = x;
}
int main(void)
{
for(int j=0; j<10; j++)
put(j, j);
int s = -45;
for(int j=0; j<10; j++)
s += get[j];
return s;
}

View File

@ -1,5 +1,6 @@
// stdlibtest
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

View File

@ -158,7 +158,7 @@ struct sinfo
bool sign, left, prefix;
};
inline int nformi(const sinfo * si, char * str, int v, bool s)
int nformi(const sinfo * si, char * str, int v, bool s)
{
char * sp = str;

View File

@ -26,6 +26,13 @@ IntegerValueRange::IntegerValueRange(void)
IntegerValueRange::~IntegerValueRange(void)
{}
void IntegerValueRange::Reset(void)
{
mMinState = S_UNKNOWN;
mMaxState = S_UNKNOWN;
}
bool IntegerValueRange::Same(const IntegerValueRange& range) const
{
if (mMinState == range.mMinState && mMaxState == range.mMaxState)
@ -83,7 +90,15 @@ bool IntegerValueRange::IsConstant(void) const
return mMinState == S_BOUND && mMaxState == S_BOUND && mMinValue == mMaxValue;
}
bool IntegerValueRange::Merge(const IntegerValueRange& range, bool head)
void IntegerValueRange::Limit(const IntegerValueRange& range)
{
if (range.mMinState == S_BOUND)
LimitMin(range.mMinValue);
if (range.mMaxState == S_BOUND)
LimitMax(range.mMaxValue);
}
bool IntegerValueRange::Merge(const IntegerValueRange& range, bool head, bool initial)
{
bool changed = false;
@ -118,12 +133,12 @@ bool IntegerValueRange::Merge(const IntegerValueRange& range, bool head)
}
else if (range.mMinValue < mMinValue)
{
if (range.mMinState == S_WEAK)
if (range.mMinState == S_WEAK && (initial || !head))
mMinState = S_WEAK;
mMinValue = range.mMinValue;
changed = true;
}
else if (mMinState == S_BOUND && range.mMinState == S_WEAK && !head)
else if (mMinState == S_BOUND && range.mMinState == S_WEAK && (initial || !head))
{
mMinState = S_WEAK;
changed = true;
@ -161,12 +176,12 @@ bool IntegerValueRange::Merge(const IntegerValueRange& range, bool head)
}
else if (range.mMaxValue > mMaxValue)
{
if (range.mMaxState == S_WEAK)
if (range.mMaxState == S_WEAK && (initial || !head))
mMaxState = S_WEAK;
mMaxValue = range.mMaxValue;
changed = true;
}
else if (mMaxState == S_BOUND && range.mMaxState == S_WEAK && !head)
else if (mMaxState == S_BOUND && range.mMaxState == S_WEAK && (initial || !head))
{
mMaxState = S_WEAK;
changed = true;
@ -3443,7 +3458,7 @@ void InterInstruction::Disassemble(FILE* file)
InterCodeBasicBlock::InterCodeBasicBlock(void)
: mInstructions(nullptr), mEntryRenameTable(-1), mExitRenameTable(-1), mMergeTValues(nullptr), mTrueJump(nullptr), mFalseJump(nullptr), mLoopPrefix(nullptr), mDominator(nullptr),
mEntryValueRange(IntegerValueRange()), mTrueValueRange(IntegerValueRange()), mFalseValueRange(IntegerValueRange()), mLocalValueRange(IntegerValueRange()), mEntryBlocks(nullptr), mLoadStoreInstructions(nullptr), mLoopPathBlocks(nullptr)
mEntryValueRange(IntegerValueRange()), mTrueValueRange(IntegerValueRange()), mFalseValueRange(IntegerValueRange()), mLocalValueRange(IntegerValueRange()), mReverseValueRange(IntegerValueRange()), mEntryBlocks(nullptr), mLoadStoreInstructions(nullptr), mLoopPathBlocks(nullptr)
{
mInPath = false;
mLoopHead = false;
@ -3602,7 +3617,7 @@ void InterCodeBasicBlock::GenerateTraces(bool expand)
if (mFalseJump)
mFalseJump->mNumEntries++;
}
else if (mTrueJump && !mFalseJump && ((expand && mTrueJump->mInstructions.Size() < 10 && mTrueJump->mInstructions.Size() > 1) || mTrueJump->mNumEntries == 1) && !mTrueJump->mLoopHead && !IsInfiniteLoop(mTrueJump, mTrueJump))
else if (mTrueJump && !mFalseJump && ((expand && mTrueJump->mInstructions.Size() < 10 && mTrueJump->mInstructions.Size() > 1 && !mLoopHead) || mTrueJump->mNumEntries == 1) && !mTrueJump->mLoopHead && !IsInfiniteLoop(mTrueJump, mTrueJump))
{
mTrueJump->mNumEntries--;
int n = mTrueJump->mNumEntries;
@ -4797,7 +4812,8 @@ void InterCodeBasicBlock::SimplifyIntegerRangeRelops(void)
}
}
bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(void)
bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(bool initial)
{
bool changed = false;
@ -4816,7 +4832,7 @@ bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(void)
else
{
for (int i = 0; i < mLocalValueRange.Size(); i++)
mLocalValueRange[i].Merge(range[i], mLoopHead);
mLocalValueRange[i].Merge(range[i], mLoopHead, initial);
}
}
@ -4838,9 +4854,9 @@ bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(void)
UpdateLocalIntegerRangeSets();
}
if (mTrueJump && mTrueJump->BuildGlobalIntegerRangeSets())
if (mTrueJump && mTrueJump->BuildGlobalIntegerRangeSets(initial))
changed = true;
if (mFalseJump && mFalseJump->BuildGlobalIntegerRangeSets())
if (mFalseJump && mFalseJump->BuildGlobalIntegerRangeSets(initial))
changed = true;
}
@ -5330,6 +5346,131 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
}
#if 1
mReverseValueRange.SetSize(mLocalValueRange.Size());
GrowingArray<int64> msize(0);
msize.SetSize(mLocalValueRange.Size());
for (int i = 0; i < mReverseValueRange.Size(); i++)
mReverseValueRange[i].Reset();
for (int i = sz - 1; i >= 0; i--)
{
InterInstruction* ins(mInstructions[i]);
if (ins->mCode == IC_LOAD && ins->mSrc[0].mMemory == IM_INDIRECT && ins->mSrc[0].mTemp >= 0)
msize[ins->mSrc[0].mTemp] = int64max(msize[ins->mSrc[0].mTemp], ins->mSrc[0].mIntConst + InterTypeSize[ins->mDst.mType]);
else if (ins->mCode == IC_STORE && ins->mSrc[1].mMemory == IM_INDIRECT && ins->mSrc[1].mTemp >= 0)
msize[ins->mSrc[1].mTemp] = int64max(msize[ins->mSrc[1].mTemp], ins->mSrc[1].mIntConst + InterTypeSize[ins->mSrc[0].mType]);
else if (ins->mCode == IC_LEA && ins->mSrc[1].mMemory != IM_INDIRECT && ins->mSrc[0].mTemp >= 0 && msize[ins->mDst.mTemp] > 0)
{
int asize = 0;
if (ins->mSrc[1].mMemory == IM_GLOBAL)
asize = ins->mSrc[1].mLinkerObject->mSize;
if (asize > 0)
{
mReverseValueRange[ins->mSrc[0].mTemp].LimitMin(0);
mReverseValueRange[ins->mSrc[0].mTemp].LimitMax(asize - msize[ins->mDst.mTemp]);
}
}
if (ins->mDst.mTemp >= 0)
{
ins->mDst.mRange.Limit(mReverseValueRange[ins->mDst.mTemp]);
mReverseValueRange[ins->mDst.mTemp].Reset();
IntegerValueRange& vr(ins->mDst.mRange);
switch (ins->mCode)
{
case IC_BINARY_OPERATOR:
switch (ins->mOperator)
{
case IA_SHL:
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[1].mTemp >= 0)
{
if (vr.mMinState == IntegerValueRange::S_BOUND)
ins->mSrc[1].mRange.LimitMin(vr.mMinValue >> ins->mSrc[0].mIntConst);
if (vr.mMaxState == IntegerValueRange::S_BOUND)
ins->mSrc[1].mRange.LimitMax(vr.mMaxValue >> ins->mSrc[0].mIntConst);
mReverseValueRange[ins->mSrc[1].mTemp].Limit(ins->mSrc[1].mRange);
}
break;
case IA_SUB:
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[1].mTemp >= 0)
{
if (vr.mMinState == IntegerValueRange::S_BOUND)
ins->mSrc[1].mRange.LimitMin(vr.mMinValue + ins->mSrc[0].mIntConst);
if (vr.mMaxState == IntegerValueRange::S_BOUND)
ins->mSrc[1].mRange.LimitMax(vr.mMaxValue + ins->mSrc[0].mIntConst);
mReverseValueRange[ins->mSrc[1].mTemp].Limit(ins->mSrc[1].mRange);
}
break;
case IA_ADD:
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[1].mTemp >= 0)
{
if (vr.mMinState == IntegerValueRange::S_BOUND)
ins->mSrc[1].mRange.LimitMin(vr.mMinValue - ins->mSrc[0].mIntConst);
if (vr.mMaxState == IntegerValueRange::S_BOUND)
ins->mSrc[1].mRange.LimitMax(vr.mMaxValue - ins->mSrc[0].mIntConst);
mReverseValueRange[ins->mSrc[1].mTemp].Limit(ins->mSrc[1].mRange);
}
else if (ins->mSrc[1].mTemp < 0 && ins->mSrc[0].mTemp >= 0)
{
if (vr.mMinState == IntegerValueRange::S_BOUND)
ins->mSrc[0].mRange.LimitMin(vr.mMinValue - ins->mSrc[1].mIntConst);
if (vr.mMaxState == IntegerValueRange::S_BOUND)
ins->mSrc[0].mRange.LimitMax(vr.mMaxValue - ins->mSrc[1].mIntConst);
mReverseValueRange[ins->mSrc[0].mTemp].Limit(ins->mSrc[0].mRange);
}
break;
case IA_MUL:
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[1].mTemp >= 0 && ins->mSrc[0].mIntConst > 0)
{
if (vr.mMinState == IntegerValueRange::S_BOUND)
ins->mSrc[1].mRange.LimitMin(vr.mMinValue / ins->mSrc[0].mIntConst);
if (vr.mMaxState == IntegerValueRange::S_BOUND)
ins->mSrc[1].mRange.LimitMax(vr.mMaxValue / ins->mSrc[0].mIntConst);
mReverseValueRange[ins->mSrc[1].mTemp].Limit(ins->mSrc[1].mRange);
}
else if (ins->mSrc[1].mTemp < 0 && ins->mSrc[0].mTemp >= 0 && ins->mSrc[1].mIntConst > 0)
{
if (vr.mMinState == IntegerValueRange::S_BOUND)
ins->mSrc[0].mRange.LimitMin(vr.mMinValue / ins->mSrc[1].mIntConst);
if (vr.mMaxState == IntegerValueRange::S_BOUND)
ins->mSrc[0].mRange.LimitMax(vr.mMaxValue / ins->mSrc[1].mIntConst);
mReverseValueRange[ins->mSrc[0].mTemp].Limit(ins->mSrc[0].mRange);
}
break;
}
break;
case IC_LEA:
if (ins->mSrc[1].mMemory == IM_INDIRECT && msize[ins->mDst.mTemp] > 0)
{
if (ins->mSrc[0].mTemp < 0)
{
msize[ins->mSrc[1].mTemp] = msize[ins->mDst.mTemp] - ins->mSrc[0].mIntConst;
}
else if (ins->mSrc[0].mRange.mMinState == IntegerValueRange::S_BOUND)
{
msize[ins->mSrc[1].mTemp] = msize[ins->mDst.mTemp] - ins->mSrc[0].mRange.mMinValue;
}
}
break;
}
}
for (int i = 0; i < ins->mNumOperands; i++)
{
if (ins->mSrc[i].mTemp >= 0)
ins->mSrc[i].mRange.Limit(mReverseValueRange[ins->mSrc[i].mTemp]);
}
if (ins->mDst.mTemp >= 0)
msize[ins->mDst.mTemp] = 0;
}
#endif
mTrueValueRange = mLocalValueRange;
mFalseValueRange = mLocalValueRange;
@ -7079,11 +7220,10 @@ bool InterCodeBasicBlock::ForwardDiamondMovedTemp(void)
if (mins->mCode == IC_LOAD_TEMPORARY)
{
int ttemp = mins->mDst.mTemp;
int stemp = mins->mSrc[0].mTemp;
if (!IsTempModifiedOnPath(ttemp, i + 1) && !IsTempModifiedOnPath(stemp, i + 1))
if (!IsTempModifiedOnPath(ttemp, i + 1) && !IsTempModifiedOnPath(stemp, i + 1) && !tblock->mExitRequiredTemps[stemp])
{
int j = 0;
while (j < tblock->mInstructions.Size() &&
@ -7107,6 +7247,8 @@ bool InterCodeBasicBlock::ForwardDiamondMovedTemp(void)
nins->mSrc[0].mType = mins->mDst.mType;
fblock->mInstructions.Insert(0, nins);
tblock->mExitRequiredTemps += stemp;
changed = true;
}
}
@ -9114,6 +9256,25 @@ void InterCodeBasicBlock::PeepholeOptimization(void)
mInstructions[i + 1]->mCode = IC_NONE; mInstructions[i + 1]->mNumOperands = 0;
changed = true;
}
else if (
mInstructions[i + 0]->mCode == IC_LEA && mInstructions[i + 0]->mSrc[1].mMemory == IM_GLOBAL &&
mInstructions[i + 1]->mCode == IC_LEA && mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[1].mFinal &&
mInstructions[i + 0]->mSrc[0].IsUByte() && mInstructions[i + 1]->mSrc[0].IsUByte() && mInstructions[i + 0]->mSrc[0].mRange.mMaxValue + mInstructions[i + 1]->mSrc[0].mRange.mMaxValue < 252)
{
mInstructions[i + 1]->mSrc[1] = mInstructions[i + 0]->mSrc[1];
mInstructions[i + 0]->mCode = IC_BINARY_OPERATOR;
mInstructions[i + 0]->mOperator = IA_ADD;
mInstructions[i + 0]->mSrc[1] = mInstructions[i + 1]->mSrc[0];
mInstructions[i + 0]->mDst.mType = IT_INT16;
mInstructions[i + 0]->mDst.mRange.mMaxState = IntegerValueRange::S_BOUND;
mInstructions[i + 0]->mDst.mRange.mMaxValue = mInstructions[i + 0]->mSrc[1].mRange.mMaxValue + mInstructions[i + 0]->mSrc[0].mRange.mMaxValue;
mInstructions[i + 0]->mDst.mRange.mMinState = IntegerValueRange::S_BOUND;
mInstructions[i + 0]->mDst.mRange.mMinValue = 0;
mInstructions[i + 1]->mSrc[0] = mInstructions[i + 0]->mDst;
changed = true;
}
#if 1
// Postincrement artifact
@ -10060,7 +10221,14 @@ void InterCodeProcedure::Close(void)
DisassembleDebug("tt");
ResetVisited();
} while (mEntryBlock->BuildGlobalIntegerRangeSets());
} while (mEntryBlock->BuildGlobalIntegerRangeSets(true));
do {
DisassembleDebug("tq");
ResetVisited();
} while (mEntryBlock->BuildGlobalIntegerRangeSets(false));
DisassembleDebug("Estimated value range");
#if 1
@ -10071,7 +10239,13 @@ void InterCodeProcedure::Close(void)
DisassembleDebug("tr");
ResetVisited();
} while (mEntryBlock->BuildGlobalIntegerRangeSets());
} while (mEntryBlock->BuildGlobalIntegerRangeSets(true));
do {
DisassembleDebug("tr");
ResetVisited();
} while (mEntryBlock->BuildGlobalIntegerRangeSets(false));
DisassembleDebug("Estimated value range 2");
#endif

View File

@ -136,6 +136,8 @@ public:
IntegerValueRange(void);
~IntegerValueRange(void);
void Reset(void);
int64 mMinValue, mMaxValue;
enum State
@ -147,7 +149,9 @@ public:
} mMinState, mMaxState;
bool Same(const IntegerValueRange& range) const;
bool Merge(const IntegerValueRange& range, bool head);
bool Merge(const IntegerValueRange& range, bool head, bool initial);
void Limit(const IntegerValueRange& range);
bool IsConstant(void) const;
@ -345,7 +349,7 @@ public:
GrowingInstructionArray mLoadStoreInstructions;
GrowingIntegerValueRangeArray mEntryValueRange, mTrueValueRange, mFalseValueRange, mLocalValueRange;
GrowingIntegerValueRangeArray mEntryValueRange, mTrueValueRange, mFalseValueRange, mLocalValueRange, mReverseValueRange;
GrowingArray<InterCodeBasicBlock*> mEntryBlocks, mLoopPathBlocks;
@ -395,7 +399,7 @@ public:
void RestartLocalIntegerRangeSets(void);
void BuildLocalIntegerRangeSets(int num);
void UpdateLocalIntegerRangeSets(void);
bool BuildGlobalIntegerRangeSets(void);
bool BuildGlobalIntegerRangeSets(bool initial);
void SimplifyIntegerRangeRelops(void);
GrowingIntArray mEntryRenameTable;

View File

@ -95,3 +95,7 @@ extern uint8 BC_REG_LOCALS;
extern uint8 BC_REG_TMP;
extern uint8 BC_REG_TMP_SAVED;
inline int64 int64max(int64 a, int64 b)
{
return a > b ? a : b;
}

View File

@ -11530,6 +11530,7 @@ bool NativeCodeBasicBlock::PatchForwardSumYPointer(const NativeCodeBasicBlock* b
bool done = !(ins.mLive & LIVE_MEM);
ins.mAddress = base;
ins.mFlags &= ~NCIF_YZERO;
if (ins.mLive & LIVE_CPU_REG_Y)
mIns.Insert(at + 1, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, yval));
@ -11562,6 +11563,13 @@ bool NativeCodeBasicBlock::PatchForwardSumYPointer(const NativeCodeBasicBlock* b
changed = true;
if (mFalseJump && mFalseJump->PatchForwardSumYPointer(block, reg, base, index, 0, yval))
changed = true;
if (changed)
{
mEntryRequiredRegs += base;
mEntryRequiredRegs += base + 1;
mEntryRequiredRegs += index;
}
}
return changed;
@ -12985,7 +12993,7 @@ bool NativeCodeBasicBlock::MoveStoreXUp(int at)
}
else
{
if (mIns[at - 1].mType == ASMIT_LDX || mIns[at - 1].mType == ASMIT_TAX)
if (mIns[at - 1].mType == ASMIT_LDX || mIns[at - 1].mType == ASMIT_TAX || mIns[at - 1].mType == ASMIT_TXA)
return done;
else if (mIns[at - 1].ChangesXReg() || mIns[at - 1].mType == ASMIT_STX)
return done;

View File

@ -1,24 +0,0 @@
#pragma once
enum TType
{
TT_VOID,
TT_NULL,
TT_BOOL,
TT_INTEGER,
TT_FLOAT,
TT_POINTER,
TT_ARRAY,
TT_STRUCT,
TT_UNION,
TT_FUNCTION
};
class Type
{
public:
TType mType;
Type* mBase;
Scope* mScope;
};

View File

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

View File

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

View File

@ -189,7 +189,6 @@
<ClInclude Include="Preprocessor.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="Scanner.h" />
<ClInclude Include="Type.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="oscar64.rc" />

View File

@ -128,9 +128,6 @@
<ClInclude Include="Scanner.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Type.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>

View File

@ -4023,15 +4023,15 @@
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64"
"ProductCode" = "8:{0ED76161-EB93-44B9-8ED5-B52DAE35B818}"
"PackageCode" = "8:{B9A27BFE-6C41-4995-B0B1-AA37F7D48E99}"
"ProductCode" = "8:{13BD934B-1637-4989-8616-270CF677ADF6}"
"PackageCode" = "8:{2EA4AD42-948A-48FA-A940-0325656775A8}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:1.5.116"
"ProductVersion" = "8:1.5.117"
"Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:"