//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// The rotate(A, B) builtin left-shifts corresponding to the usual OpenCL shift
// modulo rules. These rules state that A is left-shifted by the log2(N) least
// significant bits in B when viewed as an unsigned integer value. Thus we don't
// have to worry about signed shift amounts, and can perform the computation in
// unsigned types.
_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __clc_rotate(__CLC_GENTYPE x,
                                                  __CLC_GENTYPE n) {
  __CLC_U_GENTYPE x_as_u = __CLC_AS_U_GENTYPE(x);
  __CLC_U_GENTYPE mask = (__CLC_U_GENTYPE)(__CLC_GENSIZE - 1);

  __CLC_U_GENTYPE lshift_amt = __CLC_AS_U_GENTYPE(n) & mask;

  __CLC_U_GENTYPE rshift_amt =
      (((__CLC_U_GENTYPE)__CLC_GENSIZE - lshift_amt) & mask);

  __CLC_U_GENTYPE result = (x_as_u << lshift_amt) | (x_as_u >> rshift_amt);

  return __CLC_AS_GENTYPE(result);
}