| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals --version 2 | |
| ; RUN: opt -passes=function-attrs -S < %s | FileCheck --check-prefixes=COMMON,FNATTRS %s | |
| ; RUN: opt -passes=attributor-light -S < %s | FileCheck --check-prefixes=COMMON,ATTRIBUTOR %s | |
| declare i32 @get_val() | |
| declare void @cold0() cold | |
| declare void @cold1() cold | |
| declare void @cold_at_cb() | |
| declare void @not_cold0() | |
| declare void @not_cold1() | |
| declare void @not_cold2() | |
| define void @test_no_exit_fail() { | |
| ; COMMON: Function Attrs: nofree norecurse noreturn nosync nounwind memory(none) | |
| ; COMMON-LABEL: define void @test_no_exit_fail | |
| ; COMMON-SAME: () #[[ATTR1:[0-9]+]] { | |
| ; COMMON-NEXT: entry: | |
| ; COMMON-NEXT: br label [[WHILE_BODY:%.*]] | |
| ; COMMON: while.body: | |
| ; COMMON-NEXT: br label [[WHILE_BODY]] | |
| ; | |
| entry: | |
| br label %while.body | |
| while.body: | |
| br label %while.body | |
| } | |
| define void @test_no_exit_fail2() { | |
| ; COMMON: Function Attrs: noreturn | |
| ; COMMON-LABEL: define void @test_no_exit_fail2 | |
| ; COMMON-SAME: () #[[ATTR2:[0-9]+]] { | |
| ; COMMON-NEXT: entry: | |
| ; COMMON-NEXT: br label [[WHILE_BODY:%.*]] | |
| ; COMMON: while.body: | |
| ; COMMON-NEXT: call void @not_cold0() | |
| ; COMMON-NEXT: br label [[WHILE_BODY2:%.*]] | |
| ; COMMON: while.body2: | |
| ; COMMON-NEXT: call void @not_cold1() | |
| ; COMMON-NEXT: br label [[WHILE_BODY]] | |
| ; | |
| entry: | |
| br label %while.body | |
| while.body: | |
| call void @not_cold0() | |
| br label %while.body2 | |
| while.body2: | |
| call void @not_cold1() | |
| br label %while.body | |
| } | |
| define void @test_no_exit() { | |
| ; FNATTRS: Function Attrs: cold noreturn | |
| ; FNATTRS-LABEL: define void @test_no_exit | |
| ; FNATTRS-SAME: () #[[ATTR3:[0-9]+]] { | |
| ; FNATTRS-NEXT: entry: | |
| ; FNATTRS-NEXT: br label [[WHILE_BODY:%.*]] | |
| ; FNATTRS: while.body: | |
| ; FNATTRS-NEXT: call void @cold0() | |
| ; FNATTRS-NEXT: br label [[WHILE_BODY]] | |
| ; | |
| ; ATTRIBUTOR: Function Attrs: noreturn | |
| ; ATTRIBUTOR-LABEL: define void @test_no_exit | |
| ; ATTRIBUTOR-SAME: () #[[ATTR2]] { | |
| ; ATTRIBUTOR-NEXT: entry: | |
| ; ATTRIBUTOR-NEXT: br label [[WHILE_BODY:%.*]] | |
| ; ATTRIBUTOR: while.body: | |
| ; ATTRIBUTOR-NEXT: call void @cold0() | |
| ; ATTRIBUTOR-NEXT: br label [[WHILE_BODY]] | |
| ; | |
| entry: | |
| br label %while.body | |
| while.body: | |
| call void @cold0() | |
| br label %while.body | |
| } | |
| define void @test_no_exit2() { | |
| ; FNATTRS: Function Attrs: cold noreturn | |
| ; FNATTRS-LABEL: define void @test_no_exit2 | |
| ; FNATTRS-SAME: () #[[ATTR3]] { | |
| ; FNATTRS-NEXT: entry: | |
| ; FNATTRS-NEXT: br label [[WHILE_BODY:%.*]] | |
| ; FNATTRS: while.body: | |
| ; FNATTRS-NEXT: call void @not_cold0() | |
| ; FNATTRS-NEXT: br label [[WHILE_BODY2:%.*]] | |
| ; FNATTRS: while.body2: | |
| ; FNATTRS-NEXT: call void @cold1() | |
| ; FNATTRS-NEXT: br label [[WHILE_BODY]] | |
| ; | |
| ; ATTRIBUTOR: Function Attrs: noreturn | |
| ; ATTRIBUTOR-LABEL: define void @test_no_exit2 | |
| ; ATTRIBUTOR-SAME: () #[[ATTR2]] { | |
| ; ATTRIBUTOR-NEXT: entry: | |
| ; ATTRIBUTOR-NEXT: br label [[WHILE_BODY:%.*]] | |
| ; ATTRIBUTOR: while.body: | |
| ; ATTRIBUTOR-NEXT: call void @not_cold0() | |
| ; ATTRIBUTOR-NEXT: br label [[WHILE_BODY2:%.*]] | |
| ; ATTRIBUTOR: while.body2: | |
| ; ATTRIBUTOR-NEXT: call void @cold1() | |
| ; ATTRIBUTOR-NEXT: br label [[WHILE_BODY]] | |
| ; | |
| entry: | |
| br label %while.body | |
| while.body: | |
| call void @not_cold0() | |
| br label %while.body2 | |
| while.body2: | |
| call void @cold1() | |
| br label %while.body | |
| } | |
| define dso_local void @test_entry(i32 noundef %x) { | |
| ; FNATTRS: Function Attrs: cold | |
| ; FNATTRS-LABEL: define dso_local void @test_entry | |
| ; FNATTRS-SAME: (i32 noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] { | |
| ; FNATTRS-NEXT: entry: | |
| ; FNATTRS-NEXT: tail call void @cold0() | |
| ; FNATTRS-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X]], 0 | |
| ; FNATTRS-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] | |
| ; FNATTRS: if.then: | |
| ; FNATTRS-NEXT: tail call void @not_cold0() | |
| ; FNATTRS-NEXT: br label [[IF_END]] | |
| ; FNATTRS: if.end: | |
| ; FNATTRS-NEXT: tail call void @not_cold1() | |
| ; FNATTRS-NEXT: ret void | |
| ; | |
| ; ATTRIBUTOR-LABEL: define dso_local void @test_entry | |
| ; ATTRIBUTOR-SAME: (i32 noundef [[X:%.*]]) { | |
| ; ATTRIBUTOR-NEXT: entry: | |
| ; ATTRIBUTOR-NEXT: tail call void @cold0() | |
| ; ATTRIBUTOR-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X]], 0 | |
| ; ATTRIBUTOR-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] | |
| ; ATTRIBUTOR: if.then: | |
| ; ATTRIBUTOR-NEXT: tail call void @not_cold0() | |
| ; ATTRIBUTOR-NEXT: br label [[IF_END]] | |
| ; ATTRIBUTOR: if.end: | |
| ; ATTRIBUTOR-NEXT: tail call void @not_cold1() | |
| ; ATTRIBUTOR-NEXT: ret void | |
| ; | |
| entry: | |
| tail call void @cold0() | |
| %tobool.not = icmp eq i32 %x, 0 | |
| br i1 %tobool.not, label %if.end, label %if.then | |
| if.then: | |
| tail call void @not_cold0() | |
| br label %if.end | |
| if.end: | |
| tail call void @not_cold1() | |
| ret void | |
| } | |
| define dso_local void @test_hot_fail(i32 noundef %x) hot { | |
| ; FNATTRS: Function Attrs: hot | |
| ; FNATTRS-LABEL: define dso_local void @test_hot_fail | |
| ; FNATTRS-SAME: (i32 noundef [[X:%.*]]) #[[ATTR4:[0-9]+]] { | |
| ; FNATTRS-NEXT: entry: | |
| ; FNATTRS-NEXT: tail call void @cold0() | |
| ; FNATTRS-NEXT: ret void | |
| ; | |
| ; ATTRIBUTOR: Function Attrs: hot | |
| ; ATTRIBUTOR-LABEL: define dso_local void @test_hot_fail | |
| ; ATTRIBUTOR-SAME: (i32 noundef [[X:%.*]]) #[[ATTR3:[0-9]+]] { | |
| ; ATTRIBUTOR-NEXT: entry: | |
| ; ATTRIBUTOR-NEXT: tail call void @cold0() | |
| ; ATTRIBUTOR-NEXT: ret void | |
| ; | |
| entry: | |
| tail call void @cold0() | |
| ret void | |
| } | |
| define dso_local void @test_br2(i32 noundef %x) { | |
| ; FNATTRS: Function Attrs: cold | |
| ; FNATTRS-LABEL: define dso_local void @test_br2 | |
| ; FNATTRS-SAME: (i32 noundef [[X:%.*]]) #[[ATTR0]] { | |
| ; FNATTRS-NEXT: entry: | |
| ; FNATTRS-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X]], 0 | |
| ; FNATTRS-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] | |
| ; FNATTRS: if.then: | |
| ; FNATTRS-NEXT: tail call void @cold0() | |
| ; FNATTRS-NEXT: br label [[IF_END:%.*]] | |
| ; FNATTRS: if.else: | |
| ; FNATTRS-NEXT: tail call void @cold1() | |
| ; FNATTRS-NEXT: br label [[IF_END]] | |
| ; FNATTRS: if.end: | |
| ; FNATTRS-NEXT: ret void | |
| ; | |
| ; ATTRIBUTOR-LABEL: define dso_local void @test_br2 | |
| ; ATTRIBUTOR-SAME: (i32 noundef [[X:%.*]]) { | |
| ; ATTRIBUTOR-NEXT: entry: | |
| ; ATTRIBUTOR-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X]], 0 | |
| ; ATTRIBUTOR-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] | |
| ; ATTRIBUTOR: if.then: | |
| ; ATTRIBUTOR-NEXT: tail call void @cold0() | |
| ; ATTRIBUTOR-NEXT: br label [[IF_END:%.*]] | |
| ; ATTRIBUTOR: if.else: | |
| ; ATTRIBUTOR-NEXT: tail call void @cold1() | |
| ; ATTRIBUTOR-NEXT: br label [[IF_END]] | |
| ; ATTRIBUTOR: if.end: | |
| ; ATTRIBUTOR-NEXT: ret void | |
| ; | |
| entry: | |
| %tobool.not = icmp eq i32 %x, 0 | |
| br i1 %tobool.not, label %if.else, label %if.then | |
| if.then: | |
| tail call void @cold0() | |
| br label %if.end | |
| if.else: | |
| tail call void @cold1() | |
| br label %if.end | |
| if.end: | |
| ret void | |
| } | |
| define dso_local void @test_exit(i32 noundef %x) { | |
| ; FNATTRS: Function Attrs: cold | |
| ; FNATTRS-LABEL: define dso_local void @test_exit | |
| ; FNATTRS-SAME: (i32 noundef [[X:%.*]]) #[[ATTR0]] { | |
| ; FNATTRS-NEXT: entry: | |
| ; FNATTRS-NEXT: tail call void @not_cold0() | |
| ; FNATTRS-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X]], 0 | |
| ; FNATTRS-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] | |
| ; FNATTRS: if.then: | |
| ; FNATTRS-NEXT: tail call void @not_cold1() | |
| ; FNATTRS-NEXT: br label [[IF_END:%.*]] | |
| ; FNATTRS: if.else: | |
| ; FNATTRS-NEXT: tail call void @not_cold2() | |
| ; FNATTRS-NEXT: br label [[IF_END]] | |
| ; FNATTRS: if.end: | |
| ; FNATTRS-NEXT: tail call void @cold0() | |
| ; FNATTRS-NEXT: ret void | |
| ; | |
| ; ATTRIBUTOR-LABEL: define dso_local void @test_exit | |
| ; ATTRIBUTOR-SAME: (i32 noundef [[X:%.*]]) { | |
| ; ATTRIBUTOR-NEXT: entry: | |
| ; ATTRIBUTOR-NEXT: tail call void @not_cold0() | |
| ; ATTRIBUTOR-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X]], 0 | |
| ; ATTRIBUTOR-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] | |
| ; ATTRIBUTOR: if.then: | |
| ; ATTRIBUTOR-NEXT: tail call void @not_cold1() | |
| ; ATTRIBUTOR-NEXT: br label [[IF_END:%.*]] | |
| ; ATTRIBUTOR: if.else: | |
| ; ATTRIBUTOR-NEXT: tail call void @not_cold2() | |
| ; ATTRIBUTOR-NEXT: br label [[IF_END]] | |
| ; ATTRIBUTOR: if.end: | |
| ; ATTRIBUTOR-NEXT: tail call void @cold0() | |
| ; ATTRIBUTOR-NEXT: ret void | |
| ; | |
| entry: | |
| tail call void @not_cold0() | |
| %tobool.not = icmp eq i32 %x, 0 | |
| br i1 %tobool.not, label %if.else, label %if.then | |
| if.then: | |
| tail call void @not_cold1() | |
| br label %if.end | |
| if.else: | |
| tail call void @not_cold2() | |
| br label %if.end | |
| if.end: | |
| tail call void @cold0() | |
| ret void | |
| } | |
| define dso_local void @test_complex(i32 noundef %x) { | |
| ; FNATTRS: Function Attrs: cold | |
| ; FNATTRS-LABEL: define dso_local void @test_complex | |
| ; FNATTRS-SAME: (i32 noundef [[X:%.*]]) #[[ATTR0]] { | |
| ; FNATTRS-NEXT: entry: | |
| ; FNATTRS-NEXT: tail call void @not_cold0() | |
| ; FNATTRS-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X]], 0 | |
| ; FNATTRS-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_ELSE11:%.*]], label [[IF_THEN:%.*]] | |
| ; FNATTRS: if.then: | |
| ; FNATTRS-NEXT: [[CALL:%.*]] = tail call i32 @get_val() | |
| ; FNATTRS-NEXT: [[TOBOOL1_NOT:%.*]] = icmp eq i32 [[CALL]], 0 | |
| ; FNATTRS-NEXT: br i1 [[TOBOOL1_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN2:%.*]] | |
| ; FNATTRS: if.then2: | |
| ; FNATTRS-NEXT: tail call void @cold1() | |
| ; FNATTRS-NEXT: br label [[IF_END12:%.*]] | |
| ; FNATTRS: if.else: | |
| ; FNATTRS-NEXT: [[CALL3:%.*]] = tail call i32 @get_val() | |
| ; FNATTRS-NEXT: [[TOBOOL4_NOT:%.*]] = icmp eq i32 [[CALL3]], 0 | |
| ; FNATTRS-NEXT: br i1 [[TOBOOL4_NOT]], label [[IF_ELSE6:%.*]], label [[IF_THEN5:%.*]] | |
| ; FNATTRS: if.then5: | |
| ; FNATTRS-NEXT: tail call void @cold0() | |
| ; FNATTRS-NEXT: br label [[IF_END12]] | |
| ; FNATTRS: if.else6: | |
| ; FNATTRS-NEXT: tail call void @not_cold0() | |
| ; FNATTRS-NEXT: [[CALL7:%.*]] = tail call i32 @get_val() | |
| ; FNATTRS-NEXT: switch i32 [[CALL7]], label [[SW_DEFAULT:%.*]] [ | |
| ; FNATTRS-NEXT: i32 0, label [[SW_BB:%.*]] | |
| ; FNATTRS-NEXT: i32 1, label [[SW_BB8:%.*]] | |
| ; FNATTRS-NEXT: i32 2, label [[SW_BB9:%.*]] | |
| ; FNATTRS-NEXT: ] | |
| ; FNATTRS: sw.bb: | |
| ; FNATTRS-NEXT: tail call void @not_cold0() | |
| ; FNATTRS-NEXT: br label [[CALL_COLD:%.*]] | |
| ; FNATTRS: sw.bb8: | |
| ; FNATTRS-NEXT: tail call void @not_cold1() | |
| ; FNATTRS-NEXT: br label [[CALL_COLD]] | |
| ; FNATTRS: sw.bb9: | |
| ; FNATTRS-NEXT: tail call void @not_cold2() | |
| ; FNATTRS-NEXT: br label [[CALL_COLD]] | |
| ; FNATTRS: sw.default: | |
| ; FNATTRS-NEXT: tail call void @cold0() | |
| ; FNATTRS-NEXT: br label [[IF_END12]] | |
| ; FNATTRS: call_cold: | |
| ; FNATTRS-NEXT: tail call void @cold_at_cb() #[[ATTR0]] | |
| ; FNATTRS-NEXT: br label [[IF_END12]] | |
| ; FNATTRS: if.else11: | |
| ; FNATTRS-NEXT: tail call void @cold0() | |
| ; FNATTRS-NEXT: br label [[IF_END12]] | |
| ; FNATTRS: if.end12: | |
| ; FNATTRS-NEXT: ret void | |
| ; | |
| ; ATTRIBUTOR-LABEL: define dso_local void @test_complex | |
| ; ATTRIBUTOR-SAME: (i32 noundef [[X:%.*]]) { | |
| ; ATTRIBUTOR-NEXT: entry: | |
| ; ATTRIBUTOR-NEXT: tail call void @not_cold0() | |
| ; ATTRIBUTOR-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X]], 0 | |
| ; ATTRIBUTOR-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_ELSE11:%.*]], label [[IF_THEN:%.*]] | |
| ; ATTRIBUTOR: if.then: | |
| ; ATTRIBUTOR-NEXT: [[CALL:%.*]] = tail call i32 @get_val() | |
| ; ATTRIBUTOR-NEXT: [[TOBOOL1_NOT:%.*]] = icmp eq i32 [[CALL]], 0 | |
| ; ATTRIBUTOR-NEXT: br i1 [[TOBOOL1_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN2:%.*]] | |
| ; ATTRIBUTOR: if.then2: | |
| ; ATTRIBUTOR-NEXT: tail call void @cold1() | |
| ; ATTRIBUTOR-NEXT: br label [[IF_END12:%.*]] | |
| ; ATTRIBUTOR: if.else: | |
| ; ATTRIBUTOR-NEXT: [[CALL3:%.*]] = tail call i32 @get_val() | |
| ; ATTRIBUTOR-NEXT: [[TOBOOL4_NOT:%.*]] = icmp eq i32 [[CALL3]], 0 | |
| ; ATTRIBUTOR-NEXT: br i1 [[TOBOOL4_NOT]], label [[IF_ELSE6:%.*]], label [[IF_THEN5:%.*]] | |
| ; ATTRIBUTOR: if.then5: | |
| ; ATTRIBUTOR-NEXT: tail call void @cold0() | |
| ; ATTRIBUTOR-NEXT: br label [[IF_END12]] | |
| ; ATTRIBUTOR: if.else6: | |
| ; ATTRIBUTOR-NEXT: tail call void @not_cold0() | |
| ; ATTRIBUTOR-NEXT: [[CALL7:%.*]] = tail call i32 @get_val() | |
| ; ATTRIBUTOR-NEXT: switch i32 [[CALL7]], label [[SW_DEFAULT:%.*]] [ | |
| ; ATTRIBUTOR-NEXT: i32 0, label [[SW_BB:%.*]] | |
| ; ATTRIBUTOR-NEXT: i32 1, label [[SW_BB8:%.*]] | |
| ; ATTRIBUTOR-NEXT: i32 2, label [[SW_BB9:%.*]] | |
| ; ATTRIBUTOR-NEXT: ] | |
| ; ATTRIBUTOR: sw.bb: | |
| ; ATTRIBUTOR-NEXT: tail call void @not_cold0() | |
| ; ATTRIBUTOR-NEXT: br label [[CALL_COLD:%.*]] | |
| ; ATTRIBUTOR: sw.bb8: | |
| ; ATTRIBUTOR-NEXT: tail call void @not_cold1() | |
| ; ATTRIBUTOR-NEXT: br label [[CALL_COLD]] | |
| ; ATTRIBUTOR: sw.bb9: | |
| ; ATTRIBUTOR-NEXT: tail call void @not_cold2() | |
| ; ATTRIBUTOR-NEXT: br label [[CALL_COLD]] | |
| ; ATTRIBUTOR: sw.default: | |
| ; ATTRIBUTOR-NEXT: tail call void @cold0() | |
| ; ATTRIBUTOR-NEXT: br label [[IF_END12]] | |
| ; ATTRIBUTOR: call_cold: | |
| ; ATTRIBUTOR-NEXT: tail call void @cold_at_cb() #[[ATTR0:[0-9]+]] | |
| ; ATTRIBUTOR-NEXT: br label [[IF_END12]] | |
| ; ATTRIBUTOR: if.else11: | |
| ; ATTRIBUTOR-NEXT: tail call void @cold0() | |
| ; ATTRIBUTOR-NEXT: br label [[IF_END12]] | |
| ; ATTRIBUTOR: if.end12: | |
| ; ATTRIBUTOR-NEXT: ret void | |
| ; | |
| entry: | |
| tail call void @not_cold0() | |
| %tobool.not = icmp eq i32 %x, 0 | |
| br i1 %tobool.not, label %if.else11, label %if.then | |
| if.then: | |
| %call = tail call i32 @get_val() | |
| %tobool1.not = icmp eq i32 %call, 0 | |
| br i1 %tobool1.not, label %if.else, label %if.then2 | |
| if.then2: | |
| tail call void @cold1() | |
| br label %if.end12 | |
| if.else: | |
| %call3 = tail call i32 @get_val() | |
| %tobool4.not = icmp eq i32 %call3, 0 | |
| br i1 %tobool4.not, label %if.else6, label %if.then5 | |
| if.then5: | |
| tail call void @cold0() | |
| br label %if.end12 | |
| if.else6: | |
| tail call void @not_cold0() | |
| %call7 = tail call i32 @get_val() | |
| switch i32 %call7, label %sw.default [ | |
| i32 0, label %sw.bb | |
| i32 1, label %sw.bb8 | |
| i32 2, label %sw.bb9 | |
| ] | |
| sw.bb: | |
| tail call void @not_cold0() | |
| br label %call_cold | |
| sw.bb8: | |
| tail call void @not_cold1() | |
| br label %call_cold | |
| sw.bb9: | |
| tail call void @not_cold2() | |
| br label %call_cold | |
| sw.default: | |
| tail call void @cold0() | |
| br label %if.end12 | |
| call_cold: | |
| tail call void @cold_at_cb() cold | |
| br label %if.end12 | |
| if.else11: | |
| tail call void @cold0() | |
| br label %if.end12 | |
| if.end12: | |
| ret void | |
| } | |
| define dso_local void @test_complex2(i32 noundef %x) { | |
| ; FNATTRS: Function Attrs: cold | |
| ; FNATTRS-LABEL: define dso_local void @test_complex2 | |
| ; FNATTRS-SAME: (i32 noundef [[X:%.*]]) #[[ATTR0]] { | |
| ; FNATTRS-NEXT: entry: | |
| ; FNATTRS-NEXT: tail call void @not_cold0() | |
| ; FNATTRS-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X]], 0 | |
| ; FNATTRS-NEXT: [[CALL12:%.*]] = tail call i32 @get_val() | |
| ; FNATTRS-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_ELSE11:%.*]], label [[IF_THEN:%.*]] | |
| ; FNATTRS: if.then: | |
| ; FNATTRS-NEXT: [[TOBOOL1_NOT:%.*]] = icmp eq i32 [[CALL12]], 0 | |
| ; FNATTRS-NEXT: br i1 [[TOBOOL1_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN2:%.*]] | |
| ; FNATTRS: if.then2: | |
| ; FNATTRS-NEXT: tail call void @cold1() | |
| ; FNATTRS-NEXT: br label [[IF_END16:%.*]] | |
| ; FNATTRS: if.else: | |
| ; FNATTRS-NEXT: [[CALL3:%.*]] = tail call i32 @get_val() | |
| ; FNATTRS-NEXT: [[TOBOOL4_NOT:%.*]] = icmp eq i32 [[CALL3]], 0 | |
| ; FNATTRS-NEXT: br i1 [[TOBOOL4_NOT]], label [[IF_ELSE6:%.*]], label [[IF_THEN5:%.*]] | |
| ; FNATTRS: if.then5: | |
| ; FNATTRS-NEXT: tail call void @cold0() | |
| ; FNATTRS-NEXT: br label [[IF_END16]] | |
| ; FNATTRS: if.else6: | |
| ; FNATTRS-NEXT: tail call void @not_cold0() | |
| ; FNATTRS-NEXT: [[CALL7:%.*]] = tail call i32 @get_val() | |
| ; FNATTRS-NEXT: switch i32 [[CALL7]], label [[SW_DEFAULT:%.*]] [ | |
| ; FNATTRS-NEXT: i32 0, label [[SW_BB:%.*]] | |
| ; FNATTRS-NEXT: i32 1, label [[SW_BB8:%.*]] | |
| ; FNATTRS-NEXT: i32 2, label [[SW_BB9:%.*]] | |
| ; FNATTRS-NEXT: ] | |
| ; FNATTRS: sw.bb: | |
| ; FNATTRS-NEXT: tail call void @not_cold0() | |
| ; FNATTRS-NEXT: br label [[CALL_COLD:%.*]] | |
| ; FNATTRS: sw.bb8: | |
| ; FNATTRS-NEXT: tail call void @not_cold1() | |
| ; FNATTRS-NEXT: br label [[CALL_COLD]] | |
| ; FNATTRS: sw.bb9: | |
| ; FNATTRS-NEXT: tail call void @not_cold2() | |
| ; FNATTRS-NEXT: br label [[CALL_COLD]] | |
| ; FNATTRS: sw.default: | |
| ; FNATTRS-NEXT: tail call void @cold0() | |
| ; FNATTRS-NEXT: br label [[IF_END16]] | |
| ; FNATTRS: call_cold: | |
| ; FNATTRS-NEXT: tail call void @cold_at_cb() #[[ATTR0]] | |
| ; FNATTRS-NEXT: br label [[IF_END16]] | |
| ; FNATTRS: if.else11: | |
| ; FNATTRS-NEXT: [[CMP:%.*]] = icmp slt i32 [[CALL12]], 1 | |
| ; FNATTRS-NEXT: br i1 [[CMP]], label [[IF_END14:%.*]], label [[FOR_BODY:%.*]] | |
| ; FNATTRS: if.end14: | |
| ; FNATTRS-NEXT: tail call void @cold1() | |
| ; FNATTRS-NEXT: br label [[IF_END16]] | |
| ; FNATTRS: for.body: | |
| ; FNATTRS-NEXT: [[I_021:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[IF_ELSE11]] ] | |
| ; FNATTRS-NEXT: tail call void @cold0() | |
| ; FNATTRS-NEXT: [[INC]] = add nuw nsw i32 [[I_021]], 1 | |
| ; FNATTRS-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[CALL12]] | |
| ; FNATTRS-NEXT: br i1 [[EXITCOND_NOT]], label [[IF_END16]], label [[FOR_BODY]] | |
| ; FNATTRS: if.end16: | |
| ; FNATTRS-NEXT: ret void | |
| ; | |
| ; ATTRIBUTOR-LABEL: define dso_local void @test_complex2 | |
| ; ATTRIBUTOR-SAME: (i32 noundef [[X:%.*]]) { | |
| ; ATTRIBUTOR-NEXT: entry: | |
| ; ATTRIBUTOR-NEXT: tail call void @not_cold0() | |
| ; ATTRIBUTOR-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X]], 0 | |
| ; ATTRIBUTOR-NEXT: [[CALL12:%.*]] = tail call i32 @get_val() | |
| ; ATTRIBUTOR-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_ELSE11:%.*]], label [[IF_THEN:%.*]] | |
| ; ATTRIBUTOR: if.then: | |
| ; ATTRIBUTOR-NEXT: [[TOBOOL1_NOT:%.*]] = icmp eq i32 [[CALL12]], 0 | |
| ; ATTRIBUTOR-NEXT: br i1 [[TOBOOL1_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN2:%.*]] | |
| ; ATTRIBUTOR: if.then2: | |
| ; ATTRIBUTOR-NEXT: tail call void @cold1() | |
| ; ATTRIBUTOR-NEXT: br label [[IF_END16:%.*]] | |
| ; ATTRIBUTOR: if.else: | |
| ; ATTRIBUTOR-NEXT: [[CALL3:%.*]] = tail call i32 @get_val() | |
| ; ATTRIBUTOR-NEXT: [[TOBOOL4_NOT:%.*]] = icmp eq i32 [[CALL3]], 0 | |
| ; ATTRIBUTOR-NEXT: br i1 [[TOBOOL4_NOT]], label [[IF_ELSE6:%.*]], label [[IF_THEN5:%.*]] | |
| ; ATTRIBUTOR: if.then5: | |
| ; ATTRIBUTOR-NEXT: tail call void @cold0() | |
| ; ATTRIBUTOR-NEXT: br label [[IF_END16]] | |
| ; ATTRIBUTOR: if.else6: | |
| ; ATTRIBUTOR-NEXT: tail call void @not_cold0() | |
| ; ATTRIBUTOR-NEXT: [[CALL7:%.*]] = tail call i32 @get_val() | |
| ; ATTRIBUTOR-NEXT: switch i32 [[CALL7]], label [[SW_DEFAULT:%.*]] [ | |
| ; ATTRIBUTOR-NEXT: i32 0, label [[SW_BB:%.*]] | |
| ; ATTRIBUTOR-NEXT: i32 1, label [[SW_BB8:%.*]] | |
| ; ATTRIBUTOR-NEXT: i32 2, label [[SW_BB9:%.*]] | |
| ; ATTRIBUTOR-NEXT: ] | |
| ; ATTRIBUTOR: sw.bb: | |
| ; ATTRIBUTOR-NEXT: tail call void @not_cold0() | |
| ; ATTRIBUTOR-NEXT: br label [[CALL_COLD:%.*]] | |
| ; ATTRIBUTOR: sw.bb8: | |
| ; ATTRIBUTOR-NEXT: tail call void @not_cold1() | |
| ; ATTRIBUTOR-NEXT: br label [[CALL_COLD]] | |
| ; ATTRIBUTOR: sw.bb9: | |
| ; ATTRIBUTOR-NEXT: tail call void @not_cold2() | |
| ; ATTRIBUTOR-NEXT: br label [[CALL_COLD]] | |
| ; ATTRIBUTOR: sw.default: | |
| ; ATTRIBUTOR-NEXT: tail call void @cold0() | |
| ; ATTRIBUTOR-NEXT: br label [[IF_END16]] | |
| ; ATTRIBUTOR: call_cold: | |
| ; ATTRIBUTOR-NEXT: tail call void @cold_at_cb() #[[ATTR0]] | |
| ; ATTRIBUTOR-NEXT: br label [[IF_END16]] | |
| ; ATTRIBUTOR: if.else11: | |
| ; ATTRIBUTOR-NEXT: [[CMP:%.*]] = icmp slt i32 [[CALL12]], 1 | |
| ; ATTRIBUTOR-NEXT: br i1 [[CMP]], label [[IF_END14:%.*]], label [[FOR_BODY:%.*]] | |
| ; ATTRIBUTOR: if.end14: | |
| ; ATTRIBUTOR-NEXT: tail call void @cold1() | |
| ; ATTRIBUTOR-NEXT: br label [[IF_END16]] | |
| ; ATTRIBUTOR: for.body: | |
| ; ATTRIBUTOR-NEXT: [[I_021:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[IF_ELSE11]] ] | |
| ; ATTRIBUTOR-NEXT: tail call void @cold0() | |
| ; ATTRIBUTOR-NEXT: [[INC]] = add nuw nsw i32 [[I_021]], 1 | |
| ; ATTRIBUTOR-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[CALL12]] | |
| ; ATTRIBUTOR-NEXT: br i1 [[EXITCOND_NOT]], label [[IF_END16]], label [[FOR_BODY]] | |
| ; ATTRIBUTOR: if.end16: | |
| ; ATTRIBUTOR-NEXT: ret void | |
| ; | |
| entry: | |
| tail call void @not_cold0() | |
| %tobool.not = icmp eq i32 %x, 0 | |
| %call12 = tail call i32 @get_val() | |
| br i1 %tobool.not, label %if.else11, label %if.then | |
| if.then: | |
| %tobool1.not = icmp eq i32 %call12, 0 | |
| br i1 %tobool1.not, label %if.else, label %if.then2 | |
| if.then2: | |
| tail call void @cold1() | |
| br label %if.end16 | |
| if.else: | |
| %call3 = tail call i32 @get_val() | |
| %tobool4.not = icmp eq i32 %call3, 0 | |
| br i1 %tobool4.not, label %if.else6, label %if.then5 | |
| if.then5: | |
| tail call void @cold0() | |
| br label %if.end16 | |
| if.else6: | |
| tail call void @not_cold0() | |
| %call7 = tail call i32 @get_val() | |
| switch i32 %call7, label %sw.default [ | |
| i32 0, label %sw.bb | |
| i32 1, label %sw.bb8 | |
| i32 2, label %sw.bb9 | |
| ] | |
| sw.bb: | |
| tail call void @not_cold0() | |
| br label %call_cold | |
| sw.bb8: | |
| tail call void @not_cold1() | |
| br label %call_cold | |
| sw.bb9: | |
| tail call void @not_cold2() | |
| br label %call_cold | |
| sw.default: | |
| tail call void @cold0() | |
| br label %if.end16 | |
| call_cold: | |
| tail call void @cold_at_cb() cold | |
| br label %if.end16 | |
| if.else11: | |
| %cmp = icmp slt i32 %call12, 1 | |
| br i1 %cmp, label %if.end14, label %for.body | |
| if.end14: | |
| tail call void @cold1() | |
| br label %if.end16 | |
| for.body: | |
| %i.021 = phi i32 [ %inc, %for.body ], [ 0, %if.else11 ] | |
| tail call void @cold0() | |
| %inc = add nuw nsw i32 %i.021, 1 | |
| %exitcond.not = icmp eq i32 %inc, %call12 | |
| br i1 %exitcond.not, label %if.end16, label %for.body | |
| if.end16: | |
| ret void | |
| } | |
| define dso_local void @test_complex_fail(i32 noundef %x) { | |
| ; COMMON-LABEL: define dso_local void @test_complex_fail | |
| ; COMMON-SAME: (i32 noundef [[X:%.*]]) { | |
| ; COMMON-NEXT: entry: | |
| ; COMMON-NEXT: tail call void @not_cold0() | |
| ; COMMON-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X]], 0 | |
| ; COMMON-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_ELSE11:%.*]], label [[IF_THEN:%.*]] | |
| ; COMMON: if.then: | |
| ; COMMON-NEXT: [[CALL:%.*]] = tail call i32 @get_val() | |
| ; COMMON-NEXT: [[TOBOOL1_NOT:%.*]] = icmp eq i32 [[CALL]], 0 | |
| ; COMMON-NEXT: br i1 [[TOBOOL1_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN2:%.*]] | |
| ; COMMON: if.then2: | |
| ; COMMON-NEXT: tail call void @cold1() | |
| ; COMMON-NEXT: br label [[IF_END12:%.*]] | |
| ; COMMON: if.else: | |
| ; COMMON-NEXT: [[CALL3:%.*]] = tail call i32 @get_val() | |
| ; COMMON-NEXT: [[TOBOOL4_NOT:%.*]] = icmp eq i32 [[CALL3]], 0 | |
| ; COMMON-NEXT: br i1 [[TOBOOL4_NOT]], label [[IF_ELSE6:%.*]], label [[IF_THEN5:%.*]] | |
| ; COMMON: if.then5: | |
| ; COMMON-NEXT: tail call void @cold0() | |
| ; COMMON-NEXT: br label [[IF_END12]] | |
| ; COMMON: if.else6: | |
| ; COMMON-NEXT: tail call void @not_cold0() | |
| ; COMMON-NEXT: [[CALL7:%.*]] = tail call i32 @get_val() | |
| ; COMMON-NEXT: switch i32 [[CALL7]], label [[SW_DEFAULT:%.*]] [ | |
| ; COMMON-NEXT: i32 0, label [[SW_BB:%.*]] | |
| ; COMMON-NEXT: i32 1, label [[SW_BB8:%.*]] | |
| ; COMMON-NEXT: i32 2, label [[SW_BB9:%.*]] | |
| ; COMMON-NEXT: ] | |
| ; COMMON: sw.bb: | |
| ; COMMON-NEXT: tail call void @not_cold0() | |
| ; COMMON-NEXT: br label [[CALL_COLD:%.*]] | |
| ; COMMON: sw.bb8: | |
| ; COMMON-NEXT: tail call void @not_cold1() | |
| ; COMMON-NEXT: br label [[CALL_COLD]] | |
| ; COMMON: sw.bb9: | |
| ; COMMON-NEXT: tail call void @not_cold2() | |
| ; COMMON-NEXT: br label [[IF_END12]] | |
| ; COMMON: sw.default: | |
| ; COMMON-NEXT: tail call void @cold0() | |
| ; COMMON-NEXT: br label [[IF_END12]] | |
| ; COMMON: call_cold: | |
| ; COMMON-NEXT: tail call void @cold_at_cb() #[[ATTR0:[0-9]+]] | |
| ; COMMON-NEXT: br label [[IF_END12]] | |
| ; COMMON: if.else11: | |
| ; COMMON-NEXT: tail call void @cold0() | |
| ; COMMON-NEXT: br label [[IF_END12]] | |
| ; COMMON: if.end12: | |
| ; COMMON-NEXT: ret void | |
| ; | |
| entry: | |
| tail call void @not_cold0() | |
| %tobool.not = icmp eq i32 %x, 0 | |
| br i1 %tobool.not, label %if.else11, label %if.then | |
| if.then: | |
| %call = tail call i32 @get_val() | |
| %tobool1.not = icmp eq i32 %call, 0 | |
| br i1 %tobool1.not, label %if.else, label %if.then2 | |
| if.then2: | |
| tail call void @cold1() | |
| br label %if.end12 | |
| if.else: | |
| %call3 = tail call i32 @get_val() | |
| %tobool4.not = icmp eq i32 %call3, 0 | |
| br i1 %tobool4.not, label %if.else6, label %if.then5 | |
| if.then5: | |
| tail call void @cold0() | |
| br label %if.end12 | |
| if.else6: | |
| tail call void @not_cold0() | |
| %call7 = tail call i32 @get_val() | |
| switch i32 %call7, label %sw.default [ | |
| i32 0, label %sw.bb | |
| i32 1, label %sw.bb8 | |
| i32 2, label %sw.bb9 | |
| ] | |
| sw.bb: | |
| tail call void @not_cold0() | |
| br label %call_cold | |
| sw.bb8: | |
| tail call void @not_cold1() | |
| br label %call_cold | |
| sw.bb9: | |
| tail call void @not_cold2() | |
| br label %if.end12 | |
| sw.default: | |
| tail call void @cold0() | |
| br label %if.end12 | |
| call_cold: | |
| tail call void @cold_at_cb() cold | |
| br label %if.end12 | |
| if.else11: | |
| tail call void @cold0() | |
| br label %if.end12 | |
| if.end12: | |
| ret void | |
| } | |
| define dso_local void @test_complex2_fail(i32 noundef %x) { | |
| ; COMMON-LABEL: define dso_local void @test_complex2_fail | |
| ; COMMON-SAME: (i32 noundef [[X:%.*]]) { | |
| ; COMMON-NEXT: entry: | |
| ; COMMON-NEXT: tail call void @not_cold0() | |
| ; COMMON-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X]], 0 | |
| ; COMMON-NEXT: [[CALL12:%.*]] = tail call i32 @get_val() | |
| ; COMMON-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_ELSE11:%.*]], label [[IF_THEN:%.*]] | |
| ; COMMON: if.then: | |
| ; COMMON-NEXT: [[TOBOOL1_NOT:%.*]] = icmp eq i32 [[CALL12]], 0 | |
| ; COMMON-NEXT: br i1 [[TOBOOL1_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN2:%.*]] | |
| ; COMMON: if.then2: | |
| ; COMMON-NEXT: tail call void @cold1() | |
| ; COMMON-NEXT: br label [[IF_END16:%.*]] | |
| ; COMMON: if.else: | |
| ; COMMON-NEXT: [[CALL3:%.*]] = tail call i32 @get_val() | |
| ; COMMON-NEXT: [[TOBOOL4_NOT:%.*]] = icmp eq i32 [[CALL3]], 0 | |
| ; COMMON-NEXT: br i1 [[TOBOOL4_NOT]], label [[IF_ELSE6:%.*]], label [[IF_THEN5:%.*]] | |
| ; COMMON: if.then5: | |
| ; COMMON-NEXT: tail call void @cold0() | |
| ; COMMON-NEXT: br label [[IF_END16]] | |
| ; COMMON: if.else6: | |
| ; COMMON-NEXT: tail call void @not_cold0() | |
| ; COMMON-NEXT: [[CALL7:%.*]] = tail call i32 @get_val() | |
| ; COMMON-NEXT: switch i32 [[CALL7]], label [[SW_DEFAULT:%.*]] [ | |
| ; COMMON-NEXT: i32 0, label [[SW_BB:%.*]] | |
| ; COMMON-NEXT: i32 1, label [[SW_BB8:%.*]] | |
| ; COMMON-NEXT: i32 2, label [[SW_BB9:%.*]] | |
| ; COMMON-NEXT: ] | |
| ; COMMON: sw.bb: | |
| ; COMMON-NEXT: tail call void @not_cold0() | |
| ; COMMON-NEXT: br label [[CALL_COLD:%.*]] | |
| ; COMMON: sw.bb8: | |
| ; COMMON-NEXT: tail call void @not_cold1() | |
| ; COMMON-NEXT: br label [[CALL_COLD]] | |
| ; COMMON: sw.bb9: | |
| ; COMMON-NEXT: tail call void @not_cold2() | |
| ; COMMON-NEXT: br label [[CALL_COLD]] | |
| ; COMMON: sw.default: | |
| ; COMMON-NEXT: tail call void @cold0() | |
| ; COMMON-NEXT: br label [[IF_END16]] | |
| ; COMMON: call_cold: | |
| ; COMMON-NEXT: tail call void @cold_at_cb() #[[ATTR0]] | |
| ; COMMON-NEXT: br label [[IF_END16]] | |
| ; COMMON: if.else11: | |
| ; COMMON-NEXT: [[CMP:%.*]] = icmp slt i32 [[CALL12]], 1 | |
| ; COMMON-NEXT: br i1 [[CMP]], label [[IF_END14:%.*]], label [[FOR_BODY:%.*]] | |
| ; COMMON: if.end14: | |
| ; COMMON-NEXT: tail call void @not_cold1() | |
| ; COMMON-NEXT: br label [[IF_END16]] | |
| ; COMMON: for.body: | |
| ; COMMON-NEXT: [[I_021:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[IF_ELSE11]] ] | |
| ; COMMON-NEXT: tail call void @cold0() | |
| ; COMMON-NEXT: [[INC]] = add nuw nsw i32 [[I_021]], 1 | |
| ; COMMON-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[CALL12]] | |
| ; COMMON-NEXT: br i1 [[EXITCOND_NOT]], label [[IF_END16]], label [[FOR_BODY]] | |
| ; COMMON: if.end16: | |
| ; COMMON-NEXT: ret void | |
| ; | |
| entry: | |
| tail call void @not_cold0() | |
| %tobool.not = icmp eq i32 %x, 0 | |
| %call12 = tail call i32 @get_val() | |
| br i1 %tobool.not, label %if.else11, label %if.then | |
| if.then: | |
| %tobool1.not = icmp eq i32 %call12, 0 | |
| br i1 %tobool1.not, label %if.else, label %if.then2 | |
| if.then2: | |
| tail call void @cold1() | |
| br label %if.end16 | |
| if.else: | |
| %call3 = tail call i32 @get_val() | |
| %tobool4.not = icmp eq i32 %call3, 0 | |
| br i1 %tobool4.not, label %if.else6, label %if.then5 | |
| if.then5: | |
| tail call void @cold0() | |
| br label %if.end16 | |
| if.else6: | |
| tail call void @not_cold0() | |
| %call7 = tail call i32 @get_val() | |
| switch i32 %call7, label %sw.default [ | |
| i32 0, label %sw.bb | |
| i32 1, label %sw.bb8 | |
| i32 2, label %sw.bb9 | |
| ] | |
| sw.bb: | |
| tail call void @not_cold0() | |
| br label %call_cold | |
| sw.bb8: | |
| tail call void @not_cold1() | |
| br label %call_cold | |
| sw.bb9: | |
| tail call void @not_cold2() | |
| br label %call_cold | |
| sw.default: | |
| tail call void @cold0() | |
| br label %if.end16 | |
| call_cold: | |
| tail call void @cold_at_cb() cold | |
| br label %if.end16 | |
| if.else11: | |
| %cmp = icmp slt i32 %call12, 1 | |
| br i1 %cmp, label %if.end14, label %for.body | |
| if.end14: | |
| tail call void @not_cold1() | |
| br label %if.end16 | |
| for.body: | |
| %i.021 = phi i32 [ %inc, %for.body ], [ 0, %if.else11 ] | |
| tail call void @cold0() | |
| %inc = add nuw nsw i32 %i.021, 1 | |
| %exitcond.not = icmp eq i32 %inc, %call12 | |
| br i1 %exitcond.not, label %if.end16, label %for.body | |
| if.end16: | |
| ret void | |
| } | |
| ;. | |
| ; FNATTRS: attributes #[[ATTR0]] = { cold } | |
| ; FNATTRS: attributes #[[ATTR1]] = { nofree norecurse noreturn nosync nounwind memory(none) } | |
| ; FNATTRS: attributes #[[ATTR2]] = { noreturn } | |
| ; FNATTRS: attributes #[[ATTR3]] = { cold noreturn } | |
| ; FNATTRS: attributes #[[ATTR4]] = { hot } | |
| ;. | |
| ; ATTRIBUTOR: attributes #[[ATTR0]] = { cold } | |
| ; ATTRIBUTOR: attributes #[[ATTR1]] = { nofree norecurse noreturn nosync nounwind memory(none) } | |
| ; ATTRIBUTOR: attributes #[[ATTR2]] = { noreturn } | |
| ; ATTRIBUTOR: attributes #[[ATTR3]] = { hot } | |
| ;. |