[compiler] Inline 64bit immediates and RPO numbers in InstructionOperand

AddImmediate ends up pushing repeated immediates very often
unecessarily. Add support for Int64 immediates being inlined into
InstructionOperand if they fit into the payload (which is almost always
the case). Also add a seperate rpo_immediate vector for RPO numbers to
avoid having to add them to the immediates_ vector multiple times.
Ideally the RPO values would also be inlined, however JumpThreading
needs to patch RPO targets throughout the instruction stream, so we
need an indirection.

Change-Id: I75b1cdb05917f85d4f740a34c3720dd9cf0ee29c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2782282
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Santiago Aboy Solanes <solanes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73687}
This commit is contained in:
Ross McIlroy 2021-03-25 20:22:21 +00:00 committed by Commit Bot
parent 8f4298695e
commit 950b281ffe
14 changed files with 227 additions and 121 deletions

View File

@ -633,7 +633,7 @@ void CodeGenerator::AssembleTailCallBeforeGap(Instruction* instr,
LocationOperand source_location(LocationOperand::cast(source));
__ push(source_location.GetRegister());
} else if (source.IsImmediate()) {
__ Push(Immediate(ImmediateOperand::cast(source).inline_value()));
__ Push(Immediate(ImmediateOperand::cast(source).inline_int32_value()));
} else {
// Pushes of non-scalar data types is not supported.
UNIMPLEMENTED();

View File

@ -169,9 +169,13 @@ std::ostream& operator<<(std::ostream& os, const InstructionOperand& op) {
case InstructionOperand::IMMEDIATE: {
ImmediateOperand imm = ImmediateOperand::cast(op);
switch (imm.type()) {
case ImmediateOperand::INLINE:
return os << "#" << imm.inline_value();
case ImmediateOperand::INDEXED:
case ImmediateOperand::INLINE_INT32:
return os << "#" << imm.inline_int32_value();
case ImmediateOperand::INLINE_INT64:
return os << "#" << imm.inline_int64_value();
case ImmediateOperand::INDEXED_RPO:
return os << "[rpo_immediate:" << imm.indexed_value() << "]";
case ImmediateOperand::INDEXED_IMM:
return os << "[immediate:" << imm.indexed_value() << "]";
}
}
@ -834,6 +838,7 @@ InstructionSequence::InstructionSequence(Isolate* isolate,
constants_(ConstantMap::key_compare(),
ConstantMap::allocator_type(zone())),
immediates_(zone()),
rpo_immediates_(instruction_blocks->size(), zone()),
instructions_(zone()),
next_virtual_register_(0),
reference_maps_(zone()),

View File

@ -395,7 +395,7 @@ class ConstantOperand : public InstructionOperand {
class ImmediateOperand : public InstructionOperand {
public:
enum ImmediateType { INLINE, INDEXED };
enum ImmediateType { INLINE_INT32, INLINE_INT64, INDEXED_RPO, INDEXED_IMM };
explicit ImmediateOperand(ImmediateType type, int32_t value)
: InstructionOperand(IMMEDIATE) {
@ -406,13 +406,18 @@ class ImmediateOperand : public InstructionOperand {
ImmediateType type() const { return TypeField::decode(value_); }
int32_t inline_value() const {
DCHECK_EQ(INLINE, type());
int32_t inline_int32_value() const {
DCHECK_EQ(INLINE_INT32, type());
return static_cast<int64_t>(value_) >> ValueField::kShift;
}
int64_t inline_int64_value() const {
DCHECK_EQ(INLINE_INT64, type());
return static_cast<int64_t>(value_) >> ValueField::kShift;
}
int32_t indexed_value() const {
DCHECK_EQ(INDEXED, type());
DCHECK(type() == INDEXED_IMM || type() == INDEXED_RPO);
return static_cast<int64_t>(value_) >> ValueField::kShift;
}
@ -423,7 +428,7 @@ class ImmediateOperand : public InstructionOperand {
INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE)
STATIC_ASSERT(KindField::kSize == 3);
using TypeField = base::BitField64<ImmediateType, 3, 1>;
using TypeField = base::BitField64<ImmediateType, 3, 2>;
using ValueField = base::BitField64<int32_t, 32, 32>;
};
@ -1022,6 +1027,8 @@ std::ostream& operator<<(std::ostream&, const Instruction&);
class RpoNumber final {
public:
static const int kInvalidRpoNumber = -1;
RpoNumber() : index_(kInvalidRpoNumber) {}
int ToInt() const {
DCHECK(IsValid());
return index_;
@ -1091,8 +1098,15 @@ class V8_EXPORT_PRIVATE Constant final {
RelocInfo::Mode rmode() const { return rmode_; }
bool FitsInInt32() const {
if (type() == kInt32) return true;
DCHECK(type() == kInt64);
return value_ >= std::numeric_limits<int32_t>::min() &&
value_ <= std::numeric_limits<int32_t>::max();
}
int32_t ToInt32() const {
DCHECK(type() == kInt32 || type() == kInt64);
DCHECK(FitsInInt32());
const int32_t value = static_cast<int32_t>(value_);
DCHECK_EQ(value_, static_cast<int64_t>(value));
return value;
@ -1685,21 +1699,50 @@ class V8_EXPORT_PRIVATE InstructionSequence final
using Immediates = ZoneVector<Constant>;
Immediates& immediates() { return immediates_; }
using RpoImmediates = ZoneVector<RpoNumber>;
RpoImmediates& rpo_immediates() { return rpo_immediates_; }
ImmediateOperand AddImmediate(const Constant& constant) {
if (constant.type() == Constant::kInt32 &&
RelocInfo::IsNone(constant.rmode())) {
return ImmediateOperand(ImmediateOperand::INLINE, constant.ToInt32());
if (RelocInfo::IsNone(constant.rmode())) {
if (constant.type() == Constant::kRpoNumber) {
// Ideally we would inline RPO numbers into the operand, however jump-
// threading modifies RPO values and so we indirect through a vector
// of rpo_immediates to enable rewriting. We keep this seperate from the
// immediates vector so that we don't repeatedly push the same rpo
// number.
RpoNumber rpo_number = constant.ToRpoNumber();
DCHECK(!rpo_immediates().at(rpo_number.ToSize()).IsValid() ||
rpo_immediates().at(rpo_number.ToSize()) == rpo_number);
rpo_immediates()[rpo_number.ToSize()] = rpo_number;
return ImmediateOperand(ImmediateOperand::INDEXED_RPO,
rpo_number.ToInt());
} else if (constant.type() == Constant::kInt32) {
return ImmediateOperand(ImmediateOperand::INLINE_INT32,
constant.ToInt32());
} else if (constant.type() == Constant::kInt64 &&
constant.FitsInInt32()) {
return ImmediateOperand(ImmediateOperand::INLINE_INT64,
constant.ToInt32());
}
}
int index = static_cast<int>(immediates_.size());
immediates_.push_back(constant);
return ImmediateOperand(ImmediateOperand::INDEXED, index);
return ImmediateOperand(ImmediateOperand::INDEXED_IMM, index);
}
Constant GetImmediate(const ImmediateOperand* op) const {
switch (op->type()) {
case ImmediateOperand::INLINE:
return Constant(op->inline_value());
case ImmediateOperand::INDEXED: {
case ImmediateOperand::INLINE_INT32:
return Constant(op->inline_int32_value());
case ImmediateOperand::INLINE_INT64:
return Constant(op->inline_int64_value());
case ImmediateOperand::INDEXED_RPO: {
int index = op->indexed_value();
DCHECK_LE(0, index);
DCHECK_GT(rpo_immediates_.size(), index);
return Constant(rpo_immediates_[index]);
}
case ImmediateOperand::INDEXED_IMM: {
int index = op->indexed_value();
DCHECK_LE(0, index);
DCHECK_GT(immediates_.size(), index);
@ -1746,6 +1789,11 @@ class V8_EXPORT_PRIVATE InstructionSequence final
void RecomputeAssemblyOrderForTesting();
void IncreaseRpoForTesting(size_t rpo_count) {
DCHECK_GE(rpo_count, rpo_immediates().size());
rpo_immediates().resize(rpo_count);
}
private:
friend V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
const InstructionSequence&);
@ -1765,6 +1813,7 @@ class V8_EXPORT_PRIVATE InstructionSequence final
SourcePositionMap source_positions_;
ConstantMap constants_;
Immediates immediates_;
RpoImmediates rpo_immediates_;
InstructionDeque instructions_;
int next_virtual_register_;
ReferenceMapDeque reference_maps_;

View File

@ -131,8 +131,8 @@ bool JumpThreading::ComputeForwarding(Zone* local_zone,
// Dynamic return values might use different registers at
// different return sites and therefore cannot be shared.
if (instr->InputAt(0)->IsImmediate()) {
int32_t return_size =
ImmediateOperand::cast(instr->InputAt(0))->inline_value();
int32_t return_size = ImmediateOperand::cast(instr->InputAt(0))
->inline_int32_value();
// Instructions can be shared only for blocks that share
// the same |must_deconstruct_frame| attribute.
if (block->must_deconstruct_frame()) {
@ -243,13 +243,12 @@ void JumpThreading::ApplyForwarding(Zone* local_zone,
}
// Patch RPO immediates.
InstructionSequence::Immediates& immediates = code->immediates();
for (size_t i = 0; i < immediates.size(); i++) {
Constant constant = immediates[i];
if (constant.type() == Constant::kRpoNumber) {
RpoNumber rpo = constant.ToRpoNumber();
InstructionSequence::RpoImmediates& rpo_immediates = code->rpo_immediates();
for (size_t i = 0; i < rpo_immediates.size(); i++) {
RpoNumber rpo = rpo_immediates[i];
if (rpo.IsValid()) {
RpoNumber fw = result[rpo.ToInt()];
if (!(fw == rpo)) immediates[i] = Constant(fw);
if (fw != rpo) rpo_immediates[i] = fw;
}
}

View File

@ -1531,7 +1531,7 @@ int InstructionScheduler::GetInstructionLatency(const Instruction* instr) {
return ShrPairLatency();
} else {
// auto immediate_operand = ImmediateOperand::cast(instr->InputAt(2));
// return ShrPairLatency(false, immediate_operand->inline_value());
// return ShrPairLatency(false, immediate_operand->inline_32_value());
return 1;
}
}

View File

@ -44,6 +44,18 @@ void VerifyAllocatedGaps(const Instruction* instr, const char* caller_info) {
}
}
int GetValue(const ImmediateOperand* imm) {
switch (imm->type()) {
case ImmediateOperand::INLINE_INT32:
return imm->inline_int32_value();
case ImmediateOperand::INLINE_INT64:
return static_cast<int>(imm->inline_int64_value());
case ImmediateOperand::INDEXED_RPO:
case ImmediateOperand::INDEXED_IMM:
return imm->indexed_value();
}
}
} // namespace
RegisterAllocatorVerifier::RegisterAllocatorVerifier(
@ -151,10 +163,8 @@ void RegisterAllocatorVerifier::BuildConstraint(const InstructionOperand* op,
constraint->virtual_register_ = constraint->value_;
} else if (op->IsImmediate()) {
const ImmediateOperand* imm = ImmediateOperand::cast(op);
int value = imm->type() == ImmediateOperand::INLINE ? imm->inline_value()
: imm->indexed_value();
constraint->type_ = kImmediate;
constraint->value_ = value;
constraint->value_ = GetValue(imm);
} else {
CHECK(op->IsUnallocated());
const UnallocatedOperand* unallocated = UnallocatedOperand::cast(op);
@ -221,9 +231,7 @@ void RegisterAllocatorVerifier::CheckConstraint(
case kImmediate: {
CHECK_WITH_MSG(op->IsImmediate(), caller_info_);
const ImmediateOperand* imm = ImmediateOperand::cast(op);
int value = imm->type() == ImmediateOperand::INLINE
? imm->inline_value()
: imm->indexed_value();
int value = GetValue(imm);
CHECK_EQ(value, constraint->value_);
return;
}

View File

@ -808,7 +808,7 @@ void CodeGenerator::AssembleTailCallBeforeGap(Instruction* instr,
LocationOperand source_location(LocationOperand::cast(source));
__ Push(source_location.GetRegister());
} else if (source.IsImmediate()) {
__ Push(Immediate(ImmediateOperand::cast(source).inline_value()));
__ Push(Immediate(ImmediateOperand::cast(source).inline_int32_value()));
} else {
// Pushes of non-scalar data types is not supported.
UNIMPLEMENTED();

View File

@ -967,7 +967,8 @@ bool TryMatchLoadWord64AndShiftRight(InstructionSelector* selector, Node* node,
// immediate displacement. It seems that we never use M1 and M2, but we
// handle them here anyways.
mode = AddDisplacementToAddressingMode(mode);
inputs[input_count++] = ImmediateOperand(ImmediateOperand::INLINE, 4);
inputs[input_count++] =
ImmediateOperand(ImmediateOperand::INLINE_INT32, 4);
} else {
// In the case that the base address was zero, the displacement will be
// in a register and replacing it with an immediate is not allowed. This
@ -975,7 +976,7 @@ bool TryMatchLoadWord64AndShiftRight(InstructionSelector* selector, Node* node,
if (!inputs[input_count - 1].IsImmediate()) return false;
int32_t displacement = g.GetImmediateIntegerValue(mleft.displacement());
inputs[input_count - 1] =
ImmediateOperand(ImmediateOperand::INLINE, displacement + 4);
ImmediateOperand(ImmediateOperand::INLINE_INT32, displacement + 4);
}
InstructionOperand outputs[] = {g.DefineAsRegister(node)};
InstructionCode code = opcode | AddressingModeField::encode(mode);

View File

@ -1164,11 +1164,16 @@ std::ostream& operator<<(std::ostream& os, const InstructionOperandAsJSON& o) {
os << "\"type\": \"immediate\", ";
const ImmediateOperand* imm = ImmediateOperand::cast(op);
switch (imm->type()) {
case ImmediateOperand::INLINE: {
os << "\"text\": \"#" << imm->inline_value() << "\"";
case ImmediateOperand::INLINE_INT32: {
os << "\"text\": \"#" << imm->inline_int32_value() << "\"";
break;
}
case ImmediateOperand::INDEXED: {
case ImmediateOperand::INLINE_INT64: {
os << "\"text\": \"#" << imm->inline_int64_value() << "\"";
break;
}
case ImmediateOperand::INDEXED_RPO:
case ImmediateOperand::INDEXED_IMM: {
int index = imm->indexed_value();
os << "\"text\": \"imm:" << index << "\",";
os << "\"tooltip\": \"";

View File

@ -1062,9 +1062,9 @@ class CodeGeneratorTester {
AllocatedOperand(LocationOperand::REGISTER,
MachineRepresentation::kTagged,
kReturnRegister0.code()),
ImmediateOperand(ImmediateOperand::INLINE, -1), // poison index.
ImmediateOperand(ImmediateOperand::INLINE, optional_padding_slot),
ImmediateOperand(ImmediateOperand::INLINE, stack_slot_delta)};
ImmediateOperand(ImmediateOperand::INLINE_INT32, -1), // poison index.
ImmediateOperand(ImmediateOperand::INLINE_INT32, optional_padding_slot),
ImmediateOperand(ImmediateOperand::INLINE_INT32, stack_slot_delta)};
Instruction* tail_call =
Instruction::New(zone_, kArchTailCallCodeObject, 0, nullptr,
arraysize(callee), callee, 0, nullptr);
@ -1151,9 +1151,10 @@ class CodeGeneratorTester {
AllocatedOperand(LocationOperand::REGISTER,
MachineRepresentation::kTagged,
kReturnRegister0.code()),
ImmediateOperand(ImmediateOperand::INLINE, -1), // poison index.
ImmediateOperand(ImmediateOperand::INLINE, optional_padding_slot),
ImmediateOperand(ImmediateOperand::INLINE, first_unused_stack_slot)};
ImmediateOperand(ImmediateOperand::INLINE_INT32, -1), // poison index.
ImmediateOperand(ImmediateOperand::INLINE_INT32, optional_padding_slot),
ImmediateOperand(ImmediateOperand::INLINE_INT32,
first_unused_stack_slot)};
Instruction* tail_call =
Instruction::New(zone_, kArchTailCallCodeObject, 0, nullptr,
arraysize(callee), callee, 0, nullptr);

View File

@ -14,12 +14,14 @@ namespace compiler {
class TestCode : public HandleAndZoneScope {
public:
TestCode()
explicit TestCode(size_t block_count)
: HandleAndZoneScope(),
blocks_(main_zone()),
sequence_(main_isolate(), main_zone(), &blocks_),
rpo_number_(RpoNumber::FromInt(0)),
current_(nullptr) {}
current_(nullptr) {
sequence_.IncreaseRpoForTesting(block_count);
}
ZoneVector<InstructionBlock*> blocks_;
InstructionSequence sequence_;
@ -138,7 +140,8 @@ void VerifyForwarding(TestCode* code, int count, int* expected) {
}
TEST(FwEmpty1) {
TestCode code;
constexpr size_t kBlockCount = 3;
TestCode code(kBlockCount);
// B0
code.Jump(1);
@ -148,13 +151,14 @@ TEST(FwEmpty1) {
code.End();
static int expected[] = {2, 2, 2};
VerifyForwarding(&code, 3, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwEmptyN) {
constexpr size_t kBlockCount = 3;
for (int i = 0; i < 9; i++) {
TestCode code;
TestCode code(kBlockCount);
// B0
code.Jump(1);
@ -165,36 +169,39 @@ TEST(FwEmptyN) {
code.End();
static int expected[] = {2, 2, 2};
VerifyForwarding(&code, 3, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
}
TEST(FwNone1) {
TestCode code;
constexpr size_t kBlockCount = 1;
TestCode code(kBlockCount);
// B0
code.End();
static int expected[] = {0};
VerifyForwarding(&code, 1, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwMoves1) {
TestCode code;
constexpr size_t kBlockCount = 1;
TestCode code(kBlockCount);
// B0
code.RedundantMoves();
code.End();
static int expected[] = {0};
VerifyForwarding(&code, 1, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwMoves2) {
TestCode code;
constexpr size_t kBlockCount = 2;
TestCode code(kBlockCount);
// B0
code.RedundantMoves();
@ -203,12 +210,13 @@ TEST(FwMoves2) {
code.End();
static int expected[] = {1, 1};
VerifyForwarding(&code, 2, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwMoves2b) {
TestCode code;
constexpr size_t kBlockCount = 2;
TestCode code(kBlockCount);
// B0
code.NonRedundantMoves();
@ -217,12 +225,13 @@ TEST(FwMoves2b) {
code.End();
static int expected[] = {0, 1};
VerifyForwarding(&code, 2, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwOther2) {
TestCode code;
constexpr size_t kBlockCount = 2;
TestCode code(kBlockCount);
// B0
code.Other();
@ -231,12 +240,13 @@ TEST(FwOther2) {
code.End();
static int expected[] = {0, 1};
VerifyForwarding(&code, 2, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwNone2a) {
TestCode code;
constexpr size_t kBlockCount = 2;
TestCode code(kBlockCount);
// B0
code.Fallthru();
@ -244,12 +254,13 @@ TEST(FwNone2a) {
code.End();
static int expected[] = {1, 1};
VerifyForwarding(&code, 2, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwNone2b) {
TestCode code;
constexpr size_t kBlockCount = 2;
TestCode code(kBlockCount);
// B0
code.Jump(1);
@ -257,23 +268,25 @@ TEST(FwNone2b) {
code.End();
static int expected[] = {1, 1};
VerifyForwarding(&code, 2, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwLoop1) {
TestCode code;
constexpr size_t kBlockCount = 1;
TestCode code(kBlockCount);
// B0
code.Jump(0);
static int expected[] = {0};
VerifyForwarding(&code, 1, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwLoop2) {
TestCode code;
constexpr size_t kBlockCount = 2;
TestCode code(kBlockCount);
// B0
code.Fallthru();
@ -281,12 +294,13 @@ TEST(FwLoop2) {
code.Jump(0);
static int expected[] = {0, 0};
VerifyForwarding(&code, 2, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwLoop3) {
TestCode code;
constexpr size_t kBlockCount = 3;
TestCode code(kBlockCount);
// B0
code.Fallthru();
@ -296,12 +310,13 @@ TEST(FwLoop3) {
code.Jump(0);
static int expected[] = {0, 0, 0};
VerifyForwarding(&code, 3, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwLoop1b) {
TestCode code;
constexpr size_t kBlockCount = 2;
TestCode code(kBlockCount);
// B0
code.Fallthru();
@ -314,7 +329,8 @@ TEST(FwLoop1b) {
TEST(FwLoop2b) {
TestCode code;
constexpr size_t kBlockCount = 3;
TestCode code(kBlockCount);
// B0
code.Fallthru();
@ -324,12 +340,13 @@ TEST(FwLoop2b) {
code.Jump(1);
static int expected[] = {1, 1, 1};
VerifyForwarding(&code, 3, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwLoop3b) {
TestCode code;
constexpr size_t kBlockCount = 4;
TestCode code(kBlockCount);
// B0
code.Fallthru();
@ -341,12 +358,13 @@ TEST(FwLoop3b) {
code.Jump(1);
static int expected[] = {1, 1, 1, 1};
VerifyForwarding(&code, 4, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwLoop2_1a) {
TestCode code;
constexpr size_t kBlockCount = 5;
TestCode code(kBlockCount);
// B0
code.Fallthru();
@ -360,12 +378,13 @@ TEST(FwLoop2_1a) {
code.Jump(2);
static int expected[] = {1, 1, 1, 1, 1};
VerifyForwarding(&code, 5, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwLoop2_1b) {
TestCode code;
constexpr size_t kBlockCount = 5;
TestCode code(kBlockCount);
// B0
code.Fallthru();
@ -379,12 +398,13 @@ TEST(FwLoop2_1b) {
code.Jump(2);
static int expected[] = {2, 2, 2, 2, 2};
VerifyForwarding(&code, 5, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwLoop2_1c) {
TestCode code;
constexpr size_t kBlockCount = 5;
TestCode code(kBlockCount);
// B0
code.Fallthru();
@ -398,12 +418,13 @@ TEST(FwLoop2_1c) {
code.Jump(1);
static int expected[] = {1, 1, 1, 1, 1};
VerifyForwarding(&code, 5, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwLoop2_1d) {
TestCode code;
constexpr size_t kBlockCount = 5;
TestCode code(kBlockCount);
// B0
code.Fallthru();
@ -417,12 +438,13 @@ TEST(FwLoop2_1d) {
code.Jump(1);
static int expected[] = {1, 1, 1, 1, 1};
VerifyForwarding(&code, 5, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwLoop3_1a) {
TestCode code;
constexpr size_t kBlockCount = 6;
TestCode code(kBlockCount);
// B0
code.Fallthru();
@ -438,14 +460,16 @@ TEST(FwLoop3_1a) {
code.Jump(0);
static int expected[] = {2, 2, 2, 2, 2, 2};
VerifyForwarding(&code, 6, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
TEST(FwDiamonds) {
constexpr size_t kBlockCount = 4;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
TestCode code;
TestCode code(kBlockCount);
// B0
code.Branch(1, 2);
// B1
@ -458,17 +482,18 @@ TEST(FwDiamonds) {
code.End();
int expected[] = {0, i ? 1 : 3, j ? 2 : 3, 3};
VerifyForwarding(&code, 4, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
}
}
TEST(FwDiamonds2) {
constexpr size_t kBlockCount = 5;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
TestCode code;
TestCode code(kBlockCount);
// B0
code.Branch(1, 2);
// B1
@ -485,7 +510,7 @@ TEST(FwDiamonds2) {
int merge = k ? 3 : 4;
int expected[] = {0, i ? 1 : merge, j ? 2 : merge, merge, 4};
VerifyForwarding(&code, 5, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
}
}
@ -493,11 +518,12 @@ TEST(FwDiamonds2) {
TEST(FwDoubleDiamonds) {
constexpr size_t kBlockCount = 7;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int x = 0; x < 2; x++) {
for (int y = 0; y < 2; y++) {
TestCode code;
TestCode code(kBlockCount);
// B0
code.Branch(1, 2);
// B1
@ -519,7 +545,7 @@ TEST(FwDoubleDiamonds) {
int expected[] = {0, i ? 1 : 3, j ? 2 : 3, 3,
x ? 4 : 6, y ? 5 : 6, 6};
VerifyForwarding(&code, 7, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
}
}
@ -572,7 +598,8 @@ int find(int x, int* permutation, int size) {
void RunPermutedChain(int* permutation, int size) {
TestCode code;
const int kBlockCount = size + 2;
TestCode code(kBlockCount);
int cur = -1;
for (int i = 0; i < size; i++) {
code.Jump(find(cur + 1, permutation, size) + 1);
@ -583,7 +610,7 @@ void RunPermutedChain(int* permutation, int size) {
int expected[] = {size + 1, size + 1, size + 1, size + 1,
size + 1, size + 1, size + 1};
VerifyForwarding(&code, size + 2, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
@ -595,7 +622,8 @@ TEST(FwPermuted_chain) {
void RunPermutedDiamond(int* permutation, int size) {
TestCode code;
constexpr size_t kBlockCount = 6;
TestCode code(kBlockCount);
int br = 1 + find(0, permutation, size);
code.Jump(br);
for (int i = 0; i < size; i++) {
@ -619,7 +647,7 @@ void RunPermutedDiamond(int* permutation, int size) {
int expected[] = {br, 5, 5, 5, 5, 5};
expected[br] = br;
VerifyForwarding(&code, 6, expected);
VerifyForwarding(&code, kBlockCount, expected);
}
@ -676,7 +704,8 @@ void CheckAssemblyOrder(TestCode* code, int size, int* expected) {
}
TEST(Rewire1) {
TestCode code;
constexpr size_t kBlockCount = 3;
TestCode code(kBlockCount);
// B0
int j1 = code.Jump(1);
@ -686,17 +715,18 @@ TEST(Rewire1) {
code.End();
static int forward[] = {2, 2, 2};
ApplyForwarding(&code, 3, forward);
ApplyForwarding(&code, kBlockCount, forward);
CheckJump(&code, j1, 2);
CheckNop(&code, j2);
static int assembly[] = {0, 1, 1};
CheckAssemblyOrder(&code, 3, assembly);
CheckAssemblyOrder(&code, kBlockCount, assembly);
}
TEST(Rewire1_deferred) {
TestCode code;
constexpr size_t kBlockCount = 4;
TestCode code(kBlockCount);
// B0
int j1 = code.Jump(1);
@ -709,18 +739,19 @@ TEST(Rewire1_deferred) {
code.End();
static int forward[] = {3, 3, 3, 3};
ApplyForwarding(&code, 4, forward);
ApplyForwarding(&code, kBlockCount, forward);
CheckJump(&code, j1, 3);
CheckNop(&code, j2);
CheckNop(&code, j3);
static int assembly[] = {0, 1, 2, 1};
CheckAssemblyOrder(&code, 4, assembly);
CheckAssemblyOrder(&code, kBlockCount, assembly);
}
TEST(Rewire2_deferred) {
TestCode code;
constexpr size_t kBlockCount = 4;
TestCode code(kBlockCount);
// B0
code.Other();
@ -735,19 +766,20 @@ TEST(Rewire2_deferred) {
code.End();
static int forward[] = {0, 1, 2, 3};
ApplyForwarding(&code, 4, forward);
ApplyForwarding(&code, kBlockCount, forward);
CheckJump(&code, j1, 1);
CheckJump(&code, j2, 3);
static int assembly[] = {0, 2, 3, 1};
CheckAssemblyOrder(&code, 4, assembly);
CheckAssemblyOrder(&code, kBlockCount, assembly);
}
TEST(Rewire_diamond) {
constexpr size_t kBlockCount = 5;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
TestCode code;
TestCode code(kBlockCount);
// B0
int j1 = code.Jump(1);
// B1
@ -760,7 +792,7 @@ TEST(Rewire_diamond) {
code.End();
int forward[] = {0, 1, i ? 4 : 2, j ? 4 : 3, 4};
ApplyForwarding(&code, 5, forward);
ApplyForwarding(&code, kBlockCount, forward);
CheckJump(&code, j1, 1);
CheckBranch(&code, b1, i ? 4 : 2, j ? 4 : 3);
if (i) {
@ -781,13 +813,14 @@ TEST(Rewire_diamond) {
if (j) {
for (int k = 4; k < 5; k++) assembly[k]--;
}
CheckAssemblyOrder(&code, 5, assembly);
CheckAssemblyOrder(&code, kBlockCount, assembly);
}
}
}
TEST(RewireRet) {
TestCode code;
constexpr size_t kBlockCount = 4;
TestCode code(kBlockCount);
// B0
code.Branch(1, 2);
@ -807,7 +840,8 @@ TEST(RewireRet) {
}
TEST(RewireRet1) {
TestCode code;
constexpr size_t kBlockCount = 4;
TestCode code(kBlockCount);
// B0
code.Branch(1, 2);
@ -819,15 +853,16 @@ TEST(RewireRet1) {
code.End();
int forward[] = {0, 1, 2, 3};
VerifyForwarding(&code, 4, forward);
ApplyForwarding(&code, 4, forward);
VerifyForwarding(&code, kBlockCount, forward);
ApplyForwarding(&code, kBlockCount, forward);
CheckRet(&code, j1);
CheckRet(&code, j2);
}
TEST(RewireRet2) {
TestCode code;
constexpr size_t kBlockCount = 4;
TestCode code(kBlockCount);
// B0
code.Branch(1, 2);
@ -839,15 +874,16 @@ TEST(RewireRet2) {
code.End();
int forward[] = {0, 1, 1, 3};
VerifyForwarding(&code, 4, forward);
ApplyForwarding(&code, 4, forward);
VerifyForwarding(&code, kBlockCount, forward);
ApplyForwarding(&code, kBlockCount, forward);
CheckRet(&code, j1);
CheckNop(&code, j2);
}
TEST(DifferentSizeRet) {
TestCode code;
constexpr size_t kBlockCount = 4;
TestCode code(kBlockCount);
// B0
code.Branch(1, 2);
@ -859,8 +895,8 @@ TEST(DifferentSizeRet) {
code.End();
int forward[] = {0, 1, 2, 3};
VerifyForwarding(&code, 4, forward);
ApplyForwarding(&code, 4, forward);
VerifyForwarding(&code, kBlockCount, forward);
ApplyForwarding(&code, kBlockCount, forward);
CheckRet(&code, j1);
CheckRet(&code, j2);

View File

@ -90,7 +90,7 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build(
EXPECT_NE(InstructionOperand::CONSTANT, input->kind());
if (input->IsImmediate()) {
auto imm = ImmediateOperand::cast(input);
if (imm->type() == ImmediateOperand::INDEXED) {
if (imm->type() == ImmediateOperand::INDEXED_IMM) {
int index = imm->indexed_value();
s.immediates_.insert(
std::make_pair(index, sequence.GetImmediate(imm)));

View File

@ -267,8 +267,10 @@ class InstructionSelectorTest : public TestWithNativeContextAndZone {
} else {
EXPECT_EQ(InstructionOperand::IMMEDIATE, operand->kind());
auto imm = ImmediateOperand::cast(operand);
if (imm->type() == ImmediateOperand::INLINE) {
return Constant(imm->inline_value());
if (imm->type() == ImmediateOperand::INLINE_INT32) {
return Constant(imm->inline_int32_value());
} else if (imm->type() == ImmediateOperand::INLINE_INT64) {
return Constant(imm->inline_int64_value());
}
i = immediates_.find(imm->indexed_value());
EXPECT_EQ(imm->indexed_value(), i->first);

View File

@ -344,7 +344,7 @@ InstructionOperand* InstructionSequenceTest::ConvertInputs(
InstructionOperand InstructionSequenceTest::ConvertInputOp(TestOperand op) {
if (op.type_ == kImmediate) {
CHECK_EQ(op.vreg_.value_, kNoValue);
return ImmediateOperand(ImmediateOperand::INLINE, op.value_);
return ImmediateOperand(ImmediateOperand::INLINE_INT32, op.value_);
}
CHECK_NE(op.vreg_.value_, kNoValue);
switch (op.type_) {