[PATCH] D50222: [CodeGen] [SelectionDAG] More efficient code for X % C == 0 (UREM case)

Kapandaria via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Feb 23 11:05:15 PST 2019


gnudles requested changes to this revision.
gnudles added a comment.
This revision now requires changes to proceed.
Herald added a subscriber: jdoerfert.

Hi guy, I found the magical formula that works with d=1 and works with even numbers without the need to check for overflows:
from divisor d and reminder r, I calculate 4 constants.

void calculate_constants64(uint64_t d, uint64_t r, uint64_t &k,uint64_t &mmi, uint64_t &s,uint64_t& u)
{
	k=__builtin_ctzll(d);// the power of 2
	uint64_t p_odd=d>>k;
	mmi=find_mod_mul_inverse(p_odd,64);
	s=(r*mmi);

  u=(ULLONG_MAX-r)/d;

}
int checkrem64(uint64_t k,uint64_t mmi, uint64_t s,uint64_t u,uint64_t x)
{

  uint64_t o=((x*mmi)-s);
  o= (o>>k)|(o<<(64-k));//ROTR64(o,k)
  return o<=u;

}

this replace the following
//d is the divisor, r is the remainder
int checkrem64(uint64_t x)
{
return x%d==r;
}
this is the code to find modular inverse..
uint64_t find_mod_mul_inverse(uint64_t x, uint64_t bits)
{

  if (bits > 64 || ((x&1)==0))
          return 0;// invalid parameters
  uint64_t mask;
  if (bits == 64)
          mask = -1;
  else
  {                
          mask = 1;
          mask<<=bits;
          mask--;
  }
  x&=mask;
  uint64_t result=1, state=x, ctz=0;
  while(state!=1ULL)
  {
          ctz=__builtin_ctzll(state^1);
          result|=1ULL<<ctz;
          state+=x<<ctz;
          state&=mask;
  }
  return result;

}

good luck!


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D50222/new/

https://reviews.llvm.org/D50222





More information about the llvm-commits mailing list