Commit 572196f6 authored by dcarney's avatar dcarney Committed by Commit bot

[turbofan] support small immediates

R=titzer@chromium.org

BUG=

Review URL: https://codereview.chromium.org/1075903002

Cr-Commit-Position: refs/heads/master@{#27709}
parent 5d56277e
...@@ -100,7 +100,7 @@ class InstructionOperandConverter { ...@@ -100,7 +100,7 @@ class InstructionOperandConverter {
Constant ToConstant(InstructionOperand* op) { Constant ToConstant(InstructionOperand* op) {
if (op->IsImmediate()) { if (op->IsImmediate()) {
return gen_->code()->GetImmediate(ImmediateOperand::cast(op)->index()); return gen_->code()->GetImmediate(ImmediateOperand::cast(op));
} }
return gen_->code()->GetConstant( return gen_->code()->GetConstant(
ConstantOperand::cast(op)->virtual_register()); ConstantOperand::cast(op)->virtual_register());
......
...@@ -119,8 +119,7 @@ class OperandGenerator { ...@@ -119,8 +119,7 @@ class OperandGenerator {
} }
InstructionOperand UseImmediate(Node* node) { InstructionOperand UseImmediate(Node* node) {
int index = sequence()->AddImmediate(ToConstant(node)); return sequence()->AddImmediate(ToConstant(node));
return ImmediateOperand(index);
} }
InstructionOperand UseLocation(Node* node, LinkageLocation location, InstructionOperand UseLocation(Node* node, LinkageLocation location,
...@@ -149,8 +148,7 @@ class OperandGenerator { ...@@ -149,8 +148,7 @@ class OperandGenerator {
} }
InstructionOperand TempImmediate(int32_t imm) { InstructionOperand TempImmediate(int32_t imm) {
int index = sequence()->AddImmediate(Constant(imm)); return sequence()->AddImmediate(Constant(imm));
return ImmediateOperand(index);
} }
InstructionOperand TempLocation(LinkageLocation location, MachineType type) { InstructionOperand TempLocation(LinkageLocation location, MachineType type) {
...@@ -159,9 +157,8 @@ class OperandGenerator { ...@@ -159,9 +157,8 @@ class OperandGenerator {
} }
InstructionOperand Label(BasicBlock* block) { InstructionOperand Label(BasicBlock* block) {
int index = sequence()->AddImmediate( return sequence()->AddImmediate(
Constant(RpoNumber::FromInt(block->rpo_number()))); Constant(RpoNumber::FromInt(block->rpo_number())));
return ImmediateOperand(index);
} }
protected: protected:
......
...@@ -44,8 +44,15 @@ std::ostream& operator<<(std::ostream& os, ...@@ -44,8 +44,15 @@ std::ostream& operator<<(std::ostream& os,
case InstructionOperand::CONSTANT: case InstructionOperand::CONSTANT:
return os << "[constant:" << ConstantOperand::cast(op).virtual_register() return os << "[constant:" << ConstantOperand::cast(op).virtual_register()
<< "]"; << "]";
case InstructionOperand::IMMEDIATE: case InstructionOperand::IMMEDIATE: {
return os << "[immediate:" << ImmediateOperand::cast(op).index() << "]"; auto imm = ImmediateOperand::cast(op);
switch (imm.type()) {
case ImmediateOperand::INLINE:
return os << "#" << imm.inline_value();
case ImmediateOperand::INDEXED:
return os << "[immediate:" << imm.indexed_value() << "]";
}
}
case InstructionOperand::ALLOCATED: case InstructionOperand::ALLOCATED:
switch (AllocatedOperand::cast(op).allocated_kind()) { switch (AllocatedOperand::cast(op).allocated_kind()) {
case AllocatedOperand::STACK_SLOT: case AllocatedOperand::STACK_SLOT:
...@@ -606,7 +613,7 @@ RpoNumber InstructionSequence::InputRpo(Instruction* instr, size_t index) { ...@@ -606,7 +613,7 @@ RpoNumber InstructionSequence::InputRpo(Instruction* instr, size_t index) {
InstructionOperand* operand = instr->InputAt(index); InstructionOperand* operand = instr->InputAt(index);
Constant constant = Constant constant =
operand->IsImmediate() operand->IsImmediate()
? GetImmediate(ImmediateOperand::cast(operand)->index()) ? GetImmediate(ImmediateOperand::cast(operand))
: GetConstant(ConstantOperand::cast(operand)->virtual_register()); : GetConstant(ConstantOperand::cast(operand)->virtual_register());
return constant.ToRpoNumber(); return constant.ToRpoNumber();
} }
......
...@@ -317,22 +317,35 @@ class ConstantOperand : public InstructionOperand { ...@@ -317,22 +317,35 @@ class ConstantOperand : public InstructionOperand {
class ImmediateOperand : public InstructionOperand { class ImmediateOperand : public InstructionOperand {
public: public:
explicit ImmediateOperand(int index) : InstructionOperand(IMMEDIATE) { enum ImmediateType { INLINE, INDEXED };
value_ |= static_cast<int64_t>(index) << IndexField::kShift;
explicit ImmediateOperand(ImmediateType type, int32_t value)
: InstructionOperand(IMMEDIATE) {
value_ |= TypeField::encode(type);
value_ |= static_cast<int64_t>(value) << ValueField::kShift;
} }
int index() const { ImmediateType type() const { return TypeField::decode(value_); }
return static_cast<int64_t>(value_) >> IndexField::kShift;
int32_t inline_value() const {
DCHECK_EQ(INLINE, type());
return static_cast<int64_t>(value_) >> ValueField::kShift;
}
int32_t indexed_value() const {
DCHECK_EQ(INDEXED, type());
return static_cast<int64_t>(value_) >> ValueField::kShift;
} }
static ImmediateOperand* New(Zone* zone, int index) { static ImmediateOperand* New(Zone* zone, ImmediateType type, int32_t value) {
return InstructionOperand::New(zone, ImmediateOperand(index)); return InstructionOperand::New(zone, ImmediateOperand(type, value));
} }
INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE); INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE);
STATIC_ASSERT(KindField::kSize == 3); STATIC_ASSERT(KindField::kSize == 3);
class IndexField : public BitField64<int32_t, 35, 29> {}; class TypeField : public BitField64<ImmediateType, 3, 1> {};
class ValueField : public BitField64<int32_t, 32, 32> {};
}; };
...@@ -1066,15 +1079,28 @@ class InstructionSequence FINAL : public ZoneObject { ...@@ -1066,15 +1079,28 @@ class InstructionSequence FINAL : public ZoneObject {
typedef ZoneVector<Constant> Immediates; typedef ZoneVector<Constant> Immediates;
Immediates& immediates() { return immediates_; } Immediates& immediates() { return immediates_; }
int AddImmediate(Constant constant) { ImmediateOperand AddImmediate(const Constant& constant) {
if (constant.type() == Constant::kInt32) {
return ImmediateOperand(ImmediateOperand::INLINE, constant.ToInt32());
}
int index = static_cast<int>(immediates_.size()); int index = static_cast<int>(immediates_.size());
immediates_.push_back(constant); immediates_.push_back(constant);
return index; return ImmediateOperand(ImmediateOperand::INDEXED, index);
} }
Constant GetImmediate(int index) const {
DCHECK(index >= 0); Constant GetImmediate(const ImmediateOperand* op) const {
DCHECK(index < static_cast<int>(immediates_.size())); switch (op->type()) {
return immediates_[index]; case ImmediateOperand::INLINE:
return Constant(op->inline_value());
case ImmediateOperand::INDEXED: {
int index = op->indexed_value();
DCHECK(index >= 0);
DCHECK(index < static_cast<int>(immediates_.size()));
return immediates_[index];
}
}
UNREACHABLE();
return Constant(static_cast<int32_t>(0));
} }
class StateId { class StateId {
......
...@@ -122,8 +122,11 @@ void RegisterAllocatorVerifier::BuildConstraint(const InstructionOperand* op, ...@@ -122,8 +122,11 @@ void RegisterAllocatorVerifier::BuildConstraint(const InstructionOperand* op,
constraint->value_ = ConstantOperand::cast(op)->virtual_register(); constraint->value_ = ConstantOperand::cast(op)->virtual_register();
constraint->virtual_register_ = constraint->value_; constraint->virtual_register_ = constraint->value_;
} else if (op->IsImmediate()) { } else if (op->IsImmediate()) {
auto imm = ImmediateOperand::cast(op);
int value = imm->type() == ImmediateOperand::INLINE ? imm->inline_value()
: imm->indexed_value();
constraint->type_ = kImmediate; constraint->type_ = kImmediate;
constraint->value_ = ImmediateOperand::cast(op)->index(); constraint->value_ = value;
} else { } else {
CHECK(op->IsUnallocated()); CHECK(op->IsUnallocated());
const auto* unallocated = UnallocatedOperand::cast(op); const auto* unallocated = UnallocatedOperand::cast(op);
...@@ -183,10 +186,15 @@ void RegisterAllocatorVerifier::CheckConstraint( ...@@ -183,10 +186,15 @@ void RegisterAllocatorVerifier::CheckConstraint(
CHECK_EQ(ConstantOperand::cast(op)->virtual_register(), CHECK_EQ(ConstantOperand::cast(op)->virtual_register(),
constraint->value_); constraint->value_);
return; return;
case kImmediate: case kImmediate: {
CHECK(op->IsImmediate()); CHECK(op->IsImmediate());
CHECK_EQ(ImmediateOperand::cast(op)->index(), constraint->value_); auto imm = ImmediateOperand::cast(op);
int value = imm->type() == ImmediateOperand::INLINE
? imm->inline_value()
: imm->indexed_value();
CHECK_EQ(value, constraint->value_);
return; return;
}
case kRegister: case kRegister:
CHECK(op->IsRegister()); CHECK(op->IsRegister());
return; return;
......
...@@ -66,7 +66,7 @@ class TestCode : public HandleAndZoneScope { ...@@ -66,7 +66,7 @@ class TestCode : public HandleAndZoneScope {
Start(); Start();
sequence_.AddInstruction(Instruction::New(main_zone(), kArchNop)); sequence_.AddInstruction(Instruction::New(main_zone(), kArchNop));
int index = static_cast<int>(sequence_.instructions().size()) - 1; int index = static_cast<int>(sequence_.instructions().size()) - 1;
AddGapMove(index, ImmediateOperand::New(main_zone(), 11), AddGapMove(index, ConstantOperand::New(main_zone(), 11),
RegisterOperand::New(main_zone(), 11)); RegisterOperand::New(main_zone(), 11));
} }
void Other() { void Other() {
...@@ -80,8 +80,7 @@ class TestCode : public HandleAndZoneScope { ...@@ -80,8 +80,7 @@ class TestCode : public HandleAndZoneScope {
rpo_number_ = RpoNumber::FromInt(rpo_number_.ToInt() + 1); rpo_number_ = RpoNumber::FromInt(rpo_number_.ToInt() + 1);
} }
InstructionOperand UseRpo(int num) { InstructionOperand UseRpo(int num) {
int index = sequence_.AddImmediate(Constant(RpoNumber::FromInt(num))); return sequence_.AddImmediate(Constant(RpoNumber::FromInt(num)));
return ImmediateOperand(index);
} }
void Start(bool deferred = false) { void Start(bool deferred = false) {
if (current_ == NULL) { if (current_ == NULL) {
......
...@@ -84,9 +84,12 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build( ...@@ -84,9 +84,12 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build(
InstructionOperand* input = instr->InputAt(i); InstructionOperand* input = instr->InputAt(i);
EXPECT_NE(InstructionOperand::CONSTANT, input->kind()); EXPECT_NE(InstructionOperand::CONSTANT, input->kind());
if (input->IsImmediate()) { if (input->IsImmediate()) {
int index = ImmediateOperand::cast(input)->index(); auto imm = ImmediateOperand::cast(input);
s.immediates_.insert( if (imm->type() == ImmediateOperand::INDEXED) {
std::make_pair(index, sequence.GetImmediate(index))); int index = imm->indexed_value();
s.immediates_.insert(
std::make_pair(index, sequence.GetImmediate(imm)));
}
} }
} }
s.instructions_.push_back(instr); s.instructions_.push_back(instr);
......
...@@ -209,8 +209,12 @@ class InstructionSelectorTest : public TestWithContext, ...@@ -209,8 +209,12 @@ class InstructionSelectorTest : public TestWithContext,
EXPECT_FALSE(constants_.end() == i); EXPECT_FALSE(constants_.end() == i);
} else { } else {
EXPECT_EQ(InstructionOperand::IMMEDIATE, operand->kind()); EXPECT_EQ(InstructionOperand::IMMEDIATE, operand->kind());
i = immediates_.find(ImmediateOperand::cast(operand)->index()); auto imm = ImmediateOperand::cast(operand);
EXPECT_EQ(ImmediateOperand::cast(operand)->index(), i->first); if (imm->type() == ImmediateOperand::INLINE) {
return Constant(imm->inline_value());
}
i = immediates_.find(imm->indexed_value());
EXPECT_EQ(imm->indexed_value(), i->first);
EXPECT_FALSE(immediates_.end() == i); EXPECT_FALSE(immediates_.end() == i);
} }
return i->second; return i->second;
......
...@@ -129,8 +129,7 @@ Instruction* InstructionSequenceTest::EndBlock(BlockCompletion completion) { ...@@ -129,8 +129,7 @@ Instruction* InstructionSequenceTest::EndBlock(BlockCompletion completion) {
InstructionSequenceTest::TestOperand InstructionSequenceTest::Imm(int32_t imm) { InstructionSequenceTest::TestOperand InstructionSequenceTest::Imm(int32_t imm) {
int index = sequence()->AddImmediate(Constant(imm)); return TestOperand(kImmediate, imm);
return TestOperand(kImmediate, index);
} }
...@@ -357,7 +356,7 @@ InstructionOperand* InstructionSequenceTest::ConvertInputs( ...@@ -357,7 +356,7 @@ InstructionOperand* InstructionSequenceTest::ConvertInputs(
InstructionOperand InstructionSequenceTest::ConvertInputOp(TestOperand op) { InstructionOperand InstructionSequenceTest::ConvertInputOp(TestOperand op) {
if (op.type_ == kImmediate) { if (op.type_ == kImmediate) {
CHECK_EQ(op.vreg_.value_, kNoValue); CHECK_EQ(op.vreg_.value_, kNoValue);
return ImmediateOperand(op.value_); return ImmediateOperand(ImmediateOperand::INLINE, op.value_);
} }
CHECK_NE(op.vreg_.value_, kNoValue); CHECK_NE(op.vreg_.value_, kNoValue);
switch (op.type_) { switch (op.type_) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment