refine move cost calculation to avoid indirect moves (e.g. memory to memory)

This commit is contained in:
Joel Dice 2009-11-28 18:17:17 +00:00
parent 5ead8fab17
commit c615db31fb

View File

@ -36,6 +36,12 @@ const unsigned StealRegisterReserveCount = 2;
// compare instruction: // compare instruction:
const unsigned ResolveRegisterReserveCount = (BytesPerWord == 8 ? 2 : 4); const unsigned ResolveRegisterReserveCount = (BytesPerWord == 8 ? 2 : 4);
const unsigned RegisterCopyCost = 1;
const unsigned AddressCopyCost = 2;
const unsigned ConstantCopyCost = 3;
const unsigned MemoryCopyCost = 4;
const unsigned CopyPenalty = 10;
class Context; class Context;
class Value; class Value;
class Stack; class Stack;
@ -1247,6 +1253,7 @@ class Target {
static const unsigned MinimumFrameCost = 1; static const unsigned MinimumFrameCost = 1;
static const unsigned StealPenalty = 2; static const unsigned StealPenalty = 2;
static const unsigned StealUniquePenalty = 4; static const unsigned StealUniquePenalty = 4;
static const unsigned IndirectMovePenalty = 4;
static const unsigned LowRegisterPenalty = 10; static const unsigned LowRegisterPenalty = 10;
static const unsigned Impossible = 20; static const unsigned Impossible = 20;
@ -1277,37 +1284,49 @@ valueType(Context* c, Compiler::OperandType type)
} }
} }
Target class CostCalculator {
pickTarget(Context* c, Read* r, bool intersectRead, public:
unsigned registerReserveCount); virtual unsigned cost(Context* c, uint8_t typeMask, uint32_t registerMask,
int frameIndex) = 0;
};
unsigned unsigned
resourceCost(Context* c UNUSED, Value* v, Resource* r) resourceCost(Context* c, Value* v, Resource* r, uint8_t typeMask,
uint32_t registerMask, int frameIndex,
CostCalculator* costCalculator)
{ {
if (r->reserved or r->freezeCount or r->referenceCount) { if (r->reserved or r->freezeCount or r->referenceCount) {
return Target::Impossible; return Target::Impossible;
} else if (r->value) { } else {
unsigned baseCost = costCalculator ? costCalculator->cost
(c, typeMask, registerMask, frameIndex) : 0;
if (r->value) {
assert(c, findSite(c, r->value, r->site)); assert(c, findSite(c, r->value, r->site));
if (v and buddies(r->value, v)) { if (v and buddies(r->value, v)) {
return 0; return baseCost;
} else if (uniqueSite(c, r->value, r->site)) { } else if (uniqueSite(c, r->value, r->site)) {
return Target::StealUniquePenalty; return baseCost + Target::StealUniquePenalty;
} else { } else {
return Target::StealPenalty; return baseCost = Target::StealPenalty;
} }
} else { } else {
return 0; return baseCost;
}
} }
} }
bool bool
pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target, pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target,
unsigned* cost) unsigned* cost, CostCalculator* costCalculator = 0)
{ {
if ((1 << i) & mask) { if ((1 << i) & mask) {
RegisterResource* r = c->registerResources + i; RegisterResource* r = c->registerResources + i;
unsigned myCost = resourceCost(c, v, r) + Target::MinimumRegisterCost; unsigned myCost = resourceCost
(c, v, r, 1 << RegisterOperand, 1 << i, NoFrameIndex, costCalculator)
+ Target::MinimumRegisterCost;
if ((static_cast<uint32_t>(1) << i) == mask) { if ((static_cast<uint32_t>(1) << i) == mask) {
*cost = myCost; *cost = myCost;
return true; return true;
@ -1320,7 +1339,8 @@ pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target,
} }
int int
pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost) pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
CostCalculator* costCalculator = 0)
{ {
int target = NoRegister; int target = NoRegister;
*cost = Target::Impossible; *cost = Target::Impossible;
@ -1329,7 +1349,7 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost)
for (int i = c->generalRegisterLimit - 1; for (int i = c->generalRegisterLimit - 1;
i >= c->generalRegisterStart; --i) i >= c->generalRegisterStart; --i)
{ {
if (pickRegisterTarget(c, i, v, mask, &target, cost)) { if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) {
return i; return i;
} }
} }
@ -1339,7 +1359,7 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost)
for (int i = c->floatRegisterStart; for (int i = c->floatRegisterStart;
i < static_cast<int>(c->floatRegisterLimit); ++i) i < static_cast<int>(c->floatRegisterLimit); ++i)
{ {
if (pickRegisterTarget(c, i, v, mask, &target, cost)) { if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) {
return i; return i;
} }
} }
@ -1349,29 +1369,34 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost)
} }
Target Target
pickRegisterTarget(Context* c, Value* v, uint32_t mask) pickRegisterTarget(Context* c, Value* v, uint32_t mask,
CostCalculator* costCalculator = 0)
{ {
unsigned cost; unsigned cost;
int number = pickRegisterTarget(c, v, mask, &cost); int number = pickRegisterTarget(c, v, mask, &cost, costCalculator);
return Target(number, RegisterOperand, cost); return Target(number, RegisterOperand, cost);
} }
unsigned unsigned
frameCost(Context* c, Value* v, int frameIndex) frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator)
{ {
return resourceCost(c, v, c->frameResources + frameIndex) return resourceCost
(c, v, c->frameResources + frameIndex, 1 << MemoryOperand, 0, frameIndex,
costCalculator)
+ Target::MinimumFrameCost; + Target::MinimumFrameCost;
} }
Target Target
pickFrameTarget(Context* c, Value* v) pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
{ {
Target best; Target best;
Value* p = v; Value* p = v;
do { do {
if (p->home >= 0) { if (p->home >= 0) {
Target mine(p->home, MemoryOperand, frameCost(c, v, p->home)); Target mine
(p->home, MemoryOperand, frameCost(c, v, p->home, costCalculator));
if (mine.cost == Target::MinimumFrameCost) { if (mine.cost == Target::MinimumFrameCost) {
return mine; return mine;
} else if (mine.cost < best.cost) { } else if (mine.cost < best.cost) {
@ -1385,13 +1410,13 @@ pickFrameTarget(Context* c, Value* v)
} }
Target Target
pickAnyFrameTarget(Context* c, Value* v) pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
{ {
Target best; Target best;
unsigned count = totalFrameSize(c); unsigned count = totalFrameSize(c);
for (unsigned i = 0; i < count; ++i) { for (unsigned i = 0; i < count; ++i) {
Target mine(i, MemoryOperand, frameCost(c, v, i)); Target mine(i, MemoryOperand, frameCost(c, v, i, costCalculator));
if (mine.cost == Target::MinimumFrameCost) { if (mine.cost == Target::MinimumFrameCost) {
return mine; return mine;
} else if (mine.cost < best.cost) { } else if (mine.cost < best.cost) {
@ -1404,10 +1429,12 @@ pickAnyFrameTarget(Context* c, Value* v)
Target Target
pickTarget(Context* c, Value* value, const SiteMask& mask, pickTarget(Context* c, Value* value, const SiteMask& mask,
unsigned registerPenalty, Target best) unsigned registerPenalty, Target best,
CostCalculator* costCalculator)
{ {
if (mask.typeMask & (1 << RegisterOperand)) { if (mask.typeMask & (1 << RegisterOperand)) {
Target mine = pickRegisterTarget(c, value, mask.registerMask); Target mine = pickRegisterTarget
(c, value, mask.registerMask, costCalculator);
mine.cost += registerPenalty; mine.cost += registerPenalty;
if (mine.cost == Target::MinimumRegisterCost) { if (mine.cost == Target::MinimumRegisterCost) {
@ -1420,14 +1447,14 @@ pickTarget(Context* c, Value* value, const SiteMask& mask,
if (mask.typeMask & (1 << MemoryOperand)) { if (mask.typeMask & (1 << MemoryOperand)) {
if (mask.frameIndex >= 0) { if (mask.frameIndex >= 0) {
Target mine(mask.frameIndex, MemoryOperand, Target mine(mask.frameIndex, MemoryOperand,
frameCost(c, value, mask.frameIndex)); frameCost(c, value, mask.frameIndex, costCalculator));
if (mine.cost == Target::MinimumFrameCost) { if (mine.cost == Target::MinimumFrameCost) {
return mine; return mine;
} else if (mine.cost < best.cost) { } else if (mine.cost < best.cost) {
best = mine; best = mine;
} }
} else if (mask.frameIndex == AnyFrameIndex) { } else if (mask.frameIndex == AnyFrameIndex) {
Target mine = pickFrameTarget(c, value); Target mine = pickFrameTarget(c, value, costCalculator);
if (mine.cost == Target::MinimumFrameCost) { if (mine.cost == Target::MinimumFrameCost) {
return mine; return mine;
} else if (mine.cost < best.cost) { } else if (mine.cost < best.cost) {
@ -1441,7 +1468,7 @@ pickTarget(Context* c, Value* value, const SiteMask& mask,
Target Target
pickTarget(Context* c, Read* read, bool intersectRead, pickTarget(Context* c, Read* read, bool intersectRead,
unsigned registerReserveCount) unsigned registerReserveCount, CostCalculator* costCalculator)
{ {
unsigned registerPenalty unsigned registerPenalty
= (c->availableGeneralRegisterCount > registerReserveCount = (c->availableGeneralRegisterCount > registerReserveCount
@ -1463,7 +1490,9 @@ pickTarget(Context* c, Read* read, bool intersectRead,
if (r) { if (r) {
SiteMask intersection = mask; SiteMask intersection = mask;
if (r->intersect(&intersection)) { if (r->intersect(&intersection)) {
best = pickTarget(c, value, intersection, registerPenalty, best); best = pickTarget
(c, value, intersection, registerPenalty, best, costCalculator);
if (best.cost <= Target::MinimumFrameCost) { if (best.cost <= Target::MinimumFrameCost) {
return best; return best;
} }
@ -1471,7 +1500,7 @@ pickTarget(Context* c, Read* read, bool intersectRead,
} }
} }
best = pickTarget(c, value, mask, registerPenalty, best); best = pickTarget(c, value, mask, registerPenalty, best, costCalculator);
if (best.cost <= Target::MinimumFrameCost) { if (best.cost <= Target::MinimumFrameCost) {
return best; return best;
} }
@ -1485,7 +1514,7 @@ pickTarget(Context* c, Read* read, bool intersectRead,
return best; return best;
} }
{ Target mine = pickRegisterTarget(c, value, registerMask); { Target mine = pickRegisterTarget(c, value, registerMask, costCalculator);
mine.cost += registerPenalty; mine.cost += registerPenalty;
@ -1496,7 +1525,7 @@ pickTarget(Context* c, Read* read, bool intersectRead,
} }
} }
{ Target mine = pickFrameTarget(c, value); { Target mine = pickFrameTarget(c, value, costCalculator);
if (mine.cost == Target::MinimumFrameCost) { if (mine.cost == Target::MinimumFrameCost) {
return mine; return mine;
} else if (mine.cost < best.cost) { } else if (mine.cost < best.cost) {
@ -1510,7 +1539,7 @@ pickTarget(Context* c, Read* read, bool intersectRead,
// there are no free registers left, so moving from memory to // there are no free registers left, so moving from memory to
// memory isn't an option - try harder to find an available frame // memory isn't an option - try harder to find an available frame
// site: // site:
best = pickAnyFrameTarget(c, value); best = pickAnyFrameTarget(c, value, costCalculator);
assert(c, best.cost <= 3); assert(c, best.cost <= 3);
} }
@ -1558,7 +1587,7 @@ class ConstantSite: public Site {
} }
virtual unsigned copyCost(Context*, Site* s) { virtual unsigned copyCost(Context*, Site* s) {
return (s == this ? 0 : 3); return (s == this ? 0 : ConstantCopyCost);
} }
virtual bool match(Context*, const SiteMask& mask) { virtual bool match(Context*, const SiteMask& mask) {
@ -1650,7 +1679,7 @@ class AddressSite: public Site {
} }
virtual unsigned copyCost(Context*, Site* s) { virtual unsigned copyCost(Context*, Site* s) {
return (s == this ? 0 : 2); return (s == this ? 0 : AddressCopyCost);
} }
virtual bool match(Context*, const SiteMask& mask) { virtual bool match(Context*, const SiteMask& mask) {
@ -1738,7 +1767,7 @@ class RegisterSite: public Site {
{ {
return 0; return 0;
} else { } else {
return 1; return RegisterCopyCost;
} }
} }
@ -1928,7 +1957,7 @@ class MemorySite: public Site {
{ {
return 0; return 0;
} else { } else {
return 4; return MemoryCopyCost;
} }
} }
@ -2186,10 +2215,15 @@ sitesToString(Context* c, Value* v, char* buffer, unsigned size)
Site* Site*
pickTargetSite(Context* c, Read* read, bool intersectRead = false, pickTargetSite(Context* c, Read* read, bool intersectRead = false,
unsigned registerReserveCount = 0) unsigned registerReserveCount = 0,
CostCalculator* costCalculator = 0)
{ {
Target target(pickTarget(c, read, intersectRead, registerReserveCount)); Target target
(pickTarget
(c, read, intersectRead, registerReserveCount, costCalculator));
expect(c, target.cost < Target::Impossible); expect(c, target.cost < Target::Impossible);
if (target.type == MemoryOperand) { if (target.type == MemoryOperand) {
return frameSite(c, target.index); return frameSite(c, target.index);
} else { } else {
@ -2298,11 +2332,49 @@ Site*
maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord, maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord,
unsigned registerReserveCount = 0) unsigned registerReserveCount = 0)
{ {
Site* dst = pickTargetSite(c, read, intersectRead, registerReserveCount);
Value* value = read->value; Value* value = read->value;
unsigned size = value == value->nextWord ? BytesPerWord : 8; unsigned size = value == value->nextWord ? BytesPerWord : 8;
class MyCostCalculator: public CostCalculator {
public:
MyCostCalculator(Value* value, unsigned size, bool includeNextWord):
value(value),
size(size),
includeNextWord(includeNextWord)
{ }
virtual unsigned cost(Context* c, uint8_t typeMask, uint32_t registerMask,
int frameIndex)
{
uint8_t srcTypeMask;
uint64_t srcRegisterMask;
uint8_t tmpTypeMask;
uint64_t tmpRegisterMask;
c->arch->planMove
(size, &srcTypeMask, &srcRegisterMask,
&tmpTypeMask, &tmpRegisterMask,
typeMask, registerMask);
SiteMask srcMask(srcTypeMask, srcRegisterMask, AnyFrameIndex);
SiteMask dstMask(typeMask, registerMask, frameIndex);
for (SiteIterator it(c, value, true, includeNextWord); it.hasMore();) {
Site* s = it.next();
if (s->match(c, srcMask) or s->match(c, dstMask)) {
return 0;
}
}
return Target::IndirectMovePenalty;
}
Value* value;
unsigned size;
bool includeNextWord;
} costCalculator(value, size, includeNextWord);
Site* dst = pickTargetSite
(c, read, intersectRead, registerReserveCount, &costCalculator);
uint8_t srcTypeMask; uint8_t srcTypeMask;
uint64_t srcRegisterMask; uint64_t srcRegisterMask;
uint8_t tmpTypeMask; uint8_t tmpTypeMask;
@ -2313,21 +2385,22 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord,
1 << dst->type(c), dst->registerMask(c)); 1 << dst->type(c), dst->registerMask(c));
SiteMask srcMask(srcTypeMask, srcRegisterMask, AnyFrameIndex); SiteMask srcMask(srcTypeMask, srcRegisterMask, AnyFrameIndex);
SingleRead srcRead(srcMask, 0); unsigned cost = 0xFFFFFFFF;
srcRead.value = value; Site* src = 0;
for (SiteIterator it(c, value, true, includeNextWord); it.hasMore();) {
unsigned cost; Site* s = it.next();
Site* src = pickSourceSite unsigned v = s->copyCost(c, dst);
(c, &srcRead, dst, &cost, ~0, true, true, includeNextWord); if (v == 0) {
src = s;
if (src == 0 or cost) { cost = 0;
unsigned cost2; break;
Site* src2 = pickSourceSite }
(c, &srcRead, dst, &cost2, ~0, false, true, includeNextWord); if (not s->match(c, srcMask)) {
v += CopyPenalty;
if (src == 0 or cost2 == 0) { }
src = src2; if (v < cost) {
cost = cost2; src = s;
cost = v;
} }
} }
@ -2339,6 +2412,7 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord,
SiteMask tmpMask(tmpTypeMask, tmpRegisterMask, AnyFrameIndex); SiteMask tmpMask(tmpTypeMask, tmpRegisterMask, AnyFrameIndex);
SingleRead tmpRead(tmpMask, 0); SingleRead tmpRead(tmpMask, 0);
tmpRead.value = value; tmpRead.value = value;
tmpRead.successor_ = value;
Site* tmp = pickTargetSite(c, &tmpRead, true); Site* tmp = pickTargetSite(c, &tmpRead, true);
@ -2377,6 +2451,8 @@ pickSiteOrMove(Context* c, Value* v, const SiteMask& mask, bool intersectMask,
{ {
SingleRead read(mask, 0); SingleRead read(mask, 0);
read.value = v; read.value = v;
read.successor_ = v;
return pickSiteOrMove return pickSiteOrMove
(c, &read, intersectMask, includeNextWord, registerReserveCount); (c, &read, intersectMask, includeNextWord, registerReserveCount);
} }
@ -3685,6 +3761,7 @@ getTarget(Context* c, Value* value, Value* result, const SiteMask& resultMask)
} else { } else {
SingleRead r(resultMask, 0); SingleRead r(resultMask, 0);
r.value = result; r.value = result;
r.successor_ = result;
s = pickTargetSite(c, &r, true); s = pickTargetSite(c, &r, true);
v = result; v = result;
addSite(c, result, s); addSite(c, result, s);