/******************************************************************************* * * (c) Copyright IBM Corp. 2000, 2016 * * This program and the accompanying materials are made available * under the terms of the Eclipse Public License v1.0 and * Apache License v2.0 which accompanies this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * Contributors: * Multiple authors (IBM Corp.) - initial implementation and documentation ******************************************************************************/ #ifndef BITMANIP_H #define BITMANIP_H #define IN_BITMANIP_H #include <algorithm> // for std::max #include <limits.h> // for INT_MIN, LONG_MIN #include <stdint.h> // for int32_t, int64_t, uint32_t, etc #include <stdlib.h> // for abs, labs #include "il/DataTypes.hpp" // for CONSTANT64, TR::getMaxSignedPrecision<TR::Int64>(), etc #include "infra/Assert.hpp" // for TR_ASSERT #if defined(TR_TARGET_X86) && defined(WIN32) #define abs64 _abs64 #else #define abs64 labs #endif // For getting at different parts of a 32 bit integer class intParts { public: intParts(int32_t x) { intVal = x; } intParts() { intVal = 0; } int32_t getValue() { return intVal; } int32_t setValue(int32_t value) { return intVal=value; } int32_t getHighBits() { return (uint32_t)intVal >> 16; } int32_t getLowBits() { return (uint32_t)intVal & 0xffff; } int32_t getLowSign() { return ((uint32_t)intVal >> 15) & 0x1; } int32_t getHighSign() { return (uint32_t)intVal >> 31; } int32_t getByte3() { return (uint32_t)intVal >> 24; } int32_t getByte2() { return ((uint32_t)intVal >> 16) & 0xff; } int32_t getByte1() { return ((uint32_t)intVal >> 8) & 0xff; } int32_t getByte0() { return (uint32_t)intVal & 0xff; } private: int32_t intVal; }; // Returns true iff all the 1-bits of mask are contiguous // in the sense of "rlinm", e.g. of one of the forms // 00...011...100...0 or 11...100...011...1, (or if mask = 0) static inline bool contiguousBits(int32_t lmask) { int32_t amask; // mask as a signed value so the shifts will be algebraic amask = lmask; lmask = lmask^(amask>>31); // 1's-complement if negative. lmask = ((lmask|(lmask-1))+1)&lmask; // Turn off rightmost contiguous // string of 1's; result is 0 iff // orig. mask was in desired form. amask = lmask; lmask = abs(amask)-1; return (lmask>>31) != 0; // Map 0 --> '1'b, else --> '0'b } static inline bool contiguousBits(uint32_t lmask) { return contiguousBits((int32_t) lmask); } static inline bool contiguousBits(int64_t lmask) { int64_t amask; // mask as a signed value so the shifts will be algebraic amask = lmask; lmask = lmask^(amask>>63); // 1's-complement if negative. lmask = ((lmask|(lmask-1))+1)&lmask; // Turn off rightmost contiguous // string of 1's; result is 0 iff // orig. mask was in desired form. amask = lmask; lmask = abs64(amask)-1; return (lmask>>63) != 0; // Map 0 --> '1'b, else --> '0'b } static inline bool contiguousBits(uint64_t lmask) { return contiguousBits((int64_t) lmask); } #if defined(TR_HOST_POWER) && (defined(__IBMC__) || defined(__IBMCPP__) || defined(__ibmxl__)) #include <builtins.h> // Return a count 0..32 of leading zeroes in the given word static inline int32_t leadingZeroes (int32_t inputWord) { return __cntlz4 (inputWord); } #ifdef TR_HOST_64BIT // Return a count 0..64 of leading zeroes in the given doubleword static inline int32_t leadingZeroes (int64_t input) { return __cntlz8 (input); } #else // Return a count 0..64 of leading zeroes in the given doubleword static inline int32_t leadingZeroes (int64_t input) { uint32_t highWord=input>>32; uint32_t lowWord=input&0xffffffff; uint32_t count = __cntlz4(highWord); if (count==32) count += __cntlz4(lowWord); return count; } #endif #else extern int32_t leadingZeroes (int32_t inputWord); extern int32_t leadingZeroes (int64_t input); #endif static inline int32_t leadingZeroes (uint64_t input) { return (leadingZeroes((int64_t)input)); } static inline int32_t leadingZeroes (uint32_t inputWord) { return leadingZeroes ((int32_t)inputWord); } // Return a count 0..32 of trailing zeroes in the given word static inline int32_t trailingZeroes (int32_t inputWord) { int32_t work; work = inputWord; work = ~work & (work - 1); return 32 - leadingZeroes(work); } static inline int32_t trailingZeroes (uint32_t inputWord) { return trailingZeroes((int32_t)inputWord); } // Return a count 0..64 of trailing zeroes in the given doubleword static inline int32_t trailingZeroes (int64_t input) { int64_t work; work = input; work = ~work & (work - 1); return 64 - leadingZeroes(work); } static inline int32_t trailingZeroes(uint64_t input) { return trailingZeroes((int64_t)input); } static inline int32_t ceilingPowerOfTwo (int32_t inputWord) { return 1 << (32 - leadingZeroes(inputWord - 1)); } static inline int32_t floorPowerOfTwo (int32_t inputWord) { return 1 << (31 - leadingZeroes(inputWord)); } static inline int64_t floorPowerOfTwo64 (int64_t inputWord) { return 1LL << (63 - leadingZeroes(inputWord)); } static inline int32_t leadingOnes (int32_t inputWord) { return leadingZeroes (~inputWord); } static inline int32_t leadingOnes (uint32_t inputWord) { return leadingZeroes (~inputWord); } static inline int32_t leadingOnes (int64_t input) { return leadingZeroes (~input); } static inline int32_t leadingOnes (uint64_t input) { return leadingZeroes (~input); } // return the number of 1-bits in the argument static inline int32_t populationCount (int32_t inputWord) { uint32_t work, temp; work = inputWord; if (0 == work) return 0; work = work - ((work >> 1) & 0x55555555ul); temp = ((work >> 2) & 0x33333333ul); work = (work & 0x33333333ul) + temp; work = (work + (work >> 4)) & 0x0F0F0F0Ful; work = work + (work << 8); work = work + (work << 16); return work >> 24; } static inline int32_t populationCount (uint32_t inputWord) { return populationCount((int32_t)inputWord); } // return the number of 1-bits in the argument static inline int32_t populationCount (int64_t inputWord) { uint64_t work, temp; work = inputWord; if (0 == work) return 0; work = work - ((work >> 1) & CONSTANT64(0x5555555555555555)); temp = ((work >> 2) & CONSTANT64(0x3333333333333333)); work = (work & CONSTANT64(0x3333333333333333)) + temp; work = (work + (work >> 4)) & CONSTANT64(0x0F0F0F0F0F0F0F0F); work = work + (work << 8); work = work + (work << 16); work = work + (work << 32); return (int32_t)(work >> 56); } static inline int32_t populationCount (uint64_t inputWord) { return populationCount((int64_t)inputWord); } // return 10^exponent static inline uint64_t computePositivePowerOfTen(int32_t exponent) { // TODO: there is a better algorithm to reduce the number of multiplies -- see Simplifier.cpp reduceExpTwoAndGreaterToMultiplication TR_ASSERT(exponent >= 0 && exponent <= TR::getMaxSignedPrecision<TR::Int64>(),"exponent %d should be in the inclusive range 0->%d\n",exponent,TR::getMaxSignedPrecision<TR::Int64>()); uint64_t base = 1; for (int32_t i = 0; i < exponent; i++) base = base * 10; return base; } static inline bool isPositivePowerOfTen(int64_t val) { int32_t exponent = trailingZeroes((uint64_t)val); if (exponent <= TR::getMaxSignedPrecision<TR::Int64>() && (uint64_t)val == computePositivePowerOfTen(exponent)) return true; else return false; } #define TR_MAX_PRECISION_LOOKUP 18 static int64_t maxAbsoluteValueTable[TR_MAX_PRECISION_LOOKUP] = { // value for // precision 9, // 1 99, // 2 999, // 3 9999, // 4 99999, // 5 999999, // 6 9999999, // 7 99999999, // 8 999999999, // 9 CONSTANT64(9999999999), // 10 CONSTANT64(99999999999), // 11 CONSTANT64(999999999999), // 12 CONSTANT64(9999999999999), // 13 CONSTANT64(99999999999999), // 14 CONSTANT64(999999999999999), // 15 CONSTANT64(9999999999999999), // 16 CONSTANT64(99999999999999999), // 17 CONSTANT64(999999999999999999), // 18 }; static inline int64_t getMaxAbsValueForPrecision(int32_t precision) { if (precision > 0 && precision <= TR_MAX_PRECISION_LOOKUP) return maxAbsoluteValueTable[precision-1]; else return TR::getMaxSigned<TR::Int64>(); } static int32_t getPrecisionFromValue(int64_t value) { if (value == TR::getMinSigned<TR::Int64>()) return TR::getMaxSignedPrecision<TR::Int64>(); if (value < 0) value *= -1; for (int32_t i = 0; i < TR_MAX_PRECISION_LOOKUP; i++) { if (value <= maxAbsoluteValueTable[i]) return i + 1; } return TR::getMaxSignedPrecision<TR::Int64>(); } static inline int32_t getPrecisionFromRange(int64_t low, int64_t high) { return std::max(getPrecisionFromValue(low), getPrecisionFromValue(high)); } static inline bool isEven(int32_t input) { return (input&0x1) == 0; } static inline bool isOdd(int32_t input) { return (input&0x1) != 0; } static inline bool isEven(uint32_t input) { return isEven((int32_t)input); } static inline bool isOdd(uint32_t input) { return isOdd((int32_t)input); } static inline bool isEven(int64_t input) { return (input&0x1) == 0; } static inline bool isOdd(int64_t input) { return (input&0x1) != 0; } static inline bool isEven(uint64_t input) { return isEven((int64_t)input); } static inline bool isOdd(uint64_t input) { return isOdd((int64_t)input); } static inline bool isNonNegativePowerOf2(int32_t input) { if (input == INT_MIN) { return false; } else { return (input & -input) == input; } } static inline bool isNonPositivePowerOf2(int32_t input) { return (input & -input) == -input; } static inline bool isPowerOf2(int32_t input) { input = input < 0 ? -input : input; return (input & -input) == input; } static inline bool isNonNegativePowerOf2(int64_t input) { if (input == LONG_MIN) { return false; } else { return (input & -input) == input; } } static inline bool isNonPositivePowerOf2(int64_t input) { return (input & -input) == -input; } static inline bool isPowerOf2(int64_t input) { input = input < 0 ? -input : input; return (input & -input) == input; } #undef IN_BITMANIP_H #endif // BITMANIP_H