Files
clang-p2996/llvm/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h
Andrew Rogers 7e4bdb427f [llvm] annotate interfaces in llvm/CGData and llvm/CodeGen for DLL export (#140823)
## Purpose

This patch is one in a series of code-mods that annotate LLVM’s public
interface for export. This patch annotates the `llvm/CGData` and
`llvm/CodeGen` libraries. These annotations currently have no meaningful
impact on the LLVM build; however, they are a prerequisite to support an
LLVM Windows DLL (shared library) build.

## Background

This effort is tracked in #109483. Additional context is provided in
[this
discourse](https://discourse.llvm.org/t/psa-annotating-llvm-public-interface/85307),
and documentation for `LLVM_ABI` and related annotations is found in the
LLVM repo
[here](https://github.com/llvm/llvm-project/blob/main/llvm/docs/InterfaceExportAnnotations.rst).

The bulk of these changes were generated automatically using the
[Interface Definition Scanner (IDS)](https://github.com/compnerd/ids)
tool, followed formatting with `git clang-format`.

The following manual adjustments were also applied after running IDS on
Linux:
- Add `LLVM_ABI` to a subset of private class methods and fields that
require export
- Add `LLVM_TEMPLATE_ABI` and `LLVM_EXPORT_TEMPLATE` to exported
instantiated templates defined via X-macro
- Add `LLVM_ABI_FRIEND` to friend member functions declared with
`LLVM_ABI`
- Explicitly make classes non-copyable where needed to due IDS adding
LLVM_ABI at the class level
- Add `#include "llvm/Support/Compiler.h"` to files where it was not
auto-added by IDS due to no pre-existing block of include statements.
- Add `LLVM_ABI` to a small number of symbols that require export but
are not declared in headers

## Validation

Local builds and tests to validate cross-platform compatibility. This
included llvm, clang, and lldb on the following configurations:

- Windows with MSVC
- Windows with Clang
- Linux with GCC
- Linux with Clang
- Darwin with Clang
2025-05-28 10:19:28 -07:00

117 lines
4.8 KiB
C++

//===-- llvm/CodeGen/GlobalISel/CSEMIRBuilder.h --*- C++ -*-==//
//
// 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
//
//===----------------------------------------------------------------------===//
/// \file
/// This file implements a version of MachineIRBuilder which CSEs insts within
/// a MachineBasicBlock.
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_GLOBALISEL_CSEMIRBUILDER_H
#define LLVM_CODEGEN_GLOBALISEL_CSEMIRBUILDER_H
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
class GISelInstProfileBuilder;
/// Defines a builder that does CSE of MachineInstructions using GISelCSEInfo.
/// Eg usage.
///
/// \code
/// GISelCSEInfo *Info =
/// &getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEInfo();
/// CSEMIRBuilder CB(Builder.getState());
/// CB.setCSEInfo(Info);
/// auto A = CB.buildConstant(s32, 42);
/// auto B = CB.buildConstant(s32, 42);
/// assert(A == B);
/// unsigned CReg = MRI.createGenericVirtualRegister(s32);
/// auto C = CB.buildConstant(CReg, 42);
/// assert(C->getOpcode() == TargetOpcode::COPY);
/// \endcode
///
/// Explicitly passing in a register would materialize a copy if possible.
/// CSEMIRBuilder also does trivial constant folding for binary ops.
class LLVM_ABI CSEMIRBuilder : public MachineIRBuilder {
/// Returns true if A dominates B (within the same basic block).
/// Both iterators must be in the same basic block.
//
// TODO: Another approach for checking dominance is having two iterators and
// making them go towards each other until they meet or reach begin/end. Which
// approach is better? Should this even change dynamically? For G_CONSTANTS
// most of which will be at the top of the BB, the top down approach would be
// a better choice. Does IRTranslator placing constants at the beginning still
// make sense? Should this change based on Opcode?
bool dominates(MachineBasicBlock::const_iterator A,
MachineBasicBlock::const_iterator B) const;
/// For given ID, find a machineinstr in the CSE Map. If found, check if it
/// dominates the current insertion point and if not, move it just before the
/// current insertion point and return it. If not found, return Null
/// MachineInstrBuilder.
MachineInstrBuilder getDominatingInstrForID(FoldingSetNodeID &ID,
void *&NodeInsertPos);
/// Simple check if we can CSE (we have the CSEInfo) or if this Opcode is
/// safe to CSE.
bool canPerformCSEForOpc(unsigned Opc) const;
void profileDstOp(const DstOp &Op, GISelInstProfileBuilder &B) const;
void profileDstOps(ArrayRef<DstOp> Ops, GISelInstProfileBuilder &B) const {
for (const DstOp &Op : Ops)
profileDstOp(Op, B);
}
void profileSrcOp(const SrcOp &Op, GISelInstProfileBuilder &B) const;
void profileSrcOps(ArrayRef<SrcOp> Ops, GISelInstProfileBuilder &B) const {
for (const SrcOp &Op : Ops)
profileSrcOp(Op, B);
}
void profileMBBOpcode(GISelInstProfileBuilder &B, unsigned Opc) const;
void profileEverything(unsigned Opc, ArrayRef<DstOp> DstOps,
ArrayRef<SrcOp> SrcOps, std::optional<unsigned> Flags,
GISelInstProfileBuilder &B) const;
// Takes a MachineInstrBuilder and inserts it into the CSEMap using the
// NodeInsertPos.
MachineInstrBuilder memoizeMI(MachineInstrBuilder MIB, void *NodeInsertPos);
// If we have can CSE an instruction, but still need to materialize to a VReg,
// we emit a copy from the CSE'd inst to the VReg.
MachineInstrBuilder generateCopiesIfRequired(ArrayRef<DstOp> DstOps,
MachineInstrBuilder &MIB);
// If we have can CSE an instruction, but still need to materialize to a VReg,
// check if we can generate copies. It's not possible to return a single MIB,
// while emitting copies to multiple vregs.
bool checkCopyToDefsPossible(ArrayRef<DstOp> DstOps);
public:
// Pull in base class constructors.
using MachineIRBuilder::MachineIRBuilder;
// Unhide buildInstr
MachineInstrBuilder
buildInstr(unsigned Opc, ArrayRef<DstOp> DstOps, ArrayRef<SrcOp> SrcOps,
std::optional<unsigned> Flag = std::nullopt) override;
// Bring in the other overload from the base class.
using MachineIRBuilder::buildConstant;
MachineInstrBuilder buildConstant(const DstOp &Res,
const ConstantInt &Val) override;
// Bring in the other overload from the base class.
using MachineIRBuilder::buildFConstant;
MachineInstrBuilder buildFConstant(const DstOp &Res,
const ConstantFP &Val) override;
};
} // namespace llvm
#endif