Commit 43a86ff3 authored by epertoso's avatar epertoso Committed by Commit bot

[turbofan] Add the CheckedTruncateTaggedToWord32 opcode.

This leads to a better handling of the Smi case when we introduce a checked truncation from a number or oddbal to a 32 bit word, which we were previously doing by concatenating a Smi to float64 conversion with a float64 to word32 truncation.

BUG=

Review-Url: https://codereview.chromium.org/2191503002
Cr-Commit-Position: refs/heads/master@{#38091}
parent d30070d3
......@@ -673,6 +673,10 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kTruncateTaggedToWord32:
state = LowerTruncateTaggedToWord32(node, *effect, *control);
break;
case IrOpcode::kCheckedTruncateTaggedToWord32:
state = LowerCheckedTruncateTaggedToWord32(node, frame_state, *effect,
*control);
break;
case IrOpcode::kObjectIsCallable:
state = LowerObjectIsCallable(node, *effect, *control);
break;
......@@ -1619,6 +1623,41 @@ EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node, Node* effect,
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedTruncateTaggedToWord32(Node* node,
Node* frame_state,
Node* effect,
Node* control) {
Node* value = node->InputAt(0);
Node* check = ObjectIsSmi(value);
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
// In the Smi case, just convert to int32.
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* etrue = effect;
Node* vtrue = ChangeSmiToInt32(value);
// Otherwise, check that it's a heap number or oddball and truncate the value
// to int32.
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
ValueEffectControl false_state = BuildCheckedHeapNumberOrOddballToFloat64(
value, frame_state, effect, if_false);
false_state.value =
graph()->NewNode(machine()->TruncateFloat64ToWord32(), false_state.value);
Node* merge =
graph()->NewNode(common()->Merge(2), if_true, false_state.control);
Node* effect_phi = graph()->NewNode(common()->EffectPhi(2), etrue,
false_state.effect, merge);
Node* result =
graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), vtrue,
false_state.value, merge);
return ValueEffectControl(result, effect_phi, merge);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerObjectIsCallable(Node* node, Node* effect,
Node* control) {
......
......@@ -101,6 +101,10 @@ class EffectControlLinearizer {
Node* control);
ValueEffectControl LowerTruncateTaggedToWord32(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerCheckedTruncateTaggedToWord32(Node* node,
Node* frame_state,
Node* effect,
Node* control);
ValueEffectControl LowerObjectIsCallable(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerObjectIsNumber(Node* node, Node* effect,
......
......@@ -192,6 +192,7 @@
V(CheckedUint32ToInt32) \
V(CheckedFloat64ToInt32) \
V(CheckedTaggedToInt32) \
V(CheckedTruncateTaggedToWord32) \
V(CheckedTaggedToFloat64)
#define SIMPLIFIED_COMPARE_BINOP_LIST(V) \
......
......@@ -458,16 +458,10 @@ Node* RepresentationChanger::GetWord32RepresentationFor(
op = simplified()->ChangeTaggedToInt32();
} else if (use_info.truncation().IsUsedAsWord32()) {
if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
op = simplified()->CheckedTaggedToFloat64();
Node* effect = NodeProperties::GetEffectInput(use_node);
Node* control = NodeProperties::GetControlInput(use_node);
Node* to_float_checked =
jsgraph()->graph()->NewNode(op, node, effect, control);
NodeProperties::ReplaceEffectInput(use_node, to_float_checked);
return jsgraph()->graph()->NewNode(machine()->TruncateFloat64ToWord32(),
to_float_checked);
op = simplified()->CheckedTruncateTaggedToWord32();
} else {
op = simplified()->TruncateTaggedToWord32();
}
op = simplified()->TruncateTaggedToWord32();
} else if (use_info.type_check() == TypeCheckKind::kSigned32) {
op = simplified()->CheckedTaggedToInt32();
}
......
......@@ -364,23 +364,24 @@ CompareOperationHints::Hint CompareOperationHintOf(const Operator* op) {
V(SpeculativeNumberModulus) \
V(SpeculativeNumberShiftLeft)
#define CHECKED_OP_LIST(V) \
V(CheckBounds, 2, 1) \
V(CheckIf, 1, 0) \
V(CheckNumber, 1, 1) \
V(CheckString, 1, 1) \
V(CheckTaggedPointer, 1, 1) \
V(CheckTaggedSigned, 1, 1) \
V(CheckedInt32Add, 2, 1) \
V(CheckedInt32Sub, 2, 1) \
V(CheckedInt32Div, 2, 1) \
V(CheckedInt32Mod, 2, 1) \
V(CheckedUint32Div, 2, 1) \
V(CheckedUint32Mod, 2, 1) \
V(CheckedUint32ToInt32, 1, 1) \
V(CheckedFloat64ToInt32, 1, 1) \
V(CheckedTaggedToInt32, 1, 1) \
V(CheckedTaggedToFloat64, 1, 1)
#define CHECKED_OP_LIST(V) \
V(CheckBounds, 2, 1) \
V(CheckIf, 1, 0) \
V(CheckNumber, 1, 1) \
V(CheckString, 1, 1) \
V(CheckTaggedPointer, 1, 1) \
V(CheckTaggedSigned, 1, 1) \
V(CheckedInt32Add, 2, 1) \
V(CheckedInt32Sub, 2, 1) \
V(CheckedInt32Div, 2, 1) \
V(CheckedInt32Mod, 2, 1) \
V(CheckedUint32Div, 2, 1) \
V(CheckedUint32Mod, 2, 1) \
V(CheckedUint32ToInt32, 1, 1) \
V(CheckedFloat64ToInt32, 1, 1) \
V(CheckedTaggedToInt32, 1, 1) \
V(CheckedTaggedToFloat64, 1, 1) \
V(CheckedTruncateTaggedToWord32, 1, 1)
struct SimplifiedOperatorGlobalCache final {
#define PURE(Name, properties, input_count) \
......
......@@ -288,6 +288,7 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* CheckedFloat64ToInt32();
const Operator* CheckedTaggedToInt32();
const Operator* CheckedTaggedToFloat64();
const Operator* CheckedTruncateTaggedToWord32();
const Operator* CheckFloat64Hole(CheckFloat64HoleMode);
const Operator* CheckTaggedHole(CheckTaggedHoleMode);
......
......@@ -998,6 +998,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kCheckedFloat64ToInt32:
case IrOpcode::kCheckedTaggedToInt32:
case IrOpcode::kCheckedTaggedToFloat64:
case IrOpcode::kCheckedTruncateTaggedToWord32:
break;
case IrOpcode::kCheckFloat64Hole:
......
......@@ -442,7 +442,6 @@ TEST(ToUint32_constant) {
}
}
static void CheckChange(IrOpcode::Value expected, MachineRepresentation from,
Type* from_type, MachineRepresentation to) {
RepresentationChangerTester r;
......@@ -477,6 +476,20 @@ static void CheckTwoChanges(IrOpcode::Value expected2,
CHECK_EQ(n, c2->InputAt(0));
}
static void CheckChange(IrOpcode::Value expected, MachineRepresentation from,
Type* from_type, MachineRepresentation to,
UseInfo use_info) {
RepresentationChangerTester r;
Node* n = r.Parameter();
Node* use = r.Return(n);
Node* c =
r.changer()->GetRepresentationFor(n, from, from_type, use, use_info);
CHECK_NE(c, n);
CHECK_EQ(expected, c->opcode());
CHECK_EQ(n, c->InputAt(0));
}
TEST(SingleChanges) {
CheckChange(IrOpcode::kChangeTaggedToBit, MachineRepresentation::kTagged,
......@@ -580,6 +593,10 @@ TEST(SignednessInWord32) {
CheckChange(IrOpcode::kTruncateFloat64ToWord32,
MachineRepresentation::kFloat64, Type::Number(),
MachineRepresentation::kWord32);
CheckChange(IrOpcode::kCheckedTruncateTaggedToWord32,
MachineRepresentation::kTagged, Type::NumberOrOddball(),
MachineRepresentation::kWord32,
UseInfo::CheckedNumberOrOddballAsWord32());
CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64,
IrOpcode::kTruncateFloat64ToFloat32,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment