There are a few folds which don't depend on the offset of the alignment, but are nevertheless guarded on whether the offset is known. Run these folds unconditionally instead.
107 lines
3.5 KiB
C++
107 lines
3.5 KiB
C++
//===- 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;
|
|
}
|
|
}
|