203 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 22; Test if the !invariant.load metadata is maintained by GVN.3; RUN: opt -passes=gvn -S < %s | FileCheck %s4 5define i32 @test1(ptr nocapture %p, ptr nocapture %q) {6; CHECK-LABEL: define i32 @test17; CHECK-SAME: (ptr captures(none) [[P:%.*]], ptr captures(none) [[Q:%.*]]) {8; CHECK-NEXT: entry:9; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P]], align 4, !invariant.load [[META0:![0-9]+]]10; CHECK-NEXT: [[CONV:%.*]] = trunc i32 [[X]] to i811; CHECK-NEXT: store i8 [[CONV]], ptr [[Q]], align 112; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 113; CHECK-NEXT: ret i32 [[ADD]]14;15entry:16 %x = load i32, ptr %p, align 4, !invariant.load !017 %conv = trunc i32 %x to i818 store i8 %conv, ptr %q, align 119 %y = load i32, ptr %p, align 4, !invariant.load !020 %add = add i32 %y, 121 ret i32 %add22}23 24define i32 @test2(ptr nocapture %p, ptr nocapture %q) {25; CHECK-LABEL: define i32 @test226; CHECK-SAME: (ptr captures(none) [[P:%.*]], ptr captures(none) [[Q:%.*]]) {27; CHECK-NEXT: entry:28; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P]], align 429; CHECK-NEXT: [[CONV:%.*]] = trunc i32 [[X]] to i830; CHECK-NEXT: store i8 [[CONV]], ptr [[Q]], align 131; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 132; CHECK-NEXT: ret i32 [[ADD]]33;34entry:35 %x = load i32, ptr %p, align 436 %conv = trunc i32 %x to i837 store i8 %conv, ptr %q, align 138 %y = load i32, ptr %p, align 4, !invariant.load !039 %add = add i32 %y, 140 ret i32 %add41}42 43; With the invariant.load metadata, what would otherwise44; be a case for PRE becomes a full redundancy.45define i32 @test3(i1 %cnd, ptr %p, ptr %q) {46; CHECK-LABEL: define i32 @test347; CHECK-SAME: (i1 [[CND:%.*]], ptr [[P:%.*]], ptr [[Q:%.*]]) {48; CHECK-NEXT: entry:49; CHECK-NEXT: br i1 [[CND]], label [[BB1:%.*]], label [[BB2:%.*]]50; CHECK: bb1:51; CHECK-NEXT: store i32 5, ptr [[Q]], align 452; CHECK-NEXT: br label [[BB2]]53; CHECK: bb2:54; CHECK-NEXT: ret i32 055;56entry:57 %v1 = load i32, ptr %p58 br i1 %cnd, label %bb1, label %bb259 60bb1:61 store i32 5, ptr %q62 br label %bb263 64bb2:65 %v2 = load i32, ptr %p, !invariant.load !066 %res = sub i32 %v1, %v267 ret i32 %res68}69 70; This test is here to document a case which doesn't optimize71; as well as it could.72define i32 @test4(i1 %cnd, ptr %p, ptr %q) {73; CHECK-LABEL: define i32 @test474; CHECK-SAME: (i1 [[CND:%.*]], ptr [[P:%.*]], ptr [[Q:%.*]]) {75; CHECK-NEXT: entry:76; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[P]], align 4, !invariant.load [[META0]]77; CHECK-NEXT: br i1 [[CND]], label [[BB1:%.*]], label [[BB2:%.*]]78; CHECK: bb1:79; CHECK-NEXT: store i32 5, ptr [[Q]], align 480; CHECK-NEXT: [[V2_PRE:%.*]] = load i32, ptr [[P]], align 481; CHECK-NEXT: br label [[BB2]]82; CHECK: bb2:83; CHECK-NEXT: [[V2:%.*]] = phi i32 [ [[V2_PRE]], [[BB1]] ], [ [[V1]], [[ENTRY:%.*]] ]84; CHECK-NEXT: [[RES:%.*]] = sub i32 [[V1]], [[V2]]85; CHECK-NEXT: ret i32 [[RES]]86;87; %v2 is redundant, but GVN currently doesn't catch that88entry:89 %v1 = load i32, ptr %p, !invariant.load !090 br i1 %cnd, label %bb1, label %bb291 92bb1:93 store i32 5, ptr %q94 br label %bb295 96bb2:97 %v2 = load i32, ptr %p98 %res = sub i32 %v1, %v299 ret i32 %res100}101 102; Checks that we return the mustalias store as a def103; so that it contributes to value forwarding. Note104; that we could and should remove the store too.105define i32 @test5(i1 %cnd, ptr %p) {106; CHECK-LABEL: define i32 @test5107; CHECK-SAME: (i1 [[CND:%.*]], ptr [[P:%.*]]) {108; CHECK-NEXT: entry:109; CHECK-NEXT: store i32 5, ptr [[P]], align 4110; CHECK-NEXT: ret i32 5111;112entry:113 %v1 = load i32, ptr %p, !invariant.load !0114 store i32 5, ptr %p ;; must alias store, want to exploit115 %v2 = load i32, ptr %p, !invariant.load !0116 ret i32 %v2117}118 119 120declare void @foo()121 122; Clobbering (mayalias) stores, even in function calls, can be ignored123define i32 @test6(i1 %cnd, ptr %p) {124; CHECK-LABEL: define i32 @test6125; CHECK-SAME: (i1 [[CND:%.*]], ptr [[P:%.*]]) {126; CHECK-NEXT: entry:127; CHECK-NEXT: call void @foo()128; CHECK-NEXT: ret i32 0129;130entry:131 %v1 = load i32, ptr %p, !invariant.load !0132 call void @foo()133 %v2 = load i32, ptr %p, !invariant.load !0134 %res = sub i32 %v1, %v2135 ret i32 %res136}137 138declare noalias ptr @bar(...)139 140; Same as previous, but a function with a noalias result (since they're handled141; differently in MDA)142define i32 @test7(i1 %cnd, ptr %p) {143; CHECK-LABEL: define i32 @test7144; CHECK-SAME: (i1 [[CND:%.*]], ptr [[P:%.*]]) {145; CHECK-NEXT: entry:146; CHECK-NEXT: [[TMP0:%.*]] = call ptr (...) @bar(ptr [[P]])147; CHECK-NEXT: ret i32 0148;149entry:150 %v1 = load i32, ptr %p, !invariant.load !0151 call ptr (...) @bar(ptr %p)152 %v2 = load i32, ptr %p, !invariant.load !0153 %res = sub i32 %v1, %v2154 ret i32 %res155}156 157define i32 @test8(i1 %cnd, ptr %p) {158; CHECK-LABEL: define i32 @test8159; CHECK-SAME: (i1 [[CND:%.*]], ptr [[P:%.*]]) {160; CHECK-NEXT: entry:161; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[P]], align 4, !invariant.load [[META0]]162; CHECK-NEXT: br i1 [[CND]], label [[TAKEN:%.*]], label [[MERGE:%.*]]163; CHECK: taken:164; CHECK-NEXT: [[P2:%.*]] = call ptr (...) @bar(ptr [[P]])165; CHECK-NEXT: [[V2_PRE:%.*]] = load i32, ptr [[P2]], align 4, !invariant.load [[META0]]166; CHECK-NEXT: br label [[MERGE]]167; CHECK: merge:168; CHECK-NEXT: [[V2:%.*]] = phi i32 [ [[V1]], [[ENTRY:%.*]] ], [ [[V2_PRE]], [[TAKEN]] ]169; CHECK-NEXT: [[P3:%.*]] = phi ptr [ [[P]], [[ENTRY]] ], [ [[P2]], [[TAKEN]] ]170; CHECK-NEXT: [[RES:%.*]] = sub i32 [[V1]], [[V2]]171; CHECK-NEXT: ret i32 [[RES]]172;173entry:174 %v1 = load i32, ptr %p, !invariant.load !0175 br i1 %cnd, label %taken, label %merge176taken:177 %p2 = call ptr (...) @bar(ptr %p)178 br label %merge179merge:180 %p3 = phi ptr [%p, %entry], [%p2, %taken]181 %v2 = load i32, ptr %p3, !invariant.load !0182 %res = sub i32 %v1, %v2183 ret i32 %res184}185 186define i32 @metadata_preservation(ptr nocapture %p, ptr nocapture %q) {187; CHECK-LABEL: define i32 @metadata_preservation188; CHECK-SAME: (ptr captures(none) [[P:%.*]], ptr captures(none) [[Q:%.*]]) {189; CHECK-NEXT: entry:190; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P]], align 4, !invariant.load [[META0]]191; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], [[X]]192; CHECK-NEXT: ret i32 [[ADD]]193;194entry:195 %x = load i32, ptr %p, align 4, !invariant.load !0196 %y = load i32, ptr %p, align 4197 %add = add i32 %x, %y198 ret i32 %add199}200 201!0 = !{ }202 203