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"
11 #include "jit/MIRGenerator.h"
12 #include "jit/MIRGraph.h"
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()) {
29 JitSpew(JitSpew_FLAC
, "mark as recovered on bailout: %s%u", def
->opName(),
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()) {
47 if (!add
->hasUses()) {
51 JitSpew(JitSpew_FLAC
, "analyze add: %s%u", add
->opName(), add
->id());
53 SimpleLinearSum sum
= ExtractLinearSum(add
);
54 if (sum
.constant
== 0 || !sum
.term
) {
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()) {
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(),
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();
90 if (mir
->shouldCancel("Fold Linear Arithmetic Constants (main loop)")) {
94 for (MInstructionIterator i
= block
->begin(); i
!= block
->end(); i
++) {
95 if (!graph
.alloc().ensureBallast()) {
99 if (mir
->shouldCancel("Fold Linear Arithmetic Constants (inner loop)")) {
104 AnalyzeAdd(graph
.alloc(), i
->toAdd());
111 } /* namespace jit */