[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:
bmeurer 2016-04-24 04:39:31 -07:00 committed by Commit bot
parent 5ae587cfb3
commit 0231a7efa2
41 changed files with 241 additions and 290 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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));

View File

@ -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);
}

View File

@ -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:

View File

@ -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();

View File

@ -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);

View File

@ -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()) { \

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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) \

View File

@ -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);

View File

@ -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);
}

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -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) \

View File

@ -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();

View File

@ -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());

View File

@ -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:

View File

@ -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

View File

@ -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);

View File

@ -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())) {

View File

@ -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);
}

View File

@ -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;

View File

@ -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(),

View File

@ -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());

View File

@ -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) {
Node* value = Parameter(0);
Reduction reduction = Reduce(graph()->NewNode(
machine()->TruncateFloat64ToInt32(mode),
graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
ASSERT_TRUE(reduction.Changed());
EXPECT_EQ(value, reduction.replacement());
}
TruncateFloat64ToWord32WithChangeInt32ToFloat64) {
Node* value = Parameter(0);
Reduction reduction = Reduce(graph()->NewNode(
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);

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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)