; 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 } ;.