Skip to content

Commit fc350f0

Browse files
committed
[InstCombine] Simplify with.overflow intrinsics with assumption information
1 parent 96ab2a0 commit fc350f0

File tree

2 files changed

+31
-12
lines changed

2 files changed

+31
-12
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,33 @@ InstCombinerImpl::foldIntrinsicWithOverflowCommon(IntrinsicInst *II) {
818818
if (OptimizeOverflowCheck(WO->getBinaryOp(), WO->isSigned(), WO->getLHS(),
819819
WO->getRHS(), *WO, OperationResult, OverflowResult))
820820
return createOverflowTuple(WO, OperationResult, OverflowResult);
821+
822+
// See whether we can optimize the overflow check with assumption information.
823+
for (User *U : WO->users()) {
824+
if (!match(U, m_ExtractValue<1>(m_Value())))
825+
continue;
826+
827+
for (auto &AssumeVH : AC.assumptionsFor(U)) {
828+
if (!AssumeVH)
829+
continue;
830+
CallInst *I = cast<CallInst>(AssumeVH);
831+
if (!match(I->getArgOperand(0), m_Not(m_Specific(U))))
832+
continue;
833+
if (!isValidAssumeForContext(I, II, &DT))
834+
continue;
835+
Value *Result =
836+
Builder.CreateBinOp(WO->getBinaryOp(), WO->getLHS(), WO->getRHS());
837+
if (auto *Inst = dyn_cast<Instruction>(Result)) {
838+
if (WO->isSigned())
839+
Inst->setHasNoSignedWrap();
840+
else
841+
Inst->setHasNoUnsignedWrap();
842+
}
843+
return createOverflowTuple(WO, Result,
844+
ConstantInt::getFalse(U->getType()));
845+
}
846+
}
847+
821848
return nullptr;
822849
}
823850

llvm/test/Transforms/InstCombine/overflow.ll

+4-12
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,8 @@ if.end:
173173

174174
define i32 @uadd_no_overflow(i32 %a, i32 %b) {
175175
; CHECK-LABEL: @uadd_no_overflow(
176-
; CHECK-NEXT: [[VAL:%.*]] = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[A:%.*]], i32 [[B:%.*]])
177-
; CHECK-NEXT: [[OV:%.*]] = extractvalue { i32, i1 } [[VAL]], 1
178-
; CHECK-NEXT: [[NOWRAP:%.*]] = xor i1 [[OV]], true
179-
; CHECK-NEXT: tail call void @llvm.assume(i1 [[NOWRAP]])
180-
; CHECK-NEXT: [[RES:%.*]] = extractvalue { i32, i1 } [[VAL]], 0
181-
; CHECK-NEXT: ret i32 [[RES]]
176+
; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[A:%.*]], [[B:%.*]]
177+
; CHECK-NEXT: ret i32 [[TMP1]]
182178
;
183179
%val = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)
184180
%ov = extractvalue { i32, i1 } %val, 1
@@ -190,12 +186,8 @@ define i32 @uadd_no_overflow(i32 %a, i32 %b) {
190186

191187
define i32 @smul_no_overflow(i32 %a, i32 %b) {
192188
; CHECK-LABEL: @smul_no_overflow(
193-
; CHECK-NEXT: [[VAL:%.*]] = tail call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[A:%.*]], i32 [[B:%.*]])
194-
; CHECK-NEXT: [[OV:%.*]] = extractvalue { i32, i1 } [[VAL]], 1
195-
; CHECK-NEXT: [[NOWRAP:%.*]] = xor i1 [[OV]], true
196-
; CHECK-NEXT: tail call void @llvm.assume(i1 [[NOWRAP]])
197-
; CHECK-NEXT: [[RES:%.*]] = extractvalue { i32, i1 } [[VAL]], 0
198-
; CHECK-NEXT: ret i32 [[RES]]
189+
; CHECK-NEXT: [[TMP1:%.*]] = mul nsw i32 [[A:%.*]], [[B:%.*]]
190+
; CHECK-NEXT: ret i32 [[TMP1]]
199191
;
200192
%val = tail call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %a, i32 %b)
201193
%ov = extractvalue { i32, i1 } %val, 1

0 commit comments

Comments
 (0)