[llvm] [InstCombine] Fold umul.overflow(x, c1) | (x*c1 > c2) to x > c2/c1 (PR #147327)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 8 00:52:31 PDT 2025
================
@@ -0,0 +1,226 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+declare void @use.i1(i1 %x)
+declare void @use.i64(i64 %x)
+declare void @use.i64i1({i64, i1} %x)
+
+define i1 @umul_greater_than_or_overflow_const(i64 %in) {
+; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const(
+; CHECK-SAME: i64 [[IN:%.*]]) {
+; CHECK-NEXT: [[TMP6:%.*]] = icmp ugt i64 [[IN]], 109802048057794950
+; CHECK-NEXT: ret i1 [[TMP6]]
+;
+ %mwo = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 168)
+ %mul = extractvalue { i64, i1 } %mwo, 0
+ %ovf = extractvalue { i64, i1 } %mwo, 1
+ %cmp = icmp ugt i64 %mul, -16
+ %ret = or i1 %ovf, %cmp
+ ret i1 %ret
+}
+
+define i1 @umul_greater_than_or_overflow_const_i8(i8 %in) {
+; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_i8(
+; CHECK-SAME: i8 [[IN:%.*]]) {
+; CHECK-NEXT: [[TMP6:%.*]] = icmp ugt i8 [[IN]], 10
+; CHECK-NEXT: ret i1 [[TMP6]]
+;
+ %mwo = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %in, i8 24)
+ %mul = extractvalue { i8, i1 } %mwo, 0
+ %ovf = extractvalue { i8, i1 } %mwo, 1
+ %cmp = icmp ugt i8 %mul, -16
+ %ret = or i1 %ovf, %cmp
+ ret i1 %ret
+}
+
+define i1 @umul_greater_than_or_overflow_const_commuted(i64 %in) {
+; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_commuted(
+; CHECK-SAME: i64 [[IN:%.*]]) {
+; CHECK-NEXT: [[TMP6:%.*]] = icmp ugt i64 [[IN]], 192153584101141162
+; CHECK-NEXT: ret i1 [[TMP6]]
+;
+ %mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 48)
+ %mul = extractvalue { i64, i1 } %mwo, 0
+ %ovf = extractvalue { i64, i1 } %mwo, 1
+ %cmp = icmp ugt i64 %mul, 9223372036854775800
+ %ret = or i1 %cmp, %ovf
+ ret i1 %ret
+}
+
+define i1 @umul_greater_than_or_overflow_const_disjoint(i64 %in) {
+; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_disjoint(
+; CHECK-SAME: i64 [[IN:%.*]]) {
+; CHECK-NEXT: [[TMP6:%.*]] = icmp ugt i64 [[IN]], 230584300921369395
+; CHECK-NEXT: ret i1 [[TMP6]]
+;
+ %mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 40)
+ %mul = extractvalue { i64, i1 } %mwo, 0
+ %ovf = extractvalue { i64, i1 } %mwo, 1
+ %cmp = icmp ugt i64 %mul, 9223372036854775800
+ %ret = or disjoint i1 %ovf, %cmp
+ ret i1 %ret
+}
+
+define <2 x i1> @umul_greater_than_or_overflow_const_vector_splat(<2 x i64> %in) {
+; CHECK-LABEL: define <2 x i1> @umul_greater_than_or_overflow_const_vector_splat(
+; CHECK-SAME: <2 x i64> [[IN:%.*]]) {
+; CHECK-NEXT: [[TMP6:%.*]] = icmp ugt <2 x i64> [[IN]], splat (i64 6477087104532848)
+; CHECK-NEXT: ret <2 x i1> [[TMP6]]
+;
+ %mwo = tail call { <2 x i64>, <2 x i1> } @llvm.umul.with.overflow.v2i64(<2 x i64> %in, <2 x i64> <i64 1424, i64 1424>)
+ %mul = extractvalue { <2 x i64>, <2 x i1> } %mwo, 0
+ %ovf = extractvalue { <2 x i64>, <2 x i1> } %mwo, 1
+ %cmp = icmp ugt <2 x i64> %mul, <i64 9223372036854775800, i64 9223372036854775800>
+ %ret = or <2 x i1> %ovf, %cmp
+ ret <2 x i1> %ret
+}
+
+define <4 x i1> @umul_greater_than_or_overflow_const_vector_non_splat(<4 x i64> %in) {
+; CHECK-LABEL: define <4 x i1> @umul_greater_than_or_overflow_const_vector_non_splat(
+; CHECK-SAME: <4 x i64> [[IN:%.*]]) {
+; CHECK-NEXT: [[RET:%.*]] = icmp ugt <4 x i64> [[IN]], <i64 384307168202282291, i64 6477087104532848, i64 -1, i64 0>
+; CHECK-NEXT: ret <4 x i1> [[RET]]
+;
+ %mwo = tail call { <4 x i64>, <4 x i1> } @llvm.umul.with.overflow.v2i64(<4 x i64> %in, <4 x i64> <i64 24, i64 1424, i64 0, i64 -1>)
----------------
nikic wrote:
Please also add a test with a poison element.
https://github.com/llvm/llvm-project/pull/147327
More information about the llvm-commits
mailing list