#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Use.h"
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Casting.h"
#include <cassert>
///
/// Returns an alignment which is either specified explicitly, e.g. via
/// 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.
///
using namespace llvm;
-static bool isAligned(const Value *Base, const APInt &Offset, unsigned Align,
- const DataLayout &DL) {
- APInt BaseAlign(Offset.getBitWidth(), Base->getPointerAlignment(DL));
+static MaybeAlign getBaseAlign(const Value *Base, const DataLayout &DL) {
+ if (const MaybeAlign PA = Base->getPointerAlignment(DL))
+ return *PA;
+ Type *const Ty = Base->getType()->getPointerElementType();
+ if (!Ty->isSized())
+ return None;
+ return Align(DL.getABITypeAlignment(Ty));
+}
- if (!BaseAlign) {
- Type *Ty = Base->getType()->getPointerElementType();
- if (!Ty->isSized())
- return false;
- BaseAlign = 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));
}
-
- APInt Alignment(Offset.getBitWidth(), Align);
-
- assert(Alignment.isPowerOf2() && "must be a power of 2!");
- return BaseAlign.uge(Alignment) && !(Offset & (Alignment-1));
+ return false;
}
/// Test if V is always a pointer to allocated and suitably aligned memory for
Type *Ty = V->getType();
assert(Ty->isSized() && "must be sized");
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.
// Aligned pointers have trailing zeros - refine Known.Zero set
if (V->getType()->isPointerTy()) {
- unsigned Align = V->getPointerAlignment(Q.DL);
+ const MaybeAlign Align = V->getPointerAlignment(Q.DL);
if (Align)
- Known.Zero.setLowBits(countTrailingZeros(Align));
+ Known.Zero.setLowBits(countTrailingZeros(Align->value()));
}
// computeKnownBitsFromAssume strictly refines Known.
isa<GlobalValue>(CE1->getOperand(0))) {
GlobalValue *GV = cast<GlobalValue>(CE1->getOperand(0));
- unsigned GVAlign;
+ MaybeAlign GVAlign;
if (Module *TheModule = GV->getParent()) {
GVAlign = GV->getPointerAlignment(TheModule->getDataLayout());
// increased code size (see https://reviews.llvm.org/D55115)
// FIXME: This code should be deleted once existing targets have
// appropriate defaults
- if (GVAlign == 0U && isa<Function>(GV))
- GVAlign = 4U;
+ if (!GVAlign && isa<Function>(GV))
+ GVAlign = Align(4);
} else if (isa<Function>(GV)) {
// Without a datalayout we have to assume the worst case: that the
// function pointer isn't aligned at all.
- GVAlign = 0U;
+ GVAlign = llvm::None;
} else {
- GVAlign = GV->getAlignment();
+ GVAlign = MaybeAlign(GV->getAlignment());
}
- if (GVAlign > 1) {
+ if (GVAlign && *GVAlign > 1) {
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));
// If checking bits we know are clear, return zero.
return DerefBytes;
}
-unsigned Value::getPointerAlignment(const DataLayout &DL) const {
+MaybeAlign Value::getPointerAlignment(const DataLayout &DL) const {
assert(getType()->isPointerTy() && "must be pointer");
if (auto *GO = dyn_cast<GlobalObject>(this)) {
if (isa<Function>(GO)) {
const MaybeAlign FunctionPtrAlign = DL.getFunctionPtrAlign();
- const unsigned Align = FunctionPtrAlign ? FunctionPtrAlign->value() : 0;
switch (DL.getFunctionPtrAlignType()) {
case DataLayout::FunctionPtrAlignType::Independent:
- return Align;
+ return FunctionPtrAlign;
case DataLayout::FunctionPtrAlignType::MultipleOfFunctionAlign:
- return std::max(Align, GO->getAlignment());
+ return std::max(FunctionPtrAlign, MaybeAlign(GO->getAlignment()));
}
llvm_unreachable("Unhandled FunctionPtrAlignType");
}
- const unsigned Align = GO->getAlignment();
- if (!Align) {
+ const MaybeAlign Alignment(GO->getAlignment());
+ if (!Alignment) {
if (auto *GVar = dyn_cast<GlobalVariable>(GO)) {
Type *ObjectType = GVar->getValueType();
if (ObjectType->isSized()) {
// it the preferred alignment. Otherwise, we have to assume that it
// may only have the minimum ABI alignment.
if (GVar->isStrongDefinitionForLinker())
- return DL.getPreferredAlignment(GVar);
+ return MaybeAlign(DL.getPreferredAlignment(GVar));
else
- return DL.getABITypeAlignment(ObjectType);
+ return Align(DL.getABITypeAlignment(ObjectType));
}
}
}
- return Align;
+ return Alignment;
} else if (const Argument *A = dyn_cast<Argument>(this)) {
- const unsigned Align = A->getParamAlignment();
- if (!Align && A->hasStructRetAttr()) {
+ const MaybeAlign Alignment(A->getParamAlignment());
+ if (!Alignment && A->hasStructRetAttr()) {
// An sret parameter has at least the ABI alignment of the return type.
Type *EltTy = cast<PointerType>(A->getType())->getElementType();
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)) {
- const unsigned Align = AI->getAlignment();
- if (!Align) {
+ const MaybeAlign Alignment(AI->getAlignment());
+ if (!Alignment) {
Type *AllocatedType = AI->getAllocatedType();
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)) {
- const unsigned Align = Call->getRetAlignment();
- if (!Align && Call->getCalledFunction())
- return Call->getCalledFunction()->getAttributes().getRetAlignment();
- return Align;
+ const MaybeAlign Alignment(Call->getRetAlignment());
+ if (!Alignment && Call->getCalledFunction())
+ return MaybeAlign(
+ Call->getCalledFunction()->getAttributes().getRetAlignment());
+ return Alignment;
} else if (const LoadInst *LI = dyn_cast<LoadInst>(this)) {
if (MDNode *MD = LI->getMetadata(LLVMContext::MD_align)) {
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,
def alignedglobal : PatLeaf<(iPTR iPTR:$label), [{
if (auto *G = dyn_cast<GlobalAddressSDNode>(N)) {
const DataLayout &DL = MF->getDataLayout();
- unsigned Align = G->getGlobal()->getPointerAlignment(DL);
- return Align >= 4 && G->getOffset() % 4 == 0;
+ MaybeAlign Align = G->getGlobal()->getPointerAlignment(DL);
+ return Align && *Align >= 4 && G->getOffset() % 4 == 0;
}
if (auto *C = dyn_cast<ConstantPoolSDNode>(N))
return C->getAlignment() >= 4 && C->getOffset() % 4 == 0;
const auto &AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V));
if (!Stripped && this == &AA) {
// 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();
} else {
// Use abstract attribute information.
FunctionType *FuncType(FunctionType::get(VoidType, false));
std::unique_ptr<Function> Func(Function::Create(
FuncType, GlobalValue::ExternalLinkage));
- EXPECT_EQ(0U, Func->getPointerAlignment(DataLayout("")));
- EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fi8")));
- EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fn8")));
- EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fi16")));
- EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fn16")));
- EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fi32")));
- EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn32")));
+ EXPECT_EQ(MaybeAlign(), Func->getPointerAlignment(DataLayout("")));
+ EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("Fi8")));
+ EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("Fn8")));
+ EXPECT_EQ(Align(2), Func->getPointerAlignment(DataLayout("Fi16")));
+ EXPECT_EQ(Align(2), Func->getPointerAlignment(DataLayout("Fn16")));
+ EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fi32")));
+ EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn32")));
Func->setAlignment(Align(4));
- EXPECT_EQ(0U, Func->getPointerAlignment(DataLayout("")));
- EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fi8")));
- EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn8")));
- EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fi16")));
- EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn16")));
- EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fi32")));
- EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn32")));
+ EXPECT_EQ(MaybeAlign(), Func->getPointerAlignment(DataLayout("")));
+ EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("Fi8")));
+ EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn8")));
+ EXPECT_EQ(Align(2), Func->getPointerAlignment(DataLayout("Fi16")));
+ EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn16")));
+ EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fi32")));
+ EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn32")));
}
} // end namespace