products/Sources/formale Sprachen/Java/openjdk-20-36_src/src/hotspot/share/opto image not shown  

Quellcode-Bibliothek

© Kompilation durch diese Firma

[Weder Korrektheit noch Funktionsfähigkeit der Software werden zugesichert.]

Datei: subnode.hpp   Sprache: C

/*
 * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */


#include "precompiled.hpp"
#include "opto/ad.hpp"
#include "opto/chaitin.hpp"
#include "opto/compile.hpp"
#include "opto/matcher.hpp"
#include "opto/node.hpp"
#include "opto/regmask.hpp"
#include "utilities/population_count.hpp"
#include "utilities/powerOfTwo.hpp"

//------------------------------dump-------------------------------------------

#ifndef PRODUCT
void OptoReg::dump(int r, outputStream *st) {
  switch (r) {
  case Special: st->print("r---"); break;
  case Bad:     st->print("rBAD"); break;
  default:
    if (r < _last_Mach_Reg) st->print("%s", Matcher::regName[r]);
    else st->print("rS%d",r);
    break;
  }
}
#endif


//=============================================================================
const RegMask RegMask::Empty;

const RegMask RegMask::All(
define BODY(I) -1,
  FORALL_BODY
undef BODY
  0
);

//=============================================================================
bool RegMask::is_vector(uint ireg) {
  return (ireg == Op_VecA || ireg == Op_VecS || ireg == Op_VecD ||
          ireg == Op_VecX || ireg == Op_VecY || ireg == Op_VecZ );
}

int RegMask::num_registers(uint ireg) {
  switch(ireg) {
    case Op_VecZ:
      return SlotsPerVecZ;
    case Op_VecY:
      return SlotsPerVecY;
    case Op_VecX:
      return SlotsPerVecX;
    case Op_VecD:
      return SlotsPerVecD;
    case Op_RegVectMask:
      return SlotsPerRegVectMask;
    case Op_RegD:
    case Op_RegL:
#ifdef _LP64
    case Op_RegP:
#endif
      return 2;
    case Op_VecA:
      assert(Matcher::supports_scalable_vector(), "does not support scalable vector");
      return SlotsPerVecA;
    default:
      // Op_VecS and the rest ideal registers.
      assert(ireg == Op_VecS || !is_vector(ireg), "unexpected, possibly multi-slot register");
      return 1;
  }
}

int RegMask::num_registers(uint ireg, LRG &lrg) {
  int n_regs = num_registers(ireg);

  // assigned is OptoReg which is selected by register allocator
  OptoReg::Name assigned = lrg.reg();
  assert(OptoReg::is_valid(assigned), "should be valid opto register");

  if (lrg.is_scalable() && OptoReg::is_stack(assigned)) {
    n_regs = lrg.scalable_reg_slots();
  }
  return n_regs;
}

static const uintptr_t zero  = uintptr_t(0);  // 0x00..00
static const uintptr_t all   = ~uintptr_t(0);  // 0xFF..FF
static const uintptr_t fives = all/3;        // 0x5555..55

// only indices of power 2 are accessed, so index 3 is only filled in for storage.
static const uintptr_t low_bits[5] = { fives, // 0x5555..55
                                       all/0xF,        // 0x1111..11,
                                       all/0xFF,       // 0x0101..01,
                                       zero,           // 0x0000..00
                                       all/0xFFFF };   // 0x0001..01

// Clear out partial bits; leave only bit pairs
void RegMask::clear_to_pairs() {
  assert(valid_watermarks(), "sanity");
  for (unsigned i = _lwm; i <= _hwm; i++) {
    uintptr_t bits = _RM_UP[i];
    bits &= ((bits & fives) << 1U); // 1 hi-bit set for each pair
    bits |= (bits >> 1U);          // Smear 1 hi-bit into a pair
    _RM_UP[i] = bits;
  }
  assert(is_aligned_pairs(), "mask is not aligned, adjacent pairs");
}

bool RegMask::is_misaligned_pair() const {
  return Size() == 2 && !is_aligned_pairs();
}

bool RegMask::is_aligned_pairs() const {
  // Assert that the register mask contains only bit pairs.
  assert(valid_watermarks(), "sanity");
  for (unsigned i = _lwm; i <= _hwm; i++) {
    uintptr_t bits = _RM_UP[i];
    while (bits) {              // Check bits for pairing
      uintptr_t bit = uintptr_t(1) << find_lowest_bit(bits); // Extract low bit
      // Low bit is not odd means its mis-aligned.
      if ((bit & fives) == 0) return false;
      bits -= bit;              // Remove bit from mask
      // Check for aligned adjacent bit
      if ((bits & (bit << 1U)) == 0) return false;
      bits -= (bit << 1U); // Remove other halve of pair
    }
  }
  return true;
}

// Return TRUE if the mask contains a single bit
bool RegMask::is_bound1() const {
  if (is_AllStack()) return false;

  for (unsigned i = _lwm; i <= _hwm; i++) {
    uintptr_t v = _RM_UP[i];
    if (v != 0) {
      // Only one bit allowed -> v must be a power of two
      if (!is_power_of_2(v)) {
        return false;
      }

      // A single bit was found - check there are no bits in the rest of the mask
      for (i++; i <= _hwm; i++) {
        if (_RM_UP[i] != 0) {
          return false;
        }
      }
      // Done; found a single bit
      return true;
    }
  }
  // No bit found
  return false;
}

// Return TRUE if the mask contains an adjacent pair of bits and no other bits.
bool RegMask::is_bound_pair() const {
  if (is_AllStack()) return false;

  assert(valid_watermarks(), "sanity");
  for (unsigned i = _lwm; i <= _hwm; i++) {
    if (_RM_UP[i] != 0) {               // Found some bits
      unsigned int bit_index = find_lowest_bit(_RM_UP[i]);
      if (bit_index != _WordBitMask) {   // Bit pair stays in same word?
        uintptr_t bit = uintptr_t(1) << bit_index; // Extract lowest bit from mask
        if ((bit | (bit << 1U)) != _RM_UP[i]) {
          return false;            // Require adjacent bit pair and no more bits
        }
      } else {                     // Else its a split-pair case
        assert(is_power_of_2(_RM_UP[i]), "invariant");
        i++;                       // Skip iteration forward
        if (i > _hwm || _RM_UP[i] != 1) {
          return false// Require 1 lo bit in next word
        }
      }

      // A matching pair was found - check there are no bits in the rest of the mask
      for (i++; i <= _hwm; i++) {
        if (_RM_UP[i] != 0) {
          return false;
        }
      }
      // Found a bit pair
      return true;
    }
  }
  // True for the empty mask, too
  return true;
}

// Test for a single adjacent set of ideal register's size.
bool RegMask::is_bound(uint ireg) const {
  if (is_vector(ireg)) {
    if (is_bound_set(num_registers(ireg)))
      return true;
  } else if (is_bound1() || is_bound_pair()) {
    return true;
  }
  return false;
}

// Check that whether given reg number with size is valid
// for current regmask, where reg is the highest number.
bool RegMask::is_valid_reg(OptoReg::Name reg, const int size) const {
  for (int i = 0; i < size; i++) {
    if (!Member(reg - i)) {
      return false;
    }
  }
  return true;
}

// Find the lowest-numbered register set in the mask.  Return the
// HIGHEST register number in the set, or BAD if no sets.
// Works also for size 1.
OptoReg::Name RegMask::find_first_set(LRG &lrg, const int size) const {
  if (lrg.is_scalable() && lrg._is_vector) {
    // For scalable vector register, regmask is SlotsPerVecA bits aligned.
    assert(is_aligned_sets(SlotsPerVecA), "mask is not aligned, adjacent sets");
  } else {
    assert(is_aligned_sets(size), "mask is not aligned, adjacent sets");
  }
  assert(valid_watermarks(), "sanity");
  for (unsigned i = _lwm; i <= _hwm; i++) {
    if (_RM_UP[i]) {                // Found some bits
      // Convert to bit number, return hi bit in pair
      return OptoReg::Name((i<<_LogWordBits) + find_lowest_bit(_RM_UP[i]) + (size - 1));
    }
  }
  return OptoReg::Bad;
}

// Clear out partial bits; leave only aligned adjacent bit pairs
void RegMask::clear_to_sets(const unsigned int size) {
  if (size == 1) return;
  assert(2 <= size && size <= 16, "update low bits table");
  assert(is_power_of_2(size), "sanity");
  assert(valid_watermarks(), "sanity");
  uintptr_t low_bits_mask = low_bits[size >> 2U];
  for (unsigned i = _lwm; i <= _hwm; i++) {
    uintptr_t bits = _RM_UP[i];
    uintptr_t sets = (bits & low_bits_mask);
    for (unsigned j = 1U; j < size; j++) {
      sets = (bits & (sets << 1U)); // filter bits which produce whole sets
    }
    sets |= (sets >> 1U);           // Smear 1 hi-bit into a set
    if (size > 2) {
      sets |= (sets >> 2U);         // Smear 2 hi-bits into a set
      if (size > 4) {
        sets |= (sets >> 4U);       // Smear 4 hi-bits into a set
        if (size > 8) {
          sets |= (sets >> 8U);     // Smear 8 hi-bits into a set
        }
      }
    }
    _RM_UP[i] = sets;
  }
  assert(is_aligned_sets(size), "mask is not aligned, adjacent sets");
}

// Smear out partial bits to aligned adjacent bit sets
void RegMask::smear_to_sets(const unsigned int size) {
  if (size == 1) return;
  assert(2 <= size && size <= 16, "update low bits table");
  assert(is_power_of_2(size), "sanity");
  assert(valid_watermarks(), "sanity");
  uintptr_t low_bits_mask = low_bits[size >> 2U];
  for (unsigned i = _lwm; i <= _hwm; i++) {
    uintptr_t bits = _RM_UP[i];
    uintptr_t sets = 0;
    for (unsigned j = 0; j < size; j++) {
      sets |= (bits & low_bits_mask);  // collect partial bits
      bits  = bits >> 1U;
    }
    sets |= (sets << 1U);           // Smear 1 lo-bit  into a set
    if (size > 2) {
      sets |= (sets << 2U);         // Smear 2 lo-bits into a set
      if (size > 4) {
        sets |= (sets << 4U);       // Smear 4 lo-bits into a set
        if (size > 8) {
          sets |= (sets << 8U);     // Smear 8 lo-bits into a set
        }
      }
    }
    _RM_UP[i] = sets;
  }
  assert(is_aligned_sets(size), "mask is not aligned, adjacent sets");
}

// Assert that the register mask contains only bit sets.
bool RegMask::is_aligned_sets(const unsigned int size) const {
  if (size == 1) return true;
  assert(2 <= size && size <= 16, "update low bits table");
  assert(is_power_of_2(size), "sanity");
  uintptr_t low_bits_mask = low_bits[size >> 2U];
  assert(valid_watermarks(), "sanity");
  for (unsigned i = _lwm; i <= _hwm; i++) {
    uintptr_t bits = _RM_UP[i];
    while (bits) {              // Check bits for pairing
      uintptr_t bit = uintptr_t(1) << find_lowest_bit(bits);
      // Low bit is not odd means its mis-aligned.
      if ((bit & low_bits_mask) == 0) {
        return false;
      }
      // Do extra work since (bit << size) may overflow.
      uintptr_t hi_bit = bit << (size-1); // high bit
      uintptr_t set = hi_bit + ((hi_bit-1) & ~(bit-1));
      // Check for aligned adjacent bits in this set
      if ((bits & set) != set) {
        return false;
      }
      bits -= set;  // Remove this set
    }
  }
  return true;
}

// Return TRUE if the mask contains one adjacent set of bits and no other bits.
// Works also for size 1.
bool RegMask::is_bound_set(const unsigned int size) const {
  if (is_AllStack()) return false;
  assert(1 <= size && size <= 16, "update low bits table");
  assert(valid_watermarks(), "sanity");
  for (unsigned i = _lwm; i <= _hwm; i++) {
    if (_RM_UP[i] != 0) {       // Found some bits
      unsigned bit_index = find_lowest_bit(_RM_UP[i]);
      uintptr_t bit = uintptr_t(1) << bit_index;
      if (bit_index + size <= BitsPerWord) { // Bit set stays in same word?
        uintptr_t hi_bit = bit << (size - 1);
        uintptr_t set = hi_bit + ((hi_bit-1) & ~(bit-1));
        if (set != _RM_UP[i]) {
          return false;         // Require adjacent bit set and no more bits
        }
      } else {                  // Else its a split-set case
        // All bits from bit to highest bit in the word must be set
        if ((all & ~(bit-1)) != _RM_UP[i]) {
          return false;
        }
        i++;                    // Skip iteration forward and check high part
        // The lower bits should be 1 since it is split case.
        uintptr_t set = (bit >> (BitsPerWord - size)) - 1;
        if (i > _hwm || _RM_UP[i] != set) {
          return false// Require expected low bits in next word
        }
      }

      // A matching set found - check there are no bits in the rest of the mask
      for (i++; i <= _hwm; i++) {
        if (_RM_UP[i] != 0) {
          return false;
        }
      }
      // Done - found a bit set
      return true;
    }
  }
  // True for the empty mask, too
  return true;
}

// UP means register only, Register plus stack, or stack only is DOWN
bool RegMask::is_UP() const {
  // Quick common case check for DOWN (any stack slot is legal)
  if (is_AllStack())
    return false;
  // Slower check for any stack bits set (also DOWN)
  if (overlap(Matcher::STACK_ONLY_mask))
    return false;
  // Not DOWN, so must be UP
  return true;
}

// Compute size of register mask in bits
uint RegMask::Size() const {
  uint sum = 0;
  assert(valid_watermarks(), "sanity");
  for (unsigned i = _lwm; i <= _hwm; i++) {
    sum += population_count(_RM_UP[i]);
  }
  return sum;
}

#ifndef PRODUCT
void RegMask::dump(outputStream *st) const {
  st->print("[");

  RegMaskIterator rmi(*this);
  if (rmi.has_next()) {
    OptoReg::Name start = rmi.next();

    OptoReg::dump(start, st);   // Print register
    OptoReg::Name last = start;

    // Now I have printed an initial register.
    // Print adjacent registers as "rX-rZ" instead of "rX,rY,rZ".
    // Begin looping over the remaining registers.
    while (rmi.has_next()) {
      OptoReg::Name reg = rmi.next(); // Get a register

      if (last + 1 == reg) {      // See if they are adjacent
        // Adjacent registers just collect into long runs, no printing.
        last = reg;
      } else {                  // Ending some kind of run
        if (start == last) {    // 1-register run; no special printing
        } else if (start+1 == last) {
          st->print(",");       // 2-register run; print as "rX,rY"
          OptoReg::dump(last, st);
        } else {                // Multi-register run; print as "rX-rZ"
          st->print("-");
          OptoReg::dump(last, st);
        }
        st->print(",");         // Separate start of new run
        start = last = reg;     // Start a new register run
        OptoReg::dump(start, st); // Print register
      } // End of if ending a register run or not
    } // End of while regmask not empty

    if (start == last) {        // 1-register run; no special printing
    } else if (start+1 == last) {
      st->print(",");           // 2-register run; print as "rX,rY"
      OptoReg::dump(last, st);
    } else {                    // Multi-register run; print as "rX-rZ"
      st->print("-");
      OptoReg::dump(last, st);
    }
    if (is_AllStack()) st->print("...");
  }
  st->print("]");
}
#endif

¤ Dauer der Verarbeitung: 0.23 Sekunden  (vorverarbeitet)  ¤





Druckansicht
unsichere Verbindung
Druckansicht
sprechenden Kalenders

Eigene Datei ansehen




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 ist noch experimentell.


Bot Zugriff