1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes='bdce,sroa<preserve-cfg>,bdce' -S | FileCheck %s --check-prefixes=CHECK,CHECK-PRESERVE-CFG 3; RUN: opt < %s -passes='bdce,sroa<modify-cfg>,bdce' -S | FileCheck %s --check-prefixes=CHECK,CHECK-MODIFY-CFG 4 5; SROA fails to rewrite allocs but does rewrite some phis and delete 6; dead instructions. Ensure that this invalidates analyses required 7; for other passes. 8 9target datalayout = "e-m:e-i64:64-n32:64" 10target triple = "powerpc64le-grtev4-linux-gnu" 11 12%class.b = type { i64 } 13 14declare void @D(ptr sret(%class.b), ptr dereferenceable(32)) local_unnamed_addr 15 16; Function Attrs: nounwind 17define void @H(ptr noalias nocapture readnone, [2 x i64], ptr %ptr, i32 signext %v, i64 %l, i64 %idx, ptr nonnull dereferenceable(32) %ptr2) { 18; CHECK-LABEL: @H( 19; CHECK-NEXT: [[TMP3:%.*]] = alloca [[CLASS_B:%.*]], align 8 20; CHECK-NEXT: [[TMP4:%.*]] = extractvalue [2 x i64] [[TMP1:%.*]], 1 21; CHECK-NEXT: switch i64 [[TMP4]], label [[TMP6:%.*]] [ 22; CHECK-NEXT: i64 4, label [[FOO:%.*]] 23; CHECK-NEXT: i64 5, label [[TMP5:%.*]] 24; CHECK-NEXT: ] 25; CHECK: 5: 26; CHECK-NEXT: br label [[TMP12:%.*]] 27; CHECK: 6: 28; CHECK-NEXT: [[TMP7:%.*]] = icmp ugt i64 [[TMP4]], 5 29; CHECK-NEXT: br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP12]] 30; CHECK: 8: 31; CHECK-NEXT: [[TMP9:%.*]] = load i8, ptr inttoptr (i64 4 to ptr), align 4 32; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i8 [[TMP9]], 47 33; CHECK-NEXT: [[TMP11:%.*]] = select i1 [[TMP10]], i64 5, i64 4 34; CHECK-NEXT: br label [[TMP12]] 35; CHECK: 12: 36; CHECK-NEXT: [[TMP13:%.*]] = phi i64 [ 4, [[TMP5]] ], [ [[TMP11]], [[TMP8]] ], [ 4, [[TMP6]] ] 37; CHECK-NEXT: [[TMP14:%.*]] = icmp ne i64 [[TMP4]], 0 38; CHECK-NEXT: [[TMP15:%.*]] = icmp ugt i64 [[TMP4]], [[TMP13]] 39; CHECK-NEXT: [[TMP16:%.*]] = and i1 [[TMP14]], [[TMP15]] 40; CHECK-NEXT: br i1 [[TMP16]], label [[TMP17:%.*]], label [[A_EXIT:%.*]] 41; CHECK: 17: 42; CHECK-NEXT: [[TMP18:%.*]] = tail call ptr @memchr(ptr [[PTR:%.*]], i32 signext [[V:%.*]], i64 [[L:%.*]]) 43; CHECK-NEXT: [[TMP19:%.*]] = icmp eq ptr [[TMP18]], null 44; CHECK-NEXT: [[TMP20:%.*]] = sext i1 [[TMP19]] to i64 45; CHECK-NEXT: br label [[A_EXIT]] 46; CHECK: a.exit: 47; CHECK-NEXT: [[TMP21:%.*]] = phi i64 [ -1, [[TMP12]] ], [ [[TMP20]], [[TMP17]] ] 48; CHECK-NEXT: [[TMP22:%.*]] = inttoptr i64 0 to ptr 49; CHECK-NEXT: [[TMP23:%.*]] = sub nsw i64 [[TMP21]], [[TMP13]] 50; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[TMP3]]) 51; CHECK-NEXT: [[TMP24:%.*]] = icmp ult i64 [[TMP23]], 2 52; CHECK-NEXT: br i1 [[TMP24]], label [[G_EXIT:%.*]], label [[TMP25:%.*]] 53; CHECK: 25: 54; CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds i8, ptr [[TMP22]], i64 [[IDX:%.*]] 55; CHECK-NEXT: [[TMP27:%.*]] = icmp eq ptr [[TMP26]], null 56; CHECK-NEXT: br i1 [[TMP27]], label [[TMP28:%.*]], label [[TMP29:%.*]] 57; CHECK: 28: 58; CHECK-NEXT: unreachable 59; CHECK: 29: 60; CHECK-NEXT: call void @D(ptr nonnull sret([[CLASS_B]]) [[TMP3]], ptr nonnull dereferenceable(32) [[PTR2:%.*]]) 61; CHECK-NEXT: br label [[G_EXIT]] 62; CHECK: G.exit: 63; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[TMP3]]) 64; CHECK-NEXT: br label [[FOO]] 65; CHECK: foo: 66; CHECK-NEXT: ret void 67; 68 %3 = alloca %class.b, align 8 69 %.sroa.0 = alloca i64, align 8 70 store i64 0, ptr %.sroa.0, align 8 71 %4 = extractvalue [2 x i64] %1, 1 72 switch i64 %4, label %6 [ 73 i64 4, label %foo 74 i64 5, label %5 75 ] 76 77; <label>:5: 78 br label %12 79 80; <label>:6: 81 %7 = icmp ugt i64 %4, 5 82 br i1 %7, label %8, label %12 83 84; <label>:8: 85 %9 = load i8, ptr inttoptr (i64 4 to ptr), align 4 86 %10 = icmp eq i8 %9, 47 87 %11 = select i1 %10, i64 5, i64 4 88 br label %12 89 90; <label>:12: 91 %13 = phi ptr [ %.sroa.0, %5 ], [ %.sroa.0, %8 ], [ %.sroa.0, %6 ] 92 %14 = phi i64 [ 4, %5 ], [ %11, %8 ], [ 4, %6 ] 93 %15 = icmp ne i64 %4, 0 94 %16 = icmp ugt i64 %4, %14 95 %17 = and i1 %15, %16 96 br i1 %17, label %18, label %a.exit 97 98; <label>:18: 99 %19 = tail call ptr @memchr(ptr %ptr, i32 signext %v, i64 %l) 100 %20 = icmp eq ptr %19, null 101 %21 = sext i1 %20 to i64 102 br label %a.exit 103 104a.exit: 105 %22 = phi i64 [ -1, %12 ], [ %21, %18 ] 106 %23 = load ptr, ptr %13, align 8 107 %24 = sub nsw i64 %22, %14 108 call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %3) 109 %25 = icmp ult i64 %24, 2 110 br i1 %25, label %G.exit, label %26 111 112; <label>:27: 113 %27 = getelementptr inbounds i8, ptr %23, i64 %idx 114 %28 = icmp eq ptr %27, null 115 br i1 %28, label %29, label %30 116 117; <label>:30: 118 unreachable 119 120; <label>:31: 121 call void @D(ptr nonnull sret(%class.b) %3, ptr nonnull dereferenceable(32) %ptr2) 122 br label %G.exit 123 124G.exit: 125 call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %3) 126 br label %foo 127 128foo: 129 ret void 130} 131 132; Function Attrs: nounwind readonly 133declare ptr @memchr(ptr, i32 signext, i64) local_unnamed_addr 134 135; Function Attrs: argmemonly nounwind 136declare void @llvm.lifetime.start.p0(i64, ptr nocapture) 137 138; Function Attrs: argmemonly nounwind 139declare void @llvm.lifetime.end.p0(i64, ptr nocapture) 140;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: 141; CHECK-MODIFY-CFG: {{.*}} 142; CHECK-PRESERVE-CFG: {{.*}} 143