xref: /llvm-project/llvm/unittests/ExecutionEngine/Orc/ReOptimizeLayerTest.cpp (revision dc11c0601577afb8f67513d041ee25dabe3555b9)
1188ede28SSunho Kim #include "llvm/ExecutionEngine/Orc/ReOptimizeLayer.h"
2188ede28SSunho Kim #include "OrcTestCommon.h"
3188ede28SSunho Kim #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
4*dc11c060SLang Hames #include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
5188ede28SSunho Kim #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
6188ede28SSunho Kim #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
7188ede28SSunho Kim #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
8188ede28SSunho Kim #include "llvm/ExecutionEngine/Orc/IRPartitionLayer.h"
9188ede28SSunho Kim #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
10188ede28SSunho Kim #include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h"
11188ede28SSunho Kim #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
12188ede28SSunho Kim #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
13188ede28SSunho Kim #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
14188ede28SSunho Kim #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
15188ede28SSunho Kim #include "llvm/IR/IRBuilder.h"
16188ede28SSunho Kim #include "llvm/Support/CodeGen.h"
17188ede28SSunho Kim #include "llvm/TargetParser/Host.h"
18188ede28SSunho Kim #include "llvm/Testing/Support/Error.h"
19188ede28SSunho Kim #include "gtest/gtest.h"
20188ede28SSunho Kim 
21188ede28SSunho Kim using namespace llvm;
22188ede28SSunho Kim using namespace llvm::orc;
23188ede28SSunho Kim using namespace llvm::jitlink;
24188ede28SSunho Kim 
25188ede28SSunho Kim class ReOptimizeLayerTest : public testing::Test {
26188ede28SSunho Kim public:
27188ede28SSunho Kim   ~ReOptimizeLayerTest() {
28188ede28SSunho Kim     if (ES)
29188ede28SSunho Kim       if (auto Err = ES->endSession())
30188ede28SSunho Kim         ES->reportError(std::move(Err));
31188ede28SSunho Kim   }
32188ede28SSunho Kim 
33188ede28SSunho Kim protected:
34188ede28SSunho Kim   void SetUp() override {
35188ede28SSunho Kim     auto JTMB = JITTargetMachineBuilder::detectHost();
36188ede28SSunho Kim     // Bail out if we can not detect the host.
37188ede28SSunho Kim     if (!JTMB) {
38188ede28SSunho Kim       consumeError(JTMB.takeError());
39188ede28SSunho Kim       GTEST_SKIP();
40188ede28SSunho Kim     }
41188ede28SSunho Kim 
42e5f7e73dSSunho Kim     // COFF-ARM64 is not supported yet
43e5f7e73dSSunho Kim     auto Triple = JTMB->getTargetTriple();
44e5f7e73dSSunho Kim     if (Triple.isOSBinFormatCOFF() && Triple.isAArch64())
45e5f7e73dSSunho Kim       GTEST_SKIP();
46e5f7e73dSSunho Kim 
479b7be3ebSTom Stellard     // SystemZ is not supported yet.
489b7be3ebSTom Stellard     if (Triple.isSystemZ())
499b7be3ebSTom Stellard       GTEST_SKIP();
509b7be3ebSTom Stellard 
51beb7fb9dSTom Stellard     // 32-bit X86 is not supported yet.
52beb7fb9dSTom Stellard     if (Triple.isX86() && Triple.isArch32Bit())
53beb7fb9dSTom Stellard       GTEST_SKIP();
54beb7fb9dSTom Stellard 
5539aae575SSunho Kim     if (Triple.isPPC())
5639aae575SSunho Kim       GTEST_SKIP();
5739aae575SSunho Kim 
58188ede28SSunho Kim     auto EPC = SelfExecutorProcessControl::Create();
59188ede28SSunho Kim     if (!EPC) {
60188ede28SSunho Kim       consumeError(EPC.takeError());
61188ede28SSunho Kim       GTEST_SKIP();
62188ede28SSunho Kim     }
637fea5c03SSunho Kim 
647fea5c03SSunho Kim     auto DLOrErr = JTMB->getDefaultDataLayoutForTarget();
657fea5c03SSunho Kim     if (!DLOrErr) {
667fea5c03SSunho Kim       consumeError(DLOrErr.takeError());
677fea5c03SSunho Kim       GTEST_SKIP();
687fea5c03SSunho Kim     }
69188ede28SSunho Kim     ES = std::make_unique<ExecutionSession>(std::move(*EPC));
70188ede28SSunho Kim     JD = &ES->createBareJITDylib("main");
71188ede28SSunho Kim     ObjLinkingLayer = std::make_unique<ObjectLinkingLayer>(
72188ede28SSunho Kim         *ES, std::make_unique<InProcessMemoryManager>(16384));
737fea5c03SSunho Kim     DL = std::make_unique<DataLayout>(std::move(*DLOrErr));
74188ede28SSunho Kim 
75188ede28SSunho Kim     auto TM = JTMB->createTargetMachine();
76188ede28SSunho Kim     if (!TM) {
77188ede28SSunho Kim       consumeError(TM.takeError());
78188ede28SSunho Kim       GTEST_SKIP();
79188ede28SSunho Kim     }
80188ede28SSunho Kim     auto CompileFunction =
81188ede28SSunho Kim         std::make_unique<TMOwningSimpleCompiler>(std::move(*TM));
82188ede28SSunho Kim     CompileLayer = std::make_unique<IRCompileLayer>(*ES, *ObjLinkingLayer,
83188ede28SSunho Kim                                                     std::move(CompileFunction));
84188ede28SSunho Kim   }
85188ede28SSunho Kim 
86188ede28SSunho Kim   Error addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM) {
87188ede28SSunho Kim     assert(TSM && "Can not add null module");
88188ede28SSunho Kim 
89188ede28SSunho Kim     TSM.withModuleDo([&](Module &M) { M.setDataLayout(*DL); });
90188ede28SSunho Kim 
91188ede28SSunho Kim     return ROLayer->add(std::move(RT), std::move(TSM));
92188ede28SSunho Kim   }
93188ede28SSunho Kim 
94188ede28SSunho Kim   JITDylib *JD{nullptr};
95188ede28SSunho Kim   std::unique_ptr<ExecutionSession> ES;
96188ede28SSunho Kim   std::unique_ptr<ObjectLinkingLayer> ObjLinkingLayer;
97188ede28SSunho Kim   std::unique_ptr<IRCompileLayer> CompileLayer;
98188ede28SSunho Kim   std::unique_ptr<ReOptimizeLayer> ROLayer;
99188ede28SSunho Kim   std::unique_ptr<DataLayout> DL;
100188ede28SSunho Kim };
101188ede28SSunho Kim 
102188ede28SSunho Kim static Function *createRetFunction(Module *M, StringRef Name,
103188ede28SSunho Kim                                    uint32_t ReturnCode) {
104188ede28SSunho Kim   Function *Result = Function::Create(
105188ede28SSunho Kim       FunctionType::get(Type::getInt32Ty(M->getContext()), {}, false),
106188ede28SSunho Kim       GlobalValue::ExternalLinkage, Name, M);
107188ede28SSunho Kim 
108188ede28SSunho Kim   BasicBlock *BB = BasicBlock::Create(M->getContext(), Name, Result);
109188ede28SSunho Kim   IRBuilder<> Builder(M->getContext());
110188ede28SSunho Kim   Builder.SetInsertPoint(BB);
111188ede28SSunho Kim 
112188ede28SSunho Kim   Value *RetValue = ConstantInt::get(M->getContext(), APInt(32, ReturnCode));
113188ede28SSunho Kim   Builder.CreateRet(RetValue);
114188ede28SSunho Kim   return Result;
115188ede28SSunho Kim }
116188ede28SSunho Kim 
117188ede28SSunho Kim TEST_F(ReOptimizeLayerTest, BasicReOptimization) {
118188ede28SSunho Kim   MangleAndInterner Mangle(*ES, *DL);
119188ede28SSunho Kim 
120188ede28SSunho Kim   auto &EPC = ES->getExecutorProcessControl();
121188ede28SSunho Kim   EXPECT_THAT_ERROR(JD->define(absoluteSymbols(
122188ede28SSunho Kim                         {{Mangle("__orc_rt_jit_dispatch"),
123188ede28SSunho Kim                           {EPC.getJITDispatchInfo().JITDispatchFunction,
124188ede28SSunho Kim                            JITSymbolFlags::Exported}},
125188ede28SSunho Kim                          {Mangle("__orc_rt_jit_dispatch_ctx"),
126188ede28SSunho Kim                           {EPC.getJITDispatchInfo().JITDispatchContext,
127188ede28SSunho Kim                            JITSymbolFlags::Exported}},
128188ede28SSunho Kim                          {Mangle("__orc_rt_reoptimize_tag"),
129188ede28SSunho Kim                           {ExecutorAddr(), JITSymbolFlags::Exported}}})),
130188ede28SSunho Kim                     Succeeded());
131188ede28SSunho Kim 
132529c0913SLang Hames   auto RM = JITLinkRedirectableSymbolManager::Create(*ObjLinkingLayer);
133188ede28SSunho Kim   EXPECT_THAT_ERROR(RM.takeError(), Succeeded());
134188ede28SSunho Kim 
135188ede28SSunho Kim   ROLayer = std::make_unique<ReOptimizeLayer>(*ES, *DL, *CompileLayer, **RM);
136188ede28SSunho Kim   ROLayer->setReoptimizeFunc(
137188ede28SSunho Kim       [&](ReOptimizeLayer &Parent,
138188ede28SSunho Kim           ReOptimizeLayer::ReOptMaterializationUnitID MUID, unsigned CurVerison,
139188ede28SSunho Kim           ResourceTrackerSP OldRT, ThreadSafeModule &TSM) {
140188ede28SSunho Kim         TSM.withModuleDo([&](Module &M) {
141188ede28SSunho Kim           for (auto &F : M) {
142188ede28SSunho Kim             if (F.isDeclaration())
143188ede28SSunho Kim               continue;
144188ede28SSunho Kim             for (auto &B : F) {
145188ede28SSunho Kim               for (auto &I : B) {
146188ede28SSunho Kim                 if (ReturnInst *Ret = dyn_cast<ReturnInst>(&I)) {
147188ede28SSunho Kim                   Value *RetValue =
148188ede28SSunho Kim                       ConstantInt::get(M.getContext(), APInt(32, 53));
149188ede28SSunho Kim                   Ret->setOperand(0, RetValue);
150188ede28SSunho Kim                 }
151188ede28SSunho Kim               }
152188ede28SSunho Kim             }
153188ede28SSunho Kim           }
154188ede28SSunho Kim         });
155188ede28SSunho Kim         return Error::success();
156188ede28SSunho Kim       });
157188ede28SSunho Kim   EXPECT_THAT_ERROR(ROLayer->reigsterRuntimeFunctions(*JD), Succeeded());
158188ede28SSunho Kim 
159188ede28SSunho Kim   ThreadSafeContext Ctx(std::make_unique<LLVMContext>());
160188ede28SSunho Kim   auto M = std::make_unique<Module>("<main>", *Ctx.getContext());
161188ede28SSunho Kim   M->setTargetTriple(sys::getProcessTriple());
162188ede28SSunho Kim 
163188ede28SSunho Kim   (void)createRetFunction(M.get(), "main", 42);
164188ede28SSunho Kim 
165188ede28SSunho Kim   EXPECT_THAT_ERROR(addIRModule(JD->getDefaultResourceTracker(),
166188ede28SSunho Kim                                 ThreadSafeModule(std::move(M), std::move(Ctx))),
167188ede28SSunho Kim                     Succeeded());
168188ede28SSunho Kim 
169188ede28SSunho Kim   auto Result = cantFail(ES->lookup({JD}, Mangle("main")));
170188ede28SSunho Kim   auto FuncPtr = Result.getAddress().toPtr<int (*)()>();
171188ede28SSunho Kim   for (size_t I = 0; I <= ReOptimizeLayer::CallCountThreshold; I++)
172188ede28SSunho Kim     EXPECT_EQ(FuncPtr(), 42);
173188ede28SSunho Kim   EXPECT_EQ(FuncPtr(), 53);
174188ede28SSunho Kim }
175