222 lines · cpp
1// RUN: %clang_cc1 -fnamed-loops -triple x86_64-unknown-linux -std=c++20 -emit-llvm -o - %s | FileCheck %s2 3static int a[10]{};4struct NonTrivialDestructor {5 ~NonTrivialDestructor();6};7 8bool g(int);9bool h();10 11// CHECK-LABEL: define {{.*}} void @_Z2f1v()12// CHECK: entry:13// CHECK: %__range1 = alloca ptr, align 814// CHECK: %__begin1 = alloca ptr, align 815// CHECK: %__end1 = alloca ptr, align 816// CHECK: %i = alloca i32, align 417// CHECK: br label %x18// CHECK: x:19// CHECK: store ptr @_ZL1a, ptr %__range1, align 820// CHECK: store ptr @_ZL1a, ptr %__begin1, align 821// CHECK: store ptr getelementptr inbounds (i32, ptr @_ZL1a, i64 10), ptr %__end1, align 822// CHECK: br label %for.cond23// CHECK: for.cond:24// CHECK: %0 = load ptr, ptr %__begin1, align 825// CHECK: %1 = load ptr, ptr %__end1, align 826// CHECK: %cmp = icmp ne ptr %0, %127// CHECK: br i1 %cmp, label %for.body, label %for.end28// CHECK: for.body:29// CHECK: %2 = load ptr, ptr %__begin1, align 830// CHECK: %3 = load i32, ptr %2, align 431// CHECK: store i32 %3, ptr %i, align 432// CHECK: %4 = load i32, ptr %i, align 433// CHECK: %call = call {{.*}} i1 @_Z1gi(i32 {{.*}} %4)34// CHECK: br i1 %call, label %if.then, label %if.end35// CHECK: if.then:36// CHECK: br label %for.end37// CHECK: if.end:38// CHECK: %5 = load i32, ptr %i, align 439// CHECK: %call1 = call {{.*}} i1 @_Z1gi(i32 {{.*}} %5)40// CHECK: br i1 %call1, label %if.then2, label %if.end341// CHECK: if.then2:42// CHECK: br label %for.inc43// CHECK: if.end3:44// CHECK: br label %for.inc45// CHECK: for.inc:46// CHECK: %6 = load ptr, ptr %__begin1, align 847// CHECK: %incdec.ptr = getelementptr inbounds nuw i32, ptr %6, i32 148// CHECK: store ptr %incdec.ptr, ptr %__begin1, align 849// CHECK: br label %for.cond50// CHECK: for.end:51// CHECK: ret void52void f1() {53 x: for (int i : a) {54 if (g(i)) break x;55 if (g(i)) continue x;56 }57}58 59// CHECK-LABEL: define {{.*}} void @_Z2f2v()60// CHECK: entry:61// CHECK: %n1 = alloca %struct.NonTrivialDestructor, align 162// CHECK: %__range2 = alloca ptr, align 863// CHECK: %__begin2 = alloca ptr, align 864// CHECK: %__end2 = alloca ptr, align 865// CHECK: %i = alloca i32, align 466// CHECK: %n2 = alloca %struct.NonTrivialDestructor, align 167// CHECK: %cleanup.dest.slot = alloca i32, align 468// CHECK: %n3 = alloca %struct.NonTrivialDestructor, align 169// CHECK: %n4 = alloca %struct.NonTrivialDestructor, align 170// CHECK: br label %l171// CHECK: l1:72// CHECK: br label %while.cond73// CHECK: while.cond:74// CHECK: %call = call {{.*}} i1 @_Z1gi(i32 {{.*}} 0)75// CHECK: br i1 %call, label %while.body, label %while.end76// CHECK: while.body:77// CHECK: br label %l278// CHECK: l2:79// CHECK: store ptr @_ZL1a, ptr %__range2, align 880// CHECK: store ptr @_ZL1a, ptr %__begin2, align 881// CHECK: store ptr getelementptr inbounds (i32, ptr @_ZL1a, i64 10), ptr %__end2, align 882// CHECK: br label %for.cond83// CHECK: for.cond:84// CHECK: %0 = load ptr, ptr %__begin2, align 885// CHECK: %1 = load ptr, ptr %__end2, align 886// CHECK: %cmp = icmp ne ptr %0, %187// CHECK: br i1 %cmp, label %for.body, label %for.end88// CHECK: for.body:89// CHECK: %2 = load ptr, ptr %__begin2, align 890// CHECK: %3 = load i32, ptr %2, align 491// CHECK: store i32 %3, ptr %i, align 492// CHECK: %4 = load i32, ptr %i, align 493// CHECK: %call1 = call {{.*}} i1 @_Z1gi(i32 {{.*}} %4)94// CHECK: br i1 %call1, label %if.then, label %if.end95// CHECK: if.then:96// CHECK: store i32 4, ptr %cleanup.dest.slot, align 497// CHECK: br label %cleanup98// CHECK: if.end:99// CHECK: %5 = load i32, ptr %i, align 4100// CHECK: %call2 = call {{.*}} i1 @_Z1gi(i32 {{.*}} %5)101// CHECK: br i1 %call2, label %if.then3, label %if.end4102// CHECK: if.then3:103// CHECK: store i32 3, ptr %cleanup.dest.slot, align 4104// CHECK: br label %cleanup105// CHECK: if.end4:106// CHECK: %6 = load i32, ptr %i, align 4107// CHECK: %call5 = call {{.*}} i1 @_Z1gi(i32 {{.*}} %6)108// CHECK: br i1 %call5, label %if.then6, label %if.end7109// CHECK: if.then6:110// CHECK: store i32 6, ptr %cleanup.dest.slot, align 4111// CHECK: br label %cleanup112// CHECK: if.end7:113// CHECK: %7 = load i32, ptr %i, align 4114// CHECK: %call8 = call {{.*}} i1 @_Z1gi(i32 {{.*}} %7)115// CHECK: br i1 %call8, label %if.then9, label %if.end10116// CHECK: if.then9:117// CHECK: store i32 7, ptr %cleanup.dest.slot, align 4118// CHECK: br label %cleanup119// CHECK: if.end10:120// CHECK: call void @_ZN20NonTrivialDestructorD1Ev(ptr {{.*}} %n3)121// CHECK: store i32 0, ptr %cleanup.dest.slot, align 4122// CHECK: br label %cleanup123// CHECK: cleanup:124// CHECK: call void @_ZN20NonTrivialDestructorD1Ev(ptr {{.*}} %n2)125// CHECK: %cleanup.dest = load i32, ptr %cleanup.dest.slot, align 4126// CHECK: switch i32 %cleanup.dest, label %cleanup11 [127// CHECK: i32 0, label %cleanup.cont128// CHECK: i32 6, label %for.end129// CHECK: i32 7, label %for.inc130// CHECK: ]131// CHECK: cleanup.cont:132// CHECK: br label %for.inc133// CHECK: for.inc:134// CHECK: %8 = load ptr, ptr %__begin2, align 8135// CHECK: %incdec.ptr = getelementptr inbounds nuw i32, ptr %8, i32 1136// CHECK: store ptr %incdec.ptr, ptr %__begin2, align 8137// CHECK: br label %for.cond138// CHECK: for.end:139// CHECK: call void @_ZN20NonTrivialDestructorD1Ev(ptr {{.*}} %n4)140// CHECK: store i32 0, ptr %cleanup.dest.slot, align 4141// CHECK: br label %cleanup11142// CHECK: cleanup11:143// CHECK: call void @_ZN20NonTrivialDestructorD1Ev(ptr {{.*}} %n1)144// CHECK: %cleanup.dest12 = load i32, ptr %cleanup.dest.slot, align 4145// CHECK: switch i32 %cleanup.dest12, label %unreachable [146// CHECK: i32 0, label %cleanup.cont13147// CHECK: i32 4, label %while.end148// CHECK: i32 3, label %while.cond149// CHECK: ]150// CHECK: cleanup.cont13:151// CHECK: br label %while.cond152// CHECK: while.end:153// CHECK: ret void154// CHECK: unreachable:155// CHECK: unreachable156void f2() {157 l1: while (g(0)) {158 NonTrivialDestructor n1;159 l2: for (int i : a) {160 NonTrivialDestructor n2;161 if (g(i)) break l1;162 if (g(i)) continue l1;163 if (g(i)) break l2;164 if (g(i)) continue l2;165 NonTrivialDestructor n3;166 }167 NonTrivialDestructor n4;168 }169}170 171template <bool Continue>172void f3() {173 l1: while (g(1)) {174 for (;g(2);) {175 if constexpr (Continue) continue l1;176 else break l1;177 }178 }179}180 181// CHECK-LABEL: define {{.*}} void @_Z2f3ILb1EEvv()182// CHECK: entry:183// CHECK: br label %l1184// CHECK: l1:185// CHECK: br label %while.cond186// CHECK: while.cond:187// CHECK: %call = call {{.*}} i1 @_Z1gi(i32 {{.*}} 1)188// CHECK: br i1 %call, label %while.body, label %while.end189// CHECK: while.body:190// CHECK: br label %for.cond191// CHECK: for.cond:192// CHECK: %call1 = call {{.*}} i1 @_Z1gi(i32 {{.*}} 2)193// CHECK: br i1 %call1, label %for.body, label %for.end194// CHECK: for.body:195// CHECK: br label %while.cond196// CHECK: for.end:197// CHECK: br label %while.cond198// CHECK: while.end:199// CHECK: ret void200template void f3<true>();201 202// CHECK-LABEL: define {{.*}} void @_Z2f3ILb0EEvv()203// CHECK: entry:204// CHECK: br label %l1205// CHECK: l1:206// CHECK: br label %while.cond207// CHECK: while.cond:208// CHECK: %call = call {{.*}} i1 @_Z1gi(i32 {{.*}} 1)209// CHECK: br i1 %call, label %while.body, label %while.end210// CHECK: while.body:211// CHECK: br label %for.cond212// CHECK: for.cond:213// CHECK: %call1 = call {{.*}} i1 @_Z1gi(i32 {{.*}} 2)214// CHECK: br i1 %call1, label %for.body, label %for.end215// CHECK: for.body:216// CHECK: br label %while.end217// CHECK: for.end:218// CHECK: br label %while.cond219// CHECK: while.end:220// CHECK: ret void221template void f3<false>();222