Files
gps/tools/local/circt/include/llvm/SandboxIR/Utils.h
T
2026-07-12 11:01:51 +03:00

139 lines
5.3 KiB
C++

//===- Utils.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
//
//===----------------------------------------------------------------------===//
//
// Collector for SandboxIR related convenience functions that don't belong in
// other classes.
#ifndef LLVM_SANDBOXIR_UTILS_H
#define LLVM_SANDBOXIR_UTILS_H
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/LoopAccessAnalysis.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Verifier.h"
#include "llvm/SandboxIR/Function.h"
#include "llvm/SandboxIR/Instruction.h"
#include <optional>
namespace llvm::sandboxir {
class Utils {
public:
/// \Returns the expected type of \p Value V. For most Values this is
/// equivalent to getType, but for stores returns the stored type, rather
/// than void, and for ReturnInsts returns the returned type.
static Type *getExpectedType(const Value *V) {
if (auto *I = dyn_cast<Instruction>(V)) {
// A Return's value operand can be null if it returns void.
if (auto *RI = dyn_cast<ReturnInst>(I)) {
if (RI->getReturnValue() == nullptr)
return RI->getType();
}
return getExpectedValue(I)->getType();
}
return V->getType();
}
/// \Returns the expected Value for this instruction. For most instructions,
/// this is the instruction itself, but for stores returns the stored
/// operand, and for ReturnInstructions returns the returned value.
static Value *getExpectedValue(const Instruction *I) {
if (auto *SI = dyn_cast<StoreInst>(I))
return SI->getValueOperand();
if (auto *RI = dyn_cast<ReturnInst>(I))
return RI->getReturnValue();
return const_cast<Instruction *>(I);
}
/// \Returns the base Value for load or store instruction \p LSI.
template <typename LoadOrStoreT>
static Value *getMemInstructionBase(const LoadOrStoreT *LSI) {
static_assert(std::is_same_v<LoadOrStoreT, LoadInst> ||
std::is_same_v<LoadOrStoreT, StoreInst>,
"Expected sandboxir::Load or sandboxir::Store!");
return LSI->Ctx.getOrCreateValue(
getUnderlyingObject(LSI->getPointerOperand()->Val));
}
/// \Returns the number of bits of \p Ty.
static unsigned getNumBits(Type *Ty, const DataLayout &DL) {
return DL.getTypeSizeInBits(Ty->LLVMTy);
}
/// \Returns the number of bits required to represent the operands or return
/// value of \p V in \p DL.
static unsigned getNumBits(Value *V, const DataLayout &DL) {
Type *Ty = getExpectedType(V);
return getNumBits(Ty, DL);
}
/// \Returns the number of bits required to represent the operands or
/// return value of \p I.
static unsigned getNumBits(Instruction *I) {
return I->getDataLayout().getTypeSizeInBits(getExpectedType(I)->LLVMTy);
}
/// Equivalent to MemoryLocation::getOrNone(I).
static std::optional<llvm::MemoryLocation>
memoryLocationGetOrNone(const Instruction *I) {
return llvm::MemoryLocation::getOrNone(cast<llvm::Instruction>(I->Val));
}
/// \Returns the gap between the memory locations accessed by \p I0 and
/// \p I1 in bytes.
template <typename LoadOrStoreT>
static std::optional<int> getPointerDiffInBytes(LoadOrStoreT *I0,
LoadOrStoreT *I1,
ScalarEvolution &SE) {
static_assert(std::is_same_v<LoadOrStoreT, LoadInst> ||
std::is_same_v<LoadOrStoreT, StoreInst>,
"Expected sandboxir::Load or sandboxir::Store!");
llvm::Value *Opnd0 = I0->getPointerOperand()->Val;
llvm::Value *Opnd1 = I1->getPointerOperand()->Val;
llvm::Value *Ptr0 = getUnderlyingObject(Opnd0);
llvm::Value *Ptr1 = getUnderlyingObject(Opnd1);
if (Ptr0 != Ptr1)
return false;
llvm::Type *ElemTy = llvm::Type::getInt8Ty(SE.getContext());
return getPointersDiff(ElemTy, Opnd0, ElemTy, Opnd1, I0->getDataLayout(),
SE, /*StrictCheck=*/false, /*CheckType=*/false);
}
/// \Returns true if \p I0 accesses a memory location lower than \p I1.
/// Returns false if the difference cannot be determined, if the memory
/// locations are equal, or if I1 accesses a memory location greater than I0.
template <typename LoadOrStoreT>
static bool atLowerAddress(LoadOrStoreT *I0, LoadOrStoreT *I1,
ScalarEvolution &SE) {
auto Diff = getPointerDiffInBytes(I0, I1, SE);
if (!Diff)
return false;
return *Diff > 0;
}
/// Equivalent to BatchAA::getModRefInfo().
static ModRefInfo
aliasAnalysisGetModRefInfo(BatchAAResults &BatchAA, const Instruction *I,
const std::optional<MemoryLocation> &OptLoc) {
return BatchAA.getModRefInfo(cast<llvm::Instruction>(I->Val), OptLoc);
}
/// Equivalent to llvm::verifyFunction().
/// \Returns true if the IR is broken.
static bool verifyFunction(const Function *F, raw_ostream &OS) {
const auto &LLVMF = *cast<llvm::Function>(F->Val);
return llvm::verifyFunction(LLVMF, &OS);
}
};
} // namespace llvm::sandboxir
#endif // LLVM_SANDBOXIR_UTILS_H