1 //===- bolt/Passes/LoopInversionPass.cpp ----------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements the LoopInversionPass class.
11 //===----------------------------------------------------------------------===//
13 #include "bolt/Passes/LoopInversionPass.h"
14 #include "bolt/Core/ParallelUtilities.h"
19 extern cl::OptionCategory BoltCategory
;
21 extern cl::opt
<bolt::ReorderBasicBlocks::LayoutType
> ReorderBlocks
;
23 static cl::opt
<bool> LoopReorder(
25 cl::desc("reorder unconditional jump instructions in loops optimization"),
26 cl::init(true), cl::cat(BoltCategory
), cl::ReallyHidden
);
32 bool LoopInversionPass::runOnFunction(BinaryFunction
&BF
) {
33 bool IsChanged
= false;
34 if (BF
.getLayout().block_size() < 3 || !BF
.hasValidProfile())
37 BF
.getLayout().updateLayoutIndices();
38 for (BinaryBasicBlock
*BB
: BF
.getLayout().blocks()) {
39 if (BB
->succ_size() != 1 || BB
->pred_size() != 1)
42 BinaryBasicBlock
*SuccBB
= *BB
->succ_begin();
43 BinaryBasicBlock
*PredBB
= *BB
->pred_begin();
44 const unsigned BBIndex
= BB
->getLayoutIndex();
45 const unsigned SuccBBIndex
= SuccBB
->getLayoutIndex();
46 if (SuccBB
== PredBB
&& BB
!= SuccBB
&& BBIndex
!= 0 && SuccBBIndex
!= 0 &&
47 SuccBB
->succ_size() == 2 &&
48 BB
->getFragmentNum() == SuccBB
->getFragmentNum()) {
49 // Get the second successor (after loop BB)
50 BinaryBasicBlock
*SecondSucc
= nullptr;
51 for (BinaryBasicBlock
*Succ
: SuccBB
->successors()) {
58 assert(SecondSucc
!= nullptr && "Unable to find a second BB successor");
59 const uint64_t LoopCount
= SuccBB
->getBranchInfo(*BB
).Count
;
60 const uint64_t ExitCount
= SuccBB
->getBranchInfo(*SecondSucc
).Count
;
62 if (LoopCount
< ExitCount
) {
63 if (BBIndex
> SuccBBIndex
)
65 } else if (BBIndex
< SuccBBIndex
) {
70 BB
->setLayoutIndex(SuccBBIndex
);
71 SuccBB
->setLayoutIndex(BBIndex
);
76 BinaryFunction::BasicBlockOrderType
NewOrder(BF
.getLayout().block_begin(),
77 BF
.getLayout().block_end());
78 llvm::sort(NewOrder
, [&](BinaryBasicBlock
*BB1
, BinaryBasicBlock
*BB2
) {
79 return BB1
->getLayoutIndex() < BB2
->getLayoutIndex();
81 BF
.getLayout().update(NewOrder
);
87 Error
LoopInversionPass::runOnFunctions(BinaryContext
&BC
) {
88 std::atomic
<uint64_t> ModifiedFuncCount
{0};
89 if (opts::ReorderBlocks
== ReorderBasicBlocks::LT_NONE
||
90 opts::LoopReorder
== false)
91 return Error::success();
93 ParallelUtilities::WorkFuncTy WorkFun
= [&](BinaryFunction
&BF
) {
94 if (runOnFunction(BF
))
98 ParallelUtilities::PredicateTy SkipFunc
= [&](const BinaryFunction
&BF
) {
99 return !shouldOptimize(BF
);
102 ParallelUtilities::runOnEachFunction(
103 BC
, ParallelUtilities::SchedulingPolicy::SP_TRIVIAL
, WorkFun
, SkipFunc
,
104 "LoopInversionPass");
106 BC
.outs() << "BOLT-INFO: " << ModifiedFuncCount
107 << " Functions were reordered by LoopInversionPass\n";
108 return Error::success();
111 } // end namespace bolt
112 } // end namespace llvm