Commit 066d0233 authored by Nico Hartmann's avatar Nico Hartmann Committed by V8 LUCI CQ

Reland "[turbofan] Support additional operators in SLVerifier"

This is a reland of commit dec4bb06

Original change's description:
> [turbofan] Support additional operators in SLVerifier
>
> This CL extends SimplifiedLoweringVerifier by a few additional operators.
>
> It fixes the missing type on a LoadElement node generated during
> js-typed-lowering, that was detected by the verifier.
>
> Bug: v8:12619
> Change-Id: I14e3ece15f6a90e6906c140696dcd2e6b74a2527
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3557510
> Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
> Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80014}

Bug: v8:12619
Change-Id: If3cb6efe2005c41118f37b39b0209195b3e63a38
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3702330Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Auto-Submit: Nico Hartmann <nicohartmann@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81125}
parent 323d3bff
......@@ -1092,6 +1092,16 @@ ElementAccess AccessBuilder::ForTypedArrayElement(ExternalArrayType type,
UNREACHABLE();
}
// static
ElementAccess AccessBuilder::ForJSForInCacheArrayElement(ForInMode mode) {
ElementAccess access = {
kTaggedBase, FixedArray::kHeaderSize,
(mode == ForInMode::kGeneric ? Type::String()
: Type::InternalizedString()),
MachineType::AnyTagged(), kFullWriteBarrier};
return access;
}
// static
FieldAccess AccessBuilder::ForHashTableBaseNumberOfElements() {
FieldAccess access = {
......
......@@ -6,6 +6,7 @@
#define V8_COMPILER_ACCESS_BUILDER_H_
#include "src/base/compiler-specific.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/simplified-operator.h"
#include "src/compiler/write-barrier-kind.h"
#include "src/objects/elements-kind.h"
......@@ -320,6 +321,9 @@ class V8_EXPORT_PRIVATE AccessBuilder final
static ElementAccess ForTypedArrayElement(ExternalArrayType type,
bool is_external);
// Provides access to the for-in cache array.
static ElementAccess ForJSForInCacheArrayElement(ForInMode mode);
// Provides access to HashTable fields.
static FieldAccess ForHashTableBaseNumberOfElements();
static FieldAccess ForHashTableBaseNumberOfDeletedElement();
......
......@@ -1873,16 +1873,17 @@ Reduction JSTypedLowering::ReduceJSForInNext(Node* node) {
node->ReplaceInput(2, effect);
node->ReplaceInput(3, control);
node->TrimInputCount(4);
NodeProperties::ChangeOp(
node,
simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()));
NodeProperties::SetType(node, Type::InternalizedString());
ElementAccess access =
AccessBuilder::ForJSForInCacheArrayElement(n.Parameters().mode());
NodeProperties::ChangeOp(node, simplified()->LoadElement(access));
NodeProperties::SetType(node, access.type);
break;
}
case ForInMode::kGeneric: {
// Load the next {key} from the {cache_array}.
Node* key = effect = graph()->NewNode(
simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
simplified()->LoadElement(AccessBuilder::ForJSForInCacheArrayElement(
n.Parameters().mode())),
cache_array, index, effect, control);
// Check if the expected map still matches that of the {receiver}.
......
......@@ -22,6 +22,23 @@ Truncation LeastGeneralTruncation(const Truncation& t1, const Truncation& t2,
return LeastGeneralTruncation(LeastGeneralTruncation(t1, t2), t3);
}
bool IsNonTruncatingMachineTypeFor(const MachineType& mt, const Type& type) {
if (type.IsNone()) return true;
// TODO(nicohartmann@): Add more cases here.
if (type.Is(Type::BigInt())) {
return mt.representation() == MachineRepresentation::kTaggedPointer ||
mt.representation() == MachineRepresentation::kTagged;
}
switch (mt.representation()) {
case MachineRepresentation::kBit:
CHECK(mt.semantic() == MachineSemantic::kBool ||
mt.semantic() == MachineSemantic::kAny);
return type.Is(Type::Boolean());
default:
return true;
}
}
void SimplifiedLoweringVerifier::CheckType(Node* node, const Type& type) {
CHECK(NodeProperties::IsTyped(node));
Type node_type = NodeProperties::GetType(node);
......@@ -70,6 +87,10 @@ Truncation SimplifiedLoweringVerifier::GeneralizeTruncation(
case Truncation::TruncationKind::kAny: {
return Truncation::Any(identify_zeros);
}
case Truncation::TruncationKind::kBool: {
if (type.Is(Type::Boolean())) return Truncation::Any();
return Truncation(Truncation::TruncationKind::kBool, identify_zeros);
}
case Truncation::TruncationKind::kWord32: {
if (type.Is(Type::Signed32OrMinusZero()) ||
type.Is(Type::Unsigned32OrMinusZero())) {
......@@ -99,12 +120,26 @@ Truncation SimplifiedLoweringVerifier::GeneralizeTruncation(
void SimplifiedLoweringVerifier::VisitNode(Node* node,
OperationTyper& op_typer) {
switch (node->opcode()) {
case IrOpcode::kInt64Constant: {
case IrOpcode::kStart:
case IrOpcode::kIfTrue:
case IrOpcode::kIfFalse:
case IrOpcode::kMerge:
case IrOpcode::kEnd:
case IrOpcode::kEffectPhi:
case IrOpcode::kCheckpoint:
case IrOpcode::kFrameState:
case IrOpcode::kJSStackCheck:
break;
case IrOpcode::kInt32Constant:
case IrOpcode::kInt64Constant:
case IrOpcode::kFloat64Constant: {
// Constants might be untyped, because they are cached in the graph and
// used in different contexts such that no single type can be assigned.
// Their type is provided by an introduced TypeGuard where necessary.
break;
}
case IrOpcode::kHeapConstant:
break;
case IrOpcode::kCheckedFloat64ToInt32: {
Type input_type = InputType(node, 0);
DCHECK(input_type.Is(Type::Number()));
......@@ -121,6 +156,28 @@ void SimplifiedLoweringVerifier::VisitNode(Node* node,
CheckAndSet(node, input_type, Truncation::Word32());
break;
}
case IrOpcode::kCheckedTaggedToTaggedSigned: {
Type input_type = InputType(node, 0);
Type output_type =
Type::Intersect(input_type, Type::SignedSmall(), graph_zone());
Truncation output_trunc = InputTruncation(node, 0);
CheckAndSet(node, output_type, output_trunc);
break;
}
case IrOpcode::kCheckedTaggedToTaggedPointer:
CheckAndSet(node, InputType(node, 0), InputTruncation(node, 0));
break;
case IrOpcode::kTruncateTaggedToBit: {
Type input_type = InputType(node, 0);
Truncation input_trunc = InputTruncation(node, 0);
// Cannot have other truncation here, because identified values lead to
// different results when converted to bit.
CHECK(input_trunc == Truncation::Bool() ||
input_trunc == Truncation::Any());
Type output_type = op_typer.ToBoolean(input_type);
CheckAndSet(node, output_type, Truncation::Bool());
break;
}
case IrOpcode::kInt32Add: {
Type output_type =
op_typer.NumberAdd(InputType(node, 0), InputType(node, 1));
......@@ -141,16 +198,21 @@ void SimplifiedLoweringVerifier::VisitNode(Node* node,
CheckAndSet(node, output_type, output_trunc);
break;
}
case IrOpcode::kChangeInt31ToTaggedSigned: {
// ChangeInt31ToTaggedSigned is not truncating any values, so we can
// simply forward input.
case IrOpcode::kChangeInt31ToTaggedSigned:
case IrOpcode::kChangeInt32ToTagged:
case IrOpcode::kChangeFloat32ToFloat64:
case IrOpcode::kChangeInt32ToInt64:
case IrOpcode::kChangeUint32ToUint64:
case IrOpcode::kChangeUint64ToTagged: {
// These change operators do not truncate any values and can simply
// forward input type and truncation.
CheckAndSet(node, InputType(node, 0), InputTruncation(node, 0));
break;
}
case IrOpcode::kChangeInt32ToTagged: {
// ChangeInt32ToTagged is not truncating any values, so we can simply
// forward input.
CheckAndSet(node, InputType(node, 0), InputTruncation(node, 0));
case IrOpcode::kChangeFloat64ToInt64: {
Type input_type = InputType(node, 0);
CHECK(input_type.Is(TypeCache::Get()->kSafeInteger));
CheckAndSet(node, input_type, InputTruncation(node, 0));
break;
}
case IrOpcode::kInt64Add: {
......@@ -185,12 +247,6 @@ void SimplifiedLoweringVerifier::VisitNode(Node* node,
CheckAndSet(node, output_type, output_trunc);
break;
}
case IrOpcode::kChangeInt32ToInt64: {
// ChangeInt32ToInt64 is not truncating any values, so we can simply
// forward input.
CheckAndSet(node, InputType(node, 0), InputTruncation(node, 0));
break;
}
case IrOpcode::kDeadValue: {
CheckAndSet(node, Type::None(), Truncation::Any());
break;
......@@ -258,10 +314,295 @@ void SimplifiedLoweringVerifier::VisitNode(Node* node,
SetTruncation(node, GeneralizeTruncation(output_trunc, output_type));
break;
}
default:
// TODO(nicohartmann): Support remaining operators.
case IrOpcode::kBranch: {
CHECK(InputType(node, 0).Is(Type::Boolean()));
CHECK_EQ(InputTruncation(node, 0), Truncation::Any());
break;
}
case IrOpcode::kTypedStateValues: {
const ZoneVector<MachineType>* machine_types = MachineTypesOf(node->op());
for (int i = 0; i < static_cast<int>(machine_types->size()); ++i) {
// Inputs must not be truncated.
CHECK_EQ(InputTruncation(node, i), Truncation::Any());
CHECK(IsNonTruncatingMachineTypeFor(machine_types->at(i),
InputType(node, i)));
}
break;
}
case IrOpcode::kParameter: {
CHECK(NodeProperties::IsTyped(node));
SetTruncation(node, Truncation::Any());
break;
}
#define CASE(code, ...) case IrOpcode::k##code:
// Control operators
CASE(Loop)
CASE(Switch)
CASE(IfSuccess)
CASE(IfException)
CASE(IfValue)
CASE(IfDefault)
CASE(Deoptimize)
CASE(DeoptimizeIf)
CASE(DeoptimizeUnless)
CASE(TrapIf)
CASE(TrapUnless)
CASE(TailCall)
CASE(Terminate)
CASE(Throw)
// Constant operators
CASE(TaggedIndexConstant)
CASE(Float32Constant)
CASE(ExternalConstant)
CASE(NumberConstant)
CASE(PointerConstant)
CASE(CompressedHeapConstant)
CASE(RelocatableInt32Constant)
CASE(RelocatableInt64Constant)
// Inner operators
CASE(Select)
CASE(Phi)
CASE(InductionVariablePhi)
CASE(BeginRegion)
CASE(FinishRegion)
CASE(StateValues)
CASE(ArgumentsElementsState)
CASE(ArgumentsLengthState)
CASE(ObjectState)
CASE(ObjectId)
CASE(TypedObjectState)
CASE(Call)
CASE(OsrValue)
CASE(LoopExit)
CASE(LoopExitValue)
CASE(LoopExitEffect)
CASE(Projection)
CASE(Retain)
CASE(MapGuard)
CASE(FoldConstant)
CASE(Unreachable)
CASE(Dead)
CASE(Plug)
CASE(StaticAssert)
// Simplified change operators
CASE(ChangeTaggedSignedToInt32)
CASE(ChangeTaggedToInt32)
CASE(ChangeTaggedToInt64)
CASE(ChangeTaggedToUint32)
CASE(ChangeTaggedToFloat64)
CASE(ChangeTaggedToTaggedSigned)
CASE(ChangeInt64ToTagged)
CASE(ChangeUint32ToTagged)
CASE(ChangeFloat64ToTagged)
CASE(ChangeFloat64ToTaggedPointer)
CASE(ChangeTaggedToBit)
CASE(ChangeBitToTagged)
CASE(ChangeInt64ToBigInt)
CASE(ChangeUint64ToBigInt)
CASE(TruncateTaggedToWord32)
CASE(TruncateTaggedToFloat64)
CASE(TruncateTaggedPointerToBit)
// Simplified checked operators
CASE(CheckedInt32Add)
CASE(CheckedInt32Sub)
CASE(CheckedInt32Div)
CASE(CheckedInt32Mod)
CASE(CheckedUint32Div)
CASE(CheckedUint32Mod)
CASE(CheckedInt32Mul)
CASE(CheckedInt32ToTaggedSigned)
CASE(CheckedInt64ToInt32)
CASE(CheckedInt64ToTaggedSigned)
CASE(CheckedUint32Bounds)
CASE(CheckedUint32ToInt32)
CASE(CheckedUint32ToTaggedSigned)
CASE(CheckedUint64Bounds)
CASE(CheckedUint64ToInt32)
CASE(CheckedUint64ToTaggedSigned)
CASE(CheckedFloat64ToInt64)
CASE(CheckedTaggedSignedToInt32)
CASE(CheckedTaggedToInt32)
CASE(CheckedTaggedToArrayIndex)
CASE(CheckedTruncateTaggedToWord32)
CASE(CheckedTaggedToFloat64)
CASE(CheckedTaggedToInt64)
SIMPLIFIED_COMPARE_BINOP_LIST(CASE)
SIMPLIFIED_NUMBER_BINOP_LIST(CASE)
SIMPLIFIED_BIGINT_BINOP_LIST(CASE)
SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(CASE)
SIMPLIFIED_NUMBER_UNOP_LIST(CASE)
// Simplified unary bigint operators
CASE(BigIntNegate)
SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(CASE)
SIMPLIFIED_SPECULATIVE_BIGINT_UNOP_LIST(CASE)
SIMPLIFIED_SPECULATIVE_BIGINT_BINOP_LIST(CASE)
SIMPLIFIED_OTHER_OP_LIST(CASE)
MACHINE_COMPARE_BINOP_LIST(CASE)
MACHINE_UNOP_32_LIST(CASE)
// Binary 32bit machine operators
CASE(Word32And)
CASE(Word32Or)
CASE(Word32Xor)
CASE(Word32Shl)
CASE(Word32Shr)
CASE(Word32Sar)
CASE(Word32Rol)
CASE(Word32Ror)
CASE(Int32AddWithOverflow)
CASE(Int32SubWithOverflow)
CASE(Int32Mul)
CASE(Int32MulWithOverflow)
CASE(Int32MulHigh)
CASE(Int32Div)
CASE(Int32Mod)
CASE(Uint32Div)
CASE(Uint32Mod)
CASE(Uint32MulHigh)
// Binary 64bit machine operators
CASE(Word64And)
CASE(Word64Or)
CASE(Word64Xor)
CASE(Word64Shl)
CASE(Word64Shr)
CASE(Word64Sar)
CASE(Word64Rol)
CASE(Word64Ror)
CASE(Word64RolLowerable)
CASE(Word64RorLowerable)
CASE(Int64AddWithOverflow)
CASE(Int64Sub)
CASE(Int64SubWithOverflow)
CASE(Int64Mul)
CASE(Int64Div)
CASE(Int64Mod)
CASE(Uint64Div)
CASE(Uint64Mod)
MACHINE_FLOAT32_UNOP_LIST(CASE)
MACHINE_FLOAT32_BINOP_LIST(CASE)
MACHINE_FLOAT64_UNOP_LIST(CASE)
MACHINE_FLOAT64_BINOP_LIST(CASE)
MACHINE_ATOMIC_OP_LIST(CASE)
CASE(AbortCSADcheck)
CASE(DebugBreak)
CASE(Comment)
CASE(Load)
CASE(LoadImmutable)
CASE(Store)
CASE(StackSlot)
CASE(Word32Popcnt)
CASE(Word64Popcnt)
CASE(Word64Clz)
CASE(Word64Ctz)
CASE(Word64ClzLowerable)
CASE(Word64CtzLowerable)
CASE(Word64ReverseBits)
CASE(Word64ReverseBytes)
CASE(Simd128ReverseBytes)
CASE(Int64AbsWithOverflow)
CASE(BitcastTaggedToWord)
CASE(BitcastTaggedToWordForTagAndSmiBits)
CASE(BitcastWordToTagged)
CASE(BitcastWordToTaggedSigned)
CASE(TruncateFloat64ToWord32)
CASE(ChangeFloat64ToInt32)
CASE(ChangeFloat64ToUint32)
CASE(ChangeFloat64ToUint64)
CASE(Float64SilenceNaN)
CASE(TruncateFloat64ToInt64)
CASE(TruncateFloat64ToUint32)
CASE(TruncateFloat32ToInt32)
CASE(TruncateFloat32ToUint32)
CASE(TryTruncateFloat32ToInt64)
CASE(TryTruncateFloat64ToInt64)
CASE(TryTruncateFloat32ToUint64)
CASE(TryTruncateFloat64ToUint64)
CASE(ChangeInt32ToFloat64)
CASE(BitcastWord32ToWord64)
CASE(ChangeInt64ToFloat64)
CASE(ChangeUint32ToFloat64)
CASE(TruncateFloat64ToFloat32)
CASE(TruncateInt64ToInt32)
CASE(RoundFloat64ToInt32)
CASE(RoundInt32ToFloat32)
CASE(RoundInt64ToFloat32)
CASE(RoundInt64ToFloat64)
CASE(RoundUint32ToFloat32)
CASE(RoundUint64ToFloat32)
CASE(RoundUint64ToFloat64)
CASE(BitcastFloat32ToInt32)
CASE(BitcastFloat64ToInt64)
CASE(BitcastInt32ToFloat32)
CASE(BitcastInt64ToFloat64)
CASE(Float64ExtractLowWord32)
CASE(Float64ExtractHighWord32)
CASE(Float64InsertLowWord32)
CASE(Float64InsertHighWord32)
CASE(Word32Select)
CASE(Word64Select)
CASE(Float32Select)
CASE(Float64Select)
CASE(LoadStackCheckOffset)
CASE(LoadFramePointer)
CASE(LoadParentFramePointer)
CASE(UnalignedLoad)
CASE(UnalignedStore)
CASE(Int32PairAdd)
CASE(Int32PairSub)
CASE(Int32PairMul)
CASE(Word32PairShl)
CASE(Word32PairShr)
CASE(Word32PairSar)
CASE(ProtectedLoad)
CASE(ProtectedStore)
CASE(MemoryBarrier)
CASE(SignExtendWord8ToInt32)
CASE(SignExtendWord16ToInt32)
CASE(SignExtendWord8ToInt64)
CASE(SignExtendWord16ToInt64)
CASE(SignExtendWord32ToInt64)
CASE(StackPointerGreaterThan)
JS_SIMPLE_BINOP_LIST(CASE)
JS_SIMPLE_UNOP_LIST(CASE)
JS_OBJECT_OP_LIST(CASE)
JS_CONTEXT_OP_LIST(CASE)
JS_CALL_OP_LIST(CASE)
JS_CONSTRUCT_OP_LIST(CASE)
CASE(JSAsyncFunctionEnter)
CASE(JSAsyncFunctionReject)
CASE(JSAsyncFunctionResolve)
CASE(JSCallRuntime)
CASE(JSForInEnumerate)
CASE(JSForInNext)
CASE(JSForInPrepare)
CASE(JSGetIterator)
CASE(JSLoadMessage)
CASE(JSStoreMessage)
CASE(JSLoadModule)
CASE(JSStoreModule)
CASE(JSGetImportMeta)
CASE(JSGeneratorStore)
CASE(JSGeneratorRestoreContinuation)
CASE(JSGeneratorRestoreContext)
CASE(JSGeneratorRestoreRegister)
CASE(JSGeneratorRestoreInputOrDebugPos)
CASE(JSFulfillPromise)
CASE(JSPerformPromiseThen)
CASE(JSPromiseResolve)
CASE(JSRejectPromise)
CASE(JSResolvePromise)
CASE(JSObjectIsArray)
CASE(JSRegExpTest)
CASE(JSDebugger) {
// TODO(nicohartmann@): These operators might need to be supported.
break;
}
MACHINE_SIMD_OP_LIST(CASE)
IF_WASM(SIMPLIFIED_WASM_OP_LIST, CASE) {
// SIMD operators should not be in the graph, yet.
UNREACHABLE();
}
#undef CASE
}
}
......
......@@ -1317,11 +1317,12 @@ class RepresentationSelector {
return MachineType(rep, MachineSemantic::kInt64);
}
MachineType machine_type(rep, DeoptValueSemanticOf(type));
DCHECK(machine_type.representation() != MachineRepresentation::kWord32 ||
machine_type.semantic() == MachineSemantic::kInt32 ||
machine_type.semantic() == MachineSemantic::kUint32);
DCHECK(machine_type.representation() != MachineRepresentation::kBit ||
type.Is(Type::Boolean()));
DCHECK_IMPLIES(
machine_type.representation() == MachineRepresentation::kWord32,
machine_type.semantic() == MachineSemantic::kInt32 ||
machine_type.semantic() == MachineSemantic::kUint32);
DCHECK_IMPLIES(machine_type.representation() == MachineRepresentation::kBit,
type.Is(Type::Boolean()));
return machine_type;
}
......
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