Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Unified Diff: src/compiler/x64/instruction-selector-x64.cc

Issue 605693002: [turbofan] add new x64 addressing modes (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: gcc fix Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/x64/instruction-codes-x64.h ('k') | src/compiler/x64/instruction-selector-x64-unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/x64/instruction-selector-x64.cc
diff --git a/src/compiler/x64/instruction-selector-x64.cc b/src/compiler/x64/instruction-selector-x64.cc
index 0447b794ffe6ee151d0ddfa6a4aec6525fb4fbf7..306c4f24ea22f1b235903fd1d5b1a37620f080c8 100644
--- a/src/compiler/x64/instruction-selector-x64.cc
+++ b/src/compiler/x64/instruction-selector-x64.cc
@@ -20,11 +20,6 @@ class X64OperandGenerator FINAL : public OperandGenerator {
Register::ToAllocationIndex(reg));
}
- InstructionOperand* UseByteRegister(Node* node) {
- // TODO(dcarney): relax constraint.
- return UseFixed(node, rdx);
- }
-
InstructionOperand* UseImmediate64(Node* node) { return UseImmediate(node); }
bool CanBeImmediate(Node* node) {
@@ -59,10 +54,173 @@ class X64OperandGenerator FINAL : public OperandGenerator {
};
+// Matches nodes of form [x * N] for N in {1,2,4,8}
+class ScaleFactorMatcher : public NodeMatcher {
+ public:
+ explicit ScaleFactorMatcher(Node* node)
+ : NodeMatcher(node), left_(NULL), power_(0) {
+ Match();
+ }
+
+ bool Matches() { return left_ != NULL; }
+ int Power() {
+ DCHECK(Matches());
+ return power_;
+ }
+ Node* Left() {
+ DCHECK(Matches());
+ return left_;
+ }
+
+ private:
+ void Match() {
+ if (opcode() != IrOpcode::kInt32Mul) return;
+ Int32BinopMatcher m(node());
+ if (!m.right().HasValue()) return;
+ int32_t value = m.right().Value();
+ switch (value) {
+ case 8:
+ power_++; // Fall through.
+ case 4:
+ power_++; // Fall through.
+ case 2:
+ power_++; // Fall through.
+ case 1:
+ break;
+ default:
+ return;
+ }
+ left_ = m.left().node();
+ }
+
+ Node* left_;
+ int power_;
+};
+
+
+// Matches nodes of form:
+// [x * N]
+// [x * N + K]
+// [x + K]
+// [x] -- fallback case
+// for N in {1,2,4,8} and K int32_t
+class IndexAndDisplacementMatcher : public NodeMatcher {
+ public:
+ explicit IndexAndDisplacementMatcher(Node* node)
+ : NodeMatcher(node), index_node_(node), displacement_(0), power_(0) {
+ Match();
+ }
+
+ Node* index_node() { return index_node_; }
+ int displacement() { return displacement_; }
+ int power() { return power_; }
+
+ private:
+ void Match() {
+ if (opcode() == IrOpcode::kInt32Add) {
+ // Assume reduction has put constant on the right.
+ Int32BinopMatcher m(node());
+ if (m.right().HasValue()) {
+ displacement_ = m.right().Value();
+ index_node_ = m.left().node();
+ }
+ }
+ // Test scale factor.
+ ScaleFactorMatcher scale_matcher(index_node_);
+ if (scale_matcher.Matches()) {
+ index_node_ = scale_matcher.Left();
+ power_ = scale_matcher.Power();
+ }
+ }
+
+ Node* index_node_;
+ int displacement_;
+ int power_;
+};
+
+
+class AddressingModeMatcher {
+ public:
+ AddressingModeMatcher(X64OperandGenerator* g, Node* base, Node* index)
+ : base_operand_(NULL),
+ index_operand_(NULL),
+ displacement_operand_(NULL),
+ mode_(kMode_None) {
+ Int32Matcher index_imm(index);
+ if (index_imm.HasValue()) {
+ int32_t value = index_imm.Value();
+ if (value == 0) {
+ mode_ = kMode_MR;
+ } else {
+ mode_ = kMode_MRI;
+ index_operand_ = g->UseImmediate(index);
+ }
+ base_operand_ = g->UseRegister(base);
+ } else {
+ // Compute base operand.
+ Int64Matcher base_imm(base);
+ if (!base_imm.HasValue() || base_imm.Value() != 0) {
+ base_operand_ = g->UseRegister(base);
+ }
+ // Compute index and displacement.
+ IndexAndDisplacementMatcher matcher(index);
+ index_operand_ = g->UseRegister(matcher.index_node());
+ if (matcher.displacement() != 0) {
+ displacement_operand_ = g->TempImmediate(matcher.displacement());
+ }
+ // Compute mode with scale factor one.
+ if (base_operand_ == NULL) {
+ if (displacement_operand_ == NULL) {
+ mode_ = kMode_M1;
+ } else {
+ mode_ = kMode_M1I;
+ }
+ } else {
+ if (displacement_operand_ == NULL) {
+ mode_ = kMode_MR1;
+ } else {
+ mode_ = kMode_MR1I;
+ }
+ }
+ // Adjust mode to actual scale factor.
+ mode_ = GetMode(mode_, matcher.power());
+ }
+ DCHECK_NE(kMode_None, mode_);
+ }
+
+ AddressingMode GetMode(AddressingMode one, int power) {
+ return static_cast<AddressingMode>(static_cast<int>(one) + power);
+ }
+
+ size_t SetInputs(InstructionOperand** inputs) {
+ size_t input_count = 0;
+ // Compute inputs_ and input_count.
+ if (base_operand_ != NULL) {
+ inputs[input_count++] = base_operand_;
+ }
+ if (index_operand_ != NULL) {
+ inputs[input_count++] = index_operand_;
+ }
+ if (displacement_operand_ != NULL) {
+ // Pure displacement mode not supported by x64.
+ DCHECK_NE(input_count, 0);
+ inputs[input_count++] = displacement_operand_;
+ }
+ DCHECK_NE(input_count, 0);
+ return input_count;
+ }
+
+ static const int kMaxInputCount = 3;
+ InstructionOperand* base_operand_;
+ InstructionOperand* index_operand_;
+ InstructionOperand* displacement_operand_;
+ AddressingMode mode_;
+};
+
+
void InstructionSelector::VisitLoad(Node* node) {
MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node));
MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node));
- X64OperandGenerator g(this);
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
@@ -93,18 +251,14 @@ void InstructionSelector::VisitLoad(Node* node) {
UNREACHABLE();
return;
}
- if (g.CanBeImmediate(base)) {
- // load [#base + %index]
- Emit(opcode | AddressingModeField::encode(kMode_MRI),
- g.DefineAsRegister(node), g.UseRegister(index), g.UseImmediate(base));
- } else if (g.CanBeImmediate(index)) { // load [%base + #index]
- Emit(opcode | AddressingModeField::encode(kMode_MRI),
- g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
- } else { // load [%base + %index + K]
- Emit(opcode | AddressingModeField::encode(kMode_MR1I),
- g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
- }
- // TODO(turbofan): addressing modes [r+r*{2,4,8}+K]
+
+ X64OperandGenerator g(this);
+ AddressingModeMatcher matcher(&g, base, index);
+ InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_);
+ InstructionOperand* outputs[] = {g.DefineAsRegister(node)};
+ InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount];
+ int input_count = matcher.SetInputs(inputs);
+ Emit(code, 1, outputs, input_count, inputs);
}
@@ -128,14 +282,6 @@ void InstructionSelector::VisitStore(Node* node) {
return;
}
DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind());
- InstructionOperand* val;
- if (g.CanBeImmediate(value)) {
- val = g.UseImmediate(value);
- } else if (rep == kRepWord8 || rep == kRepBit) {
- val = g.UseByteRegister(value);
- } else {
- val = g.UseRegister(value);
- }
ArchOpcode opcode;
switch (rep) {
case kRepFloat32:
@@ -162,18 +308,20 @@ void InstructionSelector::VisitStore(Node* node) {
UNREACHABLE();
return;
}
- if (g.CanBeImmediate(base)) {
- // store [#base + %index], %|#value
- Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL,
- g.UseRegister(index), g.UseImmediate(base), val);
- } else if (g.CanBeImmediate(index)) { // store [%base + #index], %|#value
- Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL,
- g.UseRegister(base), g.UseImmediate(index), val);
- } else { // store [%base + %index], %|#value
- Emit(opcode | AddressingModeField::encode(kMode_MR1I), NULL,
- g.UseRegister(base), g.UseRegister(index), val);
+
+ InstructionOperand* val;
+ if (g.CanBeImmediate(value)) {
+ val = g.UseImmediate(value);
+ } else {
+ val = g.UseRegister(value);
}
- // TODO(turbofan): addressing modes [r+r*{2,4,8}+K]
+
+ AddressingModeMatcher matcher(&g, base, index);
+ InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_);
+ InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount + 1];
+ int input_count = matcher.SetInputs(inputs);
+ inputs[input_count++] = val;
+ Emit(code, 0, static_cast<InstructionOperand**>(NULL), input_count, inputs);
}
@@ -702,8 +850,6 @@ void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation,
// Compute InstructionOperands for inputs and outputs.
InitializeCallBuffer(call, &buffer, true, true);
- // TODO(dcarney): stack alignment for c calls.
- // TODO(dcarney): shadow space on window for c calls.
// Push any stack arguments.
for (NodeVectorRIter input = buffer.pushed_nodes.rbegin();
input != buffer.pushed_nodes.rend(); input++) {
« no previous file with comments | « src/compiler/x64/instruction-codes-x64.h ('k') | src/compiler/x64/instruction-selector-x64-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698