Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/art/art/compiler/optimizing/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 13 kB image not shown  

Quelle  induction_var_analysis.h

  Sprache: C
 

/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#ifndef ART_COMPILER_OPTIMIZING_INDUCTION_VAR_ANALYSIS_H_
#define ART_COMPILER_OPTIMIZING_INDUCTION_VAR_ANALYSIS_H_

#include <string>

#include "base/arena_containers.h"
#include "base/array_ref.h"
#include "base/macros.h"
#include "base/scoped_arena_containers.h"
#include "nodes.h"
#include "optimization.h"

namespace art HIDDEN {

/**
 * Induction variable analysis. This class does not have a direct public API.
 * Instead, the results of induction variable analysis can be queried through
 * friend classes, such as InductionVarRange.
 *
 * The analysis implementation is based on the paper by M. Gerlek et al.
 * "Beyond Induction Variables: Detecting and Classifying Sequences Using a Demand-Driven SSA Form"
 * (ACM Transactions on Programming Languages and Systems, Volume 17 Issue 1, Jan. 1995).
 */

class HInductionVarAnalysis : public HOptimization {
 public:
  explicit HInductionVarAnalysis(HGraph* graph,
                                 OptimizingCompilerStats* stats = nullptr,
                                 const char* name = kInductionPassName);

  bool Run() override;

  static constexpr const char* kInductionPassName = "induction_var_analysis";

 private:
  struct NodeInfo;
  struct StackEntry;

  enum InductionClass {
    kInvariant,
    kLinear,
    kPolynomial,
    kGeometric,
    kWrapAround,
    kPeriodic
  };

  enum InductionOp {
    // Operations.
    kNop,
    kAdd,
    kSub,
    kNeg,
    kMul,
    kDiv,
    kRem,
    kXor,
    kFetch,
    // Trip-counts.
    kTripCountInLoop,        // valid in full loop; loop is finite
    kTripCountInBody,        // valid in body only; loop is finite
    kTripCountInLoopUnsafe,  // valid in full loop; loop may be infinite
    kTripCountInBodyUnsafe,  // valid in body only; loop may be infinite
    // Comparisons for trip-count tests.
    kLT,
    kLE,
    kGT,
    kGE
  };

  /**
   * Defines a detected induction as:
   *   (1) invariant:
   *         op: a + b, a - b, -b, a * b, a / b, a % b, a ^ b, fetch
   *   (2) linear:
   *         nop: a * i + b
   *   (3) polynomial:
   *         nop: sum_lt(a) + b, for linear a
   *   (4) geometric:
   *         op: a * fetch^i + b, a * fetch^-i + b
   *   (5) wrap-around
   *         nop: a, then defined by b
   *   (6) periodic
   *         nop: a, then defined by b (repeated when exhausted)
   *   (7) trip-count:
   *         tc: defined by a, taken-test in b
   */

  struct InductionInfo : public ArenaObject<kArenaAllocInductionVarAnalysis> {
    InductionInfo(InductionClass ic,
                  InductionOp op,
                  InductionInfo* a,
                  InductionInfo* b,
                  HInstruction* f,
                  DataType::Type t)
        : induction_class(ic),
          operation(op),
          op_a(a),
          op_b(b),
          fetch(f),
          type(t) {}
    InductionClass induction_class;
    InductionOp operation;
    InductionInfo* op_a;
    InductionInfo* op_b;
    HInstruction* fetch;
    DataType::Type type;  // precision of operation
  };


  InductionInfo* CreateInvariantOp(const HBasicBlock* context,
                                   const HLoopInformation* loop,
                                   InductionOp op,
                                   InductionInfo* a,
                                   InductionInfo* b) {
    DCHECK(((op != kNeg && a != nullptr) || (op == kNeg && a == nullptr)) && b != nullptr);
    return CreateSimplifiedInvariant(context, loop, op, a, b);
  }

  InductionInfo* CreateInvariantFetch(HInstruction* f) {
    DCHECK(f != nullptr);
    return new (graph_->GetAllocator())
        InductionInfo(kInvariant, kFetch, nullptr, nullptr, f, f->GetType());
  }

  InductionInfo* CreateTripCount(InductionOp op,
                                 InductionInfo* a,
                                 InductionInfo* b,
                                 DataType::Type type) {
    DCHECK(a != nullptr && b != nullptr);
    return new (graph_->GetAllocator()) InductionInfo(kInvariant, op, a, b, nullptr, type);
  }

  InductionInfo* CreateInduction(InductionClass ic,
                                 InductionOp op,
                                 InductionInfo* a,
                                 InductionInfo* b,
                                 HInstruction* f,
                                 DataType::Type type) {
    DCHECK(a != nullptr && b != nullptr);
    return new (graph_->GetAllocator()) InductionInfo(ic, op, a, b, f, type);
  }

  // Methods for analysis.
  void VisitLoop(const HLoopInformation* loop);
  void ReVisitLoop(const HLoopInformation* loop);
  size_t TryVisitNodes(const HLoopInformation* loop,
                       HInstruction* start_instruction,
                       size_t global_depth,
                       /*inout*/ ScopedArenaSafeMap<HInstruction*, NodeInfo>* visited_instructions);
  void ExtractScc(ArrayRef<const StackEntry> stack_tail, ScopedArenaVector<HInstruction*>* scc);
  void ClassifyTrivial(const HLoopInformation* loop, HInstruction* instruction);
  void ClassifyNonTrivial(const HLoopInformation* loop, ArrayRef<const StackEntry> stack_tail);
  InductionInfo* RotatePeriodicInduction(InductionInfo* induction,
                                         InductionInfo* last,
                                         DataType::Type type);

  // Transfer operations.
  InductionInfo* TransferPhi(const HLoopInformation* loop,
                             HInstruction* phi,
                             size_t input_index,
                             size_t adjust_input_size);
  InductionInfo* TransferAddSub(const HBasicBlock* context,
                                const HLoopInformation* loop,
                                InductionInfo* a,
                                InductionInfo* b,
                                InductionOp op,
                                DataType::Type type);
  InductionInfo* TransferNeg(const HBasicBlock* context,
                             const HLoopInformation* loop,
                             InductionInfo* a,
                             DataType::Type type);
  InductionInfo* TransferMul(const HBasicBlock* context,
                             const HLoopInformation* loop,
                             InductionInfo* a,
                             InductionInfo* b,
                             DataType::Type type);
  InductionInfo* TransferConversion(InductionInfo* a, DataType::Type from, DataType::Type to);

  // Solvers.
  InductionInfo* SolvePhi(HInstruction* phi,
                          size_t input_index,
                          size_t adjust_input_size,
                          const ScopedArenaSafeMap<HInstruction*, InductionInfo*>& cycle);
  InductionInfo* SolvePhiAllInputs(const HLoopInformation* loop,
                                   HInstruction* entry_phi,
                                   HInstruction* phi,
                                   const ScopedArenaSafeMap<HInstruction*, InductionInfo*>& cycle,
                                   DataType::Type type);
  InductionInfo* SolveAddSub(const HLoopInformation* loop,
                             HInstruction* entry_phi,
                             HInstruction* instruction,
                             HInstruction* x,
                             HInstruction* y,
                             InductionOp op,
                             const ScopedArenaSafeMap<HInstruction*, InductionInfo*>& cycle,
                             DataType::Type type);
  InductionInfo* SolveOp(const HLoopInformation* loop,
                         HInstruction* entry_phi,
                         HInstruction* instruction,
                         HInstruction* x,
                         HInstruction* y,
                         InductionOp op,
                         DataType::Type type);
  InductionInfo* SolveTest(const HLoopInformation* loop,
                           HInstruction* entry_phi,
                           HInstruction* instruction,
                           int64_t opposite_value,
                           DataType::Type type);
  InductionInfo* SolveConversion(const HLoopInformation* loop,
                                 HInstruction* entry_phi,
                                 HTypeConversion* conversion,
                                 const ScopedArenaSafeMap<HInstruction*, InductionInfo*>& cycle,
                                 /*inout*/ DataType::Type* type);

  //
  // Loop trip count analysis methods.
  //

  // Trip count information.
  void VisitControl(const HLoopInformation* loop);
  void VisitCondition(const HBasicBlock* context,
                      const HLoopInformation* loop,
                      HBasicBlock* body,
                      InductionInfo* a,
                      InductionInfo* b,
                      DataType::Type type,
                      IfCondition cmp);
  void VisitTripCount(const HBasicBlock* context,
                      const HLoopInformation* loop,
                      InductionInfo* lower_expr,
                      InductionInfo* upper_expr,
                      InductionInfo* stride,
                      int64_t stride_value,
                      DataType::Type type,
                      IfCondition cmp);
  bool IsTaken(const HBasicBlock* context,
               const HLoopInformation* loop,
               InductionInfo* lower_expr,
               InductionInfo* upper_expr,
               IfCondition cmp);
  bool IsFinite(const HBasicBlock* context,
                const HLoopInformation* loop,
                InductionInfo* upper_expr,
                int64_t stride_value,
                DataType::Type type,
                IfCondition cmp);
  bool FitsNarrowerControl(const HBasicBlock* context,
                           const HLoopInformation* loop,
                           InductionInfo* lower_expr,
                           InductionInfo* upper_expr,
                           int64_t stride_value,
                           DataType::Type type,
                           IfCondition cmp);
  bool RewriteBreakLoop(const HBasicBlock* context,
                        const HLoopInformation* loop,
                        HBasicBlock* body,
                        int64_t stride_value,
                        DataType::Type type);

  //
  // Helper methods.
  //

  // Assign and lookup.
  void AssignInfo(const HLoopInformation* loop, HInstruction* instruction, InductionInfo* info);
  InductionInfo* LookupInfo(const HLoopInformation* loop, HInstruction* instruction);
  InductionInfo* CreateConstant(int64_t value, DataType::Type type);
  InductionInfo* CreateSimplifiedInvariant(const HBasicBlock* context,
                                           const HLoopInformation* loop,
                                           InductionOp op,
                                           InductionInfo* a,
                                           InductionInfo* b);
  HInstruction* GetShiftConstant(const HLoopInformation* loop,
                                 HInstruction* instruction,
                                 InductionInfo* initial);
  void AssignCycle(HPhi* phi, ArrayRef<HInstruction* const> scc);
  ArenaSet<HInstruction*>* LookupCycle(HPhi* phi);

  // Constants.
  bool IsExact(const HBasicBlock* context,
               const HLoopInformation* loop,
               InductionInfo* info,
               /*out*/int64_t* value);
  bool IsAtMost(const HBasicBlock* context,
                const HLoopInformation* loop,
                InductionInfo* info,
                /*out*/int64_t* value);
  bool IsAtLeast(const HBasicBlock* context,
                 const HLoopInformation* loop,
                 InductionInfo* info,
                 /*out*/int64_t* value);

  // Helpers.
  static bool IsNarrowingLinear(InductionInfo* info);
  static bool InductionEqual(InductionInfo* info1, InductionInfo* info2);
  static std::string FetchToString(HInstruction* fetch);
  static std::string InductionToString(InductionInfo* info);

  // Returns true if we have a pathological case we don't want to analyze.
  bool IsPathologicalCase();
  // Starting with initial_phi, it calculates how many loop header phis in a row we have. To do
  // this, we count the loop header phi which are used as an input of other loop header phis. It
  // uses `cached_values` to avoid recomputing results.
  void CalculateLoopHeaderPhisInARow(HPhi* initial_phi,
                                     ScopedArenaSafeMap<HPhi*, int>& cached_values,
                                     ScopedArenaAllocator& allocator);

  /**
   * Maintains the results of the analysis as a mapping from loops to a mapping from instructions
   * to the induction information for that instruction in that loop.
   */

  ArenaSafeMap<const HLoopInformation*, ArenaSafeMap<HInstruction*, InductionInfo*>> induction_;

  /**
   * Preserves induction cycle information for each loop-phi.
   */

  ArenaSafeMap<HPhi*, ArenaSet<HInstruction*>> cycles_;

  friend class InductionVarAnalysisTest;
  friend class InductionVarRange;
  friend class InductionVarRangeTest;

  DISALLOW_COPY_AND_ASSIGN(HInductionVarAnalysis);
};

}  // namespace art

#endif  // ART_COMPILER_OPTIMIZING_INDUCTION_VAR_ANALYSIS_H_

Messung V0.5 in Prozent
C=89 H=92 G=90

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© 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.