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

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

Issue 652363006: [turbofan] First step towards correctified 64-bit addressing. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fixes2 Created 6 years, 2 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') | test/cctest/compiler/test-simplified-lowering.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 1dc409aa4cd487cc99067c876db2ce5396279cad..17c63d2fec0aaca0ce1054b32b4e890c207683fe 100644
--- a/src/compiler/x64/instruction-selector-x64.cc
+++ b/src/compiler/x64/instruction-selector-x64.cc
@@ -25,6 +25,10 @@ class X64OperandGenerator FINAL : public OperandGenerator {
switch (node->opcode()) {
case IrOpcode::kInt32Constant:
return true;
+ case IrOpcode::kInt64Constant: {
+ const int64_t value = OpParameter<int64_t>(node);
+ return value == static_cast<int64_t>(static_cast<int32_t>(value));
+ }
default:
return false;
}
@@ -36,106 +40,14 @@ class X64OperandGenerator FINAL : public OperandGenerator {
};
-// Get the AddressingMode of scale factor N from the AddressingMode of scale
-// factor 1.
-static AddressingMode AdjustAddressingMode(AddressingMode base_mode,
- int power) {
- DCHECK(0 <= power && power < 4);
- return static_cast<AddressingMode>(static_cast<int>(base_mode) + 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_ = AdjustAddressingMode(mode_, matcher.power());
- }
- 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(static_cast<int>(input_count), 0);
- inputs[input_count++] = displacement_operand_;
- }
- DCHECK_NE(static_cast<int>(input_count), 0);
- return input_count;
- }
-
- static const int kMaxInputCount = 3;
- InstructionOperand* base_operand_;
- InstructionOperand* index_operand_;
- InstructionOperand* displacement_operand_;
- AddressingMode mode_;
-};
-
-
-static void VisitRRFloat64(InstructionSelector* selector, ArchOpcode opcode,
- Node* node) {
- X64OperandGenerator g(selector);
- selector->Emit(opcode, g.DefineAsRegister(node),
- g.UseRegister(node->InputAt(0)));
-}
-
-
void InstructionSelector::VisitLoad(Node* node) {
MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node));
MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node));
- Node* base = node->InputAt(0);
- Node* index = node->InputAt(1);
+ X64OperandGenerator g(this);
+ Node* const base = node->InputAt(0);
+ Node* const index = node->InputAt(1);
ArchOpcode opcode;
- // TODO(titzer): signed/unsigned small loads
switch (rep) {
case kRepFloat32:
opcode = kX64Movss;
@@ -161,14 +73,19 @@ void InstructionSelector::VisitLoad(Node* node) {
UNREACHABLE();
return;
}
-
- X64OperandGenerator g(this);
- AddressingModeMatcher matcher(&g, base, index);
- InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_);
- InstructionOperand* outputs[] = {g.DefineAsRegister(node)};
- InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount];
- size_t input_count = matcher.SetInputs(inputs);
- Emit(code, 1, outputs, input_count, inputs);
+ 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*1]
+ Emit(opcode | AddressingModeField::encode(kMode_MR1),
+ g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
+ }
}
@@ -218,20 +135,21 @@ void InstructionSelector::VisitStore(Node* node) {
UNREACHABLE();
return;
}
-
- InstructionOperand* val;
- if (g.CanBeImmediate(value)) {
- val = g.UseImmediate(value);
+ InstructionOperand* value_operand =
+ g.CanBeImmediate(value) ? g.UseImmediate(value) : g.UseRegister(value);
+ if (g.CanBeImmediate(base)) {
+ // store [#base + %index], %|#value
+ Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr,
+ g.UseRegister(index), g.UseImmediate(base), value_operand);
+ } else if (g.CanBeImmediate(index)) {
+ // store [%base + #index], %|#value
+ Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr,
+ g.UseRegister(base), g.UseImmediate(index), value_operand);
} else {
- val = g.UseRegister(value);
+ // store [%base + %index*1], %|#value
+ Emit(opcode | AddressingModeField::encode(kMode_MR1), nullptr,
+ g.UseRegister(base), g.UseRegister(index), value_operand);
}
-
- AddressingModeMatcher matcher(&g, base, index);
- InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_);
- InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount + 1];
- size_t input_count = matcher.SetInputs(inputs);
- inputs[input_count++] = val;
- Emit(code, 0, static_cast<InstructionOperand**>(NULL), input_count, inputs);
}
@@ -342,19 +260,21 @@ void InstructionSelector::VisitWord64Xor(Node* node) {
}
+namespace {
+
// Shared routine for multiple 32-bit shift operations.
// TODO(bmeurer): Merge this with VisitWord64Shift using template magic?
-static void VisitWord32Shift(InstructionSelector* selector, Node* node,
- ArchOpcode opcode) {
+void VisitWord32Shift(InstructionSelector* selector, Node* node,
+ ArchOpcode opcode) {
X64OperandGenerator g(selector);
- Node* left = node->InputAt(0);
- Node* right = node->InputAt(1);
+ Int32BinopMatcher m(node);
+ Node* left = m.left().node();
+ Node* right = m.right().node();
if (g.CanBeImmediate(right)) {
selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
g.UseImmediate(right));
} else {
- Int32BinopMatcher m(node);
if (m.right().IsWord32And()) {
Int32BinopMatcher mright(right);
if (mright.right().Is(0x1F)) {
@@ -369,17 +289,17 @@ static void VisitWord32Shift(InstructionSelector* selector, Node* node,
// Shared routine for multiple 64-bit shift operations.
// TODO(bmeurer): Merge this with VisitWord32Shift using template magic?
-static void VisitWord64Shift(InstructionSelector* selector, Node* node,
- ArchOpcode opcode) {
+void VisitWord64Shift(InstructionSelector* selector, Node* node,
+ ArchOpcode opcode) {
X64OperandGenerator g(selector);
- Node* left = node->InputAt(0);
- Node* right = node->InputAt(1);
+ Int64BinopMatcher m(node);
+ Node* left = m.left().node();
+ Node* right = m.right().node();
if (g.CanBeImmediate(right)) {
selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
g.UseImmediate(right));
} else {
- Int64BinopMatcher m(node);
if (m.right().IsWord64And()) {
Int64BinopMatcher mright(right);
if (mright.right().Is(0x3F)) {
@@ -391,6 +311,8 @@ static void VisitWord64Shift(InstructionSelector* selector, Node* node,
}
}
+} // namespace
+
void InstructionSelector::VisitWord32Shl(Node* node) {
VisitWord32Shift(this, node, kX64Shl32);
@@ -432,57 +354,12 @@ void InstructionSelector::VisitWord64Ror(Node* node) {
}
-static bool TryEmitLeaMultAdd(InstructionSelector* selector, Node* node,
- ArchOpcode opcode) {
- int32_t displacement_value;
- Node* left;
- {
- Int32BinopMatcher m32(node);
- left = m32.left().node();
- if (m32.right().HasValue()) {
- displacement_value = m32.right().Value();
- } else {
- Int64BinopMatcher m64(node);
- if (!m64.right().HasValue()) {
- return false;
- }
- int64_t value_64 = m64.right().Value();
- displacement_value = static_cast<int32_t>(value_64);
- if (displacement_value != value_64) return false;
- }
- }
- LeaMultiplyMatcher lmm(left);
- if (!lmm.Matches()) return false;
- AddressingMode mode;
- size_t input_count;
- X64OperandGenerator g(selector);
- InstructionOperand* index = g.UseRegister(lmm.Left());
- InstructionOperand* displacement = g.TempImmediate(displacement_value);
- InstructionOperand* inputs[] = {index, displacement, displacement};
- if (lmm.Displacement() != 0) {
- input_count = 3;
- inputs[1] = index;
- mode = kMode_MR1I;
- } else {
- input_count = 2;
- mode = kMode_M1I;
- }
- mode = AdjustAddressingMode(mode, lmm.Power());
- InstructionOperand* outputs[] = {g.DefineAsRegister(node)};
- selector->Emit(opcode | AddressingModeField::encode(mode), 1, outputs,
- input_count, inputs);
- return true;
-}
-
-
void InstructionSelector::VisitInt32Add(Node* node) {
- if (TryEmitLeaMultAdd(this, node, kX64Lea32)) return;
VisitBinop(this, node, kX64Add32);
}
void InstructionSelector::VisitInt64Add(Node* node) {
- if (TryEmitLeaMultAdd(this, node, kX64Lea)) return;
VisitBinop(this, node, kX64Add);
}
@@ -509,33 +386,9 @@ void InstructionSelector::VisitInt64Sub(Node* node) {
}
-static bool TryEmitLeaMult(InstructionSelector* selector, Node* node,
- ArchOpcode opcode) {
- LeaMultiplyMatcher lea(node);
- // Try to match lea.
- if (!lea.Matches()) return false;
- AddressingMode mode;
- size_t input_count;
- X64OperandGenerator g(selector);
- InstructionOperand* left = g.UseRegister(lea.Left());
- InstructionOperand* inputs[] = {left, left};
- if (lea.Displacement() != 0) {
- input_count = 2;
- mode = kMode_MR1;
- } else {
- input_count = 1;
- mode = kMode_M1;
- }
- mode = AdjustAddressingMode(mode, lea.Power());
- InstructionOperand* outputs[] = {g.DefineAsRegister(node)};
- selector->Emit(opcode | AddressingModeField::encode(mode), 1, outputs,
- input_count, inputs);
- return true;
-}
-
+namespace {
-static void VisitMul(InstructionSelector* selector, Node* node,
- ArchOpcode opcode) {
+void VisitMul(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
X64OperandGenerator g(selector);
Int32BinopMatcher m(node);
Node* left = m.left().node();
@@ -552,15 +405,15 @@ static void VisitMul(InstructionSelector* selector, Node* node,
}
}
+} // namespace
+
void InstructionSelector::VisitInt32Mul(Node* node) {
- if (TryEmitLeaMult(this, node, kX64Lea32)) return;
VisitMul(this, node, kX64Imul32);
}
void InstructionSelector::VisitInt64Mul(Node* node) {
- if (TryEmitLeaMult(this, node, kX64Lea)) return;
VisitMul(this, node, kX64Imul);
}
@@ -672,7 +525,37 @@ void InstructionSelector::VisitChangeInt32ToInt64(Node* node) {
void InstructionSelector::VisitChangeUint32ToUint64(Node* node) {
X64OperandGenerator g(this);
- Emit(kX64Movl, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
+ Node* value = node->InputAt(0);
+ switch (value->opcode()) {
+ case IrOpcode::kWord32And:
+ case IrOpcode::kWord32Or:
+ case IrOpcode::kWord32Xor:
+ case IrOpcode::kWord32Shl:
+ case IrOpcode::kWord32Shr:
+ case IrOpcode::kWord32Sar:
+ case IrOpcode::kWord32Ror:
+ case IrOpcode::kWord32Equal:
+ case IrOpcode::kInt32Add:
+ case IrOpcode::kInt32Sub:
+ case IrOpcode::kInt32Mul:
+ case IrOpcode::kInt32MulHigh:
+ case IrOpcode::kInt32Div:
+ case IrOpcode::kInt32LessThan:
+ case IrOpcode::kInt32LessThanOrEqual:
+ case IrOpcode::kInt32Mod:
+ case IrOpcode::kUint32Div:
+ case IrOpcode::kUint32LessThan:
+ case IrOpcode::kUint32LessThanOrEqual:
+ case IrOpcode::kUint32Mod: {
+ // These 32-bit operations implicitly zero-extend to 64-bit on x64, so the
+ // zero-extension is a no-op.
+ Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
+ return;
+ }
+ default:
+ break;
+ }
+ Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value));
}
@@ -684,7 +567,24 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
X64OperandGenerator g(this);
- Emit(kX64Movl, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
+ Node* value = node->InputAt(0);
+ if (CanCover(node, value)) {
+ switch (value->opcode()) {
+ case IrOpcode::kWord64Sar:
+ case IrOpcode::kWord64Shr: {
+ Int64BinopMatcher m(value);
+ if (m.right().Is(32)) {
+ Emit(kX64Shr, g.DefineSameAsFirst(node),
+ g.UseRegister(m.left().node()), g.TempImmediate(32));
+ return;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value));
}
@@ -731,6 +631,18 @@ void InstructionSelector::VisitFloat64Sqrt(Node* node) {
}
+namespace {
+
+void VisitRRFloat64(InstructionSelector* selector, ArchOpcode opcode,
+ Node* node) {
+ X64OperandGenerator g(selector);
+ selector->Emit(opcode, g.DefineAsRegister(node),
+ g.UseRegister(node->InputAt(0)));
+}
+
+} // namespace
+
+
void InstructionSelector::VisitFloat64Floor(Node* node) {
DCHECK(CpuFeatures::IsSupported(SSE4_1));
VisitRRFloat64(this, kSSEFloat64Floor, node);
« no previous file with comments | « src/compiler/x64/instruction-codes-x64.h ('k') | test/cctest/compiler/test-simplified-lowering.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698