32 dead_(graph->NewNode(common->Dead())),
34 default_branch_semantics_(default_branch_semantics) {
40 switch (node->opcode()) {
41 case IrOpcode::kBranch:
43 case IrOpcode::kDeoptimizeIf:
44 case IrOpcode::kDeoptimizeUnless:
46 case IrOpcode::kMerge:
48 case IrOpcode::kEffectPhi:
52 case IrOpcode::kReturn:
54 case IrOpcode::kSelect:
56 case IrOpcode::kSwitch:
58 case IrOpcode::kStaticAssert:
60 case IrOpcode::kTrapIf:
61 case IrOpcode::kTrapUnless:
72 switch (unwrapped->
opcode()) {
73 case IrOpcode::kInt32Constant: {
78 case IrOpcode::kHeapConstant: {
83 std::optional<bool> maybe_result =
94 DCHECK_EQ(IrOpcode::kBranch, node->opcode());
102 if (cond->
opcode() == IrOpcode::kBooleanNot ||
103 (cond->
opcode() == IrOpcode::kSelect &&
108 for (
Node*
const use : node->
uses()) {
109 switch (use->opcode()) {
110 case IrOpcode::kIfTrue:
113 case IrOpcode::kIfFalse:
123 node->ReplaceInput(0, cond->
InputAt(0));
127 return Changed(node);
132 for (
Node*
const use : node->
uses()) {
133 switch (use->opcode()) {
134 case IrOpcode::kIfTrue:
137 case IrOpcode::kIfFalse:
144 return Replace(
dead());
148 DCHECK(node->opcode() == IrOpcode::kDeoptimizeIf ||
149 node->opcode() == IrOpcode::kDeoptimizeUnless);
150 bool condition_is_true = node->opcode() == IrOpcode::kDeoptimizeUnless;
160 if (
condition->opcode() == IrOpcode::kBooleanNot) {
163 node, condition_is_true
166 return Changed(node);
172 ReplaceWithValue(node,
dead(), effect, control);
175 frame_state, effect, control);
178 return Replace(
dead());
182 DCHECK_EQ(IrOpcode::kMerge, node->opcode());
192 if (node->InputCount() == 2) {
193 for (
Node*
const use : node->
uses()) {
198 if (if_true->
opcode() != IrOpcode::kIfTrue) std::swap(if_true, if_false);
199 if (if_true->
opcode() == IrOpcode::kIfTrue &&
200 if_false->
opcode() == IrOpcode::kIfFalse &&
210 return Replace(control);
218 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode());
220 int const effect_input_count = inputs.
count() - 1;
222 Node*
const merge = inputs[effect_input_count];
225 Node*
const effect = inputs[0];
227 for (
int i = 1;
i < effect_input_count; ++
i) {
228 Node*
const input = inputs[
i];
234 if (input != effect)
return NoChange();
238 return Replace(effect);
243 DCHECK_EQ(IrOpcode::kPhi, node->opcode());
245 int const value_input_count = inputs.
count() - 1;
247 Node*
const merge = inputs[value_input_count];
250 if (value_input_count == 2) {
266 Node* vtrue = inputs[0];
267 Node* vfalse = inputs[1];
269 Node* if_true = merge_inputs[0];
270 Node* if_false = merge_inputs[1];
271 if (if_true->
opcode() != IrOpcode::kIfTrue) {
272 std::swap(if_true, if_false);
273 std::swap(vtrue, vfalse);
275 if (if_true->
opcode() == IrOpcode::kIfTrue &&
276 if_false->
opcode() == IrOpcode::kIfFalse &&
280 if (branch->
opcode() != IrOpcode::kBranch)
return NoChange();
282 if (cond->
opcode() == IrOpcode::kFloat32LessThan) {
284 if (mcond.
left().Is(0.0) && mcond.
right().Equals(vtrue) &&
285 vfalse->
opcode() == IrOpcode::kFloat32Sub) {
287 if (mvfalse.
left().IsZero() && mvfalse.
right().Equals(vtrue)) {
293 }
else if (cond->
opcode() == IrOpcode::kFloat64LessThan) {
295 if (mcond.
left().Is(0.0) && mcond.
right().Equals(vtrue) &&
296 vfalse->
opcode() == IrOpcode::kFloat64Sub) {
298 if (mvfalse.
left().IsZero() && mvfalse.
right().Equals(vtrue)) {
304 }
else if (cond->
opcode() == IrOpcode::kInt32LessThan) {
306 if (mcond.
left().Is(0) && mcond.
right().Equals(vtrue) &&
307 (vfalse->
opcode() == IrOpcode::kInt32Sub)) {
309 if (mvfalse.
left().Is(0) && mvfalse.
right().Equals(vtrue)) {
313 if (
machine()->Word32Select().IsSupported()) {
336 Node*
const value = inputs[0];
338 for (
int i = 1;
i < value_input_count; ++
i) {
339 Node*
const input = inputs[
i];
345 if (input != value)
return NoChange();
349 return Replace(value);
353 DCHECK_EQ(IrOpcode::kReturn, node->opcode());
356 if (effect->opcode() == IrOpcode::kCheckpoint) {
370 if (value->opcode() == IrOpcode::kPhi &&
372 control->
opcode() == IrOpcode::kMerge) {
403 if (control->
OwnedBy(node, value) && value->OwnedBy(node)) {
404 for (
int i = 0;
i < control_inputs.
count(); ++
i) {
410 effect, control_inputs[
i]);
414 Replace(control,
dead());
415 return Replace(
dead());
416 }
else if (effect->opcode() == IrOpcode::kEffectPhi &&
420 for (
int i = 0;
i < control_inputs.
count(); ++
i) {
426 effect_inputs[
i], control_inputs[
i]);
430 Replace(control,
dead());
431 return Replace(
dead());
438 DCHECK_EQ(IrOpcode::kSelect, node->opcode());
442 if (vtrue == vfalse)
return Replace(vtrue);
445 return Replace(vtrue);
447 return Replace(vfalse);
457 case IrOpcode::kFloat32LessThan: {
459 if (mcond.
left().Is(0.0) && mcond.
right().Equals(vtrue) &&
460 vfalse->
opcode() == IrOpcode::kFloat32Sub) {
462 if (mvfalse.
left().IsZero() && mvfalse.
right().Equals(vtrue)) {
468 case IrOpcode::kFloat64LessThan: {
470 if (mcond.
left().Is(0.0) && mcond.
right().Equals(vtrue) &&
471 vfalse->
opcode() == IrOpcode::kFloat64Sub) {
473 if (mvfalse.
left().IsZero() && mvfalse.
right().Equals(vtrue)) {
486 DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
496 bool matched =
false;
498 size_t const projection_count = node->op()->ControlOutputCount();
502 for (
size_t i = 0;
i < projection_count - 1;
i++) {
503 Node* if_value = projections[
i];
508 Replace(if_value, control);
513 Node* if_default = projections[projection_count - 1];
515 Replace(if_default, control);
517 return Replace(
dead());
523 DCHECK_EQ(IrOpcode::kStaticAssert, node->opcode());
527 RelaxEffectsAndControls(node);
528 return Changed(node);
536 trap->opcode() == IrOpcode::kTrapUnless);
537 bool trapping_condition =
trap->opcode() == IrOpcode::kTrapIf;
549 return Changed(
trap);
556 return Replace(control);
562 node->ReplaceInput(0, a);
563 node->TrimInputCount(1);
565 return Changed(node);
571 node->ReplaceInput(0, a);
572 node->ReplaceInput(1, b);
573 node->TrimInputCount(2);
575 return Changed(node);
T * AllocateArray(size_t length)
BranchSemantics BranchSemanticsOf(const Node *branch)
Reduction ReduceReturn(Node *node)
Reduction ReduceStaticAssert(Node *node)
CommonOperatorReducer(Editor *editor, TFGraph *graph, JSHeapBroker *broker, CommonOperatorBuilder *common, MachineOperatorBuilder *machine, Zone *temp_zone, BranchSemantics default_branch_semantics)
CommonOperatorBuilder * common() const
Reduction ReduceMerge(Node *node)
JSHeapBroker *const broker_
Reduction ReduceEffectPhi(Node *node)
Reduction ReduceSelect(Node *node)
Reduction Change(Node *node, Operator const *op, Node *a)
Reduction ReduceDeoptimizeConditional(Node *node)
Decision DecideCondition(Node *const cond, BranchSemantics branch_semantics)
Reduction ReduceSwitch(Node *node)
Reduction ReduceBranch(Node *node)
MachineOperatorBuilder * machine() const
Reduction Reduce(Node *node) final
Reduction ReducePhi(Node *node)
BranchSemantics default_branch_semantics_
Reduction ReduceTrapConditional(Node *node)
JSHeapBroker * broker() const
DeoptimizeReason reason() const
const FeedbackSource & feedback() const
static bool IsMergeOpcode(Value value)
static bool IsPhiOpcode(Value value)
static void ChangeOp(Node *node, const Operator *new_op)
static void ReplaceEffectInput(Node *node, Node *effect, int index=0)
static Node * GetEffectInput(Node *node, int index=0)
static void CollectControlProjections(Node *node, Node **proj, size_t count)
static Node * GetValueInput(Node *node, int index)
static void SetType(Node *node, Type type)
static void ReplaceValueInput(Node *node, Node *value, int index)
static Node * GetControlInput(Node *node, int index=0)
constexpr IrOpcode::Value opcode() const
void TrimInputCount(int new_input_count)
const Operator * op() const
Node * InputAt(int index) const
bool OwnedBy(Node const *owner) const
Node * NewNode(const Operator *op, int input_count, Node *const *inputs, bool incomplete=false)
JSHeapBroker *const broker_
std::optional< OolTrapLabel > trap
IfValueParameters const & IfValueParametersOf(const Operator *op)
int ValueInputCountOfReturn(Operator const *const op)
BranchHint BranchHintOf(const Operator *const op)
BranchHint NegateBranchHint(BranchHint hint)
DeoptimizeParameters const & DeoptimizeParametersOf(Operator const *const op)
Node * SkipValueIdentities(Node *node)
#define DCHECK_LE(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
const Left & left() const
const Right & right() const
const T & ResolvedValue() const
bool HasResolvedValue() const