llvm-project/llvm/lib/CodeGen/LibcallLoweringInfo.cpp
Matt Arsenault 04c81a9973
CodeGen: Add LibcallLoweringInfo analysis pass (#168622)
The libcall lowering decisions should be program dependent,
depending on the current module's RuntimeLibcallInfo. We need
another related analysis derived from that plus the current
function's subtarget to provide concrete lowering decisions.

This takes on a somewhat unusual form. It's a Module analysis,
with a lookup keyed on the subtarget. This is a separate module
analysis from RuntimeLibraryAnalysis to avoid that depending on
codegen. It's not a function pass to avoid depending on any
particular function, to avoid repeated subtarget map lookups in
most of the use passes, and to avoid any recomputation in the
common case of one subtarget (and keeps it reusable across
repeated compilations).

This also switches ExpandFp and PreISelIntrinsicLowering as
a sample function and module pass. Note this is not yet wired
up to SelectionDAG, which is still using the LibcallLoweringInfo
constructed inside of TargetLowering.
2025-12-03 22:00:12 +01:00

73 lines
2.6 KiB
C++

//===- LibcallLoweringInfo.cpp - Interface for runtime libcalls -----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/LibcallLoweringInfo.h"
#include "llvm/Analysis/RuntimeLibcallInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/InitializePasses.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
LibcallLoweringInfo::LibcallLoweringInfo(
const RTLIB::RuntimeLibcallsInfo &RTLCI,
const TargetSubtargetInfo &Subtarget)
: RTLCI(RTLCI) {
// TODO: This should be generated with lowering predicates, and assert the
// call is available.
for (RTLIB::LibcallImpl Impl : RTLIB::libcall_impls()) {
if (RTLCI.isAvailable(Impl)) {
RTLIB::Libcall LC = RTLIB::RuntimeLibcallsInfo::getLibcallFromImpl(Impl);
// FIXME: Hack, assume the first available libcall wins.
if (LibcallImpls[LC] == RTLIB::Unsupported)
LibcallImpls[LC] = Impl;
}
}
Subtarget.initLibcallLoweringInfo(*this);
}
AnalysisKey LibcallLoweringModuleAnalysis::Key;
bool LibcallLoweringModuleAnalysisResult::invalidate(
Module &, const PreservedAnalyses &PA,
ModuleAnalysisManager::Invalidator &) {
// Passes that change the runtime libcall set must explicitly invalidate this
// pass.
auto PAC = PA.getChecker<LibcallLoweringModuleAnalysis>();
return !PAC.preservedWhenStateless();
}
LibcallLoweringModuleAnalysisResult
LibcallLoweringModuleAnalysis::run(Module &M, ModuleAnalysisManager &MAM) {
LibcallLoweringMap.init(&MAM.getResult<RuntimeLibraryAnalysis>(M));
return LibcallLoweringMap;
}
INITIALIZE_PASS_BEGIN(LibcallLoweringInfoWrapper, "libcall-lowering-info",
"Library Function Lowering Analysis", false, true)
INITIALIZE_PASS_DEPENDENCY(RuntimeLibraryInfoWrapper)
INITIALIZE_PASS_END(LibcallLoweringInfoWrapper, "libcall-lowering-info",
"Library Function Lowering Analysis", false, true)
char LibcallLoweringInfoWrapper::ID = 0;
LibcallLoweringInfoWrapper::LibcallLoweringInfoWrapper() : ImmutablePass(ID) {}
bool LibcallLoweringInfoWrapper::doInitialization(Module &M) {
Result.init(&getAnalysis<RuntimeLibraryInfoWrapper>().getRTLCI(M));
return false;
}
void LibcallLoweringInfoWrapper::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<RuntimeLibraryInfoWrapper>();
AU.setPreservesAll();
}
void LibcallLoweringInfoWrapper::releaseMemory() { Result.clear(); }