Proteus
Programmable JIT compilation and optimization for C/C++ using LLVM
Loading...
Searching...
No Matches
TransformSharedArray.hpp
Go to the documentation of this file.
1//===-- TransformSharedArray.hpp -- Shared array with specialized size--===//
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_SHARED_ARRAY_HPP
12#define PROTEUS_TRANSFORM_SHARED_ARRAY_HPP
13
14#include <llvm/Analysis/ConstantFolding.h>
15#include <llvm/Demangle/Demangle.h>
16#include <llvm/IR/IRBuilder.h>
17#include <llvm/IR/Verifier.h>
18#include <llvm/Support/Debug.h>
19
20#include "proteus/Debug.h"
21#include "proteus/Logger.hpp"
22#include "proteus/Utils.h"
23
24namespace proteus {
25
26using namespace llvm;
27
29public:
30 static void transform(Module &M) {
31 for (auto &Func : M.functions()) {
32 std::string DemangledName = llvm::demangle(Func.getName().str());
33 StringRef StrRef{DemangledName};
34 if (StrRef.contains("proteus::shared_array")) {
35
36 // Use a while loop to delete while iterating.
37 while (!Func.user_empty()) {
38 User *Usr = *Func.user_begin();
39 if (!isa<CallBase>(Usr))
40 PROTEUS_FATAL_ERROR("Expected call user");
41
42 CallBase *CB = cast<CallBase>(Usr);
43 assert(CB->arg_size() == 2 && "Expected 2 arguments: N and sizeof");
44 int64_t N;
45 int64_t Sizeof;
46 if (!getConstantValue(CB->getArgOperand(0), N, M.getDataLayout()))
47 PROTEUS_FATAL_ERROR("Expected constant N argument");
48 if (!getConstantValue(CB->getArgOperand(1), Sizeof,
49 M.getDataLayout()))
50 PROTEUS_FATAL_ERROR("Expected constant Sizeof argument");
51
52 ArrayType *AType =
53 ArrayType::get(Type::getInt8Ty(M.getContext()), N * Sizeof);
54 constexpr unsigned SharedMemAddrSpace = 3;
55 GlobalVariable *SharedMemGV = new GlobalVariable(
56 M, AType, false, GlobalValue::InternalLinkage,
57 UndefValue::get(AType), ".proteus.shared", nullptr,
58 llvm::GlobalValue::NotThreadLocal, SharedMemAddrSpace, false);
59 // Using 16-byte alignment based on AOT code generation.
60 // TODO: Create or find an API to query the proper ABI alignment.
61 SharedMemGV->setAlignment(Align{16});
62
63 PROTEUS_DBG(Logger::logs("proteus")
64 << "[SharedArray] " << "Replace CB " << *CB << " with "
65 << *SharedMemGV << "\n");
66
67 CB->replaceAllUsesWith(ConstantExpr::getAddrSpaceCast(
68 SharedMemGV, CB->getFunctionType()->getReturnType()));
69 CB->eraseFromParent();
70 }
71
72#if PROTEUS_ENABLE_DEBUG
73 if (verifyModule(M, &errs()))
74 PROTEUS_FATAL_ERROR("Broken module found, JIT compilation aborted!");
75#endif
76 }
77 }
78 }
79
80private:
81 static bool getConstantValue(Value *V, int64_t &Result,
82 const DataLayout &DL) {
83 // Directly access the value of a constant.
84 if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
85 Result = CI->getSExtValue();
86 return true;
87 }
88
89 // Fold an instruction.
90 if (Instruction *I = dyn_cast<Instruction>(V)) {
91 if (Value *FoldedV = ConstantFoldInstruction(I, DL, nullptr)) {
92 if (ConstantInt *CI = dyn_cast<ConstantInt>(FoldedV)) {
93 Result = CI->getSExtValue();
94 return true;
95 }
96 }
97 }
98
99 return false;
100 }
101};
102
103} // namespace proteus
104
105#endif
#define PROTEUS_DBG(x)
Definition Debug.h:7
#define PROTEUS_FATAL_ERROR(x)
Definition Error.h:4
static llvm::raw_ostream & logs(const std::string &Name)
Definition Logger.hpp:18
Definition TransformSharedArray.hpp:28
static void transform(Module &M)
Definition TransformSharedArray.hpp:30
Definition JitEngine.cpp:20