1/** 2 * Not necessarily optimal... but it produces correct results (at least for int) 3 * If we're lucky, LLVM will recognize the pattern and produce rotate 4 * instructions: 5 * http://llvm.1065342.n5.nabble.com/rotate-td47679.html 6 * 7 * Eventually, someone should feel free to implement an llvm-specific version 8 */ 9 10_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE rotate(__CLC_GENTYPE x, __CLC_GENTYPE n){ 11 //Try to avoid extra work if someone's spinning the value through multiple 12 //full rotations 13 n = n % (__CLC_GENTYPE)__CLC_GENSIZE; 14 15#ifdef __CLC_SCALAR 16 if (n > 0){ 17 return (x << n) | (((__CLC_U_GENTYPE)x) >> (__CLC_GENSIZE - n)); 18 } else if (n == 0){ 19 return x; 20 } else { 21 return ( (((__CLC_U_GENTYPE)x) >> -n) | (x << (__CLC_GENSIZE + n)) ); 22 } 23#else 24 //XXX: There's a lot of __builtin_astype calls to cast everything to 25 // unsigned ... This should be improved so that if __CLC_GENTYPE==__CLC_U_GENTYPE, no 26 // casts are required. 27 28 __CLC_U_GENTYPE x_1 = __builtin_astype(x, __CLC_U_GENTYPE); 29 30 //XXX: Is (__CLC_U_GENTYPE >> S__CLC_GENTYPE) | (__CLC_U_GENTYPE << S__CLC_GENTYPE) legal? 31 // If so, then combine the amt and shifts into a single set of statements 32 33 __CLC_U_GENTYPE amt; 34 amt = (n < (__CLC_GENTYPE)0 ? __builtin_astype((__CLC_GENTYPE)0-n, __CLC_U_GENTYPE) : (__CLC_U_GENTYPE)0); 35 x_1 = (x_1 >> amt) | (x_1 << ((__CLC_U_GENTYPE)__CLC_GENSIZE - amt)); 36 37 amt = (n < (__CLC_GENTYPE)0 ? (__CLC_U_GENTYPE)0 : __builtin_astype(n, __CLC_U_GENTYPE)); 38 x_1 = (x_1 << amt) | (x_1 >> ((__CLC_U_GENTYPE)__CLC_GENSIZE - amt)); 39 40 return __builtin_astype(x_1, __CLC_GENTYPE); 41#endif 42} 43