blob: 71fd255a68c8babd4e5e9a1fe1253189f43b066f [file] [log] [blame]
#include "llvm/ExecutionEngine/Orc/ReOptimizeLayer.h"
#include "OrcTestCommon.h"
#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/IRPartitionLayer.h"
#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
#include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h"
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace llvm::orc;
using namespace llvm::jitlink;
class ReOptimizeLayerTest : public testing::Test {
public:
~ReOptimizeLayerTest() {
if (ES)
if (auto Err = ES->endSession())
ES->reportError(std::move(Err));
}
protected:
void SetUp() override {
auto JTMB = JITTargetMachineBuilder::detectHost();
// Bail out if we can not detect the host.
if (!JTMB) {
consumeError(JTMB.takeError());
GTEST_SKIP();
}
// COFF-ARM64 is not supported yet
auto Triple = JTMB->getTargetTriple();
if (Triple.isOSBinFormatCOFF() && Triple.isAArch64())
GTEST_SKIP();
// SystemZ is not supported yet.
if (Triple.isSystemZ())
GTEST_SKIP();
// 32-bit X86 is not supported yet.
if (Triple.isX86() && Triple.isArch32Bit())
GTEST_SKIP();
if (Triple.isPPC())
GTEST_SKIP();
// RISC-V is not supported yet
if (Triple.isRISCV())
GTEST_SKIP();
// ARM is not supported yet.
if (Triple.isARM())
GTEST_SKIP();
auto EPC = SelfExecutorProcessControl::Create();
if (!EPC) {
consumeError(EPC.takeError());
GTEST_SKIP();
}
auto DLOrErr = JTMB->getDefaultDataLayoutForTarget();
if (!DLOrErr) {
consumeError(DLOrErr.takeError());
GTEST_SKIP();
}
auto PageSize = sys::Process::getPageSize();
if (!PageSize) {
consumeError(PageSize.takeError());
GTEST_SKIP();
}
ES = std::make_unique<ExecutionSession>(std::move(*EPC));
JD = &ES->createBareJITDylib("main");
ObjLinkingLayer = std::make_unique<ObjectLinkingLayer>(
*ES, std::make_unique<InProcessMemoryManager>(*PageSize));
DL = std::make_unique<DataLayout>(std::move(*DLOrErr));
auto TM = JTMB->createTargetMachine();
if (!TM) {
consumeError(TM.takeError());
GTEST_SKIP();
}
auto CompileFunction =
std::make_unique<TMOwningSimpleCompiler>(std::move(*TM));
CompileLayer = std::make_unique<IRCompileLayer>(*ES, *ObjLinkingLayer,
std::move(CompileFunction));
}
Error addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM) {
assert(TSM && "Can not add null module");
TSM.withModuleDo([&](Module &M) { M.setDataLayout(*DL); });
return ROLayer->add(std::move(RT), std::move(TSM));
}
JITDylib *JD{nullptr};
std::unique_ptr<ExecutionSession> ES;
std::unique_ptr<ObjectLinkingLayer> ObjLinkingLayer;
std::unique_ptr<IRCompileLayer> CompileLayer;
std::unique_ptr<ReOptimizeLayer> ROLayer;
std::unique_ptr<DataLayout> DL;
};
static Function *createRetFunction(Module *M, StringRef Name,
uint32_t ReturnCode) {
Function *Result = Function::Create(
FunctionType::get(Type::getInt32Ty(M->getContext()), {}, false),
GlobalValue::ExternalLinkage, Name, M);
BasicBlock *BB = BasicBlock::Create(M->getContext(), Name, Result);
IRBuilder<> Builder(M->getContext());
Builder.SetInsertPoint(BB);
Value *RetValue = ConstantInt::get(M->getContext(), APInt(32, ReturnCode));
Builder.CreateRet(RetValue);
return Result;
}
TEST_F(ReOptimizeLayerTest, BasicReOptimization) {
MangleAndInterner Mangle(*ES, *DL);
auto &EPC = ES->getExecutorProcessControl();
EXPECT_THAT_ERROR(JD->define(absoluteSymbols(
{{Mangle("__orc_rt_jit_dispatch"),
{EPC.getJITDispatchInfo().JITDispatchFunction,
JITSymbolFlags::Exported}},
{Mangle("__orc_rt_jit_dispatch_ctx"),
{EPC.getJITDispatchInfo().JITDispatchContext,
JITSymbolFlags::Exported}},
{Mangle("__orc_rt_reoptimize_tag"),
{ExecutorAddr(), JITSymbolFlags::Exported}}})),
Succeeded());
auto RM = JITLinkRedirectableSymbolManager::Create(*ObjLinkingLayer);
EXPECT_THAT_ERROR(RM.takeError(), Succeeded());
ROLayer = std::make_unique<ReOptimizeLayer>(*ES, *DL, *CompileLayer, **RM);
ROLayer->setReoptimizeFunc(
[&](ReOptimizeLayer &Parent,
ReOptimizeLayer::ReOptMaterializationUnitID MUID, unsigned CurVerison,
ResourceTrackerSP OldRT, ThreadSafeModule &TSM) {
TSM.withModuleDo([&](Module &M) {
for (auto &F : M) {
if (F.isDeclaration())
continue;
for (auto &B : F) {
for (auto &I : B) {
if (ReturnInst *Ret = dyn_cast<ReturnInst>(&I)) {
Value *RetValue =
ConstantInt::get(M.getContext(), APInt(32, 53));
Ret->setOperand(0, RetValue);
}
}
}
}
});
return Error::success();
});
EXPECT_THAT_ERROR(ROLayer->reigsterRuntimeFunctions(*JD), Succeeded());
ThreadSafeContext Ctx(std::make_unique<LLVMContext>());
auto M = std::make_unique<Module>("<main>", *Ctx.getContext());
M->setTargetTriple(Triple(sys::getProcessTriple()));
(void)createRetFunction(M.get(), "main", 42);
EXPECT_THAT_ERROR(addIRModule(JD->getDefaultResourceTracker(),
ThreadSafeModule(std::move(M), std::move(Ctx))),
Succeeded());
auto Result = cantFail(ES->lookup({JD}, Mangle("main")));
auto FuncPtr = Result.getAddress().toPtr<int (*)()>();
for (size_t I = 0; I <= ReOptimizeLayer::CallCountThreshold; I++)
EXPECT_EQ(FuncPtr(), 42);
EXPECT_EQ(FuncPtr(), 53);
}