tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

FoldLinearArithConstants.cpp (3697B)


      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/. */
      6 
      7 #include "jit/FoldLinearArithConstants.h"
      8 
      9 #include "jit/IonAnalysis.h"
     10 #include "jit/MIR-wasm.h"
     11 #include "jit/MIR.h"
     12 #include "jit/MIRGenerator.h"
     13 #include "jit/MIRGraph.h"
     14 
     15 using namespace js;
     16 using namespace jit;
     17 
     18 namespace js {
     19 namespace jit {
     20 
     21 // Mark this node and its children as RecoveredOnBailout when they are not used.
     22 // The marked nodes will be removed during DCE. Marking as RecoveredOnBailout is
     23 // necessary because the Sink pass is ran before this pass.
     24 static void markNodesAsRecoveredOnBailout(MDefinition* def) {
     25  if (def->hasLiveDefUses() || !DeadIfUnused(def) ||
     26      !def->canRecoverOnBailout()) {
     27    return;
     28  }
     29 
     30  JitSpew(JitSpew_FLAC, "mark as recovered on bailout: %s%u", def->opName(),
     31          def->id());
     32  def->setRecoveredOnBailoutUnchecked();
     33 
     34  // Recursively mark nodes that do not have multiple uses. This loop is
     35  // necessary because a node could be an unused right shift zero or an
     36  // unused add, and both need to be marked as RecoveredOnBailout.
     37  for (size_t i = 0; i < def->numOperands(); i++) {
     38    markNodesAsRecoveredOnBailout(def->getOperand(i));
     39  }
     40 }
     41 
     42 // Fold AddIs with one variable and two or more constants into one AddI.
     43 static void AnalyzeAdd(TempAllocator& alloc, MAdd* add) {
     44  if (add->type() != MIRType::Int32 || add->isRecoveredOnBailout()) {
     45    return;
     46  }
     47 
     48  if (!add->hasUses()) {
     49    return;
     50  }
     51 
     52  JitSpew(JitSpew_FLAC, "analyze add: %s%u", add->opName(), add->id());
     53 
     54  SimpleLinearSum sum = ExtractLinearSum(add);
     55  if (sum.constant == 0 || !sum.term) {
     56    return;
     57  }
     58 
     59  // Determine which operand is the constant.
     60  int idx = add->getOperand(0)->isConstant() ? 0 : 1;
     61  if (add->getOperand(idx)->isConstant()) {
     62    // Do not replace an add where the outcome is the same add instruction.
     63    MOZ_ASSERT(add->getOperand(idx)->toConstant()->type() == MIRType::Int32);
     64    if (sum.term == add->getOperand(1 - idx) ||
     65        sum.constant == add->getOperand(idx)->toConstant()->toInt32()) {
     66      return;
     67    }
     68  }
     69 
     70  MInstruction* rhs = MConstant::NewInt32(alloc, sum.constant);
     71  add->block()->insertBefore(add, rhs);
     72 
     73  MAdd* addNew = MAdd::New(alloc, sum.term, rhs, add->truncateKind());
     74  addNew->setBailoutKind(add->bailoutKind());
     75 
     76  add->replaceAllLiveUsesWith(addNew);
     77  add->block()->insertBefore(add, addNew);
     78  JitSpew(JitSpew_FLAC, "replaced with: %s%u", addNew->opName(), addNew->id());
     79  JitSpew(JitSpew_FLAC, "and constant: %s%u (%d)", rhs->opName(), rhs->id(),
     80          sum.constant);
     81 
     82  // Mark the stale nodes as RecoveredOnBailout since the Sink pass has
     83  // been run before this pass. DCE will then remove the unused nodes.
     84  markNodesAsRecoveredOnBailout(add);
     85 }
     86 
     87 bool FoldLinearArithConstants(const MIRGenerator* mir, MIRGraph& graph) {
     88  JitSpew(JitSpew_FLAC, "Begin");
     89  for (PostorderIterator block(graph.poBegin()); block != graph.poEnd();
     90       block++) {
     91    if (mir->shouldCancel("Fold Linear Arithmetic Constants (main loop)")) {
     92      return false;
     93    }
     94 
     95    for (MInstructionIterator i = block->begin(); i != block->end(); i++) {
     96      if (!graph.alloc().ensureBallast()) {
     97        return false;
     98      }
     99 
    100      if (mir->shouldCancel("Fold Linear Arithmetic Constants (inner loop)")) {
    101        return false;
    102      }
    103 
    104      if (i->isAdd()) {
    105        AnalyzeAdd(graph.alloc(), i->toAdd());
    106      }
    107    }
    108  }
    109  return true;
    110 }
    111 
    112 } /* namespace jit */
    113 } /* namespace js */