tor-browser

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

AlignmentMaskAnalysis.cpp (3231B)


      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/AlignmentMaskAnalysis.h"
      8 #include "jit/MIR-wasm.h"
      9 #include "jit/MIR.h"
     10 #include "jit/MIRGraph.h"
     11 
     12 using namespace js;
     13 using namespace jit;
     14 
     15 static bool IsAlignmentMask(uint32_t m) {
     16  // Test whether m is just leading ones and trailing zeros.
     17  return (-m & ~m) == 0;
     18 }
     19 
     20 static void AnalyzeAsmHeapAddress(MDefinition* ptr, MIRGraph& graph) {
     21  // Fold (a+i)&m to (a&m)+i, provided that this doesn't change the result,
     22  // since the users of the BitAnd include heap accesses. This will expose
     23  // the redundancy for GVN when expressions like this:
     24  //   a&m
     25  //   (a+1)&m,
     26  //   (a+2)&m,
     27  // are transformed into this:
     28  //   a&m
     29  //   (a&m)+1
     30  //   (a&m)+2
     31  // and it will allow the constants to be folded by the
     32  // EffectiveAddressAnalysis pass.
     33  //
     34  // Putting the add on the outside might seem like it exposes other users of
     35  // the expression to the possibility of i32 overflow, if we aren't in wasm
     36  // and they aren't naturally truncating. However, since we use MAdd::New
     37  // with MIRType::Int32, we make sure that the value is truncated, just as it
     38  // would be by the MBitAnd.
     39 
     40  MOZ_ASSERT(IsCompilingWasm());
     41 
     42  if (!ptr->isBitAnd()) {
     43    return;
     44  }
     45 
     46  MDefinition* lhs = ptr->toBitAnd()->getOperand(0);
     47  MDefinition* rhs = ptr->toBitAnd()->getOperand(1);
     48  if (lhs->isConstant()) {
     49    std::swap(lhs, rhs);
     50  }
     51  if (!lhs->isAdd() || !rhs->isConstant()) {
     52    return;
     53  }
     54 
     55  MDefinition* op0 = lhs->toAdd()->getOperand(0);
     56  MDefinition* op1 = lhs->toAdd()->getOperand(1);
     57  if (op0->isConstant()) {
     58    std::swap(op0, op1);
     59  }
     60  if (!op1->isConstant()) {
     61    return;
     62  }
     63 
     64  uint32_t i = op1->toConstant()->toInt32();
     65  uint32_t m = rhs->toConstant()->toInt32();
     66  if (!IsAlignmentMask(m) || (i & m) != i) {
     67    return;
     68  }
     69 
     70  // The pattern was matched! Produce the replacement expression.
     71  MInstruction* and_ = MBitAnd::New(graph.alloc(), op0, rhs, MIRType::Int32);
     72  ptr->block()->insertBefore(ptr->toBitAnd(), and_);
     73  auto* add = MAdd::New(graph.alloc(), and_, op1, TruncateKind::Truncate);
     74  ptr->block()->insertBefore(ptr->toBitAnd(), add);
     75  ptr->replaceAllUsesWith(add);
     76  ptr->block()->discard(ptr->toBitAnd());
     77 }
     78 
     79 bool AlignmentMaskAnalysis::analyze() {
     80  for (ReversePostorderIterator block(graph_.rpoBegin());
     81       block != graph_.rpoEnd(); block++) {
     82    for (MInstructionIterator i = block->begin(); i != block->end(); i++) {
     83      if (!graph_.alloc().ensureBallast()) {
     84        return false;
     85      }
     86 
     87      // Note that we don't check for MWasmCompareExchangeHeap
     88      // or MWasmAtomicBinopHeap, because the backend and the OOB
     89      // mechanism don't support non-zero offsets for them yet.
     90      if (i->isAsmJSLoadHeap()) {
     91        AnalyzeAsmHeapAddress(i->toAsmJSLoadHeap()->base(), graph_);
     92      } else if (i->isAsmJSStoreHeap()) {
     93        AnalyzeAsmHeapAddress(i->toAsmJSStoreHeap()->base(), graph_);
     94      }
     95    }
     96  }
     97  return true;
     98 }