8221404: C2: Convert RegMask and IndexSet to use uintptr_t
Reviewed-by: kvn, thartmann
This commit is contained in:
parent
6555996f92
commit
6ae5e5b6b7
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, 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
|
||||
@ -241,7 +241,7 @@ IndexSet::IndexSet (IndexSet *set) {
|
||||
set_block(i, &_empty_block);
|
||||
} else {
|
||||
BitBlock *new_block = alloc_block();
|
||||
memcpy(new_block->words(), block->words(), sizeof(uint32_t) * words_per_block);
|
||||
memcpy(new_block->words(), block->words(), sizeof(uintptr_t) * words_per_block);
|
||||
set_block(i, new_block);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, 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
|
||||
@ -60,9 +60,12 @@ class IndexSet : public ResourceObj {
|
||||
// membership of the element in the set.
|
||||
|
||||
// The lengths of the index bitfields
|
||||
enum { bit_index_length = 5,
|
||||
word_index_length = 3,
|
||||
block_index_length = 8 // not used
|
||||
enum {
|
||||
// Each block consists of 256 bits
|
||||
block_index_length = 8,
|
||||
// Split over 4 or 8 words depending on bitness
|
||||
word_index_length = block_index_length - LogBitsPerWord,
|
||||
bit_index_length = block_index_length - word_index_length,
|
||||
};
|
||||
|
||||
// Derived constants used for manipulating the index bitfields
|
||||
@ -88,7 +91,7 @@ class IndexSet : public ResourceObj {
|
||||
return mask_bits(element >> word_index_offset,word_index_mask);
|
||||
}
|
||||
static uint get_bit_index(uint element) {
|
||||
return mask_bits(element,bit_index_mask);
|
||||
return mask_bits(element, bit_index_mask);
|
||||
}
|
||||
|
||||
//------------------------------ class BitBlock ----------------------------
|
||||
@ -102,17 +105,17 @@ class IndexSet : public ResourceObj {
|
||||
// All of BitBlocks fields and methods are declared private. We limit
|
||||
// access to IndexSet and IndexSetIterator.
|
||||
|
||||
// A BitBlock is composed of some number of 32 bit words. When a BitBlock
|
||||
// A BitBlock is composed of some number of 32- or 64-bit words. When a BitBlock
|
||||
// is not in use by any IndexSet, it is stored on a free list. The next field
|
||||
// is used by IndexSet to mainting this free list.
|
||||
// is used by IndexSet to maintain this free list.
|
||||
|
||||
union {
|
||||
uint32_t _words[words_per_block];
|
||||
uintptr_t _words[words_per_block];
|
||||
BitBlock *_next;
|
||||
} _data;
|
||||
|
||||
// accessors
|
||||
uint32_t* words() { return _data._words; }
|
||||
uintptr_t* words() { return _data._words; }
|
||||
void set_next(BitBlock *next) { _data._next = next; }
|
||||
BitBlock *next() { return _data._next; }
|
||||
|
||||
@ -121,32 +124,32 @@ class IndexSet : public ResourceObj {
|
||||
// not assume that the block index has been masked out.
|
||||
|
||||
void clear() {
|
||||
memset(words(), 0, sizeof(uint32_t) * words_per_block);
|
||||
memset(words(), 0, sizeof(uintptr_t) * words_per_block);
|
||||
}
|
||||
|
||||
bool member(uint element) {
|
||||
uint word_index = IndexSet::get_word_index(element);
|
||||
uint bit_index = IndexSet::get_bit_index(element);
|
||||
uintptr_t bit_index = IndexSet::get_bit_index(element);
|
||||
|
||||
return ((words()[word_index] & (uint32_t)(0x1 << bit_index)) != 0);
|
||||
return ((words()[word_index] & (uintptr_t(1) << bit_index)) != 0);
|
||||
}
|
||||
|
||||
bool insert(uint element) {
|
||||
uint word_index = IndexSet::get_word_index(element);
|
||||
uint bit_index = IndexSet::get_bit_index(element);
|
||||
uintptr_t bit_index = IndexSet::get_bit_index(element);
|
||||
|
||||
uint32_t bit = (0x1 << bit_index);
|
||||
uint32_t before = words()[word_index];
|
||||
uintptr_t bit = uintptr_t(1) << bit_index;
|
||||
uintptr_t before = words()[word_index];
|
||||
words()[word_index] = before | bit;
|
||||
return ((before & bit) != 0);
|
||||
}
|
||||
|
||||
bool remove(uint element) {
|
||||
uint word_index = IndexSet::get_word_index(element);
|
||||
uint bit_index = IndexSet::get_bit_index(element);
|
||||
uintptr_t bit_index = IndexSet::get_bit_index(element);
|
||||
|
||||
uint32_t bit = (0x1 << bit_index);
|
||||
uint32_t before = words()[word_index];
|
||||
uintptr_t bit = uintptr_t(1) << bit_index;
|
||||
uintptr_t before = words()[word_index];
|
||||
words()[word_index] = before & ~bit;
|
||||
return ((before & bit) != 0);
|
||||
}
|
||||
@ -376,7 +379,7 @@ class IndexSetIterator {
|
||||
|
||||
private:
|
||||
// The current word we are inspecting
|
||||
uint32_t _current;
|
||||
uintptr_t _current;
|
||||
|
||||
// What element number are we currently on?
|
||||
uint _value;
|
||||
@ -391,7 +394,7 @@ class IndexSetIterator {
|
||||
uint _max_blocks;
|
||||
|
||||
// A pointer to the contents of the current block
|
||||
uint32_t *_words;
|
||||
uintptr_t* _words;
|
||||
|
||||
// A pointer to the blocks in our set
|
||||
IndexSet::BitBlock **_blocks;
|
||||
@ -447,7 +450,7 @@ class IndexSetIterator {
|
||||
|
||||
// Return the next element of the set.
|
||||
uint next_value() {
|
||||
uint current = _current;
|
||||
uintptr_t current = _current;
|
||||
assert(current != 0, "sanity");
|
||||
uint advance = count_trailing_zeros(current);
|
||||
assert(((current >> advance) & 0x1) == 1, "sanity");
|
||||
|
@ -32,8 +32,6 @@
|
||||
#include "utilities/population_count.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
|
||||
#define RM_SIZE _RM_SIZE /* a constant private to the class RegMask */
|
||||
|
||||
//------------------------------dump-------------------------------------------
|
||||
|
||||
#ifndef PRODUCT
|
||||
@ -65,27 +63,29 @@ bool RegMask::is_vector(uint ireg) {
|
||||
}
|
||||
|
||||
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_RegD:
|
||||
case Op_RegL:
|
||||
switch(ireg) {
|
||||
case Op_VecZ:
|
||||
return SlotsPerVecZ;
|
||||
case Op_VecY:
|
||||
return SlotsPerVecY;
|
||||
case Op_VecX:
|
||||
return SlotsPerVecX;
|
||||
case Op_VecD:
|
||||
return SlotsPerVecD;
|
||||
case Op_RegD:
|
||||
case Op_RegL:
|
||||
#ifdef _LP64
|
||||
case Op_RegP:
|
||||
case Op_RegP:
|
||||
#endif
|
||||
return 2;
|
||||
case Op_VecA:
|
||||
assert(Matcher::supports_scalable_vector(), "does not support scalable vector");
|
||||
return SlotsPerVecA;
|
||||
}
|
||||
// Op_VecS and the rest ideal registers.
|
||||
return 1;
|
||||
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) {
|
||||
@ -101,14 +101,25 @@ int RegMask::num_registers(uint ireg, LRG &lrg) {
|
||||
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 (int i = _lwm; i <= _hwm; i++) {
|
||||
int bits = _A[i];
|
||||
bits &= ((bits & 0x55555555)<<1); // 1 hi-bit set for each pair
|
||||
bits |= (bits>>1); // Smear 1 hi-bit into a pair
|
||||
_A[i] = bits;
|
||||
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");
|
||||
}
|
||||
@ -120,16 +131,16 @@ bool RegMask::is_misaligned_pair() const {
|
||||
bool RegMask::is_aligned_pairs() const {
|
||||
// Assert that the register mask contains only bit pairs.
|
||||
assert(valid_watermarks(), "sanity");
|
||||
for (int i = _lwm; i <= _hwm; i++) {
|
||||
int bits = _A[i];
|
||||
for (unsigned i = _lwm; i <= _hwm; i++) {
|
||||
uintptr_t bits = _RM_UP[i];
|
||||
while (bits) { // Check bits for pairing
|
||||
int bit = bits & -bits; // Extract low bit
|
||||
uintptr_t bit = uintptr_t(1) << find_lowest_bit(bits); // Extract low bit
|
||||
// Low bit is not odd means its mis-aligned.
|
||||
if ((bit & 0x55555555) == 0) return false;
|
||||
if ((bit & fives) == 0) return false;
|
||||
bits -= bit; // Remove bit from mask
|
||||
// Check for aligned adjacent bit
|
||||
if ((bits & (bit<<1)) == 0) return false;
|
||||
bits -= (bit<<1); // Remove other halve of pair
|
||||
if ((bits & (bit << 1U)) == 0) return false;
|
||||
bits -= (bit << 1U); // Remove other halve of pair
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -144,19 +155,19 @@ bool RegMask::is_bound1() const {
|
||||
// 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;
|
||||
int bit = -1; // Set to hold the one bit allowed
|
||||
uintptr_t bit = all; // Set to hold the one bit allowed
|
||||
assert(valid_watermarks(), "sanity");
|
||||
for (int i = _lwm; i <= _hwm; i++) {
|
||||
if (_A[i]) { // Found some bits
|
||||
if (bit != -1) return false; // Already had bits, so fail
|
||||
bit = _A[i] & -(_A[i]); // Extract 1 bit from mask
|
||||
if ((bit << 1) != 0) { // Bit pair stays in same word?
|
||||
if ((bit | (bit<<1)) != _A[i])
|
||||
for (unsigned i = _lwm; i <= _hwm; i++) {
|
||||
if (_RM_UP[i]) { // Found some bits
|
||||
if (bit != all) return false; // Already had bits, so fail
|
||||
bit = uintptr_t(1) << find_lowest_bit(_RM_UP[i]); // Extract lowest bit from mask
|
||||
if ((bit << 1U) != 0) { // Bit pair stays in same word?
|
||||
if ((bit | (bit << 1U)) != _RM_UP[i])
|
||||
return false; // Require adjacent bit pair and no more bits
|
||||
} else { // Else its a split-pair case
|
||||
if(bit != _A[i]) return false; // Found many bits, so fail
|
||||
if (bit != _RM_UP[i]) return false; // Found many bits, so fail
|
||||
i++; // Skip iteration forward
|
||||
if (i > _hwm || _A[i] != 1)
|
||||
if (i > _hwm || _RM_UP[i] != 1)
|
||||
return false; // Require 1 lo bit in next word
|
||||
}
|
||||
}
|
||||
@ -186,9 +197,6 @@ bool RegMask::is_valid_reg(OptoReg::Name reg, const int size) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
// only indicies of power 2 are accessed, so index 3 is only filled in for storage.
|
||||
static int low_bits[5] = { 0x55555555, 0x11111111, 0x01010101, 0x00000000, 0x00010001 };
|
||||
|
||||
// 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.
|
||||
@ -200,90 +208,90 @@ OptoReg::Name RegMask::find_first_set(LRG &lrg, const int size) const {
|
||||
assert(is_aligned_sets(size), "mask is not aligned, adjacent sets");
|
||||
}
|
||||
assert(valid_watermarks(), "sanity");
|
||||
for (int i = _lwm; i <= _hwm; i++) {
|
||||
if (_A[i]) { // Found some bits
|
||||
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(_A[i]) + (size - 1));
|
||||
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 int size) {
|
||||
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");
|
||||
int low_bits_mask = low_bits[size>>2];
|
||||
for (int i = _lwm; i <= _hwm; i++) {
|
||||
int bits = _A[i];
|
||||
int sets = (bits & low_bits_mask);
|
||||
for (int j = 1; j < size; j++) {
|
||||
sets = (bits & (sets<<1)); // filter bits which produce whole sets
|
||||
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>>1); // Smear 1 hi-bit into a set
|
||||
sets |= (sets >> 1U); // Smear 1 hi-bit into a set
|
||||
if (size > 2) {
|
||||
sets |= (sets>>2); // Smear 2 hi-bits into a set
|
||||
sets |= (sets >> 2U); // Smear 2 hi-bits into a set
|
||||
if (size > 4) {
|
||||
sets |= (sets>>4); // Smear 4 hi-bits into a set
|
||||
sets |= (sets >> 4U); // Smear 4 hi-bits into a set
|
||||
if (size > 8) {
|
||||
sets |= (sets>>8); // Smear 8 hi-bits into a set
|
||||
sets |= (sets >> 8U); // Smear 8 hi-bits into a set
|
||||
}
|
||||
}
|
||||
}
|
||||
_A[i] = sets;
|
||||
_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 int size) {
|
||||
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");
|
||||
int low_bits_mask = low_bits[size>>2];
|
||||
for (int i = _lwm; i <= _hwm; i++) {
|
||||
int bits = _A[i];
|
||||
int sets = 0;
|
||||
for (int j = 0; j < size; j++) {
|
||||
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>>1;
|
||||
bits = bits >> 1U;
|
||||
}
|
||||
sets |= (sets<<1); // Smear 1 lo-bit into a set
|
||||
sets |= (sets << 1U); // Smear 1 lo-bit into a set
|
||||
if (size > 2) {
|
||||
sets |= (sets<<2); // Smear 2 lo-bits into a set
|
||||
sets |= (sets << 2U); // Smear 2 lo-bits into a set
|
||||
if (size > 4) {
|
||||
sets |= (sets<<4); // Smear 4 lo-bits into a set
|
||||
sets |= (sets << 4U); // Smear 4 lo-bits into a set
|
||||
if (size > 8) {
|
||||
sets |= (sets<<8); // Smear 8 lo-bits into a set
|
||||
sets |= (sets << 8U); // Smear 8 lo-bits into a set
|
||||
}
|
||||
}
|
||||
}
|
||||
_A[i] = sets;
|
||||
_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 int size) const {
|
||||
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");
|
||||
int low_bits_mask = low_bits[size>>2];
|
||||
uintptr_t low_bits_mask = low_bits[size >> 2U];
|
||||
assert(valid_watermarks(), "sanity");
|
||||
for (int i = _lwm; i <= _hwm; i++) {
|
||||
int bits = _A[i];
|
||||
for (unsigned i = _lwm; i <= _hwm; i++) {
|
||||
uintptr_t bits = _RM_UP[i];
|
||||
while (bits) { // Check bits for pairing
|
||||
int bit = bits & -bits; // Extract low bit
|
||||
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.
|
||||
int hi_bit = bit << (size-1); // high bit
|
||||
int set = hi_bit + ((hi_bit-1) & ~(bit-1));
|
||||
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;
|
||||
@ -296,32 +304,29 @@ bool RegMask::is_aligned_sets(const int size) const {
|
||||
|
||||
// Return TRUE if the mask contains one adjacent set of bits and no other bits.
|
||||
// Works also for size 1.
|
||||
int RegMask::is_bound_set(const int size) const {
|
||||
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");
|
||||
int bit = -1; // Set to hold the one bit allowed
|
||||
for (int i = _lwm; i <= _hwm; i++) {
|
||||
if (_A[i] ) { // Found some bits
|
||||
if (bit != -1)
|
||||
return false; // Already had bits, so fail
|
||||
bit = _A[i] & -_A[i]; // Extract low bit from mask
|
||||
int hi_bit = bit << (size-1); // high bit
|
||||
uintptr_t bit = all; // Set to hold the one bit allowed
|
||||
for (unsigned i = _lwm; i <= _hwm; i++) {
|
||||
if (_RM_UP[i] ) { // Found some bits
|
||||
if (bit != all)
|
||||
return false; // Already had bits, so fail
|
||||
unsigned bit_index = find_lowest_bit(_RM_UP[i]);
|
||||
bit = uintptr_t(1) << bit_index;
|
||||
uintptr_t hi_bit = bit << (size - 1); // high bit
|
||||
if (hi_bit != 0) { // Bit set stays in same word?
|
||||
int set = hi_bit + ((hi_bit-1) & ~(bit-1));
|
||||
if (set != _A[i])
|
||||
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
|
||||
if (((-1) & ~(bit-1)) != _A[i])
|
||||
if ((all & ~(bit-1)) != _RM_UP[i])
|
||||
return false; // Found many bits, so fail
|
||||
i++; // Skip iteration forward and check high part
|
||||
// The lower (32-size) bits should be 0 since it is split case.
|
||||
int clear_bit_size = 32-size;
|
||||
int shift_back_size = 32-clear_bit_size;
|
||||
int set = bit>>clear_bit_size;
|
||||
set = set & -set; // Remove sign extension.
|
||||
set = (((set << size) - 1) >> shift_back_size);
|
||||
if (i > _hwm || _A[i] != set)
|
||||
// The lower (BitsPerWord - size) bits should be 1 since it is split case.
|
||||
uintptr_t set = (bit >> (BitsPerWord - bit_index)) - 1;
|
||||
if (i > _hwm || _RM_UP[i] != set)
|
||||
return false; // Require expected low bits in next word
|
||||
}
|
||||
}
|
||||
@ -346,8 +351,8 @@ bool RegMask::is_UP() const {
|
||||
uint RegMask::Size() const {
|
||||
uint sum = 0;
|
||||
assert(valid_watermarks(), "sanity");
|
||||
for (int i = _lwm; i <= _hwm; i++) {
|
||||
sum += population_count((unsigned)_A[i]);
|
||||
for (unsigned i = _lwm; i <= _hwm; i++) {
|
||||
sum += population_count(_RM_UP[i]);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
@ -34,12 +34,12 @@ class LRG;
|
||||
|
||||
//-------------Non-zero bit search methods used by RegMask---------------------
|
||||
// Find lowest 1, undefined if empty/0
|
||||
static int find_lowest_bit(uint32_t mask) {
|
||||
static unsigned int find_lowest_bit(uintptr_t mask) {
|
||||
return count_trailing_zeros(mask);
|
||||
}
|
||||
// Find highest 1, undefined if empty/0
|
||||
static int find_highest_bit(uint32_t mask) {
|
||||
return count_leading_zeros(mask) ^ 31;
|
||||
static unsigned int find_highest_bit(uintptr_t mask) {
|
||||
return count_leading_zeros(mask) ^ (BitsPerWord - 1U);
|
||||
}
|
||||
|
||||
//------------------------------RegMask----------------------------------------
|
||||
@ -48,37 +48,39 @@ static int find_highest_bit(uint32_t mask) {
|
||||
// just a collection of Register numbers.
|
||||
|
||||
// The ADLC defines 2 macros, RM_SIZE and FORALL_BODY.
|
||||
// RM_SIZE is the size of a register mask in words.
|
||||
// RM_SIZE is the size of a register mask in 32-bit words.
|
||||
// FORALL_BODY replicates a BODY macro once per word in the register mask.
|
||||
// The usage is somewhat clumsy and limited to the regmask.[h,c]pp files.
|
||||
// However, it means the ADLC can redefine the unroll macro and all loops
|
||||
// over register masks will be unrolled by the correct amount.
|
||||
|
||||
class RegMask {
|
||||
|
||||
enum {
|
||||
_WordBits = BitsPerWord,
|
||||
_LogWordBits = LogBitsPerWord,
|
||||
_RM_SIZE = LP64_ONLY(align_up(RM_SIZE, 2) >> 1) NOT_LP64(RM_SIZE)
|
||||
};
|
||||
|
||||
union {
|
||||
double _dummy_force_double_alignment[RM_SIZE>>1];
|
||||
// Array of Register Mask bits. This array is large enough to cover
|
||||
// all the machine registers and all parameters that need to be passed
|
||||
// on the stack (stack registers) up to some interesting limit. Methods
|
||||
// that need more parameters will NOT be compiled. On Intel, the limit
|
||||
// is something like 90+ parameters.
|
||||
int _A[RM_SIZE];
|
||||
int _RM_I[RM_SIZE];
|
||||
uintptr_t _RM_UP[_RM_SIZE];
|
||||
};
|
||||
|
||||
// The low and high water marks represents the lowest and highest word
|
||||
// that might contain set register mask bits, respectively. We guarantee
|
||||
// that there are no bits in words outside this range, but any word at
|
||||
// and between the two marks can still be 0.
|
||||
int _lwm;
|
||||
int _hwm;
|
||||
|
||||
enum {
|
||||
_WordBits = BitsPerInt,
|
||||
_LogWordBits = LogBitsPerInt,
|
||||
_RM_SIZE = RM_SIZE // local constant, imported, then hidden by #undef
|
||||
};
|
||||
unsigned int _lwm;
|
||||
unsigned int _hwm;
|
||||
|
||||
public:
|
||||
enum { CHUNK_SIZE = RM_SIZE*_WordBits };
|
||||
enum { CHUNK_SIZE = RM_SIZE*BitsPerInt };
|
||||
|
||||
// SlotsPerLong is 2, since slots are 32 bits and longs are 64 bits.
|
||||
// Also, consider the maximum alignment size for a normally allocated
|
||||
@ -108,13 +110,13 @@ class RegMask {
|
||||
FORALL_BODY
|
||||
# undef BODY
|
||||
int dummy = 0) {
|
||||
# define BODY(I) _A[I] = a##I;
|
||||
# define BODY(I) _RM_I[I] = a##I;
|
||||
FORALL_BODY
|
||||
# undef BODY
|
||||
_lwm = 0;
|
||||
_hwm = RM_SIZE - 1;
|
||||
while (_hwm > 0 && _A[_hwm] == 0) _hwm--;
|
||||
while ((_lwm < _hwm) && _A[_lwm] == 0) _lwm++;
|
||||
_hwm = _RM_SIZE - 1;
|
||||
while (_hwm > 0 && _RM_UP[_hwm] == 0) _hwm--;
|
||||
while ((_lwm < _hwm) && _RM_UP[_lwm] == 0) _lwm++;
|
||||
assert(valid_watermarks(), "post-condition");
|
||||
}
|
||||
|
||||
@ -122,48 +124,41 @@ class RegMask {
|
||||
RegMask(RegMask *rm) {
|
||||
_hwm = rm->_hwm;
|
||||
_lwm = rm->_lwm;
|
||||
for (int i = 0; i < RM_SIZE; i++) {
|
||||
_A[i] = rm->_A[i];
|
||||
for (unsigned i = 0; i < _RM_SIZE; i++) {
|
||||
_RM_UP[i] = rm->_RM_UP[i];
|
||||
}
|
||||
assert(valid_watermarks(), "post-condition");
|
||||
}
|
||||
|
||||
// Construct an empty mask
|
||||
RegMask() {
|
||||
Clear();
|
||||
}
|
||||
RegMask() : _RM_UP(), _lwm(_RM_SIZE - 1), _hwm(0) {}
|
||||
|
||||
// Construct a mask with a single bit
|
||||
RegMask(OptoReg::Name reg) {
|
||||
Clear();
|
||||
RegMask(OptoReg::Name reg) : RegMask() {
|
||||
Insert(reg);
|
||||
}
|
||||
|
||||
// Check for register being in mask
|
||||
int Member(OptoReg::Name reg) const {
|
||||
bool Member(OptoReg::Name reg) const {
|
||||
assert(reg < CHUNK_SIZE, "");
|
||||
return _A[reg>>_LogWordBits] & (1<<(reg&(_WordBits-1)));
|
||||
|
||||
unsigned r = (unsigned)reg;
|
||||
return _RM_UP[r >> _LogWordBits] & (uintptr_t(1) <<(r & (_WordBits - 1U)));
|
||||
}
|
||||
|
||||
// The last bit in the register mask indicates that the mask should repeat
|
||||
// indefinitely with ONE bits. Returns TRUE if mask is infinite or
|
||||
// unbounded in size. Returns FALSE if mask is finite size.
|
||||
int is_AllStack() const { return _A[RM_SIZE-1] >> (_WordBits-1); }
|
||||
bool is_AllStack() const { return _RM_UP[_RM_SIZE - 1U] >> (_WordBits - 1U); }
|
||||
|
||||
// Work around an -xO3 optimization problme in WS6U1. The old way:
|
||||
// void set_AllStack() { _A[RM_SIZE-1] |= (1<<(_WordBits-1)); }
|
||||
// will cause _A[RM_SIZE-1] to be clobbered, not updated when set_AllStack()
|
||||
// follows an Insert() loop, like the one found in init_spill_mask(). Using
|
||||
// Insert() instead works because the index into _A in computed instead of
|
||||
// constant. See bug 4665841.
|
||||
void set_AllStack() { Insert(OptoReg::Name(CHUNK_SIZE-1)); }
|
||||
|
||||
// Test for being a not-empty mask.
|
||||
int is_NotEmpty() const {
|
||||
bool is_NotEmpty() const {
|
||||
assert(valid_watermarks(), "sanity");
|
||||
int tmp = 0;
|
||||
for (int i = _lwm; i <= _hwm; i++) {
|
||||
tmp |= _A[i];
|
||||
uintptr_t tmp = 0;
|
||||
for (unsigned i = _lwm; i <= _hwm; i++) {
|
||||
tmp |= _RM_UP[i];
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
@ -171,8 +166,8 @@ class RegMask {
|
||||
// Find lowest-numbered register from mask, or BAD if mask is empty.
|
||||
OptoReg::Name find_first_elem() const {
|
||||
assert(valid_watermarks(), "sanity");
|
||||
for (int i = _lwm; i <= _hwm; i++) {
|
||||
int bits = _A[i];
|
||||
for (unsigned i = _lwm; i <= _hwm; i++) {
|
||||
uintptr_t bits = _RM_UP[i];
|
||||
if (bits) {
|
||||
return OptoReg::Name((i<<_LogWordBits) + find_lowest_bit(bits));
|
||||
}
|
||||
@ -183,8 +178,10 @@ class RegMask {
|
||||
// Get highest-numbered register from mask, or BAD if mask is empty.
|
||||
OptoReg::Name find_last_elem() const {
|
||||
assert(valid_watermarks(), "sanity");
|
||||
for (int i = _hwm; i >= _lwm; i--) {
|
||||
int bits = _A[i];
|
||||
// Careful not to overflow if _lwm == 0
|
||||
unsigned i = _hwm + 1;
|
||||
while (i > _lwm) {
|
||||
uintptr_t bits = _RM_UP[--i];
|
||||
if (bits) {
|
||||
return OptoReg::Name((i<<_LogWordBits) + find_highest_bit(bits));
|
||||
}
|
||||
@ -199,13 +196,13 @@ class RegMask {
|
||||
// Verify watermarks are sane, i.e., within bounds and that no
|
||||
// register words below or above the watermarks have bits set.
|
||||
bool valid_watermarks() const {
|
||||
assert(_hwm >= 0 && _hwm < RM_SIZE, "_hwm out of range: %d", _hwm);
|
||||
assert(_lwm >= 0 && _lwm < RM_SIZE, "_lwm out of range: %d", _lwm);
|
||||
for (int i = 0; i < _lwm; i++) {
|
||||
assert(_A[i] == 0, "_lwm too high: %d regs at: %d", _lwm, i);
|
||||
assert(_hwm < _RM_SIZE, "_hwm out of range: %d", _hwm);
|
||||
assert(_lwm < _RM_SIZE, "_lwm out of range: %d", _lwm);
|
||||
for (unsigned i = 0; i < _lwm; i++) {
|
||||
assert(_RM_UP[i] == 0, "_lwm too high: %d regs at: %d", _lwm, i);
|
||||
}
|
||||
for (int i = _hwm + 1; i < RM_SIZE; i++) {
|
||||
assert(_A[i] == 0, "_hwm too low: %d regs at: %d", _hwm, i);
|
||||
for (unsigned i = _hwm + 1; i < _RM_SIZE; i++) {
|
||||
assert(_RM_UP[i] == 0, "_hwm too low: %d regs at: %d", _hwm, i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -233,27 +230,27 @@ class RegMask {
|
||||
OptoReg::Name find_first_set(LRG &lrg, const int size) const;
|
||||
|
||||
// Clear out partial bits; leave only aligned adjacent bit sets of size.
|
||||
void clear_to_sets(const int size);
|
||||
void clear_to_sets(const unsigned int size);
|
||||
// Smear out partial bits to aligned adjacent bit sets.
|
||||
void smear_to_sets(const int size);
|
||||
void smear_to_sets(const unsigned int size);
|
||||
// Test that the mask contains only aligned adjacent bit sets
|
||||
bool is_aligned_sets(const int size) const;
|
||||
bool is_aligned_sets(const unsigned int size) const;
|
||||
|
||||
// Test for a single adjacent set
|
||||
int is_bound_set(const int size) const;
|
||||
bool is_bound_set(const unsigned int size) const;
|
||||
|
||||
static bool is_vector(uint ireg);
|
||||
static int num_registers(uint ireg);
|
||||
static int num_registers(uint ireg, LRG &lrg);
|
||||
|
||||
// Fast overlap test. Non-zero if any registers in common.
|
||||
int overlap(const RegMask &rm) const {
|
||||
bool overlap(const RegMask &rm) const {
|
||||
assert(valid_watermarks() && rm.valid_watermarks(), "sanity");
|
||||
int hwm = MIN2(_hwm, rm._hwm);
|
||||
int lwm = MAX2(_lwm, rm._lwm);
|
||||
int result = 0;
|
||||
for (int i = lwm; i <= hwm; i++) {
|
||||
result |= _A[i] & rm._A[i];
|
||||
unsigned hwm = MIN2(_hwm, rm._hwm);
|
||||
unsigned lwm = MAX2(_lwm, rm._lwm);
|
||||
uintptr_t result = 0;
|
||||
for (unsigned i = lwm; i <= hwm; i++) {
|
||||
result |= _RM_UP[i] & rm._RM_UP[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -264,35 +261,39 @@ class RegMask {
|
||||
|
||||
// Clear a register mask
|
||||
void Clear() {
|
||||
_lwm = RM_SIZE - 1;
|
||||
_lwm = _RM_SIZE - 1;
|
||||
_hwm = 0;
|
||||
memset(_A, 0, sizeof(int)*RM_SIZE);
|
||||
memset(_RM_UP, 0, sizeof(uintptr_t)*_RM_SIZE);
|
||||
assert(valid_watermarks(), "sanity");
|
||||
}
|
||||
|
||||
// Fill a register mask with 1's
|
||||
void Set_All() {
|
||||
_lwm = 0;
|
||||
_hwm = RM_SIZE - 1;
|
||||
memset(_A, 0xFF, sizeof(int)*RM_SIZE);
|
||||
_hwm = _RM_SIZE - 1;
|
||||
memset(_RM_UP, 0xFF, sizeof(uintptr_t)*_RM_SIZE);
|
||||
assert(valid_watermarks(), "sanity");
|
||||
}
|
||||
|
||||
// Insert register into mask
|
||||
void Insert(OptoReg::Name reg) {
|
||||
assert(reg != OptoReg::Bad, "sanity");
|
||||
assert(reg != OptoReg::Special, "sanity");
|
||||
assert(reg < CHUNK_SIZE, "sanity");
|
||||
assert(valid_watermarks(), "pre-condition");
|
||||
int index = reg>>_LogWordBits;
|
||||
unsigned r = (unsigned)reg;
|
||||
unsigned index = r >> _LogWordBits;
|
||||
if (index > _hwm) _hwm = index;
|
||||
if (index < _lwm) _lwm = index;
|
||||
_A[index] |= (1<<(reg&(_WordBits-1)));
|
||||
_RM_UP[index] |= (uintptr_t(1) << (r & (_WordBits - 1U)));
|
||||
assert(valid_watermarks(), "post-condition");
|
||||
}
|
||||
|
||||
// Remove register from mask
|
||||
void Remove(OptoReg::Name reg) {
|
||||
assert(reg < CHUNK_SIZE, "");
|
||||
_A[reg>>_LogWordBits] &= ~(1<<(reg&(_WordBits-1)));
|
||||
unsigned r = (unsigned)reg;
|
||||
_RM_UP[r >> _LogWordBits] &= ~(uintptr_t(1) << (r & (_WordBits-1U)));
|
||||
}
|
||||
|
||||
// OR 'rm' into 'this'
|
||||
@ -301,8 +302,8 @@ class RegMask {
|
||||
// OR widens the live range
|
||||
if (_lwm > rm._lwm) _lwm = rm._lwm;
|
||||
if (_hwm < rm._hwm) _hwm = rm._hwm;
|
||||
for (int i = _lwm; i <= _hwm; i++) {
|
||||
_A[i] |= rm._A[i];
|
||||
for (unsigned i = _lwm; i <= _hwm; i++) {
|
||||
_RM_UP[i] |= rm._RM_UP[i];
|
||||
}
|
||||
assert(valid_watermarks(), "sanity");
|
||||
}
|
||||
@ -312,8 +313,8 @@ class RegMask {
|
||||
assert(valid_watermarks() && rm.valid_watermarks(), "sanity");
|
||||
// Do not evaluate words outside the current watermark range, as they are
|
||||
// already zero and an &= would not change that
|
||||
for (int i = _lwm; i <= _hwm; i++) {
|
||||
_A[i] &= rm._A[i];
|
||||
for (unsigned i = _lwm; i <= _hwm; i++) {
|
||||
_RM_UP[i] &= rm._RM_UP[i];
|
||||
}
|
||||
// Narrow the watermarks if &rm spans a narrower range.
|
||||
// Update after to ensure non-overlapping words are zeroed out.
|
||||
@ -324,10 +325,10 @@ class RegMask {
|
||||
// Subtract 'rm' from 'this'
|
||||
void SUBTRACT(const RegMask &rm) {
|
||||
assert(valid_watermarks() && rm.valid_watermarks(), "sanity");
|
||||
int hwm = MIN2(_hwm, rm._hwm);
|
||||
int lwm = MAX2(_lwm, rm._lwm);
|
||||
for (int i = lwm; i <= hwm; i++) {
|
||||
_A[i] &= ~rm._A[i];
|
||||
unsigned hwm = MIN2(_hwm, rm._hwm);
|
||||
unsigned lwm = MAX2(_lwm, rm._lwm);
|
||||
for (unsigned i = lwm; i <= hwm; i++) {
|
||||
_RM_UP[i] &= ~rm._RM_UP[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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.
|
||||
*/
|
||||
|
||||
package org.openjdk.bench.vm.compiler.overhead;
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Param;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.Setup;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* The purpose of these microbenchmarks is to use RepeatCompilation
|
||||
* to produce a benchmark that focuses on the overhead of various JIT
|
||||
* compilations themselves.
|
||||
*/
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
@Fork(value = 10, warmups = 1)
|
||||
public class SimpleRepeatCompilation {
|
||||
|
||||
public static final String MIXHASH_METHOD
|
||||
= "-XX:CompileCommand=option,org/openjdk/bench/vm/compiler/overhead/SimpleRepeatCompilation.mixHashCode,intx,RepeatCompilation,500";
|
||||
|
||||
@Benchmark
|
||||
@Fork(jvmArgsAppend={"-Xbatch", MIXHASH_METHOD})
|
||||
public int mixHashCode_repeat() {
|
||||
return loop_hashCode();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Fork(jvmArgsAppend={"-Xbatch", "-XX:-TieredCompilation", MIXHASH_METHOD})
|
||||
public int mixHashCode_repeat_c2() {
|
||||
return loop_hashCode();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Fork(jvmArgsAppend={"-Xbatch", "-XX:TieredStopAtLevel=1", MIXHASH_METHOD})
|
||||
public int mixHashCode_repeat_c1() {
|
||||
return loop_hashCode();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Fork(jvmArgsAppend={"-Xbatch"})
|
||||
public int mixHashCode_baseline() {
|
||||
return loop_hashCode();
|
||||
}
|
||||
|
||||
public int loop_hashCode() {
|
||||
int value = 0;
|
||||
for (int i = 0; i < 1_000_000; i++) {
|
||||
value += mixHashCode("simple_string");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public int mixHashCode(String value) {
|
||||
int h = value.hashCode();
|
||||
for (int i = 0; i < value.length(); i++) {
|
||||
h = value.charAt(i) ^ h;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
public static final String TRIVIAL_MATH_METHOD
|
||||
= "-XX:CompileCommand=option,org/openjdk/bench/vm/compiler/overhead/SimpleRepeatCompilation.trivialMath,intx,RepeatCompilation,2000";
|
||||
|
||||
@Benchmark
|
||||
@Fork(jvmArgsAppend={"-Xbatch",TRIVIAL_MATH_METHOD})
|
||||
public int trivialMath_repeat() {
|
||||
return loop_trivialMath();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Fork(jvmArgsAppend={"-Xbatch", "-XX:-TieredCompilation", TRIVIAL_MATH_METHOD})
|
||||
public int trivialMath_repeat_c2() {
|
||||
return loop_trivialMath();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Fork(jvmArgsAppend={"-Xbatch", "-XX:TieredStopAtLevel=1", TRIVIAL_MATH_METHOD})
|
||||
public int trivialMath_repeat_c1() {
|
||||
return loop_trivialMath();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Fork(jvmArgsAppend={"-Xbatch"})
|
||||
public int trivialMath_baseline() {
|
||||
return loop_trivialMath();
|
||||
}
|
||||
|
||||
public int loop_trivialMath() {
|
||||
int value = 0;
|
||||
for (int i = 0; i < 1_000_000; i++) {
|
||||
value += trivialMath(i, i - 1);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public int trivialMath(int a, int b) {
|
||||
return a * b + a;
|
||||
}
|
||||
|
||||
|
||||
public static final String LARGE_METHOD
|
||||
= "-XX:CompileCommand=option,org/openjdk/bench/vm/compiler/overhead/SimpleRepeatCompilation.largeMethod,intx,RepeatCompilation,100";
|
||||
|
||||
@Benchmark
|
||||
@Fork(jvmArgsAppend={"-Xbatch",LARGE_METHOD})
|
||||
public int largeMethod_repeat() {
|
||||
return loop_largeMethod();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Fork(jvmArgsAppend={"-Xbatch", "-XX:-TieredCompilation", LARGE_METHOD})
|
||||
public int largeMethod_repeat_c2() {
|
||||
return loop_largeMethod();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Fork(jvmArgsAppend={"-Xbatch", "-XX:TieredStopAtLevel=1", LARGE_METHOD})
|
||||
public int largeMethod_repeat_c1() {
|
||||
return loop_largeMethod();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Fork(jvmArgsAppend={"-Xbatch"})
|
||||
public int largeMethod_baseline() {
|
||||
return loop_largeMethod();
|
||||
}
|
||||
|
||||
public int loop_largeMethod() {
|
||||
int value = 0;
|
||||
for (int i = 0; i < 50_000; i++) {
|
||||
value += largeMethod(i, i - 1);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// Meaningless but largish method with plenty of locals
|
||||
// to put more stress on register allocation
|
||||
public int largeMethod(int a, int b) {
|
||||
int c = b + 17;
|
||||
int d = a + b + 6;
|
||||
int e = c + d + 99;
|
||||
int f = d + e + 919;
|
||||
long val = 0;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
for (int k = 0; k < 2; k++) {
|
||||
a -= b;
|
||||
b += c;
|
||||
c -= d;
|
||||
d += e;
|
||||
e -= a;
|
||||
val = a - b + c - d + e - f;
|
||||
}
|
||||
}
|
||||
}
|
||||
int g = b;
|
||||
int h = a;
|
||||
int l = c;
|
||||
int m = d;
|
||||
int n = d;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
for (int k = 0; k < 2; k++) {
|
||||
g += b;
|
||||
h -= c;
|
||||
l += d;
|
||||
m -= e;
|
||||
e += a;
|
||||
val = g + h + l + m + n;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
for (int k = 0; k < 2; k++) {
|
||||
a -= b;
|
||||
b += c;
|
||||
c -= d;
|
||||
d += e;
|
||||
e -= a;
|
||||
val = a - b - c - d - e - f;
|
||||
}
|
||||
}
|
||||
}
|
||||
int o = b;
|
||||
int p = a;
|
||||
int q = c;
|
||||
int r = d;
|
||||
int s = d;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
for (int k = 0; k < 2; k++) {
|
||||
o += b;
|
||||
p += c;
|
||||
q += d;
|
||||
r += e;
|
||||
s += a;
|
||||
val = o + p + q + r + s;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
for (int k = 0; k < 2; k++) {
|
||||
g += b;
|
||||
h -= c;
|
||||
l += d;
|
||||
m -= e;
|
||||
e += a;
|
||||
val = g + h + l + m + n;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (int)(val ^ (val >> 32L));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user