Skip to content

Commit 3566efe

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).
1 parent 964097d commit 3566efe

File tree

2 files changed

+31
-8
lines changed

2 files changed

+31
-8
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: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ define i1 @assume_mul_nuw_square_i8(i8 %s) {
99
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i8 [[S:%.*]], [[S]]
1010
; CHECK-NEXT: [[COND:%.*]] = icmp ule i8 [[MUL]], 120
1111
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
12-
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[S]], 16
13-
; CHECK-NEXT: ret i1 [[CMP]]
12+
; CHECK-NEXT: ret i1 true
1413
;
1514
start:
1615
%mul = mul nuw i8 %s, %s
@@ -26,8 +25,7 @@ define i1 @assume_mul_nuw_square_i5(i5 %s) {
2625
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i5 [[S:%.*]], [[S]]
2726
; CHECK-NEXT: [[COND:%.*]] = icmp ult i5 [[MUL]], 15
2827
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
29-
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i5 [[S]], 8
30-
; CHECK-NEXT: ret i1 [[CMP]]
28+
; CHECK-NEXT: ret i1 true
3129
;
3230
start:
3331
%mul = mul nuw i5 %s, %s
@@ -44,11 +42,9 @@ define i1 @branch_mul_nuw_square(i8 %s, i8 %num) {
4442
; CHECK-NEXT: [[COND:%.*]] = icmp ule i8 [[MUL]], [[NUM:%.*]]
4543
; CHECK-NEXT: br i1 [[COND]], label [[TRUE:%.*]], label [[FALSE:%.*]]
4644
; CHECK: true:
47-
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[S]], 16
48-
; CHECK-NEXT: ret i1 [[CMP]]
45+
; CHECK-NEXT: ret i1 true
4946
; CHECK: false:
50-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i8 [[S]], 16
51-
; CHECK-NEXT: ret i1 [[CMP2]]
47+
; CHECK-NEXT: ret i1 true
5248
;
5349
entry:
5450
%mul = mul nuw i8 %s, %s

0 commit comments

Comments
 (0)