| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 | |
| ; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 --keep-loops="true" -S | FileCheck %s | |
| ; Threading the latch edge to %exit does not bypass the header. | |
| define void @trip_count_one(ptr %p) { | |
| ; CHECK-LABEL: define void @trip_count_one( | |
| ; CHECK-SAME: ptr [[P:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: store i32 0, ptr [[P]], align 4 | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| br label %header | |
| header: | |
| %first = phi i1 [ true, %entry ], [ false, %latch ] | |
| br i1 %first, label %body, label %exit | |
| body: | |
| store i32 0, ptr %p, align 4 | |
| br label %latch | |
| latch: | |
| br label %header | |
| exit: | |
| ret void | |
| } | |
| ; %inner reaches %latch without going through %header, so threading %latch to | |
| ; %inner would form a cycle bypassing %header. | |
| define void @latch_to_body(ptr %p, i1 %a, i1 %c) { | |
| ; CHECK-LABEL: define void @latch_to_body( | |
| ; CHECK-SAME: ptr [[P:%.*]], i1 [[A:%.*]], i1 [[C:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: br label %[[HEADER:.*]] | |
| ; CHECK: [[HEADER]]: | |
| ; CHECK-NEXT: [[V:%.*]] = phi i1 [ [[A]], %[[ENTRY]] ], [ false, %[[INNER:.*]] ] | |
| ; CHECK-NEXT: br i1 [[V]], label %[[EXIT:.*]], label %[[INNER]] | |
| ; CHECK: [[INNER]]: | |
| ; CHECK-NEXT: store i32 0, ptr [[P]], align 4 | |
| ; CHECK-NEXT: br i1 [[C]], label %[[HEADER]], label %[[EXIT]] | |
| ; CHECK: [[EXIT]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| br label %header | |
| header: | |
| %v = phi i1 [ %a, %entry ], [ false, %latch ] | |
| br i1 %v, label %exit, label %inner | |
| inner: | |
| store i32 0, ptr %p, align 4 | |
| br i1 %c, label %latch, label %exit | |
| latch: | |
| br label %header | |
| exit: | |
| ret void | |
| } | |
| ; Do not thread through a loop header with multiple backedges. | |
| define void @multi_latch(ptr %p, i1 %a, i1 %b, i1 %c) { | |
| ; CHECK-LABEL: define void @multi_latch( | |
| ; CHECK-SAME: ptr [[P:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], i1 [[C:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: br label %[[HEADER:.*]] | |
| ; CHECK: [[HEADER]]: | |
| ; CHECK-NEXT: [[V:%.*]] = phi i1 [ [[A]], %[[ENTRY]] ], [ [[B]], %[[LATCH1:.*]] ], [ false, %[[LATCH2:.*]] ] | |
| ; CHECK-NEXT: br i1 [[V]], label %[[BODY:.*]], label %[[EXIT:.*]] | |
| ; CHECK: [[BODY]]: | |
| ; CHECK-NEXT: store i32 0, ptr [[P]], align 4 | |
| ; CHECK-NEXT: br i1 [[C]], label %[[LATCH1]], label %[[LATCH2]] | |
| ; CHECK: [[LATCH1]]: | |
| ; CHECK-NEXT: store i32 1, ptr [[P]], align 4 | |
| ; CHECK-NEXT: br label %[[HEADER]] | |
| ; CHECK: [[LATCH2]]: | |
| ; CHECK-NEXT: store i32 2, ptr [[P]], align 4 | |
| ; CHECK-NEXT: br label %[[HEADER]] | |
| ; CHECK: [[EXIT]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| br label %header | |
| header: | |
| %v = phi i1 [ %a, %entry ], [ %b, %latch1 ], [ false, %latch2 ] | |
| br i1 %v, label %body, label %exit | |
| body: | |
| store i32 0, ptr %p, align 4 | |
| br i1 %c, label %latch1, label %latch2 | |
| latch1: | |
| store i32 1, ptr %p, align 4 | |
| br label %header | |
| latch2: | |
| store i32 2, ptr %p, align 4 | |
| br label %header | |
| exit: | |
| ret void | |
| } | |