[turbofan] Introduce TruncateTaggedToWord32 simplified operator.
This allows us to get rid of the "push TruncateFloat64ToInt32 into Phi" trick that was used in the MachineOperatorReducer to combine the ChangeTaggedToFloat64 and TruncateFloat64ToInt32 operations. Instead of doing that later, we can just introduce the proper operator during the representation selection directly. Also separate the TruncateFloat64ToInt32 machine operator, which had two different meanings depending on a flag (either JavaScript truncation or C++ style round to zero). Now there's a TruncateFloat64ToWord32 which represents the JavaScript truncation (implemented via TruncateDoubleToI macro + code stub) and the RoundFloat64ToInt32, which implements the C++ round towards zero operation (in the same style as the other WebAssembly driven Round* machine operators). R=jarin@chromium.org Review URL: https://codereview.chromium.org/1919513002 Cr-Commit-Position: refs/heads/master@{#35743}
This commit is contained in:
parent
5ae587cfb3
commit
0231a7efa2
@ -5221,7 +5221,7 @@ compiler::Node* ConvertTaggedAtomicIndexToWord32(CodeStubAssembler* a,
|
||||
a->Bind(&if_numberisnotsmi);
|
||||
{
|
||||
Node* number_index_value = a->LoadHeapNumberValue(number_index);
|
||||
Node* access_index = a->TruncateFloat64ToInt32(number_index_value);
|
||||
Node* access_index = a->TruncateFloat64ToWord32(number_index_value);
|
||||
Node* test_index = a->ChangeInt32ToFloat64(access_index);
|
||||
|
||||
CodeStubAssembler::Label if_indexesareequal(a), if_indexesarenotequal(a);
|
||||
|
@ -726,17 +726,13 @@ Node* CodeStubAssembler::TruncateTaggedToWord32(Node* context, Node* value) {
|
||||
return var_result.value();
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::TruncateFloat64ToInt32(Node* value) {
|
||||
return TruncateFloat64ToInt32JavaScript(value);
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::TruncateHeapNumberValueToWord32(Node* object) {
|
||||
Node* value = LoadHeapNumberValue(object);
|
||||
return TruncateFloat64ToInt32(value);
|
||||
return TruncateFloat64ToWord32(value);
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::ChangeFloat64ToTagged(Node* value) {
|
||||
Node* value32 = TruncateFloat64ToInt32RoundToZero(value);
|
||||
Node* value32 = RoundFloat64ToInt32(value);
|
||||
Node* value64 = ChangeInt32ToFloat64(value32);
|
||||
|
||||
Label if_valueisint32(this), if_valueisheapnumber(this), if_join(this);
|
||||
@ -745,16 +741,9 @@ Node* CodeStubAssembler::ChangeFloat64ToTagged(Node* value) {
|
||||
Branch(Float64Equal(value, value64), &if_valueisequal, &if_valueisnotequal);
|
||||
Bind(&if_valueisequal);
|
||||
{
|
||||
Label if_valueiszero(this), if_valueisnotzero(this);
|
||||
Branch(Float64Equal(value, Float64Constant(0.0)), &if_valueiszero,
|
||||
&if_valueisnotzero);
|
||||
|
||||
Bind(&if_valueiszero);
|
||||
GotoUnless(Word32Equal(value32, Int32Constant(0)), &if_valueisint32);
|
||||
BranchIfInt32LessThan(Float64ExtractHighWord32(value), Int32Constant(0),
|
||||
&if_valueisheapnumber, &if_valueisint32);
|
||||
|
||||
Bind(&if_valueisnotzero);
|
||||
Goto(&if_valueisint32);
|
||||
}
|
||||
Bind(&if_valueisnotequal);
|
||||
Goto(&if_valueisheapnumber);
|
||||
|
@ -169,8 +169,6 @@ class CodeStubAssembler : public compiler::CodeAssembler {
|
||||
compiler::Node* value);
|
||||
compiler::Node* TruncateTaggedToWord32(compiler::Node* context,
|
||||
compiler::Node* value);
|
||||
// Truncate to int32 using JavaScript truncation mode.
|
||||
compiler::Node* TruncateFloat64ToInt32(compiler::Node* value);
|
||||
// Truncate the floating point value of a HeapNumber to an Int32.
|
||||
compiler::Node* TruncateHeapNumberValueToWord32(compiler::Node* object);
|
||||
|
||||
|
@ -1142,15 +1142,12 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
|
||||
VisitRR(this, kArmVcvtF32F64, node);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
|
||||
VisitRR(this, kArchTruncateDoubleToI, 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::VisitRoundFloat64ToInt32(Node* node) {
|
||||
VisitRR(this, kArmVcvtS32F64, node);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1407,15 +1407,12 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
|
||||
VisitRR(this, kArm64Float64ToFloat32, node);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
|
||||
VisitRR(this, kArchTruncateDoubleToI, 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();
|
||||
void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
|
||||
VisitRR(this, kArm64Float64ToInt32, node);
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,6 +43,8 @@ Reduction ChangeLowering::Reduce(Node* node) {
|
||||
return ChangeTaggedToUI32(node->InputAt(0), control, kUnsigned);
|
||||
case IrOpcode::kChangeUint32ToTagged:
|
||||
return ChangeUint32ToTagged(node->InputAt(0), control);
|
||||
case IrOpcode::kTruncateTaggedToWord32:
|
||||
return TruncateTaggedToWord32(node->InputAt(0), control);
|
||||
case IrOpcode::kLoadField:
|
||||
return LoadField(node);
|
||||
case IrOpcode::kStoreField:
|
||||
@ -179,8 +181,7 @@ Reduction ChangeLowering::ChangeBoolToBit(Node* value) {
|
||||
|
||||
|
||||
Reduction ChangeLowering::ChangeFloat64ToTagged(Node* value, Node* control) {
|
||||
Node* value32 = graph()->NewNode(
|
||||
machine()->TruncateFloat64ToInt32(TruncationMode::kRoundToZero), value);
|
||||
Node* value32 = graph()->NewNode(machine()->RoundFloat64ToInt32(), value);
|
||||
Node* check_same = graph()->NewNode(
|
||||
machine()->Float64Equal(), value,
|
||||
graph()->NewNode(machine()->ChangeInt32ToFloat64(), value32));
|
||||
@ -391,6 +392,48 @@ Reduction ChangeLowering::ChangeUint32ToTagged(Node* value, Node* control) {
|
||||
return Replace(phi);
|
||||
}
|
||||
|
||||
Reduction ChangeLowering::TruncateTaggedToWord32(Node* value, Node* control) {
|
||||
Node* check = TestNotSmi(value);
|
||||
Node* branch =
|
||||
graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
|
||||
|
||||
Node* if_not_smi = graph()->NewNode(common()->IfTrue(), branch);
|
||||
|
||||
Node* vnot_smi;
|
||||
if (NodeProperties::GetType(value)->Maybe(Type::Undefined())) {
|
||||
Node* check_undefined = graph()->NewNode(machine()->WordEqual(), value,
|
||||
jsgraph()->UndefinedConstant());
|
||||
Node* branch_undefined = graph()->NewNode(
|
||||
common()->Branch(BranchHint::kFalse), check_undefined, if_not_smi);
|
||||
|
||||
Node* if_undefined = graph()->NewNode(common()->IfTrue(), branch_undefined);
|
||||
Node* vundefined = jsgraph()->Int32Constant(0);
|
||||
|
||||
Node* if_not_undefined =
|
||||
graph()->NewNode(common()->IfFalse(), branch_undefined);
|
||||
Node* vheap_number =
|
||||
graph()->NewNode(machine()->TruncateFloat64ToWord32(),
|
||||
LoadHeapNumberValue(value, if_not_undefined));
|
||||
|
||||
if_not_smi =
|
||||
graph()->NewNode(common()->Merge(2), if_undefined, if_not_undefined);
|
||||
vnot_smi =
|
||||
graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
|
||||
vundefined, vheap_number, if_not_smi);
|
||||
} else {
|
||||
vnot_smi = graph()->NewNode(machine()->TruncateFloat64ToWord32(),
|
||||
LoadHeapNumberValue(value, if_not_smi));
|
||||
}
|
||||
|
||||
Node* if_smi = graph()->NewNode(common()->IfFalse(), branch);
|
||||
Node* vfrom_smi = ChangeSmiToWord32(value);
|
||||
|
||||
Node* merge = graph()->NewNode(common()->Merge(2), if_not_smi, if_smi);
|
||||
Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
|
||||
vnot_smi, vfrom_smi, merge);
|
||||
|
||||
return Replace(phi);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -51,6 +51,7 @@ class ChangeLowering final : public Reducer {
|
||||
Reduction ChangeTaggedToUI32(Node* value, Node* control,
|
||||
Signedness signedness);
|
||||
Reduction ChangeUint32ToTagged(Node* value, Node* control);
|
||||
Reduction TruncateTaggedToWord32(Node* value, Node* control);
|
||||
|
||||
Reduction LoadField(Node* node);
|
||||
Reduction StoreField(Node* node);
|
||||
|
@ -160,15 +160,6 @@ Node* CodeAssembler::WordShl(Node* value, int shift) {
|
||||
return raw_assembler_->WordShl(value, IntPtrConstant(shift));
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TruncateFloat64ToInt32RoundToZero(Node* a) {
|
||||
return raw_assembler_->TruncateFloat64ToInt32(TruncationMode::kRoundToZero,
|
||||
a);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TruncateFloat64ToInt32JavaScript(Node* a) {
|
||||
return raw_assembler_->TruncateFloat64ToInt32(TruncationMode::kJavaScript, a);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::ChangeUint32ToWord(Node* value) {
|
||||
if (raw_assembler_->machine()->Is64()) {
|
||||
value = raw_assembler_->ChangeUint32ToUint64(value);
|
||||
|
@ -108,12 +108,14 @@ class Schedule;
|
||||
V(Float64ExtractLowWord32) \
|
||||
V(Float64ExtractHighWord32) \
|
||||
V(BitcastWordToTagged) \
|
||||
V(TruncateFloat64ToWord32) \
|
||||
V(TruncateInt64ToInt32) \
|
||||
V(ChangeFloat64ToUint32) \
|
||||
V(ChangeInt32ToFloat64) \
|
||||
V(ChangeInt32ToInt64) \
|
||||
V(ChangeUint32ToFloat64) \
|
||||
V(ChangeUint32ToUint64) \
|
||||
V(RoundFloat64ToInt32) \
|
||||
V(Float64RoundDown) \
|
||||
V(Float64RoundUp) \
|
||||
V(Float64RoundTruncate) \
|
||||
@ -241,8 +243,6 @@ class CodeAssembler {
|
||||
CODE_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_ASSEMBLER_UNARY_OP)
|
||||
#undef DECLARE_CODE_ASSEMBLER_UNARY_OP
|
||||
|
||||
Node* TruncateFloat64ToInt32RoundToZero(Node* a);
|
||||
Node* TruncateFloat64ToInt32JavaScript(Node* a);
|
||||
// No-op on 32-bit, otherwise zero extend.
|
||||
Node* ChangeUint32ToWord(Node* value);
|
||||
// No-op on 32-bit, otherwise sign extend.
|
||||
|
@ -293,8 +293,7 @@ EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node, Node* effect,
|
||||
Node* control) {
|
||||
Node* value = node->InputAt(0);
|
||||
|
||||
Node* value32 = graph()->NewNode(
|
||||
machine()->TruncateFloat64ToInt32(TruncationMode::kRoundToZero), value);
|
||||
Node* value32 = graph()->NewNode(machine()->RoundFloat64ToInt32(), value);
|
||||
Node* check_same = graph()->NewNode(
|
||||
machine()->Float64Equal(), value,
|
||||
graph()->NewNode(machine()->ChangeInt32ToFloat64(), value32));
|
||||
|
@ -872,15 +872,12 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
|
||||
VisitRO(this, node, kSSEFloat64ToFloat32);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
|
||||
VisitRR(this, node, kArchTruncateDoubleToI);
|
||||
}
|
||||
|
||||
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();
|
||||
void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
|
||||
VisitRO(this, node, kSSEFloat64ToInt32);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1045,10 +1045,12 @@ void InstructionSelector::VisitNode(Node* node) {
|
||||
return MarkAsWord64(node), VisitChangeUint32ToUint64(node);
|
||||
case IrOpcode::kTruncateFloat64ToFloat32:
|
||||
return MarkAsFloat32(node), VisitTruncateFloat64ToFloat32(node);
|
||||
case IrOpcode::kTruncateFloat64ToInt32:
|
||||
return MarkAsWord32(node), VisitTruncateFloat64ToInt32(node);
|
||||
case IrOpcode::kTruncateFloat64ToWord32:
|
||||
return MarkAsWord32(node), VisitTruncateFloat64ToWord32(node);
|
||||
case IrOpcode::kTruncateInt64ToInt32:
|
||||
return MarkAsWord32(node), VisitTruncateInt64ToInt32(node);
|
||||
case IrOpcode::kRoundFloat64ToInt32:
|
||||
return MarkAsWord32(node), VisitRoundFloat64ToInt32(node);
|
||||
case IrOpcode::kRoundInt64ToFloat32:
|
||||
return MarkAsFloat32(node), VisitRoundInt64ToFloat32(node);
|
||||
case IrOpcode::kRoundInt32ToFloat32:
|
||||
|
@ -419,8 +419,12 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
|
||||
if (m.HasValue()) return ReplaceInt64(static_cast<uint64_t>(m.Value()));
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kTruncateFloat64ToInt32:
|
||||
return ReduceTruncateFloat64ToInt32(node);
|
||||
case IrOpcode::kTruncateFloat64ToWord32: {
|
||||
Float64Matcher m(node->InputAt(0));
|
||||
if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
|
||||
if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
|
||||
return NoChange();
|
||||
}
|
||||
case IrOpcode::kTruncateInt64ToInt32: {
|
||||
Int64Matcher m(node->InputAt(0));
|
||||
if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
|
||||
@ -433,6 +437,12 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
|
||||
if (m.IsChangeFloat32ToFloat64()) return Replace(m.node()->InputAt(0));
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kRoundFloat64ToInt32: {
|
||||
Float64Matcher m(node->InputAt(0));
|
||||
if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
|
||||
if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kFloat64InsertLowWord32:
|
||||
return ReduceFloat64InsertLowWord32(node);
|
||||
case IrOpcode::kFloat64InsertHighWord32:
|
||||
@ -645,37 +655,6 @@ Reduction MachineOperatorReducer::ReduceUint32Mod(Node* node) {
|
||||
}
|
||||
|
||||
|
||||
Reduction MachineOperatorReducer::ReduceTruncateFloat64ToInt32(Node* node) {
|
||||
Float64Matcher m(node->InputAt(0));
|
||||
if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
|
||||
if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
|
||||
if (m.IsPhi()) {
|
||||
Node* const phi = m.node();
|
||||
DCHECK_EQ(MachineRepresentation::kFloat64, PhiRepresentationOf(phi->op()));
|
||||
if (phi->OwnedBy(node)) {
|
||||
// TruncateFloat64ToInt32[mode](Phi[Float64](x1,...,xn))
|
||||
// => Phi[Int32](TruncateFloat64ToInt32[mode](x1),
|
||||
// ...,
|
||||
// TruncateFloat64ToInt32[mode](xn))
|
||||
const int value_input_count = phi->InputCount() - 1;
|
||||
for (int i = 0; i < value_input_count; ++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);
|
||||
if (reduction.Changed()) input = reduction.replacement();
|
||||
phi->ReplaceInput(i, input);
|
||||
}
|
||||
NodeProperties::ChangeOp(
|
||||
phi,
|
||||
common()->Phi(MachineRepresentation::kWord32, value_input_count));
|
||||
return Replace(phi);
|
||||
}
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
|
||||
Reduction MachineOperatorReducer::ReduceStore(Node* node) {
|
||||
MachineRepresentation const rep =
|
||||
StoreRepresentationOf(node->op()).representation();
|
||||
|
@ -70,7 +70,6 @@ class MachineOperatorReducer final : public Reducer {
|
||||
Reduction ReduceUint32Div(Node* node);
|
||||
Reduction ReduceInt32Mod(Node* node);
|
||||
Reduction ReduceUint32Mod(Node* node);
|
||||
Reduction ReduceTruncateFloat64ToInt32(Node* node);
|
||||
Reduction ReduceStore(Node* node);
|
||||
Reduction ReduceProjection(size_t index, Node* node);
|
||||
Reduction ReduceWord32Shifts(Node* node);
|
||||
|
@ -12,24 +12,6 @@ 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:
|
||||
@ -147,6 +129,7 @@ MachineRepresentation StackSlotRepresentationOf(Operator const* op) {
|
||||
V(Uint64LessThan, Operator::kNoProperties, 2, 0, 1) \
|
||||
V(Uint64LessThanOrEqual, Operator::kNoProperties, 2, 0, 1) \
|
||||
V(BitcastWordToTagged, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(TruncateFloat64ToWord32, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(ChangeFloat32ToFloat64, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(ChangeFloat64ToInt32, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(ChangeFloat64ToUint32, Operator::kNoProperties, 1, 0, 1) \
|
||||
@ -158,6 +141,7 @@ MachineRepresentation StackSlotRepresentationOf(Operator const* op) {
|
||||
V(TryTruncateFloat32ToUint64, Operator::kNoProperties, 1, 0, 2) \
|
||||
V(TryTruncateFloat64ToUint64, Operator::kNoProperties, 1, 0, 2) \
|
||||
V(ChangeInt32ToFloat64, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(RoundFloat64ToInt32, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(RoundInt32ToFloat32, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(RoundInt64ToFloat32, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(RoundInt64ToFloat64, Operator::kNoProperties, 1, 0, 1) \
|
||||
@ -274,19 +258,6 @@ 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() \
|
||||
@ -406,19 +377,6 @@ 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) {
|
||||
#define LOAD(Type) \
|
||||
if (rep == MachineType::Type()) { \
|
||||
|
@ -32,22 +32,6 @@ class OptionalOperator final {
|
||||
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,
|
||||
@ -223,6 +207,9 @@ class MachineOperatorBuilder final : public ZoneObject {
|
||||
// This operator reinterprets the bits of a word as tagged pointer.
|
||||
const Operator* BitcastWordToTagged();
|
||||
|
||||
// JavaScript float64 to int32/uint32 truncation.
|
||||
const Operator* TruncateFloat64ToWord32();
|
||||
|
||||
// These operators change the representation of numbers while preserving the
|
||||
// value of the number. Narrowing operators assume the input is representable
|
||||
// in the target type and are *not* defined for other inputs.
|
||||
@ -246,8 +233,8 @@ class MachineOperatorBuilder final : public ZoneObject {
|
||||
// These operators truncate or round numbers, both changing the representation
|
||||
// of the number and mapping multiple input values onto the same output value.
|
||||
const Operator* TruncateFloat64ToFloat32();
|
||||
const Operator* TruncateFloat64ToInt32(TruncationMode);
|
||||
const Operator* TruncateInt64ToInt32();
|
||||
const Operator* RoundFloat64ToInt32();
|
||||
const Operator* RoundInt32ToFloat32();
|
||||
const Operator* RoundInt64ToFloat32();
|
||||
const Operator* RoundInt64ToFloat64();
|
||||
|
@ -719,17 +719,13 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
|
||||
VisitRR(this, kMipsCvtSD, 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::VisitTruncateFloat64ToWord32(Node* node) {
|
||||
VisitRR(this, kArchTruncateDoubleToI, node);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
|
||||
VisitRR(this, kMipsTruncWD, node);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
|
||||
VisitRR(this, kMipsFloat64ExtractLowWord32, node);
|
||||
|
@ -1094,17 +1094,13 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
|
||||
VisitRR(this, kMips64CvtSD, 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::VisitTruncateFloat64ToWord32(Node* node) {
|
||||
VisitRR(this, kArchTruncateDoubleToI, node);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
|
||||
VisitRR(this, kMips64TruncWD, node);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitRoundInt64ToFloat32(Node* node) {
|
||||
VisitRR(this, kMips64CvtSL, node);
|
||||
|
@ -206,6 +206,7 @@
|
||||
V(ChangeFloat64ToTagged) \
|
||||
V(ChangeBoolToBit) \
|
||||
V(ChangeBitToBool) \
|
||||
V(TruncateTaggedToWord32) \
|
||||
V(Allocate) \
|
||||
V(LoadField) \
|
||||
V(LoadBuffer) \
|
||||
@ -287,6 +288,7 @@
|
||||
V(Uint64Div) \
|
||||
V(Uint64Mod) \
|
||||
V(BitcastWordToTagged) \
|
||||
V(TruncateFloat64ToWord32) \
|
||||
V(ChangeFloat32ToFloat64) \
|
||||
V(ChangeFloat64ToInt32) \
|
||||
V(ChangeFloat64ToUint32) \
|
||||
@ -302,8 +304,8 @@
|
||||
V(ChangeUint32ToFloat64) \
|
||||
V(ChangeUint32ToUint64) \
|
||||
V(TruncateFloat64ToFloat32) \
|
||||
V(TruncateFloat64ToInt32) \
|
||||
V(TruncateInt64ToInt32) \
|
||||
V(RoundFloat64ToInt32) \
|
||||
V(RoundInt32ToFloat32) \
|
||||
V(RoundInt64ToFloat32) \
|
||||
V(RoundInt64ToFloat64) \
|
||||
|
@ -1133,8 +1133,7 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
|
||||
VisitRR(this, kPPC_DoubleToFloat32, node);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
|
||||
void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
|
||||
switch (TruncationModeOf(node->op())) {
|
||||
case TruncationMode::kJavaScript:
|
||||
return VisitRR(this, kArchTruncateDoubleToI, node);
|
||||
|
@ -472,6 +472,9 @@ class RawMachineAssembler {
|
||||
Node* BitcastWordToTagged(Node* a) {
|
||||
return AddNode(machine()->BitcastWordToTagged(), a);
|
||||
}
|
||||
Node* TruncateFloat64ToWord32(Node* a) {
|
||||
return AddNode(machine()->TruncateFloat64ToWord32(), a);
|
||||
}
|
||||
Node* ChangeFloat32ToFloat64(Node* a) {
|
||||
return AddNode(machine()->ChangeFloat32ToFloat64(), a);
|
||||
}
|
||||
@ -517,12 +520,12 @@ class RawMachineAssembler {
|
||||
Node* TruncateFloat64ToFloat32(Node* a) {
|
||||
return AddNode(machine()->TruncateFloat64ToFloat32(), a);
|
||||
}
|
||||
Node* TruncateFloat64ToInt32(TruncationMode mode, Node* a) {
|
||||
return AddNode(machine()->TruncateFloat64ToInt32(mode), a);
|
||||
}
|
||||
Node* TruncateInt64ToInt32(Node* a) {
|
||||
return AddNode(machine()->TruncateInt64ToInt32(), a);
|
||||
}
|
||||
Node* RoundFloat64ToInt32(Node* a) {
|
||||
return AddNode(machine()->RoundFloat64ToInt32(), a);
|
||||
}
|
||||
Node* RoundInt32ToFloat32(Node* a) {
|
||||
return AddNode(machine()->RoundInt32ToFloat32(), a);
|
||||
}
|
||||
|
@ -371,7 +371,7 @@ Node* RepresentationChanger::GetWord32RepresentationFor(
|
||||
} else if (output_type->Is(Type::Signed32())) {
|
||||
op = machine()->ChangeFloat64ToInt32();
|
||||
} else if (truncation.TruncatesToWord32()) {
|
||||
op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
|
||||
op = machine()->TruncateFloat64ToWord32();
|
||||
}
|
||||
} else if (output_rep == MachineRepresentation::kFloat32) {
|
||||
node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
|
||||
@ -380,7 +380,7 @@ Node* RepresentationChanger::GetWord32RepresentationFor(
|
||||
} else if (output_type->Is(Type::Signed32())) {
|
||||
op = machine()->ChangeFloat64ToInt32();
|
||||
} else if (truncation.TruncatesToWord32()) {
|
||||
op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
|
||||
op = machine()->TruncateFloat64ToWord32();
|
||||
}
|
||||
} else if (output_rep == MachineRepresentation::kTagged) {
|
||||
if (output_type->Is(Type::TaggedSigned())) {
|
||||
@ -390,8 +390,7 @@ Node* RepresentationChanger::GetWord32RepresentationFor(
|
||||
} else if (output_type->Is(Type::Signed32())) {
|
||||
op = simplified()->ChangeTaggedToInt32();
|
||||
} else if (truncation.TruncatesToWord32()) {
|
||||
node = InsertChangeTaggedToFloat64(node);
|
||||
op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
|
||||
op = simplified()->TruncateTaggedToWord32();
|
||||
}
|
||||
}
|
||||
if (op == nullptr) {
|
||||
|
@ -1042,7 +1042,7 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
|
||||
VisitRR(this, kS390_DoubleToFloat32, node);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
|
||||
void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
|
||||
switch (TruncationModeOf(node->op())) {
|
||||
case TruncationMode::kJavaScript:
|
||||
return VisitRR(this, kArchTruncateDoubleToI, node);
|
||||
|
@ -1309,7 +1309,7 @@ class RepresentationSelector {
|
||||
case IrOpcode::kTruncateFloat64ToFloat32:
|
||||
return VisitUnop(node, UseInfo::TruncatingFloat64(),
|
||||
MachineRepresentation::kFloat32);
|
||||
case IrOpcode::kTruncateFloat64ToInt32:
|
||||
case IrOpcode::kTruncateFloat64ToWord32:
|
||||
return VisitUnop(node, UseInfo::TruncatingFloat64(),
|
||||
MachineRepresentation::kWord32);
|
||||
|
||||
@ -1595,9 +1595,7 @@ void SimplifiedLowering::DoJSToNumberTruncatesToWord32(
|
||||
vfalse1 = efalse1 = graph()->NewNode(
|
||||
simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
|
||||
efalse1, if_false1);
|
||||
vfalse1 = graph()->NewNode(
|
||||
machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript),
|
||||
vfalse1);
|
||||
vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1);
|
||||
}
|
||||
|
||||
if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
|
||||
|
@ -96,6 +96,18 @@ Reduction SimplifiedOperatorReducer::Reduce(Node* node) {
|
||||
if (m.HasValue()) return ReplaceNumber(FastUI2D(m.Value()));
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kTruncateTaggedToWord32: {
|
||||
NumberMatcher m(node->InputAt(0));
|
||||
if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
|
||||
if (m.IsChangeInt31ToTagged() || m.IsChangeInt32ToTagged() ||
|
||||
m.IsChangeUint32ToTagged()) {
|
||||
return Replace(m.InputAt(0));
|
||||
}
|
||||
if (m.IsChangeFloat64ToTagged()) {
|
||||
return Change(node, machine()->TruncateFloat64ToWord32(), m.InputAt(0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kNumberCeil:
|
||||
case IrOpcode::kNumberFloor:
|
||||
case IrOpcode::kNumberRound:
|
||||
|
@ -192,6 +192,7 @@ const ElementAccess& ElementAccessOf(const Operator* op) {
|
||||
V(ChangeFloat64ToTagged, Operator::kNoProperties, 1) \
|
||||
V(ChangeBoolToBit, Operator::kNoProperties, 1) \
|
||||
V(ChangeBitToBool, Operator::kNoProperties, 1) \
|
||||
V(TruncateTaggedToWord32, Operator::kNoProperties, 1) \
|
||||
V(ObjectIsCallable, Operator::kNoProperties, 1) \
|
||||
V(ObjectIsNumber, Operator::kNoProperties, 1) \
|
||||
V(ObjectIsReceiver, Operator::kNoProperties, 1) \
|
||||
|
@ -169,6 +169,7 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
|
||||
const Operator* ChangeFloat64ToTagged();
|
||||
const Operator* ChangeBoolToBit();
|
||||
const Operator* ChangeBitToBool();
|
||||
const Operator* TruncateTaggedToWord32();
|
||||
|
||||
const Operator* ObjectIsCallable();
|
||||
const Operator* ObjectIsNumber();
|
||||
|
@ -1915,6 +1915,11 @@ Type* Typer::Visitor::TypeChangeBitToBool(Node* node) {
|
||||
return ChangeRepresentation(arg, Type::TaggedPointer(), zone());
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeTruncateTaggedToWord32(Node* node) {
|
||||
Type* arg = Operand(node, 0);
|
||||
// TODO(neis): DCHECK(arg->Is(Type::Number()));
|
||||
return ChangeRepresentation(arg, Type::UntaggedIntegral32(), zone());
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeAllocate(Node* node) { return Type::TaggedPointer(); }
|
||||
|
||||
@ -2303,9 +2308,9 @@ Type* Typer::Visitor::TypeTruncateFloat64ToFloat32(Node* node) {
|
||||
return Type::Intersect(Type::Number(), Type::UntaggedFloat32(), zone());
|
||||
}
|
||||
|
||||
|
||||
Type* Typer::Visitor::TypeTruncateFloat64ToInt32(Node* node) {
|
||||
return Type::Intersect(Type::Signed32(), Type::UntaggedIntegral32(), zone());
|
||||
Type* Typer::Visitor::TypeTruncateFloat64ToWord32(Node* node) {
|
||||
return Type::Intersect(Type::Integral32(), Type::UntaggedIntegral32(),
|
||||
zone());
|
||||
}
|
||||
|
||||
|
||||
@ -2313,6 +2318,9 @@ Type* Typer::Visitor::TypeTruncateInt64ToInt32(Node* node) {
|
||||
return Type::Intersect(Type::Signed32(), Type::UntaggedIntegral32(), zone());
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeRoundFloat64ToInt32(Node* node) {
|
||||
return Type::Intersect(Type::Signed32(), Type::UntaggedIntegral32(), zone());
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeRoundInt32ToFloat32(Node* node) {
|
||||
return Type::Intersect(Type::PlainNumber(), Type::UntaggedFloat32(), zone());
|
||||
|
@ -857,6 +857,15 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
// CheckUpperIs(node, to));
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kTruncateTaggedToWord32: {
|
||||
// Number /\ Tagged -> Signed32 /\ UntaggedInt32
|
||||
// TODO(neis): Activate once ChangeRepresentation works in typer.
|
||||
// Type* from = Type::Intersect(Type::Number(), Type::Tagged());
|
||||
// Type* to = Type::Intersect(Type::Number(), Type::UntaggedInt32());
|
||||
// CheckValueInputIs(node, 0, from));
|
||||
// CheckUpperIs(node, to));
|
||||
break;
|
||||
}
|
||||
|
||||
case IrOpcode::kLoadField:
|
||||
// Object -> fieldtype
|
||||
@ -979,6 +988,7 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
case IrOpcode::kFloat64LessThan:
|
||||
case IrOpcode::kFloat64LessThanOrEqual:
|
||||
case IrOpcode::kTruncateInt64ToInt32:
|
||||
case IrOpcode::kRoundFloat64ToInt32:
|
||||
case IrOpcode::kRoundInt32ToFloat32:
|
||||
case IrOpcode::kRoundInt64ToFloat32:
|
||||
case IrOpcode::kRoundInt64ToFloat64:
|
||||
@ -986,7 +996,7 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
case IrOpcode::kRoundUint64ToFloat64:
|
||||
case IrOpcode::kRoundUint64ToFloat32:
|
||||
case IrOpcode::kTruncateFloat64ToFloat32:
|
||||
case IrOpcode::kTruncateFloat64ToInt32:
|
||||
case IrOpcode::kTruncateFloat64ToWord32:
|
||||
case IrOpcode::kBitcastFloat32ToInt32:
|
||||
case IrOpcode::kBitcastFloat64ToInt64:
|
||||
case IrOpcode::kBitcastInt32ToFloat32:
|
||||
|
@ -1139,8 +1139,7 @@ Node* WasmGraphBuilder::BuildI32SConvertF32(Node* input) {
|
||||
if (module_ && module_->asm_js()) {
|
||||
// asm.js must use the wacky JS semantics.
|
||||
input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
|
||||
return graph()->NewNode(
|
||||
m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input);
|
||||
return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
|
||||
}
|
||||
|
||||
// Truncation of the input value is needed for the overflow check later.
|
||||
@ -1161,8 +1160,7 @@ Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input) {
|
||||
MachineOperatorBuilder* m = jsgraph()->machine();
|
||||
if (module_ && module_->asm_js()) {
|
||||
// asm.js must use the wacky JS semantics.
|
||||
return graph()->NewNode(
|
||||
m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input);
|
||||
return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
|
||||
}
|
||||
// Truncation of the input value is needed for the overflow check later.
|
||||
Node* trunc = Unop(wasm::kExprF64Trunc, input);
|
||||
@ -1183,8 +1181,7 @@ Node* WasmGraphBuilder::BuildI32UConvertF32(Node* input) {
|
||||
if (module_ && module_->asm_js()) {
|
||||
// asm.js must use the wacky JS semantics.
|
||||
input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
|
||||
return graph()->NewNode(
|
||||
m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input);
|
||||
return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
|
||||
}
|
||||
|
||||
// Truncation of the input value is needed for the overflow check later.
|
||||
@ -1205,8 +1202,7 @@ Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input) {
|
||||
MachineOperatorBuilder* m = jsgraph()->machine();
|
||||
if (module_ && module_->asm_js()) {
|
||||
// asm.js must use the wacky JS semantics.
|
||||
return graph()->NewNode(
|
||||
m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input);
|
||||
return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
|
||||
}
|
||||
// Truncation of the input value is needed for the overflow check later.
|
||||
Node* trunc = Unop(wasm::kExprF64Trunc, input);
|
||||
@ -2007,8 +2003,7 @@ Node* WasmGraphBuilder::BuildChangeFloat64ToTagged(Node* value) {
|
||||
MachineOperatorBuilder* machine = jsgraph()->machine();
|
||||
CommonOperatorBuilder* common = jsgraph()->common();
|
||||
|
||||
Node* const value32 = graph()->NewNode(
|
||||
machine->TruncateFloat64ToInt32(TruncationMode::kRoundToZero), value);
|
||||
Node* value32 = graph()->NewNode(machine->RoundFloat64ToInt32(), value);
|
||||
Node* check_same = graph()->NewNode(
|
||||
machine->Float64Equal(), value,
|
||||
graph()->NewNode(machine->ChangeInt32ToFloat64(), value32));
|
||||
@ -2239,15 +2234,13 @@ Node* WasmGraphBuilder::FromJS(Node* node, Node* context,
|
||||
|
||||
switch (type) {
|
||||
case wasm::kAstI32: {
|
||||
num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToInt32(
|
||||
TruncationMode::kJavaScript),
|
||||
num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToWord32(),
|
||||
num);
|
||||
break;
|
||||
}
|
||||
case wasm::kAstI64:
|
||||
// TODO(titzer): JS->i64 has no good solution right now. Using 32 bits.
|
||||
num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToInt32(
|
||||
TruncationMode::kJavaScript),
|
||||
num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToWord32(),
|
||||
num);
|
||||
if (jsgraph()->machine()->Is64()) {
|
||||
// We cannot change an int32 to an int64 on a 32 bit platform. Instead
|
||||
|
@ -1141,15 +1141,8 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
|
||||
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();
|
||||
void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
|
||||
VisitRR(this, node, kArchTruncateDoubleToI);
|
||||
}
|
||||
|
||||
|
||||
@ -1175,6 +1168,9 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
|
||||
Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value));
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
|
||||
VisitRO(this, node, kSSEFloat64ToInt32);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) {
|
||||
X64OperandGenerator g(this);
|
||||
|
@ -844,8 +844,7 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
|
||||
g.Use(node->InputAt(0)));
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
|
||||
void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
|
||||
X87OperandGenerator g(this);
|
||||
|
||||
switch (TruncationModeOf(node->op())) {
|
||||
|
@ -533,7 +533,7 @@ TEST(SignednessInWord32) {
|
||||
Type::None(), MachineRepresentation::kFloat64);
|
||||
CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64,
|
||||
Type::Signed32(), MachineRepresentation::kWord32);
|
||||
CheckChange(IrOpcode::kTruncateFloat64ToInt32,
|
||||
CheckChange(IrOpcode::kTruncateFloat64ToWord32,
|
||||
MachineRepresentation::kFloat64, Type::Number(),
|
||||
MachineRepresentation::kWord32);
|
||||
|
||||
@ -542,7 +542,7 @@ TEST(SignednessInWord32) {
|
||||
MachineRepresentation::kWord32, Type::None(),
|
||||
MachineRepresentation::kFloat32);
|
||||
CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
|
||||
IrOpcode::kTruncateFloat64ToInt32,
|
||||
IrOpcode::kTruncateFloat64ToWord32,
|
||||
MachineRepresentation::kFloat32, Type::Number(),
|
||||
MachineRepresentation::kWord32);
|
||||
}
|
||||
|
@ -5323,8 +5323,7 @@ TEST(RunTruncateInt64ToInt32P) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(RunTruncateFloat64ToInt32P) {
|
||||
TEST(RunTruncateFloat64ToWord32P) {
|
||||
struct {
|
||||
double from;
|
||||
double raw;
|
||||
@ -5385,8 +5384,7 @@ TEST(RunTruncateFloat64ToInt32P) {
|
||||
{-1.7976931348623157e+308, 0}};
|
||||
double input = -1.0;
|
||||
RawMachineAssemblerTester<int32_t> m;
|
||||
m.Return(m.TruncateFloat64ToInt32(
|
||||
TruncationMode::kJavaScript,
|
||||
m.Return(m.TruncateFloat64ToWord32(
|
||||
m.LoadFromPointer(&input, MachineType::Float64())));
|
||||
for (size_t i = 0; i < arraysize(kValues); ++i) {
|
||||
input = kValues[i].from;
|
||||
|
@ -1046,8 +1046,7 @@ TEST(LowerNumberToInt32_to_ChangeTaggedToInt32) {
|
||||
CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p0, use->InputAt(0));
|
||||
}
|
||||
|
||||
|
||||
TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32) {
|
||||
TEST(LowerNumberToInt32_to_TruncateFloat64ToWord32) {
|
||||
// NumberToInt32(x: kRepFloat64) used as MachineType::Int32()
|
||||
TestingGraph t(Type::Number());
|
||||
Node* p0 = t.ExampleWithOutput(MachineType::Float64());
|
||||
@ -1055,22 +1054,17 @@ TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32) {
|
||||
Node* use = t.Use(trunc, MachineType::Int32());
|
||||
t.Return(use);
|
||||
t.Lower();
|
||||
CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0));
|
||||
CheckChangeOf(IrOpcode::kTruncateFloat64ToWord32, p0, use->InputAt(0));
|
||||
}
|
||||
|
||||
|
||||
TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32_with_change) {
|
||||
TEST(LowerNumberToInt32_to_TruncateTaggedToWord32) {
|
||||
// NumberToInt32(x: kTypeNumber | kRepTagged) used as MachineType::Int32()
|
||||
TestingGraph t(Type::Number());
|
||||
Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), t.p0);
|
||||
Node* use = t.Use(trunc, MachineType::Int32());
|
||||
t.Return(use);
|
||||
t.Lower();
|
||||
Node* node = use->InputAt(0);
|
||||
CHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, node->opcode());
|
||||
Node* of = node->InputAt(0);
|
||||
CHECK_EQ(IrOpcode::kChangeTaggedToFloat64, of->opcode());
|
||||
CHECK_EQ(t.p0, of->InputAt(0));
|
||||
CheckChangeOf(IrOpcode::kTruncateTaggedToWord32, t.p0, use->InputAt(0));
|
||||
}
|
||||
|
||||
|
||||
@ -1084,8 +1078,7 @@ TEST(LowerNumberToUint32_to_ChangeTaggedToUint32) {
|
||||
CheckChangeOf(IrOpcode::kChangeTaggedToUint32, t.p0, use->InputAt(0));
|
||||
}
|
||||
|
||||
|
||||
TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32) {
|
||||
TEST(LowerNumberToUint32_to_TruncateFloat64ToWord32) {
|
||||
// NumberToUint32(x: kRepFloat64) used as MachineType::Uint32()
|
||||
TestingGraph t(Type::Number());
|
||||
Node* p0 = t.ExampleWithOutput(MachineType::Float64());
|
||||
@ -1095,26 +1088,20 @@ TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32) {
|
||||
Node* use = t.Use(trunc, MachineType::Uint32());
|
||||
t.Return(use);
|
||||
t.Lower();
|
||||
CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0));
|
||||
CheckChangeOf(IrOpcode::kTruncateFloat64ToWord32, p0, use->InputAt(0));
|
||||
}
|
||||
|
||||
|
||||
TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_with_change) {
|
||||
TEST(LowerNumberToUint32_to_TruncateTaggedToWord32) {
|
||||
// NumberToInt32(x: kTypeNumber | kRepTagged) used as MachineType::Uint32()
|
||||
TestingGraph t(Type::Number());
|
||||
Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), t.p0);
|
||||
Node* use = t.Use(trunc, MachineType::Uint32());
|
||||
t.Return(use);
|
||||
t.Lower();
|
||||
Node* node = use->InputAt(0);
|
||||
CHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, node->opcode());
|
||||
Node* of = node->InputAt(0);
|
||||
CHECK_EQ(IrOpcode::kChangeTaggedToFloat64, of->opcode());
|
||||
CHECK_EQ(t.p0, of->InputAt(0));
|
||||
CheckChangeOf(IrOpcode::kTruncateTaggedToWord32, t.p0, use->InputAt(0));
|
||||
}
|
||||
|
||||
|
||||
TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_uint32) {
|
||||
TEST(LowerNumberToUint32_to_TruncateFloat64ToWord32_uint32) {
|
||||
// NumberToUint32(x: kRepFloat64) used as kRepWord32
|
||||
TestingGraph t(Type::Unsigned32());
|
||||
Node* input = t.ExampleWithOutput(MachineType::Float64());
|
||||
@ -1122,7 +1109,7 @@ TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_uint32) {
|
||||
Node* use = t.Use(trunc, MachineType::RepWord32());
|
||||
t.Return(use);
|
||||
t.Lower();
|
||||
CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, input, use->InputAt(0));
|
||||
CheckChangeOf(IrOpcode::kTruncateFloat64ToWord32, input, use->InputAt(0));
|
||||
}
|
||||
|
||||
|
||||
@ -1150,7 +1137,7 @@ TEST(InsertBasicChanges) {
|
||||
MachineType::Int32(), Type::Signed32());
|
||||
CheckChangeInsertion(IrOpcode::kChangeFloat64ToUint32, MachineType::Float64(),
|
||||
MachineType::Uint32(), Type::Unsigned32());
|
||||
CheckChangeInsertion(IrOpcode::kTruncateFloat64ToInt32,
|
||||
CheckChangeInsertion(IrOpcode::kTruncateFloat64ToWord32,
|
||||
MachineType::Float64(), MachineType::Uint32(),
|
||||
Type::Integral32());
|
||||
CheckChangeInsertion(IrOpcode::kChangeTaggedToInt32, MachineType::AnyTagged(),
|
||||
|
@ -199,11 +199,9 @@ TARGET_TEST_F(InstructionSelectorTest, ReturnZero) {
|
||||
// -----------------------------------------------------------------------------
|
||||
// Conversions.
|
||||
|
||||
|
||||
TARGET_TEST_F(InstructionSelectorTest, TruncateFloat64ToInt32WithParameter) {
|
||||
TARGET_TEST_F(InstructionSelectorTest, TruncateFloat64ToWord32WithParameter) {
|
||||
StreamBuilder m(this, MachineType::Int32(), MachineType::Float64());
|
||||
m.Return(
|
||||
m.TruncateFloat64ToInt32(TruncationMode::kJavaScript, m.Parameter(0)));
|
||||
m.Return(m.TruncateFloat64ToWord32(m.Parameter(0)));
|
||||
Stream s = m.Build(kAllInstructions);
|
||||
ASSERT_EQ(4U, s.size());
|
||||
EXPECT_EQ(kArchNop, s[0]->arch_opcode());
|
||||
|
@ -236,10 +236,6 @@ const uint32_t kUint32Values[] = {
|
||||
0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff};
|
||||
|
||||
|
||||
const TruncationMode kTruncationModes[] = {TruncationMode::kJavaScript,
|
||||
TruncationMode::kRoundToZero};
|
||||
|
||||
|
||||
struct ComparisonBinaryOperator {
|
||||
const Operator* (MachineOperatorBuilder::*constructor)();
|
||||
const char* constructor_name;
|
||||
@ -413,51 +409,28 @@ TEST_F(MachineOperatorReducerTest, TruncateFloat64ToFloat32WithConstant) {
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// TruncateFloat64ToInt32
|
||||
|
||||
// TruncateFloat64ToWord32
|
||||
|
||||
TEST_F(MachineOperatorReducerTest,
|
||||
TruncateFloat64ToInt32WithChangeInt32ToFloat64) {
|
||||
TRACED_FOREACH(TruncationMode, mode, kTruncationModes) {
|
||||
TruncateFloat64ToWord32WithChangeInt32ToFloat64) {
|
||||
Node* value = Parameter(0);
|
||||
Reduction reduction = Reduce(graph()->NewNode(
|
||||
machine()->TruncateFloat64ToInt32(mode),
|
||||
machine()->TruncateFloat64ToWord32(),
|
||||
graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
|
||||
ASSERT_TRUE(reduction.Changed());
|
||||
EXPECT_EQ(value, reduction.replacement());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithConstant) {
|
||||
TEST_F(MachineOperatorReducerTest, TruncateFloat64ToWord32WithConstant) {
|
||||
TRACED_FOREACH(double, x, kFloat64Values) {
|
||||
Reduction reduction = Reduce(graph()->NewNode(
|
||||
machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript),
|
||||
Float64Constant(x)));
|
||||
machine()->TruncateFloat64ToWord32(), Float64Constant(x)));
|
||||
ASSERT_TRUE(reduction.Changed());
|
||||
EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithPhi) {
|
||||
Node* const p0 = Parameter(0);
|
||||
Node* const p1 = Parameter(1);
|
||||
Node* const merge = graph()->start();
|
||||
TRACED_FOREACH(TruncationMode, mode, kTruncationModes) {
|
||||
Reduction reduction = Reduce(graph()->NewNode(
|
||||
machine()->TruncateFloat64ToInt32(mode),
|
||||
graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), p0,
|
||||
p1, merge)));
|
||||
ASSERT_TRUE(reduction.Changed());
|
||||
EXPECT_THAT(
|
||||
reduction.replacement(),
|
||||
IsPhi(MachineRepresentation::kWord32, IsTruncateFloat64ToInt32(p0),
|
||||
IsTruncateFloat64ToInt32(p1), merge));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// TruncateInt64ToInt32
|
||||
|
||||
@ -485,8 +458,30 @@ TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithConstant) {
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Word32And
|
||||
// RoundFloat64ToInt32
|
||||
|
||||
TEST_F(MachineOperatorReducerTest,
|
||||
RoundFloat64ToInt32WithChangeInt32ToFloat64) {
|
||||
Node* value = Parameter(0);
|
||||
Reduction reduction = Reduce(graph()->NewNode(
|
||||
machine()->RoundFloat64ToInt32(),
|
||||
graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
|
||||
ASSERT_TRUE(reduction.Changed());
|
||||
EXPECT_EQ(value, reduction.replacement());
|
||||
}
|
||||
|
||||
TEST_F(MachineOperatorReducerTest, RoundFloat64ToInt32WithConstant) {
|
||||
TRACED_FOREACH(double, x, kFloat64Values) {
|
||||
Reduction reduction = Reduce(
|
||||
graph()->NewNode(machine()->RoundFloat64ToInt32(), Float64Constant(x)));
|
||||
ASSERT_TRUE(reduction.Changed());
|
||||
EXPECT_THAT(reduction.replacement(),
|
||||
IsInt32Constant(static_cast<int32_t>(x)));
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Word32And
|
||||
|
||||
TEST_F(MachineOperatorReducerTest, Word32AndWithWord32ShlWithConstant) {
|
||||
Node* const p0 = Parameter(0);
|
||||
|
@ -2287,6 +2287,7 @@ IS_BINOP_MATCHER(Float64InsertHighWord32)
|
||||
return MakeMatcher(new IsUnopMatcher(IrOpcode::k##Name, input_matcher)); \
|
||||
}
|
||||
IS_UNOP_MATCHER(BooleanNot)
|
||||
IS_UNOP_MATCHER(TruncateFloat64ToWord32)
|
||||
IS_UNOP_MATCHER(ChangeFloat64ToInt32)
|
||||
IS_UNOP_MATCHER(ChangeFloat64ToUint32)
|
||||
IS_UNOP_MATCHER(ChangeInt32ToFloat64)
|
||||
@ -2294,7 +2295,6 @@ IS_UNOP_MATCHER(ChangeInt32ToInt64)
|
||||
IS_UNOP_MATCHER(ChangeUint32ToFloat64)
|
||||
IS_UNOP_MATCHER(ChangeUint32ToUint64)
|
||||
IS_UNOP_MATCHER(TruncateFloat64ToFloat32)
|
||||
IS_UNOP_MATCHER(TruncateFloat64ToInt32)
|
||||
IS_UNOP_MATCHER(TruncateInt64ToInt32)
|
||||
IS_UNOP_MATCHER(Float32Abs)
|
||||
IS_UNOP_MATCHER(Float64Abs)
|
||||
|
@ -313,6 +313,7 @@ Matcher<Node*> IsInt64Sub(const Matcher<Node*>& lhs_matcher,
|
||||
const Matcher<Node*>& rhs_matcher);
|
||||
Matcher<Node*> IsJSAdd(const Matcher<Node*>& lhs_matcher,
|
||||
const Matcher<Node*>& rhs_matcher);
|
||||
Matcher<Node*> IsTruncateFloat64ToWord32(const Matcher<Node*>& input_matcher);
|
||||
Matcher<Node*> IsChangeFloat64ToInt32(const Matcher<Node*>& input_matcher);
|
||||
Matcher<Node*> IsChangeFloat64ToUint32(const Matcher<Node*>& input_matcher);
|
||||
Matcher<Node*> IsChangeInt32ToFloat64(const Matcher<Node*>& input_matcher);
|
||||
@ -320,7 +321,6 @@ Matcher<Node*> IsChangeInt32ToInt64(const Matcher<Node*>& input_matcher);
|
||||
Matcher<Node*> IsChangeUint32ToFloat64(const Matcher<Node*>& input_matcher);
|
||||
Matcher<Node*> IsChangeUint32ToUint64(const Matcher<Node*>& input_matcher);
|
||||
Matcher<Node*> IsTruncateFloat64ToFloat32(const Matcher<Node*>& input_matcher);
|
||||
Matcher<Node*> IsTruncateFloat64ToInt32(const Matcher<Node*>& input_matcher);
|
||||
Matcher<Node*> IsTruncateInt64ToInt32(const Matcher<Node*>& input_matcher);
|
||||
Matcher<Node*> IsFloat32Max(const Matcher<Node*>& lhs_matcher,
|
||||
const Matcher<Node*>& rhs_matcher);
|
||||
|
@ -401,6 +401,28 @@ TEST_F(SimplifiedOperatorReducerTest, ChangeUint32ToTagged) {
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// TruncateTaggedToWord32
|
||||
|
||||
TEST_F(SimplifiedOperatorReducerTest,
|
||||
TruncateTaggedToWord3WithChangeFloat64ToTagged) {
|
||||
Node* param0 = Parameter(0);
|
||||
Reduction reduction = Reduce(graph()->NewNode(
|
||||
simplified()->TruncateTaggedToWord32(),
|
||||
graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0)));
|
||||
ASSERT_TRUE(reduction.Changed());
|
||||
EXPECT_THAT(reduction.replacement(), IsTruncateFloat64ToWord32(param0));
|
||||
}
|
||||
|
||||
TEST_F(SimplifiedOperatorReducerTest, TruncateTaggedToWord32WithConstant) {
|
||||
TRACED_FOREACH(double, n, kFloat64Values) {
|
||||
Reduction reduction = Reduce(graph()->NewNode(
|
||||
simplified()->TruncateTaggedToWord32(), NumberConstant(n)));
|
||||
ASSERT_TRUE(reduction.Changed());
|
||||
EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(n)));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -31,7 +31,6 @@ std::ostream& operator<<(std::ostream& os, const PureOperator& pop) {
|
||||
return os << IrOpcode::Mnemonic(pop.opcode);
|
||||
}
|
||||
|
||||
|
||||
const PureOperator kPureOperators[] = {
|
||||
#define PURE(Name, properties, input_count) \
|
||||
{ \
|
||||
@ -56,6 +55,7 @@ const PureOperator kPureOperators[] = {
|
||||
PURE(NumberShiftRightLogical, Operator::kNoProperties, 2),
|
||||
PURE(NumberToInt32, Operator::kNoProperties, 1),
|
||||
PURE(NumberToUint32, Operator::kNoProperties, 1),
|
||||
PURE(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1),
|
||||
PURE(ChangeTaggedToInt32, Operator::kNoProperties, 1),
|
||||
PURE(ChangeTaggedToUint32, Operator::kNoProperties, 1),
|
||||
PURE(ChangeTaggedToFloat64, Operator::kNoProperties, 1),
|
||||
@ -64,6 +64,7 @@ const PureOperator kPureOperators[] = {
|
||||
PURE(ChangeFloat64ToTagged, Operator::kNoProperties, 1),
|
||||
PURE(ChangeBoolToBit, Operator::kNoProperties, 1),
|
||||
PURE(ChangeBitToBool, Operator::kNoProperties, 1),
|
||||
PURE(TruncateTaggedToWord32, Operator::kNoProperties, 1),
|
||||
PURE(ObjectIsNumber, Operator::kNoProperties, 1),
|
||||
PURE(ObjectIsReceiver, Operator::kNoProperties, 1),
|
||||
PURE(ObjectIsSmi, Operator::kNoProperties, 1)
|
||||
|
Loading…
Reference in New Issue
Block a user