Bug 1867190 - Add prefs for PHC probablities r=glandium
[gecko.git] / js / src / jit / FoldLinearArithConstants.cpp
blob5cb5ef62f61e134c05099dc424dfc83844ca6b7e
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "jit/FoldLinearArithConstants.h"
9 #include "jit/IonAnalysis.h"
10 #include "jit/MIR.h"
11 #include "jit/MIRGenerator.h"
12 #include "jit/MIRGraph.h"
14 using namespace js;
15 using namespace jit;
17 namespace js {
18 namespace jit {
20 // Mark this node and its children as RecoveredOnBailout when they are not used.
21 // The marked nodes will be removed during DCE. Marking as RecoveredOnBailout is
22 // necessary because the Sink pass is ran before this pass.
23 static void markNodesAsRecoveredOnBailout(MDefinition* def) {
24 if (def->hasLiveDefUses() || !DeadIfUnused(def) ||
25 !def->canRecoverOnBailout()) {
26 return;
29 JitSpew(JitSpew_FLAC, "mark as recovered on bailout: %s%u", def->opName(),
30 def->id());
31 def->setRecoveredOnBailoutUnchecked();
33 // Recursively mark nodes that do not have multiple uses. This loop is
34 // necessary because a node could be an unused right shift zero or an
35 // unused add, and both need to be marked as RecoveredOnBailout.
36 for (size_t i = 0; i < def->numOperands(); i++) {
37 markNodesAsRecoveredOnBailout(def->getOperand(i));
41 // Fold AddIs with one variable and two or more constants into one AddI.
42 static void AnalyzeAdd(TempAllocator& alloc, MAdd* add) {
43 if (add->type() != MIRType::Int32 || add->isRecoveredOnBailout()) {
44 return;
47 if (!add->hasUses()) {
48 return;
51 JitSpew(JitSpew_FLAC, "analyze add: %s%u", add->opName(), add->id());
53 SimpleLinearSum sum = ExtractLinearSum(add);
54 if (sum.constant == 0 || !sum.term) {
55 return;
58 // Determine which operand is the constant.
59 int idx = add->getOperand(0)->isConstant() ? 0 : 1;
60 if (add->getOperand(idx)->isConstant()) {
61 // Do not replace an add where the outcome is the same add instruction.
62 MOZ_ASSERT(add->getOperand(idx)->toConstant()->type() == MIRType::Int32);
63 if (sum.term == add->getOperand(1 - idx) ||
64 sum.constant == add->getOperand(idx)->toConstant()->toInt32()) {
65 return;
69 MInstruction* rhs = MConstant::New(alloc, Int32Value(sum.constant));
70 add->block()->insertBefore(add, rhs);
72 MAdd* addNew = MAdd::New(alloc, sum.term, rhs, add->truncateKind());
73 addNew->setBailoutKind(add->bailoutKind());
75 add->replaceAllLiveUsesWith(addNew);
76 add->block()->insertBefore(add, addNew);
77 JitSpew(JitSpew_FLAC, "replaced with: %s%u", addNew->opName(), addNew->id());
78 JitSpew(JitSpew_FLAC, "and constant: %s%u (%d)", rhs->opName(), rhs->id(),
79 sum.constant);
81 // Mark the stale nodes as RecoveredOnBailout since the Sink pass has
82 // been run before this pass. DCE will then remove the unused nodes.
83 markNodesAsRecoveredOnBailout(add);
86 bool FoldLinearArithConstants(MIRGenerator* mir, MIRGraph& graph) {
87 JitSpew(JitSpew_FLAC, "Begin");
88 for (PostorderIterator block(graph.poBegin()); block != graph.poEnd();
89 block++) {
90 if (mir->shouldCancel("Fold Linear Arithmetic Constants (main loop)")) {
91 return false;
94 for (MInstructionIterator i = block->begin(); i != block->end(); i++) {
95 if (!graph.alloc().ensureBallast()) {
96 return false;
99 if (mir->shouldCancel("Fold Linear Arithmetic Constants (inner loop)")) {
100 return false;
103 if (i->isAdd()) {
104 AnalyzeAdd(graph.alloc(), i->toAdd());
108 return true;
111 } /* namespace jit */
112 } /* namespace js */