| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -passes='loop-mssa(simple-loop-unswitch<nontrivial>),verify<loops>' -S < %s | FileCheck %s |
| ; |
| ;; Check that when we duplicate the load in the loop header, we also duplicate |
| ;; the corresponding dbg.value. |
| ;; FIXME: the hoisted load dominates the duplicated dbg.value, however as it's |
| ;; not subsequently used in the loop, so it doesn't get remapped into the |
| ;; debug user and we get a undef/poison dbg.value. This is suboptimal, but it's |
| ;; important that the dbg.value gets duplicated nonetheless. |
| |
| declare void @clobber() |
| declare void @llvm.dbg.value(metadata, metadata, metadata) |
| |
| define i32 @partial_unswitch_true_successor(ptr %ptr, i32 %N) { |
| ; CHECK-LABEL: @partial_unswitch_true_successor( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[PTR:%.*]], align 4 |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100 |
| ; CHECK-NEXT: br i1 [[TMP1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] |
| ; CHECK: entry.split.us: |
| ; CHECK-NEXT: br label [[LOOP_HEADER_US:%.*]] |
| ; CHECK: loop.header.us: |
| ; CHECK-NEXT: [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ] |
| ; CHECK-NEXT: #dbg_value(i32 poison, [[META3:![0-9]+]], !DIExpression(), [[META8:![0-9]+]]) |
| ; CHECK-NEXT: br label [[NOCLOBBER_US:%.*]] |
| ; CHECK: noclobber.us: |
| ; CHECK-NEXT: br label [[LOOP_LATCH_US]] |
| ; CHECK: loop.latch.us: |
| ; CHECK-NEXT: [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]] |
| ; CHECK-NEXT: [[IV_NEXT_US]] = add i32 [[IV_US]], 1 |
| ; CHECK-NEXT: br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]] |
| ; CHECK: exit.split.us: |
| ; CHECK-NEXT: br label [[EXIT:%.*]] |
| ; CHECK: entry.split: |
| ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] |
| ; CHECK: loop.header: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] |
| ; CHECK-NEXT: [[LV:%.*]] = load i32, ptr [[PTR]], align 4 |
| ; CHECK-NEXT: #dbg_value(i32 [[LV]], [[META3]], !DIExpression(), [[META8]]) |
| ; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 |
| ; CHECK-NEXT: br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]] |
| ; CHECK: noclobber: |
| ; CHECK-NEXT: br label [[LOOP_LATCH]] |
| ; CHECK: clobber: |
| ; CHECK-NEXT: call void @clobber() |
| ; CHECK-NEXT: br label [[LOOP_LATCH]] |
| ; CHECK: loop.latch: |
| ; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N]] |
| ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 |
| ; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]], !llvm.loop [[LOOP9:![0-9]+]] |
| ; CHECK: exit.split: |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i32 10 |
| ; |
| entry: |
| br label %loop.header |
| |
| loop.header: |
| %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] |
| %lv = load i32, ptr %ptr |
| call void @llvm.dbg.value(metadata i32 %lv, metadata !6, metadata !DIExpression()), !dbg !7 |
| %sc = icmp eq i32 %lv, 100 |
| br i1 %sc, label %noclobber, label %clobber |
| |
| noclobber: |
| br label %loop.latch |
| |
| clobber: |
| call void @clobber() |
| br label %loop.latch |
| |
| loop.latch: |
| %c = icmp ult i32 %iv, %N |
| %iv.next = add i32 %iv, 1 |
| br i1 %c, label %loop.header, label %exit |
| |
| exit: |
| ret i32 10 |
| } |
| |
| !llvm.module.flags = !{!21} |
| !llvm.dbg.cu = !{!2} |
| |
| !0 = distinct !DISubprogram(name: "foo", line: 2, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !20, scope: !1, type: !3) |
| !1 = !DIFile(filename: "b.c", directory: "/private/tmp") |
| !2 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang", isOptimized: true, emissionKind: FullDebug, file: !20) |
| !3 = !DISubroutineType(types: !4) |
| !4 = !{!5} |
| !5 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) |
| !6 = !DILocalVariable(name: "i", line: 2, arg: 1, scope: !0, file: !1, type: !5) |
| !7 = !DILocation(line: 2, column: 13, scope: !0) |
| !9 = !DILocalVariable(name: "k", line: 3, scope: !10, file: !1, type: !5) |
| !10 = distinct !DILexicalBlock(line: 2, column: 16, file: !20, scope: !0) |
| !11 = !DILocation(line: 3, column: 12, scope: !10) |
| !12 = !DILocation(line: 4, column: 3, scope: !10) |
| !13 = !DILocation(line: 5, column: 5, scope: !14) |
| !14 = distinct !DILexicalBlock(line: 4, column: 10, file: !20, scope: !10) |
| !15 = !DILocation(line: 6, column: 3, scope: !14) |
| !16 = !DILocation(line: 7, column: 5, scope: !17) |
| !17 = distinct !DILexicalBlock(line: 6, column: 10, file: !20, scope: !10) |
| !18 = !DILocation(line: 8, column: 3, scope: !17) |
| !19 = !DILocation(line: 9, column: 3, scope: !10) |
| !20 = !DIFile(filename: "b.c", directory: "/private/tmp") |
| !21 = !{i32 1, !"Debug Info Version", i32 3} |
| |
| |