blob: 13c7fce38ef015868bf9b4cb2feee8bdc007b701 [file] [log] [blame]
; 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 i1 @umul_greater_than_or_overflow_const_multiuse_mul(i64 %in) {
; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_multiuse_mul(
; CHECK-SAME: i64 [[IN:%.*]]) {
; CHECK-NEXT: [[MUL:%.*]] = mul i64 [[IN]], 48
; CHECK-NEXT: [[RET:%.*]] = icmp ugt i64 [[IN]], 192153584101141162
; CHECK-NEXT: tail call void @use.i64(i64 [[MUL]])
; CHECK-NEXT: ret i1 [[RET]]
;
%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 %ovf, %cmp
tail call void @use.i64(i64 %mul)
ret i1 %ret
}
define i1 @umul_greater_than_or_overflow_const_multiuse_overflow(i64 %in) {
; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_multiuse_overflow(
; CHECK-SAME: i64 [[IN:%.*]]) {
; CHECK-NEXT: [[OVF:%.*]] = icmp ugt i64 [[IN]], 384307168202282325
; CHECK-NEXT: [[RET:%.*]] = icmp ugt i64 [[IN]], 192153584101141162
; CHECK-NEXT: tail call void @use.i1(i1 [[OVF]])
; CHECK-NEXT: ret i1 [[RET]]
;
%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 %ovf, %cmp
tail call void @use.i1(i1 %ovf)
ret i1 %ret
}
define i1 @umul_greater_than_or_overflow_const_multiuse_umul_call(i64 %in) {
; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_multiuse_umul_call(
; CHECK-SAME: i64 [[IN:%.*]]) {
; CHECK-NEXT: [[MWO:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 48)
; CHECK-NEXT: [[RET:%.*]] = icmp ugt i64 [[IN]], 192153584101141162
; CHECK-NEXT: tail call void @use.i64i1({ i64, i1 } [[MWO]])
; CHECK-NEXT: ret i1 [[RET]]
;
%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 %ovf, %cmp
tail call void @use.i64i1({ i64, i1 } %mwo)
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
}
; Negative test
define <4 x i1> @umul_greater_than_or_overflow_const_vector_non_splat_negative(<4 x i64> %in) {
; CHECK-LABEL: define <4 x i1> @umul_greater_than_or_overflow_const_vector_non_splat_negative(
; CHECK-SAME: <4 x i64> [[IN:%.*]]) {
; CHECK-NEXT: [[MWO:%.*]] = tail call { <4 x i64>, <4 x i1> } @llvm.umul.with.overflow.v4i64(<4 x i64> [[IN]], <4 x i64> <i64 24, i64 1424, i64 0, i64 -1>)
; CHECK-NEXT: [[MUL:%.*]] = extractvalue { <4 x i64>, <4 x i1> } [[MWO]], 0
; CHECK-NEXT: [[OVF:%.*]] = extractvalue { <4 x i64>, <4 x i1> } [[MWO]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <4 x i64> [[MUL]], <i64 9223372036854775000, i64 9223372036854775800, i64 -16, i64 -16>
; CHECK-NEXT: [[RET:%.*]] = or <4 x i1> [[OVF]], [[CMP]]
; 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>)
%mul = extractvalue { <4 x i64>, <4 x i1> } %mwo, 0
%ovf = extractvalue { <4 x i64>, <4 x i1> } %mwo, 1
%cmp = icmp ugt <4 x i64> %mul, <i64 9223372036854775000, i64 9223372036854775800, i64 -16, i64 -16>
%ret = or <4 x i1> %ovf, %cmp
ret <4 x i1> %ret
}
; Negative test
define <2 x i1> @umul_greater_than_or_overflow_const_vector_poison_non_splat_negative(<2 x i64> %in) {
; CHECK-LABEL: define <2 x i1> @umul_greater_than_or_overflow_const_vector_poison_non_splat_negative(
; CHECK-SAME: <2 x i64> [[IN:%.*]]) {
; CHECK-NEXT: [[MWO:%.*]] = tail call { <2 x i64>, <2 x i1> } @llvm.umul.with.overflow.v2i64(<2 x i64> [[IN]], <2 x i64> <i64 poison, i64 1424>)
; CHECK-NEXT: [[MUL:%.*]] = extractvalue { <2 x i64>, <2 x i1> } [[MWO]], 0
; CHECK-NEXT: [[OVF:%.*]] = extractvalue { <2 x i64>, <2 x i1> } [[MWO]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i64> [[MUL]], <i64 9223372036854775800, i64 poison>
; CHECK-NEXT: [[RET:%.*]] = or <2 x i1> [[OVF]], [[CMP]]
; CHECK-NEXT: ret <2 x i1> [[RET]]
;
%mwo = tail call { <2 x i64>, <2 x i1> } @llvm.umul.with.overflow.v2i64(<2 x i64> %in, <2 x i64> <i64 poison, 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 poison>
%ret = or <2 x i1> %ovf, %cmp
ret <2 x i1> %ret
}
; Negative test
define i1 @umul_greater_than_and_overflow_const_negative(i64 %in) {
; CHECK-LABEL: define i1 @umul_greater_than_and_overflow_const_negative(
; CHECK-SAME: i64 [[IN:%.*]]) {
; CHECK-NEXT: [[TMP2:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 48)
; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0
; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1
; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i64 [[TMP3]], 9223372036854775800
; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[TMP4]], [[TMP5]]
; 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 ult i64 %mul, 9223372036854775800
%ret = and i1 %ovf, %cmp
ret i1 %ret
}
; Negative test
define i1 @umul_less_than_or_overflow_const_negative(i64 %in) {
; CHECK-LABEL: define i1 @umul_less_than_or_overflow_const_negative(
; CHECK-SAME: i64 [[IN:%.*]]) {
; CHECK-NEXT: [[TMP2:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 48)
; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0
; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1
; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i64 [[TMP3]], 9223372036854775800
; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]]
; 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 ult i64 %mul, 9223372036854775800
%ret = or i1 %ovf, %cmp
ret i1 %ret
}
; Negative test
define i1 @umul_greater_than_or_overflow_const_multiuse_icmp_negative(i64 %in) {
; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_multiuse_icmp_negative(
; CHECK-SAME: i64 [[IN:%.*]]) {
; CHECK-NEXT: [[TMP2:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 48)
; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0
; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1
; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt i64 [[TMP3]], 9223372036854775800
; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]]
; CHECK-NEXT: tail call void @use.i1(i1 [[TMP5]])
; 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 %ovf, %cmp
tail call void @use.i1(i1 %cmp)
ret i1 %ret
}
; Negative test. The umul.with.overflow should be folded away before.
define i1 @umul_greater_than_or_overflow_const_0_negative(i64 %in) {
; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_0_negative(
; CHECK-SAME: i64 [[IN:%.*]]) {
; CHECK-NEXT: ret i1 false
;
%mwo = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 0)
%mul = extractvalue { i64, i1 } %mwo, 0
%ovf = extractvalue { i64, i1 } %mwo, 1
%cmp = icmp ugt i64 %mul, 0
%ret = or i1 %ovf, %cmp
ret i1 %ret
}