Skip to content
This repository has been archived by the owner on Apr 3, 2020. It is now read-only.

Commit

Permalink
[turbofan] Add TruncationMode for TruncateFloat64ToInt32.
Browse files Browse the repository at this point in the history
We actually need round to zero truncation to implement the counterpart
of LDoubleToI in TurboFan, which tries to convert a double to an integer
as required for keyed load/store optimizations.

Drive-by-cleanup: Reduce some code duplication in the InstructionSelector
implementations.

R=jarin@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#29527}
  • Loading branch information
bmeurer authored and Commit bot committed Jul 8, 2015
1 parent 3973642 commit 4b38c15
Show file tree
Hide file tree
Showing 17 changed files with 235 additions and 159 deletions.
11 changes: 11 additions & 0 deletions src/compiler/arm/instruction-selector-arm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,17 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
}


void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
switch (TruncationModeOf(node->op())) {
case TruncationMode::kJavaScript:
return VisitRR(this, kArchTruncateDoubleToI, node);
case TruncationMode::kRoundToZero:
return VisitRR(this, kArmVcvtS32F64, node);
}
UNREACHABLE();
}


void InstructionSelector::VisitFloat32Add(Node* node) {
ArmOperandGenerator g(this);
Float32BinopMatcher m(node);
Expand Down
15 changes: 12 additions & 3 deletions src/compiler/arm64/instruction-selector-arm64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1237,9 +1237,18 @@ void InstructionSelector::VisitChangeUint32ToUint64(Node* node) {


void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
Arm64OperandGenerator g(this);
Emit(kArm64Float64ToFloat32, g.DefineAsRegister(node),
g.UseRegister(node->InputAt(0)));
VisitRR(this, kArm64Float64ToFloat32, node);
}


void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
switch (TruncationModeOf(node->op())) {
case TruncationMode::kJavaScript:
return VisitRR(this, kArchTruncateDoubleToI, node);
case TruncationMode::kRoundToZero:
return VisitRR(this, kArm64Float64ToInt32, node);
}
UNREACHABLE();
}


Expand Down
44 changes: 24 additions & 20 deletions src/compiler/ia32/instruction-selector-ia32.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,14 @@ class IA32OperandGenerator final : public OperandGenerator {

namespace {

void VisitROFloat(InstructionSelector* selector, Node* node,
ArchOpcode opcode) {
void VisitRO(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
IA32OperandGenerator g(selector);
selector->Emit(opcode, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}


void VisitRRFloat(InstructionSelector* selector, Node* node,
InstructionCode opcode) {
void VisitRR(InstructionSelector* selector, Node* node,
InstructionCode opcode) {
IA32OperandGenerator g(selector);
selector->Emit(opcode, g.DefineAsRegister(node),
g.UseRegister(node->InputAt(0)));
Expand Down Expand Up @@ -648,38 +647,43 @@ void InstructionSelector::VisitUint32Mod(Node* node) {


void InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) {
IA32OperandGenerator g(this);
Emit(kSSEFloat32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
VisitRO(this, node, kSSEFloat32ToFloat64);
}


void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
IA32OperandGenerator g(this);
Emit(kSSEInt32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
VisitRO(this, node, kSSEInt32ToFloat64);
}


void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
IA32OperandGenerator g(this);
Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
VisitRO(this, node, kSSEUint32ToFloat64);
}


void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
IA32OperandGenerator g(this);
Emit(kSSEFloat64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
VisitRO(this, node, kSSEFloat64ToInt32);
}


void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
IA32OperandGenerator g(this);
Emit(kSSEFloat64ToUint32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
VisitRO(this, node, kSSEFloat64ToUint32);
}


void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
IA32OperandGenerator g(this);
Emit(kSSEFloat64ToFloat32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
VisitRO(this, node, kSSEFloat64ToFloat32);
}


void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
switch (TruncationModeOf(node->op())) {
case TruncationMode::kJavaScript:
return VisitRR(this, node, kArchTruncateDoubleToI);
case TruncationMode::kRoundToZero:
return VisitRO(this, node, kSSEFloat64ToInt32);
}
UNREACHABLE();
}


Expand Down Expand Up @@ -791,22 +795,22 @@ void InstructionSelector::VisitFloat64Abs(Node* node) {


void InstructionSelector::VisitFloat32Sqrt(Node* node) {
VisitROFloat(this, node, kSSEFloat32Sqrt);
VisitRO(this, node, kSSEFloat32Sqrt);
}


void InstructionSelector::VisitFloat64Sqrt(Node* node) {
VisitROFloat(this, node, kSSEFloat64Sqrt);
VisitRO(this, node, kSSEFloat64Sqrt);
}


void InstructionSelector::VisitFloat64RoundDown(Node* node) {
VisitRRFloat(this, node, kSSEFloat64Round | MiscField::encode(kRoundDown));
VisitRR(this, node, kSSEFloat64Round | MiscField::encode(kRoundDown));
}


void InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
VisitRRFloat(this, node, kSSEFloat64Round | MiscField::encode(kRoundToZero));
VisitRR(this, node, kSSEFloat64Round | MiscField::encode(kRoundToZero));
}


Expand Down
7 changes: 0 additions & 7 deletions src/compiler/instruction-selector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -779,13 +779,6 @@ void InstructionSelector::VisitNode(Node* node) {

#if V8_TURBOFAN_BACKEND

void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
OperandGenerator g(this);
Emit(kArchTruncateDoubleToI, g.DefineAsRegister(node),
g.UseRegister(node->InputAt(0)));
}


void InstructionSelector::VisitLoadStackPointer(Node* node) {
OperandGenerator g(this);
Emit(kArchStackPointer, g.DefineAsRegister(node));
Expand Down
9 changes: 4 additions & 5 deletions src/compiler/machine-operator-reducer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -646,14 +646,13 @@ Reduction MachineOperatorReducer::ReduceTruncateFloat64ToInt32(Node* node) {
Node* const phi = m.node();
DCHECK_EQ(kRepFloat64, RepresentationOf(OpParameter<MachineType>(phi)));
if (phi->OwnedBy(node)) {
// TruncateFloat64ToInt32(Phi[Float64](x1,...,xn))
// => Phi[Int32](TruncateFloat64ToInt32(x1),
// TruncateFloat64ToInt32[mode](Phi[Float64](x1,...,xn))
// => Phi[Int32](TruncateFloat64ToInt32[mode](x1),
// ...,
// TruncateFloat64ToInt32(xn))
// TruncateFloat64ToInt32[mode](xn))
const int value_input_count = phi->InputCount() - 1;
for (int i = 0; i < value_input_count; ++i) {
Node* input = graph()->NewNode(machine()->TruncateFloat64ToInt32(),
phi->InputAt(i));
Node* input = graph()->NewNode(node->op(), phi->InputAt(i));
// TODO(bmeurer): Reschedule input for reduction once we have Revisit()
// instead of recursing into ReduceTruncateFloat64ToInt32() here.
Reduction reduction = ReduceTruncateFloat64ToInt32(input);
Expand Down
46 changes: 45 additions & 1 deletion src/compiler/machine-operator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,24 @@ namespace v8 {
namespace internal {
namespace compiler {

std::ostream& operator<<(std::ostream& os, TruncationMode mode) {
switch (mode) {
case TruncationMode::kJavaScript:
return os << "JavaScript";
case TruncationMode::kRoundToZero:
return os << "RoundToZero";
}
UNREACHABLE();
return os;
}


TruncationMode TruncationModeOf(Operator const* op) {
DCHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, op->opcode());
return OpParameter<TruncationMode>(op);
}


std::ostream& operator<<(std::ostream& os, WriteBarrierKind kind) {
switch (kind) {
case kNoWriteBarrier:
Expand Down Expand Up @@ -117,7 +135,6 @@ CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const* op) {
V(ChangeUint32ToFloat64, Operator::kNoProperties, 1, 0, 1) \
V(ChangeUint32ToUint64, Operator::kNoProperties, 1, 0, 1) \
V(TruncateFloat64ToFloat32, Operator::kNoProperties, 1, 0, 1) \
V(TruncateFloat64ToInt32, Operator::kNoProperties, 1, 0, 1) \
V(TruncateInt64ToInt32, Operator::kNoProperties, 1, 0, 1) \
V(Float32Abs, Operator::kNoProperties, 1, 0, 1) \
V(Float32Add, Operator::kCommutative, 2, 0, 1) \
Expand Down Expand Up @@ -191,6 +208,19 @@ struct MachineOperatorGlobalCache {
PURE_OPTIONAL_OP_LIST(PURE)
#undef PURE

template <TruncationMode kMode>
struct TruncateFloat64ToInt32Operator final
: public Operator1<TruncationMode> {
TruncateFloat64ToInt32Operator()
: Operator1<TruncationMode>(IrOpcode::kTruncateFloat64ToInt32,
Operator::kPure, "TruncateFloat64ToInt32",
1, 0, 0, 1, 0, 0, kMode) {}
};
TruncateFloat64ToInt32Operator<TruncationMode::kJavaScript>
kTruncateFloat64ToInt32JavaScript;
TruncateFloat64ToInt32Operator<TruncationMode::kRoundToZero>
kTruncateFloat64ToInt32RoundToZero;

#define LOAD(Type) \
struct Load##Type##Operator final : public Operator1<LoadRepresentation> { \
Load##Type##Operator() \
Expand Down Expand Up @@ -268,6 +298,20 @@ PURE_OP_LIST(PURE)
PURE_OPTIONAL_OP_LIST(PURE)
#undef PURE


const Operator* MachineOperatorBuilder::TruncateFloat64ToInt32(
TruncationMode mode) {
switch (mode) {
case TruncationMode::kJavaScript:
return &cache_.kTruncateFloat64ToInt32JavaScript;
case TruncationMode::kRoundToZero:
return &cache_.kTruncateFloat64ToInt32RoundToZero;
}
UNREACHABLE();
return nullptr;
}


const Operator* MachineOperatorBuilder::Load(LoadRepresentation rep) {
switch (rep) {
#define LOAD(Type) \
Expand Down
23 changes: 20 additions & 3 deletions src/compiler/machine-operator.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ namespace compiler {
struct MachineOperatorGlobalCache;
class Operator;


// For operators that are not supported on all platforms.
class OptionalOperator {
class OptionalOperator final {
public:
explicit OptionalOperator(const Operator* op) : op_(op) {}

Expand All @@ -28,9 +29,25 @@ class OptionalOperator {
}

private:
const Operator* op_;
const Operator* const op_;
};


// Supported float64 to int32 truncation modes.
enum class TruncationMode : uint8_t {
kJavaScript, // ES6 section 7.1.5
kRoundToZero // Round towards zero. Implementation defined for NaN and ovf.
};

V8_INLINE size_t hash_value(TruncationMode mode) {
return static_cast<uint8_t>(mode);
}

std::ostream& operator<<(std::ostream&, TruncationMode);

TruncationMode TruncationModeOf(Operator const*);


// Supported write barrier modes.
enum WriteBarrierKind { kNoWriteBarrier, kFullWriteBarrier };

Expand Down Expand Up @@ -175,7 +192,7 @@ class MachineOperatorBuilder final : public ZoneObject {
// These operators truncate numbers, both changing the representation of
// the number and mapping multiple input values onto the same output value.
const Operator* TruncateFloat64ToFloat32();
const Operator* TruncateFloat64ToInt32(); // JavaScript semantics.
const Operator* TruncateFloat64ToInt32(TruncationMode);
const Operator* TruncateInt64ToInt32();

// Floating point operators always operate with IEEE 754 round-to-nearest
Expand Down
11 changes: 11 additions & 0 deletions src/compiler/mips/instruction-selector-mips.cc
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,17 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
}


void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
switch (TruncationModeOf(node->op())) {
case TruncationMode::kJavaScript:
return VisitRR(this, kArchTruncateDoubleToI, node);
case TruncationMode::kRoundToZero:
return VisitRR(this, kMipsTruncWD, node);
}
UNREACHABLE();
}


void InstructionSelector::VisitFloat32Add(Node* node) {
VisitRRR(this, kMipsAddS, node);
}
Expand Down
11 changes: 11 additions & 0 deletions src/compiler/mips64/instruction-selector-mips64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,17 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
}


void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
switch (TruncationModeOf(node->op())) {
case TruncationMode::kJavaScript:
return VisitRR(this, kArchTruncateDoubleToI, node);
case TruncationMode::kRoundToZero:
return VisitRR(this, kMips64TruncWD, node);
}
UNREACHABLE();
}


void InstructionSelector::VisitFloat32Add(Node* node) {
VisitRRR(this, kMips64AddS, node);
}
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/raw-machine-assembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,8 +412,8 @@ class RawMachineAssembler : public GraphBuilder {
Node* TruncateFloat64ToFloat32(Node* a) {
return NewNode(machine()->TruncateFloat64ToFloat32(), a);
}
Node* TruncateFloat64ToInt32(Node* a) {
return NewNode(machine()->TruncateFloat64ToInt32(), a);
Node* TruncateFloat64ToInt32(TruncationMode mode, Node* a) {
return NewNode(machine()->TruncateFloat64ToInt32(mode), a);
}
Node* TruncateInt64ToInt32(Node* a) {
return NewNode(machine()->TruncateInt64ToInt32(), a);
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/representation-change.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,13 +232,13 @@ class RepresentationChanger {
// Select the correct X -> Word32 truncation operator.
const Operator* op = NULL;
if (output_type & kRepFloat64) {
op = machine()->TruncateFloat64ToInt32();
op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
} else if (output_type & kRepFloat32) {
node = InsertChangeFloat32ToFloat64(node);
op = machine()->TruncateFloat64ToInt32();
op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
} else if (output_type & kRepTagged) {
node = InsertChangeTaggedToFloat64(node);
op = machine()->TruncateFloat64ToInt32();
op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
} else {
return TypeError(node, output_type, kRepWord32);
}
Expand Down
15 changes: 11 additions & 4 deletions src/compiler/simplified-lowering.cc
Original file line number Diff line number Diff line change
Expand Up @@ -727,8 +727,10 @@ class RepresentationSelector {
// Require the input in float64 format and perform truncation.
// TODO(turbofan): avoid a truncation with a smi check.
VisitUnop(node, kTypeInt32 | kRepFloat64, kTypeInt32 | kRepWord32);
if (lower())
node->set_op(lowering->machine()->TruncateFloat64ToInt32());
if (lower()) {
node->set_op(lowering->machine()->TruncateFloat64ToInt32(
TruncationMode::kJavaScript));
}
}
break;
}
Expand All @@ -755,8 +757,10 @@ class RepresentationSelector {
// Require the input in float64 format and perform truncation.
// TODO(turbofan): avoid a truncation with a smi check.
VisitUnop(node, kTypeUint32 | kRepFloat64, kTypeUint32 | kRepWord32);
if (lower())
node->set_op(lowering->machine()->TruncateFloat64ToInt32());
if (lower()) {
node->set_op(lowering->machine()->TruncateFloat64ToInt32(
TruncationMode::kJavaScript));
}
}
break;
}
Expand Down Expand Up @@ -1008,6 +1012,9 @@ class RepresentationSelector {
case IrOpcode::kTruncateFloat64ToFloat32:
return VisitUnop(node, kTypeNumber | kRepFloat64,
kTypeNumber | kRepFloat32);
case IrOpcode::kTruncateFloat64ToInt32:
return VisitUnop(node, kTypeNumber | kRepFloat64,
kTypeInt32 | kRepWord32);
case IrOpcode::kTruncateInt64ToInt32:
// TODO(titzer): Is kTypeInt32 correct here?
return VisitUnop(node, kTypeInt32 | kRepWord64,
Expand Down
Loading

0 comments on commit 4b38c15

Please sign in to comment.