blob: 4a6ed18714c2c972d5da52418fbb073ce203456e [file] [edit]
//===- llvm/BundleAttributes.cpp - LLVM Bundle Attributes -------*- 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
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/BundleAttributes.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/IR/Constants.h"
using namespace llvm;
StringRef llvm::getNameFromBundleAttr(BundleAttr BA) {
switch (BA) {
#define ATTR(Name, Str) \
case BundleAttr::Name: \
return #Str;
#include "llvm/IR/BundleAttributes.def"
case BundleAttr::None:
return "none";
}
llvm_unreachable("unknonwn bundle attribute");
}
BundleAttr llvm::getBundleAttrFromID(uint32_t ID) {
switch (ID) {
#define ATTR(Name, Str) \
case LLVMContext::OB_##Name: \
return BundleAttr::Name;
#include "llvm/IR/BundleAttributes.def"
default:
return BundleAttr::None;
}
}
AssumeAlignInfo llvm::getAssumeAlignInfo(OperandBundleUse OBU) {
assert(OBU.getTagID() == LLVMContext::OB_Align && OBU.Inputs.size() >= 2 &&
OBU.Inputs.size() <= 3);
AssumeAlignInfo Ret{OBU.Inputs[0], OBU.Inputs[1], nullptr, std::nullopt,
std::nullopt};
if (auto *Align = dyn_cast<ConstantInt>(OBU.Inputs[1]))
Ret.AlignmentVal = Align->getZExtValue();
if (OBU.Inputs.size() == 3) {
Ret.Offset = &OBU.Inputs[2];
if (auto *Offset = dyn_cast<ConstantInt>(OBU.Inputs[2]))
Ret.OffsetVal = Offset->getZExtValue();
} else {
Ret.OffsetVal = 0;
}
return Ret;
}
AssumeNoUndefInfo llvm::getAssumeNoUndefInfo(OperandBundleUse OBU) {
assert(OBU.getTagID() == LLVMContext::OB_NoUndef && OBU.Inputs.size() == 1);
return {OBU.Inputs[0]};
}
AssumeSeparateStorageInfo
llvm::getAssumeSeparateStorageInfo(OperandBundleUse OBU) {
assert(OBU.getTagID() == LLVMContext::OB_SeparateStorage &&
OBU.Inputs.size() == 2);
return {OBU.Inputs[0], OBU.Inputs[1]};
}
AssumeNonNullInfo llvm::getAssumeNonNullInfo(OperandBundleUse OBU) {
assert(OBU.getTagID() == LLVMContext::OB_NonNull && OBU.Inputs.size() == 1);
return {OBU.Inputs[0]};
}
AssumeDereferenceableInfo
llvm::getAssumeDereferenceableInfo(OperandBundleUse OBU) {
assert(OBU.getTagID() == LLVMContext::OB_Dereferenceable &&
OBU.Inputs.size() == 2);
AssumeDereferenceableInfo Ret{OBU.Inputs[0], OBU.Inputs[1], std::nullopt};
if (auto *Size = dyn_cast<ConstantInt>(OBU.Inputs[1]))
Ret.CountVal = Size->getZExtValue();
return Ret;
}
bool llvm::assumeBundleImpliesNonNull(const Value *Val, const Function *Context,
OperandBundleUse OBU) {
switch (getBundleAttrFromOBU(OBU)) {
case BundleAttr::Align: {
auto [Ptr, _, _2, Alignment, Offset] = getAssumeAlignInfo(OBU);
return Ptr == Val && Alignment && Offset && isPowerOf2_64(*Alignment) &&
*Offset % *Alignment != 0;
}
case BundleAttr::Dereferenceable: {
auto [Ptr, _, Count] = getAssumeDereferenceableInfo(OBU);
return Ptr == Val && Count && *Count != 0 &&
!NullPointerIsDefined(Context,
Val->getType()->getPointerAddressSpace());
}
case BundleAttr::NonNull:
return getAssumeNonNullInfo(OBU).Ptr == Val;
default:
return false;
}
}