brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.5 KiB · c7a2386 Raw
363 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=instcombine -S %s | FileCheck %s3 4; Check that we simplify llvm.umul.with.overflow, if the overflow check is5; weakened by or (icmp ne %res, 0) %overflow. This is generated by code using6; __builtin_mul_overflow with negative integer constants, e.g.7 8;   bool test(unsigned long long v, unsigned long long *res) {9;     return __builtin_mul_overflow(v, -4775807LL, res);10;   }11 12declare { i64, i1 } @llvm.umul.with.overflow.i64(i64, i64) #013 14define i1 @test1(i64 %a, i64 %b, ptr %ptr) {15; CHECK-LABEL: @test1(16; CHECK-NEXT:    [[MUL:%.*]] = mul i64 [[A:%.*]], [[B:%.*]]17; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A]], 018; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i64 [[B]], 019; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = and i1 [[TMP1]], [[TMP2]]20; CHECK-NEXT:    store i64 [[MUL]], ptr [[PTR:%.*]], align 821; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]22;23 24  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)25  %overflow = extractvalue { i64, i1 } %res, 126  %mul = extractvalue { i64, i1 } %res, 027  %cmp  = icmp ne i64 %mul, 028  %overflow.1 = or i1 %overflow, %cmp29  store i64 %mul, ptr %ptr, align 830  ret i1 %overflow.131}32 33define i1 @test1_logical(i64 %a, i64 %b, ptr %ptr) {34; CHECK-LABEL: @test1_logical(35; CHECK-NEXT:    [[MUL:%.*]] = mul i64 [[A:%.*]], [[B:%.*]]36; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A]], 037; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i64 [[B]], 038; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = and i1 [[TMP1]], [[TMP2]]39; CHECK-NEXT:    store i64 [[MUL]], ptr [[PTR:%.*]], align 840; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]41;42 43  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)44  %overflow = extractvalue { i64, i1 } %res, 145  %mul = extractvalue { i64, i1 } %res, 046  %cmp  = icmp ne i64 %mul, 047  %overflow.1 = select i1 %overflow, i1 true, i1 %cmp48  store i64 %mul, ptr %ptr, align 849  ret i1 %overflow.150}51 52define i1 @test1_or_ops_swapped(i64 %a, i64 %b, ptr %ptr) {53; CHECK-LABEL: @test1_or_ops_swapped(54; CHECK-NEXT:    [[MUL:%.*]] = mul i64 [[A:%.*]], [[B:%.*]]55; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A]], 056; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i64 [[B]], 057; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = and i1 [[TMP1]], [[TMP2]]58; CHECK-NEXT:    store i64 [[MUL]], ptr [[PTR:%.*]], align 859; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]60;61 62 63  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)64  %overflow = extractvalue { i64, i1 } %res, 165  %mul = extractvalue { i64, i1 } %res, 066  %cmp  = icmp ne i64 %mul, 067  %overflow.1 = or i1 %cmp, %overflow68  store i64 %mul, ptr %ptr, align 869  ret i1 %overflow.170}71 72define i1 @test1_or_ops_swapped_logical(i64 %a, i64 %b, ptr %ptr) {73; CHECK-LABEL: @test1_or_ops_swapped_logical(74; CHECK-NEXT:    [[MUL:%.*]] = mul i64 [[A:%.*]], [[B:%.*]]75; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A]], 076; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i64 [[B]], 077; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = and i1 [[TMP1]], [[TMP2]]78; CHECK-NEXT:    store i64 [[MUL]], ptr [[PTR:%.*]], align 879; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]80;81 82 83  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)84  %overflow = extractvalue { i64, i1 } %res, 185  %mul = extractvalue { i64, i1 } %res, 086  %cmp  = icmp ne i64 %mul, 087  %overflow.1 = select i1 %cmp, i1 true, i1 %overflow88  store i64 %mul, ptr %ptr, align 889  ret i1 %overflow.190}91 92define i1 @test2(i64 %a, i64 %b, ptr %ptr) {93; CHECK-LABEL: @test2(94; CHECK-NEXT:    [[MUL:%.*]] = mul i64 [[A:%.*]], [[B:%.*]]95; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A]], 096; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i64 [[B]], 097; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = and i1 [[TMP1]], [[TMP2]]98; CHECK-NEXT:    [[NEG:%.*]] = sub i64 0, [[MUL]]99; CHECK-NEXT:    store i64 [[NEG]], ptr [[PTR:%.*]], align 8100; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]101;102 103  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)104  %overflow = extractvalue { i64, i1 } %res, 1105  %mul = extractvalue { i64, i1 } %res, 0106  %cmp = icmp ne i64 %mul, 0107  %overflow.1 = or i1 %overflow, %cmp108  %neg = sub i64 0, %mul109  store i64 %neg, ptr %ptr, align 8110  ret i1 %overflow.1111}112 113define i1 @test2_logical(i64 %a, i64 %b, ptr %ptr) {114; CHECK-LABEL: @test2_logical(115; CHECK-NEXT:    [[MUL:%.*]] = mul i64 [[A:%.*]], [[B:%.*]]116; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A]], 0117; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i64 [[B]], 0118; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = and i1 [[TMP1]], [[TMP2]]119; CHECK-NEXT:    [[NEG:%.*]] = sub i64 0, [[MUL]]120; CHECK-NEXT:    store i64 [[NEG]], ptr [[PTR:%.*]], align 8121; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]122;123 124  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)125  %overflow = extractvalue { i64, i1 } %res, 1126  %mul = extractvalue { i64, i1 } %res, 0127  %cmp = icmp ne i64 %mul, 0128  %overflow.1 = select i1 %overflow, i1 true, i1 %cmp129  %neg = sub i64 0, %mul130  store i64 %neg, ptr %ptr, align 8131  ret i1 %overflow.1132}133 134declare void @use(i1)135 136define i1 @test3_multiple_overflow_users(i64 %a, i64 %b, ptr %ptr) {137; CHECK-LABEL: @test3_multiple_overflow_users(138; CHECK-NEXT:    [[RES:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[A:%.*]], i64 [[B:%.*]])139; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[RES]], 1140; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A]], 0141; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i64 [[B]], 0142; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = and i1 [[TMP1]], [[TMP2]]143; CHECK-NEXT:    call void @use(i1 [[OVERFLOW]])144; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]145;146  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)147  %overflow = extractvalue { i64, i1 } %res, 1148  %mul = extractvalue { i64, i1 } %res, 0149  %cmp = icmp ne i64 %mul, 0150  %overflow.1 = or i1 %overflow, %cmp151  call void @use(i1 %overflow)152  ret i1 %overflow.1153}154 155define i1 @test3_multiple_overflow_users_logical(i64 %a, i64 %b, ptr %ptr) {156; CHECK-LABEL: @test3_multiple_overflow_users_logical(157; CHECK-NEXT:    [[RES:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[A:%.*]], i64 [[B:%.*]])158; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[RES]], 1159; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A]], 0160; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i64 [[B]], 0161; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = and i1 [[TMP1]], [[TMP2]]162; CHECK-NEXT:    call void @use(i1 [[OVERFLOW]])163; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]164;165  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)166  %overflow = extractvalue { i64, i1 } %res, 1167  %mul = extractvalue { i64, i1 } %res, 0168  %cmp = icmp ne i64 %mul, 0169  %overflow.1 = select i1 %overflow, i1 true, i1 %cmp170  call void @use(i1 %overflow)171  ret i1 %overflow.1172}173 174; Do not simplify if %overflow and %mul have multiple uses.175define i1 @test3_multiple_overflow_and_mul_users(i64 %a, i64 %b, ptr %ptr) {176; CHECK-LABEL: @test3_multiple_overflow_and_mul_users(177; CHECK-NEXT:    [[RES:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[A:%.*]], i64 [[B:%.*]])178; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[RES]], 1179; CHECK-NEXT:    [[MUL:%.*]] = extractvalue { i64, i1 } [[RES]], 0180; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i64 [[MUL]], 0181; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = or i1 [[OVERFLOW]], [[CMP]]182; CHECK-NEXT:    [[NEG:%.*]] = sub i64 0, [[MUL]]183; CHECK-NEXT:    store i64 [[NEG]], ptr [[PTR:%.*]], align 8184; CHECK-NEXT:    call void @use(i1 [[OVERFLOW]])185; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]186;187  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)188  %overflow = extractvalue { i64, i1 } %res, 1189  %mul = extractvalue { i64, i1 } %res, 0190  %cmp = icmp ne i64 %mul, 0191  %overflow.1 = or i1 %overflow, %cmp192  %neg = sub i64 0, %mul193  store i64 %neg, ptr %ptr, align 8194  call void @use(i1 %overflow)195  ret i1 %overflow.1196}197 198define i1 @test3_multiple_overflow_and_mul_users_logical(i64 %a, i64 %b, ptr %ptr) {199; CHECK-LABEL: @test3_multiple_overflow_and_mul_users_logical(200; CHECK-NEXT:    [[RES:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[A:%.*]], i64 [[B:%.*]])201; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[RES]], 1202; CHECK-NEXT:    [[MUL:%.*]] = extractvalue { i64, i1 } [[RES]], 0203; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i64 [[MUL]], 0204; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = or i1 [[OVERFLOW]], [[CMP]]205; CHECK-NEXT:    [[NEG:%.*]] = sub i64 0, [[MUL]]206; CHECK-NEXT:    store i64 [[NEG]], ptr [[PTR:%.*]], align 8207; CHECK-NEXT:    call void @use(i1 [[OVERFLOW]])208; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]209;210  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)211  %overflow = extractvalue { i64, i1 } %res, 1212  %mul = extractvalue { i64, i1 } %res, 0213  %cmp = icmp ne i64 %mul, 0214  %overflow.1 = select i1 %overflow, i1 true, i1 %cmp215  %neg = sub i64 0, %mul216  store i64 %neg, ptr %ptr, align 8217  call void @use(i1 %overflow)218  ret i1 %overflow.1219}220 221 222declare void @use.2({ i64, i1 })223define i1 @test3_multiple_res_users(i64 %a, i64 %b, ptr %ptr) {224; CHECK-LABEL: @test3_multiple_res_users(225; CHECK-NEXT:    [[RES:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[A:%.*]], i64 [[B:%.*]])226; CHECK-NEXT:    [[MUL:%.*]] = extractvalue { i64, i1 } [[RES]], 0227; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A]], 0228; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i64 [[B]], 0229; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = and i1 [[TMP1]], [[TMP2]]230; CHECK-NEXT:    [[NEG:%.*]] = sub i64 0, [[MUL]]231; CHECK-NEXT:    store i64 [[NEG]], ptr [[PTR:%.*]], align 8232; CHECK-NEXT:    call void @use.2({ i64, i1 } [[RES]])233; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]234;235  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)236  %overflow = extractvalue { i64, i1 } %res, 1237  %mul = extractvalue { i64, i1 } %res, 0238  %cmp = icmp ne i64 %mul, 0239  %overflow.1 = or i1 %overflow, %cmp240  %neg = sub i64 0, %mul241  store i64 %neg, ptr %ptr, align 8242  call void @use.2({ i64, i1 } %res)243  ret i1 %overflow.1244}245 246define i1 @test3_multiple_res_users_logical(i64 %a, i64 %b, ptr %ptr) {247; CHECK-LABEL: @test3_multiple_res_users_logical(248; CHECK-NEXT:    [[RES:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[A:%.*]], i64 [[B:%.*]])249; CHECK-NEXT:    [[MUL:%.*]] = extractvalue { i64, i1 } [[RES]], 0250; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A]], 0251; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i64 [[B]], 0252; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = and i1 [[TMP1]], [[TMP2]]253; CHECK-NEXT:    [[NEG:%.*]] = sub i64 0, [[MUL]]254; CHECK-NEXT:    store i64 [[NEG]], ptr [[PTR:%.*]], align 8255; CHECK-NEXT:    call void @use.2({ i64, i1 } [[RES]])256; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]257;258  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)259  %overflow = extractvalue { i64, i1 } %res, 1260  %mul = extractvalue { i64, i1 } %res, 0261  %cmp = icmp ne i64 %mul, 0262  %overflow.1 = select i1 %overflow, i1 true, i1 %cmp263  %neg = sub i64 0, %mul264  store i64 %neg, ptr %ptr, align 8265  call void @use.2({ i64, i1 } %res)266  ret i1 %overflow.1267}268 269declare void @use.3(i64)270 271; Simplify if %mul has multiple uses.272define i1 @test3_multiple_mul_users(i64 %a, i64 %b, ptr %ptr) {273; CHECK-LABEL: @test3_multiple_mul_users(274; CHECK-NEXT:    [[MUL:%.*]] = mul i64 [[A:%.*]], [[B:%.*]]275; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A]], 0276; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i64 [[B]], 0277; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = and i1 [[TMP1]], [[TMP2]]278; CHECK-NEXT:    [[NEG:%.*]] = sub i64 0, [[MUL]]279; CHECK-NEXT:    store i64 [[NEG]], ptr [[PTR:%.*]], align 8280; CHECK-NEXT:    call void @use.3(i64 [[MUL]])281; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]282;283 284  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)285  %overflow = extractvalue { i64, i1 } %res, 1286  %mul = extractvalue { i64, i1 } %res, 0287  %cmp = icmp ne i64 %mul, 0288  %overflow.1 = or i1 %overflow, %cmp289  %neg = sub i64 0, %mul290  store i64 %neg, ptr %ptr, align 8291  call void @use.3(i64 %mul)292  ret i1 %overflow.1293}294 295define i1 @test3_multiple_mul_users_logical(i64 %a, i64 %b, ptr %ptr) {296; CHECK-LABEL: @test3_multiple_mul_users_logical(297; CHECK-NEXT:    [[MUL:%.*]] = mul i64 [[A:%.*]], [[B:%.*]]298; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A]], 0299; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i64 [[B]], 0300; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = and i1 [[TMP1]], [[TMP2]]301; CHECK-NEXT:    [[NEG:%.*]] = sub i64 0, [[MUL]]302; CHECK-NEXT:    store i64 [[NEG]], ptr [[PTR:%.*]], align 8303; CHECK-NEXT:    call void @use.3(i64 [[MUL]])304; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]305;306 307  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)308  %overflow = extractvalue { i64, i1 } %res, 1309  %mul = extractvalue { i64, i1 } %res, 0310  %cmp = icmp ne i64 %mul, 0311  %overflow.1 = select i1 %overflow, i1 true, i1 %cmp312  %neg = sub i64 0, %mul313  store i64 %neg, ptr %ptr, align 8314  call void @use.3(i64 %mul)315  ret i1 %overflow.1316}317 318 319 320define i1 @test4_no_icmp_ne(i64 %a, i64 %b, ptr %ptr) {321; CHECK-LABEL: @test4_no_icmp_ne(322; CHECK-NEXT:    [[RES:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[A:%.*]], i64 [[B:%.*]])323; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[RES]], 1324; CHECK-NEXT:    [[MUL:%.*]] = extractvalue { i64, i1 } [[RES]], 0325; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[MUL]], 0326; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = or i1 [[OVERFLOW]], [[CMP]]327; CHECK-NEXT:    [[NEG:%.*]] = sub i64 0, [[MUL]]328; CHECK-NEXT:    store i64 [[NEG]], ptr [[PTR:%.*]], align 8329; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]330;331  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)332  %overflow = extractvalue { i64, i1 } %res, 1333  %mul = extractvalue { i64, i1 } %res, 0334  %cmp = icmp sgt i64 %mul, 0335  %overflow.1 = or i1 %overflow, %cmp336  %neg = sub i64 0, %mul337  store i64 %neg, ptr %ptr, align 8338  ret i1 %overflow.1339}340 341define i1 @test4_no_icmp_ne_logical(i64 %a, i64 %b, ptr %ptr) {342; CHECK-LABEL: @test4_no_icmp_ne_logical(343; CHECK-NEXT:    [[RES:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[A:%.*]], i64 [[B:%.*]])344; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[RES]], 1345; CHECK-NEXT:    [[MUL:%.*]] = extractvalue { i64, i1 } [[RES]], 0346; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[MUL]], 0347; CHECK-NEXT:    [[OVERFLOW_1:%.*]] = or i1 [[OVERFLOW]], [[CMP]]348; CHECK-NEXT:    [[NEG:%.*]] = sub i64 0, [[MUL]]349; CHECK-NEXT:    store i64 [[NEG]], ptr [[PTR:%.*]], align 8350; CHECK-NEXT:    ret i1 [[OVERFLOW_1]]351;352  %res = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)353  %overflow = extractvalue { i64, i1 } %res, 1354  %mul = extractvalue { i64, i1 } %res, 0355  %cmp = icmp sgt i64 %mul, 0356  %overflow.1 = select i1 %overflow, i1 true, i1 %cmp357  %neg = sub i64 0, %mul358  store i64 %neg, ptr %ptr, align 8359  ret i1 %overflow.1360}361 362attributes #0 = { nounwind readnone speculatable willreturn }363