[clang] [clang] Implement __builtin_stdc_rotate_left, __builtin_stdc_rotate_right (PR #160259)
NagaChaitanya Vellanki via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 26 09:03:38 PDT 2025
================
@@ -2492,12 +2492,36 @@ RValue CodeGenFunction::emitRotate(const CallExpr *E, bool IsRotateRight) {
// The builtin's shift arg may have a different type than the source arg and
// result, but the LLVM intrinsic uses the same type for all values.
llvm::Type *Ty = Src->getType();
+
+ unsigned BitWidth = Ty->getIntegerBitWidth();
+ llvm::Value *BitWidthVal = ConstantInt::get(Ty, BitWidth);
+
+ bool IsShiftAmtSigned = E->getArg(1)->getType()->isSignedIntegerType();
+
+ if (IsShiftAmtSigned) {
+ // converting BitWidth to the type of ShiftAmt
+ llvm::Type *ShiftTy = ShiftAmt->getType();
+ llvm::Value *BitWidthInShiftTy = ConstantInt::get(ShiftTy, BitWidth);
+
+ // if ShiftAmt is negative, normalize ShiftAmt to [0, BitWidth - 1]
+ llvm::Value *RemResult = Builder.CreateSRem(ShiftAmt, BitWidthInShiftTy);
+ llvm::Value *PositiveShift =
+ Builder.CreateAdd(RemResult, BitWidthInShiftTy);
+
+ llvm::Value *Zero = ConstantInt::get(ShiftTy, 0);
+ llvm::Value *IsRemNegative = Builder.CreateICmpSLT(RemResult, Zero);
+
+ ShiftAmt = Builder.CreateSelect(IsRemNegative, PositiveShift, RemResult);
+ }
+
+ // converting ShiftAmt to Src type, ShiftAmt is positive
ShiftAmt = Builder.CreateIntCast(ShiftAmt, Ty, false);
+ ShiftAmt = Builder.CreateURem(ShiftAmt, BitWidthVal);
----------------
chaitanyav wrote:
i am able to reproduce the issue and working on the fix
```bash
nagac at macbook-pro ~/scratch/llvm_test ./test_rotate_runtime
Static assertions passed - compile-time evaluation works!
Runtime: 341 rotate left 1 = 171 (expected 171)
Runtime: 341 rotate right 1 = 426 (expected 426)
Runtime: 1 rotate left 36 (_BitInt(37)) = 68719476736 (expected 68719476736)
All tests passed! Both compile-time and runtime paths work correctly.
```
https://github.com/llvm/llvm-project/pull/160259
More information about the cfe-commits
mailing list