586 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 62; RUN: opt < %s -passes=gvn -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 74; FIXME: The first call could be also removed by GVN. Right now75; DCE removes it. The second call is CSE'd with the first one.76define i1 @proveEqualityForStrip(ptr %a) {77; CHECK-LABEL: define i1 @proveEqualityForStrip(78; CHECK-SAME: ptr [[A:%.*]]) {79; CHECK-NEXT: [[B1:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr [[A]])80; CHECK-NEXT: ret i1 true81;82 %b1 = call ptr @llvm.strip.invariant.group.p0(ptr %a)83 %b2 = call ptr @llvm.strip.invariant.group.p0(ptr %a)84 %r = icmp eq ptr %b1, %b285 ret i1 %r86}87 88define i8 @unoptimizable1() {89; CHECK-LABEL: define i8 @unoptimizable1() {90; CHECK-NEXT: [[ENTRY:.*:]]91; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 192; CHECK-NEXT: store i8 42, ptr [[PTR]], align 193; CHECK-NEXT: call void @foo(ptr [[PTR]])94; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]]95; CHECK-NEXT: ret i8 [[A]]96;97entry:98 %ptr = alloca i899 store i8 42, ptr %ptr100 call void @foo(ptr %ptr)101 %a = load i8, ptr %ptr, !invariant.group !0102 ret i8 %a103}104 105define void @indirectLoads() {106; CHECK-LABEL: define void @indirectLoads() {107; CHECK-NEXT: [[ENTRY:.*:]]108; CHECK-NEXT: [[A:%.*]] = alloca ptr, align 8109; CHECK-NEXT: [[CALL:%.*]] = call ptr @getPointer(ptr null)110; CHECK-NEXT: call void @_ZN1AC1Ev(ptr [[CALL]])111; CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[CALL]], align 8, !invariant.group [[META0]]112; CHECK-NEXT: [[CMP_VTABLES:%.*]] = icmp eq ptr [[VTABLE]], getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2)113; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_VTABLES]])114; CHECK-NEXT: store ptr [[CALL]], ptr [[A]], align 8115; CHECK-NEXT: call void @_ZN1A3fooEv(ptr [[CALL]])116; CHECK-NEXT: call void @_ZN1A3fooEv(ptr [[CALL]])117; CHECK-NEXT: call void @_ZN1A3fooEv(ptr [[CALL]])118; CHECK-NEXT: call void @_ZN1A3fooEv(ptr [[CALL]])119; CHECK-NEXT: ret void120;121entry:122 %a = alloca ptr, align 8123 124 %call = call ptr @getPointer(ptr null)125 call void @_ZN1AC1Ev(ptr %call)126 127 %vtable = load ptr, ptr %call, align 8, !invariant.group !0128 %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2)129 call void @llvm.assume(i1 %cmp.vtables)130 131 store ptr %call, ptr %a, align 8132 %0 = load ptr, ptr %a, align 8133 134 %vtable1 = load ptr, ptr %0, align 8, !invariant.group !0135 %1 = load ptr, ptr %vtable1, align 8136 call void %1(ptr %0)137 %2 = load ptr, ptr %a, align 8138 139 %vtable2 = load ptr, ptr %2, align 8, !invariant.group !0140 %3 = load ptr, ptr %vtable2, align 8141 142 call void %3(ptr %2)143 %4 = load ptr, ptr %a, align 8144 145 %vtable4 = load ptr, ptr %4, align 8, !invariant.group !0146 %5 = load ptr, ptr %vtable4, align 8147 call void %5(ptr %4)148 149 %vtable5 = load ptr, ptr %call, align 8, !invariant.group !0150 %6 = load ptr, ptr %vtable5, align 8151 call void %6(ptr %4)152 153 ret void154}155 156define void @combiningBitCastWithLoad() {157; CHECK-LABEL: define void @combiningBitCastWithLoad() {158; CHECK-NEXT: [[ENTRY:.*:]]159; CHECK-NEXT: [[A:%.*]] = alloca ptr, align 8160; CHECK-NEXT: [[CALL:%.*]] = call ptr @getPointer(ptr null)161; CHECK-NEXT: call void @_ZN1AC1Ev(ptr [[CALL]])162; CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[CALL]], align 8, !invariant.group [[META0]]163; CHECK-NEXT: [[CMP_VTABLES:%.*]] = icmp eq ptr [[VTABLE]], getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2)164; CHECK-NEXT: store ptr [[CALL]], ptr [[A]], align 8165; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VTABLE]], align 8166; CHECK-NEXT: call void [[TMP0]](ptr [[CALL]])167; CHECK-NEXT: ret void168;169entry:170 %a = alloca ptr, align 8171 172 %call = call ptr @getPointer(ptr null)173 call void @_ZN1AC1Ev(ptr %call)174 175 %vtable = load ptr, ptr %call, align 8, !invariant.group !0176 %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2)177 178 store ptr %call, ptr %a, align 8179 %0 = load ptr, ptr %a, align 8180 181 %vtable1 = load ptr, ptr %0, align 8, !invariant.group !0182 %1 = load ptr, ptr %vtable1, align 8183 call void %1(ptr %0)184 185 ret void186}187 188define void @loadCombine() {189; CHECK-LABEL: define void @loadCombine() {190; CHECK-NEXT: [[ENTER:.*:]]191; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1192; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1193; CHECK-NEXT: call void @foo(ptr [[PTR]])194; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]]195; CHECK-NEXT: call void @bar(i8 [[A]])196; CHECK-NEXT: call void @bar(i8 [[A]])197; CHECK-NEXT: ret void198;199enter:200 %ptr = alloca i8201 store i8 42, ptr %ptr202 call void @foo(ptr %ptr)203 %a = load i8, ptr %ptr, !invariant.group !0204 %b = load i8, ptr %ptr, !invariant.group !0205 call void @bar(i8 %a)206 call void @bar(i8 %b)207 ret void208}209 210define void @loadCombine1() {211; CHECK-LABEL: define void @loadCombine1() {212; CHECK-NEXT: [[ENTER:.*:]]213; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1214; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1215; CHECK-NEXT: call void @foo(ptr [[PTR]])216; CHECK-NEXT: [[C:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]]217; CHECK-NEXT: call void @bar(i8 [[C]])218; CHECK-NEXT: call void @bar(i8 [[C]])219; CHECK-NEXT: ret void220;221enter:222 %ptr = alloca i8223 store i8 42, ptr %ptr224 call void @foo(ptr %ptr)225 %c = load i8, ptr %ptr226 %d = load i8, ptr %ptr, !invariant.group !0227 call void @bar(i8 %c)228 call void @bar(i8 %d)229 ret void230}231 232define void @loadCombine2() {233; CHECK-LABEL: define void @loadCombine2() {234; CHECK-NEXT: [[ENTER:.*:]]235; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1236; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1237; CHECK-NEXT: call void @foo(ptr [[PTR]])238; CHECK-NEXT: [[E:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]]239; CHECK-NEXT: call void @bar(i8 [[E]])240; CHECK-NEXT: call void @bar(i8 [[E]])241; CHECK-NEXT: ret void242;243enter:244 %ptr = alloca i8245 store i8 42, ptr %ptr246 call void @foo(ptr %ptr)247 %e = load i8, ptr %ptr, !invariant.group !0248 %f = load i8, ptr %ptr249 call void @bar(i8 %e)250 call void @bar(i8 %f)251 ret void252}253 254define void @loadCombine3() {255; CHECK-LABEL: define void @loadCombine3() {256; CHECK-NEXT: [[ENTER:.*:]]257; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1258; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1259; CHECK-NEXT: call void @foo(ptr [[PTR]])260; CHECK-NEXT: [[E:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]]261; CHECK-NEXT: call void @bar(i8 [[E]])262; CHECK-NEXT: call void @bar(i8 [[E]])263; CHECK-NEXT: ret void264;265enter:266 %ptr = alloca i8267 store i8 42, ptr %ptr268 call void @foo(ptr %ptr)269 %e = load i8, ptr %ptr, !invariant.group !0270 %f = load i8, ptr %ptr, !invariant.group !0271 call void @bar(i8 %e)272 call void @bar(i8 %f)273 ret void274}275 276define i8 @unoptimizable2() {277; CHECK-LABEL: define i8 @unoptimizable2() {278; CHECK-NEXT: [[ENTRY:.*:]]279; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1280; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1281; CHECK-NEXT: call void @foo(ptr [[PTR]])282; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[PTR]], align 1283; CHECK-NEXT: call void @foo(ptr [[PTR]])284; CHECK-NEXT: ret i8 [[A]]285;286entry:287 %ptr = alloca i8288 store i8 42, ptr %ptr289 call void @foo(ptr %ptr)290 %a = load i8, ptr %ptr291 call void @foo(ptr %ptr)292 %b = load i8, ptr %ptr, !invariant.group !0293 294 ret i8 %a295}296 297define i8 @unoptimizable3() {298; CHECK-LABEL: define i8 @unoptimizable3() {299; CHECK-NEXT: [[ENTRY:.*:]]300; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1301; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]]302; CHECK-NEXT: [[PTR2:%.*]] = call ptr @getPointer(ptr [[PTR]])303; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[PTR2]], align 1, !invariant.group [[META0]]304; CHECK-NEXT: ret i8 [[A]]305;306entry:307 %ptr = alloca i8308 store i8 42, ptr %ptr, !invariant.group !0309 %ptr2 = call ptr @getPointer(ptr %ptr)310 %a = load i8, ptr %ptr2, !invariant.group !0311 312 ret i8 %a313}314 315define i8 @optimizable4() {316; CHECK-LABEL: define i8 @optimizable4() {317; CHECK-NEXT: [[ENTRY:.*:]]318; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1319; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]]320; CHECK-NEXT: [[PTR2:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[PTR]])321; CHECK-NEXT: ret i8 42322;323entry:324 %ptr = alloca i8325 store i8 42, ptr %ptr, !invariant.group !0326 %ptr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr)327 %a = load i8, ptr %ptr2, !invariant.group !0328 329 ret i8 %a330}331 332define i8 @volatile1() {333; CHECK-LABEL: define i8 @volatile1() {334; CHECK-NEXT: [[ENTRY:.*:]]335; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1336; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]]337; CHECK-NEXT: call void @foo(ptr [[PTR]])338; CHECK-NEXT: [[B:%.*]] = load volatile i8, ptr [[PTR]], align 1339; CHECK-NEXT: call void @bar(i8 [[B]])340; CHECK-NEXT: [[C:%.*]] = load volatile i8, ptr [[PTR]], align 1, !invariant.group [[META0]]341; CHECK-NEXT: call void @bar(i8 [[C]])342; CHECK-NEXT: ret i8 42343;344entry:345 %ptr = alloca i8346 store i8 42, ptr %ptr, !invariant.group !0347 call void @foo(ptr %ptr)348 %a = load i8, ptr %ptr, !invariant.group !0349 %b = load volatile i8, ptr %ptr350 call void @bar(i8 %b)351 352 %c = load volatile i8, ptr %ptr, !invariant.group !0353; FIXME: we could change %c to 42, preserving volatile load354 call void @bar(i8 %c)355 ret i8 %a356}357 358define i8 @volatile2() {359; CHECK-LABEL: define i8 @volatile2() {360; CHECK-NEXT: [[ENTRY:.*:]]361; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1362; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]]363; CHECK-NEXT: call void @foo(ptr [[PTR]])364; CHECK-NEXT: [[B:%.*]] = load volatile i8, ptr [[PTR]], align 1365; CHECK-NEXT: call void @bar(i8 [[B]])366; CHECK-NEXT: [[C:%.*]] = load volatile i8, ptr [[PTR]], align 1, !invariant.group [[META0]]367; CHECK-NEXT: call void @bar(i8 [[C]])368; CHECK-NEXT: ret i8 42369;370entry:371 %ptr = alloca i8372 store i8 42, ptr %ptr, !invariant.group !0373 call void @foo(ptr %ptr)374 %a = load i8, ptr %ptr, !invariant.group !0375 %b = load volatile i8, ptr %ptr376 call void @bar(i8 %b)377 378 %c = load volatile i8, ptr %ptr, !invariant.group !0379; FIXME: we could change %c to 42, preserving volatile load380 call void @bar(i8 %c)381 ret i8 %a382}383 384define i8 @fun() {385; CHECK-LABEL: define i8 @fun() {386; CHECK-NEXT: [[ENTRY:.*:]]387; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1388; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]]389; CHECK-NEXT: call void @foo(ptr [[PTR]])390; CHECK-NEXT: call void @bar(i8 42)391; CHECK-NEXT: [[NEWPTR:%.*]] = call ptr @getPointer(ptr [[PTR]])392; CHECK-NEXT: [[C:%.*]] = load i8, ptr [[NEWPTR]], align 1, !invariant.group [[META0]]393; CHECK-NEXT: call void @bar(i8 [[C]])394; CHECK-NEXT: [[UNKNOWNVALUE:%.*]] = load i8, ptr @unknownPtr, align 1395; CHECK-NEXT: store i8 [[UNKNOWNVALUE]], ptr [[PTR]], align 1, !invariant.group [[META0]]396; CHECK-NEXT: [[NEWPTR2:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[PTR]])397; CHECK-NEXT: ret i8 [[UNKNOWNVALUE]]398;399entry:400 %ptr = alloca i8401 store i8 42, ptr %ptr, !invariant.group !0402 call void @foo(ptr %ptr)403 404 %a = load i8, ptr %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change405 call void @bar(i8 %a)406 407 %newPtr = call ptr @getPointer(ptr %ptr)408 %c = load i8, ptr %newPtr, !invariant.group !0 ; Can't assume anything, because we only have information about %ptr409 call void @bar(i8 %c)410 411 %unknownValue = load i8, ptr @unknownPtr412; FIXME: Can assume that %unknownValue == 42413 store i8 %unknownValue, ptr %ptr, !invariant.group !0414 415 %newPtr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr)416 %d = load i8, ptr %newPtr2, !invariant.group !0417 ret i8 %d418}419 420; This test checks if invariant.group understands gep with zeros421define void @testGEP0() {422; CHECK-LABEL: define void @testGEP0() {423; CHECK-NEXT: [[A:%.*]] = alloca [[STRUCT_A:%.*]], align 8424; CHECK-NEXT: store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr [[A]], align 8, !invariant.group [[META0]]425; CHECK-NEXT: call void @_ZN1A3fooEv(ptr nonnull dereferenceable(8) [[A]])426; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr @unknownPtr, align 4427; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0428; CHECK-NEXT: br i1 [[TMP2]], label %[[_Z1GR1A_EXIT:.*]], label %[[BB3:.*]]429; CHECK: [[BB3]]:430; CHECK-NEXT: call void @_ZN1A3fooEv(ptr nonnull [[A]])431; CHECK-NEXT: br label %[[_Z1GR1A_EXIT]]432; CHECK: [[_Z1GR1A_EXIT]]:433; CHECK-NEXT: ret void434;435 %a = alloca %struct.A, align 8436 store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr %a, align 8, !invariant.group !0437 call void @_ZN1A3fooEv(ptr nonnull dereferenceable(8) %a) ; This call may change vptr438 %1 = load i8, ptr @unknownPtr, align 4439 %2 = icmp eq i8 %1, 0440 br i1 %2, label %_Z1gR1A.exit, label %3441 442; This should be devirtualized by invariant.group443 %4 = load ptr, ptr %a, align 8, !invariant.group !0444 %5 = load ptr, ptr %4, align 8445 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; And in the case it is not global482define void @testNotGlobal() {483; CHECK-LABEL: define void @testNotGlobal() {484; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1485; CHECK-NEXT: call void @foo(ptr [[A]])486; CHECK-NEXT: [[B:%.*]] = load i8, ptr [[A]], align 1, !invariant.group [[META0]]487; CHECK-NEXT: call void @foo2(ptr [[A]], i8 [[B]])488; CHECK-NEXT: call void @bar(i8 [[B]])489; CHECK-NEXT: call void @fooBit(ptr [[A]], i1 true)490; CHECK-NEXT: [[TMP1:%.*]] = trunc i8 [[B]] to i1491; CHECK-NEXT: call void @fooBit(ptr [[A]], i1 [[TMP1]])492; CHECK-NEXT: call void @fooBit(ptr [[A]], i1 [[TMP1]])493; CHECK-NEXT: ret void494;495 %a = alloca i8496 call void @foo(ptr %a)497 %b = load i8, ptr %a, !invariant.group !0498 call void @foo2(ptr %a, i8 %b)499 500 %1 = load i8, ptr %a, !invariant.group !0501 call void @bar(i8 %1)502 503 call void @fooBit(ptr %a, i1 1)504 %2 = load i1, ptr %a, !invariant.group !0505 call void @fooBit(ptr %a, i1 %2)506 %3 = load i1, ptr %a, !invariant.group !0507 call void @fooBit(ptr %a, i1 %3)508 ret void509}510 511define void @handling_loops() {512; CHECK-LABEL: define void @handling_loops() {513; CHECK-NEXT: [[A:%.*]] = alloca [[STRUCT_A:%.*]], align 8514; CHECK-NEXT: store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr [[A]], align 8, !invariant.group [[META0]]515; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr @unknownPtr, align 4516; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i8 [[TMP1]], 0517; CHECK-NEXT: br i1 [[TMP2]], [[DOTLR_PH_I:label %.*]], label %[[_Z2G2R1A_EXIT:.*]]518; CHECK: [[_LR_PH_I:.*:]]519; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i8 [[TMP1]], 1520; CHECK-NEXT: br i1 [[TMP3]], label %[[DOT_CRIT_EDGE_PREHEADER:.*]], label %[[_Z2G2R1A_EXIT]]521; CHECK: [[__CRIT_EDGE_PREHEADER:.*:]]522; CHECK-NEXT: br label %[[DOT_CRIT_EDGE:.*]]523; CHECK: [[__CRIT_EDGE:.*:]]524; CHECK-NEXT: [[TMP4:%.*]] = phi i8 [ [[TMP5:%.*]], %[[DOT_CRIT_EDGE]] ], [ 1, %[[DOT_CRIT_EDGE_PREHEADER]] ]525; CHECK-NEXT: call void @_ZN1A3fooEv(ptr nonnull [[A]])526; CHECK-NEXT: [[TMP5]] = add nuw nsw i8 [[TMP4]], 1527; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr @unknownPtr, align 4528; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i8 [[TMP5]], [[TMP6]]529; CHECK-NEXT: br i1 [[TMP7]], label %[[DOT_CRIT_EDGE]], label %[[_Z2G2R1A_EXIT_LOOPEXIT:.*]]530; CHECK: [[_Z2G2R1A_EXIT_LOOPEXIT]]:531; CHECK-NEXT: br label %[[_Z2G2R1A_EXIT]]532; CHECK: [[_Z2G2R1A_EXIT]]:533; CHECK-NEXT: ret void534;535 %a = alloca %struct.A, align 8536 store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr %a, align 8, !invariant.group !0537 %1 = load i8, ptr @unknownPtr, align 4538 %2 = icmp sgt i8 %1, 0539 br i1 %2, label %.lr.ph.i, label %_Z2g2R1A.exit540 541.lr.ph.i: ; preds = %0542 %3 = load i8, ptr @unknownPtr, align 4543 %4 = icmp sgt i8 %3, 1544 br i1 %4, label %._crit_edge.preheader, label %_Z2g2R1A.exit545 546._crit_edge.preheader: ; preds = %.lr.ph.i547 br label %._crit_edge548 549._crit_edge: ; preds = %._crit_edge.preheader, %._crit_edge550 %5 = phi i8 [ %7, %._crit_edge ], [ 1, %._crit_edge.preheader ]551 %.pre = load ptr, ptr %a, align 8, !invariant.group !0552 %6 = load ptr, ptr %.pre, align 8553 call void %6(ptr nonnull %a) #3554 %7 = add nuw nsw i8 %5, 1555 %8 = load i8, ptr @unknownPtr, align 4556 %9 = icmp slt i8 %7, %8557 br i1 %9, label %._crit_edge, label %_Z2g2R1A.exit.loopexit558 559_Z2g2R1A.exit.loopexit: ; preds = %._crit_edge560 br label %_Z2g2R1A.exit561 562_Z2g2R1A.exit: ; preds = %_Z2g2R1A.exit.loopexit, %.lr.ph.i, %0563 ret void564}565 566 567declare void @foo(ptr)568declare void @foo2(ptr, i8)569declare void @bar(i8)570declare ptr @getPointer(ptr)571declare void @_ZN1A3fooEv(ptr)572declare void @_ZN1AC1Ev(ptr)573declare void @fooBit(ptr, i1)574 575declare ptr @llvm.launder.invariant.group.p0(ptr)576declare ptr @llvm.strip.invariant.group.p0(ptr)577 578 579declare void @llvm.assume(i1 %cmp.vtables)580 581 582!0 = !{}583;.584; CHECK: [[META0]] = !{}585;.586