Skip to content

Commit 4de537f

Browse files
authored
[libspirv] Clone remangled functions on name clash (private default AS) (#20889)
When the target’s default address space is private (e.g., SPIR), simultaneous pointer address space remangling and long -> long long remangling can cause clone name collisions, preventing the remangled function from being cloned. Example: _Z1fPm -> remangled to _Z1fPU3AS0y; remangler clones back to _Z1fPm to preserve the original. Later, _Z1fPU3AS4m -> remangled to _Z1fPy; we need to clone _Z1fPy to _Z1fPm, but _Z1fPm already exists. Fix: Append a temporary suffix to avoid clashes (e.g., _Z1fPm$TmpSuffix). Remove the suffix in post-processing, replacing the old _Z1fPm (clone of _Z1fPU3AS0y) with the new remangled implementation. llvm-diff shows no change for targets whose default AS isn't private: remangled-l64-signed_char.libspirv-nvptx64-nvidia-cuda.bc and remangled-l64-unsigned_char.libspirv-amdgcn-amd-amdhsa.bc.
1 parent e4cbcf5 commit 4de537f

File tree

1 file changed

+37
-28
lines changed

1 file changed

+37
-28
lines changed

libclc/utils/libclc-remangler/LibclcRemangler.cpp

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,8 @@ class LibCLCRemangler : public ASTConsumer {
857857
if (RemangledName == OriginalName)
858858
return true;
859859

860-
StringRef CloneName, CloneeName;
860+
std::string CloneName;
861+
StringRef CloneeName;
861862
if (CloneeTypeReplacement) {
862863
CloneName = OriginalName;
863864
CloneeName = RemangledName;
@@ -866,19 +867,26 @@ class LibCLCRemangler : public ASTConsumer {
866867
CloneeName = OriginalName;
867868
}
868869

869-
// If the clone name already exists in the module then we have to assume it
870-
// does the right thing already. We're only going to end up creating a copy
871-
// of that function without external users being able to reach it.
870+
// If the clone name is an original function in the module, it may later be
871+
// remangled and must be replaced. Example (TargetDefaultAddrSpace != 0):
872+
// _Z1fPm -> remangled to _Z1fPU3AS0y; remangler clones back to _Z1fPm to
873+
// preserve the original. Later, _Z1fPU3AS4m -> remangled to _Z1fPy; we need
874+
// to clone _Z1fPy to _Z1fPm, but it already exists. To avoid a clash,
875+
// append a temporary suffix (e.g., _Z1fPm$TmpSuffix). The suffix is removed
876+
// in post-processing, and the old Z1fPm (clone of _Z1fPU3AS0y) is replaced
877+
// by Z1fPm$TmpSuffix.
872878
if (M->getFunction(CloneName)) {
873-
return true;
879+
CloneName += TmpSuffix;
880+
if (M->getFunction(CloneName))
881+
return true;
874882
}
875883

876884
if (Function *Clonee = M->getFunction(CloneeName)) {
877885
ValueToValueMapTy Dummy;
878886
Function *NewF = CloneFunction(Clonee, Dummy);
879-
NewF->setName(CloneName.str());
887+
NewF->setName(CloneName);
880888
} else if (Verbose) {
881-
errs() << "Could not create copy " << CloneName.data() << " : missing "
889+
errs() << "Could not create copy " << CloneName << " : missing "
882890
<< CloneeName.data() << '\n';
883891
}
884892
return true;
@@ -910,6 +918,7 @@ class LibCLCRemangler : public ASTConsumer {
910918
return false;
911919

912920
if (RemangledName != MangledName) {
921+
RenamedFunctions.insert(MangledName);
913922
if (Verbose || TestRun) {
914923
errs() << "Mangling changed:"
915924
<< "\n"
@@ -927,13 +936,12 @@ class LibCLCRemangler : public ASTConsumer {
927936
// RemangledName may already exist. For instance, the function name
928937
// _Z1fPU3AS4i would be remangled to _Z1fPi, which is a valid variant and
929938
// might already be present. Since we cannot alter the name of an existing
930-
// variant function that may not have been processed yet, we append a
931-
// temporary suffix to RemangledName to prevent a name clash. This
932-
// temporary suffix will be removed during the post-processing stage, once
933-
// all functions have been handled.
934-
if (ASTCtx->getTargetAddressSpace(LangAS::Default) != 0)
935-
if (M->getFunction(RemangledName))
936-
RemangledName += TmpSuffix;
939+
// variant function that may not have been processed yet (it will become a
940+
// clone of the original function), we append a temporary suffix to
941+
// RemangledName to prevent a name clash. This temporary suffix will be
942+
// removed eventually and Old _Z1fPi will be replaced by _Z1fPi$TmpSuffix.
943+
if (M->getFunction(RemangledName))
944+
RemangledName += TmpSuffix;
937945

938946
// If the remangled name already exists in the module then we have to
939947
// assume it does the right thing already. We're only going to end up
@@ -954,28 +962,27 @@ class LibCLCRemangler : public ASTConsumer {
954962
return true;
955963
}
956964

957-
// When TargetDefaultAddrSpace is not 0, post-processing is necessary after
958-
// all functions have been processed. During this stage, the temporary suffix
959-
// is removed from the remangled name.
965+
// The temporary suffix is removed from the remangled or cloned name.
960966
void postProcessRemoveTmpSuffix(llvm::Module *M) {
961967
if (TestRun)
962968
return;
963-
for (auto &F : *M) {
969+
for (auto &F : make_early_inc_range(*M)) {
964970
StringRef Name = F.getName();
965971
if (!Name.consume_back(TmpSuffix))
966972
continue;
967-
// If a name clash persists, the old function is renamed. For example,
968-
// _Z1fPi is remangled to _Z1fPU3AS0i, and the remangler clones
969-
// _Z1fPU3AS0i to _Z1fPi to preserve the original implementation.
970-
// Subsequently, _Z1fPU3AS4i is remangled to _Z1fPi, and the remangled
971-
// name is temporarily changed to _Z1fPi$TmpSuffix. When attempting to
972-
// revert _Z1fPi$TmpSuffix back to _Z1fPi, a clash occurs because _Z1fPi
973-
// still exists. Delete the old _Z1fPi which is no longer useful.
974973
if (auto *Func = M->getFunction(Name)) {
975-
Func->replaceAllUsesWith(ConstantPointerNull::get(Func->getType()));
976-
Func->eraseFromParent();
974+
if (RenamedFunctions.count(Name.str())) {
975+
// Drop unuseful clone of the original or remangled function.
976+
Func->replaceAllUsesWith(ConstantPointerNull::get(Func->getType()));
977+
Func->eraseFromParent();
978+
} else {
979+
// Name doesn't exist in the original module. Drop unuseful clone of
980+
// remangled function.
981+
F.eraseFromParent();
982+
continue;
983+
}
977984
}
978-
// Complete the mangling process from _Z1fPU3AS4i to _Z1fPi.
985+
// Complete the mangling process, e.g. from _Z1fPU3AS4i to _Z1fPi.
979986
F.setName(Name);
980987
}
981988
}
@@ -1032,6 +1039,8 @@ class LibCLCRemangler : public ASTConsumer {
10321039
ASTContext *ASTCtx;
10331040
LLVMContext LLVMCtx;
10341041
TargetTypeReplacements Replacements;
1042+
// Functions in the input module that have been renamed due to remangling.
1043+
std::unordered_set<std::string> RenamedFunctions;
10351044
};
10361045

10371046
class LibCLCRemanglerActionFactory {

0 commit comments

Comments
 (0)