brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.0 KiB · 554d3ce Raw
598 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature2; RUN: opt < %s -S -passes=early-cse -earlycse-debug-hash | FileCheck %s --check-prefixes=CHECK,NO_ASSUME3; RUN: opt < %s -S -passes=early-cse --enable-knowledge-retention | FileCheck %s --check-prefixes=CHECK,USE_ASSUME4; RUN: opt < %s -S -passes=early-cse | FileCheck %s --check-prefixes=CHECK,NO_ASSUME5 6declare ptr @llvm.invariant.start.p0(i64, ptr nocapture) nounwind readonly7declare void @llvm.invariant.end.p0(ptr, i64, ptr nocapture) nounwind8 9; Check that we do load-load forwarding over invariant.start, since it does not10; clobber memory11define i8 @test_bypass1(ptr%P) {12; NO_ASSUME-LABEL: define {{[^@]+}}@test_bypass113; NO_ASSUME-SAME: (ptr [[P:%.*]]) {14; NO_ASSUME-NEXT:    [[V1:%.*]] = load i8, ptr [[P]], align 115; NO_ASSUME-NEXT:    [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[P]])16; NO_ASSUME-NEXT:    ret i8 017;18; USE_ASSUME-LABEL: define {{[^@]+}}@test_bypass119; USE_ASSUME-SAME: (ptr [[P:%.*]]) {20; USE_ASSUME-NEXT:    [[V1:%.*]] = load i8, ptr [[P]], align 121; USE_ASSUME-NEXT:    [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[P]])22; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 1), "nonnull"(ptr [[P]]) ]23; USE_ASSUME-NEXT:    ret i8 024;25 26  %V1 = load i8, ptr %P27  %i = call ptr @llvm.invariant.start.p0(i64 1, ptr %P)28  %V2 = load i8, ptr %P29  %Diff = sub i8 %V1, %V230  ret i8 %Diff31}32 33 34; Trivial Store->load forwarding over invariant.start35define i8 @test_bypass2(ptr%P) {36; NO_ASSUME-LABEL: define {{[^@]+}}@test_bypass237; NO_ASSUME-SAME: (ptr [[P:%.*]]) {38; NO_ASSUME-NEXT:    store i8 42, ptr [[P]], align 139; NO_ASSUME-NEXT:    [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[P]])40; NO_ASSUME-NEXT:    ret i8 4241;42; USE_ASSUME-LABEL: define {{[^@]+}}@test_bypass243; USE_ASSUME-SAME: (ptr [[P:%.*]]) {44; USE_ASSUME-NEXT:    store i8 42, ptr [[P]], align 145; USE_ASSUME-NEXT:    [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[P]])46; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 1), "nonnull"(ptr [[P]]) ]47; USE_ASSUME-NEXT:    ret i8 4248;49 50  store i8 42, ptr %P51  %i = call ptr @llvm.invariant.start.p0(i64 1, ptr %P)52  %V1 = load i8, ptr %P53  ret i8 %V154}55 56define i8 @test_bypass_store_load(ptr%P, ptr%P2) {57; NO_ASSUME-LABEL: define {{[^@]+}}@test_bypass_store_load58; NO_ASSUME-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {59; NO_ASSUME-NEXT:    store i8 42, ptr [[P]], align 160; NO_ASSUME-NEXT:    [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[P]])61; NO_ASSUME-NEXT:    store i8 0, ptr [[P2]], align 162; NO_ASSUME-NEXT:    ret i8 4263;64; USE_ASSUME-LABEL: define {{[^@]+}}@test_bypass_store_load65; USE_ASSUME-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {66; USE_ASSUME-NEXT:    store i8 42, ptr [[P]], align 167; USE_ASSUME-NEXT:    [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[P]])68; USE_ASSUME-NEXT:    store i8 0, ptr [[P2]], align 169; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 1), "nonnull"(ptr [[P]]) ]70; USE_ASSUME-NEXT:    ret i8 4271;72 73  store i8 42, ptr %P74  %i = call ptr @llvm.invariant.start.p0(i64 1, ptr %P)75  store i8 0, ptr %P276  %V1 = load i8, ptr %P77  ret i8 %V178}79 80define i8 @test_bypass_store_load_aatags_1(ptr%P, ptr%P2) {81; NO_ASSUME-LABEL: define {{[^@]+}}@test_bypass_store_load_aatags_182; NO_ASSUME-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {83; NO_ASSUME-NEXT:    store i8 42, ptr [[P]], align 1, !tbaa [[TBAA0:![0-9]+]]84; NO_ASSUME-NEXT:    [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[P]])85; NO_ASSUME-NEXT:    store i8 0, ptr [[P2]], align 186; NO_ASSUME-NEXT:    ret i8 4287;88; USE_ASSUME-LABEL: define {{[^@]+}}@test_bypass_store_load_aatags_189; USE_ASSUME-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {90; USE_ASSUME-NEXT:    store i8 42, ptr [[P]], align 1, !tbaa [[TBAA0:![0-9]+]]91; USE_ASSUME-NEXT:    [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[P]])92; USE_ASSUME-NEXT:    store i8 0, ptr [[P2]], align 193; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 1), "nonnull"(ptr [[P]]) ]94; USE_ASSUME-NEXT:    ret i8 4295;96 97  store i8 42, ptr %P, !tbaa !098  %i = call ptr @llvm.invariant.start.p0(i64 1, ptr %P)99  store i8 0, ptr %P2100  %V1 = load i8, ptr %P101  ret i8 %V1102}103 104; The test demonstrates a missed optimization opportunity in case when the load105; has AA tags that are different from the store tags.106define i8 @test_bypass_store_load_aatags_2(ptr%P, ptr%P2) {107; CHECK-LABEL: define {{[^@]+}}@test_bypass_store_load_aatags_2108; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {109; CHECK-NEXT:    store i8 42, ptr [[P]], align 1110; CHECK-NEXT:    [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[P]])111; CHECK-NEXT:    store i8 0, ptr [[P2]], align 1112; CHECK-NEXT:    [[V1:%.*]] = load i8, ptr [[P]], align 1, !tbaa [[TBAA0:![0-9]+]]113; CHECK-NEXT:    ret i8 [[V1]]114;115 116  store i8 42, ptr %P117  %i = call ptr @llvm.invariant.start.p0(i64 1, ptr %P)118  store i8 0, ptr %P2119  %V1 = load i8, ptr %P, !tbaa !0120  ret i8 %V1121}122 123; We can DSE over invariant.start calls, since the first store to124; %P is valid, and the second store is actually unreachable based on semantics125; of invariant.start.126define void @test_bypass3(ptr %P) {127; NO_ASSUME-LABEL: define {{[^@]+}}@test_bypass3128; NO_ASSUME-SAME: (ptr [[P:%.*]]) {129; NO_ASSUME-NEXT:    [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[P]])130; NO_ASSUME-NEXT:    store i8 60, ptr [[P]], align 1131; NO_ASSUME-NEXT:    ret void132;133; USE_ASSUME-LABEL: define {{[^@]+}}@test_bypass3134; USE_ASSUME-SAME: (ptr [[P:%.*]]) {135; USE_ASSUME-NEXT:    [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[P]])136; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 1), "nonnull"(ptr [[P]]) ]137; USE_ASSUME-NEXT:    store i8 60, ptr [[P]], align 1138; USE_ASSUME-NEXT:    ret void139;140 141  store i8 50, ptr %P142  %i = call ptr @llvm.invariant.start.p0(i64 1, ptr %P)143  store i8 60, ptr %P144  ret void145}146 147 148; FIXME: Now the first store can actually be eliminated, since there is no read within149; the invariant region, between start and end.150define void @test_bypass4(ptr %P) {151; CHECK-LABEL: define {{[^@]+}}@test_bypass4152; CHECK-SAME: (ptr [[P:%.*]]) {153; CHECK-NEXT:    store i8 50, ptr [[P]], align 1154; CHECK-NEXT:    [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[P]])155; CHECK-NEXT:    call void @llvm.invariant.end.p0(ptr [[I]], i64 1, ptr [[P]])156; CHECK-NEXT:    store i8 60, ptr [[P]], align 1157; CHECK-NEXT:    ret void158;159 160 161  store i8 50, ptr %P162  %i = call ptr @llvm.invariant.start.p0(i64 1, ptr %P)163  call void @llvm.invariant.end.p0(ptr %i, i64 1, ptr %P)164  store i8 60, ptr %P165  ret void166}167 168 169declare void @clobber()170 171define i32 @test_before_load(ptr %p) {172; NO_ASSUME-LABEL: define {{[^@]+}}@test_before_load173; NO_ASSUME-SAME: (ptr [[P:%.*]]) {174; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])175; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4176; NO_ASSUME-NEXT:    call void @clobber()177; NO_ASSUME-NEXT:    ret i32 0178;179; USE_ASSUME-LABEL: define {{[^@]+}}@test_before_load180; USE_ASSUME-SAME: (ptr [[P:%.*]]) {181; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])182; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4183; USE_ASSUME-NEXT:    call void @clobber()184; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]185; USE_ASSUME-NEXT:    ret i32 0186;187  call ptr @llvm.invariant.start.p0(i64 4, ptr %p)188  %v1 = load i32, ptr %p189  call void @clobber()190  %v2 = load i32, ptr %p191  %sub = sub i32 %v1, %v2192  ret i32 %sub193}194 195define i32 @test_before_clobber(ptr %p) {196; NO_ASSUME-LABEL: define {{[^@]+}}@test_before_clobber197; NO_ASSUME-SAME: (ptr [[P:%.*]]) {198; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4199; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])200; NO_ASSUME-NEXT:    call void @clobber()201; NO_ASSUME-NEXT:    ret i32 0202;203; USE_ASSUME-LABEL: define {{[^@]+}}@test_before_clobber204; USE_ASSUME-SAME: (ptr [[P:%.*]]) {205; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4206; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])207; USE_ASSUME-NEXT:    call void @clobber()208; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]209; USE_ASSUME-NEXT:    ret i32 0210;211  %v1 = load i32, ptr %p212  call ptr @llvm.invariant.start.p0(i64 4, ptr %p)213  call void @clobber()214  %v2 = load i32, ptr %p215  %sub = sub i32 %v1, %v2216  ret i32 %sub217}218 219define i32 @test_duplicate_scope(ptr %p) {220; NO_ASSUME-LABEL: define {{[^@]+}}@test_duplicate_scope221; NO_ASSUME-SAME: (ptr [[P:%.*]]) {222; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4223; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])224; NO_ASSUME-NEXT:    call void @clobber()225; NO_ASSUME-NEXT:    [[TMP2:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])226; NO_ASSUME-NEXT:    ret i32 0227;228; USE_ASSUME-LABEL: define {{[^@]+}}@test_duplicate_scope229; USE_ASSUME-SAME: (ptr [[P:%.*]]) {230; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4231; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])232; USE_ASSUME-NEXT:    call void @clobber()233; USE_ASSUME-NEXT:    [[TMP2:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])234; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]235; USE_ASSUME-NEXT:    ret i32 0236;237  %v1 = load i32, ptr %p238  call ptr @llvm.invariant.start.p0(i64 4, ptr %p)239  call void @clobber()240  call ptr @llvm.invariant.start.p0(i64 4, ptr %p)241  %v2 = load i32, ptr %p242  %sub = sub i32 %v1, %v2243  ret i32 %sub244}245 246define i32 @test_unanalzyable_load(ptr %p) {247; NO_ASSUME-LABEL: define {{[^@]+}}@test_unanalzyable_load248; NO_ASSUME-SAME: (ptr [[P:%.*]]) {249; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])250; NO_ASSUME-NEXT:    call void @clobber()251; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4252; NO_ASSUME-NEXT:    call void @clobber()253; NO_ASSUME-NEXT:    ret i32 0254;255; USE_ASSUME-LABEL: define {{[^@]+}}@test_unanalzyable_load256; USE_ASSUME-SAME: (ptr [[P:%.*]]) {257; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])258; USE_ASSUME-NEXT:    call void @clobber()259; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4260; USE_ASSUME-NEXT:    call void @clobber()261; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]262; USE_ASSUME-NEXT:    ret i32 0263;264  call ptr @llvm.invariant.start.p0(i64 4, ptr %p)265  call void @clobber()266  %v1 = load i32, ptr %p267  call void @clobber()268  %v2 = load i32, ptr %p269  %sub = sub i32 %v1, %v2270  ret i32 %sub271}272 273define i32 @test_negative_after_clobber(ptr %p) {274; CHECK-LABEL: define {{[^@]+}}@test_negative_after_clobber275; CHECK-SAME: (ptr [[P:%.*]]) {276; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4277; CHECK-NEXT:    call void @clobber()278; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])279; CHECK-NEXT:    [[V2:%.*]] = load i32, ptr [[P]], align 4280; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]281; CHECK-NEXT:    ret i32 [[SUB]]282;283  %v1 = load i32, ptr %p284  call void @clobber()285  call ptr @llvm.invariant.start.p0(i64 4, ptr %p)286  %v2 = load i32, ptr %p287  %sub = sub i32 %v1, %v2288  ret i32 %sub289}290 291define i32 @test_merge(ptr %p, i1 %cnd) {292; NO_ASSUME-LABEL: define {{[^@]+}}@test_merge293; NO_ASSUME-SAME: (ptr [[P:%.*]], i1 [[CND:%.*]]) {294; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4295; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])296; NO_ASSUME-NEXT:    br i1 [[CND]], label [[MERGE:%.*]], label [[TAKEN:%.*]]297; NO_ASSUME:       taken:298; NO_ASSUME-NEXT:    call void @clobber()299; NO_ASSUME-NEXT:    br label [[MERGE]]300; NO_ASSUME:       merge:301; NO_ASSUME-NEXT:    ret i32 0302;303; USE_ASSUME-LABEL: define {{[^@]+}}@test_merge304; USE_ASSUME-SAME: (ptr [[P:%.*]], i1 [[CND:%.*]]) {305; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4306; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])307; USE_ASSUME-NEXT:    br i1 [[CND]], label [[MERGE:%.*]], label [[TAKEN:%.*]]308; USE_ASSUME:       taken:309; USE_ASSUME-NEXT:    call void @clobber()310; USE_ASSUME-NEXT:    br label [[MERGE]]311; USE_ASSUME:       merge:312; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]313; USE_ASSUME-NEXT:    ret i32 0314;315  %v1 = load i32, ptr %p316  call ptr @llvm.invariant.start.p0(i64 4, ptr %p)317  br i1 %cnd, label %merge, label %taken318 319taken:320  call void @clobber()321  br label %merge322merge:323  %v2 = load i32, ptr %p324  %sub = sub i32 %v1, %v2325  ret i32 %sub326}327 328define i32 @test_negative_after_mergeclobber(ptr %p, i1 %cnd) {329; CHECK-LABEL: define {{[^@]+}}@test_negative_after_mergeclobber330; CHECK-SAME: (ptr [[P:%.*]], i1 [[CND:%.*]]) {331; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4332; CHECK-NEXT:    br i1 [[CND]], label [[MERGE:%.*]], label [[TAKEN:%.*]]333; CHECK:       taken:334; CHECK-NEXT:    call void @clobber()335; CHECK-NEXT:    br label [[MERGE]]336; CHECK:       merge:337; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])338; CHECK-NEXT:    [[V2:%.*]] = load i32, ptr [[P]], align 4339; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]340; CHECK-NEXT:    ret i32 [[SUB]]341;342  %v1 = load i32, ptr %p343  br i1 %cnd, label %merge, label %taken344 345taken:346  call void @clobber()347  br label %merge348merge:349  call ptr @llvm.invariant.start.p0(i64 4, ptr %p)350  %v2 = load i32, ptr %p351  %sub = sub i32 %v1, %v2352  ret i32 %sub353}354 355; In theory, this version could work, but earlycse is incapable of356; merging facts along distinct paths.357define i32 @test_false_negative_merge(ptr %p, i1 %cnd) {358; CHECK-LABEL: define {{[^@]+}}@test_false_negative_merge359; CHECK-SAME: (ptr [[P:%.*]], i1 [[CND:%.*]]) {360; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4361; CHECK-NEXT:    br i1 [[CND]], label [[MERGE:%.*]], label [[TAKEN:%.*]]362; CHECK:       taken:363; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])364; CHECK-NEXT:    call void @clobber()365; CHECK-NEXT:    br label [[MERGE]]366; CHECK:       merge:367; CHECK-NEXT:    [[V2:%.*]] = load i32, ptr [[P]], align 4368; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]369; CHECK-NEXT:    ret i32 [[SUB]]370;371  %v1 = load i32, ptr %p372  br i1 %cnd, label %merge, label %taken373 374taken:375  call ptr @llvm.invariant.start.p0(i64 4, ptr %p)376  call void @clobber()377  br label %merge378merge:379  %v2 = load i32, ptr %p380  %sub = sub i32 %v1, %v2381  ret i32 %sub382}383 384define i32 @test_merge_unanalyzable_load(ptr %p, i1 %cnd) {385; NO_ASSUME-LABEL: define {{[^@]+}}@test_merge_unanalyzable_load386; NO_ASSUME-SAME: (ptr [[P:%.*]], i1 [[CND:%.*]]) {387; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])388; NO_ASSUME-NEXT:    call void @clobber()389; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4390; NO_ASSUME-NEXT:    br i1 [[CND]], label [[MERGE:%.*]], label [[TAKEN:%.*]]391; NO_ASSUME:       taken:392; NO_ASSUME-NEXT:    call void @clobber()393; NO_ASSUME-NEXT:    br label [[MERGE]]394; NO_ASSUME:       merge:395; NO_ASSUME-NEXT:    ret i32 0396;397; USE_ASSUME-LABEL: define {{[^@]+}}@test_merge_unanalyzable_load398; USE_ASSUME-SAME: (ptr [[P:%.*]], i1 [[CND:%.*]]) {399; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])400; USE_ASSUME-NEXT:    call void @clobber()401; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4402; USE_ASSUME-NEXT:    br i1 [[CND]], label [[MERGE:%.*]], label [[TAKEN:%.*]]403; USE_ASSUME:       taken:404; USE_ASSUME-NEXT:    call void @clobber()405; USE_ASSUME-NEXT:    br label [[MERGE]]406; USE_ASSUME:       merge:407; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]408; USE_ASSUME-NEXT:    ret i32 0409;410  call ptr @llvm.invariant.start.p0(i64 4, ptr %p)411  call void @clobber()412  %v1 = load i32, ptr %p413  br i1 %cnd, label %merge, label %taken414 415taken:416  call void @clobber()417  br label %merge418merge:419  %v2 = load i32, ptr %p420  %sub = sub i32 %v1, %v2421  ret i32 %sub422}423 424define void @test_dse_before_load(ptr %p, i1 %cnd) {425; NO_ASSUME-LABEL: define {{[^@]+}}@test_dse_before_load426; NO_ASSUME-SAME: (ptr [[P:%.*]], i1 [[CND:%.*]]) {427; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])428; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4429; NO_ASSUME-NEXT:    call void @clobber()430; NO_ASSUME-NEXT:    ret void431;432; USE_ASSUME-LABEL: define {{[^@]+}}@test_dse_before_load433; USE_ASSUME-SAME: (ptr [[P:%.*]], i1 [[CND:%.*]]) {434; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])435; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4436; USE_ASSUME-NEXT:    call void @clobber()437; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]438; USE_ASSUME-NEXT:    ret void439;440  call ptr @llvm.invariant.start.p0(i64 4, ptr %p)441  %v1 = load i32, ptr %p442  call void @clobber()443  store i32 %v1, ptr %p444  ret void445}446 447define void @test_dse_after_load(ptr %p, i1 %cnd) {448; NO_ASSUME-LABEL: define {{[^@]+}}@test_dse_after_load449; NO_ASSUME-SAME: (ptr [[P:%.*]], i1 [[CND:%.*]]) {450; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4451; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])452; NO_ASSUME-NEXT:    call void @clobber()453; NO_ASSUME-NEXT:    ret void454;455; USE_ASSUME-LABEL: define {{[^@]+}}@test_dse_after_load456; USE_ASSUME-SAME: (ptr [[P:%.*]], i1 [[CND:%.*]]) {457; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4458; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])459; USE_ASSUME-NEXT:    call void @clobber()460; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]461; USE_ASSUME-NEXT:    ret void462;463  %v1 = load i32, ptr %p464  call ptr @llvm.invariant.start.p0(i64 4, ptr %p)465  call void @clobber()466  store i32 %v1, ptr %p467  ret void468}469 470 471; In this case, we have a false negative since MemoryLocation is implicitly472; typed due to the user of a Value to represent the address.  Note that other473; passes will canonicalize away the bitcasts in this example.474define i32 @test_false_negative_types(ptr %p) {475; CHECK-LABEL: define {{[^@]+}}@test_false_negative_types476; CHECK-SAME: (ptr [[P:%.*]]) {477; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])478; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4479; CHECK-NEXT:    call void @clobber()480; CHECK-NEXT:    [[V2F:%.*]] = load float, ptr [[P]], align 4481; CHECK-NEXT:    [[V2:%.*]] = bitcast float [[V2F]] to i32482; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]483; CHECK-NEXT:    ret i32 [[SUB]]484;485  call ptr @llvm.invariant.start.p0(i64 4, ptr %p)486  %v1 = load i32, ptr %p487  call void @clobber()488  %v2f = load float, ptr %p489  %v2 = bitcast float %v2f to i32490  %sub = sub i32 %v1, %v2491  ret i32 %sub492}493 494define i32 @test_negative_size1(ptr %p) {495; CHECK-LABEL: define {{[^@]+}}@test_negative_size1496; CHECK-SAME: (ptr [[P:%.*]]) {497; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 3, ptr [[P]])498; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4499; CHECK-NEXT:    call void @clobber()500; CHECK-NEXT:    [[V2:%.*]] = load i32, ptr [[P]], align 4501; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]502; CHECK-NEXT:    ret i32 [[SUB]]503;504  call ptr @llvm.invariant.start.p0(i64 3, ptr %p)505  %v1 = load i32, ptr %p506  call void @clobber()507  %v2 = load i32, ptr %p508  %sub = sub i32 %v1, %v2509  ret i32 %sub510}511 512define i32 @test_negative_size2(ptr %p) {513; CHECK-LABEL: define {{[^@]+}}@test_negative_size2514; CHECK-SAME: (ptr [[P:%.*]]) {515; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.invariant.start.p0(i64 0, ptr [[P]])516; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4517; CHECK-NEXT:    call void @clobber()518; CHECK-NEXT:    [[V2:%.*]] = load i32, ptr [[P]], align 4519; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]520; CHECK-NEXT:    ret i32 [[SUB]]521;522  call ptr @llvm.invariant.start.p0(i64 0, ptr %p)523  %v1 = load i32, ptr %p524  call void @clobber()525  %v2 = load i32, ptr %p526  %sub = sub i32 %v1, %v2527  ret i32 %sub528}529 530define i32 @test_negative_scope(ptr %p) {531; CHECK-LABEL: define {{[^@]+}}@test_negative_scope532; CHECK-SAME: (ptr [[P:%.*]]) {533; CHECK-NEXT:    [[SCOPE:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])534; CHECK-NEXT:    call void @llvm.invariant.end.p0(ptr [[SCOPE]], i64 4, ptr [[P]])535; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4536; CHECK-NEXT:    call void @clobber()537; CHECK-NEXT:    [[V2:%.*]] = load i32, ptr [[P]], align 4538; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]539; CHECK-NEXT:    ret i32 [[SUB]]540;541  %scope = call ptr @llvm.invariant.start.p0(i64 4, ptr %p)542  call void @llvm.invariant.end.p0(ptr %scope, i64 4, ptr %p)543  %v1 = load i32, ptr %p544  call void @clobber()545  %v2 = load i32, ptr %p546  %sub = sub i32 %v1, %v2547  ret i32 %sub548}549 550define i32 @test_false_negative_scope(ptr %p) {551; CHECK-LABEL: define {{[^@]+}}@test_false_negative_scope552; CHECK-SAME: (ptr [[P:%.*]]) {553; CHECK-NEXT:    [[SCOPE:%.*]] = call ptr @llvm.invariant.start.p0(i64 4, ptr [[P]])554; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4555; CHECK-NEXT:    call void @clobber()556; CHECK-NEXT:    [[V2:%.*]] = load i32, ptr [[P]], align 4557; CHECK-NEXT:    call void @llvm.invariant.end.p0(ptr [[SCOPE]], i64 4, ptr [[P]])558; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]559; CHECK-NEXT:    ret i32 [[SUB]]560;561  %scope = call ptr @llvm.invariant.start.p0(i64 4, ptr %p)562  %v1 = load i32, ptr %p563  call void @clobber()564  %v2 = load i32, ptr %p565  call void @llvm.invariant.end.p0(ptr %scope, i64 4, ptr %p)566  %sub = sub i32 %v1, %v2567  ret i32 %sub568}569 570; Invariant load defact starts an invariant.start scope of the appropriate size571define i32 @test_invariant_load_scope(ptr %p) {572; NO_ASSUME-LABEL: define {{[^@]+}}@test_invariant_load_scope573; NO_ASSUME-SAME: (ptr [[P:%.*]]) {574; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4, !invariant.load !4575; NO_ASSUME-NEXT:    call void @clobber()576; NO_ASSUME-NEXT:    ret i32 0577;578; USE_ASSUME-LABEL: define {{[^@]+}}@test_invariant_load_scope579; USE_ASSUME-SAME: (ptr [[P:%.*]]) {580; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4, !invariant.load !4581; USE_ASSUME-NEXT:    call void @clobber()582; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]583; USE_ASSUME-NEXT:    ret i32 0584;585  %v1 = load i32, ptr %p, !invariant.load !{}586  call void @clobber()587  %v2 = load i32, ptr %p588  %sub = sub i32 %v1, %v2589  ret i32 %sub590}591 592; USE_ASSUME: declare void @llvm.assume(i1 noundef)593 594!0 = !{!1, !1, i64 0}595!1 = !{!"float", !2, i64 0}596!2 = !{!"omnipotent char", !3, i64 0}597!3 = !{!"Simple C/C++ TBAA"}598