Skip to content

Commit 5214d5e

Browse files
committed
[PredicateInfo] Infer operand bound from mul nuw square predicates
A mul nuw X, X used in an assume/branch condition cannot overflow (or the condition would be poison, which is UB for assumes and control flow), which implies: X < 2^ceil(bitwidth(X)/2) (e.g., i16: X < 256). Fixes #122412
1 parent 8d3a30c commit 5214d5e

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

llvm/lib/Transforms/Utils/PredicateInfo.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,14 @@ void collectCmpOps(CmpInst *Comparison, SmallVectorImpl<Value *> &CmpOperands) {
345345

346346
CmpOperands.push_back(Op0);
347347
CmpOperands.push_back(Op1);
348+
349+
auto AddSquareOp = [&CmpOperands](Value *V) {
350+
Value *SquareOp;
351+
if (match(V, m_NUWMul(m_Value(SquareOp), m_Deferred(SquareOp))))
352+
CmpOperands.push_back(SquareOp);
353+
};
354+
AddSquareOp(Op0);
355+
AddSquareOp(Op1);
348356
}
349357

350358
// Add Op, PB to the list of value infos for Op, and mark Op to be renamed.
@@ -735,6 +743,25 @@ std::optional<PredicateConstraint> PredicateBase::getConstraint() const {
735743
return std::nullopt;
736744
}
737745

746+
// A `mul nuw RenamedOp, RenamedOp` used by the condition cannot overflow
747+
// (or the condition would be poison, which is UB for assumes and control
748+
// flow), which implies `RenamedOp < 2^ceil(bitwidth(RenamedOp)/2)`
749+
// (e.g., i16: `RenamedOp < 256`).
750+
auto IsNuwSquareOfRenamedOp = [this](Value *V) {
751+
return match(V, m_NUWMul(m_Specific(RenamedOp), m_Specific(RenamedOp)));
752+
};
753+
if (RenamedOp->getType()->isIntegerTy() &&
754+
(IsNuwSquareOfRenamedOp(Cmp->getOperand(0)) ||
755+
IsNuwSquareOfRenamedOp(Cmp->getOperand(1)))) {
756+
unsigned BitWidth = RenamedOp->getType()->getScalarSizeInBits();
757+
unsigned LimitBits = (BitWidth + 1) / 2;
758+
if (LimitBits < BitWidth) {
759+
APInt Upper = APInt::getOneBitSet(BitWidth, LimitBits);
760+
return {
761+
{CmpInst::ICMP_ULT, ConstantInt::get(RenamedOp->getType(), Upper)}};
762+
}
763+
}
764+
738765
CmpInst::Predicate Pred;
739766
Value *OtherOp;
740767
if (Cmp->getOperand(0) == RenamedOp) {

llvm/test/Transforms/SCCP/assume-mul-nuw-square.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ define i1 @src(i16 %num, i16 %s) {
99
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i16 [[S:%.*]], [[S]]
1010
; CHECK-NEXT: [[COND:%.*]] = icmp ule i16 [[MUL]], [[NUM:%.*]]
1111
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
12-
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[S]], 256
13-
; CHECK-NEXT: ret i1 [[CMP]]
12+
; CHECK-NEXT: ret i1 true
1413
;
1514
start:
1615
%mul = mul nuw i16 %s, %s

0 commit comments

Comments
 (0)