Skip to content

Commit fbe261f

Browse files
committed
Address feedback from code review
* Use APInt for Divisor * Move rotation normalization code into ExprConstShared.h
1 parent e92986d commit fbe261f

File tree

3 files changed

+48
-72
lines changed

3 files changed

+48
-72
lines changed

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4145,41 +4145,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
41454145

41464146
return interp__builtin_elementwise_int_binop(
41474147
S, OpPC, Call, [IsRotateRight](const APSInt &Value, APSInt Amount) {
4148-
// Normalize shift amount to [0, BitWidth) range to match runtime
4149-
// behavior. This matches the algorithm in ExprConstant.cpp.
4150-
unsigned BitWidth = Value.getBitWidth();
4151-
unsigned AmtBitWidth = Amount.getBitWidth();
4152-
if (BitWidth == 1) {
4153-
// Rotating a 1-bit value is always a no-op
4154-
Amount = APSInt(llvm::APInt(AmtBitWidth, 0), Amount.isUnsigned());
4155-
} else {
4156-
// Divisor is always unsigned to avoid misinterpreting BitWidth as
4157-
// negative in small bit widths (e.g., BitWidth=2 would be -2 if
4158-
// signed).
4159-
APSInt Divisor;
4160-
if (AmtBitWidth > BitWidth) {
4161-
Divisor = APSInt(llvm::APInt(AmtBitWidth, BitWidth),
4162-
/*isUnsigned=*/true);
4163-
} else {
4164-
Divisor =
4165-
APSInt(llvm::APInt(BitWidth, BitWidth), /*isUnsigned=*/true);
4166-
if (AmtBitWidth < BitWidth) {
4167-
Amount = Amount.extend(BitWidth);
4168-
}
4169-
}
4170-
4171-
// Normalize to [0, BitWidth)
4172-
if (Amount.isSigned()) {
4173-
Amount = APSInt(Amount.srem(Divisor), /*isUnsigned=*/false);
4174-
if (Amount.isNegative()) {
4175-
APSInt SignedDivisor(Divisor, /*isUnsigned=*/false);
4176-
Amount += SignedDivisor;
4177-
}
4178-
} else {
4179-
Amount = APSInt(Amount.urem(Divisor), /*isUnsigned=*/true);
4180-
}
4181-
}
4182-
4148+
Amount = NormalizeRotateAmount(Value, Amount);
41834149
return IsRotateRight ? Value.rotr(Amount.getZExtValue())
41844150
: Value.rotl(Amount.getZExtValue());
41854151
});

clang/lib/AST/ExprConstShared.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919

2020
namespace llvm {
2121
class APFloat;
22-
class APInt;
2322
class APSInt;
23+
class APInt;
2424
}
2525
namespace clang {
2626
class QualType;
@@ -81,5 +81,7 @@ uint8_t GFNIMultiplicativeInverse(uint8_t Byte);
8181
uint8_t GFNIMul(uint8_t AByte, uint8_t BByte);
8282
uint8_t GFNIAffine(uint8_t XByte, const llvm::APInt &AQword,
8383
const llvm::APSInt &Imm, bool Inverse = false);
84+
llvm::APSInt NormalizeRotateAmount(const llvm::APSInt &Value,
85+
const llvm::APSInt &Amount);
8486

8587
#endif

clang/lib/AST/ExprConstant.cpp

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16352,42 +16352,12 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1635216352
case Builtin::BI_rotr:
1635316353
case Builtin::BI_lrotr:
1635416354
case Builtin::BI_rotr64: {
16355-
APSInt Val, Amt;
16356-
if (!EvaluateInteger(E->getArg(0), Val, Info) ||
16357-
!EvaluateInteger(E->getArg(1), Amt, Info))
16355+
APSInt Value, Amount;
16356+
if (!EvaluateInteger(E->getArg(0), Value, Info) ||
16357+
!EvaluateInteger(E->getArg(1), Amount, Info))
1635816358
return false;
1635916359

16360-
// Normalize shift amount to [0, BitWidth) range to match runtime behavior
16361-
unsigned BitWidth = Val.getBitWidth();
16362-
unsigned AmtBitWidth = Amt.getBitWidth();
16363-
if (BitWidth == 1) {
16364-
// Rotating a 1-bit value is always a no-op
16365-
Amt = APSInt(APInt(AmtBitWidth, 0), Amt.isUnsigned());
16366-
} else {
16367-
// Divisor is always unsigned to avoid misinterpreting BitWidth as
16368-
// negative in small bit widths (e.g., BitWidth=2 would be -2 if signed).
16369-
APSInt Divisor;
16370-
if (AmtBitWidth > BitWidth) {
16371-
Divisor =
16372-
APSInt(llvm::APInt(AmtBitWidth, BitWidth), /*isUnsigned=*/true);
16373-
} else {
16374-
Divisor = APSInt(llvm::APInt(BitWidth, BitWidth), /*isUnsigned=*/true);
16375-
if (AmtBitWidth < BitWidth) {
16376-
Amt = Amt.extend(BitWidth);
16377-
}
16378-
}
16379-
16380-
// Normalize to [0, BitWidth)
16381-
if (Amt.isSigned()) {
16382-
Amt = APSInt(Amt.srem(Divisor), /*isUnsigned=*/false);
16383-
if (Amt.isNegative()) {
16384-
APSInt SignedDivisor(Divisor, /*isUnsigned=*/false);
16385-
Amt += SignedDivisor;
16386-
}
16387-
} else {
16388-
Amt = APSInt(Amt.urem(Divisor), /*isUnsigned=*/true);
16389-
}
16390-
}
16360+
Amount = NormalizeRotateAmount(Value, Amount);
1639116361

1639216362
switch (BuiltinOp) {
1639316363
case Builtin::BI__builtin_rotateright8:
@@ -16400,9 +16370,11 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1640016370
case Builtin::BI_rotr:
1640116371
case Builtin::BI_lrotr:
1640216372
case Builtin::BI_rotr64:
16403-
return Success(APSInt(Val.rotr(Amt.getZExtValue()), Val.isUnsigned()), E);
16373+
return Success(
16374+
APSInt(Value.rotr(Amount.getZExtValue()), Value.isUnsigned()), E);
1640416375
default:
16405-
return Success(APSInt(Val.rotl(Amt.getZExtValue()), Val.isUnsigned()), E);
16376+
return Success(
16377+
APSInt(Value.rotl(Amount.getZExtValue()), Value.isUnsigned()), E);
1640616378
}
1640716379
}
1640816380

@@ -19781,6 +19753,42 @@ void HandleComplexComplexDiv(APFloat A, APFloat B, APFloat C, APFloat D,
1978119753
}
1978219754
}
1978319755

19756+
APSInt NormalizeRotateAmount(const APSInt &Value, const APSInt &Amount) {
19757+
// Normalize shift amount to [0, BitWidth) range to match runtime behavior
19758+
APSInt NormAmt = Amount;
19759+
unsigned BitWidth = Value.getBitWidth();
19760+
unsigned AmtBitWidth = NormAmt.getBitWidth();
19761+
if (BitWidth == 1) {
19762+
// Rotating a 1-bit value is always a no-op
19763+
NormAmt = APSInt(APInt(AmtBitWidth, 0), NormAmt.isUnsigned());
19764+
} 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).
19767+
APInt Divisor;
19768+
if (AmtBitWidth > BitWidth) {
19769+
Divisor = llvm::APInt(AmtBitWidth, BitWidth);
19770+
} else {
19771+
Divisor = llvm::APInt(BitWidth, BitWidth);
19772+
if (AmtBitWidth < BitWidth) {
19773+
NormAmt = NormAmt.extend(BitWidth);
19774+
}
19775+
}
19776+
19777+
// Normalize to [0, BitWidth)
19778+
if (NormAmt.isSigned()) {
19779+
NormAmt = APSInt(NormAmt.srem(Divisor), /*isUnsigned=*/false);
19780+
if (NormAmt.isNegative()) {
19781+
APSInt SignedDivisor(Divisor, /*isUnsigned=*/false);
19782+
NormAmt += SignedDivisor;
19783+
}
19784+
} else {
19785+
NormAmt = APSInt(NormAmt.urem(Divisor), /*isUnsigned=*/true);
19786+
}
19787+
}
19788+
19789+
return NormAmt;
19790+
}
19791+
1978419792
bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
1978519793
if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma)
1978619794
return ExprEvaluatorBaseTy::VisitBinaryOperator(E);

0 commit comments

Comments
 (0)