From 068f6783d178630c8a0ffea8d594c5838ce3ebe2 Mon Sep 17 00:00:00 2001 From: EmilioCorigliano Date: Tue, 16 Jun 2026 19:28:41 +0200 Subject: [PATCH 01/11] upd(FuncRetToRef): removed volatile load and stores --- passes/FuncRetToRef.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/FuncRetToRef.cpp b/passes/FuncRetToRef.cpp index 3b46c9e..5f4c364 100644 --- a/passes/FuncRetToRef.cpp +++ b/passes/FuncRetToRef.cpp @@ -118,7 +118,7 @@ void FuncRetToRef::updateRetInstructions(Function &Fn) { Value *ReturnPtr = Fn.getArg(Fn.arg_size()-1); // the last argument is the return ptr // Store the returnvalue in the returnptr - B.CreateStore(ReturnValue, ReturnPtr, true); + B.CreateStore(ReturnValue, ReturnPtr); // create a ret instruction B.CreateRetVoid(); @@ -208,7 +208,7 @@ void FuncRetToRef::updateFunctionCalls(Function &Fn, Function &NewFn) { abort(); } // use the load on the return value instead of the previous function output - Instruction *TmpLoad = B.CreateLoad(CInstr->getType(), TmpAlloca, true); + Instruction *TmpLoad = B.CreateLoad(CInstr->getType(), TmpAlloca); createdNewCall = true; CInstr->replaceNonMetadataUsesWith(TmpLoad); } From e729ae20139922c978f849b1a6cc78e7550b7a98 Mon Sep 17 00:00:00 2001 From: EmilioCorigliano Date: Tue, 16 Jun 2026 19:29:37 +0200 Subject: [PATCH 02/11] upd(Utils): update functions to exclude and duplicate values --- passes/Utils/Utils.cpp | 33 +++++++++++++++++++++++++++------ passes/Utils/Utils.h | 3 ++- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/passes/Utils/Utils.cpp b/passes/Utils/Utils.cpp index 581b0bb..abc0ea1 100644 --- a/passes/Utils/Utils.cpp +++ b/passes/Utils/Utils.cpp @@ -218,12 +218,15 @@ StringRef getLinkageName(const LinkageMap &linkageMap, const std::string &functi } } -bool isToDuplicate(CallBase *CInstr) { - Intrinsic::ID intrinsicID = CInstr->getIntrinsicID(); - if (intrinsicID != Intrinsic::not_intrinsic) { - return true; - } else if(CInstr->getCalledFunction() != NULL && isToDuplicateName(CInstr->getCalledFunction()->getName())) { - return true; +bool isToDuplicate(Value *V) { + if(isa(V)) { + CallBase *CInstr = cast(V); + Intrinsic::ID intrinsicID = CInstr->getIntrinsicID(); + if (intrinsicID != Intrinsic::not_intrinsic) { + return true; + } else if(CInstr->getCalledFunction() != NULL && isToDuplicateName(CInstr->getCalledFunction()->getName())) { + return true; + } } return false; @@ -251,6 +254,24 @@ bool isToDuplicateName(StringRef FnMangledName) { return false; } +bool isToExclude(Value *V) { + if(isa(V)) { + Instruction *Inst = cast(V); + if (Inst->isVolatile()) { + return true; + } + } + + if(isa(V)) { + CallBase *CInstr = cast(V); + if(CInstr->getCalledFunction() != NULL && isToExcludeName(CInstr->getCalledFunction()->getName())) { + return true; + } + } + + return false; +} + bool isToExcludeName(StringRef FnMangledName) { if(FnMangledName.ends_with("_ret")) { FnMangledName = FnMangledName.substr(0, FnMangledName.size() - 4); diff --git a/passes/Utils/Utils.h b/passes/Utils/Utils.h index cdc7f0b..22313f8 100644 --- a/passes/Utils/Utils.h +++ b/passes/Utils/Utils.h @@ -45,8 +45,9 @@ LinkageMap mapFunctionLinkageNames(const Module &M); void printLinkageMap(const LinkageMap &linkageMap); StringRef getLinkageName(const LinkageMap &linkageMap, const std::string &functionName); bool isToDuplicateName(StringRef FnMangledName); -bool isToDuplicate(CallBase *CInstr); +bool isToDuplicate(Value *CInstr); bool isToExcludeName(StringRef FnMangledName); +bool isToExclude(Value *V); void createFtFuncs(Module &Md); From 983b0ebab1641d543cc9fe0ba48d28342db4d79a Mon Sep 17 00:00:00 2001 From: EmilioCorigliano Date: Tue, 16 Jun 2026 19:31:45 +0200 Subject: [PATCH 03/11] upd(EDDI): create synchronizeFunctionArguments --- passes/ASPIS.h | 2 +- passes/EDDI.cpp | 76 ++++++++++++++++++++++++++----------------------- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/passes/ASPIS.h b/passes/ASPIS.h index 1d250c5..c1c756e 100644 --- a/passes/ASPIS.h +++ b/passes/ASPIS.h @@ -76,7 +76,7 @@ class EDDI : public PassInfoMixin { bool isValueDuplicated(Instruction &V); Function *duplicateFnArgs(Function &Fn, Module &Md); void CreateErrBB(Module &Md, Function &Fn, BasicBlock *ErrBB); - bool temporaryArgumentDuplication(Module &Md, llvm::Value *value, IRBuilder<> &B); + bool synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilder<> &B); Value *getDuplicateValue(Value *V, Instruction *I); void createCompareOnOperand(std::vector *CmpInstructions, Value *V, Instruction &I, IRBuilder<> &B); void compareValues(std::vector *CmpInstructions, Value &V1, Value &V2, IRBuilder<> &B); diff --git a/passes/EDDI.cpp b/passes/EDDI.cpp index c0e861a..dfa6809 100755 --- a/passes/EDDI.cpp +++ b/passes/EDDI.cpp @@ -701,7 +701,7 @@ void EDDI::duplicateOperands( } } else if (isa(I) && isa(V) && cast(V)->isConstant()) { IRBuilder<> B(&I); - temporaryArgumentDuplication(*I.getModule(), V, B); + synchronizeFunctionArguments(*I.getModule(), V, B); } if (IClone != nullptr) { @@ -780,17 +780,11 @@ void EDDI::comparePtrs(std::vector *CmpInstructions, Value &V1, Value & if(deducedTypes.transparentTypes.find(&V1)->second.size() != 1) { errs() << "\tMultiple types 1!\n"; - for(auto el=deducedTypes.transparentTypes.find(&V1)->second.cbegin(); el != deducedTypes.transparentTypes.find(&V1)->second.cend(); el++) { - errs() << "\t" << el->get()->toString() << "\n"; - } return; } if(deducedTypes.transparentTypes.find(&V2)->second.size() != 1) { errs() << "\tMultiple types 2!\n"; - for(auto el=deducedTypes.transparentTypes.find(&V2)->second.cbegin(); el != deducedTypes.transparentTypes.find(&V2)->second.cend(); el++) { - errs() << "\t" << el->get()->toString() << "\n"; - } return; } @@ -1096,16 +1090,8 @@ void EDDI::fixFuncValsPassedByReference( Value *Duplicate = getDuplicateValue(Operand, &I); if (Duplicate != nullptr) { - Value *Original = Operand; - Value *Copy = Duplicate; - if(Original->getType()->isPointerTy() && Copy->getType()->isPointerTy()) { - Type *OriginalType = Original->getType(); - Instruction *TmpLoad = B.CreateLoad(OriginalType, Original); - Instruction *TmpStore = B.CreateStore(TmpLoad, Copy); - DuplicatedInstructionMap.insert( - std::pair(TmpLoad, TmpLoad)); - DuplicatedInstructionMap.insert( - std::pair(TmpStore, TmpStore)); + if(Operand->getType()->isPointerTy() && Duplicate->getType()->isPointerTy()) { + synchronizeFunctionArguments(*I.getModule(), Operand, B); } } } @@ -1975,7 +1961,7 @@ PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) { if(Arg->getType()->isPointerTy() && !CInstr->isByValArgument(i) && isa(Arg) && !isa(Arg)) { // If cannot perform TAD, do not duplicate Arg - temporaryArgumentDuplication(Md, Arg, B); + synchronizeFunctionArguments(Md, Arg, B); } else { // Otherwise pass two times the same arg DuplicatedInstructionMap.insert(std::pair(Arg, Arg)); // TODO: Check if needed @@ -2048,7 +2034,7 @@ PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) { return PreservedAnalyses::none(); } -bool EDDI::temporaryArgumentDuplication(Module &Md, llvm::Value *value, IRBuilder<> &B) { +bool EDDI::synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilder<> &B) { const llvm::DataLayout &DL = Md.getDataLayout(); auto TTIter = deducedTypes.transparentTypes.find(value); @@ -2088,44 +2074,62 @@ bool EDDI::temporaryArgumentDuplication(Module &Md, llvm::Value *value, IRBuilde } } - // currentPtr is now the pointer to the final value - + bool hasPerformedTAD = false; + Value *valueDup = nullptr; uint64_t SizeInBytes = 0; - AllocaInst *allocaPrev = nullptr; - if(isa(currentPtr)) { auto *gepInst = cast(currentPtr); SizeInBytes = DL.getTypeAllocSize(gepInst->getSourceElementType()); - allocaPrev = B.CreateAlloca(VTy->getLLVMType(), ConstantInt::get(VTy->getLLVMType(), SizeInBytes)); } else { SizeInBytes = DL.getTypeAllocSize(VTy->getLLVMType()); - allocaPrev = B.CreateAlloca(VTy->getLLVMType()); } - deducedTypes.transparentTypes[allocaPrev].insert(VTy->clone()); + auto valueDupIt = DuplicatedInstructionMap.find(value); + if(valueDupIt == DuplicatedInstructionMap.end()) { + hasPerformedTAD = true; + // currentPtr is now the pointer to the final value + + AllocaInst *allocaPrev = nullptr; + + if(isa(currentPtr)) { + allocaPrev = B.CreateAlloca(VTy->getLLVMType(), ConstantInt::get(B.getInt8Ty(), SizeInBytes)); + } else { + allocaPrev = B.CreateAlloca(VTy->getLLVMType()); + } + allocaPrev->moveAfter(allocaPrev->getParent()->getParent()->getEntryBlock().getFirstNonPHIOrDbgOrAlloca()); + deducedTypes.transparentTypes[allocaPrev].insert(VTy->clone()); + valueDup = allocaPrev; + } else { + hasPerformedTAD = false; + valueDup = valueDupIt->second; + } Value *Size = llvm::ConstantInt::get(B.getInt8Ty(), SizeInBytes); llvm::CallInst *memcpy_call = B.CreateMemCpy( - allocaPrev, allocaPrev->getPointerAlignment(DL), - currentPtr, allocaPrev->getPointerAlignment(DL), + valueDup, valueDup->getPointerAlignment(DL), + currentPtr, valueDup->getPointerAlignment(DL), Size); auto VTyPtr = VTy->clone(); // Now we need to create as many allocas as the number of pointer indirections // in order to duplicate the whole pointer chain - for (int i = 0; i < indirections; ++i) { - VTyPtr = VTyPtr->getPointerToType(); - auto *allocaCurr = B.CreateAlloca(VTyPtr->getLLVMType()); - deducedTypes.transparentTypes[allocaCurr].insert(VTyPtr->getPointerToType()->clone()); - B.CreateStore(allocaPrev, allocaCurr); - allocaPrev = allocaCurr; + if(hasPerformedTAD) { + for (int i = 0; i < indirections; ++i) { + VTyPtr = VTyPtr->getPointerToType(); + auto *allocaCurr = B.CreateAlloca(VTyPtr->getLLVMType()); + allocaCurr->moveAfter(allocaCurr->getParent()->getParent()->getEntryBlock().getFirstNonPHIOrDbgOrAlloca()); + deducedTypes.transparentTypes[allocaCurr].insert(VTyPtr->getPointerToType()->clone()); + B.CreateStore(valueDup, allocaCurr); + valueDup = allocaCurr; + } + + DuplicatedInstructionMap.emplace(valueDup, value); + DuplicatedInstructionMap.emplace(value, valueDup); } - DuplicatedInstructionMap.emplace(allocaPrev, value); - DuplicatedInstructionMap.emplace(value, allocaPrev); DuplicatedInstructionMap.insert(std::pair(memcpy_call, memcpy_call)); return true; From fa7bec3daf33733c548e416aa149bac46051a578 Mon Sep 17 00:00:00 2001 From: EmilioCorigliano Date: Tue, 16 Jun 2026 19:32:15 +0200 Subject: [PATCH 04/11] upd(EDDI): exclude volatile and inline asm --- passes/EDDI.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/passes/EDDI.cpp b/passes/EDDI.cpp index dfa6809..b7031dd 100755 --- a/passes/EDDI.cpp +++ b/passes/EDDI.cpp @@ -1370,6 +1370,10 @@ int EDDI::duplicateInstruction(Instruction &I, BasicBlock &ErrBB) { return 0; } + if(I.isVolatile() || (isa(I) && cast(I).isInlineAsm())) { + return 0; + } + Instruction *clonedInst = nullptr; int res = 0; From f753ffddbde09e969013a7010f5246f541c3cf33 Mon Sep 17 00:00:00 2001 From: EmilioCorigliano Date: Tue, 16 Jun 2026 19:32:55 +0200 Subject: [PATCH 05/11] upd(EDDI): update to exclude and to duplicate functions --- passes/EDDI.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/EDDI.cpp b/passes/EDDI.cpp index b7031dd..5e4d0dc 100755 --- a/passes/EDDI.cpp +++ b/passes/EDDI.cpp @@ -1461,13 +1461,13 @@ int EDDI::duplicateInstruction(Instruction &I, BasicBlock &ErrBB) { Function *Callee = CInstr->getCalledFunction(); Callee = getFunctionFromDuplicate(Callee); - if(CInstr->getCalledFunction() != NULL && isToExcludeName(CInstr->getCalledFunction()->getName())) { + if((FuncAnnotations.find(Callee) != FuncAnnotations.end() && FuncAnnotations.find(Callee)->second.starts_with("exclude")) || (Callee != NULL && isToExclude(CInstr))) { return 0; } // check if the function call has to be duplicated if ((FuncAnnotations.find(Callee) != FuncAnnotations.end() && FuncAnnotations.find(Callee)->second.starts_with("to_duplicate")) || - isToDuplicate(CInstr)) { + (Callee != NULL && isToDuplicate(CInstr))) { // duplicate the instruction clonedInst = cloneInstr(*CInstr); From 4904e4a559993034ea61b41d0c1bbdf8fa6e5e33 Mon Sep 17 00:00:00 2001 From: EmilioCorigliano Date: Wed, 17 Jun 2026 01:00:21 +0200 Subject: [PATCH 06/11] fix(EDDI): fix TAD in case of global variables --- passes/ASPIS.h | 4 ++-- passes/EDDI.cpp | 38 ++++++++++++++++++-------------------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/passes/ASPIS.h b/passes/ASPIS.h index c1c756e..8678b3e 100644 --- a/passes/ASPIS.h +++ b/passes/ASPIS.h @@ -76,8 +76,8 @@ class EDDI : public PassInfoMixin { bool isValueDuplicated(Instruction &V); Function *duplicateFnArgs(Function &Fn, Module &Md); void CreateErrBB(Module &Md, Function &Fn, BasicBlock *ErrBB); - bool synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilder<> &B); - Value *getDuplicateValue(Value *V, Instruction *I); + bool synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilder<> &B, Instruction *I); + Value *getDuplicateValue(Value *V, Function *I); void createCompareOnOperand(std::vector *CmpInstructions, Value *V, Instruction &I, IRBuilder<> &B); void compareValues(std::vector *CmpInstructions, Value &V1, Value &V2, IRBuilder<> &B); void fixGlobalCtors(Module &M); diff --git a/passes/EDDI.cpp b/passes/EDDI.cpp index 5e4d0dc..4a4390a 100755 --- a/passes/EDDI.cpp +++ b/passes/EDDI.cpp @@ -597,7 +597,7 @@ EDDI::cloneInstr(Instruction &I) { return IClone; } -Value *EDDI::getDuplicateValue(Value *V, Instruction *I) { +Value *EDDI::getDuplicateValue(Value *V, Function *Fn) { // Fast path if V is a local variable, it should have only one duplicate if(!isa(V) || isa(V)) { assert((DuplicatedInstructionMap.count(V) <= 1) && "Local variable has more than one duplicate"); @@ -620,7 +620,7 @@ Value *EDDI::getDuplicateValue(Value *V, Instruction *I) { return duplicate; } else { // If it is an instruction, we need to check if it is in the same function of I - if (isa(duplicate) && cast(duplicate)->getParent()->getParent() == I->getParent()->getParent()) { + if (isa(duplicate) && cast(duplicate)->getParent()->getParent() == Fn) { return duplicate; } } @@ -643,7 +643,7 @@ void EDDI::duplicateOperands( BasicBlock &ErrBB) { // see if I has a clone - Value *Clone = getDuplicateValue(&I, &I); + Value *Clone = getDuplicateValue(&I, I.getFunction()); Instruction *IClone = nullptr; if(Clone != nullptr && isa(Clone)) { IClone = cast(Clone); @@ -671,7 +671,7 @@ void EDDI::duplicateOperands( if (IClone != nullptr) { GEPOperator *GEPOperand = cast(IClone->getOperand(J)); Value *PtrOperand = GEPOperand->getPointerOperand(); - Value *ClonePtrOperand = getDuplicateValue(PtrOperand, &I); + Value *ClonePtrOperand = getDuplicateValue(PtrOperand, I.getFunction()); // update the duplicate GEP operator using the duplicate of the pointer // operand if (ClonePtrOperand != nullptr) { @@ -701,12 +701,12 @@ void EDDI::duplicateOperands( } } else if (isa(I) && isa(V) && cast(V)->isConstant()) { IRBuilder<> B(&I); - synchronizeFunctionArguments(*I.getModule(), V, B); + synchronizeFunctionArguments(*I.getModule(), V, B, &I); } if (IClone != nullptr) { // use the duplicated instruction as operand of IClone - Value *CloneOperand = getDuplicateValue(V, &I); + Value *CloneOperand = getDuplicateValue(V, I.getFunction()); if (CloneOperand != nullptr) { IClone->setOperand(J, CloneOperand); // set the J-th operand with the duplicate value } @@ -938,7 +938,7 @@ void EDDI::addConsistencyChecks( // if the instruction is a call with indirect function, we try to get a compare if(isa(I) && cast(I).isIndirectCall()) { - Value *Duplicate = getDuplicateValue(cast(I).getCalledOperand(), &I); + Value *Duplicate = getDuplicateValue(cast(I).getCalledOperand(), I.getFunction()); if (Duplicate != nullptr) { Value *Original = cast(I).getCalledOperand(); Value *Copy = Duplicate; @@ -1087,11 +1087,11 @@ void EDDI::fixFuncValsPassedByReference( Value *V = I.getOperand(i); if (isa(V)) { Instruction *Operand = cast(V); - Value *Duplicate = getDuplicateValue(Operand, &I); + Value *Duplicate = getDuplicateValue(Operand, I.getFunction()); if (Duplicate != nullptr) { if(Operand->getType()->isPointerTy() && Duplicate->getType()->isPointerTy()) { - synchronizeFunctionArguments(*I.getModule(), Operand, B); + synchronizeFunctionArguments(*I.getModule(), Operand, B, &I); } } } @@ -1257,7 +1257,7 @@ int EDDI::transformCallBaseInst(CallBase *CInstr, IRBuilder<> &B, BasicBlock &Er Value *Arg = CInstr->getArgOperand(i); // see if Original has a copy - Value *Copy = getDuplicateValue(Arg, CInstr); + Value *Copy = getDuplicateValue(Arg, CInstr->getFunction()); if(Copy == nullptr) { Copy = Arg; } @@ -1425,7 +1425,7 @@ int EDDI::duplicateInstruction(Instruction &I, BasicBlock &ErrBB) { if (IClone->isIdenticalTo(&I)) { IClone->eraseFromParent(); - Value *Copy = getDuplicateValue(&I, &I); + Value *Copy = getDuplicateValue(&I, I.getFunction()); if(Copy != nullptr) { DuplicatedInstructionMap.erase(Copy); DuplicatedInstructionMap.erase(&I); @@ -1956,7 +1956,7 @@ PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) { Value *Arg = CInstr->getArgOperand(i); // If argument has already a duplicate, nothing to do - if(getDuplicateValue(Arg, CInstr) != nullptr || !isa(Arg)) { + if(getDuplicateValue(Arg, CInstr->getFunction()) != nullptr || !isa(Arg)) { // If Argument already duplicated continue to next argument continue; } @@ -1965,7 +1965,7 @@ PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) { if(Arg->getType()->isPointerTy() && !CInstr->isByValArgument(i) && isa(Arg) && !isa(Arg)) { // If cannot perform TAD, do not duplicate Arg - synchronizeFunctionArguments(Md, Arg, B); + synchronizeFunctionArguments(Md, Arg, B, CInstr); } else { // Otherwise pass two times the same arg DuplicatedInstructionMap.insert(std::pair(Arg, Arg)); // TODO: Check if needed @@ -2038,7 +2038,7 @@ PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) { return PreservedAnalyses::none(); } -bool EDDI::synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilder<> &B) { +bool EDDI::synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilder<> &B, Instruction *I) { const llvm::DataLayout &DL = Md.getDataLayout(); auto TTIter = deducedTypes.transparentTypes.find(value); @@ -2079,7 +2079,7 @@ bool EDDI::synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilde } bool hasPerformedTAD = false; - Value *valueDup = nullptr; + Value *valueDup = getDuplicateValue(value, I->getFunction()); uint64_t SizeInBytes = 0; if(isa(currentPtr)) { auto *gepInst = cast(currentPtr); @@ -2088,8 +2088,7 @@ bool EDDI::synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilde SizeInBytes = DL.getTypeAllocSize(VTy->getLLVMType()); } - auto valueDupIt = DuplicatedInstructionMap.find(value); - if(valueDupIt == DuplicatedInstructionMap.end()) { + if(valueDup == nullptr) { hasPerformedTAD = true; // currentPtr is now the pointer to the final value @@ -2106,7 +2105,6 @@ bool EDDI::synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilde valueDup = allocaPrev; } else { hasPerformedTAD = false; - valueDup = valueDupIt->second; } Value *Size = llvm::ConstantInt::get(B.getInt8Ty(), SizeInBytes); @@ -2130,8 +2128,8 @@ bool EDDI::synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilde valueDup = allocaCurr; } - DuplicatedInstructionMap.emplace(valueDup, value); - DuplicatedInstructionMap.emplace(value, valueDup); + DuplicatedInstructionMap.insert(std::pair(valueDup, value)); + DuplicatedInstructionMap.insert(std::pair(value, valueDup)); } DuplicatedInstructionMap.insert(std::pair(memcpy_call, memcpy_call)); From 590d6e828dd8be80a8810d406325a598798b0145 Mon Sep 17 00:00:00 2001 From: EmilioCorigliano Date: Wed, 17 Jun 2026 14:15:07 +0200 Subject: [PATCH 07/11] upd(EDDI): now synchronizeFunctionArguments can synchronize the argument before or after the instruction --- passes/ASPIS.h | 2 +- passes/EDDI.cpp | 36 +++++++++++++++++++++++++++++++----- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/passes/ASPIS.h b/passes/ASPIS.h index 8678b3e..2cc4fca 100644 --- a/passes/ASPIS.h +++ b/passes/ASPIS.h @@ -76,7 +76,7 @@ class EDDI : public PassInfoMixin { bool isValueDuplicated(Instruction &V); Function *duplicateFnArgs(Function &Fn, Module &Md); void CreateErrBB(Module &Md, Function &Fn, BasicBlock *ErrBB); - bool synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilder<> &B, Instruction *I); + bool synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilder<> &B, Instruction *I, bool before); Value *getDuplicateValue(Value *V, Function *I); void createCompareOnOperand(std::vector *CmpInstructions, Value *V, Instruction &I, IRBuilder<> &B); void compareValues(std::vector *CmpInstructions, Value &V1, Value &V2, IRBuilder<> &B); diff --git a/passes/EDDI.cpp b/passes/EDDI.cpp index 4a4390a..e2ef9dd 100755 --- a/passes/EDDI.cpp +++ b/passes/EDDI.cpp @@ -701,7 +701,7 @@ void EDDI::duplicateOperands( } } else if (isa(I) && isa(V) && cast(V)->isConstant()) { IRBuilder<> B(&I); - synchronizeFunctionArguments(*I.getModule(), V, B, &I); + synchronizeFunctionArguments(*I.getModule(), V, B, &I, true); } if (IClone != nullptr) { @@ -1091,7 +1091,7 @@ void EDDI::fixFuncValsPassedByReference( if (Duplicate != nullptr) { if(Operand->getType()->isPointerTy() && Duplicate->getType()->isPointerTy()) { - synchronizeFunctionArguments(*I.getModule(), Operand, B, &I); + synchronizeFunctionArguments(*I.getModule(), Operand, B, &I, false); } } } @@ -1462,6 +1462,19 @@ int EDDI::duplicateInstruction(Instruction &I, BasicBlock &ErrBB) { Callee = getFunctionFromDuplicate(Callee); if((FuncAnnotations.find(Callee) != FuncAnnotations.end() && FuncAnnotations.find(Callee)->second.starts_with("exclude")) || (Callee != NULL && isToExclude(CInstr))) { + IRBuilder<> B(CInstr); + fixFuncValsPassedByReference(*CInstr, B); + +#ifdef CHECK_AT_CALLS +#if (SELECTIVE_CHECKING == 1) + if(I.getParent()->getTerminator() == NULL) { + errs() << "Malformed block!\n"; + I.getParent()->print(errs()); + errs() << "\n"; + } else if (I.getParent()->getTerminator()->getNumSuccessors() > 1) +#endif + addConsistencyChecks(I, ErrBB); +#endif return 0; } @@ -1965,7 +1978,7 @@ PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) { if(Arg->getType()->isPointerTy() && !CInstr->isByValArgument(i) && isa(Arg) && !isa(Arg)) { // If cannot perform TAD, do not duplicate Arg - synchronizeFunctionArguments(Md, Arg, B, CInstr); + synchronizeFunctionArguments(Md, Arg, B, CInstr, true); } else { // Otherwise pass two times the same arg DuplicatedInstructionMap.insert(std::pair(Arg, Arg)); // TODO: Check if needed @@ -2038,7 +2051,7 @@ PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) { return PreservedAnalyses::none(); } -bool EDDI::synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilder<> &B, Instruction *I) { +bool EDDI::synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilder<> &B, Instruction *I, bool before) { const llvm::DataLayout &DL = Md.getDataLayout(); auto TTIter = deducedTypes.transparentTypes.find(value); @@ -2090,6 +2103,7 @@ bool EDDI::synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilde if(valueDup == nullptr) { hasPerformedTAD = true; + assert(hasPerformedTAD && before && "TAD shall be performed only for syncrhonization before the instruction"); // currentPtr is now the pointer to the final value AllocaInst *allocaPrev = nullptr; @@ -2113,7 +2127,19 @@ bool EDDI::synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilde valueDup, valueDup->getPointerAlignment(DL), currentPtr, valueDup->getPointerAlignment(DL), Size); - + if(!before) { + if(!I->isTerminator()) { + memcpy_call->moveAfter(I); + } else { + if(isa(I)) { + memcpy_call->moveBefore(cast(I)->getNormalDest()->getFirstNonPHIOrDbgOrAlloca()); + } else { + errs() << "Error: not handled instruction for synchronize function arguments\n"; + abort(); + } + } + } + auto VTyPtr = VTy->clone(); // Now we need to create as many allocas as the number of pointer indirections From 376523483bbff3e9fefb05c3650a5c928c5e4fff Mon Sep 17 00:00:00 2001 From: EmilioCorigliano Date: Wed, 17 Jun 2026 17:09:37 +0200 Subject: [PATCH 08/11] feat(EDDI): duplicate volatile integer after loads and create consistency checks before store --- passes/EDDI.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/passes/EDDI.cpp b/passes/EDDI.cpp index e2ef9dd..3b49342 100755 --- a/passes/EDDI.cpp +++ b/passes/EDDI.cpp @@ -1370,7 +1370,27 @@ int EDDI::duplicateInstruction(Instruction &I, BasicBlock &ErrBB) { return 0; } - if(I.isVolatile() || (isa(I) && cast(I).isInlineAsm())) { + if(I.isVolatile()) { + if(isa(I) && I.getType()->isIntegerTy()) { + IRBuilder<> B(&I); + auto Idup = B.CreateAdd(&I, llvm::ConstantInt::get(I.getType(), 0)); + cast(Idup)->moveAfter(&I); + DuplicatedInstructionMap.insert(std::pair(&I, Idup)); + DuplicatedInstructionMap.insert(std::pair(Idup, &I)); + } else if(isa(I)) { +#ifdef CHECK_AT_STORES +#if (SELECTIVE_CHECKING == 1) + if(I.getParent()->getTerminator() == NULL) { + errs() << "Malformed block!\n"; + I.getParent()->print(errs()); + errs() << "\n"; + } else if (I.getParent()->getTerminator()->getNumSuccessors() > 1) +#endif + addConsistencyChecks(I, ErrBB); +#endif + } + return 0; + } else if (isa(I) && cast(I).isInlineAsm()) { return 0; } From 994aee16f4715b09dd2c622026a646d12671688a Mon Sep 17 00:00:00 2001 From: EmilioCorigliano Date: Wed, 17 Jun 2026 17:52:45 +0200 Subject: [PATCH 09/11] feat(EDDI): duplicate volatiles explicitly marked as to_duplicate or to_harden --- passes/EDDI.cpp | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/passes/EDDI.cpp b/passes/EDDI.cpp index 3b49342..668989f 100755 --- a/passes/EDDI.cpp +++ b/passes/EDDI.cpp @@ -1371,25 +1371,43 @@ int EDDI::duplicateInstruction(Instruction &I, BasicBlock &ErrBB) { } if(I.isVolatile()) { - if(isa(I) && I.getType()->isIntegerTy()) { - IRBuilder<> B(&I); - auto Idup = B.CreateAdd(&I, llvm::ConstantInt::get(I.getType(), 0)); - cast(Idup)->moveAfter(&I); - DuplicatedInstructionMap.insert(std::pair(&I, Idup)); - DuplicatedInstructionMap.insert(std::pair(Idup, &I)); + bool shouldDuplicateAnyway = false; + if(isa(I)) { + if(FuncAnnotations.find(cast(I).getPointerOperand()) != FuncAnnotations.end() && + (FuncAnnotations.find(cast(I).getPointerOperand())->second.starts_with("to_duplicate") || FuncAnnotations.find(cast(I).getPointerOperand())->second.starts_with("to_harden"))) { + shouldDuplicateAnyway = true; + } else if(I.getType()->isIntegerTy()) { + IRBuilder<> B(&I); + auto Idup = B.CreateAdd(&I, llvm::ConstantInt::get(I.getType(), 0)); + cast(Idup)->moveAfter(&I); + DuplicatedInstructionMap.insert(std::pair(&I, Idup)); + DuplicatedInstructionMap.insert(std::pair(Idup, &I)); + } else if(I.getType()->isFloatingPointTy()) { + IRBuilder<> B(&I); + auto Idup = B.CreateAdd(&I, llvm::ConstantFP::get(I.getType(), 0)); + cast(Idup)->moveAfter(&I); + DuplicatedInstructionMap.insert(std::pair(&I, Idup)); + DuplicatedInstructionMap.insert(std::pair(Idup, &I)); + } } else if(isa(I)) { + if(getDuplicateValue(cast(I).getPointerOperand(), I.getFunction()) != nullptr) { + shouldDuplicateAnyway = true; + } else { #ifdef CHECK_AT_STORES #if (SELECTIVE_CHECKING == 1) - if(I.getParent()->getTerminator() == NULL) { - errs() << "Malformed block!\n"; - I.getParent()->print(errs()); - errs() << "\n"; - } else if (I.getParent()->getTerminator()->getNumSuccessors() > 1) + if(I.getParent()->getTerminator() == NULL) { + errs() << "Malformed block!\n"; + I.getParent()->print(errs()); + errs() << "\n"; + } else if (I.getParent()->getTerminator()->getNumSuccessors() > 1) #endif - addConsistencyChecks(I, ErrBB); + addConsistencyChecks(I, ErrBB); #endif + } + } + if(!shouldDuplicateAnyway) { + return 0; } - return 0; } else if (isa(I) && cast(I).isInlineAsm()) { return 0; } From c442120af36a99d4d3c38cb9d75b39aa36483828 Mon Sep 17 00:00:00 2001 From: EmilioCorigliano Date: Wed, 17 Jun 2026 23:43:34 +0200 Subject: [PATCH 10/11] feat(EDDI): add other functions to be excluded by default --- passes/EDDI.cpp | 9 +++++---- passes/Utils/Utils.cpp | 9 +++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/passes/EDDI.cpp b/passes/EDDI.cpp index 668989f..9fdb104 100755 --- a/passes/EDDI.cpp +++ b/passes/EDDI.cpp @@ -982,10 +982,10 @@ void EDDI::addConsistencyChecks( } void EDDI::createCompareOnOperand(std::vector *CmpInstructions, Value *V, Instruction &I, IRBuilder<> &B) { - auto Duplicate = DuplicatedInstructionMap.find(V); + auto Duplicate = getDuplicateValue(V, I.getFunction()); // if the duplicate doesn't exist, we cannot perform a compare - if (Duplicate == DuplicatedInstructionMap.end()) { + if (Duplicate == nullptr) { return; } @@ -1002,8 +1002,8 @@ void EDDI::createCompareOnOperand(std::vector *CmpInstructions, Value * // TODO: are there other cases to support? } - Value *Original = Duplicate->first; - Value *Copy = Duplicate->second; + Value *Original = V; + Value *Copy = Duplicate; // we compare the operands only if they are found in the TDA transparent types if(deducedTypes.transparentTypes.find(V) == deducedTypes.transparentTypes.end()) { @@ -1056,6 +1056,7 @@ void EDDI::compareValues(std::vector *CmpInstructions, Value &V1, Value } else if(V1Ty->isArrayTT()) { int arraysize = V1Ty->getLLVMType()->getArrayNumElements(); + // TODO: understand if is possible to remove the extracted values when no check is performed for (int i = 0; i < arraysize; i++) { Value *OriginalElem = B.CreateExtractValue(&V1, i); Value *CopyElem = B.CreateExtractValue(&V2, i); diff --git a/passes/Utils/Utils.cpp b/passes/Utils/Utils.cpp index abc0ea1..e96910e 100644 --- a/passes/Utils/Utils.cpp +++ b/passes/Utils/Utils.cpp @@ -244,7 +244,8 @@ bool isToDuplicateName(StringRef FnMangledName) { if(FnName.find("std::ostream") != FnName.npos || FnName.find("std::basic_ostream") != FnName.npos || FnName.find("std::basic_ios") != FnName.npos || - FnName.find("std::thread") != FnName.npos) { + FnName.find("std::thread") != FnName.npos || + FnName.find("printf") != FnName.npos) { return false; } @@ -279,7 +280,11 @@ bool isToExcludeName(StringRef FnMangledName) { auto FnName = demangle(FnMangledName.str()); - if(FnName.find("std::thread") != FnName.npos) { + if(FnName.find("std::ostream") != FnName.npos || + FnName.find("std::basic_ostream") != FnName.npos || + FnName.find("std::basic_ios") != FnName.npos || + FnName.find("std::thread") != FnName.npos || + FnName.find("printf") != FnName.npos) { return true; } From 14aad08c108ea9d2628a88f4bb6c382ac223f63e Mon Sep 17 00:00:00 2001 From: EmilioCorigliano Date: Fri, 19 Jun 2026 18:53:53 +0200 Subject: [PATCH 11/11] fix(EDDI): fixed isLocalValueInitializedBefore function --- passes/EDDI.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/passes/EDDI.cpp b/passes/EDDI.cpp index 9fdb104..cffda60 100755 --- a/passes/EDDI.cpp +++ b/passes/EDDI.cpp @@ -847,7 +847,7 @@ void EDDI::comparePtrs(std::vector *CmpInstructions, Value &V1, Value & bool isLocalValueInitializedBefore(Instruction *AI, Instruction *At) { - + assert(AI->getParent()->getParent() == At->getParent()->getParent() && "Alloca and Instruction not in the same function!"); std::unordered_set storeInsts; @@ -907,6 +907,11 @@ bool isLocalValueInitializedBefore(Instruction *AI, Instruction *At) { if(isa(I) && storeInsts.find(cast(I)) != storeInsts.end()) { break; } + + // return false if we don't have a next node before encountering a store + if(I->getNextNode() == nullptr) { + return false; + } } while(I = I->getNextNode()); }