| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 |
| ; RUN: opt -S -passes=loop-fusion < %s | FileCheck %s |
| ; Test that loop-fusion does not crash on functions with indirectbr and |
| ; loops that lack a preheader (or other required loop structure). |
| |
| define i32 @foo(ptr nocapture readonly %p) { |
| ; CHECK-LABEL: define i32 @foo( |
| ; CHECK-SAME: ptr readonly captures(none) [[P:%.*]]) { |
| ; CHECK-NEXT: [[ENTRY:.*]]: |
| ; CHECK-NEXT: [[TBL:%.*]] = alloca <2 x ptr>, align 16 |
| ; CHECK-NEXT: store <2 x ptr> <ptr blockaddress(@foo, %[[INDIRECT:.*]]), ptr blockaddress(@foo, %[[EXIT:.*]])>, ptr [[TBL]], align 16 |
| ; CHECK-NEXT: br label %[[FOR_COND:.*]] |
| ; CHECK: [[FOR_COND]]: |
| ; CHECK-NEXT: [[CUR:%.*]] = phi ptr [ [[P]], %[[ENTRY]] ], [ [[NEXT:%.*]], %[[FOR_COND]] ] |
| ; CHECK-NEXT: [[VAL:%.*]] = load i8, ptr [[CUR]], align 1 |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[VAL]], 7 |
| ; CHECK-NEXT: [[NEXT]] = getelementptr inbounds i8, ptr [[CUR]], i64 1 |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[INDIRECT_PREHEADER:.*]], label %[[FOR_COND]] |
| ; CHECK: [[INDIRECT_PREHEADER]]: |
| ; CHECK-NEXT: [[RAW:%.*]] = load i8, ptr [[NEXT]], align 1 |
| ; CHECK-NEXT: [[IDX:%.*]] = sext i8 [[RAW]] to i64 |
| ; CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds <2 x ptr>, ptr [[TBL]], i64 0, i64 [[IDX]] |
| ; CHECK-NEXT: [[DEST:%.*]] = load ptr, ptr [[SLOT]], align 8 |
| ; CHECK-NEXT: br label %[[INDIRECT]] |
| ; CHECK: [[INDIRECT]]: |
| ; CHECK-NEXT: indirectbr ptr [[DEST]], [label %[[INDIRECT]], label %[[EXIT]]] |
| ; CHECK: [[INDIRECT2:.*:]] |
| ; CHECK-NEXT: indirectbr ptr [[DEST]], [label %[[INDIRECT]], label %[[EXIT]]] |
| ; CHECK: [[EXIT]]: |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| entry: |
| %tbl = alloca <2 x ptr>, align 16 |
| store <2 x ptr> <ptr blockaddress(@foo, %indirect), ptr blockaddress(@foo, %exit)>, ptr %tbl, align 16 |
| br label %for.cond |
| |
| for.cond: ; preds = %for.cond, %entry |
| %cur = phi ptr [ %p, %entry ], [ %next, %for.cond ] |
| %val = load i8, ptr %cur, align 1 |
| %cmp = icmp eq i8 %val, 7 |
| %next = getelementptr inbounds i8, ptr %cur, i64 1 |
| br i1 %cmp, label %indirect.preheader, label %for.cond |
| |
| indirect.preheader: ; preds = %for.cond |
| %raw = load i8, ptr %next, align 1 |
| %idx = sext i8 %raw to i64 |
| %slot = getelementptr inbounds <2 x ptr>, ptr %tbl, i64 0, i64 %idx |
| %dest = load ptr, ptr %slot, align 8 |
| br label %indirect |
| |
| indirect: |
| indirectbr ptr %dest, [label %indirect, label %exit] |
| |
| indirect2: |
| indirectbr ptr %dest, [label %indirect, label %exit] |
| |
| exit: |
| ret i32 0 |
| } |