diff --git a/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp b/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp --- a/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp +++ b/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp @@ -437,6 +437,16 @@ } static bool shouldApply(Function &F, ProfileSummaryInfo& PSI) { + // If any of the basic blocks have address taken, we should skip this pass + // because the cloned blocks by this pass will not have address taken, and + // hence they may be optimized out by SimplifyCFG if they are targets of + // indirect branches. + bool HasBBAddressTaken = + llvm::any_of(F.getBasicBlockList(), + [](const BasicBlock &BB) { return BB.hasAddressTaken(); }); + if (HasBBAddressTaken) + return false; + if (ForceCHR) return true; diff --git a/llvm/test/Transforms/PGOProfile/chr.ll b/llvm/test/Transforms/PGOProfile/chr.ll --- a/llvm/test/Transforms/PGOProfile/chr.ll +++ b/llvm/test/Transforms/PGOProfile/chr.ll @@ -2527,6 +2527,55 @@ ret void } +; Test that chr will skip this function when addresses are taken on basic blocks. +@gototable = weak_odr dso_local local_unnamed_addr constant [2 x i8*] [i8* blockaddress(@test_chr_with_bbs_address_taken, %bb3), i8* blockaddress(@test_chr_with_bbs_address_taken, %bb3)] +define void @test_chr_with_bbs_address_taken(i32* %i) !prof !14 { +; CHECK-LABEL: @test_chr_with_bbs_address_taken( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: br i1 [[TMP2]], label [[BB1:%.*]], label [[BB0:%.*]], !prof [[PROF16]] +; CHECK: bb0: +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: br label [[BB1]] +; CHECK: bb1: +; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0]], 2 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 +; CHECK-NEXT: br i1 [[TMP4]], label [[BB4:%.*]], label [[BB2:%.*]], !prof [[PROF16]] +; CHECK: bb2: +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: br label [[BB4]] +; CHECK: bb4: +; CHECK-NEXT: ret void +; +entry: + %0 = load i32, i32* %i + %1 = and i32 %0, 1 + %2 = icmp eq i32 %1, 0 + br i1 %2, label %bb1, label %bb0, !prof !15 + +bb0: + call void @foo() + br label %bb1 + +bb1: + %3 = and i32 %0, 2 + %4 = icmp eq i32 %3, 0 + br i1 %4, label %bb4, label %bb2, !prof !15 + +bb2: + call void @foo() + %pc = bitcast i32* %i to i8* + indirectbr i8* %pc, [label %bb3, label %bb3] + +bb3: + br label %bb4 + +bb4: + ret void +} + !llvm.module.flags = !{!0} !0 = !{i32 1, !"ProfileSummary", !1} !1 = !{!2, !3, !4, !5, !6, !7, !8, !9}