Commit d08f9045 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Introduce simplified NumberBitwise{Or,Xor,And} operators.

Currently we still (mis)used some machine operators in typed lowering
(namely Word32Or, Word32Xor and Word32And). But these operators are
"polymorphic" in the signedness of their inputs and output, hence the
representation selection (and thereby simplified lowering) was unable to
figure out whether a bitwise operation that was seen would produce an
unsigned or a signed result. If such nodes also have frame state uses,
the only safe choice was float64, which was not only a lot less ideal,
but also the main cause of the for-in related deoptimizer loops.

Adding dedicated NumberBitwiseOr, NumberBitwiseAnd and NumberBitwiseXor
simplified operators not only gives us precise (and correct) typing for
the bitwise operations, but also allows us to actually verify the graph
properly after typed lowering.

Drive-by-fix: Remove the double-to-smi magic from the Deoptimizer, which
is responsible for various deopt-loops in TurboFan, and is no longer
needed with the addition of the NumberBitwise operators.

R=jarin@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#31594}
parent 85e085b7
......@@ -68,7 +68,6 @@ FieldAccess AccessBuilder::ForJSDateField(JSDate::FieldIndex index) {
// static
FieldAccess AccessBuilder::ForFixedArrayLength(Zone* zone) {
STATIC_ASSERT(FixedArray::kMaxLength <= 1 << 30);
FieldAccess access = {
kTaggedBase, FixedArray::kLengthOffset, MaybeHandle<Name>(),
Type::Intersect(Type::Range(0, FixedArray::kMaxLength, zone),
......@@ -96,9 +95,11 @@ FieldAccess AccessBuilder::ForDescriptorArrayEnumCacheBridgeCache() {
// static
FieldAccess AccessBuilder::ForMapBitField3() {
FieldAccess access = {kTaggedBase, Map::kBitField3Offset, Handle<Name>(),
Type::UntaggedUnsigned32(), kMachUint32};
FieldAccess AccessBuilder::ForMapBitField3(Zone* zone) {
FieldAccess access = {
kTaggedBase, Map::kBitField3Offset, Handle<Name>(),
Type::Intersect(Type::Signed32(), Type::UntaggedSigned32(), zone),
kMachInt32};
return access;
}
......
......@@ -50,7 +50,7 @@ class AccessBuilder final : public AllStatic {
static FieldAccess ForDescriptorArrayEnumCacheBridgeCache();
// Provides access to Map::bit_field3() field.
static FieldAccess ForMapBitField3();
static FieldAccess ForMapBitField3(Zone* zone);
// Provides access to Map::descriptors() field.
static FieldAccess ForMapDescriptors();
......
......@@ -1525,12 +1525,13 @@ Reduction JSTypedLowering::ReduceJSForInPrepare(Node* node) {
Node* etrue0;
{
// Enum cache case.
Node* cache_type_enum_length = etrue0 = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForMapBitField3()), cache_type,
effect, if_true0);
cache_length_true0 =
graph()->NewNode(machine()->Word32And(), cache_type_enum_length,
jsgraph()->Uint32Constant(Map::EnumLengthBits::kMask));
Node* cache_type_enum_length = etrue0 =
graph()->NewNode(simplified()->LoadField(
AccessBuilder::ForMapBitField3(graph()->zone())),
cache_type, effect, if_true0);
cache_length_true0 = graph()->NewNode(
simplified()->NumberBitwiseAnd(), cache_type_enum_length,
jsgraph()->Int32Constant(Map::EnumLengthBits::kMask));
Node* check1 =
graph()->NewNode(machine()->Word32Equal(), cache_length_true0,
......@@ -1795,11 +1796,11 @@ Reduction JSTypedLowering::Reduce(Node* node) {
case IrOpcode::kJSGreaterThanOrEqual:
return ReduceJSComparison(node);
case IrOpcode::kJSBitwiseOr:
return ReduceInt32Binop(node, machine()->Word32Or());
return ReduceInt32Binop(node, simplified()->NumberBitwiseOr());
case IrOpcode::kJSBitwiseXor:
return ReduceInt32Binop(node, machine()->Word32Xor());
return ReduceInt32Binop(node, simplified()->NumberBitwiseXor());
case IrOpcode::kJSBitwiseAnd:
return ReduceInt32Binop(node, machine()->Word32And());
return ReduceInt32Binop(node, simplified()->NumberBitwiseAnd());
case IrOpcode::kJSShiftLeft:
return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftLeft());
case IrOpcode::kJSShiftRight:
......
......@@ -172,6 +172,9 @@
V(NumberMultiply) \
V(NumberDivide) \
V(NumberModulus) \
V(NumberBitwiseOr) \
V(NumberBitwiseXor) \
V(NumberBitwiseAnd) \
V(NumberShiftLeft) \
V(NumberShiftRight) \
V(NumberShiftRightLogical) \
......
......@@ -331,6 +331,12 @@ class RepresentationChanger {
return machine()->Int32Div();
case IrOpcode::kNumberModulus:
return machine()->Int32Mod();
case IrOpcode::kNumberBitwiseOr:
return machine()->Word32Or();
case IrOpcode::kNumberBitwiseXor:
return machine()->Word32Xor();
case IrOpcode::kNumberBitwiseAnd:
return machine()->Word32And();
case IrOpcode::kNumberEqual:
return machine()->Word32Equal();
case IrOpcode::kNumberLessThan:
......
......@@ -718,6 +718,13 @@ class RepresentationSelector {
if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
break;
}
case IrOpcode::kNumberBitwiseOr:
case IrOpcode::kNumberBitwiseXor:
case IrOpcode::kNumberBitwiseAnd: {
VisitInt32Binop(node);
if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
break;
}
case IrOpcode::kNumberShiftLeft: {
VisitBinop(node, kMachInt32, kMachUint32, kMachInt32);
if (lower()) lowering->DoShift(node, lowering->machine()->Word32Shl());
......
......@@ -168,6 +168,9 @@ const ElementAccess& ElementAccessOf(const Operator* op) {
V(NumberMultiply, Operator::kCommutative, 2) \
V(NumberDivide, Operator::kNoProperties, 2) \
V(NumberModulus, Operator::kNoProperties, 2) \
V(NumberBitwiseOr, Operator::kCommutative, 2) \
V(NumberBitwiseXor, Operator::kCommutative, 2) \
V(NumberBitwiseAnd, Operator::kCommutative, 2) \
V(NumberShiftLeft, Operator::kNoProperties, 2) \
V(NumberShiftRight, Operator::kNoProperties, 2) \
V(NumberShiftRightLogical, Operator::kNoProperties, 2) \
......
......@@ -140,6 +140,9 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* NumberMultiply();
const Operator* NumberDivide();
const Operator* NumberModulus();
const Operator* NumberBitwiseOr();
const Operator* NumberBitwiseXor();
const Operator* NumberBitwiseAnd();
const Operator* NumberShiftLeft();
const Operator* NumberShiftRight();
const Operator* NumberShiftRightLogical();
......
......@@ -1556,6 +1556,21 @@ Type* Typer::Visitor::TypeNumberModulus(Node* node) {
}
Type* Typer::Visitor::TypeNumberBitwiseOr(Node* node) {
return Type::Signed32(zone());
}
Type* Typer::Visitor::TypeNumberBitwiseXor(Node* node) {
return Type::Signed32(zone());
}
Type* Typer::Visitor::TypeNumberBitwiseAnd(Node* node) {
return Type::Signed32(zone());
}
Type* Typer::Visitor::TypeNumberShiftLeft(Node* node) {
return Type::Signed32(zone());
}
......
......@@ -635,6 +635,14 @@ void Verifier::Visitor::Check(Node* node) {
// TODO(rossberg): activate once we retype after opcode changes.
// CheckUpperIs(node, Type::Number());
break;
case IrOpcode::kNumberBitwiseOr:
case IrOpcode::kNumberBitwiseXor:
case IrOpcode::kNumberBitwiseAnd:
// (Signed32, Signed32) -> Signed32
CheckValueInputIs(node, 0, Type::Signed32());
CheckValueInputIs(node, 1, Type::Signed32());
CheckUpperIs(node, Type::Signed32());
break;
case IrOpcode::kNumberShiftLeft:
case IrOpcode::kNumberShiftRight:
// (Signed32, Unsigned32) -> Signed32
......
......@@ -2491,16 +2491,6 @@ Object* TranslatedValue::GetRawValue() const {
break;
}
case kDouble: {
int int_value = FastD2IChecked(double_value());
bool is_smi = !IsMinusZero(double_value()) &&
double_value() == int_value && Smi::IsValid(int_value);
if (is_smi) {
return Smi::FromInt(static_cast<int32_t>(int_value));
}
break;
}
case kBoolBit: {
if (uint32_value() == 0) {
return isolate()->heap()->false_value();
......
......@@ -378,11 +378,11 @@ class JSBitwiseTypedLoweringTester : public JSTypedLoweringTester {
: JSTypedLoweringTester(), language_mode_(language_mode) {
int i = 0;
set(i++, javascript.BitwiseOr(language_mode_), true);
set(i++, machine.Word32Or(), true);
set(i++, simplified.NumberBitwiseOr(), true);
set(i++, javascript.BitwiseXor(language_mode_), true);
set(i++, machine.Word32Xor(), true);
set(i++, simplified.NumberBitwiseXor(), true);
set(i++, javascript.BitwiseAnd(language_mode_), true);
set(i++, machine.Word32And(), true);
set(i++, simplified.NumberBitwiseAnd(), true);
}
static const int kNumberOps = 6;
const Operator* ops[kNumberOps];
......
......@@ -48,6 +48,12 @@ const PureOperator kPureOperators[] = {
PURE(NumberMultiply, Operator::kCommutative, 2),
PURE(NumberDivide, Operator::kNoProperties, 2),
PURE(NumberModulus, Operator::kNoProperties, 2),
PURE(NumberBitwiseOr, Operator::kCommutative, 2),
PURE(NumberBitwiseXor, Operator::kCommutative, 2),
PURE(NumberBitwiseAnd, Operator::kCommutative, 2),
PURE(NumberShiftLeft, Operator::kNoProperties, 2),
PURE(NumberShiftRight, Operator::kNoProperties, 2),
PURE(NumberShiftRightLogical, Operator::kNoProperties, 2),
PURE(NumberToInt32, Operator::kNoProperties, 1),
PURE(NumberToUint32, Operator::kNoProperties, 1),
PURE(PlainPrimitiveToNumber, Operator::kNoProperties, 1),
......
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