1 #include "llvm/ExecutionEngine/Orc/ReOptimizeLayer.h"
2 #include "OrcTestCommon.h"
3 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
4 #include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
5 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
6 #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
7 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
8 #include "llvm/ExecutionEngine/Orc/IRPartitionLayer.h"
9 #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
10 #include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h"
11 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
12 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
13 #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
14 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
15 #include "llvm/IR/IRBuilder.h"
16 #include "llvm/Support/CodeGen.h"
17 #include "llvm/TargetParser/Host.h"
18 #include "llvm/Testing/Support/Error.h"
19 #include "gtest/gtest.h"
22 using namespace llvm::orc
;
23 using namespace llvm::jitlink
;
25 class ReOptimizeLayerTest
: public testing::Test
{
27 ~ReOptimizeLayerTest() {
29 if (auto Err
= ES
->endSession())
30 ES
->reportError(std::move(Err
));
34 void SetUp() override
{
35 auto JTMB
= JITTargetMachineBuilder::detectHost();
36 // Bail out if we can not detect the host.
38 consumeError(JTMB
.takeError());
42 // COFF-ARM64 is not supported yet
43 auto Triple
= JTMB
->getTargetTriple();
44 if (Triple
.isOSBinFormatCOFF() && Triple
.isAArch64())
47 // SystemZ is not supported yet.
48 if (Triple
.isSystemZ())
51 // 32-bit X86 is not supported yet.
52 if (Triple
.isX86() && Triple
.isArch32Bit())
58 auto EPC
= SelfExecutorProcessControl::Create();
60 consumeError(EPC
.takeError());
64 auto DLOrErr
= JTMB
->getDefaultDataLayoutForTarget();
66 consumeError(DLOrErr
.takeError());
69 ES
= std::make_unique
<ExecutionSession
>(std::move(*EPC
));
70 JD
= &ES
->createBareJITDylib("main");
71 ObjLinkingLayer
= std::make_unique
<ObjectLinkingLayer
>(
72 *ES
, std::make_unique
<InProcessMemoryManager
>(16384));
73 DL
= std::make_unique
<DataLayout
>(std::move(*DLOrErr
));
75 auto TM
= JTMB
->createTargetMachine();
77 consumeError(TM
.takeError());
80 auto CompileFunction
=
81 std::make_unique
<TMOwningSimpleCompiler
>(std::move(*TM
));
82 CompileLayer
= std::make_unique
<IRCompileLayer
>(*ES
, *ObjLinkingLayer
,
83 std::move(CompileFunction
));
86 Error
addIRModule(ResourceTrackerSP RT
, ThreadSafeModule TSM
) {
87 assert(TSM
&& "Can not add null module");
89 TSM
.withModuleDo([&](Module
&M
) { M
.setDataLayout(*DL
); });
91 return ROLayer
->add(std::move(RT
), std::move(TSM
));
94 JITDylib
*JD
{nullptr};
95 std::unique_ptr
<ExecutionSession
> ES
;
96 std::unique_ptr
<ObjectLinkingLayer
> ObjLinkingLayer
;
97 std::unique_ptr
<IRCompileLayer
> CompileLayer
;
98 std::unique_ptr
<ReOptimizeLayer
> ROLayer
;
99 std::unique_ptr
<DataLayout
> DL
;
102 static Function
*createRetFunction(Module
*M
, StringRef Name
,
103 uint32_t ReturnCode
) {
104 Function
*Result
= Function::Create(
105 FunctionType::get(Type::getInt32Ty(M
->getContext()), {}, false),
106 GlobalValue::ExternalLinkage
, Name
, M
);
108 BasicBlock
*BB
= BasicBlock::Create(M
->getContext(), Name
, Result
);
109 IRBuilder
<> Builder(M
->getContext());
110 Builder
.SetInsertPoint(BB
);
112 Value
*RetValue
= ConstantInt::get(M
->getContext(), APInt(32, ReturnCode
));
113 Builder
.CreateRet(RetValue
);
117 TEST_F(ReOptimizeLayerTest
, BasicReOptimization
) {
118 MangleAndInterner
Mangle(*ES
, *DL
);
120 auto &EPC
= ES
->getExecutorProcessControl();
121 EXPECT_THAT_ERROR(JD
->define(absoluteSymbols(
122 {{Mangle("__orc_rt_jit_dispatch"),
123 {EPC
.getJITDispatchInfo().JITDispatchFunction
,
124 JITSymbolFlags::Exported
}},
125 {Mangle("__orc_rt_jit_dispatch_ctx"),
126 {EPC
.getJITDispatchInfo().JITDispatchContext
,
127 JITSymbolFlags::Exported
}},
128 {Mangle("__orc_rt_reoptimize_tag"),
129 {ExecutorAddr(), JITSymbolFlags::Exported
}}})),
132 auto RM
= JITLinkRedirectableSymbolManager::Create(*ObjLinkingLayer
);
133 EXPECT_THAT_ERROR(RM
.takeError(), Succeeded());
135 ROLayer
= std::make_unique
<ReOptimizeLayer
>(*ES
, *DL
, *CompileLayer
, **RM
);
136 ROLayer
->setReoptimizeFunc(
137 [&](ReOptimizeLayer
&Parent
,
138 ReOptimizeLayer::ReOptMaterializationUnitID MUID
, unsigned CurVerison
,
139 ResourceTrackerSP OldRT
, ThreadSafeModule
&TSM
) {
140 TSM
.withModuleDo([&](Module
&M
) {
142 if (F
.isDeclaration())
146 if (ReturnInst
*Ret
= dyn_cast
<ReturnInst
>(&I
)) {
148 ConstantInt::get(M
.getContext(), APInt(32, 53));
149 Ret
->setOperand(0, RetValue
);
155 return Error::success();
157 EXPECT_THAT_ERROR(ROLayer
->reigsterRuntimeFunctions(*JD
), Succeeded());
159 ThreadSafeContext
Ctx(std::make_unique
<LLVMContext
>());
160 auto M
= std::make_unique
<Module
>("<main>", *Ctx
.getContext());
161 M
->setTargetTriple(sys::getProcessTriple());
163 (void)createRetFunction(M
.get(), "main", 42);
165 EXPECT_THAT_ERROR(addIRModule(JD
->getDefaultResourceTracker(),
166 ThreadSafeModule(std::move(M
), std::move(Ctx
))),
169 auto Result
= cantFail(ES
->lookup({JD
}, Mangle("main")));
170 auto FuncPtr
= Result
.getAddress().toPtr
<int (*)()>();
171 for (size_t I
= 0; I
<= ReOptimizeLayer::CallCountThreshold
; I
++)
172 EXPECT_EQ(FuncPtr(), 42);
173 EXPECT_EQ(FuncPtr(), 53);