Proteus
Programmable JIT compilation and optimization for C/C++ using LLVM
Loading...
Searching...
No Matches
TransformLambdaSpecialization.hpp
Go to the documentation of this file.
1//===-- TransformLambdaSpecialization.hpp -- Specialize arguments --===//
2//
3// Part of the Proteus Project, under the Apache License v2.0 with LLVM
4// Exceptions. See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef PROTEUS_TRANSFORM_LAMBDA_SPECIALIZATION_HPP
12#define PROTEUS_TRANSFORM_LAMBDA_SPECIALIZATION_HPP
13
15#include "proteus/Debug.h"
16#include "proteus/Utils.h"
17
18#include <llvm/Demangle/Demangle.h>
19#include <llvm/IR/IRBuilder.h>
20#include <llvm/IR/Instructions.h>
21#include <llvm/IR/Module.h>
22#include <llvm/Support/Casting.h>
23#include <llvm/Support/Debug.h>
24
25namespace proteus {
26
27using namespace llvm;
28
30 const RuntimeConstant &RC) {
31 switch (RC.Type) {
33 return ConstantInt::get(ArgType, RC.Value.BoolVal);
35 return ConstantInt::get(ArgType, RC.Value.Int8Val);
37 return ConstantInt::get(ArgType, RC.Value.Int32Val);
39 return ConstantInt::get(ArgType, RC.Value.Int64Val);
41 return ConstantFP::get(ArgType, RC.Value.FloatVal);
43 return ConstantFP::get(ArgType, RC.Value.DoubleVal);
45 return ConstantFP::get(ArgType, RC.Value.LongDoubleVal);
47 auto *IntC = ConstantInt::get(Type::getInt64Ty(Ctx), RC.Value.Int64Val);
48 return ConstantExpr::getIntToPtr(IntC, ArgType);
49 }
50 default:
51 std::string TypeString;
53 ArgType->print(TypeOstream);
54 reportFatalError("JIT Incompatible type in runtime constant: " +
55 TypeOstream.str());
56 }
57}
58
60private:
61 static const RuntimeConstant *
62 findArgByOffset(const SmallVector<RuntimeConstant> &RCVec, int32_t Offset) {
63 for (auto &Arg : RCVec) {
64 if (Arg.Offset == Offset)
65 return &Arg;
66 }
67 return nullptr;
68 };
69
70 static const RuntimeConstant *
71 findArgByPos(const SmallVector<RuntimeConstant> &RCVec, int32_t Pos) {
72 for (auto &Arg : RCVec) {
73 if (Arg.Pos == Pos)
74 return &Arg;
75 }
76 return nullptr;
77 };
78
79 static auto traceOut(int Slot, Constant *C) {
82 OS << "[LambdaSpec] Replacing slot " << Slot << " with " << *C << "\n";
83
84 return S;
85 };
86
87 static void handleLoad(Module &M, User *User,
88 const SmallVector<RuntimeConstant> &RCVec) {
89 auto *Arg = findArgByPos(RCVec, 0);
90 if (!Arg)
91 return;
92
93 Constant *C = getConstant(M.getContext(), User->getType(), *Arg);
94 User->replaceAllUsesWith(C);
95 PROTEUS_DBG(Logger::logs("proteus") << traceOut(Arg->Pos, C));
96 if (Config::get().ProteusTraceOutput >= 1)
97 Logger::trace(traceOut(Arg->Pos, C));
98 }
99
100 static void handleGEP(Module &M, GetElementPtrInst *GEP, User *User,
101 const SmallVector<RuntimeConstant> &RCVec) {
102 auto *GEPSlot = GEP->getOperand(User->getNumOperands() - 1);
104 int Slot = CI->getZExtValue();
105 Type *SrcTy = GEP->getSourceElementType();
106
107 auto *Arg = SrcTy->isStructTy() ? findArgByPos(RCVec, Slot)
108 : findArgByOffset(RCVec, Slot);
109 if (!Arg)
110 return;
111
112 for (auto *GEPUser : GEP->users()) {
114 if (!LI)
115 reportFatalError("Expected load instruction");
116 Type *LoadType = LI->getType();
117 Constant *C = getConstant(M.getContext(), LoadType, *Arg);
118 LI->replaceAllUsesWith(C);
119 PROTEUS_DBG(Logger::logs("proteus") << traceOut(Arg->Pos, C));
120 if (Config::get().ProteusTraceOutput >= 1)
121 Logger::trace(traceOut(Arg->Pos, C));
122 }
123 }
124
125public:
126 static void transform(Module &M, Function &F,
127 const SmallVector<RuntimeConstant> &RCVec) {
128 auto *LambdaClass = F.getArg(0);
129 PROTEUS_DBG(Logger::logs("proteus")
130 << "[LambdaSpec] Function: " << F.getName() << " RCVec size "
131 << RCVec.size() << "\n");
132 PROTEUS_DBG(Logger::logs("proteus")
133 << "TransformLambdaSpecialization::transform" << "\n");
134 PROTEUS_DBG(Logger::logs("proteus") << "\t args" << "\n");
135 if (Config::get().ProteusDebugOutput) {
136 for (auto &Arg : RCVec) {
137 Logger::logs("proteus")
138 << "{" << Arg.Value.Int64Val << ", " << Arg.Pos << " }\n";
139 }
140 }
141
142 PROTEUS_DBG(Logger::logs("proteus") << "\t users" << "\n");
143 for (User *User : LambdaClass->users()) {
144 PROTEUS_DBG(Logger::logs("proteus") << *User << "\n");
145 if (isa<LoadInst>(User))
146 handleLoad(M, User, RCVec);
147 else if (auto *GEP = dyn_cast<GetElementPtrInst>(User))
148 handleGEP(M, GEP, User, RCVec);
149 }
150 }
151};
152
153} // namespace proteus
154
155#endif
#define PROTEUS_DBG(x)
Definition Debug.h:9
static Config & get()
Definition Config.hpp:300
static void trace(llvm::StringRef Msg)
Definition Logger.hpp:30
static llvm::raw_ostream & logs(const std::string &Name)
Definition Logger.hpp:19
Definition TransformLambdaSpecialization.hpp:59
static void transform(Module &M, Function &F, const SmallVector< RuntimeConstant > &RCVec)
Definition TransformLambdaSpecialization.hpp:126
Definition Helpers.h:141
Definition ObjectCacheChain.cpp:26
static int Pos
Definition JitInterface.hpp:105
@ INT32
Definition CompilerInterfaceTypes.h:25
@ INT64
Definition CompilerInterfaceTypes.h:26
@ FLOAT
Definition CompilerInterfaceTypes.h:27
@ LONG_DOUBLE
Definition CompilerInterfaceTypes.h:29
@ INT8
Definition CompilerInterfaceTypes.h:24
@ BOOL
Definition CompilerInterfaceTypes.h:23
@ PTR
Definition CompilerInterfaceTypes.h:30
@ DOUBLE
Definition CompilerInterfaceTypes.h:28
void reportFatalError(const llvm::Twine &Reason, const char *FILE, unsigned Line)
Definition Error.cpp:14
T getRuntimeConstantValue(void *Arg)
Definition CompilerInterfaceRuntimeConstantInfo.h:113
Constant * getConstant(LLVMContext &Ctx, Type *ArgType, const RuntimeConstant &RC)
Definition TransformLambdaSpecialization.hpp:29
Definition CompilerInterfaceTypes.h:72