Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  EffectiveAddressAnalysis.cpp

  Sprache: C
 

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=8 sts=2 et sw=2 tw=80:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "jit/EffectiveAddressAnalysis.h"

#include "jit/IonAnalysis.h"
#include "jit/MIR-wasm.h"
#include "jit/MIR.h"
#include "jit/MIRGenerator.h"
#include "jit/MIRGraph.h"
#include "util/CheckedArithmetic.h"

using namespace js;
using namespace jit;

static void AnalyzeLsh(TempAllocator& alloc, MLsh* lsh) {
  if (lsh->type() != MIRType::Int32) {
    return;
  }

  if (lsh->isRecoveredOnBailout()) {
    return;
  }

  MDefinition* index = lsh->lhs();
  MOZ_ASSERT(index->type() == MIRType::Int32);

  MConstant* shiftValue = lsh->rhs()->maybeConstantValue();
  if (!shiftValue) {
    return;
  }

  if (shiftValue->type() != MIRType::Int32 ||
      !IsShiftInScaleRange(shiftValue->toInt32())) {
    return;
  }

  Scale scale = ShiftToScale(shiftValue->toInt32());

  int32_t displacement = 0;
  MInstruction* last = lsh;
  MDefinition* base = nullptr;
  while (true) {
    if (!last->hasOneUse()) {
      break;
    }

    MUseIterator use = last->usesBegin();
    if (!use->consumer()->isDefinition() ||
        !use->consumer()->toDefinition()->isAdd()) {
      break;
    }

    MAdd* add = use->consumer()->toDefinition()->toAdd();
    if (add->type() != MIRType::Int32 || !add->isTruncated()) {
      break;
    }

    MDefinition* other = add->getOperand(1 - add->indexOf(*use));

    if (MConstant* otherConst = other->maybeConstantValue()) {
      displacement += otherConst->toInt32();
    } else {
      if (base) {
        break;
      }
      base = other;
    }

    last = add;
    if (last->isRecoveredOnBailout()) {
      return;
    }
  }

  if (!base) {
    uint32_t elemSize = 1 << ScaleToShift(scale);
    if (displacement % elemSize != 0) {
      return;
    }

    if (!last->hasOneUse()) {
      return;
    }

    MUseIterator use = last->usesBegin();
    if (!use->consumer()->isDefinition() ||
        !use->consumer()->toDefinition()->isBitAnd()) {
      return;
    }

    MBitAnd* bitAnd = use->consumer()->toDefinition()->toBitAnd();
    if (bitAnd->isRecoveredOnBailout()) {
      return;
    }

    MDefinition* other = bitAnd->getOperand(1 - bitAnd->indexOf(*use));
    MConstant* otherConst = other->maybeConstantValue();
    if (!otherConst || otherConst->type() != MIRType::Int32) {
      return;
    }

    uint32_t bitsClearedByShift = elemSize - 1;
    uint32_t bitsClearedByMask = ~uint32_t(otherConst->toInt32());
    if ((bitsClearedByShift & bitsClearedByMask) != bitsClearedByMask) {
      return;
    }

    bitAnd->replaceAllUsesWith(last);
    return;
  }

  if (base->isRecoveredOnBailout()) {
    return;
  }

  MEffectiveAddress* eaddr =
      MEffectiveAddress::New(alloc, base, index, scale, displacement);
  last->replaceAllUsesWith(eaddr);
  last->block()->insertAfter(last, eaddr);
}

// Transform:
//
//   [AddI]
//   addl       $9, %esi
//   [LoadUnboxedScalar]
//   movsd      0x0(%rbx,%rsi,8), %xmm4
//
// into:
//
//   [LoadUnboxedScalar]
//   movsd      0x48(%rbx,%rsi,8), %xmm4
//
// This is possible when the AddI is only used by the LoadUnboxedScalar opcode.
static void AnalyzeLoadUnboxedScalar(MLoadUnboxedScalar* load) {
  if (load->isRecoveredOnBailout()) {
    return;
  }

  if (!load->getOperand(1)->isAdd()) {
    return;
  }

  JitSpew(JitSpew_EAA, "analyze: %s%u", load->opName(), load->id());

  MAdd* add = load->getOperand(1)->toAdd();

  if (add->type() != MIRType::Int32 || !add->hasUses() ||
      add->truncateKind() != TruncateKind::Truncate) {
    return;
  }

  MDefinition* lhs = add->lhs();
  MDefinition* rhs = add->rhs();
  MDefinition* constant = nullptr;
  MDefinition* node = nullptr;

  if (lhs->isConstant()) {
    constant = lhs;
    node = rhs;
  } else if (rhs->isConstant()) {
    constant = rhs;
    node = lhs;
  } else
    return;

  MOZ_ASSERT(constant->type() == MIRType::Int32);

  size_t storageSize = Scalar::byteSize(load->storageType());
  int32_t c1 = load->offsetAdjustment();
  int32_t c2 = 0;
  if (!SafeMul(constant->maybeConstantValue()->toInt32(), storageSize, &c2)) {
    return;
  }

  int32_t offset = 0;
  if (!SafeAdd(c1, c2, &offset)) {
    return;
  }

  JitSpew(JitSpew_EAA, "set offset: %d + %d = %d on: %s%u", c1, c2, offset,
          load->opName(), load->id());
  load->setOffsetAdjustment(offset);
  load->replaceOperand(1, node);

  if (!add->hasLiveDefUses() && DeadIfUnused(add) &&
      add->canRecoverOnBailout()) {
    JitSpew(JitSpew_EAA, "mark as recovered on bailout: %s%u", add->opName(),
            add->id());
    add->setRecoveredOnBailoutUnchecked();
  }
}

template <typename AsmJSMemoryAccess>
void EffectiveAddressAnalysis::analyzeAsmJSHeapAccess(AsmJSMemoryAccess* ins) {
  MDefinition* base = ins->base();

  if (base->isConstant()) {
    // If the index is within the minimum heap length, we can optimize away the
    // bounds check.  Asm.js accesses always have an int32 base, the memory is
    // always a memory32.
    int32_t imm = base->toConstant()->toInt32();
    if (imm >= 0) {
      int32_t end = (uint32_t)imm + ins->byteSize();
      if (end >= imm && (uint32_t)end <= mir_->minWasmMemory0Length()) {
        ins->removeBoundsCheck();
      }
    }
  }
}

// This analysis converts patterns of the form:
//   truncate(x + (y << {0,1,2,3}))
//   truncate(x + (y << {0,1,2,3}) + imm32)
// into a single lea instruction, and patterns of the form:
//   asmload(x + imm32)
//   asmload(x << {0,1,2,3})
//   asmload((x << {0,1,2,3}) + imm32)
//   asmload((x << {0,1,2,3}) & mask)            (where mask is redundant
//                                                with shift)
//   asmload(((x << {0,1,2,3}) + imm32) & mask)  (where mask is redundant
//                                                with shift + imm32)
// into a single asmload instruction (and for asmstore too).
//
// Additionally, we should consider the general forms:
//   truncate(x + y + imm32)
//   truncate((y << {0,1,2,3}) + imm32)
bool EffectiveAddressAnalysis::analyze() {
  JitSpew(JitSpew_EAA, "Begin");
  for (ReversePostorderIterator block(graph_.rpoBegin());
       block != graph_.rpoEnd(); block++) {
    for (MInstructionIterator i = block->begin(); i != block->end(); i++) {
      if (!graph_.alloc().ensureBallast()) {
        return false;
      }

      // Note that we don't check for MWasmCompareExchangeHeap
      // or MWasmAtomicBinopHeap, because the backend and the OOB
      // mechanism don't support non-zero offsets for them yet
      // (TODO bug 1254935).
      if (i->isLsh()) {
        AnalyzeLsh(graph_.alloc(), i->toLsh());
      } else if (i->isLoadUnboxedScalar()) {
        AnalyzeLoadUnboxedScalar(i->toLoadUnboxedScalar());
      } else if (i->isAsmJSLoadHeap()) {
        analyzeAsmJSHeapAccess(i->toAsmJSLoadHeap());
      } else if (i->isAsmJSStoreHeap()) {
        analyzeAsmJSHeapAccess(i->toAsmJSStoreHeap());
      }
    }
  }
  return true;
}

Messung V0.5 in Prozent
C=91 H=94 G=92

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-06-10) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik