Skip to content

Commit 3c553fc

Browse files
authored
[InstCombine] Infer nuw on mul nsw with non-negative operands (#90170)
If a mul nsw has non-negative operands, it's also nuw. Proof: https://alive2.llvm.org/ce/z/2Dz9Uu Fixes #90020.
1 parent feaddc1 commit 3c553fc

File tree

6 files changed

+18
-9
lines changed

6 files changed

+18
-9
lines changed

llvm/include/llvm/Analysis/ValueTracking.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,8 @@ enum class OverflowResult {
860860
};
861861

862862
OverflowResult computeOverflowForUnsignedMul(const Value *LHS, const Value *RHS,
863-
const SimplifyQuery &SQ);
863+
const SimplifyQuery &SQ,
864+
bool IsNSW = false);
864865
OverflowResult computeOverflowForSignedMul(const Value *LHS, const Value *RHS,
865866
const SimplifyQuery &SQ);
866867
OverflowResult

llvm/include/llvm/Transforms/InstCombine/InstCombiner.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,9 +461,10 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
461461

462462
OverflowResult computeOverflowForUnsignedMul(const Value *LHS,
463463
const Value *RHS,
464-
const Instruction *CxtI) const {
465-
return llvm::computeOverflowForUnsignedMul(LHS, RHS,
466-
SQ.getWithInstruction(CxtI));
464+
const Instruction *CxtI,
465+
bool IsNSW = false) const {
466+
return llvm::computeOverflowForUnsignedMul(
467+
LHS, RHS, SQ.getWithInstruction(CxtI), IsNSW);
467468
}
468469

469470
OverflowResult computeOverflowForSignedMul(const Value *LHS, const Value *RHS,

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6686,9 +6686,15 @@ llvm::computeConstantRangeIncludingKnownBits(const WithCache<const Value *> &V,
66866686

66876687
OverflowResult llvm::computeOverflowForUnsignedMul(const Value *LHS,
66886688
const Value *RHS,
6689-
const SimplifyQuery &SQ) {
6689+
const SimplifyQuery &SQ,
6690+
bool IsNSW) {
66906691
KnownBits LHSKnown = computeKnownBits(LHS, /*Depth=*/0, SQ);
66916692
KnownBits RHSKnown = computeKnownBits(RHS, /*Depth=*/0, SQ);
6693+
6694+
// mul nsw of two non-negative numbers is also nuw.
6695+
if (IsNSW && LHSKnown.isNonNegative() && RHSKnown.isNonNegative())
6696+
return OverflowResult::NeverOverflows;
6697+
66926698
ConstantRange LHSRange = ConstantRange::fromKnownBits(LHSKnown, false);
66936699
ConstantRange RHSRange = ConstantRange::fromKnownBits(RHSKnown, false);
66946700
return mapOverflowResult(LHSRange.unsignedMulMayOverflow(RHSRange));

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,9 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
354354
}
355355

356356
bool willNotOverflowUnsignedMul(const Value *LHS, const Value *RHS,
357-
const Instruction &CxtI) const {
358-
return computeOverflowForUnsignedMul(LHS, RHS, &CxtI) ==
357+
const Instruction &CxtI,
358+
bool IsNSW = false) const {
359+
return computeOverflowForUnsignedMul(LHS, RHS, &CxtI, IsNSW) ==
359360
OverflowResult::NeverOverflows;
360361
}
361362

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
530530
I.setHasNoSignedWrap(true);
531531
}
532532

533-
if (!HasNUW && willNotOverflowUnsignedMul(Op0, Op1, I)) {
533+
if (!HasNUW && willNotOverflowUnsignedMul(Op0, Op1, I, I.hasNoSignedWrap())) {
534534
Changed = true;
535535
I.setHasNoUnsignedWrap(true);
536536
}

llvm/test/Transforms/InstCombine/mul.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2146,7 +2146,7 @@ define i8 @mul_nsw_nonneg(i8 %x, i8 %y) {
21462146
; CHECK-NEXT: call void @llvm.assume(i1 [[X_NNEG]])
21472147
; CHECK-NEXT: [[Y_NNEG:%.*]] = icmp sgt i8 [[Y:%.*]], -1
21482148
; CHECK-NEXT: call void @llvm.assume(i1 [[Y_NNEG]])
2149-
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[X]], [[Y]]
2149+
; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i8 [[X]], [[Y]]
21502150
; CHECK-NEXT: ret i8 [[MUL]]
21512151
;
21522152
%x.nneg = icmp sge i8 %x, 0

0 commit comments

Comments
 (0)