515 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals --version 22; RUN: opt -passes=gvn -S < %s | FileCheck %s3 4declare void @use.ptr(ptr) memory(none)5declare void @use.i64(i64) memory(none)6declare void @use.i32(i32) memory(none)7 8define i32 @test1(ptr %p) {9; CHECK-LABEL: define i32 @test110; CHECK-SAME: (ptr [[P:%.*]]) {11; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG0:![0-9]+]]12; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]]13; CHECK-NEXT: ret i32 [[C]]14;15 %a = load i32, ptr %p, !range !016 %b = load i32, ptr %p, !range !017 %c = add i32 %a, %b18 ret i32 %c19}20 21define i32 @test2(ptr %p) {22; CHECK-LABEL: define i32 @test223; CHECK-SAME: (ptr [[P:%.*]]) {24; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 425; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]]26; CHECK-NEXT: ret i32 [[C]]27;28 %a = load i32, ptr %p, !range !029 %b = load i32, ptr %p30 %c = add i32 %a, %b31 ret i32 %c32}33 34define i32 @test3(ptr %p) {35; CHECK-LABEL: define i32 @test336; CHECK-SAME: (ptr [[P:%.*]]) {37; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG1:![0-9]+]]38; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]]39; CHECK-NEXT: ret i32 [[C]]40;41 %a = load i32, ptr %p, !range !042 %b = load i32, ptr %p, !range !143 %c = add i32 %a, %b44 ret i32 %c45}46 47define i32 @test4(ptr %p) {48; CHECK-LABEL: define i32 @test449; CHECK-SAME: (ptr [[P:%.*]]) {50; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG2:![0-9]+]]51; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]]52; CHECK-NEXT: ret i32 [[C]]53;54 %a = load i32, ptr %p, !range !055 %b = load i32, ptr %p, !range !256 %c = add i32 %a, %b57 ret i32 %c58}59 60define i32 @test5(ptr %p) {61; CHECK-LABEL: define i32 @test562; CHECK-SAME: (ptr [[P:%.*]]) {63; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG3:![0-9]+]]64; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]]65; CHECK-NEXT: ret i32 [[C]]66;67 %a = load i32, ptr %p, !range !368 %b = load i32, ptr %p, !range !469 %c = add i32 %a, %b70 ret i32 %c71}72 73define i32 @test6(ptr %p) {74; CHECK-LABEL: define i32 @test675; CHECK-SAME: (ptr [[P:%.*]]) {76; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG4:![0-9]+]]77; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]]78; CHECK-NEXT: ret i32 [[C]]79;80 %a = load i32, ptr %p, !range !581 %b = load i32, ptr %p, !range !682 %c = add i32 %a, %b83 ret i32 %c84}85 86define i32 @test7(ptr %p) {87; CHECK-LABEL: define i32 @test788; CHECK-SAME: (ptr [[P:%.*]]) {89; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG5:![0-9]+]]90; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]]91; CHECK-NEXT: ret i32 [[C]]92;93 %a = load i32, ptr %p, !range !794 %b = load i32, ptr %p, !range !895 %c = add i32 %a, %b96 ret i32 %c97}98 99define i32 @test8(ptr %p) {100; CHECK-LABEL: define i32 @test8101; CHECK-SAME: (ptr [[P:%.*]]) {102; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4103; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]]104; CHECK-NEXT: ret i32 [[C]]105;106 %a = load i32, ptr %p, !range !9107 %b = load i32, ptr %p, !range !10108 %c = add i32 %a, %b109 ret i32 %c110}111 112define i32 @load_noundef_load(ptr %p) {113; CHECK-LABEL: define i32 @load_noundef_load114; CHECK-SAME: (ptr [[P:%.*]]) {115; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG0]], !noundef [[META6:![0-9]+]]116; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]]117; CHECK-NEXT: ret i32 [[C]]118;119 %a = load i32, ptr %p, !range !0, !noundef !11120 %b = load i32, ptr %p, !range !1121 %c = add i32 %a, %b122 ret i32 %c123}124 125define i32 @load_load_noundef(ptr %p) {126; CHECK-LABEL: define i32 @load_load_noundef127; CHECK-SAME: (ptr [[P:%.*]]) {128; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG1]]129; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]]130; CHECK-NEXT: ret i32 [[C]]131;132 %a = load i32, ptr %p, !range !0133 %b = load i32, ptr %p, !range !1, !noundef !11134 %c = add i32 %a, %b135 ret i32 %c136}137 138define void @load_dereferenceable_dominating(ptr %p) {139; CHECK-LABEL: define void @load_dereferenceable_dominating140; CHECK-SAME: (ptr [[P:%.*]]) {141; CHECK-NEXT: [[A:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable [[META7:![0-9]+]]142; CHECK-NEXT: call void @use.ptr(ptr [[A]])143; CHECK-NEXT: call void @use.ptr(ptr [[A]])144; CHECK-NEXT: ret void145;146 %a = load ptr, ptr %p, !dereferenceable !{i64 10}147 %b = load ptr, ptr %p148 call void @use.ptr(ptr %a)149 call void @use.ptr(ptr %b)150 ret void151}152 153define void @load_dereferenceable_not_dominating(ptr %p) {154; CHECK-LABEL: define void @load_dereferenceable_not_dominating155; CHECK-SAME: (ptr [[P:%.*]]) {156; CHECK-NEXT: [[A:%.*]] = load ptr, ptr [[P]], align 8157; CHECK-NEXT: call void @use.ptr(ptr [[A]])158; CHECK-NEXT: call void @use.ptr(ptr [[A]])159; CHECK-NEXT: ret void160;161 %a = load ptr, ptr %p162 %b = load ptr, ptr %p, !dereferenceable !{i64 10}163 call void @use.ptr(ptr %a)164 call void @use.ptr(ptr %b)165 ret void166}167 168define void @load_ptr_nonnull_to_i64(ptr %p) {169; CHECK-LABEL: define void @load_ptr_nonnull_to_i64170; CHECK-SAME: (ptr [[P:%.*]]) {171; CHECK-NEXT: [[VAL:%.*]] = load ptr, ptr [[P]], align 8172; CHECK-NEXT: [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64173; CHECK-NEXT: call void @use.i64(i64 [[VAL_INT]])174; CHECK-NEXT: call void @use.i64(i64 [[VAL_INT]])175; CHECK-NEXT: ret void176;177 %val = load ptr, ptr %p, align 8, !nonnull !{}178 %val.int = ptrtoint ptr %val to i64179 %val2 = load i64, ptr %p, align 8180 call void @use.i64(i64 %val.int)181 call void @use.i64(i64 %val2)182 ret void183}184 185define void @load_ptr_nonnull_noundef_to_i64(ptr %p) {186; CHECK-LABEL: define void @load_ptr_nonnull_noundef_to_i64187; CHECK-SAME: (ptr [[P:%.*]]) {188; CHECK-NEXT: [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !nonnull [[META6]], !noundef [[META6]]189; CHECK-NEXT: [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64190; CHECK-NEXT: call void @use.i64(i64 [[VAL_INT]])191; CHECK-NEXT: call void @use.i64(i64 [[VAL_INT]])192; CHECK-NEXT: ret void193;194 %val = load ptr, ptr %p, align 8, !nonnull !{}, !noundef !{}195 %val.int = ptrtoint ptr %val to i64196 %val2 = load i64, ptr %p, align 8197 call void @use.i64(i64 %val.int)198 call void @use.i64(i64 %val2)199 ret void200}201 202define void @load_ptr_invariant_load_to_i64(ptr %p) {203; CHECK-LABEL: define void @load_ptr_invariant_load_to_i64204; CHECK-SAME: (ptr [[P:%.*]]) {205; CHECK-NEXT: [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !invariant.load [[META6]]206; CHECK-NEXT: [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64207; CHECK-NEXT: call void @use.i64(i64 [[VAL_INT]])208; CHECK-NEXT: call void @use.i64(i64 [[VAL_INT]])209; CHECK-NEXT: ret void210;211 %val = load ptr, ptr %p, align 8, !invariant.load !{}212 %val.int = ptrtoint ptr %val to i64213 %val2 = load i64, ptr %p, align 8214 call void @use.i64(i64 %val.int)215 call void @use.i64(i64 %val2)216 ret void217}218 219define void @load_ptr_dereferenceable_to_i64(ptr %p) {220; CHECK-LABEL: define void @load_ptr_dereferenceable_to_i64221; CHECK-SAME: (ptr [[P:%.*]]) {222; CHECK-NEXT: [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable [[META7]]223; CHECK-NEXT: [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64224; CHECK-NEXT: call void @use.i64(i64 [[VAL_INT]])225; CHECK-NEXT: call void @use.i64(i64 [[VAL_INT]])226; CHECK-NEXT: ret void227;228 %val = load ptr, ptr %p, align 8, !dereferenceable !{i64 10}229 %val.int = ptrtoint ptr %val to i64230 %val2 = load i64, ptr %p, align 8231 call void @use.i64(i64 %val.int)232 call void @use.i64(i64 %val2)233 ret void234}235 236define void @load_ptr_dereferenceable_or_null_to_i64(ptr %p) {237; CHECK-LABEL: define void @load_ptr_dereferenceable_or_null_to_i64238; CHECK-SAME: (ptr [[P:%.*]]) {239; CHECK-NEXT: [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable_or_null [[META7]]240; CHECK-NEXT: [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64241; CHECK-NEXT: call void @use.i64(i64 [[VAL_INT]])242; CHECK-NEXT: call void @use.i64(i64 [[VAL_INT]])243; CHECK-NEXT: ret void244;245 %val = load ptr, ptr %p, align 8, !dereferenceable_or_null !{i64 10}246 %val.int = ptrtoint ptr %val to i64247 %val2 = load i64, ptr %p, align 8248 call void @use.i64(i64 %val.int)249 call void @use.i64(i64 %val2)250 ret void251}252 253define void @load_ptr_nonnull_to_i32(ptr %p) {254; CHECK-LABEL: define void @load_ptr_nonnull_to_i32255; CHECK-SAME: (ptr [[P:%.*]]) {256; CHECK-NEXT: [[VAL:%.*]] = load ptr, ptr [[P]], align 8257; CHECK-NEXT: [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64258; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[VAL_INT]] to i32259; CHECK-NEXT: call void @use.i64(i64 [[VAL_INT]])260; CHECK-NEXT: call void @use.i32(i32 [[TMP1]])261; CHECK-NEXT: ret void262;263 %val = load ptr, ptr %p, align 8, !nonnull !{}264 %val.int = ptrtoint ptr %val to i64265 %val2 = load i32, ptr %p, align 8266 call void @use.i64(i64 %val.int)267 call void @use.i32(i32 %val2)268 ret void269}270 271define void @load_i64_range_to_i32_range(ptr %p) {272; CHECK-LABEL: define void @load_i64_range_to_i32_range273; CHECK-SAME: (ptr [[P:%.*]]) {274; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[P]], align 8275; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[VAL]] to i32276; CHECK-NEXT: call void @use.i64(i64 [[VAL]])277; CHECK-NEXT: call void @use.i32(i32 [[TMP1]])278; CHECK-NEXT: ret void279;280 %val = load i64, ptr %p, align 8, !range !{i64 0, i64 10}281 %val2 = load i32, ptr %p, align 8, !range !{i32 0, i32 10}282 call void @use.i64(i64 %val)283 call void @use.i32(i32 %val2)284 ret void285}286 287define i64 @load_is_stored(ptr %p, ptr %p2) {288; CHECK-LABEL: define i64 @load_is_stored289; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {290; CHECK-NEXT: [[V1:%.*]] = load i64, ptr [[P]], align 4, !range [[RNG8:![0-9]+]]291; CHECK-NEXT: store i64 [[V1]], ptr [[P2]], align 4292; CHECK-NEXT: ret i64 [[V1]]293;294 %v1 = load i64, ptr %p, !range !{i64 0, i64 10}295 store i64 %v1, ptr %p2296 %v2 = load i64, ptr %p2297 ret i64 %v2298}299 300define void @non_local_dominating(i1 %c, ptr %p) {301; CHECK-LABEL: define void @non_local_dominating302; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]]) {303; CHECK-NEXT: [[V1:%.*]] = load i64, ptr [[P]], align 4, !range [[RNG9:![0-9]+]]304; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[JOIN:%.*]]305; CHECK: if:306; CHECK-NEXT: br label [[JOIN]]307; CHECK: join:308; CHECK-NEXT: call void @use.i64(i64 [[V1]])309; CHECK-NEXT: call void @use.i64(i64 [[V1]])310; CHECK-NEXT: ret void311;312 %v1 = load i64, ptr %p, !range !{i64 0, i64 10}313 br i1 %c, label %if, label %join314 315if:316 br label %join317 318join:319 %v2 = load i64, ptr %p, !range !{i64 20, i64 30}320 call void @use.i64(i64 %v1)321 call void @use.i64(i64 %v2)322 ret void323}324 325define void @non_local_non_dominating(i1 %c, ptr %p) {326; CHECK-LABEL: define void @non_local_non_dominating327; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]]) {328; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]329; CHECK: if:330; CHECK-NEXT: [[V1:%.*]] = load i64, ptr [[P]], align 4, !range [[RNG9]]331; CHECK-NEXT: call void @use.i64(i64 [[V1]])332; CHECK-NEXT: br label [[JOIN:%.*]]333; CHECK: else:334; CHECK-NEXT: [[V2:%.*]] = load i64, ptr [[P]], align 4, !range [[RNG10:![0-9]+]]335; CHECK-NEXT: call void @use.i64(i64 [[V2]])336; CHECK-NEXT: br label [[JOIN]]337; CHECK: join:338; CHECK-NEXT: [[V3:%.*]] = phi i64 [ [[V2]], [[ELSE]] ], [ [[V1]], [[IF]] ]339; CHECK-NEXT: call void @use.i64(i64 [[V3]])340; CHECK-NEXT: ret void341;342 br i1 %c, label %if, label %else343 344if:345 %v1 = load i64, ptr %p, !range !{i64 0, i64 10}346 call void @use.i64(i64 %v1)347 br label %join348 349else:350 %v2 = load i64, ptr %p, !range !{i64 10, i64 20}351 call void @use.i64(i64 %v2)352 br label %join353 354join:355 %v3 = load i64, ptr %p, !range !{i64 20, i64 30}356 call void @use.i64(i64 %v3)357 ret void358}359 360define void @non_local_coerced(i1 %c, ptr %p) {361; CHECK-LABEL: define void @non_local_coerced362; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]]) {363; CHECK-NEXT: [[V1_PTR:%.*]] = load ptr, ptr [[P]], align 8364; CHECK-NEXT: [[V1:%.*]] = ptrtoint ptr [[V1_PTR]] to i64365; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[JOIN:%.*]]366; CHECK: if:367; CHECK-NEXT: br label [[JOIN]]368; CHECK: join:369; CHECK-NEXT: call void @use.i64(i64 [[V1]])370; CHECK-NEXT: call void @use.i64(i64 [[V1]])371; CHECK-NEXT: ret void372;373 %v1.ptr = load ptr, ptr %p, !nonnull !{}374 %v1 = ptrtoint ptr %v1.ptr to i64375 br i1 %c, label %if, label %join376 377if:378 br label %join379 380join:381 %v2 = load i64, ptr %p, !range !{i64 20, i64 30}382 call void @use.i64(i64 %v1)383 call void @use.i64(i64 %v2)384 ret void385}386 387define void @non_local_pre(i1 %c, ptr %p) {388; CHECK-LABEL: define void @non_local_pre389; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]]) {390; CHECK-NEXT: [[V2_PRE:%.*]] = load i64, ptr [[P]], align 4, !range [[RNG9]]391; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[JOIN:%.*]]392; CHECK: if:393; CHECK-NEXT: call void @use.i64(i64 [[V2_PRE]])394; CHECK-NEXT: br label [[JOIN]]395; CHECK: join:396; CHECK-NEXT: call void @use.i64(i64 [[V2_PRE]])397; CHECK-NEXT: ret void398;399 br i1 %c, label %if, label %join400 401if:402 %v1 = load i64, ptr %p, !range !{i64 0, i64 10}403 call void @use.i64(i64 %v1)404 br label %join405 406join:407 %v2 = load i64, ptr %p, !range !{i64 20, i64 30}408 call void @use.i64(i64 %v2)409 ret void410}411 412; We should preserve the !nosanitize if both insns have it.413define void @test_nosanitize1(ptr %p) {414; CHECK-LABEL: define void @test_nosanitize1415; CHECK-SAME: (ptr [[P:%.*]]) {416; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[P]], align 4, !nosanitize [[META6]]417; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[V1]], 0418; CHECK-NEXT: br i1 [[COND]], label [[IF:%.*]], label [[JOIN:%.*]]419; CHECK: if:420; CHECK-NEXT: call void @use.i32(i32 0)421; CHECK-NEXT: br label [[JOIN]]422; CHECK: join:423; CHECK-NEXT: ret void424;425 %v1 = load i32, ptr %p, !nosanitize !11426 %cond = icmp eq i32 %v1, 0427 br i1 %cond, label %if, label %join428 429if:430 %v2 = load i32, ptr %p, !nosanitize !11431 call void @use.i32(i32 %v2)432 br label %join433 434join:435 ret void436}437 438define void @test_nosanitize2(ptr %p) {439; CHECK-LABEL: define void @test_nosanitize2440; CHECK-SAME: (ptr [[P:%.*]]) {441; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[P]], align 4442; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[V1]], 0443; CHECK-NEXT: br i1 [[COND]], label [[IF:%.*]], label [[JOIN:%.*]]444; CHECK: if:445; CHECK-NEXT: call void @use.i32(i32 0)446; CHECK-NEXT: br label [[JOIN]]447; CHECK: join:448; CHECK-NEXT: ret void449;450 %v1 = load i32, ptr %p, !nosanitize !11451 %cond = icmp eq i32 %v1, 0452 br i1 %cond, label %if, label %join453 454if:455 %v2 = load i32, ptr %p456 call void @use.i32(i32 %v2)457 br label %join458 459join:460 ret void461}462 463define void @test_nosanitize3(ptr %p) {464; CHECK-LABEL: define void @test_nosanitize3465; CHECK-SAME: (ptr [[P:%.*]]) {466; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[P]], align 4467; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[V1]], 0468; CHECK-NEXT: br i1 [[COND]], label [[IF:%.*]], label [[JOIN:%.*]]469; CHECK: if:470; CHECK-NEXT: call void @use.i32(i32 0)471; CHECK-NEXT: br label [[JOIN]]472; CHECK: join:473; CHECK-NEXT: ret void474;475 %v1 = load i32, ptr %p476 %cond = icmp eq i32 %v1, 0477 br i1 %cond, label %if, label %join478 479if:480 %v2 = load i32, ptr %p, !nosanitize !11481 call void @use.i32(i32 %v2)482 br label %join483 484join:485 ret void486}487 488!0 = !{i32 0, i32 2}489!1 = !{i32 3, i32 5}490!2 = !{i32 2, i32 5}491!3 = !{i32 -5, i32 -2}492!4 = !{i32 1, i32 5}493!5 = !{i32 10, i32 1}494!6 = !{i32 12, i32 16}495!7 = !{i32 1, i32 2, i32 3, i32 4}496!8 = !{i32 5, i32 1}497!9 = !{i32 1, i32 5}498!10 = !{i32 5, i32 1}499!11 = !{}500;.501; CHECK: attributes #[[ATTR0:[0-9]+]] = { memory(none) }502;.503; CHECK: [[RNG0]] = !{i32 0, i32 2}504; CHECK: [[RNG1]] = !{i32 0, i32 2, i32 3, i32 5}505; CHECK: [[RNG2]] = !{i32 0, i32 5}506; CHECK: [[RNG3]] = !{i32 -5, i32 -2, i32 1, i32 5}507; CHECK: [[RNG4]] = !{i32 10, i32 1}508; CHECK: [[RNG5]] = !{i32 3, i32 4, i32 5, i32 2}509; CHECK: [[META6]] = !{}510; CHECK: [[META7]] = !{i64 10}511; CHECK: [[RNG8]] = !{i64 0, i64 10}512; CHECK: [[RNG9]] = !{i64 0, i64 10, i64 20, i64 30}513; CHECK: [[RNG10]] = !{i64 10, i64 30}514;.515