Skip to content

Commit 3a6d57a

Browse files
committed
Fix 2-bit rotation normalization
srem treats both operands as signed. In 2-bit representation 2 is interpretted as -2. Since the rotation amount is 0 or 1 in 2-bit, we can determine by checking if the amount is odd or even
1 parent 493ee8c commit 3a6d57a

File tree

2 files changed

+14
-2
lines changed

2 files changed

+14
-2
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19761,9 +19761,13 @@ APSInt NormalizeRotateAmount(const APSInt &Value, const APSInt &Amount) {
1976119761
if (BitWidth == 1) {
1976219762
// Rotating a 1-bit value is always a no-op
1976319763
NormAmt = APSInt(APInt(AmtBitWidth, 0), NormAmt.isUnsigned());
19764+
} else if (BitWidth == 2) {
19765+
// For 2-bit values: rotation amount is 0 or 1 based on
19766+
// whether the amount is even or odd. We can't use srem here because
19767+
// the divisor (2) would be misinterpreted as -2 in 2-bit signed arithmetic.
19768+
NormAmt =
19769+
APSInt(APInt(AmtBitWidth, NormAmt[0] ? 1 : 0), NormAmt.isUnsigned());
1976419770
} else {
19765-
// Divisor is always unsigned to avoid misinterpreting BitWidth as
19766-
// negative in small bit widths (e.g., BitWidth=2 would be -2 if signed).
1976719771
APInt Divisor;
1976819772
if (AmtBitWidth > BitWidth) {
1976919773
Divisor = llvm::APInt(AmtBitWidth, BitWidth);

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2497,6 +2497,14 @@ RValue CodeGenFunction::emitRotate(const CallExpr *E, bool IsRotateRight) {
24972497
if (BitWidth == 1) {
24982498
// Rotating a 1-bit value is always a no-op
24992499
ShiftAmt = ConstantInt::get(ShiftTy, 0);
2500+
} else if (BitWidth == 2) {
2501+
// For 2-bit values: rotation amount is 0 or 1 based on
2502+
// whether the amount is even or odd. We can't use srem here because
2503+
// the divisor (2) would be misinterpreted as -2 in 2-bit signed arithmetic.
2504+
llvm::Value *One = ConstantInt::get(ShiftTy, 1);
2505+
ShiftAmt = Builder.CreateAnd(ShiftAmt, One);
2506+
if (ShiftTy != Ty)
2507+
ShiftAmt = Builder.CreateIntCast(ShiftAmt, Ty, false);
25002508
} else {
25012509
unsigned ShiftAmtBitWidth = ShiftTy->getIntegerBitWidth();
25022510
bool ShiftAmtIsSigned = E->getArg(1)->getType()->isSignedIntegerType();

0 commit comments

Comments
 (0)