brintos

brintos / llvm-project-archived public Read only

0
0
Text · 20.5 KiB · 7c14059 Raw
596 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 42; RUN: opt < %s -passes=newgvn -S | FileCheck %s3 4%struct.A = type { ptr }5@_ZTV1A = available_externally unnamed_addr constant [3 x ptr] [ptr null, ptr @_ZTI1A, ptr @_ZN1A3fooEv], align 86@_ZTI1A = external constant ptr7 8@unknownPtr = external global i89 10define i8 @simple() {11; CHECK-LABEL: define i8 @simple() {12; CHECK-NEXT:  entry:13; CHECK-NEXT:    [[PTR:%.*]] = alloca i8, align 114; CHECK-NEXT:    store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0:![0-9]+]]15; CHECK-NEXT:    call void @foo(ptr [[PTR]])16; CHECK-NEXT:    ret i8 4217;18entry:19  %ptr = alloca i820  store i8 42, ptr %ptr, !invariant.group !021  call void @foo(ptr %ptr)22 23  %a = load i8, ptr %ptr, !invariant.group !024  %b = load i8, ptr %ptr, !invariant.group !025  %c = load i8, ptr %ptr, !invariant.group !026  ret i8 %a27}28 29define i8 @optimizable1() {30; CHECK-LABEL: define i8 @optimizable1() {31; CHECK-NEXT:  entry:32; CHECK-NEXT:    [[PTR:%.*]] = alloca i8, align 133; CHECK-NEXT:    store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]]34; CHECK-NEXT:    [[PTR2:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[PTR]])35; CHECK-NEXT:    call void @foo(ptr [[PTR2]])36; CHECK-NEXT:    ret i8 4237;38entry:39  %ptr = alloca i840  store i8 42, ptr %ptr, !invariant.group !041  %ptr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr)42  %a = load i8, ptr %ptr, !invariant.group !043 44  call void @foo(ptr %ptr2); call to use %ptr245  ret i8 %a46}47 48define i8 @optimizable2() {49; CHECK-LABEL: define i8 @optimizable2() {50; CHECK-NEXT:  entry:51; CHECK-NEXT:    [[PTR:%.*]] = alloca i8, align 152; CHECK-NEXT:    store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]]53; CHECK-NEXT:    call void @foo(ptr [[PTR]])54; CHECK-NEXT:    store i8 13, ptr [[PTR]], align 155; CHECK-NEXT:    call void @bar(i8 13)56; CHECK-NEXT:    call void @foo(ptr [[PTR]])57; CHECK-NEXT:    ret i8 4258;59entry:60  %ptr = alloca i861  store i8 42, ptr %ptr, !invariant.group !062  call void @foo(ptr %ptr)63 64  store i8 13, ptr %ptr ; can't use this store with invariant.group65  %a = load i8, ptr %ptr66  call void @bar(i8 %a) ; call to use %a67 68  call void @foo(ptr %ptr)69  %b = load i8, ptr %ptr, !invariant.group !070 71  ret i8 %b72}73 74define i1 @proveEqualityForStrip(ptr %a) {75; CHECK-LABEL: define i1 @proveEqualityForStrip(76; CHECK-SAME: ptr [[A:%.*]]) {77; CHECK-NEXT:    ret i1 true78;79  %b1 = call ptr @llvm.strip.invariant.group.p0(ptr %a)80  %b2 = call ptr @llvm.strip.invariant.group.p0(ptr %a)81  %r = icmp eq ptr %b1, %b282  ret i1 %r83}84 85define i8 @unoptimizable1() {86; CHECK-LABEL: define i8 @unoptimizable1() {87; CHECK-NEXT:  entry:88; CHECK-NEXT:    [[PTR:%.*]] = alloca i8, align 189; CHECK-NEXT:    store i8 42, ptr [[PTR]], align 190; CHECK-NEXT:    call void @foo(ptr [[PTR]])91; CHECK-NEXT:    [[A:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]]92; CHECK-NEXT:    ret i8 [[A]]93;94entry:95  %ptr = alloca i896  store i8 42, ptr %ptr97  call void @foo(ptr %ptr)98  %a = load i8, ptr %ptr, !invariant.group !099  ret i8 %a100}101 102; NewGVN doesn't support assumes.103define void @indirectLoads() {104; CHECK-LABEL: define void @indirectLoads() {105; CHECK-NEXT:  entry:106; CHECK-NEXT:    [[A:%.*]] = alloca ptr, align 8107; CHECK-NEXT:    [[CALL:%.*]] = call ptr @getPointer(ptr null)108; CHECK-NEXT:    call void @_ZN1AC1Ev(ptr [[CALL]])109; CHECK-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[CALL]], align 8, !invariant.group [[META0]]110; CHECK-NEXT:    [[CMP_VTABLES:%.*]] = icmp eq ptr [[VTABLE]], getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2)111; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_VTABLES]])112; CHECK-NEXT:    store ptr [[CALL]], ptr [[A]], align 8113; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[VTABLE]], align 8114; CHECK-NEXT:    call void [[TMP0]](ptr [[CALL]])115; CHECK-NEXT:    [[VTABLE2:%.*]] = load ptr, ptr [[CALL]], align 8, !invariant.group [[META0]]116; CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[VTABLE2]], align 8117; CHECK-NEXT:    call void [[TMP1]](ptr [[CALL]])118; CHECK-NEXT:    [[VTABLE4:%.*]] = load ptr, ptr [[CALL]], align 8, !invariant.group [[META0]]119; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[VTABLE4]], align 8120; CHECK-NEXT:    call void [[TMP2]](ptr [[CALL]])121; CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[VTABLE]], align 8122; CHECK-NEXT:    call void [[TMP3]](ptr [[CALL]])123; CHECK-NEXT:    ret void124;125entry:126  %a = alloca ptr, align 8127 128  %call = call ptr @getPointer(ptr null)129  call void @_ZN1AC1Ev(ptr %call)130 131  %vtable = load ptr, ptr %call, align 8, !invariant.group !0132  %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2)133  call void @llvm.assume(i1 %cmp.vtables)134 135  store ptr %call, ptr %a, align 8136  %0 = load ptr, ptr %a, align 8137 138; FIXME: call void @_ZN1A3fooEv(139  %vtable1 = load ptr, ptr %0, align 8, !invariant.group !0140  %1 = load ptr, ptr %vtable1, align 8141  call void %1(ptr %0)142  %2 = load ptr, ptr %a, align 8143 144; FIXME: call void @_ZN1A3fooEv(145  %vtable2 = load ptr, ptr %2, align 8, !invariant.group !0146  %3 = load ptr, ptr %vtable2, align 8147 148  call void %3(ptr %2)149  %4 = load ptr, ptr %a, align 8150 151  %vtable4 = load ptr, ptr %4, align 8, !invariant.group !0152  %5 = load ptr, ptr %vtable4, align 8153; FIXME: call void @_ZN1A3fooEv(154  call void %5(ptr %4)155 156  %vtable5 = load ptr, ptr %call, align 8, !invariant.group !0157  %6 = load ptr, ptr %vtable5, align 8158; FIXME: call void @_ZN1A3fooEv(159  call void %6(ptr %4)160 161  ret void162}163 164; NewGVN won't CSE loads with different pointee types.165define void @combiningBitCastWithLoad() {166; CHECK-LABEL: define void @combiningBitCastWithLoad() {167; CHECK-NEXT:  entry:168; CHECK-NEXT:    [[A:%.*]] = alloca ptr, align 8169; CHECK-NEXT:    [[CALL:%.*]] = call ptr @getPointer(ptr null)170; CHECK-NEXT:    call void @_ZN1AC1Ev(ptr [[CALL]])171; CHECK-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[CALL]], align 8, !invariant.group [[META0]]172; CHECK-NEXT:    store ptr [[CALL]], ptr [[A]], align 8173; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[VTABLE]], align 8174; CHECK-NEXT:    call void [[TMP0]](ptr [[CALL]])175; CHECK-NEXT:    ret void176;177entry:178  %a = alloca ptr, align 8179 180  %call = call ptr @getPointer(ptr null)181  call void @_ZN1AC1Ev(ptr %call)182 183  %vtable = load ptr, ptr %call, align 8, !invariant.group !0184  %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2)185 186  store ptr %call, ptr %a, align 8187; FIXME-NOT: !invariant.group188  %0 = load ptr, ptr %a, align 8189 190  %vtable1 = load ptr, ptr %0, align 8, !invariant.group !0191  %1 = load ptr, ptr %vtable1, align 8192  call void %1(ptr %0)193 194  ret void195}196 197define void @loadCombine() {198; CHECK-LABEL: define void @loadCombine() {199; CHECK-NEXT:  enter:200; CHECK-NEXT:    [[PTR:%.*]] = alloca i8, align 1201; CHECK-NEXT:    store i8 42, ptr [[PTR]], align 1202; CHECK-NEXT:    call void @foo(ptr [[PTR]])203; CHECK-NEXT:    [[A:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]]204; CHECK-NEXT:    call void @bar(i8 [[A]])205; CHECK-NEXT:    call void @bar(i8 [[A]])206; CHECK-NEXT:    ret void207;208enter:209  %ptr = alloca i8210  store i8 42, ptr %ptr211  call void @foo(ptr %ptr)212  %a = load i8, ptr %ptr, !invariant.group !0213  %b = load i8, ptr %ptr, !invariant.group !0214  call void @bar(i8 %a)215  call void @bar(i8 %b)216  ret void217}218 219define void @loadCombine1() {220; CHECK-LABEL: define void @loadCombine1() {221; CHECK-NEXT:  enter:222; CHECK-NEXT:    [[PTR:%.*]] = alloca i8, align 1223; CHECK-NEXT:    store i8 42, ptr [[PTR]], align 1224; CHECK-NEXT:    call void @foo(ptr [[PTR]])225; CHECK-NEXT:    [[C:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]]226; CHECK-NEXT:    call void @bar(i8 [[C]])227; CHECK-NEXT:    call void @bar(i8 [[C]])228; CHECK-NEXT:    ret void229;230enter:231  %ptr = alloca i8232  store i8 42, ptr %ptr233  call void @foo(ptr %ptr)234  %c = load i8, ptr %ptr235  %d = load i8, ptr %ptr, !invariant.group !0236  call void @bar(i8 %c)237  call void @bar(i8 %d)238  ret void239}240 241define void @loadCombine2() {242; CHECK-LABEL: define void @loadCombine2() {243; CHECK-NEXT:  enter:244; CHECK-NEXT:    [[PTR:%.*]] = alloca i8, align 1245; CHECK-NEXT:    store i8 42, ptr [[PTR]], align 1246; CHECK-NEXT:    call void @foo(ptr [[PTR]])247; CHECK-NEXT:    [[E:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]]248; CHECK-NEXT:    call void @bar(i8 [[E]])249; CHECK-NEXT:    call void @bar(i8 [[E]])250; CHECK-NEXT:    ret void251;252enter:253  %ptr = alloca i8254  store i8 42, ptr %ptr255  call void @foo(ptr %ptr)256  %e = load i8, ptr %ptr, !invariant.group !0257  %f = load i8, ptr %ptr258  call void @bar(i8 %e)259  call void @bar(i8 %f)260  ret void261}262 263define void @loadCombine3() {264; CHECK-LABEL: define void @loadCombine3() {265; CHECK-NEXT:  enter:266; CHECK-NEXT:    [[PTR:%.*]] = alloca i8, align 1267; CHECK-NEXT:    store i8 42, ptr [[PTR]], align 1268; CHECK-NEXT:    call void @foo(ptr [[PTR]])269; CHECK-NEXT:    [[E:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]]270; CHECK-NEXT:    call void @bar(i8 [[E]])271; CHECK-NEXT:    call void @bar(i8 [[E]])272; CHECK-NEXT:    ret void273;274enter:275  %ptr = alloca i8276  store i8 42, ptr %ptr277  call void @foo(ptr %ptr)278  %e = load i8, ptr %ptr, !invariant.group !0279  %f = load i8, ptr %ptr, !invariant.group !0280  call void @bar(i8 %e)281  call void @bar(i8 %f)282  ret void283}284 285define i8 @unoptimizable2() {286; CHECK-LABEL: define i8 @unoptimizable2() {287; CHECK-NEXT:  entry:288; CHECK-NEXT:    [[PTR:%.*]] = alloca i8, align 1289; CHECK-NEXT:    store i8 42, ptr [[PTR]], align 1290; CHECK-NEXT:    call void @foo(ptr [[PTR]])291; CHECK-NEXT:    [[A:%.*]] = load i8, ptr [[PTR]], align 1292; CHECK-NEXT:    call void @foo(ptr [[PTR]])293; CHECK-NEXT:    ret i8 [[A]]294;295entry:296  %ptr = alloca i8297  store i8 42, ptr %ptr298  call void @foo(ptr %ptr)299  %a = load i8, ptr %ptr300  call void @foo(ptr %ptr)301  %b = load i8, ptr %ptr, !invariant.group !0302 303  ret i8 %a304}305 306define i8 @unoptimizable3() {307; CHECK-LABEL: define i8 @unoptimizable3() {308; CHECK-NEXT:  entry:309; CHECK-NEXT:    [[PTR:%.*]] = alloca i8, align 1310; CHECK-NEXT:    store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]]311; CHECK-NEXT:    [[PTR2:%.*]] = call ptr @getPointer(ptr [[PTR]])312; CHECK-NEXT:    [[A:%.*]] = load i8, ptr [[PTR2]], align 1, !invariant.group [[META0]]313; CHECK-NEXT:    ret i8 [[A]]314;315entry:316  %ptr = alloca i8317  store i8 42, ptr %ptr, !invariant.group !0318  %ptr2 = call ptr @getPointer(ptr %ptr)319  %a = load i8, ptr %ptr2, !invariant.group !0320 321  ret i8 %a322}323 324; NewGVN cares about the launder for some reason.325define i8 @optimizable4() {326; CHECK-LABEL: define i8 @optimizable4() {327; CHECK-NEXT:  entry:328; CHECK-NEXT:    [[PTR:%.*]] = alloca i8, align 1329; CHECK-NEXT:    store i8 42, ptr [[PTR]], align 1330; CHECK-NEXT:    [[PTR2:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[PTR]])331; CHECK-NEXT:    [[A:%.*]] = load i8, ptr [[PTR2]], align 1332; CHECK-NEXT:    ret i8 [[A]]333;334entry:335  %ptr = alloca i8336  store i8 42, ptr %ptr337  %ptr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr)338; FIXME-NOT: load339  %a = load i8, ptr %ptr2340 341; FIXME: ret i8 42342  ret i8 %a343}344 345define i8 @volatile1() {346; CHECK-LABEL: define i8 @volatile1() {347; CHECK-NEXT:  entry:348; CHECK-NEXT:    [[PTR:%.*]] = alloca i8, align 1349; CHECK-NEXT:    store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]]350; CHECK-NEXT:    call void @foo(ptr [[PTR]])351; CHECK-NEXT:    [[B:%.*]] = load volatile i8, ptr [[PTR]], align 1352; CHECK-NEXT:    call void @bar(i8 [[B]])353; CHECK-NEXT:    [[C:%.*]] = load volatile i8, ptr [[PTR]], align 1, !invariant.group [[META0]]354; CHECK-NEXT:    call void @bar(i8 [[C]])355; CHECK-NEXT:    ret i8 42356;357entry:358  %ptr = alloca i8359  store i8 42, ptr %ptr, !invariant.group !0360  call void @foo(ptr %ptr)361  %a = load i8, ptr %ptr, !invariant.group !0362  %b = load volatile i8, ptr %ptr363  call void @bar(i8 %b)364 365  %c = load volatile i8, ptr %ptr, !invariant.group !0366; We might be able to optimize this, but nobody cares367  call void @bar(i8 %c)368  ret i8 %a369}370 371define i8 @volatile2() {372; CHECK-LABEL: define i8 @volatile2() {373; CHECK-NEXT:  entry:374; CHECK-NEXT:    [[PTR:%.*]] = alloca i8, align 1375; CHECK-NEXT:    store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]]376; CHECK-NEXT:    call void @foo(ptr [[PTR]])377; CHECK-NEXT:    [[B:%.*]] = load volatile i8, ptr [[PTR]], align 1378; CHECK-NEXT:    call void @bar(i8 [[B]])379; CHECK-NEXT:    [[C:%.*]] = load volatile i8, ptr [[PTR]], align 1, !invariant.group [[META0]]380; CHECK-NEXT:    call void @bar(i8 [[C]])381; CHECK-NEXT:    ret i8 42382;383entry:384  %ptr = alloca i8385  store i8 42, ptr %ptr, !invariant.group !0386  call void @foo(ptr %ptr)387  %a = load i8, ptr %ptr, !invariant.group !0388  %b = load volatile i8, ptr %ptr389  call void @bar(i8 %b)390 391  %c = load volatile i8, ptr %ptr, !invariant.group !0392; We might be able to optimize this, but nobody cares393  call void @bar(i8 %c)394  ret i8 %a395}396 397define void @fun() {398; CHECK-LABEL: define void @fun() {399; CHECK-NEXT:  entry:400; CHECK-NEXT:    [[PTR:%.*]] = alloca i8, align 1401; CHECK-NEXT:    store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]]402; CHECK-NEXT:    call void @foo(ptr [[PTR]])403; CHECK-NEXT:    call void @bar(i8 42)404; CHECK-NEXT:    ret void405;406entry:407  %ptr = alloca i8408  store i8 42, ptr %ptr, !invariant.group !0409  call void @foo(ptr %ptr)410 411  %a = load i8, ptr %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change412  call void @bar(i8 %a)413 414  ret void415}416 417; FIXME: NewGVN doesn't run instsimplify on a load from a vtable definition?418; This test checks if invariant.group understands gep with zeros419define void @testGEP0() {420; CHECK-LABEL: define void @testGEP0() {421; CHECK-NEXT:    [[A:%.*]] = alloca [[STRUCT_A:%.*]], align 8422; CHECK-NEXT:    store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr [[A]], align 8, !invariant.group [[META0]]423; CHECK-NEXT:    call void @_ZN1A3fooEv(ptr nonnull dereferenceable(8) [[A]])424; CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr @unknownPtr, align 4425; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0426; CHECK-NEXT:    br i1 [[TMP2]], label [[_Z1GR1A_EXIT:%.*]], label [[TMP3:%.*]]427; CHECK:       3:428; CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), align 8429; CHECK-NEXT:    call void [[TMP4]](ptr nonnull [[A]])430; CHECK-NEXT:    br label [[_Z1GR1A_EXIT]]431; CHECK:       _Z1gR1A.exit:432; CHECK-NEXT:    ret void433;434  %a = alloca %struct.A, align 8435  store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr %a, align 8, !invariant.group !0436  call void @_ZN1A3fooEv(ptr nonnull dereferenceable(8) %a) ; This call may change vptr437  %1 = load i8, ptr @unknownPtr, align 4438  %2 = icmp eq i8 %1, 0439  br i1 %2, label %_Z1gR1A.exit, label %3440 441; This should be devirtualized by invariant.group442  %4 = load ptr, ptr %a, align 8, !invariant.group !0443  %5 = load ptr, ptr %4, align 8444; FIXME: call void @_ZN1A3fooEv(ptr nonnull %a)445  call void %5(ptr nonnull %a)446  br label %_Z1gR1A.exit447 448_Z1gR1A.exit:                                     ; preds = %0, %3449  ret void450}451 452; Check if no optimizations are performed with global pointers.453; FIXME: we could do the optimizations if we would check if dependency comes454; from the same function.455define void @testGlobal() {456; CHECK-LABEL: define void @testGlobal() {457; CHECK-NEXT:    [[A:%.*]] = load i8, ptr @unknownPtr, align 1, !invariant.group [[META0]]458; CHECK-NEXT:    call void @foo2(ptr @unknownPtr, i8 [[A]])459; CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr @unknownPtr, align 1, !invariant.group [[META0]]460; CHECK-NEXT:    call void @bar(i8 [[TMP1]])461; CHECK-NEXT:    call void @fooBit(ptr @unknownPtr, i1 true)462; CHECK-NEXT:    [[TMP2:%.*]] = load i1, ptr @unknownPtr, align 1, !invariant.group [[META0]]463; CHECK-NEXT:    call void @fooBit(ptr @unknownPtr, i1 [[TMP2]])464; CHECK-NEXT:    [[TMP3:%.*]] = load i1, ptr @unknownPtr, align 1, !invariant.group [[META0]]465; CHECK-NEXT:    call void @fooBit(ptr @unknownPtr, i1 [[TMP3]])466; CHECK-NEXT:    ret void467;468  %a = load i8, ptr @unknownPtr, !invariant.group !0469  call void @foo2(ptr @unknownPtr, i8 %a)470  %1 = load i8, ptr @unknownPtr, !invariant.group !0471  call void @bar(i8 %1)472 473  call void @fooBit(ptr @unknownPtr, i1 1)474; Adding regex because of canonicalization of bitcasts475  %2 = load i1, ptr @unknownPtr, !invariant.group !0476  call void @fooBit(ptr @unknownPtr, i1 %2)477  %3 = load i1, ptr @unknownPtr, !invariant.group !0478  call void @fooBit(ptr @unknownPtr, i1 %3)479  ret void480}481 482; Might be similar to above where NewGVN doesn't handle loads of different types from the same location.483; Not super important anyway.484define void @testTrunc() {485; CHECK-LABEL: define void @testTrunc() {486; CHECK-NEXT:    [[A:%.*]] = alloca i8, align 1487; CHECK-NEXT:    call void @foo(ptr [[A]])488; CHECK-NEXT:    [[B:%.*]] = load i8, ptr [[A]], align 1, !invariant.group [[META0]]489; CHECK-NEXT:    call void @foo2(ptr [[A]], i8 [[B]])490; CHECK-NEXT:    call void @bar(i8 [[B]])491; CHECK-NEXT:    call void @fooBit(ptr [[A]], i1 true)492; CHECK-NEXT:    [[TMP1:%.*]] = load i1, ptr [[A]], align 1, !invariant.group [[META0]]493; CHECK-NEXT:    call void @fooBit(ptr [[A]], i1 [[TMP1]])494; CHECK-NEXT:    call void @fooBit(ptr [[A]], i1 [[TMP1]])495; CHECK-NEXT:    ret void496;497  %a = alloca i8498  call void @foo(ptr %a)499  %b = load i8, ptr %a, !invariant.group !0500  call void @foo2(ptr %a, i8 %b)501 502  %1 = load i8, ptr %a, !invariant.group !0503  call void @bar(i8 %1)504 505  call void @fooBit(ptr %a, i1 1)506; FIXME: %1 = trunc i8 %b to i1507  %2 = load i1, ptr %a, !invariant.group !0508; FIXME-NEXT: call void @fooBit(ptr %a, i1 %1)509  call void @fooBit(ptr %a, i1 %2)510  %3 = load i1, ptr %a, !invariant.group !0511; FIXME-NEXT: call void @fooBit(ptr %a, i1 %1)512  call void @fooBit(ptr %a, i1 %3)513  ret void514}515 516; See comment in @testGEP0 on what NewGVN is lacking.517define void @handling_loops() {518; CHECK-LABEL: define void @handling_loops() {519; CHECK-NEXT:    [[A:%.*]] = alloca [[STRUCT_A:%.*]], align 8520; CHECK-NEXT:    store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr [[A]], align 8, !invariant.group [[META0]]521; CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr @unknownPtr, align 4522; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i8 [[TMP1]], 0523; CHECK-NEXT:    br i1 [[TMP2]], label [[DOTLR_PH_I:%.*]], label [[_Z2G2R1A_EXIT:%.*]]524; CHECK:       .lr.ph.i:525; CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt i8 [[TMP1]], 1526; CHECK-NEXT:    br i1 [[TMP3]], label [[DOT_CRIT_EDGE_PREHEADER:%.*]], label [[_Z2G2R1A_EXIT]]527; CHECK:       ._crit_edge.preheader:528; CHECK-NEXT:    br label [[DOT_CRIT_EDGE:%.*]]529; CHECK:       ._crit_edge:530; CHECK-NEXT:    [[TMP4:%.*]] = phi i8 [ [[TMP6:%.*]], [[DOT_CRIT_EDGE]] ], [ 1, [[DOT_CRIT_EDGE_PREHEADER]] ]531; CHECK-NEXT:    [[TMP5:%.*]] = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), align 8532; CHECK-NEXT:    call void [[TMP5]](ptr nonnull [[A]])533; CHECK-NEXT:    [[TMP6]] = add nuw nsw i8 [[TMP4]], 1534; CHECK-NEXT:    [[TMP7:%.*]] = load i8, ptr @unknownPtr, align 4535; CHECK-NEXT:    [[TMP8:%.*]] = icmp slt i8 [[TMP6]], [[TMP7]]536; CHECK-NEXT:    br i1 [[TMP8]], label [[DOT_CRIT_EDGE]], label [[_Z2G2R1A_EXIT_LOOPEXIT:%.*]]537; CHECK:       _Z2g2R1A.exit.loopexit:538; CHECK-NEXT:    br label [[_Z2G2R1A_EXIT]]539; CHECK:       _Z2g2R1A.exit:540; CHECK-NEXT:    ret void541;542  %a = alloca %struct.A, align 8543  store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr %a, align 8, !invariant.group !0544  %1 = load i8, ptr @unknownPtr, align 4545  %2 = icmp sgt i8 %1, 0546  br i1 %2, label %.lr.ph.i, label %_Z2g2R1A.exit547 548.lr.ph.i:                                         ; preds = %0549  %3 = load i8, ptr @unknownPtr, align 4550  %4 = icmp sgt i8 %3, 1551  br i1 %4, label %._crit_edge.preheader, label %_Z2g2R1A.exit552 553._crit_edge.preheader:                            ; preds = %.lr.ph.i554  br label %._crit_edge555 556._crit_edge:                                      ; preds = %._crit_edge.preheader, %._crit_edge557  %5 = phi i8 [ %7, %._crit_edge ], [ 1, %._crit_edge.preheader ]558  %.pre = load ptr, ptr %a, align 8, !invariant.group !0559  %6 = load ptr, ptr %.pre, align 8560  ; FIXME: call void @_ZN1A3fooEv(ptr nonnull %a)561  call void %6(ptr nonnull %a) #3562  ; FIXME-NOT: call void %563  %7 = add nuw nsw i8 %5, 1564  %8 = load i8, ptr @unknownPtr, align 4565  %9 = icmp slt i8 %7, %8566  br i1 %9, label %._crit_edge, label %_Z2g2R1A.exit.loopexit567 568_Z2g2R1A.exit.loopexit:                           ; preds = %._crit_edge569  br label %_Z2g2R1A.exit570 571_Z2g2R1A.exit:                                    ; preds = %_Z2g2R1A.exit.loopexit, %.lr.ph.i, %0572  ret void573}574 575 576declare void @foo(ptr)577declare void @foo2(ptr, i8)578declare void @bar(i8)579declare ptr @getPointer(ptr)580declare void @_ZN1A3fooEv(ptr)581declare void @_ZN1AC1Ev(ptr)582declare void @fooBit(ptr, i1)583 584declare ptr @llvm.launder.invariant.group.p0(ptr)585declare ptr @llvm.strip.invariant.group.p0(ptr)586 587; Function Attrs: nounwind588declare void @llvm.assume(i1 %cmp.vtables) #0589 590 591attributes #0 = { nounwind }592!0 = !{}593;.594; CHECK: [[META0]] = !{}595;.596