forked from OSchip/llvm-project
[Alignment][NFC] Value::getPointerAlignment returns MaybeAlign
Summary: This is patch is part of a series to introduce an Alignment type. See this thread for context: http://lists.llvm.org/pipermail/llvm-dev/2019-July/133851.html See this patch for the introduction of the type: https://reviews.llvm.org/D64790 Reviewers: courbet, jdoerfert Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D68398 llvm-svn: 374889
This commit is contained in:
parent
86d0f8b148
commit
bae629b966
|
@ -17,6 +17,7 @@
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/iterator_range.h"
|
#include "llvm/ADT/iterator_range.h"
|
||||||
#include "llvm/IR/Use.h"
|
#include "llvm/IR/Use.h"
|
||||||
|
#include "llvm/Support/Alignment.h"
|
||||||
#include "llvm/Support/CBindingWrapping.h"
|
#include "llvm/Support/CBindingWrapping.h"
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
@ -631,7 +632,7 @@ public:
|
||||||
///
|
///
|
||||||
/// Returns an alignment which is either specified explicitly, e.g. via
|
/// Returns an alignment which is either specified explicitly, e.g. via
|
||||||
/// align attribute of a function argument, or guaranteed by DataLayout.
|
/// align attribute of a function argument, or guaranteed by DataLayout.
|
||||||
unsigned getPointerAlignment(const DataLayout &DL) const;
|
MaybeAlign getPointerAlignment(const DataLayout &DL) const;
|
||||||
|
|
||||||
/// Translate PHI node to its predecessor from the given basic block.
|
/// Translate PHI node to its predecessor from the given basic block.
|
||||||
///
|
///
|
||||||
|
|
|
@ -27,21 +27,24 @@
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
static bool isAligned(const Value *Base, const APInt &Offset, unsigned Align,
|
static MaybeAlign getBaseAlign(const Value *Base, const DataLayout &DL) {
|
||||||
const DataLayout &DL) {
|
if (const MaybeAlign PA = Base->getPointerAlignment(DL))
|
||||||
APInt BaseAlign(Offset.getBitWidth(), Base->getPointerAlignment(DL));
|
return *PA;
|
||||||
|
Type *const Ty = Base->getType()->getPointerElementType();
|
||||||
if (!BaseAlign) {
|
|
||||||
Type *Ty = Base->getType()->getPointerElementType();
|
|
||||||
if (!Ty->isSized())
|
if (!Ty->isSized())
|
||||||
return false;
|
return None;
|
||||||
BaseAlign = DL.getABITypeAlignment(Ty);
|
return Align(DL.getABITypeAlignment(Ty));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isAligned(const Value *Base, const APInt &Offset, Align Alignment,
|
||||||
|
const DataLayout &DL) {
|
||||||
|
if (MaybeAlign BA = getBaseAlign(Base, DL)) {
|
||||||
|
const APInt APBaseAlign(Offset.getBitWidth(), BA->value());
|
||||||
|
const APInt APAlign(Offset.getBitWidth(), Alignment.value());
|
||||||
|
assert(APAlign.isPowerOf2() && "must be a power of 2!");
|
||||||
|
return APBaseAlign.uge(APAlign) && !(Offset & (APAlign - 1));
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
APInt Alignment(Offset.getBitWidth(), Align);
|
|
||||||
|
|
||||||
assert(Alignment.isPowerOf2() && "must be a power of 2!");
|
|
||||||
return BaseAlign.uge(Alignment) && !(Offset & (Alignment-1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test if V is always a pointer to allocated and suitably aligned memory for
|
/// Test if V is always a pointer to allocated and suitably aligned memory for
|
||||||
|
@ -73,7 +76,7 @@ static bool isDereferenceableAndAlignedPointer(
|
||||||
Type *Ty = V->getType();
|
Type *Ty = V->getType();
|
||||||
assert(Ty->isSized() && "must be sized");
|
assert(Ty->isSized() && "must be sized");
|
||||||
APInt Offset(DL.getTypeStoreSizeInBits(Ty), 0);
|
APInt Offset(DL.getTypeStoreSizeInBits(Ty), 0);
|
||||||
return isAligned(V, Offset, Align, DL);
|
return isAligned(V, Offset, llvm::Align(Align), DL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For GEPs, determine if the indexing lands within the allocated object.
|
// For GEPs, determine if the indexing lands within the allocated object.
|
||||||
|
|
|
@ -1721,9 +1721,9 @@ void computeKnownBits(const Value *V, KnownBits &Known, unsigned Depth,
|
||||||
|
|
||||||
// Aligned pointers have trailing zeros - refine Known.Zero set
|
// Aligned pointers have trailing zeros - refine Known.Zero set
|
||||||
if (V->getType()->isPointerTy()) {
|
if (V->getType()->isPointerTy()) {
|
||||||
unsigned Align = V->getPointerAlignment(Q.DL);
|
const MaybeAlign Align = V->getPointerAlignment(Q.DL);
|
||||||
if (Align)
|
if (Align)
|
||||||
Known.Zero.setLowBits(countTrailingZeros(Align));
|
Known.Zero.setLowBits(countTrailingZeros(Align->value()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// computeKnownBitsFromAssume strictly refines Known.
|
// computeKnownBitsFromAssume strictly refines Known.
|
||||||
|
|
|
@ -1122,7 +1122,7 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
|
||||||
isa<GlobalValue>(CE1->getOperand(0))) {
|
isa<GlobalValue>(CE1->getOperand(0))) {
|
||||||
GlobalValue *GV = cast<GlobalValue>(CE1->getOperand(0));
|
GlobalValue *GV = cast<GlobalValue>(CE1->getOperand(0));
|
||||||
|
|
||||||
unsigned GVAlign;
|
MaybeAlign GVAlign;
|
||||||
|
|
||||||
if (Module *TheModule = GV->getParent()) {
|
if (Module *TheModule = GV->getParent()) {
|
||||||
GVAlign = GV->getPointerAlignment(TheModule->getDataLayout());
|
GVAlign = GV->getPointerAlignment(TheModule->getDataLayout());
|
||||||
|
@ -1136,19 +1136,19 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
|
||||||
// increased code size (see https://reviews.llvm.org/D55115)
|
// increased code size (see https://reviews.llvm.org/D55115)
|
||||||
// FIXME: This code should be deleted once existing targets have
|
// FIXME: This code should be deleted once existing targets have
|
||||||
// appropriate defaults
|
// appropriate defaults
|
||||||
if (GVAlign == 0U && isa<Function>(GV))
|
if (!GVAlign && isa<Function>(GV))
|
||||||
GVAlign = 4U;
|
GVAlign = Align(4);
|
||||||
} else if (isa<Function>(GV)) {
|
} else if (isa<Function>(GV)) {
|
||||||
// Without a datalayout we have to assume the worst case: that the
|
// Without a datalayout we have to assume the worst case: that the
|
||||||
// function pointer isn't aligned at all.
|
// function pointer isn't aligned at all.
|
||||||
GVAlign = 0U;
|
GVAlign = llvm::None;
|
||||||
} else {
|
} else {
|
||||||
GVAlign = GV->getAlignment();
|
GVAlign = MaybeAlign(GV->getAlignment());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GVAlign > 1) {
|
if (GVAlign && *GVAlign > 1) {
|
||||||
unsigned DstWidth = CI2->getType()->getBitWidth();
|
unsigned DstWidth = CI2->getType()->getBitWidth();
|
||||||
unsigned SrcWidth = std::min(DstWidth, Log2_32(GVAlign));
|
unsigned SrcWidth = std::min(DstWidth, Log2(*GVAlign));
|
||||||
APInt BitsNotSet(APInt::getLowBitsSet(DstWidth, SrcWidth));
|
APInt BitsNotSet(APInt::getLowBitsSet(DstWidth, SrcWidth));
|
||||||
|
|
||||||
// If checking bits we know are clear, return zero.
|
// If checking bits we know are clear, return zero.
|
||||||
|
|
|
@ -671,22 +671,21 @@ uint64_t Value::getPointerDereferenceableBytes(const DataLayout &DL,
|
||||||
return DerefBytes;
|
return DerefBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Value::getPointerAlignment(const DataLayout &DL) const {
|
MaybeAlign Value::getPointerAlignment(const DataLayout &DL) const {
|
||||||
assert(getType()->isPointerTy() && "must be pointer");
|
assert(getType()->isPointerTy() && "must be pointer");
|
||||||
if (auto *GO = dyn_cast<GlobalObject>(this)) {
|
if (auto *GO = dyn_cast<GlobalObject>(this)) {
|
||||||
if (isa<Function>(GO)) {
|
if (isa<Function>(GO)) {
|
||||||
const MaybeAlign FunctionPtrAlign = DL.getFunctionPtrAlign();
|
const MaybeAlign FunctionPtrAlign = DL.getFunctionPtrAlign();
|
||||||
const unsigned Align = FunctionPtrAlign ? FunctionPtrAlign->value() : 0;
|
|
||||||
switch (DL.getFunctionPtrAlignType()) {
|
switch (DL.getFunctionPtrAlignType()) {
|
||||||
case DataLayout::FunctionPtrAlignType::Independent:
|
case DataLayout::FunctionPtrAlignType::Independent:
|
||||||
return Align;
|
return FunctionPtrAlign;
|
||||||
case DataLayout::FunctionPtrAlignType::MultipleOfFunctionAlign:
|
case DataLayout::FunctionPtrAlignType::MultipleOfFunctionAlign:
|
||||||
return std::max(Align, GO->getAlignment());
|
return std::max(FunctionPtrAlign, MaybeAlign(GO->getAlignment()));
|
||||||
}
|
}
|
||||||
llvm_unreachable("Unhandled FunctionPtrAlignType");
|
llvm_unreachable("Unhandled FunctionPtrAlignType");
|
||||||
}
|
}
|
||||||
const unsigned Align = GO->getAlignment();
|
const MaybeAlign Alignment(GO->getAlignment());
|
||||||
if (!Align) {
|
if (!Alignment) {
|
||||||
if (auto *GVar = dyn_cast<GlobalVariable>(GO)) {
|
if (auto *GVar = dyn_cast<GlobalVariable>(GO)) {
|
||||||
Type *ObjectType = GVar->getValueType();
|
Type *ObjectType = GVar->getValueType();
|
||||||
if (ObjectType->isSized()) {
|
if (ObjectType->isSized()) {
|
||||||
|
@ -694,42 +693,43 @@ unsigned Value::getPointerAlignment(const DataLayout &DL) const {
|
||||||
// it the preferred alignment. Otherwise, we have to assume that it
|
// it the preferred alignment. Otherwise, we have to assume that it
|
||||||
// may only have the minimum ABI alignment.
|
// may only have the minimum ABI alignment.
|
||||||
if (GVar->isStrongDefinitionForLinker())
|
if (GVar->isStrongDefinitionForLinker())
|
||||||
return DL.getPreferredAlignment(GVar);
|
return MaybeAlign(DL.getPreferredAlignment(GVar));
|
||||||
else
|
else
|
||||||
return DL.getABITypeAlignment(ObjectType);
|
return Align(DL.getABITypeAlignment(ObjectType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Align;
|
return Alignment;
|
||||||
} else if (const Argument *A = dyn_cast<Argument>(this)) {
|
} else if (const Argument *A = dyn_cast<Argument>(this)) {
|
||||||
const unsigned Align = A->getParamAlignment();
|
const MaybeAlign Alignment(A->getParamAlignment());
|
||||||
if (!Align && A->hasStructRetAttr()) {
|
if (!Alignment && A->hasStructRetAttr()) {
|
||||||
// An sret parameter has at least the ABI alignment of the return type.
|
// An sret parameter has at least the ABI alignment of the return type.
|
||||||
Type *EltTy = cast<PointerType>(A->getType())->getElementType();
|
Type *EltTy = cast<PointerType>(A->getType())->getElementType();
|
||||||
if (EltTy->isSized())
|
if (EltTy->isSized())
|
||||||
return DL.getABITypeAlignment(EltTy);
|
return Align(DL.getABITypeAlignment(EltTy));
|
||||||
}
|
}
|
||||||
return Align;
|
return Alignment;
|
||||||
} else if (const AllocaInst *AI = dyn_cast<AllocaInst>(this)) {
|
} else if (const AllocaInst *AI = dyn_cast<AllocaInst>(this)) {
|
||||||
const unsigned Align = AI->getAlignment();
|
const MaybeAlign Alignment(AI->getAlignment());
|
||||||
if (!Align) {
|
if (!Alignment) {
|
||||||
Type *AllocatedType = AI->getAllocatedType();
|
Type *AllocatedType = AI->getAllocatedType();
|
||||||
if (AllocatedType->isSized())
|
if (AllocatedType->isSized())
|
||||||
return DL.getPrefTypeAlignment(AllocatedType);
|
return MaybeAlign(DL.getPrefTypeAlignment(AllocatedType));
|
||||||
}
|
}
|
||||||
return Align;
|
return Alignment;
|
||||||
} else if (const auto *Call = dyn_cast<CallBase>(this)) {
|
} else if (const auto *Call = dyn_cast<CallBase>(this)) {
|
||||||
const unsigned Align = Call->getRetAlignment();
|
const MaybeAlign Alignment(Call->getRetAlignment());
|
||||||
if (!Align && Call->getCalledFunction())
|
if (!Alignment && Call->getCalledFunction())
|
||||||
return Call->getCalledFunction()->getAttributes().getRetAlignment();
|
return MaybeAlign(
|
||||||
return Align;
|
Call->getCalledFunction()->getAttributes().getRetAlignment());
|
||||||
|
return Alignment;
|
||||||
} else if (const LoadInst *LI = dyn_cast<LoadInst>(this)) {
|
} else if (const LoadInst *LI = dyn_cast<LoadInst>(this)) {
|
||||||
if (MDNode *MD = LI->getMetadata(LLVMContext::MD_align)) {
|
if (MDNode *MD = LI->getMetadata(LLVMContext::MD_align)) {
|
||||||
ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(0));
|
ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(0));
|
||||||
return CI->getLimitedValue();
|
return MaybeAlign(CI->getLimitedValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return llvm::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Value *Value::DoPHITranslation(const BasicBlock *CurBB,
|
const Value *Value::DoPHITranslation(const BasicBlock *CurBB,
|
||||||
|
|
|
@ -2203,8 +2203,8 @@ def : InstAlias<"prfm $Rt, [$Rn]", (PRFMui prfop:$Rt, GPR64sp:$Rn, 0)>;
|
||||||
def alignedglobal : PatLeaf<(iPTR iPTR:$label), [{
|
def alignedglobal : PatLeaf<(iPTR iPTR:$label), [{
|
||||||
if (auto *G = dyn_cast<GlobalAddressSDNode>(N)) {
|
if (auto *G = dyn_cast<GlobalAddressSDNode>(N)) {
|
||||||
const DataLayout &DL = MF->getDataLayout();
|
const DataLayout &DL = MF->getDataLayout();
|
||||||
unsigned Align = G->getGlobal()->getPointerAlignment(DL);
|
MaybeAlign Align = G->getGlobal()->getPointerAlignment(DL);
|
||||||
return Align >= 4 && G->getOffset() % 4 == 0;
|
return Align && *Align >= 4 && G->getOffset() % 4 == 0;
|
||||||
}
|
}
|
||||||
if (auto *C = dyn_cast<ConstantPoolSDNode>(N))
|
if (auto *C = dyn_cast<ConstantPoolSDNode>(N))
|
||||||
return C->getAlignment() >= 4 && C->getOffset() % 4 == 0;
|
return C->getAlignment() >= 4 && C->getOffset() % 4 == 0;
|
||||||
|
|
|
@ -2770,7 +2770,8 @@ struct AAAlignFloating : AAAlignImpl {
|
||||||
const auto &AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V));
|
const auto &AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V));
|
||||||
if (!Stripped && this == &AA) {
|
if (!Stripped && this == &AA) {
|
||||||
// Use only IR information if we did not strip anything.
|
// Use only IR information if we did not strip anything.
|
||||||
T.takeKnownMaximum(V.getPointerAlignment(DL));
|
const MaybeAlign PA = V.getPointerAlignment(DL);
|
||||||
|
T.takeKnownMaximum(PA ? PA->value() : 0);
|
||||||
T.indicatePessimisticFixpoint();
|
T.indicatePessimisticFixpoint();
|
||||||
} else {
|
} else {
|
||||||
// Use abstract attribute information.
|
// Use abstract attribute information.
|
||||||
|
|
|
@ -143,23 +143,23 @@ TEST(FunctionTest, GetPointerAlignment) {
|
||||||
FunctionType *FuncType(FunctionType::get(VoidType, false));
|
FunctionType *FuncType(FunctionType::get(VoidType, false));
|
||||||
std::unique_ptr<Function> Func(Function::Create(
|
std::unique_ptr<Function> Func(Function::Create(
|
||||||
FuncType, GlobalValue::ExternalLinkage));
|
FuncType, GlobalValue::ExternalLinkage));
|
||||||
EXPECT_EQ(0U, Func->getPointerAlignment(DataLayout("")));
|
EXPECT_EQ(MaybeAlign(), Func->getPointerAlignment(DataLayout("")));
|
||||||
EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fi8")));
|
EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("Fi8")));
|
||||||
EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fn8")));
|
EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("Fn8")));
|
||||||
EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fi16")));
|
EXPECT_EQ(Align(2), Func->getPointerAlignment(DataLayout("Fi16")));
|
||||||
EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fn16")));
|
EXPECT_EQ(Align(2), Func->getPointerAlignment(DataLayout("Fn16")));
|
||||||
EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fi32")));
|
EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fi32")));
|
||||||
EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn32")));
|
EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn32")));
|
||||||
|
|
||||||
Func->setAlignment(Align(4));
|
Func->setAlignment(Align(4));
|
||||||
|
|
||||||
EXPECT_EQ(0U, Func->getPointerAlignment(DataLayout("")));
|
EXPECT_EQ(MaybeAlign(), Func->getPointerAlignment(DataLayout("")));
|
||||||
EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fi8")));
|
EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("Fi8")));
|
||||||
EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn8")));
|
EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn8")));
|
||||||
EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fi16")));
|
EXPECT_EQ(Align(2), Func->getPointerAlignment(DataLayout("Fi16")));
|
||||||
EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn16")));
|
EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn16")));
|
||||||
EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fi32")));
|
EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fi32")));
|
||||||
EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn32")));
|
EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn32")));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace
|
} // end namespace
|
||||||
|
|
Loading…
Reference in New Issue