22 dead_(js_graph->Dead()),
28 switch (node->opcode()) {
31 case IrOpcode::kDeoptimizeIf:
32 case IrOpcode::kDeoptimizeUnless:
34 case IrOpcode::kMerge:
38 case IrOpcode::kBranch:
40 case IrOpcode::kIfFalse:
42 case IrOpcode::kIfTrue:
44 case IrOpcode::kTrapIf:
45 case IrOpcode::kTrapUnless:
47 case IrOpcode::kStart:
50 if (node->op()->ControlOutputCount() > 0) {
87 auto SemanticsOf = [phase = this->
phase_](
Node* branch) {
89 if (branch->
opcode() == IrOpcode::kBranch) {
101 if (merge->
opcode() != IrOpcode::kMerge)
return;
109 int input_count = inputs.
count();
110 for (
int i = 0;
i != input_count; ++
i) {
111 Node* input = inputs[
i];
115 if (!branch_condition.
IsSet())
return;
116 if (SemanticsOf(branch_condition.
branch) != semantics)
return;
117 bool condition_value = branch_condition.
is_true;
135 input_count + 1, &phi_inputs.
at(0));
164 DCHECK_EQ(phi->opcode(), IrOpcode::kPhi);
167 if (!phi->OwnedBy(branch))
return false;
168 if (phi->InputCount() != 3)
return false;
169 if (phi->InputAt(2) != merge)
return false;
170 if (merge->
UseCount() != 2)
return false;
173 Node* first_value = phi_inputs[0];
174 Node* second_value = phi_inputs[1];
175 if (first_value->
opcode() != IrOpcode::kInt32Constant ||
176 second_value->
opcode() != IrOpcode::kInt32Constant) {
180 Node* predecessor0 = merge_inputs[0];
181 Node* predecessor1 = merge_inputs[1];
183 Node** projections = zone()->AllocateArray<
Node*>(2);
185 Node* branch_true = projections[0];
186 Node* branch_false = projections[1];
193 Node* predecessor_true =
nullptr;
194 Node* predecessor_false =
nullptr;
195 if (mfirst_value.
Is(1) && msecond_value.
Is(0)) {
196 predecessor_true = predecessor0;
197 predecessor_false = predecessor1;
198 }
else if (mfirst_value.
Is(0) && msecond_value.
Is(1)) {
199 predecessor_true = predecessor1;
200 predecessor_false = predecessor0;
207 edge.UpdateTo(predecessor_true);
210 edge.UpdateTo(predecessor_false);
214 branch_false->
Kill();
224 if (!IsReduced(control_input))
return NoChange();
228 if (branch_condition.
IsSet()) {
229 bool condition_value = branch_condition.
is_true;
230 for (
Node*
const use : node->
uses()) {
231 switch (use->opcode()) {
232 case IrOpcode::kIfTrue:
233 Replace(use, condition_value ? control_input :
dead());
235 case IrOpcode::kIfFalse:
236 Replace(use, condition_value ?
dead() : control_input);
242 return Replace(
dead());
246 if (
condition->opcode() == IrOpcode::kPhi &&
247 control_input->
opcode() == IrOpcode::kMerge) {
249 return Replace(
dead());
254 for (
Node*
const use : node->
uses()) {
257 return TakeStatesFromFirstControl(node);
261 DCHECK(node->opcode() == IrOpcode::kTrapIf ||
262 node->opcode() == IrOpcode::kTrapUnless);
263 bool trapping_condition = node->opcode() == IrOpcode::kTrapIf;
269 if (!IsReduced(control_input))
return NoChange();
274 if (branch_condition.
IsSet()) {
275 bool condition_value = branch_condition.
is_true;
276 if (condition_value == trapping_condition) {
282 return Changed(node);
285 RelaxEffectsAndControls(node);
288 return Replace(control);
292 !trapping_condition,
false);
296 DCHECK(node->opcode() == IrOpcode::kDeoptimizeIf ||
297 node->opcode() == IrOpcode::kDeoptimizeUnless);
298 bool condition_is_true = node->opcode() == IrOpcode::kDeoptimizeUnless;
307 if (!IsReduced(control)) {
313 if (branch_condition.
IsSet()) {
315 bool condition_value = branch_condition.
is_true;
316 if (condition_is_true == condition_value) {
319 ReplaceWithValue(node,
dead(), effect, control);
322 frame_state, effect, control);
325 return Replace(
dead());
328 condition_is_true,
false);
338 if (!IsReduced(branch)) {
343 is_true_branch,
true);
350 return TakeStatesFromFirstControl(node);
357 for (
Node* input : inputs) {
358 if (!IsReduced(input)) {
363 auto input_it = inputs.
begin();
371 auto input_end = inputs.
end();
372 for (; input_it != input_end; ++input_it) {
378 return UpdateStates(node, conditions);
386 DCHECK_EQ(1, node->op()->ControlInputCount());
387 return TakeStatesFromFirstControl(node);
void emplace_back(Args &&... args)
Reduction UpdateStatesHelper(Node *node, ControlPathConditions prev_conditions, Node *current_condition, Node *current_branch, bool is_true_branch, bool in_new_block)
Isolate * isolate() const
Reduction Reduce(Node *node) final
void SimplifyBranchCondition(Node *branch)
bool TryEliminateBranchWithPhiCondition(Node *branch, Node *phi, Node *merge)
Reduction ReduceLoop(Node *node)
Reduction ReduceBranch(Node *node)
JSGraph * jsgraph() const
Reduction ReduceOtherControl(Node *node)
Reduction ReduceMerge(Node *node)
Reduction ReduceIf(Node *node, bool is_true_branch)
Reduction ReduceDeoptimizeConditional(Node *node)
ControlPathState< BranchCondition, kUniqueInstance > ControlPathConditions
BranchElimination(Editor *editor, JSGraph *js_graph, Zone *zone, Phase phase=kLATE)
Reduction ReduceTrapConditional(Node *node)
CommonOperatorBuilder * common() const
Reduction ReduceStart(Node *node)
~BranchElimination() final
void ResetToCommonAncestor(ControlPathState other)
NodeState LookupState(Node *node) const
DeoptimizeReason reason() const
const FeedbackSource & feedback() const
Isolate * isolate() const
CommonOperatorBuilder * common() const
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 ReplaceValueInput(Node *node, Node *value, int index)
static Node * GetControlInput(Node *node, int index=0)
constexpr IrOpcode::Value opcode() const
const Operator * op() const
Node * InputAt(int index) const
Node * NewNode(const Operator *op, int input_count, Node *const *inputs, bool incomplete=false)
const BranchParameters & BranchParametersOf(const Operator *const op)
template bool DefaultConstruct< bool >(Zone *zone)
DeoptimizeParameters const & DeoptimizeParametersOf(Operator const *const op)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
bool Is(const T &value) const