1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes='loop-mssa(simple-loop-unswitch<nontrivial>),loop-mssa(simple-loop-unswitch<nontrivial>),verify<loops>' -S < %s | FileCheck %s 3 4; Below bugs have caused endless unswitch. 5; 6; https://bugs.llvm.org/show_bug.cgi?id=50279 7; https://bugs.llvm.org/show_bug.cgi?id=50302 8; 9; This test's loop should be unswitched only one time even though we run 10; SimpleLoopUnswitch pass two times. 11 12@a = dso_local local_unnamed_addr global i32 0, align 4 13@c = dso_local local_unnamed_addr global i32 0, align 4 14@b = dso_local local_unnamed_addr global i8 0, align 1 15 16; Function Attrs: nofree norecurse nosync nounwind uwtable 17define dso_local void @d() { 18; CHECK-LABEL: @d( 19; CHECK-NEXT: entry: 20; CHECK-NEXT: br label [[FOR_COND:%.*]] 21; CHECK: for.cond: 22; CHECK-NEXT: br i1 false, label [[FOR_END:%.*]], label [[FOR_COND]] 23; CHECK: for.end: 24; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr null, align 2 25; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i16 [[TMP0]], 0 26; CHECK-NEXT: br i1 [[TMP1]], label [[FOR_END_SPLIT:%.*]], label [[FOR_END_SPLIT_US:%.*]] 27; CHECK: for.end.split.us: 28; CHECK-NEXT: br label [[G_US:%.*]] 29; CHECK: g.us: 30; CHECK-NEXT: br label [[G_SPLIT_US6:%.*]] 31; CHECK: for.cond1.us1: 32; CHECK-NEXT: [[TMP2:%.*]] = load i16, ptr null, align 2 33; CHECK-NEXT: [[TOBOOL4_NOT_US:%.*]] = icmp eq i16 [[TMP2]], 0 34; CHECK-NEXT: br i1 [[TOBOOL4_NOT_US]], label [[FOR_COND5_PREHEADER_US4:%.*]], label [[G_LOOPEXIT_US:%.*]] 35; CHECK: for.cond5.us2: 36; CHECK-NEXT: br i1 false, label [[FOR_COND1_LOOPEXIT_US5:%.*]], label [[FOR_INC_US3:%.*]] 37; CHECK: for.inc.us3: 38; CHECK-NEXT: store i8 0, ptr @b, align 1 39; CHECK-NEXT: br label [[FOR_COND5_US2:%.*]] 40; CHECK: for.cond5.preheader.us4: 41; CHECK-NEXT: br label [[FOR_COND5_US2]] 42; CHECK: for.cond1.loopexit.us5: 43; CHECK-NEXT: br label [[FOR_COND1_US1:%.*]], !llvm.loop [[LOOP0:![0-9]+]] 44; CHECK: g.loopexit.us: 45; CHECK-NEXT: br label [[G_US]] 46; CHECK: g.split.us6: 47; CHECK-NEXT: br label [[FOR_COND1_US1]] 48; CHECK: for.end.split: 49; CHECK-NEXT: br label [[G:%.*]] 50; CHECK: g.loopexit: 51; CHECK-NEXT: br label [[G]], !llvm.loop [[LOOP2:![0-9]+]] 52; CHECK: g: 53; CHECK-NEXT: [[TMP3:%.*]] = load i16, ptr null, align 2 54; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i16 [[TMP3]], 0 55; CHECK-NEXT: br i1 [[TMP4]], label [[G_SPLIT_US:%.*]], label [[G_SPLIT:%.*]] 56; CHECK: g.split.us: 57; CHECK-NEXT: br label [[FOR_COND1_US:%.*]] 58; CHECK: for.cond1.us: 59; CHECK-NEXT: br label [[FOR_COND5_PREHEADER_US:%.*]] 60; CHECK: for.cond5.us: 61; CHECK-NEXT: br i1 false, label [[FOR_COND1_LOOPEXIT_US:%.*]], label [[FOR_INC_US:%.*]] 62; CHECK: for.inc.us: 63; CHECK-NEXT: store i8 0, ptr @b, align 1 64; CHECK-NEXT: br label [[FOR_COND5_US:%.*]] 65; CHECK: for.cond5.preheader.us: 66; CHECK-NEXT: br label [[FOR_COND5_US]] 67; CHECK: for.cond1.loopexit.us: 68; CHECK-NEXT: br label [[FOR_COND1_US]] 69; CHECK: g.split: 70; CHECK-NEXT: br label [[FOR_COND1:%.*]] 71; CHECK: for.cond1.loopexit: 72; CHECK-NEXT: br label [[FOR_COND1]], !llvm.loop [[LOOP0]] 73; CHECK: for.cond1: 74; CHECK-NEXT: [[TMP5:%.*]] = load i16, ptr null, align 2 75; CHECK-NEXT: [[TOBOOL4_NOT:%.*]] = icmp eq i16 [[TMP5]], 0 76; CHECK-NEXT: br i1 [[TOBOOL4_NOT]], label [[FOR_COND5_PREHEADER:%.*]], label [[G_LOOPEXIT:%.*]] 77; CHECK: for.cond5.preheader: 78; CHECK-NEXT: br label [[FOR_COND5:%.*]] 79; CHECK: for.cond5: 80; CHECK-NEXT: br i1 false, label [[FOR_COND1_LOOPEXIT:%.*]], label [[FOR_INC:%.*]] 81; CHECK: for.inc: 82; CHECK-NEXT: store i8 0, ptr @b, align 1 83; CHECK-NEXT: br label [[FOR_COND5]] 84; 85entry: 86 br label %for.cond 87 88for.cond: ; preds = %for.cond, %entry 89 br i1 false, label %for.end, label %for.cond 90 91for.end: ; preds = %for.cond 92 br label %g 93 94g: ; preds = %for.cond1, %for.end 95 br label %for.cond1 96 97for.cond1: ; preds = %for.cond5, %g 98 %0 = load i16, ptr null, align 2 99 %tobool4.not = icmp eq i16 %0, 0 100 br i1 %tobool4.not, label %for.cond5, label %g 101 102for.cond5: ; preds = %for.inc, %for.cond1 103 br i1 false, label %for.cond1, label %for.inc 104 105for.inc: ; preds = %for.cond5 106 store i8 0, ptr @b, align 1 107 br label %for.cond5 108} 109 110define void @e(ptr %p) { 111; CHECK-LABEL: @e( 112; CHECK-NEXT: entry: 113; CHECK-NEXT: br label [[FOR_COND:%.*]] 114; CHECK: for.cond: 115; CHECK-NEXT: br i1 false, label [[FOR_END:%.*]], label [[FOR_COND]] 116; CHECK: for.end: 117; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[P:%.*]], align 2 118; CHECK-NEXT: [[TMP1:%.*]] = trunc i16 [[TMP0]] to i1 119; CHECK-NEXT: br i1 [[TMP1]], label [[FOR_END_SPLIT:%.*]], label [[FOR_END_SPLIT_US:%.*]] 120; CHECK: for.end.split.us: 121; CHECK-NEXT: br label [[G_US:%.*]] 122; CHECK: g.us: 123; CHECK-NEXT: br label [[G_SPLIT_US6:%.*]] 124; CHECK: for.cond1.us1: 125; CHECK-NEXT: [[TMP2:%.*]] = load i16, ptr [[P]], align 2 126; CHECK-NEXT: [[TOBOOL4_NOT_US:%.*]] = trunc i16 [[TMP2]] to i1 127; CHECK-NEXT: br i1 [[TOBOOL4_NOT_US]], label [[FOR_COND5_PREHEADER_US4:%.*]], label [[G_LOOPEXIT_US:%.*]] 128; CHECK: for.cond5.us2: 129; CHECK-NEXT: br i1 false, label [[FOR_COND1_LOOPEXIT_US5:%.*]], label [[FOR_INC_US3:%.*]] 130; CHECK: for.inc.us3: 131; CHECK-NEXT: store i8 0, ptr @b, align 1 132; CHECK-NEXT: br label [[FOR_COND5_US2:%.*]] 133; CHECK: for.cond5.preheader.us4: 134; CHECK-NEXT: br label [[FOR_COND5_US2]] 135; CHECK: for.cond1.loopexit.us5: 136; CHECK-NEXT: br label [[FOR_COND1_US1:%.*]], !llvm.loop [[LOOP3:![0-9]+]] 137; CHECK: g.loopexit.us: 138; CHECK-NEXT: br label [[G_US]] 139; CHECK: g.split.us6: 140; CHECK-NEXT: br label [[FOR_COND1_US1]] 141; CHECK: for.end.split: 142; CHECK-NEXT: br label [[G:%.*]] 143; CHECK: g.loopexit: 144; CHECK-NEXT: br label [[G]], !llvm.loop [[LOOP4:![0-9]+]] 145; CHECK: g: 146; CHECK-NEXT: [[TMP3:%.*]] = load i16, ptr [[P]], align 2 147; CHECK-NEXT: [[TMP4:%.*]] = trunc i16 [[TMP3]] to i1 148; CHECK-NEXT: br i1 [[TMP4]], label [[G_SPLIT_US:%.*]], label [[G_SPLIT:%.*]] 149; CHECK: g.split.us: 150; CHECK-NEXT: br label [[FOR_COND1_US:%.*]] 151; CHECK: for.cond1.us: 152; CHECK-NEXT: br label [[FOR_COND5_PREHEADER_US:%.*]] 153; CHECK: for.cond5.us: 154; CHECK-NEXT: br i1 false, label [[FOR_COND1_LOOPEXIT_US:%.*]], label [[FOR_INC_US:%.*]] 155; CHECK: for.inc.us: 156; CHECK-NEXT: store i8 0, ptr @b, align 1 157; CHECK-NEXT: br label [[FOR_COND5_US:%.*]] 158; CHECK: for.cond5.preheader.us: 159; CHECK-NEXT: br label [[FOR_COND5_US]] 160; CHECK: for.cond1.loopexit.us: 161; CHECK-NEXT: br label [[FOR_COND1_US]] 162; CHECK: g.split: 163; CHECK-NEXT: br label [[FOR_COND1:%.*]] 164; CHECK: for.cond1.loopexit: 165; CHECK-NEXT: br label [[FOR_COND1]], !llvm.loop [[LOOP3]] 166; CHECK: for.cond1: 167; CHECK-NEXT: [[TMP5:%.*]] = load i16, ptr [[P]], align 2 168; CHECK-NEXT: [[TOBOOL4_NOT:%.*]] = trunc i16 [[TMP5]] to i1 169; CHECK-NEXT: br i1 [[TOBOOL4_NOT]], label [[FOR_COND5_PREHEADER:%.*]], label [[G_LOOPEXIT:%.*]] 170; CHECK: for.cond5.preheader: 171; CHECK-NEXT: br label [[FOR_COND5:%.*]] 172; CHECK: for.cond5: 173; CHECK-NEXT: br i1 false, label [[FOR_COND1_LOOPEXIT:%.*]], label [[FOR_INC:%.*]] 174; CHECK: for.inc: 175; CHECK-NEXT: store i8 0, ptr @b, align 1 176; CHECK-NEXT: br label [[FOR_COND5]] 177; 178entry: 179 br label %for.cond 180 181for.cond: ; preds = %for.cond, %entry 182 br i1 false, label %for.end, label %for.cond 183 184for.end: ; preds = %for.cond 185 br label %g 186 187g: ; preds = %for.cond1, %for.end 188 br label %for.cond1 189 190for.cond1: ; preds = %for.cond5, %g 191 %0 = load i16, ptr %p, align 2 192 %tobool4.not = trunc i16 %0 to i1 193 br i1 %tobool4.not, label %for.cond5, label %g 194 195for.cond5: ; preds = %for.inc, %for.cond1 196 br i1 false, label %for.cond1, label %for.inc 197 198for.inc: ; preds = %for.cond5 199 store i8 0, ptr @b, align 1 200 br label %for.cond5 201} 202