1 //===- MachineSizeOptsTest.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 #include "llvm/CodeGen/MachineSizeOpts.h"
10 #include "llvm/Analysis/BlockFrequencyInfo.h"
11 #include "llvm/Analysis/BranchProbabilityInfo.h"
12 #include "llvm/Analysis/LoopInfo.h"
13 #include "llvm/Analysis/ProfileSummaryInfo.h"
14 #include "llvm/CodeGen/MIRParser/MIRParser.h"
15 #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
16 #include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
17 #include "llvm/CodeGen/MachineDominators.h"
18 #include "llvm/CodeGen/MachineLoopInfo.h"
19 #include "llvm/CodeGen/MachineModuleInfo.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/MC/TargetRegistry.h"
22 #include "llvm/Support/MemoryBuffer.h"
23 #include "llvm/Support/TargetSelect.h"
24 #include "llvm/Target/TargetMachine.h"
25 #include "gtest/gtest.h"
31 std::unique_ptr
<TargetMachine
> createTargetMachine() {
32 auto TT(Triple::normalize("x86_64--"));
34 const Target
*TheTarget
= TargetRegistry::lookupTarget(TT
, Error
);
35 return std::unique_ptr
<TargetMachine
>(
36 TheTarget
->createTargetMachine(TT
, "", "", TargetOptions(), std::nullopt
,
37 std::nullopt
, CodeGenOptLevel::Default
));
40 class MachineSizeOptsTest
: public testing::Test
{
42 static const char* MIRString
;
44 std::unique_ptr
<TargetMachine
> TM
;
45 std::unique_ptr
<MachineModuleInfo
> MMI
;
46 std::unique_ptr
<MIRParser
> Parser
;
47 std::unique_ptr
<Module
> M
;
49 std::unique_ptr
<MachineDominatorTree
> MDT
;
50 std::unique_ptr
<MachineLoopInfo
> MLI
;
51 std::unique_ptr
<MachineBranchProbabilityInfo
> MBPI
;
52 std::unique_ptr
<MachineBlockFrequencyInfo
> MBFI
;
53 BFIData(MachineFunction
&MF
) {
54 MDT
.reset(new MachineDominatorTree(MF
));
55 MLI
.reset(new MachineLoopInfo(*MDT
));
56 MBPI
.reset(new MachineBranchProbabilityInfo());
57 MBFI
.reset(new MachineBlockFrequencyInfo(MF
, *MBPI
, *MLI
));
59 MachineBlockFrequencyInfo
*get() { return MBFI
.get(); }
62 static void SetUpTestCase() {
63 LLVMInitializeX86TargetInfo();
64 LLVMInitializeX86Target();
65 LLVMInitializeX86TargetMC();
68 void SetUp() override
{
69 TM
= createTargetMachine();
70 std::unique_ptr
<MemoryBuffer
> MBuffer
=
71 MemoryBuffer::getMemBuffer(MIRString
);
72 Parser
= createMIRParser(std::move(MBuffer
), Context
);
74 report_fatal_error("null MIRParser");
75 M
= Parser
->parseIRModule();
77 report_fatal_error("parseIRModule failed");
78 M
->setTargetTriple(TM
->getTargetTriple().getTriple());
79 M
->setDataLayout(TM
->createDataLayout());
80 MMI
= std::make_unique
<MachineModuleInfo
>(TM
.get());
81 if (Parser
->parseMachineFunctions(*M
, *MMI
))
82 report_fatal_error("parseMachineFunctions failed");
85 MachineFunction
*getMachineFunction(Module
*M
, StringRef Name
) {
86 auto F
= M
->getFunction(Name
);
88 report_fatal_error("null Function");
89 auto &MF
= MMI
->getOrCreateMachineFunction(*F
);
94 TEST_F(MachineSizeOptsTest
, Test
) {
95 MachineFunction
*F
= getMachineFunction(M
.get(), "f");
96 ASSERT_TRUE(F
!= nullptr);
97 MachineFunction
*G
= getMachineFunction(M
.get(), "g");
98 ASSERT_TRUE(G
!= nullptr);
99 MachineFunction
*H
= getMachineFunction(M
.get(), "h");
100 ASSERT_TRUE(H
!= nullptr);
101 ProfileSummaryInfo PSI
= ProfileSummaryInfo(*M
);
102 ASSERT_TRUE(PSI
.hasProfileSummary());
106 MachineBlockFrequencyInfo
*MBFI_F
= BFID_F
.get();
107 MachineBlockFrequencyInfo
*MBFI_G
= BFID_G
.get();
108 MachineBlockFrequencyInfo
*MBFI_H
= BFID_H
.get();
109 MachineBasicBlock
&BB0
= F
->front();
110 auto iter
= BB0
.succ_begin();
111 MachineBasicBlock
*BB1
= *iter
;
113 MachineBasicBlock
*BB2
= *iter
;
115 ASSERT_TRUE(iter
== BB0
.succ_end());
116 MachineBasicBlock
*BB3
= *BB1
->succ_begin();
117 ASSERT_TRUE(BB3
== *BB2
->succ_begin());
118 EXPECT_FALSE(shouldOptimizeForSize(F
, &PSI
, MBFI_F
, PGSOQueryType::Test
));
119 EXPECT_TRUE(shouldOptimizeForSize(G
, &PSI
, MBFI_G
, PGSOQueryType::Test
));
120 EXPECT_FALSE(shouldOptimizeForSize(H
, &PSI
, MBFI_H
, PGSOQueryType::Test
));
121 EXPECT_FALSE(shouldOptimizeForSize(&BB0
, &PSI
, MBFI_F
, PGSOQueryType::Test
));
122 EXPECT_FALSE(shouldOptimizeForSize(BB1
, &PSI
, MBFI_F
, PGSOQueryType::Test
));
123 EXPECT_TRUE(shouldOptimizeForSize(BB2
, &PSI
, MBFI_F
, PGSOQueryType::Test
));
124 EXPECT_FALSE(shouldOptimizeForSize(BB3
, &PSI
, MBFI_F
, PGSOQueryType::Test
));
127 const char* MachineSizeOptsTest::MIRString
= R
"MIR(
129 define i32 @g(i32 %x) !prof !14 {
133 define i32 @h(i32 %x) !prof !15 {
137 define i32 @f(i32 %x) !prof !16 {
139 %y1 = icmp eq i32 %x, 0
140 br i1 %y1, label %bb1, label %bb2, !prof !17
143 %z1 = call i32 @g(i32 %x)
147 %z2 = call i32 @h(i32 %x)
150 bb3: ; preds = %bb2, %bb1
151 %y2 = phi i32 [ 0, %bb1 ], [ 1, %bb2 ]
155 !llvm.module.flags = !{!0}
157 !0 = !{i32 1, !"ProfileSummary
", !1}
158 !1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
159 !2 = !{!"ProfileFormat
", !"InstrProf
"}
160 !3 = !{!"TotalCount
", i64 10000}
161 !4 = !{!"MaxCount
", i64 10}
162 !5 = !{!"MaxInternalCount
", i64 1}
163 !6 = !{!"MaxFunctionCount
", i64 1000}
164 !7 = !{!"NumCounts
", i64 3}
165 !8 = !{!"NumFunctions
", i64 3}
166 !9 = !{!"DetailedSummary
", !10}
167 !10 = !{!11, !12, !13}
168 !11 = !{i32 10000, i64 1000, i32 1}
169 !12 = !{i32 999000, i64 300, i32 3}
170 !13 = !{i32 999999, i64 5, i32 10}
171 !14 = !{!"function_entry_count
", i64 1}
172 !15 = !{!"function_entry_count
", i64 100}
173 !16 = !{!"function_entry_count
", i64 400}
174 !17 = !{!"branch_weights
", i32 100, i32 1}
181 %1:gr32 = MOV32r0 implicit-def dead $eflags
190 %1:gr32 = MOV32r0 implicit-def dead $eflags
197 tracksRegLiveness: true
200 successors: %bb.1(0x7ebb907a), %bb.2(0x01446f86)
204 TEST32rr %1, %1, implicit-def $eflags
205 JCC_1 %bb.2, 5, implicit $eflags
209 successors: %bb.3(0x80000000)
211 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
213 CALL64pcrel32 @g, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
214 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
216 %4:gr32 = MOV32r0 implicit-def dead $eflags
220 successors: %bb.3(0x80000000)
222 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
224 CALL64pcrel32 @h, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
225 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
230 %0:gr32 = PHI %2, %bb.2, %4, %bb.1
237 } // anonymous namespace