| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --version 5 | |
| ; RUN: opt < %s -S -passes="inline" | FileCheck %s | |
| define void @callee(i32 %a, i32 %b) #0 { | |
| ; CHECK: Function Attrs: mustprogress | |
| ; CHECK-LABEL: define void @callee( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR0:[0-9]+]] { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: br label %[[FOR_COND:.*]] | |
| ; CHECK: [[FOR_COND]]: | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY:.*]], label %[[FOR_END:.*]] | |
| ; CHECK: [[FOR_BODY]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND]], !llvm.loop [[LOOP0:![0-9]+]] | |
| ; CHECK: [[FOR_END]]: | |
| ; CHECK-NEXT: br label %[[WHILE_BODY:.*]] | |
| ; CHECK: [[WHILE_BODY]]: | |
| ; CHECK-NEXT: br label %[[WHILE_BODY]] | |
| ; | |
| entry: | |
| br label %for.cond | |
| for.cond: | |
| %cmp = icmp slt i32 %a, %b | |
| br i1 %cmp, label %for.body, label %for.end | |
| for.body: | |
| br label %for.cond, !llvm.loop !0 | |
| for.end: | |
| br label %while.body | |
| while.body: | |
| br label %while.body | |
| } | |
| define void @caller(i32 %a, i32 %b) #1 { | |
| ; CHECK: Function Attrs: noinline | |
| ; CHECK-LABEL: define void @caller( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR1:[0-9]+]] { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: br label %[[FOR_COND:.*]] | |
| ; CHECK: [[FOR_COND]]: | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[CALLEE_EXIT:.*]], label %[[FOR_END:.*]] | |
| ; CHECK: [[CALLEE_EXIT]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND]] | |
| ; CHECK: [[FOR_END]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND_I:.*]] | |
| ; CHECK: [[FOR_COND_I]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND_I]], !llvm.loop [[LOOP0]] | |
| ; CHECK: [[CALLEE_EXIT1:.*:]] | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| br label %for.cond | |
| for.cond: | |
| %cmp = icmp slt i32 %a, %b | |
| br i1 %cmp, label %for.body, label %for.end | |
| for.body: | |
| br label %for.cond | |
| for.end: | |
| call void @callee(i32 0, i32 5) | |
| ret void | |
| } | |
| define void @callee_no_metadata(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @callee_no_metadata( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: br label %[[FOR_COND:.*]] | |
| ; CHECK: [[FOR_COND]]: | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY:.*]], label %[[FOR_END:.*]] | |
| ; CHECK: [[FOR_BODY]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND]] | |
| ; CHECK: [[FOR_END]]: | |
| ; CHECK-NEXT: br label %[[WHILE_BODY:.*]] | |
| ; CHECK: [[WHILE_BODY]]: | |
| ; CHECK-NEXT: br label %[[WHILE_BODY]] | |
| ; | |
| entry: | |
| br label %for.cond | |
| for.cond: | |
| %cmp = icmp slt i32 %a, %b | |
| br i1 %cmp, label %for.body, label %for.end | |
| for.body: | |
| br label %for.cond | |
| for.end: | |
| br label %while.body | |
| while.body: | |
| br label %while.body | |
| } | |
| define void @caller_no_metadata(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @caller_no_metadata( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: br label %[[FOR_COND:.*]] | |
| ; CHECK: [[FOR_COND]]: | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[CALLEE_NO_METADATA_EXIT:.*]], label %[[FOR_END:.*]] | |
| ; CHECK: [[CALLEE_NO_METADATA_EXIT]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND]] | |
| ; CHECK: [[FOR_END]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND_I:.*]] | |
| ; CHECK: [[FOR_COND_I]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND_I]] | |
| ; CHECK: [[CALLEE_NO_METADATA_EXIT1:.*:]] | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| br label %for.cond | |
| for.cond: | |
| %cmp = icmp slt i32 %a, %b | |
| br i1 %cmp, label %for.body, label %for.end | |
| for.body: | |
| br label %for.cond | |
| for.end: | |
| call void @callee_no_metadata(i32 0, i32 5) | |
| ret void | |
| } | |
| define void @callee_mustprogress(i32 %a, i32 %b) #0 { | |
| ; CHECK: Function Attrs: mustprogress | |
| ; CHECK-LABEL: define void @callee_mustprogress( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR0]] { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: br label %[[FOR_COND:.*]] | |
| ; CHECK: [[FOR_COND]]: | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY:.*]], label %[[FOR_END:.*]] | |
| ; CHECK: [[FOR_BODY]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND]] | |
| ; CHECK: [[FOR_END]]: | |
| ; CHECK-NEXT: br label %[[WHILE_BODY:.*]] | |
| ; CHECK: [[WHILE_BODY]]: | |
| ; CHECK-NEXT: br label %[[WHILE_BODY]] | |
| ; | |
| entry: | |
| br label %for.cond | |
| for.cond: | |
| %cmp = icmp slt i32 %a, %b | |
| br i1 %cmp, label %for.body, label %for.end | |
| for.body: | |
| br label %for.cond | |
| for.end: | |
| br label %while.body | |
| while.body: | |
| br label %while.body | |
| } | |
| define void @caller_mustprogress(i32 %a, i32 %b) #0 { | |
| ; CHECK: Function Attrs: mustprogress | |
| ; CHECK-LABEL: define void @caller_mustprogress( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR0]] { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: br label %[[FOR_COND:.*]] | |
| ; CHECK: [[FOR_COND]]: | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[CALLEE_MUSTPROGRESS_EXIT:.*]], label %[[FOR_END:.*]] | |
| ; CHECK: [[CALLEE_MUSTPROGRESS_EXIT]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND]] | |
| ; CHECK: [[FOR_END]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND_I:.*]] | |
| ; CHECK: [[FOR_COND_I]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND_I]] | |
| ; CHECK: [[CALLEE_MUSTPROGRESS_EXIT1:.*:]] | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| br label %for.cond | |
| for.cond: | |
| %cmp = icmp slt i32 %a, %b | |
| br i1 %cmp, label %for.body, label %for.end | |
| for.body: | |
| br label %for.cond | |
| for.end: | |
| call void @callee_mustprogress(i32 0, i32 5) | |
| ret void | |
| } | |
| define void @caller_mustprogress_callee_no_metadata(i32 %a, i32 %b) #0 { | |
| ; CHECK-LABEL: define void @caller_mustprogress_callee_no_metadata( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: br label %[[FOR_COND:.*]] | |
| ; CHECK: [[FOR_COND]]: | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[CALLEE_NO_METADATA_EXIT:.*]], label %[[FOR_END:.*]] | |
| ; CHECK: [[CALLEE_NO_METADATA_EXIT]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND]] | |
| ; CHECK: [[FOR_END]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND_I:.*]] | |
| ; CHECK: [[FOR_COND_I]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND_I]] | |
| ; CHECK: [[CALLEE_NO_METADATA_EXIT1:.*:]] | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| br label %for.cond | |
| for.cond: | |
| %cmp = icmp slt i32 %a, %b | |
| br i1 %cmp, label %for.body, label %for.end | |
| for.body: | |
| br label %for.cond | |
| for.end: | |
| call void @callee_no_metadata(i32 0, i32 5) | |
| ret void | |
| } | |
| define void @callee_multiple(i32 %a, i32 %b) #0 { | |
| ; CHECK: Function Attrs: mustprogress | |
| ; CHECK-LABEL: define void @callee_multiple( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR0]] { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 | |
| ; CHECK-NEXT: store i32 [[B]], ptr [[B_ADDR]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND:.*]] | |
| ; CHECK: [[FOR_COND]]: | |
| ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 | |
| ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], [[TMP1]] | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY:.*]], label %[[FOR_END:.*]] | |
| ; CHECK: [[FOR_BODY]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND]], !llvm.loop [[LOOP2:![0-9]+]] | |
| ; CHECK: [[FOR_END]]: | |
| ; CHECK-NEXT: store i32 0, ptr [[I]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND1:.*]] | |
| ; CHECK: [[FOR_COND1]]: | |
| ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[I]], align 4 | |
| ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP2]], 10 | |
| ; CHECK-NEXT: br i1 [[CMP2]], label %[[FOR_BODY3:.*]], label %[[FOR_END4:.*]] | |
| ; CHECK: [[FOR_BODY3]]: | |
| ; CHECK-NEXT: br label %[[FOR_INC:.*]] | |
| ; CHECK: [[FOR_INC]]: | |
| ; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[I]], align 4 | |
| ; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP3]], 1 | |
| ; CHECK-NEXT: store i32 [[INC]], ptr [[I]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND1]], !llvm.loop [[LOOP3:![0-9]+]] | |
| ; CHECK: [[FOR_END4]]: | |
| ; CHECK-NEXT: br label %[[WHILE_BODY:.*]] | |
| ; CHECK: [[WHILE_BODY]]: | |
| ; CHECK-NEXT: br label %[[WHILE_BODY]] | |
| ; | |
| entry: | |
| %a.addr = alloca i32, align 4 | |
| %b.addr = alloca i32, align 4 | |
| %i = alloca i32, align 4 | |
| store i32 %a, ptr %a.addr, align 4 | |
| store i32 %b, ptr %b.addr, align 4 | |
| br label %for.cond | |
| for.cond: | |
| %0 = load i32, ptr %a.addr, align 4 | |
| %1 = load i32, ptr %b.addr, align 4 | |
| %cmp = icmp slt i32 %0, %1 | |
| br i1 %cmp, label %for.body, label %for.end | |
| for.body: | |
| br label %for.cond, !llvm.loop !2 | |
| for.end: | |
| store i32 0, ptr %i, align 4 | |
| br label %for.cond1 | |
| for.cond1: | |
| %2 = load i32, ptr %i, align 4 | |
| %cmp2 = icmp slt i32 %2, 10 | |
| br i1 %cmp2, label %for.body3, label %for.end4 | |
| for.body3: | |
| br label %for.inc | |
| for.inc: | |
| %3 = load i32, ptr %i, align 4 | |
| %inc = add nsw i32 %3, 1 | |
| store i32 %inc, ptr %i, align 4 | |
| br label %for.cond1, !llvm.loop !4 | |
| for.end4: | |
| br label %while.body | |
| while.body: | |
| br label %while.body | |
| } | |
| define void @caller_multiple(i32 %a, i32 %b) #1 { | |
| ; CHECK: Function Attrs: noinline | |
| ; CHECK-LABEL: define void @caller_multiple( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR1]] { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: [[A_ADDR_I:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[B_ADDR_I:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[I_I:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 | |
| ; CHECK-NEXT: store i32 [[B]], ptr [[B_ADDR]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND:.*]] | |
| ; CHECK: [[FOR_COND]]: | |
| ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 | |
| ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], [[TMP1]] | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY:.*]], label %[[FOR_END:.*]] | |
| ; CHECK: [[FOR_BODY]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND]] | |
| ; CHECK: [[FOR_END]]: | |
| ; CHECK-NEXT: store i32 0, ptr [[I]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND1:.*]] | |
| ; CHECK: [[FOR_COND1]]: | |
| ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[I]], align 4 | |
| ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP2]], 10 | |
| ; CHECK-NEXT: br i1 [[CMP2]], label %[[FOR_BODY3:.*]], label %[[FOR_END4:.*]] | |
| ; CHECK: [[FOR_BODY3]]: | |
| ; CHECK-NEXT: br label %[[FOR_INC:.*]] | |
| ; CHECK: [[FOR_INC]]: | |
| ; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[I]], align 4 | |
| ; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP3]], 1 | |
| ; CHECK-NEXT: store i32 [[INC]], ptr [[I]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND1]] | |
| ; CHECK: [[FOR_END4]]: | |
| ; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A_ADDR_I]]) | |
| ; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B_ADDR_I]]) | |
| ; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[I_I]]) | |
| ; CHECK-NEXT: store i32 0, ptr [[A_ADDR_I]], align 4 | |
| ; CHECK-NEXT: store i32 5, ptr [[B_ADDR_I]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND_I:.*]] | |
| ; CHECK: [[FOR_COND_I]]: | |
| ; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[A_ADDR_I]], align 4 | |
| ; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[B_ADDR_I]], align 4 | |
| ; CHECK-NEXT: [[CMP_I:%.*]] = icmp slt i32 [[TMP4]], [[TMP5]] | |
| ; CHECK-NEXT: br i1 [[CMP_I]], label %[[FOR_BODY_I:.*]], label %[[FOR_END_I:.*]] | |
| ; CHECK: [[FOR_BODY_I]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND_I]], !llvm.loop [[LOOP2]] | |
| ; CHECK: [[FOR_END_I]]: | |
| ; CHECK-NEXT: store i32 0, ptr [[I_I]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND1_I:.*]] | |
| ; CHECK: [[FOR_COND1_I]]: | |
| ; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[I_I]], align 4 | |
| ; CHECK-NEXT: [[CMP2_I:%.*]] = icmp slt i32 [[TMP6]], 10 | |
| ; CHECK-NEXT: br i1 [[CMP2_I]], label %[[FOR_BODY3_I:.*]], label %[[CALLEE_MULTIPLE_EXIT:.*]] | |
| ; CHECK: [[FOR_BODY3_I]]: | |
| ; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[I_I]], align 4 | |
| ; CHECK-NEXT: [[INC_I:%.*]] = add nsw i32 [[TMP7]], 1 | |
| ; CHECK-NEXT: store i32 [[INC_I]], ptr [[I_I]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND1_I]], !llvm.loop [[LOOP3]] | |
| ; CHECK: [[CALLEE_MULTIPLE_EXIT]]: | |
| ; CHECK-NEXT: br label %[[WHILE_BODY_I:.*]] | |
| ; CHECK: [[WHILE_BODY_I]]: | |
| ; CHECK-NEXT: br label %[[WHILE_BODY_I]] | |
| ; CHECK: [[CALLEE_MULTIPLE_EXIT1:.*:]] | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| %a.addr = alloca i32, align 4 | |
| %b.addr = alloca i32, align 4 | |
| %i = alloca i32, align 4 | |
| store i32 %a, ptr %a.addr, align 4 | |
| store i32 %b, ptr %b.addr, align 4 | |
| br label %for.cond | |
| for.cond: | |
| %0 = load i32, ptr %a.addr, align 4 | |
| %1 = load i32, ptr %b.addr, align 4 | |
| %cmp = icmp slt i32 %0, %1 | |
| br i1 %cmp, label %for.body, label %for.end | |
| for.body: | |
| br label %for.cond | |
| for.end: | |
| store i32 0, ptr %i, align 4 | |
| br label %for.cond1 | |
| for.cond1: | |
| %2 = load i32, ptr %i, align 4 | |
| %cmp2 = icmp slt i32 %2, 10 | |
| br i1 %cmp2, label %for.body3, label %for.end4 | |
| for.body3: | |
| br label %for.inc | |
| for.inc: | |
| %3 = load i32, ptr %i, align 4 | |
| %inc = add nsw i32 %3, 1 | |
| store i32 %inc, ptr %i, align 4 | |
| br label %for.cond1 | |
| for.end4: | |
| call void @callee_multiple(i32 0, i32 5) | |
| ret void | |
| } | |
| define void @callee_nested(i32 %a, i32 %b) #0 { | |
| ; CHECK: Function Attrs: mustprogress | |
| ; CHECK-LABEL: define void @callee_nested( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR0]] { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 | |
| ; CHECK-NEXT: store i32 [[B]], ptr [[B_ADDR]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND:.*]] | |
| ; CHECK: [[FOR_COND]]: | |
| ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 | |
| ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], [[TMP1]] | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY:.*]], label %[[FOR_END:.*]] | |
| ; CHECK: [[FOR_BODY]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND]], !llvm.loop [[LOOP0]] | |
| ; CHECK: [[FOR_END]]: | |
| ; CHECK-NEXT: store i32 0, ptr [[I]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND1:.*]] | |
| ; CHECK: [[FOR_COND1]]: | |
| ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[I]], align 4 | |
| ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP2]], 10 | |
| ; CHECK-NEXT: br i1 [[CMP2]], label %[[FOR_BODY3:.*]], label %[[FOR_END8:.*]] | |
| ; CHECK: [[FOR_BODY3]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND4:.*]] | |
| ; CHECK: [[FOR_COND4]]: | |
| ; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[B_ADDR]], align 4 | |
| ; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[A_ADDR]], align 4 | |
| ; CHECK-NEXT: [[CMP5:%.*]] = icmp slt i32 [[TMP3]], [[TMP4]] | |
| ; CHECK-NEXT: br i1 [[CMP5]], label %[[FOR_BODY6:.*]], label %[[FOR_END7:.*]] | |
| ; CHECK: [[FOR_BODY6]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND4]], !llvm.loop [[LOOP2]] | |
| ; CHECK: [[FOR_END7]]: | |
| ; CHECK-NEXT: br label %[[FOR_INC:.*]] | |
| ; CHECK: [[FOR_INC]]: | |
| ; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[I]], align 4 | |
| ; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP5]], 1 | |
| ; CHECK-NEXT: store i32 [[INC]], ptr [[I]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND1]], !llvm.loop [[LOOP4:![0-9]+]] | |
| ; CHECK: [[FOR_END8]]: | |
| ; CHECK-NEXT: br label %[[WHILE_BODY:.*]] | |
| ; CHECK: [[WHILE_BODY]]: | |
| ; CHECK-NEXT: br label %[[WHILE_BODY]] | |
| ; | |
| entry: | |
| %a.addr = alloca i32, align 4 | |
| %b.addr = alloca i32, align 4 | |
| %i = alloca i32, align 4 | |
| store i32 %a, ptr %a.addr, align 4 | |
| store i32 %b, ptr %b.addr, align 4 | |
| br label %for.cond | |
| for.cond: | |
| %0 = load i32, ptr %a.addr, align 4 | |
| %1 = load i32, ptr %b.addr, align 4 | |
| %cmp = icmp slt i32 %0, %1 | |
| br i1 %cmp, label %for.body, label %for.end | |
| for.body: | |
| br label %for.cond, !llvm.loop !0 | |
| for.end: | |
| store i32 0, ptr %i, align 4 | |
| br label %for.cond1 | |
| for.cond1: | |
| %2 = load i32, ptr %i, align 4 | |
| %cmp2 = icmp slt i32 %2, 10 | |
| br i1 %cmp2, label %for.body3, label %for.end8 | |
| for.body3: | |
| br label %for.cond4 | |
| for.cond4: | |
| %3 = load i32, ptr %b.addr, align 4 | |
| %4 = load i32, ptr %a.addr, align 4 | |
| %cmp5 = icmp slt i32 %3, %4 | |
| br i1 %cmp5, label %for.body6, label %for.end7 | |
| for.body6: | |
| br label %for.cond4, !llvm.loop !2 | |
| for.end7: | |
| br label %for.inc | |
| for.inc: | |
| %5 = load i32, ptr %i, align 4 | |
| %inc = add nsw i32 %5, 1 | |
| store i32 %inc, ptr %i, align 4 | |
| br label %for.cond1, !llvm.loop !3 | |
| for.end8: | |
| br label %while.body | |
| while.body: | |
| br label %while.body | |
| } | |
| define void @caller_nested(i32 %a, i32 %b) #1 { | |
| ; CHECK: Function Attrs: noinline | |
| ; CHECK-LABEL: define void @caller_nested( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR1]] { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: [[A_ADDR_I:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[B_ADDR_I:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[I_I:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[I9:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 | |
| ; CHECK-NEXT: store i32 [[B]], ptr [[B_ADDR]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND:.*]] | |
| ; CHECK: [[FOR_COND]]: | |
| ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 | |
| ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], [[TMP1]] | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY:.*]], label %[[FOR_END8:.*]] | |
| ; CHECK: [[FOR_BODY]]: | |
| ; CHECK-NEXT: store i32 0, ptr [[I]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND1:.*]] | |
| ; CHECK: [[FOR_COND1]]: | |
| ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[I]], align 4 | |
| ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP2]], 10 | |
| ; CHECK-NEXT: br i1 [[CMP2]], label %[[FOR_BODY3:.*]], label %[[FOR_END7:.*]] | |
| ; CHECK: [[FOR_BODY3]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND4:.*]] | |
| ; CHECK: [[FOR_COND4]]: | |
| ; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[B_ADDR]], align 4 | |
| ; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[A_ADDR]], align 4 | |
| ; CHECK-NEXT: [[CMP5:%.*]] = icmp slt i32 [[TMP3]], [[TMP4]] | |
| ; CHECK-NEXT: br i1 [[CMP5]], label %[[FOR_BODY6:.*]], label %[[FOR_END:.*]] | |
| ; CHECK: [[FOR_BODY6]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND4]] | |
| ; CHECK: [[FOR_END]]: | |
| ; CHECK-NEXT: br label %[[FOR_INC:.*]] | |
| ; CHECK: [[FOR_INC]]: | |
| ; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[I]], align 4 | |
| ; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP5]], 1 | |
| ; CHECK-NEXT: store i32 [[INC]], ptr [[I]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND1]] | |
| ; CHECK: [[FOR_END7]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND]] | |
| ; CHECK: [[FOR_END8]]: | |
| ; CHECK-NEXT: store i32 0, ptr [[I9]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND10:.*]] | |
| ; CHECK: [[FOR_COND10]]: | |
| ; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[I9]], align 4 | |
| ; CHECK-NEXT: [[CMP11:%.*]] = icmp slt i32 [[TMP6]], 10 | |
| ; CHECK-NEXT: br i1 [[CMP11]], label %[[FOR_BODY12:.*]], label %[[FOR_END15:.*]] | |
| ; CHECK: [[FOR_BODY12]]: | |
| ; CHECK-NEXT: br label %[[FOR_INC13:.*]] | |
| ; CHECK: [[FOR_INC13]]: | |
| ; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[I9]], align 4 | |
| ; CHECK-NEXT: [[INC14:%.*]] = add nsw i32 [[TMP7]], 1 | |
| ; CHECK-NEXT: store i32 [[INC14]], ptr [[I9]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND10]] | |
| ; CHECK: [[FOR_END15]]: | |
| ; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A_ADDR_I]]) | |
| ; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B_ADDR_I]]) | |
| ; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[I_I]]) | |
| ; CHECK-NEXT: store i32 0, ptr [[A_ADDR_I]], align 4 | |
| ; CHECK-NEXT: store i32 5, ptr [[B_ADDR_I]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND_I:.*]] | |
| ; CHECK: [[FOR_COND_I]]: | |
| ; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[A_ADDR_I]], align 4 | |
| ; CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[B_ADDR_I]], align 4 | |
| ; CHECK-NEXT: [[CMP_I:%.*]] = icmp slt i32 [[TMP8]], [[TMP9]] | |
| ; CHECK-NEXT: br i1 [[CMP_I]], label %[[FOR_BODY_I:.*]], label %[[FOR_END_I:.*]] | |
| ; CHECK: [[FOR_BODY_I]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND_I]], !llvm.loop [[LOOP0]] | |
| ; CHECK: [[FOR_END_I]]: | |
| ; CHECK-NEXT: store i32 0, ptr [[I_I]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND1_I:.*]] | |
| ; CHECK: [[FOR_COND1_I]]: | |
| ; CHECK-NEXT: [[TMP10:%.*]] = load i32, ptr [[I_I]], align 4 | |
| ; CHECK-NEXT: [[CMP2_I:%.*]] = icmp slt i32 [[TMP10]], 10 | |
| ; CHECK-NEXT: br i1 [[CMP2_I]], label %[[FOR_BODY3_I:.*]], label %[[CALLEE_NESTED_EXIT:.*]] | |
| ; CHECK: [[FOR_BODY3_I]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND4_I:.*]] | |
| ; CHECK: [[FOR_COND4_I]]: | |
| ; CHECK-NEXT: [[TMP11:%.*]] = load i32, ptr [[B_ADDR_I]], align 4 | |
| ; CHECK-NEXT: [[TMP12:%.*]] = load i32, ptr [[A_ADDR_I]], align 4 | |
| ; CHECK-NEXT: [[CMP5_I:%.*]] = icmp slt i32 [[TMP11]], [[TMP12]] | |
| ; CHECK-NEXT: br i1 [[CMP5_I]], label %[[FOR_BODY6_I:.*]], label %[[FOR_END7_I:.*]] | |
| ; CHECK: [[FOR_BODY6_I]]: | |
| ; CHECK-NEXT: br label %[[FOR_COND4_I]], !llvm.loop [[LOOP2]] | |
| ; CHECK: [[FOR_END7_I]]: | |
| ; CHECK-NEXT: [[TMP13:%.*]] = load i32, ptr [[I_I]], align 4 | |
| ; CHECK-NEXT: [[INC_I:%.*]] = add nsw i32 [[TMP13]], 1 | |
| ; CHECK-NEXT: store i32 [[INC_I]], ptr [[I_I]], align 4 | |
| ; CHECK-NEXT: br label %[[FOR_COND1_I]], !llvm.loop [[LOOP4]] | |
| ; CHECK: [[CALLEE_NESTED_EXIT]]: | |
| ; CHECK-NEXT: br label %[[WHILE_BODY_I:.*]] | |
| ; CHECK: [[WHILE_BODY_I]]: | |
| ; CHECK-NEXT: br label %[[WHILE_BODY_I]] | |
| ; CHECK: [[CALLEE_NESTED_EXIT1:.*:]] | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| %a.addr = alloca i32, align 4 | |
| %b.addr = alloca i32, align 4 | |
| %i = alloca i32, align 4 | |
| %i9 = alloca i32, align 4 | |
| store i32 %a, ptr %a.addr, align 4 | |
| store i32 %b, ptr %b.addr, align 4 | |
| br label %for.cond | |
| for.cond: | |
| %0 = load i32, ptr %a.addr, align 4 | |
| %1 = load i32, ptr %b.addr, align 4 | |
| %cmp = icmp slt i32 %0, %1 | |
| br i1 %cmp, label %for.body, label %for.end8 | |
| for.body: | |
| store i32 0, ptr %i, align 4 | |
| br label %for.cond1 | |
| for.cond1: | |
| %2 = load i32, ptr %i, align 4 | |
| %cmp2 = icmp slt i32 %2, 10 | |
| br i1 %cmp2, label %for.body3, label %for.end7 | |
| for.body3: | |
| br label %for.cond4 | |
| for.cond4: | |
| %3 = load i32, ptr %b.addr, align 4 | |
| %4 = load i32, ptr %a.addr, align 4 | |
| %cmp5 = icmp slt i32 %3, %4 | |
| br i1 %cmp5, label %for.body6, label %for.end | |
| for.body6: | |
| br label %for.cond4 | |
| for.end: | |
| br label %for.inc | |
| for.inc: | |
| %5 = load i32, ptr %i, align 4 | |
| %inc = add nsw i32 %5, 1 | |
| store i32 %inc, ptr %i, align 4 | |
| br label %for.cond1 | |
| for.end7: | |
| br label %for.cond | |
| for.end8: | |
| store i32 0, ptr %i9, align 4 | |
| br label %for.cond10 | |
| for.cond10: | |
| %6 = load i32, ptr %i9, align 4 | |
| %cmp11 = icmp slt i32 %6, 10 | |
| br i1 %cmp11, label %for.body12, label %for.end15 | |
| for.body12: | |
| br label %for.inc13 | |
| for.inc13: | |
| %7 = load i32, ptr %i9, align 4 | |
| %inc14 = add nsw i32 %7, 1 | |
| store i32 %inc14, ptr %i9, align 4 | |
| br label %for.cond10 | |
| for.end15: | |
| call void @callee_nested(i32 0, i32 5) | |
| ret void | |
| } | |
| attributes #0 = { mustprogress } | |
| attributes #1 = { noinline } | |
| attributes #2 = { noinline mustprogress } | |
| !0 = distinct !{!0, !1} | |
| !1 = !{!"llvm.loop.mustprogress"} | |
| !2 = distinct !{!2, !1} | |
| !3 = distinct !{!3, !1} | |
| !4 = distinct !{!4, !1} | |
| !5 = distinct !{!5, !1} | |
| !6 = distinct !{!6, !1} | |
| !7 = distinct !{!7, !1} | |
| ;. | |
| ; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]]} | |
| ; CHECK: [[META1]] = !{!"llvm.loop.mustprogress"} | |
| ; CHECK: [[LOOP2]] = distinct !{[[LOOP2]], [[META1]]} | |
| ; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META1]]} | |
| ; CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[META1]]} | |
| ;. |