ConstantDivision.cpp

Go to the documentation of this file.
00001 //===-- ConstantDivision.cpp ----------------------------------------------===//
00002 //
00003 //                     The KLEE Symbolic Virtual Machine
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "ConstantDivision.h"
00011 
00012 #include "klee/util/Bits.h"
00013 
00014 #include <algorithm>
00015 #include <cassert>
00016 
00017 namespace klee {
00018 
00019 /* Macros and functions which define the basic bit-level operations 
00020  * needed to implement quick division operations.
00021  *
00022  * Based on Hacker's Delight (2003) by Henry S. Warren, Jr.
00023  */
00024 
00025 /* 32 -- number of bits in the integer type on this architecture */
00026 
00027 /* 2^32 -- NUM_BITS=32 requires 64 bits to represent this unsigned value */
00028 #define TWO_TO_THE_32_U64 (1ULL << 32)
00029 
00030 /* 2e31 -- NUM_BITS=32 requires 64 bits to represent this signed value */
00031 #define TWO_TO_THE_31_S64 (1LL << 31)
00032 
00033 /* ABS(x) -- positive x */
00034 #define ABS(x) ( ((x)>0)?x:-(x) ) /* fails if x is the min value of its type */
00035 
00036 /* XSIGN(x) -- -1 if x<0 and 0 otherwise */
00037 #define XSIGN(x) ( (x) >> 31 )
00038 
00039 /* LOG2_CEIL(x) -- logarithm base 2 of x, rounded up */
00040 #define LOG2_CEIL(x) ( 32 - ldz(x - 1) )
00041 
00042 /* ones(x) -- counts the number of bits in x with the value 1 */
00043 static uint32_t ones( register uint32_t x ) {
00044   x -= ((x >> 1) & 0x55555555);
00045   x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
00046   x = (((x >> 4) + x) & 0x0f0f0f0f);
00047   x += (x >> 8);
00048   x += (x >> 16);
00049 
00050   return( x & 0x0000003f );
00051 }
00052 
00053 /* ldz(x) -- counts the number of leading zeroes in a 32-bit word */
00054 static uint32_t ldz( register uint32_t x ) {
00055   x |= (x >> 1);
00056   x |= (x >> 2);
00057   x |= (x >> 4);
00058   x |= (x >> 8);
00059   x |= (x >> 16);
00060 
00061   return 32 - ones(x);
00062 }
00063 
00064 /* exp_base_2(n) -- 2^n computed as an integer */
00065 static uint32_t exp_base_2( register int32_t n ) {
00066   register uint32_t x = ~n & (n - 32);
00067   x = x >> 31;
00068   return( x << n );
00069 }
00070 
00071 // A simple algorithm: Iterate over all contiguous regions of 1 bits
00072 // in x starting with the lowest bits.
00073 //
00074 // For a particular range where x is 1 for bits [low,high) then:
00075 //   1) if the range is just one bit, simple add it
00076 //   2) if the range is more than one bit, replace with an add
00077 //      of the high bit and a subtract of the low bit. we apply
00078 //      one useful optimization: if we were going to add the bit
00079 //      below the one we wish to subtract, we simply change that
00080 //      add to a subtract instead of subtracting the low bit itself.
00081 // Obviously we must take care when high==64.
00082 void ComputeMultConstants64(uint64_t multiplicand, 
00083                             uint64_t &add, uint64_t &sub) {
00084   uint64_t x = multiplicand;
00085   add = sub = 0;
00086 
00087   while (x) {
00088     // Determine rightmost contiguous region of 1s.
00089     unsigned low = bits64::indexOfRightmostBit(x);
00090     uint64_t lowbit = 1LL << low;
00091     uint64_t p = x + lowbit;
00092     uint64_t q = bits64::isolateRightmostBit(p);
00093     unsigned high = q ? bits64::indexOfSingleBit(q) : 64;
00094 
00095     if (high==low+1) { // Just one bit...
00096       add |= lowbit;
00097     } else {
00098       // Rewrite as +(1<<high) - (1<<low).
00099 
00100       // Optimize +(1<<x) - (1<<(x+1)) to -(1<<x).
00101       if (low && (add & (lowbit>>1))) {
00102         add ^= lowbit>>1;
00103         sub ^= lowbit>>1;
00104       } else {
00105         sub |= lowbit;
00106       }
00107 
00108       if (high!=64)
00109         add |= 1LL << high;
00110     }
00111 
00112     x = p ^ q;
00113   }
00114 
00115   assert(multiplicand == add - sub);
00116 }
00117 
00118 void ComputeUDivConstants32(uint32_t d, uint32_t &mprime, uint32_t &sh1, 
00119                             uint32_t &sh2) {
00120   int32_t l = LOG2_CEIL( d ); /* signed so l-1 => -1 when l=0 (see sh2) */
00121   uint32_t mid = exp_base_2(l) - d;
00122 
00123   mprime = (TWO_TO_THE_32_U64 * mid / d) + 1;
00124   sh1    = std::min( l,   1 );
00125   sh2    = std::max( l-1, 0 );
00126 }
00127 
00128 void ComputeSDivConstants32(int32_t d, int32_t &mprime, int32_t &dsign, 
00129                             int32_t &shpost ) {
00130   uint64_t abs_d = ABS( (int64_t)d ); /* use 64-bits in case d is INT32_MIN */
00131 
00132   /* LOG2_CEIL works on 32-bits, so we cast abs_d.  The only possible value
00133    * outside the 32-bit rep. is 2^31.  This is special cased to save computer 
00134    * time since 64-bit routines would be overkill. */
00135   int32_t l = std::max( 1U, LOG2_CEIL((uint32_t)abs_d) );
00136   if( abs_d == TWO_TO_THE_31_S64 ) l = 31;
00137 
00138   uint32_t mid = exp_base_2( l - 1 );
00139   uint64_t m = TWO_TO_THE_32_U64 * mid / abs_d + 1ULL;
00140 
00141   mprime = m - TWO_TO_THE_32_U64; /* implicit cast to 32-bits signed */
00142   dsign  = XSIGN( d );
00143   shpost = l - 1;
00144 }
00145 
00146 }

Generated on Fri Jun 5 03:31:32 2009 for klee by  doxygen 1.5.8