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

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: 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') | no next file » | 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..7a797618297d2779a8ff291ea4266db1e5a4d7ac 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,172 @@ 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), matches_(false), power_(0) {
+ Match();
+ }
+
+ bool matches() { return matches_; }
+ int power() {
+ DCHECK(matches_);
+ return power_;
+ }
+ Node* left() {
+ DCHECK(matches_);
+ return InputAt(0);
+ }
+
+ private:
+ void Match() {
+ if (opcode() != IrOpcode::kInt32Mul) return;
titzer 2014/09/26 11:04:11 I think you can use an Int32BinopMatcher here. It
dcarney 2014/09/26 12:49:51 Done.
+ // Assume reduction has put constant on right.
+ Int32Matcher right_matcher(InputAt(1));
+ if (!right_matcher.HasValue()) return;
+ int32_t right_value = right_matcher.Value();
+ switch (right_value) {
+ case 8:
+ power_++; // Fall through.
+ case 4:
+ power_++; // Fall through.
+ case 2:
+ power_++; // Fall through.
+ case 1:
+ break;
+ default:
+ return;
+ }
+ matches_ = true;
+ }
+
+ bool matches_;
+ int power_;
+};
+
+
+// Matches nodes of form:
+// [x * N]
+// [x * N + K]
+// [x + K]
titzer 2014/09/26 11:04:12 This case is redundant since N can be 1.
dcarney 2014/09/26 12:49:51 yeah. but it's matched differently. so i list it
+// [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_; }
+ AddressingMode GetMode(AddressingMode one) {
+ return static_cast<AddressingMode>(static_cast<int>(one) + power_);
+ }
+
+ private:
+ void Match() {
+ if (opcode() == IrOpcode::kInt32Add) {
titzer 2014/09/26 11:04:12 Here also.
dcarney 2014/09/26 12:49:51 Done.
+ // Assume reduction has put constant on the right.
+ Int32Matcher right_matcher(InputAt(1));
+ if (right_matcher.HasValue()) {
+ displacement_ = right_matcher.Value();
+ index_node_ = InputAt(0);
+ }
+ }
+ // 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 {
titzer 2014/09/26 11:04:11 Is it possible to inline IndexAndDisplacement matc
dcarney 2014/09/26 12:49:51 yeah. but i want the 2 above matcher classes to be
+ 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.
+ Int32Matcher 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_ = matcher.GetMode(mode_);
+ }
+ DCHECK_NE(kMode_None, mode_);
+ }
+
+ 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 +250,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 +281,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 +307,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 +849,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') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698