From 98d66a7d31ea690d8e8e2c60330616fcda6c71e8 Mon Sep 17 00:00:00 2001 From: Hyxogen <8938732+Hyxogen@users.noreply.github.com> Date: Fri, 3 Nov 2023 11:04:31 +0100 Subject: [PATCH] icf: compare alloca position for testing equivalence 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. --- llvm/include/llvm/Cheerp/IdenticalCodeFolding.h | 1 + llvm/lib/CheerpUtils/IdenticalCodeFolding.cpp | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Cheerp/IdenticalCodeFolding.h b/llvm/include/llvm/Cheerp/IdenticalCodeFolding.h index 5f15e277f5ff..934bacd48be3 100644 --- a/llvm/include/llvm/Cheerp/IdenticalCodeFolding.h +++ b/llvm/include/llvm/Cheerp/IdenticalCodeFolding.h @@ -68,6 +68,7 @@ class IdenticalCodeFolding std::unordered_map, bool, pair_hash> functionEquivalence; std::unordered_map externalFunctionMapping; std::vector deleteList; + std::unordered_map allocaPairs; }; class HashAccumulator64 { diff --git a/llvm/lib/CheerpUtils/IdenticalCodeFolding.cpp b/llvm/lib/CheerpUtils/IdenticalCodeFolding.cpp index b0f682614c45..c1cb5b8fc22d 100644 --- a/llvm/lib/CheerpUtils/IdenticalCodeFolding.cpp +++ b/llvm/lib/CheerpUtils/IdenticalCodeFolding.cpp @@ -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")) @@ -232,9 +234,15 @@ bool IdenticalCodeFolding::equivalentInstruction(const llvm::Instruction* A, con { const AllocaInst* a = cast(A); const AllocaInst* b = cast(B); - return CacheAndReturn(equivalentType(a->getAllocatedType(), b->getAllocatedType()) && + if ((allocaPairs.count(a) && allocaPairs[a] != b) || (allocaPairs.count(b) && allocaPairs[b] != a)) + return 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; + return CacheAndReturn(equivalent); } case Instruction::Unreachable: {