Skip to content

Commit

Permalink
icf: compare alloca position for testing equivalence
Browse files Browse the repository at this point in the history
This fixes an incorrect detection of identical code involving alloca
ordering.

Previously for allocas, we only checked if the allocated type, operands
and alignment were the same. However this doesn't take into account that
two identical alloca instructions at different relative points in the
function can not be taken for the same.

Fixed by adding a map that keeps track of allocas that take place at
relatively the same position, and using that map to check alloca
equivalence.
  • Loading branch information
Hyxogen authored and yuri91 committed Nov 3, 2023
1 parent 54b6ed0 commit f101b4e
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 2 deletions.
1 change: 1 addition & 0 deletions llvm/include/llvm/Cheerp/IdenticalCodeFolding.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class IdenticalCodeFolding
std::unordered_map<std::pair<const llvm::Function*, const llvm::Function*>, bool, pair_hash> functionEquivalence;
std::unordered_map<const llvm::Function*, bool> externalFunctionMapping;
std::vector<llvm::Function*> deleteList;
std::unordered_map<const llvm::AllocaInst*, const llvm::AllocaInst*> allocaPairs;
};

class HashAccumulator64 {
Expand Down
17 changes: 15 additions & 2 deletions llvm/lib/CheerpUtils/IdenticalCodeFolding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ bool IdenticalCodeFolding::equivalentFunction(const llvm::Function* A, const llv
llvm::errs() << "function A: " << A->getName() << '\n';
llvm::errs() << "function B: " << B->getName() << '\n';
#endif
// Clear up equivalent allocas of previous function
allocaPairs.clear();

// Do not fold wasm/asmjs with generic JS functions.
if (A->getSection() != StringRef("asmjs") || B->getSection() != StringRef("asmjs"))
Expand Down Expand Up @@ -232,9 +234,20 @@ bool IdenticalCodeFolding::equivalentInstruction(const llvm::Instruction* A, con
{
const AllocaInst* a = cast<AllocaInst>(A);
const AllocaInst* b = cast<AllocaInst>(B);
return CacheAndReturn(equivalentType(a->getAllocatedType(), b->getAllocatedType()) &&

auto it = allocaPairs.find(a);
if (it != allocaPairs.end() && it->second != b)
return CacheAndReturn(false);

const bool equivalent = equivalentType(a->getAllocatedType(), b->getAllocatedType()) &&
equivalentOperand(a->getArraySize(), b->getArraySize()) &&
a->getAlign() == b->getAlign());
a->getAlign() == b->getAlign();

if (equivalent) {
allocaPairs[a] = b;
allocaPairs[b] = a;
}
return CacheAndReturn(equivalent);
}
case Instruction::Unreachable:
{
Expand Down

0 comments on commit f101b4e

Please sign in to comment.