Skip to content

Commit eda8e99

Browse files
author
luxufan
committed
[InstCombine] Combine (zext a) mul (zext b) to llvm.umul.with.overflow only if mul has NUW flag
Fixes: #59836 Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D141031
1 parent 0db88db commit eda8e99

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6338,11 +6338,11 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
63386338
}
63396339

63406340
// (zext a) * (zext b) --> llvm.umul.with.overflow.
6341-
if (match(Op0, m_Mul(m_ZExt(m_Value(A)), m_ZExt(m_Value(B))))) {
6341+
if (match(Op0, m_NUWMul(m_ZExt(m_Value(A)), m_ZExt(m_Value(B))))) {
63426342
if (Instruction *R = processUMulZExtIdiom(I, Op0, Op1, *this))
63436343
return R;
63446344
}
6345-
if (match(Op1, m_Mul(m_ZExt(m_Value(A)), m_ZExt(m_Value(B))))) {
6345+
if (match(Op1, m_NUWMul(m_ZExt(m_Value(A)), m_ZExt(m_Value(B))))) {
63466346
if (Instruction *R = processUMulZExtIdiom(I, Op1, Op0, *this))
63476347
return R;
63486348
}

llvm/test/Transforms/InstCombine/overflow-mul.ll

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,41 @@ define i1 @pr21445(i8 %a) {
241241
%cmp = icmp ne i32 %mul, %and
242242
ret i1 %cmp
243243
}
244+
245+
; Negative test: mul(zext x, zext y) may overflow.
246+
define i32 @mul_may_overflow(i32 %x, i32 %y) {
247+
; CHECK-LABEL: @mul_may_overflow(
248+
; CHECK-NEXT: entry:
249+
; CHECK-NEXT: [[L:%.*]] = zext i32 [[X:%.*]] to i34
250+
; CHECK-NEXT: [[R:%.*]] = zext i32 [[Y:%.*]] to i34
251+
; CHECK-NEXT: [[MUL34:%.*]] = mul i34 [[L]], [[R]]
252+
; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ult i34 [[MUL34]], 4294967296
253+
; CHECK-NEXT: [[RETVAL:%.*]] = zext i1 [[OVERFLOW]] to i32
254+
; CHECK-NEXT: ret i32 [[RETVAL]]
255+
;
256+
entry:
257+
%l = zext i32 %x to i34
258+
%r = zext i32 %y to i34
259+
%mul34 = mul i34 %l, %r
260+
%overflow = icmp ule i34 %mul34, 4294967295
261+
%retval = zext i1 %overflow to i32
262+
ret i32 %retval
263+
}
264+
265+
define i32 @mul_known_nuw(i32 %x, i32 %y) {
266+
; CHECK-LABEL: @mul_known_nuw(
267+
; CHECK-NEXT: entry:
268+
; CHECK-NEXT: [[UMUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
269+
; CHECK-NEXT: [[TMP0:%.*]] = extractvalue { i32, i1 } [[UMUL]], 1
270+
; CHECK-NEXT: [[OVERFLOW:%.*]] = xor i1 [[TMP0]], true
271+
; CHECK-NEXT: [[RETVAL:%.*]] = zext i1 [[OVERFLOW]] to i32
272+
; CHECK-NEXT: ret i32 [[RETVAL]]
273+
;
274+
entry:
275+
%l = zext i32 %x to i34
276+
%r = zext i32 %y to i34
277+
%mul34 = mul nuw i34 %l, %r
278+
%overflow = icmp ule i34 %mul34, 4294967295
279+
%retval = zext i1 %overflow to i32
280+
ret i32 %retval
281+
}

0 commit comments

Comments
 (0)