|
|
@@ -8,7 +8,17 @@
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
#include "llvm/Analysis/CFG.h"
|
|
|
#include "llvm/Analysis/CallGraph.h"
|
|
|
-#include "LogSystem.h"
|
|
|
+#include "llvm/IR/IRBuilder.h"
|
|
|
+#include "llvm/Transforms/Utils/ValueMapper.h"
|
|
|
+#include "llvm/Transforms/Utils/Cloning.h"
|
|
|
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
|
|
+
|
|
|
+#include "Util/LogSystem.h"
|
|
|
+#include "Util/CallGraphManager.h"
|
|
|
+#include "Util/Utils.h"
|
|
|
+#include "Fusion/SliceAnalyzer.h"
|
|
|
+#include "Fusion/Fusion.h"
|
|
|
+
|
|
|
#include <vector>
|
|
|
#include <map>
|
|
|
#include <set>
|
|
|
@@ -16,64 +26,27 @@
|
|
|
#include <random>
|
|
|
#include <algorithm>
|
|
|
#include <string>
|
|
|
-#include "llvm/IR/IRBuilder.h"
|
|
|
-#include "llvm/Transforms/Utils/ValueMapper.h"
|
|
|
-#include "llvm/Transforms/Utils/Cloning.h"
|
|
|
-#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
-namespace {
|
|
|
- struct Slice {
|
|
|
- std::vector<BasicBlock*> blocks;
|
|
|
- };
|
|
|
+extern logging::LogSystem logger;
|
|
|
|
|
|
+namespace {
|
|
|
struct SliceBlocks {
|
|
|
std::vector<BasicBlock*> blocks;
|
|
|
- BasicBlock* phiBlock;
|
|
|
- };
|
|
|
-
|
|
|
- struct CallNode {
|
|
|
- std::string name;
|
|
|
- bool isTarget;
|
|
|
- std::set<std::string> callers;
|
|
|
- std::set<std::string> callees;
|
|
|
- unsigned depth;
|
|
|
- std::set<BasicBlock*> criticalPoints;
|
|
|
- unsigned points_num; // 融合点个数
|
|
|
- unsigned slices_num; //分片个数
|
|
|
- std::vector<Slice> slices; // 存储函数分片
|
|
|
-
|
|
|
- CallNode() : name(""), isTarget(false), depth(0), points_num(0), slices_num(0) {}
|
|
|
-
|
|
|
- CallNode(std::string n, bool target = false)
|
|
|
- : name(n), isTarget(target), depth(0), points_num(0), slices_num(0) {}
|
|
|
- };
|
|
|
-
|
|
|
- struct SliceTransition {
|
|
|
- BasicBlock* bunkerLastBlock; // bunker分片的最后一个基本块
|
|
|
- BasicBlock* targetFirstBlock; // target分片的第一个基本块
|
|
|
- BasicBlock* targetLastBlock; // target分片的最后一个基本块
|
|
|
- BasicBlock* nextBunkerBlock; // 下一个bunker分片的第一个基本块
|
|
|
+ std::vector<BasicBlock*> backBlocks;
|
|
|
};
|
|
|
|
|
|
struct CodeFusionPass : public ModulePass {
|
|
|
public:
|
|
|
static char ID;
|
|
|
- CodeFusionPass() : ModulePass(ID) {}
|
|
|
+ CodeFusionPass() : ModulePass(ID), callGraph() {}
|
|
|
|
|
|
bool runOnModule(Module &M) override {
|
|
|
auto& logger = logging::LogSystem::getInstance();
|
|
|
- logger.setGlobalLevel(logging::LogLevel::DEBUG);
|
|
|
+ logger.setGlobalLevel(logging::LogLevel::TRACE);
|
|
|
// 配置Log输出权限
|
|
|
logger.enableFunction("runOnModule");
|
|
|
- // logger.enableFunction("dumpControlFlowGraph");
|
|
|
- logger.enableFunction("buildCallGraph");
|
|
|
- // logger.enableFunction("analyzeFunctionCriticalPoints");
|
|
|
- // logger.enableFunction("calculateCallDepths");
|
|
|
- logger.enableFunction("matchFunctionsForFusion");
|
|
|
- logger.enableFunction("createFunctionSlices");
|
|
|
- logger.enableFunction("countFusionPoints");
|
|
|
logger.enableFunction("generateFusionMatchGraph");
|
|
|
logger.enableFunction("performCodeFusion");
|
|
|
logger.enableFunction("updateCallSite");
|
|
|
@@ -91,21 +64,33 @@ namespace {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- buildCallGraph(M);
|
|
|
- analyzeFunctionCriticalPoints(M);
|
|
|
- calculateCallDepths(M);
|
|
|
- generateProjectCallGraph();
|
|
|
+ callGraph.buildCallGraph(M, targetFunctions);
|
|
|
+ callGraph.buildCallGraph(M, bunkerFunctions);
|
|
|
+
|
|
|
+ // 遍历模块中的所有函数,对每个函数调用SliceAnalyzer的分析函数
|
|
|
+ for (Function &F : M) {
|
|
|
+ if (!F.isDeclaration()) {
|
|
|
+ std::string fname = F.getName().str();
|
|
|
+ auto criticalPoints = slicefusion::SliceAnalyzer::analyzeFunctionCriticalPoints(F);
|
|
|
+ // 将分析结果存储到callGraph中
|
|
|
+ callGraph[fname].criticalPoints = criticalPoints;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 生成项目调用图
|
|
|
+ callGraph.generateProjectCallGraph();
|
|
|
+ // 遍历模块中的所有函数,对每个函数调用SliceAnalyzer的分析函数
|
|
|
for (Function &F : M) {
|
|
|
if(!F.isDeclaration()){
|
|
|
- dumpControlFlowGraph(F);
|
|
|
+ callGraph.dumpControlFlowGraph(F);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
LOG_INFO("runOnModule", "Creating slices for target functions");
|
|
|
for (const auto& targetFuncName : targetFunctions) {
|
|
|
- LOG_INFO("runOnModule", "targetFuncName: {0}",targetFuncName);
|
|
|
+ LOG_INFO("runOnModule", "targetFuncName: {0}", targetFuncName);
|
|
|
if (Function* F = M.getFunction(targetFuncName)) {
|
|
|
- createFunctionSlices(*F);
|
|
|
+ slicefusion::SliceAnalyzer::createFunctionSlices(*F, callGraph[targetFuncName]);
|
|
|
} else {
|
|
|
LOG_ERROR("runOnModule", "Could not find function {0} in module", targetFuncName);
|
|
|
}
|
|
|
@@ -113,1985 +98,28 @@ namespace {
|
|
|
|
|
|
LOG_INFO("runOnModule", "Creating fusion points for bunker functions");
|
|
|
for (const auto& bunkerFuncName : bunkerFunctions) {
|
|
|
- LOG_INFO("runOnModule", "bunkerFuncName: {0}",bunkerFuncName);
|
|
|
+ LOG_INFO("runOnModule", "bunkerFuncName: {0}", bunkerFuncName);
|
|
|
if (Function* F = M.getFunction(bunkerFuncName)) {
|
|
|
- countFusionPoints(*F);
|
|
|
- createFunctionSlices(*F);
|
|
|
+ slicefusion::SliceAnalyzer::countFusionPoints(*F, callGraph[bunkerFuncName]);
|
|
|
} else {
|
|
|
LOG_ERROR("runOnModule", "Could not find function {0} in module", bunkerFuncName);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if(matchFunctionsForFusion()){
|
|
|
- generateFusionMatchGraph();
|
|
|
- performCodeFusion(M);
|
|
|
+ // 创建一个Fusion对象并保持它的生命周期
|
|
|
+ slicefusion::Fusion fusion(callGraph);
|
|
|
+ if(fusion.matchFunctionsForFusion(targetFunctions, bunkerFunctions)) {
|
|
|
+ callGraph.generateFusionMatchGraph(targetFunctions, bunkerFunctions, fusion.getFusionPairs());
|
|
|
+ fusion.performCodeFusion(M);
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
- std::map<std::string, CallNode> callGraph;
|
|
|
- std::map<std::string, unsigned> maxCallDepths;
|
|
|
+ CallGraphManager callGraph;
|
|
|
std::set<std::string> targetFunctions;
|
|
|
std::set<std::string> bunkerFunctions;
|
|
|
- std::map<std::string, std::string> fusionPairs;
|
|
|
-
|
|
|
- size_t getRandomIndex(size_t max) {
|
|
|
- static unsigned seed = 0;
|
|
|
- seed = (seed * 1103515245 + 12345) & 0x7fffffff;
|
|
|
- return seed % max;
|
|
|
- }
|
|
|
-
|
|
|
- bool matchFunctionsForFusion() {
|
|
|
- LOG_INFO("matchFunctionsForFusion", "Starting function matching process");
|
|
|
-
|
|
|
- if (bunkerFunctions.size() < targetFunctions.size()) {
|
|
|
- LOG_WARNING("matchFunctionsForFusion",
|
|
|
- "Insufficient bunker functions ({0}) for target functions ({1})",
|
|
|
- bunkerFunctions.size(),
|
|
|
- targetFunctions.size());
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- std::vector<std::string> sortedTargets(targetFunctions.begin(), targetFunctions.end());
|
|
|
- std::sort(sortedTargets.begin(), sortedTargets.end(),
|
|
|
- [this](const std::string& a, const std::string& b) {
|
|
|
- return callGraph[a].slices_num > callGraph[b].slices_num; // 降序排列
|
|
|
- });
|
|
|
-
|
|
|
- std::vector<std::string> availableBunkers(bunkerFunctions.begin(), bunkerFunctions.end());
|
|
|
-
|
|
|
- for (const auto& targetFunc : sortedTargets) {
|
|
|
- const auto& targetNode = callGraph[targetFunc];
|
|
|
- size_t requiredPoints = targetNode.slices_num;
|
|
|
-
|
|
|
- bool matched = false;
|
|
|
- while (!availableBunkers.empty() && !matched) {
|
|
|
- size_t idx = getRandomIndex(availableBunkers.size());
|
|
|
- const auto& bunkerFunc = availableBunkers[idx];
|
|
|
- const auto& bunkerNode = callGraph[bunkerFunc];
|
|
|
-
|
|
|
- if (bunkerNode.points_num >= requiredPoints) {
|
|
|
- fusionPairs[targetFunc] = bunkerFunc;
|
|
|
- availableBunkers.erase(availableBunkers.begin() + idx);
|
|
|
- matched = true;
|
|
|
- LOG_INFO("matchFunctionsForFusion",
|
|
|
- "Matched target {0} ({1} slices) with bunker {2} ({3} fusion points)",
|
|
|
- targetFunc,
|
|
|
- targetNode.slices_num,
|
|
|
- bunkerFunc,
|
|
|
- bunkerNode.points_num);
|
|
|
- } else {
|
|
|
- availableBunkers.erase(availableBunkers.begin() + idx);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!matched) {
|
|
|
- LOG_ERROR("matchFunctionsForFusion",
|
|
|
- "Could not find suitable bunker function for target {0}",
|
|
|
- targetFunc);
|
|
|
- return false;
|
|
|
- }
|
|
|
- // LOG_INFO("matchFunctionsForFusion", "Remaining bunker functions after matching {0}:", targetFunc);
|
|
|
- // for (const auto& remainingBunker : availableBunkers) {
|
|
|
- // const auto& bunkerNode = callGraph[remainingBunker];
|
|
|
- // LOG_INFO("matchFunctionsForFusion",
|
|
|
- // " {0} (Critical Points: {1})",
|
|
|
- // remainingBunker,
|
|
|
- // bunkerNode.criticalPoints.size());
|
|
|
- // }
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- void generateFusionMatchGraph() {
|
|
|
- LOG_INFO("generateFusionMatchGraph", "Generating fusion match visualization");
|
|
|
-
|
|
|
- errs() << "```mermaid\n";
|
|
|
- errs() << "graph LR\n";
|
|
|
- errs() << " %% Fusion Match Graph\n";
|
|
|
- errs() << " %% Left side: Target Project, Right side: Bunker Project\n\n";
|
|
|
-
|
|
|
- errs() << " subgraph Target[\"Target Project\"]\n";
|
|
|
- errs() << " direction TB\n";
|
|
|
- for (const auto& targetFunc : targetFunctions) {
|
|
|
- std::string nodeId = sanitizeNodeId(targetFunc);
|
|
|
- std::string sliceNum = std::to_string(callGraph[targetFunc].slices_num);
|
|
|
- errs() << " " << nodeId << "[\"" << targetFunc
|
|
|
- << "\\nSliceNum: " << sliceNum
|
|
|
- << "\"]:::target\n";
|
|
|
- }
|
|
|
- errs() << " end\n\n";
|
|
|
-
|
|
|
- errs() << " subgraph Bunker[\"Bunker Project\"]\n";
|
|
|
- errs() << " direction TB\n";
|
|
|
- for (const auto& bunkerFunc : bunkerFunctions) {
|
|
|
- std::string nodeId = sanitizeNodeId(bunkerFunc);
|
|
|
- std::string criticalPoints = std::to_string(callGraph[bunkerFunc].criticalPoints.size());
|
|
|
- errs() << " " << nodeId << "[\"" << bunkerFunc
|
|
|
- << "\\nCritical Points: " << criticalPoints
|
|
|
- << "\"]:::bunker\n";
|
|
|
- }
|
|
|
- errs() << " end\n\n";
|
|
|
-
|
|
|
- errs() << " %% Fusion Matches\n";
|
|
|
- for (const auto& match : fusionPairs) {
|
|
|
- std::string targetId = sanitizeNodeId(match.first);
|
|
|
- std::string bunkerId = sanitizeNodeId(match.second);
|
|
|
- errs() << " " << targetId << " ==>|fusion| " << bunkerId << "\n";
|
|
|
- }
|
|
|
-
|
|
|
- errs() << " %% Styles\n";
|
|
|
- errs() << " classDef target fill:#f96,stroke:#333,stroke-width:2px\n";
|
|
|
- errs() << " classDef bunker fill:#9cf,stroke:#333,stroke-width:2px\n";
|
|
|
- errs() << " style Target fill:#fff,stroke:#f96,stroke-width:2px\n";
|
|
|
- errs() << " style Bunker fill:#fff,stroke:#9cf,stroke-width:2px\n";
|
|
|
-
|
|
|
- errs() << "```\n\n";
|
|
|
-
|
|
|
- LOG_INFO("generateFusionMatchGraph",
|
|
|
- "Generated visualization with {0} target functions and {1} bunker functions",
|
|
|
- targetFunctions.size(),
|
|
|
- bunkerFunctions.size());
|
|
|
- LOG_INFO("generateFusionMatchGraph",
|
|
|
- "Total fusion matches: {0}",
|
|
|
- fusionPairs.size());
|
|
|
- }
|
|
|
-
|
|
|
- void countFusionPoints(Function& F) {
|
|
|
- std::string fname = F.getName().str();
|
|
|
-
|
|
|
- if (targetFunctions.find(fname) != targetFunctions.end()) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- auto& criticalPoints = callGraph[fname].criticalPoints;
|
|
|
- if (criticalPoints.empty()) {
|
|
|
- callGraph[fname].points_num = 0;
|
|
|
- return;
|
|
|
- }
|
|
|
- callGraph[fname].points_num = criticalPoints.size();
|
|
|
-
|
|
|
- LOG_INFO("countFusionPoints",
|
|
|
- "Counted {0} fusion points for bunker function {1}",
|
|
|
- criticalPoints.size(),
|
|
|
- fname);
|
|
|
- }
|
|
|
-
|
|
|
- void createFunctionSlices(Function& F) {
|
|
|
- std::string fname = F.getName().str();
|
|
|
-
|
|
|
- if (!callGraph[fname].isTarget) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- auto& criticalPoints = callGraph[fname].criticalPoints;
|
|
|
- if (criticalPoints.empty()) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- BasicBlock* entryBlock = &F.getEntryBlock();
|
|
|
- criticalPoints.insert(entryBlock);
|
|
|
-
|
|
|
- std::vector<BasicBlock*> orderedPoints(criticalPoints.begin(), criticalPoints.end());
|
|
|
- std::sort(orderedPoints.begin(), orderedPoints.end(),
|
|
|
- [](BasicBlock* a, BasicBlock* b) {
|
|
|
- return a->getName() < b->getName();
|
|
|
- });
|
|
|
-
|
|
|
- std::set<BasicBlock*> processedBlocks;
|
|
|
- std::vector<Slice>& slices = callGraph[fname].slices;
|
|
|
- slices.clear(); // 确保开始前清空
|
|
|
-
|
|
|
- for (size_t i = 0; i < orderedPoints.size(); i++) {
|
|
|
- BasicBlock* currentCritical = orderedPoints[i];
|
|
|
-
|
|
|
- if (processedBlocks.count(currentCritical)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- size_t numSuccessors = std::distance(succ_begin(currentCritical), succ_end(currentCritical));
|
|
|
- size_t numPredecessors = std::distance(pred_begin(currentCritical), pred_end(currentCritical));
|
|
|
-
|
|
|
- Slice newSlice;
|
|
|
- if (numSuccessors <= 1 && numPredecessors <= 1) {
|
|
|
- newSlice.blocks.push_back(currentCritical);
|
|
|
- processedBlocks.insert(currentCritical);
|
|
|
- } else {
|
|
|
- BasicBlock* nextCritical = nullptr;
|
|
|
- for (size_t j = i + 1; j < orderedPoints.size(); j++) {
|
|
|
- if (!processedBlocks.count(orderedPoints[j])) {
|
|
|
- nextCritical = orderedPoints[j];
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!nextCritical) {
|
|
|
- newSlice.blocks.push_back(currentCritical);
|
|
|
- processedBlocks.insert(currentCritical);
|
|
|
- } else {
|
|
|
- std::queue<BasicBlock*> queue;
|
|
|
- queue.push(currentCritical);
|
|
|
- while (!queue.empty()) {
|
|
|
- BasicBlock* current = queue.front();
|
|
|
- queue.pop();
|
|
|
- if (processedBlocks.count(current)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- processedBlocks.insert(current);
|
|
|
- newSlice.blocks.push_back(current);
|
|
|
- if (current != nextCritical) {
|
|
|
- for (BasicBlock* succ : successors(current)) {
|
|
|
- if (!processedBlocks.count(succ) &&
|
|
|
- (succ == nextCritical || !criticalPoints.count(succ))) {
|
|
|
- queue.push(succ);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (!newSlice.blocks.empty()) {
|
|
|
- slices.push_back(newSlice);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- callGraph[fname].slices_num = slices.size();
|
|
|
-
|
|
|
- LOG_INFO("createFunctionSlices",
|
|
|
- "Created {0} slices for target function {1}",
|
|
|
- slices.size(),
|
|
|
- fname);
|
|
|
-
|
|
|
- for (size_t i = 0; i < slices.size(); i++) {
|
|
|
- std::string blockNames;
|
|
|
- for (BasicBlock* block : slices[i].blocks) {
|
|
|
- if (!blockNames.empty()) {
|
|
|
- blockNames += ", ";
|
|
|
- }
|
|
|
- blockNames += getNodeId(block);
|
|
|
- }
|
|
|
- LOG_DEBUG("createFunctionSlices",
|
|
|
- "Slice {0} of function {1} contains blocks: {2}",
|
|
|
- i,
|
|
|
- fname,
|
|
|
- blockNames);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- bool isTargetCode(Function &F) {
|
|
|
- if (MDNode *MD = F.getMetadata("project_source")) {
|
|
|
- if (MDString *ProjectStr = dyn_cast<MDString>(MD->getOperand(0))) {
|
|
|
- std::string projectName = ProjectStr->getString().str();
|
|
|
- return (projectName == "Target");
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- void dumpControlFlowGraph(Function &F) {
|
|
|
- LOG_INFO("dumpControlFlowGraph", "Generating control flow graph for function: {0}",
|
|
|
- F.getName().str());
|
|
|
-
|
|
|
- if (F.empty()) {
|
|
|
- LOG_WARNING("dumpControlFlowGraph", "Function is empty!");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- LOG_INFO("dumpControlFlowGraph", "Starting Mermaid graph generation");
|
|
|
- errs() << "```mermaid: " << F.getName().str() << "\n";
|
|
|
- errs() << "graph TD\n";
|
|
|
-
|
|
|
- for (BasicBlock &BB : F) {
|
|
|
- std::string nodeId = getNodeId(&BB);
|
|
|
- if (!nodeId.empty() && nodeId[0] == '%') {
|
|
|
- nodeId = nodeId.substr(1);
|
|
|
- }
|
|
|
- std::replace(nodeId.begin(), nodeId.end(), '.', '_');
|
|
|
- std::replace(nodeId.begin(), nodeId.end(), ' ', '_');
|
|
|
- std::replace(nodeId.begin(), nodeId.end(), '%', '_');
|
|
|
- std::replace(nodeId.begin(), nodeId.end(), '-', '_');
|
|
|
-
|
|
|
- LOG_TRACE("dumpControlFlowGraph", "Processing block with ID: {0}", nodeId);
|
|
|
-
|
|
|
- std::string blockContent;
|
|
|
- raw_string_ostream contentOS(blockContent);
|
|
|
-
|
|
|
- contentOS << "Block " << nodeId << ":\\n";
|
|
|
-
|
|
|
- for (Instruction &I : BB) {
|
|
|
- std::string instStr;
|
|
|
- raw_string_ostream instOS(instStr);
|
|
|
- I.print(instOS);
|
|
|
- instOS.flush();
|
|
|
-
|
|
|
- std::replace(instStr.begin(), instStr.end(), '"', '\'');
|
|
|
- std::replace(instStr.begin(), instStr.end(), '\n', ' ');
|
|
|
-
|
|
|
- if (instStr.length() > 50) {
|
|
|
- LOG_TRACE("dumpControlFlowGraph", "Truncating long instruction in block {0}", nodeId);
|
|
|
- instStr = instStr.substr(0, 47) + "...";
|
|
|
- }
|
|
|
-
|
|
|
- contentOS << instStr << "\\n";
|
|
|
- }
|
|
|
- contentOS.flush();
|
|
|
-
|
|
|
- std::string fname = F.getName().str();
|
|
|
-
|
|
|
- if (callGraph[fname].criticalPoints.count(&BB)) {
|
|
|
- LOG_TRACE("dumpControlFlowGraph", "Marking block {0} as critical", nodeId);
|
|
|
- errs() << " " << nodeId << "[\"" << blockContent << "\"]:::critical\n";
|
|
|
- } else {
|
|
|
- errs() << " " << nodeId << "[\"" << blockContent << "\"]\n";
|
|
|
- }
|
|
|
-
|
|
|
- for (BasicBlock *Succ : successors(&BB)) {
|
|
|
- std::string succId;
|
|
|
- raw_string_ostream succOS(succId);
|
|
|
- Succ->printAsOperand(succOS, false);
|
|
|
- succOS.flush();
|
|
|
-
|
|
|
- if (!succId.empty() && succId[0] == '%') {
|
|
|
- succId = succId.substr(1);
|
|
|
- }
|
|
|
-
|
|
|
- std::replace(succId.begin(), succId.end(), '.', '_');
|
|
|
- std::replace(succId.begin(), succId.end(), ' ', '_');
|
|
|
- std::replace(succId.begin(), succId.end(), '%', '_');
|
|
|
- std::replace(succId.begin(), succId.end(), '-', '_');
|
|
|
-
|
|
|
- LOG_TRACE("dumpControlFlowGraph", "Processing edge from {0} to {1}", nodeId, succId);
|
|
|
-
|
|
|
- if (BranchInst *BI = dyn_cast<BranchInst>(BB.getTerminator())) {
|
|
|
- if (BI->isConditional()) {
|
|
|
- std::string condStr;
|
|
|
- raw_string_ostream condOS(condStr);
|
|
|
- BI->getCondition()->print(condOS);
|
|
|
- condOS.flush();
|
|
|
-
|
|
|
- bool isTrue = BI->getSuccessor(0) == Succ;
|
|
|
- LOG_TRACE("dumpControlFlowGraph", "Adding conditional branch edge: {0}",
|
|
|
- isTrue ? "true" : "false");
|
|
|
- errs() << " " << nodeId << " -->|"
|
|
|
- << (isTrue ? "true" : "false") << "| "
|
|
|
- << succId << "\n";
|
|
|
- } else {
|
|
|
- errs() << " " << nodeId << " --> " << succId << "\n";
|
|
|
- }
|
|
|
- } else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB.getTerminator())) {
|
|
|
- if (Succ == SI->getDefaultDest()) {
|
|
|
- LOG_TRACE("dumpControlFlowGraph", "Adding switch default edge");
|
|
|
- errs() << " " << nodeId << " -->|default| " << succId << "\n";
|
|
|
- } else {
|
|
|
- for (auto Case : SI->cases()) {
|
|
|
- if (Case.getCaseSuccessor() == Succ) {
|
|
|
- std::string caseStr;
|
|
|
- raw_string_ostream caseOS(caseStr);
|
|
|
- Case.getCaseValue()->print(caseOS);
|
|
|
- LOG_TRACE("dumpControlFlowGraph", "Adding switch case edge: {0}",
|
|
|
- caseStr);
|
|
|
- errs() << " " << nodeId << " -->|case "
|
|
|
- << caseStr << "| " << succId << "\n";
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- errs() << " " << nodeId << " --> " << succId << "\n";
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- errs() << " classDef critical fill:#f96,stroke:#333,stroke-width:4px\n";
|
|
|
- errs() << "```\n";
|
|
|
- LOG_INFO("dumpControlFlowGraph", "Completed graph generation");
|
|
|
- }
|
|
|
-
|
|
|
- std::string getNodeId(BasicBlock *BB) {
|
|
|
- std::string nodeId;
|
|
|
- raw_string_ostream idOS(nodeId);
|
|
|
- BB->printAsOperand(idOS, false);
|
|
|
- idOS.flush();
|
|
|
- return nodeId;
|
|
|
- }
|
|
|
-
|
|
|
- bool checkCriticalPoint(BasicBlock *BB) {
|
|
|
- if (!BB) return false;
|
|
|
- Function *F = BB->getParent();
|
|
|
- if (!F) return false;
|
|
|
- BasicBlock *Entry = &F->getEntryBlock();
|
|
|
- BasicBlock *Exit = nullptr;
|
|
|
- for (BasicBlock &B : *F) {
|
|
|
- if (isa<ReturnInst>(B.getTerminator()) ||
|
|
|
- isa<UnreachableInst>(B.getTerminator())) {
|
|
|
- Exit = &B;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (!Exit) return false;
|
|
|
- std::set<BasicBlock*> visitedWithoutCurrent;
|
|
|
- std::function<bool(BasicBlock*, BasicBlock*)> canReachExitWithout;
|
|
|
- canReachExitWithout = [&canReachExitWithout, &visitedWithoutCurrent, BB]
|
|
|
- (BasicBlock *Start, BasicBlock *Target) -> bool {
|
|
|
- if (Start == BB) return false;
|
|
|
- if (Start == Target) return true;
|
|
|
-
|
|
|
- if (visitedWithoutCurrent.count(Start)) return false;
|
|
|
- visitedWithoutCurrent.insert(Start);
|
|
|
-
|
|
|
- for (BasicBlock *Succ : successors(Start)) {
|
|
|
- if (canReachExitWithout(Succ, Target)) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
- };
|
|
|
- visitedWithoutCurrent.clear();
|
|
|
- return !canReachExitWithout(Entry, Exit);
|
|
|
- }
|
|
|
-
|
|
|
- void analyzeFunctionCriticalPoints(Module &M) {
|
|
|
- for (Function &F : M) {
|
|
|
- if (!F.isDeclaration()) {
|
|
|
- std::string fname = F.getName().str();
|
|
|
-
|
|
|
- for (BasicBlock &BB : F) {
|
|
|
- if (checkCriticalPoint(&BB)) {
|
|
|
- callGraph[fname].criticalPoints.insert(&BB);
|
|
|
- }
|
|
|
- }
|
|
|
- LOG_INFO("analyzeFunctionCriticalPoints",
|
|
|
- "Function {0} has {1} critical points",
|
|
|
- fname,
|
|
|
- callGraph[fname].criticalPoints.size());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- void buildCallGraph(Module &M) {
|
|
|
- LOG_INFO("buildCallGraph", "Building complete call graph");
|
|
|
- for (Function &F : M) {
|
|
|
- if (!F.isDeclaration()) {
|
|
|
- std::string fname = F.getName().str();
|
|
|
- bool isTarget = targetFunctions.find(fname) != targetFunctions.end();
|
|
|
- callGraph[fname] = CallNode(fname, isTarget);
|
|
|
- }
|
|
|
- }
|
|
|
- for (Function &F : M) {
|
|
|
- if (!F.isDeclaration()) {
|
|
|
- std::string callerName = F.getName().str();
|
|
|
- for (BasicBlock &BB : F) {
|
|
|
- for (Instruction &I : BB) {
|
|
|
- if (CallInst *CI = dyn_cast<CallInst>(&I)) {
|
|
|
- Function *CalledF = CI->getCalledFunction();
|
|
|
- if (CalledF && !CalledF->isDeclaration()) {
|
|
|
- std::string calleeName = CalledF->getName().str();
|
|
|
- callGraph[callerName].callees.insert(calleeName);
|
|
|
- callGraph[calleeName].callers.insert(callerName);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- void calculateCallDepths(Module &M) {
|
|
|
- LOG_INFO("calculateCallDepths", "Calculating call depths for all functions in module");
|
|
|
-
|
|
|
- maxCallDepths.clear();
|
|
|
-
|
|
|
- for (Function &F : M) {
|
|
|
- if (F.isDeclaration()) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- std::string startFunc = F.getName().str();
|
|
|
- std::map<std::string, unsigned> depths;
|
|
|
- std::queue<std::pair<std::string, unsigned>> queue;
|
|
|
- std::set<std::string> visited;
|
|
|
-
|
|
|
- queue.push(std::make_pair(startFunc, 0));
|
|
|
- visited.insert(startFunc);
|
|
|
-
|
|
|
- while (!queue.empty()) {
|
|
|
- std::string currentFunc = queue.front().first;
|
|
|
- unsigned depth = queue.front().second;
|
|
|
- queue.pop();
|
|
|
- depths[currentFunc] = depth;
|
|
|
- for (const std::string &caller : callGraph[currentFunc].callers) {
|
|
|
- if (visited.find(caller) == visited.end()) {
|
|
|
- queue.push(std::make_pair(caller, depth + 1));
|
|
|
- visited.insert(caller);
|
|
|
- }
|
|
|
- }
|
|
|
- for (const std::string &callee : callGraph[currentFunc].callees) {
|
|
|
- if (visited.find(callee) == visited.end()) {
|
|
|
- queue.push(std::make_pair(callee, depth + 1));
|
|
|
- visited.insert(callee);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for (const auto &pair : depths) {
|
|
|
- const std::string &func = pair.first;
|
|
|
- unsigned depth = pair.second;
|
|
|
- maxCallDepths[func] = std::max(maxCallDepths[func], depth);
|
|
|
- }
|
|
|
-
|
|
|
- LOG_DEBUG("calculateCallDepths",
|
|
|
- "Function {0}: processed {1} related functions, max depth {2}",
|
|
|
- startFunc,
|
|
|
- depths.size(),
|
|
|
- maxCallDepths[startFunc]);
|
|
|
- }
|
|
|
-
|
|
|
- unsigned maxDepth = 0;
|
|
|
- std::string deepestFunc;
|
|
|
- for (const auto &pair : maxCallDepths) {
|
|
|
- if (pair.second > maxDepth) {
|
|
|
- maxDepth = pair.second;
|
|
|
- deepestFunc = pair.first;
|
|
|
- }
|
|
|
- }
|
|
|
- LOG_INFO("calculateCallDepths",
|
|
|
- "Analysis complete - Total functions: {0}, Maximum depth: {1} (in function: {2})",
|
|
|
- maxCallDepths.size(),
|
|
|
- maxDepth,
|
|
|
- deepestFunc);
|
|
|
- }
|
|
|
-
|
|
|
- void generateProjectCallGraph() {
|
|
|
- errs() << "```mermaid\n";
|
|
|
- errs() << "graph TD\n";
|
|
|
- errs() << " %% Project Call Graph\n";
|
|
|
-
|
|
|
- for (const auto &pair : callGraph) {
|
|
|
- const std::string &name = pair.first;
|
|
|
- const CallNode &node = pair.second;
|
|
|
- std::string nodeId = sanitizeNodeId(name);
|
|
|
- std::string depth = std::to_string(maxCallDepths[name]);
|
|
|
- std::string criticalPoints = std::to_string(node.criticalPoints.size());
|
|
|
- std::string style = node.isTarget ? ":::target" : "";
|
|
|
- errs() << " " << nodeId << "[\"" << name
|
|
|
- << "\\nDepth: " << depth
|
|
|
- << "\\nCritical Points: " << criticalPoints
|
|
|
- << "\"]" << style << "\n";
|
|
|
- }
|
|
|
-
|
|
|
- for (const auto &pair : callGraph) {
|
|
|
- const std::string &name = pair.first;
|
|
|
- const CallNode &node = pair.second;
|
|
|
- std::string callerId = sanitizeNodeId(name);
|
|
|
- for (const auto &callee : node.callees) {
|
|
|
- std::string calleeId = sanitizeNodeId(callee);
|
|
|
- errs() << " " << callerId << " --> " << calleeId << "\n";
|
|
|
- }
|
|
|
- }
|
|
|
- errs() << " classDef target fill:#f96,stroke:#333,stroke-width:4px\n";
|
|
|
- errs() << "```\n\n";
|
|
|
- }
|
|
|
-
|
|
|
- std::string sanitizeNodeId(const std::string &name) {
|
|
|
- std::string id = name;
|
|
|
- // 移除前导 %
|
|
|
- if (!id.empty() && id[0] == '%') {
|
|
|
- id = id.substr(1);
|
|
|
- }
|
|
|
-
|
|
|
- // 替换非法字符
|
|
|
- std::replace(id.begin(), id.end(), '.', '_');
|
|
|
- std::replace(id.begin(), id.end(), ' ', '_');
|
|
|
- std::replace(id.begin(), id.end(), '-', '_');
|
|
|
- std::replace(id.begin(), id.end(), '%', '_');
|
|
|
-
|
|
|
- // 确保ID以字母开头
|
|
|
- if (!id.empty() && std::isdigit(id[0])) {
|
|
|
- id = "block_" + id;
|
|
|
- }
|
|
|
-
|
|
|
- return id;
|
|
|
- }
|
|
|
-
|
|
|
- // 创建融合函数类型
|
|
|
- FunctionType* createFusedFunctionType(Function* bunkerFunc, Function* targetFunc, LLVMContext& Context) {
|
|
|
- LOG_DEBUG("createFusedFunctionType",
|
|
|
- "Creating fused type for bunker={0}({1}) and target={2}({3})",
|
|
|
- bunkerFunc->getName().str(),
|
|
|
- getReadableTypeName(bunkerFunc->getReturnType()),
|
|
|
- targetFunc->getName().str(),
|
|
|
- getReadableTypeName(targetFunc->getReturnType()));
|
|
|
-
|
|
|
- std::vector<Type*> paramTypes;
|
|
|
-
|
|
|
- // 添加控制参数
|
|
|
- paramTypes.push_back(Type::getInt1Ty(Context));
|
|
|
-
|
|
|
- // 添加bunker函数参数
|
|
|
- for (const auto& arg : bunkerFunc->args()) {
|
|
|
- paramTypes.push_back(arg.getType());
|
|
|
- }
|
|
|
-
|
|
|
- // 添加target函数参数
|
|
|
- for (const auto& arg : targetFunc->args()) {
|
|
|
- paramTypes.push_back(arg.getType());
|
|
|
- }
|
|
|
-
|
|
|
- // 创建返回类型
|
|
|
- Type* returnType;
|
|
|
- if (bunkerFunc->getReturnType()->isVoidTy() && targetFunc->getReturnType()->isVoidTy()) {
|
|
|
- LOG_DEBUG("createFusedFunctionType", "Both functions return void, creating void return type");
|
|
|
- returnType = Type::getVoidTy(Context);
|
|
|
- } else if (bunkerFunc->getReturnType()->isVoidTy()) {
|
|
|
- LOG_DEBUG("createFusedFunctionType",
|
|
|
- "Bunker returns void, using target return type: {0}",
|
|
|
- getReadableTypeName(targetFunc->getReturnType()));
|
|
|
- returnType = targetFunc->getReturnType();
|
|
|
- } else if (targetFunc->getReturnType()->isVoidTy()) {
|
|
|
- LOG_DEBUG("createFusedFunctionType",
|
|
|
- "Target returns void, using bunker return type: {0}",
|
|
|
- getReadableTypeName(bunkerFunc->getReturnType()));
|
|
|
- returnType = bunkerFunc->getReturnType();
|
|
|
- } else {
|
|
|
- LOG_DEBUG("createFusedFunctionType", "Creating struct return type for non-void returns");
|
|
|
- std::vector<Type*> structTypes;
|
|
|
- structTypes.push_back(targetFunc->getReturnType());
|
|
|
- structTypes.push_back(bunkerFunc->getReturnType());
|
|
|
- returnType = StructType::create(Context, structTypes,
|
|
|
- "fused_return_" + bunkerFunc->getName().str() + "_" + targetFunc->getName().str());
|
|
|
- }
|
|
|
-
|
|
|
- LOG_DEBUG("createFusedFunctionType",
|
|
|
- "Created fused function type with return type: {0}",
|
|
|
- getReadableTypeName(returnType));
|
|
|
-
|
|
|
- return FunctionType::get(returnType, paramTypes, false);
|
|
|
- }
|
|
|
-
|
|
|
- // 更新调用点
|
|
|
- void updateCallSite(CallInst* CI, Function* fusedFunc, Function* origFunc, Function* otherFunc, bool isTarget) {
|
|
|
- // 记录原始调用指令
|
|
|
- std::string originalInstStr;
|
|
|
- raw_string_ostream originalOS(originalInstStr);
|
|
|
- CI->print(originalOS);
|
|
|
- LOG_DEBUG("updateCallSite", "Original call instruction:\n {0}", originalInstStr);
|
|
|
-
|
|
|
- IRBuilder<> Builder(CI);
|
|
|
- std::vector<Value*> Args;
|
|
|
-
|
|
|
- // 添加控制参数
|
|
|
- Args.push_back(ConstantInt::get(Type::getInt1Ty(CI->getContext()), isTarget));
|
|
|
-
|
|
|
- // 记录参数类型信息
|
|
|
- LOG_DEBUG("updateCallSite", "Adding {0} control parameter", isTarget ? "target" : "bunker");
|
|
|
-
|
|
|
- // 如果是target调用,先添加bunker的默认参数
|
|
|
- if (isTarget) {
|
|
|
- LOG_DEBUG("updateCallSite", "Adding default bunker parameters:");
|
|
|
- for (const auto& arg : otherFunc->args()) {
|
|
|
- Type* ArgType = arg.getType();
|
|
|
- LOG_DEBUG("updateCallSite", " Parameter type: {0}", getReadableTypeName(ArgType));
|
|
|
- if (ArgType->isPointerTy()) {
|
|
|
- Args.push_back(ConstantPointerNull::get(cast<PointerType>(ArgType)));
|
|
|
- } else if (ArgType->isIntegerTy()) {
|
|
|
- Args.push_back(ConstantInt::get(ArgType, 0));
|
|
|
- } else if (ArgType->isFloatingPointTy()) {
|
|
|
- Args.push_back(ConstantFP::get(ArgType, 0.0));
|
|
|
- } else {
|
|
|
- Args.push_back(UndefValue::get(ArgType));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 添加原始调用的参数
|
|
|
- LOG_DEBUG("updateCallSite", "Adding original call parameters:");
|
|
|
- for (unsigned i = 0; i < CI->getNumArgOperands(); ++i) {
|
|
|
- Value* ArgVal = CI->getArgOperand(i);
|
|
|
- LOG_DEBUG("updateCallSite", " Argument {0}: type={1}",
|
|
|
- i, getReadableTypeName(ArgVal->getType()));
|
|
|
- Args.push_back(ArgVal);
|
|
|
- }
|
|
|
-
|
|
|
- // 如果是bunker调用,后添加target的默认参数
|
|
|
- if (!isTarget) {
|
|
|
- LOG_DEBUG("updateCallSite", "Adding default target parameters:");
|
|
|
- for (const auto& arg : otherFunc->args()) {
|
|
|
- Type* ArgType = arg.getType();
|
|
|
- LOG_DEBUG("updateCallSite", " Parameter type: {0}", getReadableTypeName(ArgType));
|
|
|
- if (ArgType->isPointerTy()) {
|
|
|
- Args.push_back(ConstantPointerNull::get(cast<PointerType>(ArgType)));
|
|
|
- } else if (ArgType->isIntegerTy()) {
|
|
|
- Args.push_back(ConstantInt::get(ArgType, 0));
|
|
|
- } else if (ArgType->isFloatingPointTy()) {
|
|
|
- Args.push_back(ConstantFP::get(ArgType, 0.0));
|
|
|
- } else {
|
|
|
- Args.push_back(UndefValue::get(ArgType));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 创建新的调用指令
|
|
|
- CallInst* NewCI = Builder.CreateCall(fusedFunc, Args);
|
|
|
-
|
|
|
- // 记录新调用指令
|
|
|
- std::string newInstStr;
|
|
|
- raw_string_ostream newOS(newInstStr);
|
|
|
- NewCI->print(newOS);
|
|
|
- LOG_DEBUG("updateCallSite", "New call instruction:\n {0}", newInstStr);
|
|
|
-
|
|
|
- // 处理返回值
|
|
|
- if (!CI->getType()->isVoidTy()) {
|
|
|
- LOG_DEBUG("updateCallSite", "Processing non-void return value of type: {0}",
|
|
|
- getReadableTypeName(CI->getType()));
|
|
|
-
|
|
|
- Value* ExtractedValue = nullptr;
|
|
|
- if (StructType* STy = dyn_cast<StructType>(fusedFunc->getReturnType())) {
|
|
|
- LOG_DEBUG("updateCallSite", "Extracting value from struct return type");
|
|
|
-
|
|
|
- // 确保返回值是有效的结构体类型
|
|
|
- if (STy->getNumElements() != 2) {
|
|
|
- LOG_ERROR("updateCallSite", "Invalid fused function return type: expected 2 elements, got {0}",
|
|
|
- STy->getNumElements());
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 获取正确的索引和对应的类型
|
|
|
- unsigned idx = isTarget ? 0 : 1;
|
|
|
- Type* expectedType = STy->getElementType(idx);
|
|
|
-
|
|
|
- // 创建extractvalue指令
|
|
|
- ExtractedValue = Builder.CreateExtractValue(NewCI, {idx},
|
|
|
- "extracted_" + std::string(isTarget ? "target" : "bunker") + "_return");
|
|
|
-
|
|
|
- LOG_DEBUG("updateCallSite", "Extracted value type: {0}",
|
|
|
- getReadableTypeName(ExtractedValue->getType()));
|
|
|
-
|
|
|
- // 验证提取的值类型
|
|
|
- if (!ExtractedValue || ExtractedValue->getType() != expectedType) {
|
|
|
- LOG_ERROR("updateCallSite", "Extracted value type mismatch: expected {0}, got {1}",
|
|
|
- getReadableTypeName(expectedType),
|
|
|
- ExtractedValue ? getReadableTypeName(ExtractedValue->getType()) : "null");
|
|
|
- return;
|
|
|
- }
|
|
|
- } else {
|
|
|
- ExtractedValue = NewCI;
|
|
|
- LOG_DEBUG("updateCallSite", "Using direct return value");
|
|
|
- }
|
|
|
-
|
|
|
- // 类型转换
|
|
|
- if (ExtractedValue && ExtractedValue->getType() != CI->getType()) {
|
|
|
- LOG_DEBUG("updateCallSite", "Type conversion needed from {0} to {1}",
|
|
|
- getReadableTypeName(ExtractedValue->getType()),
|
|
|
- getReadableTypeName(CI->getType()));
|
|
|
-
|
|
|
- // 确保源类型和目标类型都是有效的
|
|
|
- if (!ExtractedValue->getType() || !CI->getType()) {
|
|
|
- LOG_ERROR("updateCallSite", "Invalid type for conversion");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (CI->getType()->isPointerTy() && ExtractedValue->getType()->isPointerTy()) {
|
|
|
- ExtractedValue = Builder.CreateBitCast(ExtractedValue, CI->getType(),
|
|
|
- "conv_ptr_" + std::string(isTarget ? "target" : "bunker"));
|
|
|
- } else if (CI->getType()->isIntegerTy() && ExtractedValue->getType()->isIntegerTy()) {
|
|
|
- ExtractedValue = Builder.CreateIntCast(ExtractedValue, CI->getType(), true,
|
|
|
- "conv_int_" + std::string(isTarget ? "target" : "bunker"));
|
|
|
- } else if (CI->getType()->isFloatingPointTy() && ExtractedValue->getType()->isFloatingPointTy()) {
|
|
|
- if (CI->getType()->isDoubleTy()) {
|
|
|
- ExtractedValue = Builder.CreateFPExt(ExtractedValue, CI->getType(),
|
|
|
- "conv_fp_ext_" + std::string(isTarget ? "target" : "bunker"));
|
|
|
- } else {
|
|
|
- ExtractedValue = Builder.CreateFPTrunc(ExtractedValue, CI->getType(),
|
|
|
- "conv_fp_trunc_" + std::string(isTarget ? "target" : "bunker"));
|
|
|
- }
|
|
|
- } else {
|
|
|
- LOG_ERROR("updateCallSite", "Unsupported type conversion");
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 验证最终的返回值
|
|
|
- if (!ExtractedValue || ExtractedValue->getType() != CI->getType()) {
|
|
|
- LOG_ERROR("updateCallSite", "Final value type mismatch: expected {0}, got {1}",
|
|
|
- getReadableTypeName(CI->getType()),
|
|
|
- ExtractedValue ? getReadableTypeName(ExtractedValue->getType()) : "null");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 替换原始调用的所有使用
|
|
|
- CI->replaceAllUsesWith(ExtractedValue);
|
|
|
- LOG_DEBUG("updateCallSite", "Successfully replaced all uses of original call");
|
|
|
- } else {
|
|
|
- LOG_DEBUG("updateCallSite", "Void return type, no value processing needed");
|
|
|
- }
|
|
|
-
|
|
|
- // 删除原始调用指令
|
|
|
- CI->eraseFromParent();
|
|
|
- LOG_INFO("updateCallSite", "Successfully updated call site from {0} to {1}",
|
|
|
- originalInstStr, newInstStr);
|
|
|
- }
|
|
|
-
|
|
|
- // 添加一个辅助函数来获取可读的类型名称
|
|
|
- std::string getReadableTypeName(Type* Ty) {
|
|
|
- if (!Ty) return "null";
|
|
|
-
|
|
|
- if (Ty->isVoidTy()) return "void";
|
|
|
- if (Ty->isIntegerTy()) return "i" + std::to_string(Ty->getIntegerBitWidth());
|
|
|
- if (Ty->isFloatingPointTy()) return Ty->isDoubleTy() ? "double" : "float";
|
|
|
- if (Ty->isPointerTy()) return getReadableTypeName(Ty->getPointerElementType()) + "*";
|
|
|
- if (Ty->isArrayTy()) return "array of " + getReadableTypeName(Ty->getArrayElementType());
|
|
|
- if (Ty->isStructTy()) {
|
|
|
- if (StructType* STy = dyn_cast<StructType>(Ty)) {
|
|
|
- return STy->hasName() ? STy->getName().str() : "anonymous struct";
|
|
|
- }
|
|
|
- return "struct";
|
|
|
- }
|
|
|
- if (Ty->isFunctionTy()) return "function";
|
|
|
-
|
|
|
- return "unknown";
|
|
|
- }
|
|
|
-
|
|
|
- void performCodeFusion(Module &M) {
|
|
|
- LOG_INFO("performCodeFusion", "Starting code fusion");
|
|
|
-
|
|
|
- for (const auto& fusion : fusionPairs) {
|
|
|
- const std::string& targetName = fusion.first;
|
|
|
- const std::string& bunkerName = fusion.second;
|
|
|
-
|
|
|
- Function* targetFunc = M.getFunction(targetName);
|
|
|
- Function* bunkerFunc = M.getFunction(bunkerName);
|
|
|
-
|
|
|
- if (!targetFunc || !bunkerFunc) {
|
|
|
- LOG_ERROR("performCodeFusion",
|
|
|
- "Cannot find functions: target={0}, bunker={1}",
|
|
|
- targetName, bunkerName);
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- LOG_INFO("performCodeFusion",
|
|
|
- "Processing function pair: target={0}, bunker={1}",
|
|
|
- targetName, bunkerName);
|
|
|
-
|
|
|
- // 创建融合函数类型
|
|
|
- FunctionType* fusedType = createFusedFunctionType(bunkerFunc, targetFunc, M.getContext());
|
|
|
- Function* fusedFunc = Function::Create(fusedType, bunkerFunc->getLinkage(),
|
|
|
- "fused_" + bunkerName, &M);
|
|
|
-
|
|
|
- // 创建入口基本块
|
|
|
- BasicBlock* entryBlock = BasicBlock::Create(M.getContext(), "entry", fusedFunc);
|
|
|
- if (!entryBlock) {
|
|
|
- LOG_ERROR("performCodeFusion", "Failed to create entry block");
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- IRBuilder<> Builder(entryBlock);
|
|
|
-
|
|
|
- // 获取控制参数(isTarget)
|
|
|
- Value* isTarget = fusedFunc->arg_begin();
|
|
|
-
|
|
|
- // 创建参数映射
|
|
|
- ValueToValueMapTy bunkerVMap, targetVMap;
|
|
|
- unsigned argIdx = 1; // 跳过isTarget参数
|
|
|
-
|
|
|
- // 映射bunker函数参数
|
|
|
- for (auto& arg : bunkerFunc->args()) {
|
|
|
- bunkerVMap[&arg] = fusedFunc->getArg(argIdx++);
|
|
|
- }
|
|
|
-
|
|
|
- // 映射target函数参数
|
|
|
- for (auto& arg : targetFunc->args()) {
|
|
|
- targetVMap[&arg] = fusedFunc->getArg(argIdx++);
|
|
|
- }
|
|
|
-
|
|
|
- // 获取target函数的分片
|
|
|
- const auto& targetSlices = callGraph[targetName].slices;
|
|
|
- size_t currentSliceIndex = 0;
|
|
|
-
|
|
|
- // 获取bunker函数的关键点集合
|
|
|
- const auto& criticalPoints = callGraph[bunkerName].criticalPoints;
|
|
|
-
|
|
|
- // 用于存储所有克隆的基本块
|
|
|
- std::map<BasicBlock*, BasicBlock*> bunkerBlockMap;
|
|
|
- std::map<BasicBlock*, BasicBlock*> targetBlockMap;
|
|
|
- std::map<BasicBlock*, BasicBlock*> reverseTargetBlockMap;
|
|
|
- std::map<BasicBlock*, BasicBlock*> reverseBunkerBlockMap;
|
|
|
- std::vector<BasicBlock*> allFusedBlocks;
|
|
|
-
|
|
|
- std::vector<SliceTransition> sliceTransitions;
|
|
|
- std::vector<SliceBlocks> targetSliceBlocksList;
|
|
|
- std::vector<SliceBlocks> bunkerSliceBlocksList;
|
|
|
-
|
|
|
- // 存储条件块的映射
|
|
|
- // std::map<BasicBlock*, BasicBlock*> condBlockMap;
|
|
|
-
|
|
|
- // bool hasOpenBunkerSlice = false;
|
|
|
-
|
|
|
- // // 遍历bunker函数的所有基本块
|
|
|
- // for (BasicBlock& BB : *bunkerFunc) {
|
|
|
- // // 如果当前基本块是关键点且还有未插入的target分片
|
|
|
- // if (currentSliceIndex < targetSlices.size() && criticalPoints.count(&BB)) {
|
|
|
- // // 处理未闭合的bunker条件分片
|
|
|
- // if (hasOpenBunkerSlice) {
|
|
|
- // // 创建phi块作为bunker条件分片的结束
|
|
|
- // BasicBlock* bunkerPhiBlock = BasicBlock::Create(M.getContext(),
|
|
|
- // "bunker_phi_" + std::to_string(currentSliceIndex), fusedFunc);
|
|
|
-
|
|
|
- // // 将当前bunker条件分片的skip块指向phi块
|
|
|
- // IRBuilder<> Builder(currentBunkerSkipBlock);
|
|
|
- // Builder.CreateBr(bunkerPhiBlock);
|
|
|
-
|
|
|
- // // 创建target分片的条件块
|
|
|
- // BasicBlock* targetCondBlock = BasicBlock::Create(M.getContext(),
|
|
|
- // "target_slice_cond_" + std::to_string(currentSliceIndex), fusedFunc);
|
|
|
-
|
|
|
- // // 将bunker的phi块指向target的条件块
|
|
|
- // IRBuilder<> PhiBuilder(bunkerPhiBlock);
|
|
|
- // PhiBuilder.CreateBr(targetCondBlock);
|
|
|
-
|
|
|
- // hasOpenBunkerSlice = false;
|
|
|
- // }else {
|
|
|
- // // 直接创建target分片的条件块
|
|
|
- // BasicBlock* targetCondBlock = BasicBlock::Create(M.getContext(),
|
|
|
- // "target_slice_cond_" + std::to_string(currentSliceIndex), fusedFunc);
|
|
|
-
|
|
|
- // // 如果这是第一个块,从入口块跳转到这里
|
|
|
- // if (allFusedBlocks.empty()) {
|
|
|
- // IRBuilder<> EntryBuilder(entryBlock);
|
|
|
- // EntryBuilder.CreateBr(targetCondBlock);
|
|
|
- // }
|
|
|
- // }
|
|
|
- // BasicBlock* targetSkipBlock = BasicBlock::Create(M.getContext(),
|
|
|
- // "target_slice_skip_" + std::to_string(currentSliceIndex), fusedFunc);
|
|
|
-
|
|
|
- // // 创建phi块用于合并控制流
|
|
|
- // BasicBlock* targetPhiBlock = BasicBlock::Create(M.getContext(),
|
|
|
- // "target_phi_" + std::to_string(currentSliceIndex), fusedFunc);
|
|
|
-
|
|
|
- // IRBuilder<> CondBuilder(targetCondBlock);
|
|
|
- // Value* shouldRunTarget = CondBuilder.CreateICmpEQ(isTarget,
|
|
|
- // ConstantInt::getTrue(Type::getInt1Ty(M.getContext())));
|
|
|
-
|
|
|
- // // 克隆并插入target分片的基本块
|
|
|
- // for (BasicBlock* targetBB : currentSlice.blocks) {
|
|
|
- // BasicBlock* clonedTargetBB = CloneBasicBlock(targetBB, targetVMap,
|
|
|
- // "target_" + targetBB->getName(), fusedFunc);
|
|
|
- // targetBlockMap[targetBB] = clonedTargetBB;
|
|
|
- // allFusedBlocks.push_back(clonedTargetBB);
|
|
|
- // }
|
|
|
-
|
|
|
- // // 设置条件跳转
|
|
|
- // CondBuilder.CreateCondBr(shouldRunTarget,
|
|
|
- // targetBlockMap[currentSlice.blocks.front()],
|
|
|
- // targetSkipBlock);
|
|
|
-
|
|
|
- // // 修改target分片最后一个块的跳转到phi块
|
|
|
- // BasicBlock* lastTargetBB = targetBlockMap[currentSlice.blocks.back()];
|
|
|
- // if (BranchInst* BI = dyn_cast<BranchInst>(lastTargetBB->getTerminator())) {
|
|
|
- // IRBuilder<> Builder(lastTargetBB);
|
|
|
- // Builder.CreateBr(targetPhiBlock);
|
|
|
- // BI->eraseFromParent();
|
|
|
- // }
|
|
|
-
|
|
|
- // // 从skip块跳转到phi块
|
|
|
- // IRBuilder<> SkipBuilder(targetSkipBlock);
|
|
|
- // SkipBuilder.CreateBr(targetPhiBlock);
|
|
|
-
|
|
|
- // // 创建新的bunker条件分片
|
|
|
- // currentBunkerCondBlock = BasicBlock::Create(M.getContext(),
|
|
|
- // "bunker_slice_cond_" + std::to_string(currentSliceIndex), fusedFunc);
|
|
|
- // currentBunkerSkipBlock = BasicBlock::Create(M.getContext(),
|
|
|
- // "bunker_slice_skip_" + std::to_string(currentSliceIndex), fusedFunc);
|
|
|
-
|
|
|
- // // 从phi块跳转到下一个bunker条件块
|
|
|
- // IRBuilder<> PhiBuilder(targetPhiBlock);
|
|
|
- // PhiBuilder.CreateBr(currentBunkerCondBlock);
|
|
|
-
|
|
|
- // // 设置bunker条件块的分支
|
|
|
- // IRBuilder<> BunkerCondBuilder(currentBunkerCondBlock);
|
|
|
- // Value* shouldRunBunker = BunkerCondBuilder.CreateICmpEQ(isTarget,
|
|
|
- // ConstantInt::getFalse(Type::getInt1Ty(M.getContext())));
|
|
|
- // BunkerCondBuilder.CreateCondBr(shouldRunBunker,
|
|
|
- // clonedBunkerBB,
|
|
|
- // currentBunkerSkipBlock);
|
|
|
-
|
|
|
- // hasOpenBunkerSlice = true;
|
|
|
- // currentSliceIndex++;
|
|
|
- // }
|
|
|
- // else{
|
|
|
- // // 克隆bunker基本块
|
|
|
- // BasicBlock* clonedBunkerBB = CloneBasicBlock(&BB, bunkerVMap,
|
|
|
- // "bunker_" + BB.getName(), fusedFunc);
|
|
|
- // bunkerBlockMap[&BB] = clonedBunkerBB;
|
|
|
- // allFusedBlocks.push_back(clonedBunkerBB);
|
|
|
- // }
|
|
|
- // }
|
|
|
- // // 处理最后一个未闭合的bunker条件分片
|
|
|
- // if (hasOpenBunkerSlice) {
|
|
|
- // BasicBlock* finalPhiBlock = BasicBlock::Create(M.getContext(),
|
|
|
- // "bunker_final_phi", fusedFunc);
|
|
|
- // IRBuilder<> Builder(currentBunkerSkipBlock);
|
|
|
- // Builder.CreateBr(finalPhiBlock);
|
|
|
- // }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // 遍历bunker函数的所有基本块
|
|
|
- BasicBlock* currentBunkerSliceStart = nullptr;
|
|
|
- std::vector<BasicBlock*> currentBunkerSlice;
|
|
|
- sliceTransitions.clear();
|
|
|
-
|
|
|
- // 在循环外声明phi块变量
|
|
|
- BasicBlock* currentBunkerPhiBlock = nullptr;
|
|
|
-
|
|
|
- for (BasicBlock& BB : *bunkerFunc) {
|
|
|
- // 如果当前基本块是关键点且还有未插入的target分片
|
|
|
- if (currentSliceIndex < targetSlices.size() && criticalPoints.count(&BB)) {
|
|
|
- // 记录分片转换信息
|
|
|
- SliceTransition transition;
|
|
|
-
|
|
|
- // 如果存在当前的bunker phi块,说明前一个bunker分片已完成
|
|
|
- if (currentBunkerPhiBlock) {
|
|
|
- transition.bunkerLastBlock = currentBunkerPhiBlock;
|
|
|
- // 为bunker分片的最后一个基本块添加到phi块的跳转
|
|
|
- if (!currentBunkerSlice.empty()) {
|
|
|
- BasicBlock* lastBunkerBlock = currentBunkerSlice.back();
|
|
|
- if (BranchInst* BI = dyn_cast<BranchInst>(lastBunkerBlock->getTerminator())) {
|
|
|
- BI->eraseFromParent();
|
|
|
- }
|
|
|
- IRBuilder<> Builder(lastBunkerBlock);
|
|
|
- Builder.CreateBr(currentBunkerPhiBlock);
|
|
|
- }
|
|
|
- // 将phi块添加到分片和allFusedBlocks中
|
|
|
- allFusedBlocks.push_back(currentBunkerPhiBlock);
|
|
|
- SliceBlocks currentBunkerSliceBlocks;
|
|
|
- currentBunkerSliceBlocks.blocks = currentBunkerSlice;
|
|
|
- currentBunkerSliceBlocks.phiBlock = currentBunkerPhiBlock;
|
|
|
- bunkerSliceBlocksList.push_back(currentBunkerSliceBlocks);
|
|
|
- }
|
|
|
-
|
|
|
- // 为target分片创建条件块、跳过块和合并块
|
|
|
- BasicBlock* targetCondBlock = BasicBlock::Create(M.getContext(),
|
|
|
- "target_cond_" + std::to_string(currentSliceIndex), fusedFunc);
|
|
|
- BasicBlock* targetSkipBlock = BasicBlock::Create(M.getContext(),
|
|
|
- "target_skip_" + std::to_string(currentSliceIndex), fusedFunc);
|
|
|
- BasicBlock* targetPhiBlock = BasicBlock::Create(M.getContext(),
|
|
|
- "target_phi_" + std::to_string(currentSliceIndex), fusedFunc);
|
|
|
-
|
|
|
- // bunker分片到target cond块的跳转
|
|
|
- if (currentBunkerPhiBlock) {
|
|
|
- IRBuilder<> bunkerPhiBuilder(currentBunkerPhiBlock);
|
|
|
- bunkerPhiBuilder.CreateBr(targetCondBlock);
|
|
|
- }
|
|
|
-
|
|
|
- // 将条件块加入到allFusedBlocks
|
|
|
- allFusedBlocks.push_back(targetCondBlock);
|
|
|
- allFusedBlocks.push_back(targetSkipBlock);
|
|
|
-
|
|
|
- // 在条件块中创建条件跳转
|
|
|
- IRBuilder<> targetCondBuilder(targetCondBlock);
|
|
|
- Value* shouldRunTarget = targetCondBuilder.CreateICmpEQ(isTarget,
|
|
|
- ConstantInt::getTrue(Type::getInt1Ty(M.getContext())));
|
|
|
-
|
|
|
- // 克隆并插入target分片的基本块
|
|
|
- std::vector<BasicBlock*> targetSliceBlocks;
|
|
|
- for (BasicBlock* targetBB : targetSlices[currentSliceIndex].blocks) {
|
|
|
- BasicBlock* clonedTargetBB = CloneBasicBlock(targetBB, targetVMap,
|
|
|
- "target_" + targetBB->getName(), fusedFunc);
|
|
|
- targetBlockMap[clonedTargetBB] = targetBB;
|
|
|
- reverseTargetBlockMap[targetBB] = clonedTargetBB;
|
|
|
- allFusedBlocks.push_back(clonedTargetBB);
|
|
|
- targetSliceBlocks.push_back(clonedTargetBB);
|
|
|
- LOG_INFO("performCodeFusion",
|
|
|
- "adding: {0}",
|
|
|
- getNodeId(clonedTargetBB));
|
|
|
- }
|
|
|
-
|
|
|
- // 为最后一个实际基本块添加到phi块的跳转
|
|
|
- if (!targetSliceBlocks.empty()) {
|
|
|
- BasicBlock* lastActualBlock = targetSliceBlocks.back();
|
|
|
- if (BranchInst* BI = dyn_cast<BranchInst>(lastActualBlock->getTerminator())) {
|
|
|
- BI->eraseFromParent();
|
|
|
- }
|
|
|
- IRBuilder<> Builder(lastActualBlock);
|
|
|
- Builder.CreateBr(targetPhiBlock);
|
|
|
- }
|
|
|
-
|
|
|
- // 添加phi块到末尾
|
|
|
- allFusedBlocks.push_back(targetPhiBlock);
|
|
|
-
|
|
|
- SliceBlocks currentTargetSlice;
|
|
|
- for (BasicBlock* clonedBB : targetSliceBlocks) {
|
|
|
- LOG_INFO("performCodeFusion",
|
|
|
- "before push Block ID: {0}",
|
|
|
- getNodeId(clonedBB));
|
|
|
- }
|
|
|
- currentTargetSlice.blocks = targetSliceBlocks;
|
|
|
- currentTargetSlice.phiBlock = targetPhiBlock;
|
|
|
- targetSliceBlocksList.push_back(currentTargetSlice);
|
|
|
-
|
|
|
- // 为bunker分片创建条件块、跳过块和合并块
|
|
|
- BasicBlock* bunkerCondBlock = BasicBlock::Create(M.getContext(),
|
|
|
- "bunker_cond_" + std::to_string(currentSliceIndex), fusedFunc);
|
|
|
- BasicBlock* bunkerSkipBlock = BasicBlock::Create(M.getContext(),
|
|
|
- "bunker_skip_" + std::to_string(currentSliceIndex), fusedFunc);
|
|
|
- BasicBlock* bunkerPhiBlock = BasicBlock::Create(M.getContext(),
|
|
|
- "bunker_phi_" + std::to_string(currentSliceIndex), fusedFunc);
|
|
|
- currentBunkerPhiBlock = bunkerPhiBlock;
|
|
|
-
|
|
|
- // 将条件块加入到allFusedBlocks
|
|
|
- allFusedBlocks.push_back(bunkerCondBlock);
|
|
|
- allFusedBlocks.push_back(bunkerSkipBlock);
|
|
|
-
|
|
|
- // 在条件块中创建条件跳转
|
|
|
- IRBuilder<> bunkerCondBuilder(bunkerCondBlock);
|
|
|
- Value* shouldRunBunker = bunkerCondBuilder.CreateICmpEQ(isTarget,
|
|
|
- ConstantInt::getFalse(Type::getInt1Ty(M.getContext())));
|
|
|
-
|
|
|
- // 克隆当前bunker基本块
|
|
|
- BasicBlock* clonedBunkerBB = CloneBasicBlock(&BB, bunkerVMap,
|
|
|
- "bunker_" + BB.getName(), fusedFunc);
|
|
|
- bunkerBlockMap[clonedBunkerBB] = &BB;
|
|
|
- reverseBunkerBlockMap[&BB] = clonedBunkerBB;
|
|
|
- allFusedBlocks.push_back(clonedBunkerBB);
|
|
|
-
|
|
|
- // 设置初始条件跳转
|
|
|
- targetCondBuilder.CreateCondBr(shouldRunTarget,
|
|
|
- targetSliceBlocks.front(), targetSkipBlock); // 跳转到第一个实际target块
|
|
|
-
|
|
|
- // 设置skip块到phi块的跳转
|
|
|
- IRBuilder<> targetSkipBuilder(targetSkipBlock);
|
|
|
- targetSkipBuilder.CreateBr(targetPhiBlock);
|
|
|
-
|
|
|
- // target分片到bunker cond块的跳转
|
|
|
- IRBuilder<> targetPhiBuilder(targetPhiBlock);
|
|
|
- targetPhiBuilder.CreateBr(bunkerCondBlock);
|
|
|
-
|
|
|
- // 设置bunker条件跳转
|
|
|
- bunkerCondBuilder.CreateCondBr(shouldRunBunker,
|
|
|
- clonedBunkerBB, bunkerSkipBlock);
|
|
|
-
|
|
|
- // 设置bunker skip块到phi块的跳转
|
|
|
- IRBuilder<> bunkerSkipBuilder(bunkerSkipBlock);
|
|
|
- bunkerSkipBuilder.CreateBr(bunkerPhiBlock);
|
|
|
-
|
|
|
- transition.targetFirstBlock = targetCondBlock;
|
|
|
- transition.targetLastBlock = targetPhiBlock;
|
|
|
- transition.nextBunkerBlock = bunkerCondBlock;
|
|
|
- sliceTransitions.push_back(transition);
|
|
|
-
|
|
|
- // 开始新的bunker分片
|
|
|
- currentBunkerSlice.clear();
|
|
|
- currentBunkerSlice.push_back(clonedBunkerBB);
|
|
|
-
|
|
|
-
|
|
|
- currentSliceIndex++;
|
|
|
- } else {
|
|
|
- // 克隆bunker基本块
|
|
|
- BasicBlock* clonedBunkerBB = CloneBasicBlock(&BB, bunkerVMap,
|
|
|
- "bunker_" + BB.getName(), fusedFunc);
|
|
|
- bunkerBlockMap[clonedBunkerBB] = &BB;
|
|
|
- reverseBunkerBlockMap[&BB] = clonedBunkerBB;
|
|
|
- allFusedBlocks.push_back(clonedBunkerBB);
|
|
|
- currentBunkerSlice.push_back(clonedBunkerBB);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 处理最后一个bunker分片
|
|
|
- if (currentBunkerPhiBlock) {
|
|
|
- sliceTransitions.back().bunkerLastBlock = currentBunkerPhiBlock;
|
|
|
- // 为最后一个bunker分片的最后一个基本块添加到phi块的跳转
|
|
|
- if (!currentBunkerSlice.empty()) {
|
|
|
- BasicBlock* lastBunkerBlock = currentBunkerSlice.back();
|
|
|
- if (BranchInst* BI = dyn_cast<BranchInst>(lastBunkerBlock->getTerminator())) {
|
|
|
- BI->eraseFromParent();
|
|
|
- }
|
|
|
- IRBuilder<> Builder(lastBunkerBlock);
|
|
|
- Builder.CreateBr(currentBunkerPhiBlock);
|
|
|
- }
|
|
|
- // 将最后的phi块添加到分片和allFusedBlocks中
|
|
|
- allFusedBlocks.push_back(currentBunkerPhiBlock);
|
|
|
- SliceBlocks currentBunkerSliceBlocks;
|
|
|
- currentBunkerSliceBlocks.blocks = currentBunkerSlice;
|
|
|
- currentBunkerSliceBlocks.phiBlock = currentBunkerPhiBlock;
|
|
|
- bunkerSliceBlocksList.push_back(currentBunkerSliceBlocks);
|
|
|
- // 为最后一个phi块添加返回指令
|
|
|
- IRBuilder<> PhiBuilder(currentBunkerPhiBlock);
|
|
|
- if (fusedFunc->getReturnType()->isVoidTy()) {
|
|
|
- PhiBuilder.CreateRetVoid();
|
|
|
- } else {
|
|
|
- // 创建默认返回值
|
|
|
- Value* defaultRetVal;
|
|
|
- Type* returnType = fusedFunc->getReturnType();
|
|
|
-
|
|
|
- if (StructType* STy = dyn_cast<StructType>(returnType)) {
|
|
|
- // 如果是结构体返回类型,创建一个零初始化的结构体
|
|
|
- defaultRetVal = ConstantAggregateZero::get(STy);
|
|
|
- } else if (returnType->isPointerTy()) {
|
|
|
- defaultRetVal = ConstantPointerNull::get(cast<PointerType>(returnType));
|
|
|
- } else if (returnType->isIntegerTy()) {
|
|
|
- defaultRetVal = ConstantInt::get(returnType, 0);
|
|
|
- } else if (returnType->isFloatingPointTy()) {
|
|
|
- defaultRetVal = ConstantFP::get(returnType, 0.0);
|
|
|
- } else {
|
|
|
- defaultRetVal = UndefValue::get(returnType);
|
|
|
- }
|
|
|
-
|
|
|
- PhiBuilder.CreateRet(defaultRetVal);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // // 添加新的日志打印代码
|
|
|
- // if (fusedFunc->getName() == "fused_createDynamicArray") {
|
|
|
- // LOG_INFO("performCodeFusion", "Listing all instructions after block cloning in function: {0}",
|
|
|
- // fusedFunc->getName().str());
|
|
|
- // dumpControlFlowGraph(*fusedFunc);
|
|
|
- // }
|
|
|
-
|
|
|
- // // 在检查映射前添加调试信息
|
|
|
- // LOG_INFO("performCodeFusion", "Dumping reverseBunkerBlockMap contents:");
|
|
|
- // for (const auto& pair : reverseBunkerBlockMap) {
|
|
|
- // LOG_INFO("performCodeFusion",
|
|
|
- // "Map entry: cloned={0} -> original={1}",
|
|
|
- // getNodeId(pair.first),
|
|
|
- // getNodeId(pair.second));
|
|
|
- // }
|
|
|
-
|
|
|
- // // 在检查映射前添加调试信息
|
|
|
- // LOG_INFO("performCodeFusion", "Dumping BunkerBlockMap contents:");
|
|
|
- // for (const auto& pair : bunkerBlockMap) {
|
|
|
- // LOG_INFO("performCodeFusion",
|
|
|
- // "Map entry: original={0} -> cloned={1}",
|
|
|
- // getNodeId(pair.first),
|
|
|
- // getNodeId(pair.second));
|
|
|
- // }
|
|
|
-
|
|
|
- // // 输出所有bunkerSliceBlocksList中的块的id
|
|
|
- // LOG_INFO("performCodeFusion", "bunkerSliceBlocksList size: {0}", bunkerSliceBlocksList.size());
|
|
|
- // LOG_INFO("performCodeFusion", "Dumping bunkerSliceBlocksList contents:");
|
|
|
- // for (const auto& sliceBlocks : bunkerSliceBlocksList) {
|
|
|
- // for (BasicBlock* clonedBB : sliceBlocks.blocks) {
|
|
|
- // LOG_INFO("performCodeFusion",
|
|
|
- // "Block ID: {0}",
|
|
|
- // getNodeId(clonedBB));
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- // // 在检查映射前添加调试信息
|
|
|
- // LOG_INFO("performCodeFusion", "Dumping reverseTargetBlockMap contents:");
|
|
|
- // for (const auto& pair : reverseTargetBlockMap) {
|
|
|
- // LOG_INFO("performCodeFusion",
|
|
|
- // "Map entry: cloned={0} -> original={1}",
|
|
|
- // getNodeId(pair.first),
|
|
|
- // getNodeId(pair.second));
|
|
|
- // }
|
|
|
-
|
|
|
- // // 在检查映射前添加调试信息
|
|
|
- // LOG_INFO("performCodeFusion", "Dumping TargetBlockMap contents:");
|
|
|
- // for (const auto& pair : targetBlockMap) {
|
|
|
- // LOG_INFO("performCodeFusion",
|
|
|
- // "Map entry: original={0} -> cloned={1}",
|
|
|
- // getNodeId(pair.first),
|
|
|
- // getNodeId(pair.second));
|
|
|
- // }
|
|
|
-
|
|
|
- // // 输出所有targetSliceBlocksList中的块的id
|
|
|
- // LOG_INFO("performCodeFusion", "targetSliceBlocksList size: {0}", targetSliceBlocksList.size());
|
|
|
- // LOG_INFO("performCodeFusion", "Dumping targetSliceBlocksList contents:");
|
|
|
- // for (const auto& sliceBlocks : targetSliceBlocksList) {
|
|
|
- // for (BasicBlock* clonedBB : sliceBlocks.blocks) {
|
|
|
- // LOG_INFO("performCodeFusion",
|
|
|
- // "Block ID: {0}",
|
|
|
- // getNodeId(clonedBB));
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- // 修复target分片内的跳转
|
|
|
- for (const auto& sliceBlocks : targetSliceBlocksList) {
|
|
|
- for (BasicBlock* clonedBB : sliceBlocks.blocks) {
|
|
|
- // 修复所有非终结指令
|
|
|
- for (Instruction &I : make_range(clonedBB->begin(), --clonedBB->end())) {
|
|
|
- RemapInstruction(&I, targetVMap, RF_NoModuleLevelChanges);
|
|
|
-
|
|
|
- if (PHINode* PHI = dyn_cast<PHINode>(&I)) {
|
|
|
- for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
|
|
|
- BasicBlock* incomingBlock = PHI->getIncomingBlock(i);
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Processing PHI incoming block {0} in block {1}",
|
|
|
- getNodeId(incomingBlock),
|
|
|
- getNodeId(clonedBB));
|
|
|
- if (reverseTargetBlockMap.count(incomingBlock)) {
|
|
|
- BasicBlock* mappedBlock = reverseTargetBlockMap[incomingBlock];
|
|
|
- PHI->setIncomingBlock(i, mappedBlock);
|
|
|
- }
|
|
|
- else{
|
|
|
- LOG_WARNING("performCodeFusion",
|
|
|
- "Incoming block {0} not found in reverseTargetBlockMap",
|
|
|
- getNodeId(incomingBlock));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 处理终结指令
|
|
|
- if (BranchInst* BI = dyn_cast<BranchInst>(clonedBB->getTerminator())) {
|
|
|
- // 检查是否是条件分支
|
|
|
- if (BI->isConditional()) {
|
|
|
- // 获取并映射条件值
|
|
|
- Value* originalCond = BI->getCondition();
|
|
|
- Value* mappedCond = MapValue(originalCond, targetVMap);
|
|
|
-
|
|
|
- if (mappedCond) {
|
|
|
- if (mappedCond->getType()->isIntegerTy(1)) {
|
|
|
- // 更新条件值
|
|
|
- BI->setCondition(mappedCond);
|
|
|
- } else {
|
|
|
- LOG_ERROR("performCodeFusion",
|
|
|
- "Invalid condition type in block {0}: expected i1, got {1}",
|
|
|
- getNodeId(clonedBB),
|
|
|
- getReadableTypeName(mappedCond->getType()));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 检查是否是分片的最后一个基本块
|
|
|
- bool isLastInSlice = (clonedBB == sliceBlocks.blocks.back());
|
|
|
-
|
|
|
- if (!isLastInSlice) {
|
|
|
- // 获取当前克隆块对应的原始块
|
|
|
- BasicBlock* originalBB = targetBlockMap[clonedBB];
|
|
|
- if (!originalBB) {
|
|
|
- LOG_ERROR("performCodeFusion",
|
|
|
- "Could not find original block for cloned block {0}",
|
|
|
- getNodeId(clonedBB));
|
|
|
- continue;
|
|
|
- }
|
|
|
- // 获取原始块的终结指令
|
|
|
- BranchInst* originalBI = dyn_cast<BranchInst>(originalBB->getTerminator());
|
|
|
- if (!originalBI) {
|
|
|
- LOG_ERROR("performCodeFusion",
|
|
|
- "Could not find branch instruction in original block {0}",
|
|
|
- getNodeId(originalBB));
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- // 修复克隆块的后继块
|
|
|
- for (unsigned i = 0; i < originalBI->getNumSuccessors(); i++) {
|
|
|
- BasicBlock* originalSucc = originalBI->getSuccessor(i);
|
|
|
- if (!originalSucc) {
|
|
|
- LOG_WARNING("performCodeFusion",
|
|
|
- "Null successor found at index {0} in original block {1}",
|
|
|
- i,
|
|
|
- getNodeId(originalBB));
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- // 在reverseTargetBlockMap中查找对应的克隆后继块
|
|
|
- if (reverseTargetBlockMap.count(originalSucc)) {
|
|
|
- BasicBlock* mappedSucc = reverseTargetBlockMap[originalSucc];
|
|
|
- if (mappedSucc) {
|
|
|
- // LOG_DEBUG("performCodeFusion",
|
|
|
- // "Remapping successor for block {0}: {1} -> {2}",
|
|
|
- // getNodeId(clonedBB),
|
|
|
- // getNodeId(originalSucc),
|
|
|
- // getNodeId(mappedSucc));
|
|
|
- BI->setSuccessor(i, mappedSucc);
|
|
|
- } else {
|
|
|
- LOG_WARNING("performCodeFusion",
|
|
|
- "Mapped successor is null for original block {0}",
|
|
|
- getNodeId(originalSucc));
|
|
|
- }
|
|
|
- } else {
|
|
|
- LOG_WARNING("performCodeFusion",
|
|
|
- "Could not find mapping for original successor block {0}",
|
|
|
- getNodeId(originalSucc));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // // 正常修复跳转目标
|
|
|
- // for (unsigned i = 0; i < BI->getNumSuccessors(); i++) {
|
|
|
- // BasicBlock* succ = BI->getSuccessor(i);
|
|
|
- // if (reverseTargetBlockMap.count(succ)) {
|
|
|
- // // 获取原始基本块
|
|
|
- // BasicBlock* originalSucc = reverseTargetBlockMap[succ];
|
|
|
- // if (targetBlockMap.count(originalSucc)) {
|
|
|
- // errs() << "2331: \n";
|
|
|
- // auto it = targetBlockMap.find(originalSucc);
|
|
|
- // if (it != targetBlockMap.end()) {
|
|
|
- // errs() << "2332: \n";
|
|
|
- // BasicBlock* mappedSucc = it->second;
|
|
|
- // LOG_DEBUG("performCodeFusion",
|
|
|
- // "Remapping successor {0} to {1}",
|
|
|
- // getNodeId(succ),
|
|
|
- // getNodeId(mappedSucc));
|
|
|
- // BI->setSuccessor(i, mappedSucc);
|
|
|
- // }
|
|
|
- // }
|
|
|
- // } else {
|
|
|
- // LOG_WARNING("performCodeFusion",
|
|
|
- // "Could not find mapping for successor block {0}",
|
|
|
- // getNodeId(succ));
|
|
|
- // }
|
|
|
- // }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 修复bunker块内的跳转
|
|
|
- for (const auto& sliceBlocks : bunkerSliceBlocksList) {
|
|
|
- for (BasicBlock* clonedBB : sliceBlocks.blocks) {
|
|
|
- // 修复所有非终结指令
|
|
|
- for (Instruction &I : make_range(clonedBB->begin(), --clonedBB->end())) {
|
|
|
- RemapInstruction(&I, bunkerVMap, RF_NoModuleLevelChanges);
|
|
|
-
|
|
|
- if (PHINode* PHI = dyn_cast<PHINode>(&I)) {
|
|
|
- for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
|
|
|
- BasicBlock* incomingBlock = PHI->getIncomingBlock(i);
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Processing PHI incoming block {0} in block {1}",
|
|
|
- getNodeId(incomingBlock),
|
|
|
- getNodeId(clonedBB));
|
|
|
- if (reverseBunkerBlockMap.count(incomingBlock)) {
|
|
|
- BasicBlock* mappedBlock = reverseBunkerBlockMap[incomingBlock];
|
|
|
- PHI->setIncomingBlock(i, mappedBlock);
|
|
|
- }
|
|
|
- else{
|
|
|
- LOG_WARNING("performCodeFusion",
|
|
|
- "Incoming block {0} not found in reverseTargetBlockMap",
|
|
|
- getNodeId(incomingBlock));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 处理终结指令
|
|
|
- if (BranchInst* BI = dyn_cast<BranchInst>(clonedBB->getTerminator())) {
|
|
|
- // 检查是否是条件分支
|
|
|
- if (BI->isConditional()) {
|
|
|
- // 获取并映射条件值
|
|
|
- Value* originalCond = BI->getCondition();
|
|
|
- Value* mappedCond = MapValue(originalCond, bunkerVMap);
|
|
|
-
|
|
|
- if (mappedCond) {
|
|
|
- if (mappedCond->getType()->isIntegerTy(1)) {
|
|
|
- // 更新条件值
|
|
|
- BI->setCondition(mappedCond);
|
|
|
- } else {
|
|
|
- LOG_ERROR("performCodeFusion",
|
|
|
- "Invalid condition type in block {0}: expected i1, got {1}",
|
|
|
- getNodeId(clonedBB),
|
|
|
- getReadableTypeName(mappedCond->getType()));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 检查是否是分片的最后一个基本块
|
|
|
- bool isLastInSlice = (clonedBB == sliceBlocks.blocks.back());
|
|
|
-
|
|
|
- if (!isLastInSlice) {
|
|
|
- // 获取当前克隆块对应的原始块
|
|
|
- BasicBlock* originalBB = bunkerBlockMap[clonedBB];
|
|
|
- if (!originalBB) {
|
|
|
- LOG_ERROR("performCodeFusion",
|
|
|
- "Could not find original block for cloned block {0}",
|
|
|
- getNodeId(clonedBB));
|
|
|
- continue;
|
|
|
- }
|
|
|
- // 获取原始块的终结指令
|
|
|
- BranchInst* originalBI = dyn_cast<BranchInst>(originalBB->getTerminator());
|
|
|
- if (!originalBI) {
|
|
|
- LOG_ERROR("performCodeFusion",
|
|
|
- "Could not find branch instruction in original block {0}",
|
|
|
- getNodeId(originalBB));
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- // 修复克隆块的后继块
|
|
|
- for (unsigned i = 0; i < originalBI->getNumSuccessors(); i++) {
|
|
|
- BasicBlock* originalSucc = originalBI->getSuccessor(i);
|
|
|
- if (!originalSucc) {
|
|
|
- LOG_WARNING("performCodeFusion",
|
|
|
- "Null successor found at index {0} in original block {1}",
|
|
|
- i,
|
|
|
- getNodeId(originalBB));
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- // 在reverseBunkerBlockMap中查找对应的克隆后继块
|
|
|
- if (reverseBunkerBlockMap.count(originalSucc)) {
|
|
|
- BasicBlock* mappedSucc = reverseBunkerBlockMap[originalSucc];
|
|
|
- if (mappedSucc) {
|
|
|
- // LOG_DEBUG("performCodeFusion",
|
|
|
- // "Remapping successor for block {0}: {1} -> {2}",
|
|
|
- // getNodeId(clonedBB),
|
|
|
- // getNodeId(originalSucc),
|
|
|
- // getNodeId(mappedSucc));
|
|
|
- BI->setSuccessor(i, mappedSucc);
|
|
|
- } else {
|
|
|
- LOG_WARNING("performCodeFusion",
|
|
|
- "Mapped successor is null for original block {0}",
|
|
|
- getNodeId(originalSucc));
|
|
|
- }
|
|
|
- } else {
|
|
|
- LOG_WARNING("performCodeFusion",
|
|
|
- "Could not find mapping for original successor block {0}",
|
|
|
- getNodeId(originalSucc));
|
|
|
- }
|
|
|
- }
|
|
|
- // // 正常修复跳转目标
|
|
|
- // for (unsigned i = 0; i < BI->getNumSuccessors(); i++) {
|
|
|
- // BasicBlock* succ = BI->getSuccessor(i);
|
|
|
- // if (reverseBunkerBlockMap.count(succ)) {
|
|
|
- // // 获取原始基本块
|
|
|
- // BasicBlock* originalSucc = reverseBunkerBlockMap[succ];
|
|
|
- // errs() << "2331: \n";
|
|
|
- // if (bunkerBlockMap.count(originalSucc)) {
|
|
|
- // errs() << "2332: \n";
|
|
|
- // auto it = bunkerBlockMap.find(originalSucc);
|
|
|
- // if (it != bunkerBlockMap.end()) {
|
|
|
- // BasicBlock* mappedSucc = it->second;
|
|
|
- // LOG_DEBUG("performCodeFusion",
|
|
|
- // "Remapping successor {0} to {1}",
|
|
|
- // getNodeId(succ),
|
|
|
- // getNodeId(mappedSucc));
|
|
|
- // BI->setSuccessor(i, mappedSucc);
|
|
|
- // }
|
|
|
- // }
|
|
|
- // } else {
|
|
|
- // LOG_WARNING("performCodeFusion",
|
|
|
- // "Could not find mapping for bunker successor block {0}",
|
|
|
- // getNodeId(succ));
|
|
|
- // }
|
|
|
- // }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 从入口块创建跳转到第一个块
|
|
|
- Builder.CreateBr(allFusedBlocks.front());
|
|
|
-
|
|
|
- // 添加新的日志打印代码
|
|
|
- LOG_INFO("performCodeFusion", "Listing all instructions after block cloning in function: {0}",
|
|
|
- fusedFunc->getName().str());
|
|
|
- dumpControlFlowGraph(*fusedFunc);
|
|
|
-
|
|
|
- // 在处理返回值之前添加日志
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Processing return values for fused function: {0}",
|
|
|
- fusedFunc->getName().str());
|
|
|
-
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Fused function return type: {0}",
|
|
|
- getReadableTypeName(fusedFunc->getReturnType()));
|
|
|
-
|
|
|
- // 处理返回值
|
|
|
- if (!fusedFunc->getReturnType()->isVoidTy()) {
|
|
|
- Type* returnType = fusedFunc->getReturnType();
|
|
|
-
|
|
|
- if (StructType* STy = dyn_cast<StructType>(returnType)) {
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Processing struct return type with {0} elements",
|
|
|
- STy->getNumElements());
|
|
|
-
|
|
|
- // 处理 bunker 函数的返回指令
|
|
|
- for (auto& pair : bunkerBlockMap) {
|
|
|
- BasicBlock* BB = pair.first;
|
|
|
- if (!BB || BB->empty()) continue;
|
|
|
-
|
|
|
- std::vector<Instruction*> toDelete; // 存储需要删除的指令
|
|
|
- bool foundReturn = false;
|
|
|
-
|
|
|
- for (BasicBlock::iterator I = BB->begin(); I != BB->end();) {
|
|
|
- Instruction* Inst = &*I;
|
|
|
- ++I;
|
|
|
- if (ReturnInst* RI = dyn_cast<ReturnInst>(Inst)){
|
|
|
- // 添加额外的安全检查
|
|
|
- if (!RI->getParent()) continue;
|
|
|
- foundReturn = true;
|
|
|
- IRBuilder<> Builder(RI);
|
|
|
- Value* bunkerRetVal = RI->getReturnValue();
|
|
|
-
|
|
|
- // 创建结构体实例并正确初始化
|
|
|
- Value* structVal = UndefValue::get(STy);
|
|
|
- Type* targetType = STy->getElementType(0);
|
|
|
- Type* bunkerType = STy->getElementType(1);
|
|
|
-
|
|
|
- // 设置target返回值位置为默认值
|
|
|
- LOG_DEBUG("performCodeFusion", "Setting default target return value");
|
|
|
- Value* defaultTargetVal;
|
|
|
- if (targetType->isPointerTy()) {
|
|
|
- defaultTargetVal = ConstantPointerNull::get(cast<PointerType>(targetType));
|
|
|
- } else if (targetType->isIntegerTy()) {
|
|
|
- defaultTargetVal = ConstantInt::get(targetType, 0);
|
|
|
- } else if (targetType->isFloatingPointTy()) {
|
|
|
- defaultTargetVal = ConstantFP::get(targetType, 0.0);
|
|
|
- } else {
|
|
|
- defaultTargetVal = Constant::getNullValue(targetType);
|
|
|
- }
|
|
|
-
|
|
|
- // Value* mappedBunkerRetVal = MapValue(bunkerRetVal, bunkerVMap);
|
|
|
- structVal = Builder.CreateInsertValue(structVal, defaultTargetVal, 0, "struct.target");
|
|
|
- structVal = Builder.CreateInsertValue(structVal, bunkerRetVal, 1, "struct.bunker");
|
|
|
- ReturnInst* NewRI = ReturnInst::Create(M.getContext(), structVal, RI);
|
|
|
- ReplaceInstWithInst(RI, NewRI);
|
|
|
-
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Created struct return for bunker block: {0} with types: target={1}, bunker={2}",
|
|
|
- getNodeId(BB),
|
|
|
- getReadableTypeName(targetType),
|
|
|
- getReadableTypeName(bunkerType));
|
|
|
- }else if (foundReturn) {
|
|
|
- // 将返回指令之后的所有指令标记为待删除
|
|
|
- toDelete.push_back(Inst);
|
|
|
- }
|
|
|
- }
|
|
|
- for (Instruction* I : toDelete) {
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Removing extra instruction after return in block {0}: {1}",
|
|
|
- getNodeId(BB),
|
|
|
- I->getOpcodeName());
|
|
|
- I->eraseFromParent();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 处理 target 函数的返回指令
|
|
|
- for (auto& pair : targetBlockMap) {
|
|
|
- BasicBlock* BB = pair.first;
|
|
|
- if (!BB || BB->empty()) continue;
|
|
|
-
|
|
|
- std::vector<Instruction*> toDelete; // 存储需要删除的指令
|
|
|
- bool foundReturn = false;
|
|
|
-
|
|
|
- for (BasicBlock::iterator I = BB->begin(); I != BB->end();) {
|
|
|
- Instruction* Inst = &*I;
|
|
|
- ++I;
|
|
|
- if (ReturnInst* RI = dyn_cast<ReturnInst>(Inst)){
|
|
|
- // 添加额外的安全检查
|
|
|
- if (!RI->getParent()) continue;
|
|
|
- foundReturn = true;
|
|
|
- IRBuilder<> Builder(RI);
|
|
|
- Value* targetRetVal = RI->getReturnValue();
|
|
|
-
|
|
|
- // 创建结构体实例并正确初始化
|
|
|
- Value* structVal = ConstantAggregateZero::get(STy);
|
|
|
- Type* targetType = STy->getElementType(0);
|
|
|
- Type* bunkerType = STy->getElementType(1);
|
|
|
-
|
|
|
- // 设置bunker返回值位置为默认值
|
|
|
- Value* defaultBunkerVal;
|
|
|
- if (bunkerType->isPointerTy()) {
|
|
|
- defaultBunkerVal = ConstantPointerNull::get(cast<PointerType>(bunkerType));
|
|
|
- } else if (bunkerType->isIntegerTy()) {
|
|
|
- defaultBunkerVal = ConstantInt::get(bunkerType, 0);
|
|
|
- } else if (bunkerType->isFloatingPointTy()) {
|
|
|
- defaultBunkerVal = ConstantFP::get(bunkerType, 0.0);
|
|
|
- } else {
|
|
|
- defaultBunkerVal = Constant::getNullValue(bunkerType);
|
|
|
- }
|
|
|
-
|
|
|
- // Value* mappedTargetRetVal = MapValue(targetRetVal, targetVMap);
|
|
|
-
|
|
|
- structVal = Builder.CreateInsertValue(structVal, targetRetVal, 0, "struct.target");
|
|
|
- structVal = Builder.CreateInsertValue(structVal, defaultBunkerVal, 1, "struct.bunker");
|
|
|
- ReturnInst* NewRI = ReturnInst::Create(M.getContext(), structVal, RI);
|
|
|
- ReplaceInstWithInst(RI, NewRI);
|
|
|
-
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Created struct return for target block: {0} with types: target={1}, bunker={2}",
|
|
|
- getNodeId(BB),
|
|
|
- getReadableTypeName(targetType),
|
|
|
- getReadableTypeName(bunkerType));
|
|
|
- }else if (foundReturn) {
|
|
|
- // 将返回指令之后的所有指令标记为待删除
|
|
|
- toDelete.push_back(Inst);
|
|
|
- }
|
|
|
- }
|
|
|
- for (Instruction* I : toDelete) {
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Removing extra instruction after return in block {0}: {1}",
|
|
|
- getNodeId(BB),
|
|
|
- I->getOpcodeName());
|
|
|
- I->eraseFromParent();
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 处理非结构体返回值的情况
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Non-struct return type detected: {0}",
|
|
|
- getReadableTypeName(returnType));
|
|
|
-
|
|
|
- // 处理 bunker 函数的返回指令
|
|
|
- for (auto& pair : bunkerBlockMap) {
|
|
|
- BasicBlock* BB = pair.first;
|
|
|
-
|
|
|
- LOG_DEBUG("performCodeFusion", "Processing bunker block: {0}", getNodeId(BB));
|
|
|
-
|
|
|
- if (!BB || BB->empty()) continue;
|
|
|
-
|
|
|
- std::vector<Instruction*> toDelete; // 存储需要删除的指令
|
|
|
- bool foundReturn = false;
|
|
|
-
|
|
|
- for (BasicBlock::iterator I = BB->begin(); I != BB->end();) {
|
|
|
- Instruction* Inst = &*I;
|
|
|
- ++I;
|
|
|
-
|
|
|
- // 打印每条指令的信息
|
|
|
- std::string instStr;
|
|
|
- raw_string_ostream rso(instStr);
|
|
|
- Inst->print(rso);
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Block {0} - Processing instruction: {1} (opcode: {2})",
|
|
|
- getNodeId(BB),
|
|
|
- instStr,
|
|
|
- Inst->getOpcodeName());
|
|
|
-
|
|
|
- if (ReturnInst* RI = dyn_cast<ReturnInst>(Inst)){
|
|
|
- // 添加额外的安全检查
|
|
|
- if (!RI->getParent()) continue;
|
|
|
- foundReturn = true;
|
|
|
- IRBuilder<> Builder(RI);
|
|
|
- Value* bunkerRetVal = RI->getReturnValue();
|
|
|
- // 先重映射返回值
|
|
|
- // if (bunkerRetVal) {
|
|
|
- // LOG_DEBUG("performCodeFusion", "Mapping bunker return value");
|
|
|
- // bunkerRetVal = MapValue(bunkerRetVal, bunkerVMap);
|
|
|
- // }
|
|
|
-
|
|
|
- if (!bunkerRetVal) {
|
|
|
- LOG_DEBUG("performCodeFusion", "Setting default bunker return value");
|
|
|
- if (returnType->isIntegerTy()) {
|
|
|
- bunkerRetVal = ConstantInt::get(returnType, 0);
|
|
|
- } else if (returnType->isPointerTy()) {
|
|
|
- bunkerRetVal = ConstantPointerNull::get(cast<PointerType>(returnType));
|
|
|
- } else if (returnType->isFloatingPointTy()) {
|
|
|
- bunkerRetVal = ConstantFP::get(returnType, 0.0);
|
|
|
- } else {
|
|
|
- bunkerRetVal = UndefValue::get(returnType);
|
|
|
- }
|
|
|
- } else if (bunkerRetVal->getType() != returnType) {
|
|
|
- LOG_DEBUG("performCodeFusion", "Casting bunker return value to {0}", getReadableTypeName(returnType));
|
|
|
- bunkerRetVal = Builder.CreateBitCast(bunkerRetVal, returnType);
|
|
|
- }
|
|
|
-
|
|
|
- ReturnInst* NewRI = ReturnInst::Create(M.getContext(), bunkerRetVal);
|
|
|
- ReplaceInstWithInst(RI, NewRI);
|
|
|
-
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Updated bunker return in block {0} with value type {1}",
|
|
|
- getNodeId(BB),
|
|
|
- getReadableTypeName(bunkerRetVal->getType()));
|
|
|
- }else if (foundReturn) {
|
|
|
- // 将返回指令之后的所有指令标记为待删除
|
|
|
- toDelete.push_back(Inst);
|
|
|
- }
|
|
|
- }
|
|
|
- for (Instruction* I : toDelete) {
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Removing extra instruction after return in block {0}: {1}",
|
|
|
- getNodeId(BB),
|
|
|
- I->getOpcodeName());
|
|
|
- I->eraseFromParent();
|
|
|
- }
|
|
|
- }
|
|
|
- // 处理 target 函数的返回指令
|
|
|
- for (auto& pair : targetBlockMap) {
|
|
|
- BasicBlock* BB = pair.first;
|
|
|
-
|
|
|
- LOG_DEBUG("performCodeFusion", "Processing target block: {0}", getNodeId(BB));
|
|
|
-
|
|
|
- if (!BB || BB->empty()) continue;
|
|
|
-
|
|
|
- std::vector<Instruction*> toDelete; // 存储需要删除的指令
|
|
|
- bool foundReturn = false;
|
|
|
-
|
|
|
- for (BasicBlock::iterator I = BB->begin(); I != BB->end();) {
|
|
|
- Instruction* Inst = &*I;
|
|
|
- ++I;
|
|
|
-
|
|
|
- // 打印每条指令的信息
|
|
|
- std::string instStr;
|
|
|
- raw_string_ostream rso(instStr);
|
|
|
- Inst->print(rso);
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Block {0} - Processing instruction: {1} (opcode: {2})",
|
|
|
- getNodeId(BB),
|
|
|
- instStr,
|
|
|
- Inst->getOpcodeName());
|
|
|
-
|
|
|
- if (ReturnInst* RI = dyn_cast<ReturnInst>(Inst)){
|
|
|
- // 添加额外的安全检查
|
|
|
- if (!RI->getParent()) continue;
|
|
|
- foundReturn = true;
|
|
|
- IRBuilder<> Builder(RI);
|
|
|
- Value* targetRetVal = RI->getReturnValue();
|
|
|
- // 先重映射返回值
|
|
|
- // if (targetRetVal) {
|
|
|
- // LOG_DEBUG("performCodeFusion", "Mapping target return value");
|
|
|
- // targetRetVal = MapValue(targetRetVal, targetVMap);
|
|
|
- // }
|
|
|
-
|
|
|
- if (!targetRetVal) {
|
|
|
- LOG_DEBUG("performCodeFusion", "Setting default target return value");
|
|
|
- if (returnType->isIntegerTy()) {
|
|
|
- targetRetVal = ConstantInt::get(returnType, 0);
|
|
|
- } else if (returnType->isPointerTy()) {
|
|
|
- targetRetVal = ConstantPointerNull::get(cast<PointerType>(returnType));
|
|
|
- } else if (returnType->isFloatingPointTy()) {
|
|
|
- targetRetVal = ConstantFP::get(returnType, 0.0);
|
|
|
- } else {
|
|
|
- targetRetVal = UndefValue::get(returnType);
|
|
|
- }
|
|
|
- } else if (targetRetVal->getType() != returnType) {
|
|
|
- LOG_DEBUG("performCodeFusion", "Casting target return value to {0}", getReadableTypeName(returnType));
|
|
|
- targetRetVal = Builder.CreateBitCast(targetRetVal, returnType);
|
|
|
- }
|
|
|
-
|
|
|
- ReturnInst* NewRI = ReturnInst::Create(M.getContext(), targetRetVal);
|
|
|
- ReplaceInstWithInst(RI, NewRI);
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Updated target return in block {0} with value type {1}",
|
|
|
- getNodeId(BB),
|
|
|
- getReadableTypeName(targetRetVal->getType()));
|
|
|
- }else if (foundReturn) {
|
|
|
- // 将返回指令之后的所有指令标记为待删除
|
|
|
- toDelete.push_back(Inst);
|
|
|
- }
|
|
|
- }
|
|
|
- for (Instruction* I : toDelete) {
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Removing extra instruction after return in block {0}: {1}",
|
|
|
- getNodeId(BB),
|
|
|
- I->getOpcodeName());
|
|
|
- I->eraseFromParent();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- LOG_INFO("performCodeFusion",
|
|
|
- "Fused function {0} has void return type",
|
|
|
- fusedFunc->getName().str());
|
|
|
-
|
|
|
- // 处理 void 返回类型的情况
|
|
|
- for (auto& pair : bunkerBlockMap) {
|
|
|
- BasicBlock* BB = pair.first;
|
|
|
- if (!BB || BB->empty()) continue;
|
|
|
-
|
|
|
- std::vector<Instruction*> toDelete; // 存储需要删除的指令
|
|
|
- bool foundReturn = false;
|
|
|
-
|
|
|
- for (BasicBlock::iterator I = BB->begin(); I != BB->end();) {
|
|
|
- Instruction* Inst = &*I;
|
|
|
- ++I;
|
|
|
- if (ReturnInst* RI = dyn_cast<ReturnInst>(Inst)){
|
|
|
- // 添加额外的安全检查
|
|
|
- if (!RI->getParent()) continue;
|
|
|
- foundReturn = true;
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Converting bunker return instruction to void return in block: {0}",
|
|
|
- getNodeId(BB));
|
|
|
-
|
|
|
- ReturnInst* NewRI = ReturnInst::Create(M.getContext(), nullptr, RI);
|
|
|
- ReplaceInstWithInst(RI, NewRI);
|
|
|
- }else if (foundReturn) {
|
|
|
- // 将返回指令之后的所有指令标记为待删除
|
|
|
- toDelete.push_back(Inst);
|
|
|
- }
|
|
|
- }
|
|
|
- for (Instruction* I : toDelete) {
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Removing extra instruction after return in block {0}: {1}",
|
|
|
- getNodeId(BB),
|
|
|
- I->getOpcodeName());
|
|
|
- I->eraseFromParent();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for (auto& pair : targetBlockMap) {
|
|
|
- BasicBlock* BB = pair.first;
|
|
|
- if (!BB || BB->empty()) continue;
|
|
|
-
|
|
|
- std::vector<Instruction*> toDelete; // 存储需要删除的指令
|
|
|
- bool foundReturn = false;
|
|
|
-
|
|
|
- for (BasicBlock::iterator I = BB->begin(); I != BB->end();) {
|
|
|
- Instruction* Inst = &*I;
|
|
|
- ++I;
|
|
|
- if (ReturnInst* RI = dyn_cast<ReturnInst>(Inst)){
|
|
|
- // 添加额外的安全检查
|
|
|
- if (!RI->getParent()) continue;
|
|
|
- foundReturn = true;
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Converting target return instruction to void return in block: {0}",
|
|
|
- BB->getName().str());
|
|
|
-
|
|
|
- ReturnInst* NewRI = ReturnInst::Create(M.getContext(), nullptr, RI);
|
|
|
- ReplaceInstWithInst(RI, NewRI);
|
|
|
- }else if (foundReturn) {
|
|
|
- // 将返回指令之后的所有指令标记为待删除
|
|
|
- toDelete.push_back(Inst);
|
|
|
- }
|
|
|
- }
|
|
|
- for (Instruction* I : toDelete) {
|
|
|
- LOG_DEBUG("performCodeFusion",
|
|
|
- "Removing extra instruction after return in block {0}: {1}",
|
|
|
- getNodeId(BB),
|
|
|
- I->getOpcodeName());
|
|
|
- I->eraseFromParent();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 添加新的日志打印代码
|
|
|
- LOG_INFO("performCodeFusion", "Listing all instructions after return repairing in function: {0}",
|
|
|
- fusedFunc->getName().str());
|
|
|
- dumpControlFlowGraph(*fusedFunc);
|
|
|
-
|
|
|
- // 更新调用点
|
|
|
- std::vector<CallInst*> bunkerCalls;
|
|
|
- std::vector<CallInst*> targetCalls;
|
|
|
-
|
|
|
- // 收集所有调用点
|
|
|
- for (auto& U : bunkerFunc->uses()) {
|
|
|
- if (CallInst* CI = dyn_cast<CallInst>(U.getUser())) {
|
|
|
- bunkerCalls.push_back(CI);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for (auto& U : targetFunc->uses()) {
|
|
|
- if (CallInst* CI = dyn_cast<CallInst>(U.getUser())) {
|
|
|
- targetCalls.push_back(CI);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for (CallInst* CI : bunkerCalls) {
|
|
|
- updateCallSite(CI, fusedFunc, bunkerFunc, targetFunc, false);
|
|
|
- }
|
|
|
-
|
|
|
- for (CallInst* CI : targetCalls) {
|
|
|
- updateCallSite(CI, fusedFunc, targetFunc, bunkerFunc, true);
|
|
|
- }
|
|
|
-
|
|
|
- // 删除原始函数
|
|
|
- bunkerFunc->eraseFromParent();
|
|
|
- targetFunc->eraseFromParent();
|
|
|
-
|
|
|
-
|
|
|
- // 添加新的日志打印代码
|
|
|
- LOG_INFO("performCodeFusion", "Listing all instructions after update calls in function: {0}",
|
|
|
- fusedFunc->getName().str());
|
|
|
- dumpControlFlowGraph(*fusedFunc);
|
|
|
-
|
|
|
-
|
|
|
- LOG_INFO("performCodeFusion",
|
|
|
- "Completed function fusion: {0}",
|
|
|
- fusedFunc->getName().str());
|
|
|
- }
|
|
|
-
|
|
|
- LOG_INFO("performCodeFusion",
|
|
|
- "Code fusion completed, processed {0} function pairs",
|
|
|
- fusionPairs.size());
|
|
|
- }
|
|
|
};
|
|
|
}
|
|
|
|