239 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 52; RUN: opt -S -passes=instcombine < %s | FileCheck %s3 4declare void @use.i1(i1 %x)5declare void @use.i64(i64 %x)6declare void @use.i64i1({i64, i1} %x)7 8define i1 @umul_greater_than_or_overflow_const(i64 %in) {9; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const(10; CHECK-SAME: i64 [[IN:%.*]]) {11; CHECK-NEXT: [[TMP6:%.*]] = icmp ugt i64 [[IN]], 10980204805779495012; CHECK-NEXT: ret i1 [[TMP6]]13;14 %mwo = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 168)15 %mul = extractvalue { i64, i1 } %mwo, 016 %ovf = extractvalue { i64, i1 } %mwo, 117 %cmp = icmp ugt i64 %mul, -1618 %ret = or i1 %ovf, %cmp19 ret i1 %ret20}21 22define i1 @umul_greater_than_or_overflow_const_i8(i8 %in) {23; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_i8(24; CHECK-SAME: i8 [[IN:%.*]]) {25; CHECK-NEXT: [[TMP6:%.*]] = icmp ugt i8 [[IN]], 1026; CHECK-NEXT: ret i1 [[TMP6]]27;28 %mwo = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %in, i8 24)29 %mul = extractvalue { i8, i1 } %mwo, 030 %ovf = extractvalue { i8, i1 } %mwo, 131 %cmp = icmp ugt i8 %mul, -1632 %ret = or i1 %ovf, %cmp33 ret i1 %ret34}35 36define i1 @umul_greater_than_or_overflow_const_commuted(i64 %in) {37; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_commuted(38; CHECK-SAME: i64 [[IN:%.*]]) {39; CHECK-NEXT: [[TMP6:%.*]] = icmp ugt i64 [[IN]], 19215358410114116240; CHECK-NEXT: ret i1 [[TMP6]]41;42 %mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 48)43 %mul = extractvalue { i64, i1 } %mwo, 044 %ovf = extractvalue { i64, i1 } %mwo, 145 %cmp = icmp ugt i64 %mul, 922337203685477580046 %ret = or i1 %cmp, %ovf47 ret i1 %ret48}49 50define i1 @umul_greater_than_or_overflow_const_disjoint(i64 %in) {51; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_disjoint(52; CHECK-SAME: i64 [[IN:%.*]]) {53; CHECK-NEXT: [[TMP6:%.*]] = icmp ugt i64 [[IN]], 23058430092136939554; CHECK-NEXT: ret i1 [[TMP6]]55;56 %mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 40)57 %mul = extractvalue { i64, i1 } %mwo, 058 %ovf = extractvalue { i64, i1 } %mwo, 159 %cmp = icmp ugt i64 %mul, 922337203685477580060 %ret = or disjoint i1 %ovf, %cmp61 ret i1 %ret62}63 64define i1 @umul_greater_than_or_overflow_const_multiuse_mul(i64 %in) {65; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_multiuse_mul(66; CHECK-SAME: i64 [[IN:%.*]]) {67; CHECK-NEXT: [[MUL:%.*]] = mul i64 [[IN]], 4868; CHECK-NEXT: [[RET:%.*]] = icmp ugt i64 [[IN]], 19215358410114116269; CHECK-NEXT: tail call void @use.i64(i64 [[MUL]])70; CHECK-NEXT: ret i1 [[RET]]71;72 %mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 48)73 %mul = extractvalue { i64, i1 } %mwo, 074 %ovf = extractvalue { i64, i1 } %mwo, 175 %cmp = icmp ugt i64 %mul, 922337203685477580076 %ret = or i1 %ovf, %cmp77 tail call void @use.i64(i64 %mul)78 ret i1 %ret79}80 81define i1 @umul_greater_than_or_overflow_const_multiuse_overflow(i64 %in) {82; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_multiuse_overflow(83; CHECK-SAME: i64 [[IN:%.*]]) {84; CHECK-NEXT: [[OVF:%.*]] = icmp ugt i64 [[IN]], 38430716820228232585; CHECK-NEXT: [[RET:%.*]] = icmp ugt i64 [[IN]], 19215358410114116286; CHECK-NEXT: tail call void @use.i1(i1 [[OVF]])87; CHECK-NEXT: ret i1 [[RET]]88;89 %mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 48)90 %mul = extractvalue { i64, i1 } %mwo, 091 %ovf = extractvalue { i64, i1 } %mwo, 192 %cmp = icmp ugt i64 %mul, 922337203685477580093 %ret = or i1 %ovf, %cmp94 tail call void @use.i1(i1 %ovf)95 ret i1 %ret96}97 98define i1 @umul_greater_than_or_overflow_const_multiuse_umul_call(i64 %in) {99; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_multiuse_umul_call(100; CHECK-SAME: i64 [[IN:%.*]]) {101; CHECK-NEXT: [[MWO:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 48)102; CHECK-NEXT: [[RET:%.*]] = icmp ugt i64 [[IN]], 192153584101141162103; CHECK-NEXT: tail call void @use.i64i1({ i64, i1 } [[MWO]])104; CHECK-NEXT: ret i1 [[RET]]105;106 %mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 48)107 %mul = extractvalue { i64, i1 } %mwo, 0108 %ovf = extractvalue { i64, i1 } %mwo, 1109 %cmp = icmp ugt i64 %mul, 9223372036854775800110 %ret = or i1 %ovf, %cmp111 tail call void @use.i64i1({ i64, i1 } %mwo)112 ret i1 %ret113}114 115define <2 x i1> @umul_greater_than_or_overflow_const_vector_splat(<2 x i64> %in) {116; CHECK-LABEL: define <2 x i1> @umul_greater_than_or_overflow_const_vector_splat(117; CHECK-SAME: <2 x i64> [[IN:%.*]]) {118; CHECK-NEXT: [[TMP6:%.*]] = icmp ugt <2 x i64> [[IN]], splat (i64 6477087104532848)119; CHECK-NEXT: ret <2 x i1> [[TMP6]]120;121 %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>)122 %mul = extractvalue { <2 x i64>, <2 x i1> } %mwo, 0123 %ovf = extractvalue { <2 x i64>, <2 x i1> } %mwo, 1124 %cmp = icmp ugt <2 x i64> %mul, <i64 9223372036854775800, i64 9223372036854775800>125 %ret = or <2 x i1> %ovf, %cmp126 ret <2 x i1> %ret127}128 129; Negative test130define <4 x i1> @umul_greater_than_or_overflow_const_vector_non_splat_negative(<4 x i64> %in) {131; CHECK-LABEL: define <4 x i1> @umul_greater_than_or_overflow_const_vector_non_splat_negative(132; CHECK-SAME: <4 x i64> [[IN:%.*]]) {133; 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>)134; CHECK-NEXT: [[MUL:%.*]] = extractvalue { <4 x i64>, <4 x i1> } [[MWO]], 0135; CHECK-NEXT: [[OVF:%.*]] = extractvalue { <4 x i64>, <4 x i1> } [[MWO]], 1136; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <4 x i64> [[MUL]], <i64 9223372036854775000, i64 9223372036854775800, i64 -16, i64 -16>137; CHECK-NEXT: [[RET:%.*]] = or <4 x i1> [[OVF]], [[CMP]]138; CHECK-NEXT: ret <4 x i1> [[RET]]139;140 %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>)141 %mul = extractvalue { <4 x i64>, <4 x i1> } %mwo, 0142 %ovf = extractvalue { <4 x i64>, <4 x i1> } %mwo, 1143 %cmp = icmp ugt <4 x i64> %mul, <i64 9223372036854775000, i64 9223372036854775800, i64 -16, i64 -16>144 %ret = or <4 x i1> %ovf, %cmp145 ret <4 x i1> %ret146}147 148; Negative test149define <2 x i1> @umul_greater_than_or_overflow_const_vector_poison_non_splat_negative(<2 x i64> %in) {150; CHECK-LABEL: define <2 x i1> @umul_greater_than_or_overflow_const_vector_poison_non_splat_negative(151; CHECK-SAME: <2 x i64> [[IN:%.*]]) {152; 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>)153; CHECK-NEXT: [[MUL:%.*]] = extractvalue { <2 x i64>, <2 x i1> } [[MWO]], 0154; CHECK-NEXT: [[OVF:%.*]] = extractvalue { <2 x i64>, <2 x i1> } [[MWO]], 1155; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i64> [[MUL]], <i64 9223372036854775800, i64 poison>156; CHECK-NEXT: [[RET:%.*]] = or <2 x i1> [[OVF]], [[CMP]]157; CHECK-NEXT: ret <2 x i1> [[RET]]158;159 %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>)160 %mul = extractvalue { <2 x i64>, <2 x i1> } %mwo, 0161 %ovf = extractvalue { <2 x i64>, <2 x i1> } %mwo, 1162 %cmp = icmp ugt <2 x i64> %mul, <i64 9223372036854775800, i64 poison>163 %ret = or <2 x i1> %ovf, %cmp164 ret <2 x i1> %ret165}166 167; Negative test168define i1 @umul_greater_than_and_overflow_const_negative(i64 %in) {169; CHECK-LABEL: define i1 @umul_greater_than_and_overflow_const_negative(170; CHECK-SAME: i64 [[IN:%.*]]) {171; CHECK-NEXT: [[TMP2:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 48)172; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0173; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1174; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i64 [[TMP3]], 9223372036854775800175; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[TMP4]], [[TMP5]]176; CHECK-NEXT: ret i1 [[TMP6]]177;178 %mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 48)179 %mul = extractvalue { i64, i1 } %mwo, 0180 %ovf = extractvalue { i64, i1 } %mwo, 1181 %cmp = icmp ult i64 %mul, 9223372036854775800182 %ret = and i1 %ovf, %cmp183 ret i1 %ret184}185 186; Negative test187define i1 @umul_less_than_or_overflow_const_negative(i64 %in) {188; CHECK-LABEL: define i1 @umul_less_than_or_overflow_const_negative(189; CHECK-SAME: i64 [[IN:%.*]]) {190; CHECK-NEXT: [[TMP2:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 48)191; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0192; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1193; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i64 [[TMP3]], 9223372036854775800194; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]]195; CHECK-NEXT: ret i1 [[TMP6]]196;197 %mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 48)198 %mul = extractvalue { i64, i1 } %mwo, 0199 %ovf = extractvalue { i64, i1 } %mwo, 1200 %cmp = icmp ult i64 %mul, 9223372036854775800201 %ret = or i1 %ovf, %cmp202 ret i1 %ret203}204 205; Negative test206define i1 @umul_greater_than_or_overflow_const_multiuse_icmp_negative(i64 %in) {207; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_multiuse_icmp_negative(208; CHECK-SAME: i64 [[IN:%.*]]) {209; CHECK-NEXT: [[TMP2:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 48)210; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0211; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1212; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt i64 [[TMP3]], 9223372036854775800213; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]]214; CHECK-NEXT: tail call void @use.i1(i1 [[TMP5]])215; CHECK-NEXT: ret i1 [[TMP6]]216;217 %mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 48)218 %mul = extractvalue { i64, i1 } %mwo, 0219 %ovf = extractvalue { i64, i1 } %mwo, 1220 %cmp = icmp ugt i64 %mul, 9223372036854775800221 %ret = or i1 %ovf, %cmp222 tail call void @use.i1(i1 %cmp)223 ret i1 %ret224}225 226; Negative test. The umul.with.overflow should be folded away before.227define i1 @umul_greater_than_or_overflow_const_0_negative(i64 %in) {228; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_0_negative(229; CHECK-SAME: i64 [[IN:%.*]]) {230; CHECK-NEXT: ret i1 false231;232 %mwo = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 0)233 %mul = extractvalue { i64, i1 } %mwo, 0234 %ovf = extractvalue { i64, i1 } %mwo, 1235 %cmp = icmp ugt i64 %mul, 0236 %ret = or i1 %ovf, %cmp237 ret i1 %ret238}239