Showing with 577 additions and 322 deletions.
  1. +3 −1 include/llvm/CodeGen/FastISel.h
  2. +29 −0 include/llvm/IR/Attributes.h
  3. +2 −1 include/llvm/IR/Function.h
  4. +2 −0 include/llvm/IR/Instruction.h
  5. +8 −20 include/llvm/IR/Instructions.h
  6. +2 −6 include/llvm/Target/TargetLowering.h
  7. +1 −2 lib/Analysis/MemoryBuiltins.cpp
  8. +8 −16 lib/Analysis/ValueTracking.cpp
  9. +7 −15 lib/CodeGen/SelectionDAG/FastISel.cpp
  10. +16 −32 lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
  11. +1 −0 lib/CodeGen/SelectionDAG/TargetLowering.cpp
  12. +0 −8 lib/CodeGen/TargetLoweringBase.cpp
  13. +31 −0 lib/IR/Attributes.cpp
  14. +14 −0 lib/IR/BasicBlock.cpp
  15. +19 −0 lib/IR/Function.cpp
  16. +32 −0 lib/IR/Instruction.cpp
  17. +74 −0 lib/IR/Instructions.cpp
  18. +5 −3 lib/IR/Mangler.cpp
  19. +17 −1 lib/IR/Module.cpp
  20. +35 −0 lib/IR/Verifier.cpp
  21. +24 −13 lib/Target/NVPTX/NVPTXLowerKernelArgs.cpp
  22. +0 −44 lib/Target/PowerPC/PPCISelLowering.cpp
  23. +0 −6 lib/Target/PowerPC/PPCISelLowering.h
  24. +0 −45 lib/Target/X86/X86ISelLowering.cpp
  25. +0 −7 lib/Target/X86/X86ISelLowering.h
  26. +1 −1 lib/Transforms/Instrumentation/MemorySanitizer.cpp
  27. +4 −11 lib/Transforms/Instrumentation/SafeStack.cpp
  28. +1 −2 lib/Transforms/Scalar/MemCpyOptimizer.cpp
  29. +5 −5 test/Analysis/ValueTracking/memory-dereferenceable.ll
  30. +3 −3 test/Bitcode/compatibility-3.6.ll
  31. +3 −3 test/Bitcode/compatibility-3.7.ll
  32. +3 −3 test/Bitcode/compatibility.ll
  33. +1 −1 test/Bitcode/highLevelStructure.3.2.ll
  34. +2 −2 test/CodeGen/AMDGPU/invariant-load-no-alias-store.ll
  35. +1 −1 test/CodeGen/WebAssembly/reg-stackify.ll
  36. +41 −0 test/CodeGen/X86/byval3-64.ll
  37. +0 −14 test/CodeGen/X86/byval3.ll
  38. +47 −0 test/CodeGen/X86/byval4-64.ll
  39. +3 −17 test/CodeGen/X86/byval4.ll
  40. +55 −0 test/CodeGen/X86/byval5-64.ll
  41. +3 −17 test/CodeGen/X86/byval5.ll
  42. +49 −0 test/CodeGen/X86/movtopush-aligned.ll
  43. +2 −2 test/CodeGen/X86/movtopush.ll
  44. +3 −3 test/Transforms/ArgumentPromotion/fp80.ll
  45. +2 −2 test/Transforms/ArgumentPromotion/inalloca.ll
  46. +1 −1 test/Transforms/InstCombine/align-addr.ll
  47. +1 −1 test/Transforms/InstCombine/gc.relocate.ll
  48. +2 −2 test/Transforms/InstCombine/memcpy-from-global.ll
  49. +11 −8 test/Transforms/LICM/hoist-deref-load.ll
  50. +2 −2 test/Transforms/MemCpyOpt/memcpy.ll
  51. +1 −1 test/Transforms/SimplifyCFG/SpeculativeExec.ll
4 changes: 3 additions & 1 deletion include/llvm/CodeGen/FastISel.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ class FastISel {
bool IsInAlloca : 1;
bool IsReturned : 1;
uint16_t Alignment;
uint64_t IndirectSize;

ArgListEntry()
: Val(nullptr), Ty(nullptr), IsSExt(false), IsZExt(false),
IsInReg(false), IsSRet(false), IsNest(false), IsByVal(false),
IsInAlloca(false), IsReturned(false), Alignment(0) {}
IsInAlloca(false), IsReturned(false), Alignment(0),
IndirectSize(0) {}

/// \brief Set CallLoweringInfo attribute flags based on a call instruction
/// and called function attributes.
Expand Down
29 changes: 29 additions & 0 deletions include/llvm/IR/Attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ class AttributeImpl;
class AttributeSetImpl;
class AttributeSetNode;
class Constant;
class DataLayout;
template<typename T> struct DenseMapInfo;
class Function;
class FunctionType;
class LLVMContext;
class Type;

Expand Down Expand Up @@ -267,6 +269,33 @@ class AttributeSet {
AttributeSet addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index,
uint64_t Bytes) const;

/// \brief Add dereferenceable(sizeof(T)) and align(alignof(T))
/// attributes to each T* byval or inalloca argument.
/// Because attribute sets are immutable, this returns a new set.
template <typename ArgTypesIter>
AttributeSet fixupSizeAndAlignForIndirectAttrs(ArgTypesIter ArgTypes,
const DataLayout *DL) const {
AttributeSet NewAttrs = *this;
// We require a DataLayout to perform any fixups.
if (!DL)
return NewAttrs;

unsigned AttrIdx = 1;
for (Type *ArgTy : ArgTypes) {
if (hasAttribute(AttrIdx, Attribute::ByVal) ||
hasAttribute(AttrIdx, Attribute::InAlloca))
NewAttrs = NewAttrs.fixupSizeAndAlignForIndirectAttr(AttrIdx, ArgTy, *DL);
++AttrIdx;
}
return NewAttrs;
}

/// \brief Add dereferenceable(sizeof(T)) and align(alignof(T)) attributes
/// to the T* byval or inalloca argument at the given index.
/// Because attribute sets are immutable, this returns a new set.
AttributeSet fixupSizeAndAlignForIndirectAttr(unsigned Index, Type *Ty,
const DataLayout &DL) const;

//===--------------------------------------------------------------------===//
// AttributeSet Accessors
//===--------------------------------------------------------------------===//
Expand Down
3 changes: 2 additions & 1 deletion include/llvm/IR/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class Function : public GlobalObject, public ilist_node<Function> {
}

friend class SymbolTableListTraits<Function>;
friend class Module;

void setParent(Module *parent);

Expand Down Expand Up @@ -165,7 +166,7 @@ class Function : public GlobalObject, public ilist_node<Function> {
AttributeSet getAttributes() const { return AttributeSets; }

/// @brief Set the attribute list for this Function.
void setAttributes(AttributeSet attrs) { AttributeSets = attrs; }
void setAttributes(AttributeSet attrs);

/// @brief Add function attributes to this function.
void addFnAttr(Attribute::AttrKind N) {
Expand Down
2 changes: 2 additions & 0 deletions include/llvm/IR/Instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,8 @@ class Instruction : public User,
}

friend class SymbolTableListTraits<Instruction>;
friend class BasicBlock;
friend class Function;
void setParent(BasicBlock *P);
protected:
// Instruction subclasses can stick up to 15 bits of stuff into the
Expand Down
28 changes: 8 additions & 20 deletions include/llvm/IR/Instructions.h
Original file line number Diff line number Diff line change
Expand Up @@ -1605,7 +1605,7 @@ class CallInst : public Instruction,

/// setAttributes - Set the parameter attributes for this call.
///
void setAttributes(const AttributeSet &Attrs) { AttributeList = Attrs; }
void setAttributes(const AttributeSet &Attrs);

/// addAttribute - adds the attribute to the list of attributes.
void addAttribute(unsigned i, Attribute::AttrKind attr);
Expand Down Expand Up @@ -1654,21 +1654,15 @@ class CallInst : public Instruction,
bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind A) const;

/// \brief Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned i) const {
return AttributeList.getParamAlignment(i);
}
unsigned getParamAlignment(unsigned i) const;

/// \brief Extract the number of dereferenceable bytes for a call or
/// parameter (0=unknown).
uint64_t getDereferenceableBytes(unsigned i) const {
return AttributeList.getDereferenceableBytes(i);
}
uint64_t getDereferenceableBytes(unsigned i) const;

/// \brief Extract the number of dereferenceable_or_null bytes for a call or
/// parameter (0=unknown).
uint64_t getDereferenceableOrNullBytes(unsigned i) const {
return AttributeList.getDereferenceableOrNullBytes(i);
}
uint64_t getDereferenceableOrNullBytes(unsigned i) const;

/// @brief Determine if the parameter or return value is marked with NoAlias
/// attribute.
Expand Down Expand Up @@ -3529,7 +3523,7 @@ class InvokeInst : public TerminatorInst,

/// setAttributes - Set the parameter attributes for this invoke.
///
void setAttributes(const AttributeSet &Attrs) { AttributeList = Attrs; }
void setAttributes(const AttributeSet &Attrs);

/// addAttribute - adds the attribute to the list of attributes.
void addAttribute(unsigned i, Attribute::AttrKind attr);
Expand Down Expand Up @@ -3576,21 +3570,15 @@ class InvokeInst : public TerminatorInst,
bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind A) const;

/// \brief Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned i) const {
return AttributeList.getParamAlignment(i);
}
unsigned getParamAlignment(unsigned i) const;

/// \brief Extract the number of dereferenceable bytes for a call or
/// parameter (0=unknown).
uint64_t getDereferenceableBytes(unsigned i) const {
return AttributeList.getDereferenceableBytes(i);
}
uint64_t getDereferenceableBytes(unsigned i) const;

/// \brief Extract the number of dereferenceable_or_null bytes for a call or
/// parameter (0=unknown).
uint64_t getDereferenceableOrNullBytes(unsigned i) const {
return AttributeList.getDereferenceableOrNullBytes(i);
}
uint64_t getDereferenceableOrNullBytes(unsigned i) const;

/// @brief Determine if the parameter or return value is marked with NoAlias
/// attribute.
Expand Down
8 changes: 2 additions & 6 deletions include/llvm/Target/TargetLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -746,11 +746,6 @@ class TargetLoweringBase {
return getValueType(DL, Ty, AllowUnknown).getSimpleVT();
}

/// Return the desired alignment for ByVal or InAlloca aggregate function
/// arguments in the caller parameter area. This is the actual alignment, not
/// its logarithm.
virtual unsigned getByValTypeAlignment(Type *Ty, const DataLayout &DL) const;

/// Return the type of registers that this ValueType will eventually require.
MVT getRegisterType(MVT VT) const {
assert((unsigned)VT.SimpleTy < array_lengthof(RegisterTypeForVT));
Expand Down Expand Up @@ -2323,10 +2318,11 @@ class TargetLowering : public TargetLoweringBase {
bool isInAlloca : 1;
bool isReturned : 1;
uint16_t Alignment;
uint64_t IndirectSize;

ArgListEntry() : isSExt(false), isZExt(false), isInReg(false),
isSRet(false), isNest(false), isByVal(false), isInAlloca(false),
isReturned(false), Alignment(0) { }
isReturned(false), Alignment(0), IndirectSize(0) { }

void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx);
};
Expand Down
3 changes: 1 addition & 2 deletions lib/Analysis/MemoryBuiltins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,8 +448,7 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitArgument(Argument &A) {
++ObjectVisitorArgument;
return unknown();
}
PointerType *PT = cast<PointerType>(A.getType());
APInt Size(IntTyBits, DL.getTypeAllocSize(PT->getPointerElementType()));
APInt Size(IntTyBits, A.getDereferenceableBytes());
return std::make_pair(align(Size, A.getParamAlignment()), Zero);
}

Expand Down
24 changes: 8 additions & 16 deletions lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1573,17 +1573,13 @@ static unsigned getAlignment(const Value *V, const DataLayout &DL) {
}
}
} else if (const Argument *A = dyn_cast<Argument>(V)) {
Align = A->getType()->isPointerTy() ? A->getParamAlignment() : 0;

if (!Align && A->hasStructRetAttr()) {
// An sret parameter has at least the ABI alignment of the return type.
Type *EltTy = cast<PointerType>(A->getType())->getPointerElementType();
if (EltTy->isSized())
Align = DL.getABITypeAlignment(EltTy);
}
} else if (const AllocaInst *AI = dyn_cast<AllocaInst>(V))
if (A->getType()->isPointerTy())
Align = A->getParamAlignment();
} else if (const AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
Align = AI->getAlignment();
else if (auto CS = ImmutableCallSite(V))
if (Align == 0)
Align = DL.getABITypeAlignment(AI->getAllocatedType());
} else if (auto CS = ImmutableCallSite(V))
Align = CS.getAttributes().getParamAlignment(AttributeSet::ReturnIndex);
else if (const LoadInst *LI = dyn_cast<LoadInst>(V))
if (MDNode *MD = LI->getMetadata(LLVMContext::MD_align)) {
Expand Down Expand Up @@ -3173,12 +3169,8 @@ static bool isAligned(const Value *Base, APInt Offset, unsigned Align,
const DataLayout &DL) {
APInt BaseAlign(Offset.getBitWidth(), getAlignment(Base, DL));

if (!BaseAlign) {
Type *Ty = cast<PointerType>(Base->getType())->getPointerElementType();
if (!Ty->isSized())
return false;
BaseAlign = DL.getABITypeAlignment(Ty);
}
if (!BaseAlign)
return false;

APInt Alignment(Offset.getBitWidth(), Align);

Expand Down
22 changes: 7 additions & 15 deletions lib/CodeGen/SelectionDAG/FastISel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ void FastISel::ArgListEntry::setAttributes(ImmutableCallSite *CS,
IsInAlloca = CS->paramHasAttr(AttrIdx, Attribute::InAlloca);
IsReturned = CS->paramHasAttr(AttrIdx, Attribute::Returned);
Alignment = CS->getParamAlignment(AttrIdx);
IndirectSize = CS->getDereferenceableBytes(AttrIdx);
}

/// Set the current block to which generated machine instructions will be
Expand Down Expand Up @@ -948,11 +949,10 @@ bool FastISel::lowerCallTo(CallLoweringInfo &CLI) {
// Handle all of the outgoing arguments.
CLI.clearOuts();
for (auto &Arg : CLI.getArgs()) {
Type *FinalType = Arg.Ty;
if (Arg.IsByVal)
FinalType = cast<PointerType>(Arg.Ty)->getPointerElementType();
bool NeedsRegBlock = TLI.functionArgumentNeedsConsecutiveRegisters(
FinalType, CLI.CallConv, CLI.IsVarArg);
bool NeedsRegBlock = false;
if (!Arg.IsByVal)
NeedsRegBlock = TLI.functionArgumentNeedsConsecutiveRegisters(
Arg.Ty, CLI.CallConv, CLI.IsVarArg);

ISD::ArgFlagsTy Flags;
if (Arg.IsZExt)
Expand All @@ -975,16 +975,8 @@ bool FastISel::lowerCallTo(CallLoweringInfo &CLI) {
Flags.setByVal();
}
if (Arg.IsByVal || Arg.IsInAlloca) {
PointerType *Ty = cast<PointerType>(Arg.Ty);
Type *ElementTy = Ty->getPointerElementType();
unsigned FrameSize = DL.getTypeAllocSize(ElementTy);
// For ByVal, alignment should come from FE. BE will guess if this info is
// not there, but there are cases it cannot get right.
unsigned FrameAlign = Arg.Alignment;
if (!FrameAlign)
FrameAlign = TLI.getByValTypeAlignment(ElementTy, DL);
Flags.setByValSize(FrameSize);
Flags.setByValAlign(FrameAlign);
Flags.setByValSize(Arg.IndirectSize);
Flags.setByValAlign(Arg.Alignment);
}
if (Arg.IsNest)
Flags.setNest();
Expand Down
48 changes: 16 additions & 32 deletions lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7101,11 +7101,12 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
SmallVector<EVT, 4> ValueVTs;
ComputeValueVTs(*this, DL, Args[i].Ty, ValueVTs);
Type *FinalType = Args[i].Ty;
if (Args[i].isByVal)
FinalType = cast<PointerType>(Args[i].Ty)->getPointerElementType();
bool NeedsRegBlock = functionArgumentNeedsConsecutiveRegisters(
FinalType, CLI.CallConv, CLI.IsVarArg);

bool NeedsRegBlock = false;
if (!Args[i].isByVal)
NeedsRegBlock = functionArgumentNeedsConsecutiveRegisters(
Args[i].Ty, CLI.CallConv, CLI.IsVarArg);

for (unsigned Value = 0, NumValues = ValueVTs.size(); Value != NumValues;
++Value) {
EVT VT = ValueVTs[Value];
Expand Down Expand Up @@ -7135,17 +7136,8 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
Flags.setByVal();
}
if (Args[i].isByVal || Args[i].isInAlloca) {
PointerType *Ty = cast<PointerType>(Args[i].Ty);
Type *ElementTy = Ty->getPointerElementType();
Flags.setByValSize(DL.getTypeAllocSize(ElementTy));
// For ByVal, alignment should come from FE. BE will guess if this
// info is not there but there are cases it cannot get right.
unsigned FrameAlign;
if (Args[i].Alignment)
FrameAlign = Args[i].Alignment;
else
FrameAlign = getByValTypeAlignment(ElementTy, DL);
Flags.setByValAlign(FrameAlign);
Flags.setByValSize(Args[i].IndirectSize);
Flags.setByValAlign(Args[i].Alignment);
}
if (Args[i].isNest)
Flags.setNest();
Expand Down Expand Up @@ -7383,11 +7375,12 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
ComputeValueVTs(*TLI, DAG.getDataLayout(), I->getType(), ValueVTs);
bool isArgValueUsed = !I->use_empty();
unsigned PartBase = 0;
Type *FinalType = I->getType();
if (F.getAttributes().hasAttribute(Idx, Attribute::ByVal))
FinalType = cast<PointerType>(FinalType)->getPointerElementType();
bool NeedsRegBlock = TLI->functionArgumentNeedsConsecutiveRegisters(
FinalType, F.getCallingConv(), F.isVarArg());

bool NeedsRegBlock = false;
if (!F.getAttributes().hasAttribute(Idx, Attribute::ByVal))
NeedsRegBlock = TLI->functionArgumentNeedsConsecutiveRegisters(
I->getType(), F.getCallingConv(), F.isVarArg());

for (unsigned Value = 0, NumValues = ValueVTs.size();
Value != NumValues; ++Value) {
EVT VT = ValueVTs[Value];
Expand Down Expand Up @@ -7420,17 +7413,8 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
Flags.setByVal();
}
if (Flags.isByVal() || Flags.isInAlloca()) {
PointerType *Ty = cast<PointerType>(I->getType());
Type *ElementTy = Ty->getPointerElementType();
Flags.setByValSize(DL.getTypeAllocSize(ElementTy));
// For ByVal, alignment should be passed from FE. BE will guess if
// this info is not there but there are cases it cannot get right.
unsigned FrameAlign;
if (F.getParamAlignment(Idx))
FrameAlign = F.getParamAlignment(Idx);
else
FrameAlign = TLI->getByValTypeAlignment(ElementTy, DL);
Flags.setByValAlign(FrameAlign);
Flags.setByValSize(F.getDereferenceableBytes(Idx));
Flags.setByValAlign(F.getParamAlignment(Idx));
}
if (F.getAttributes().hasAttribute(Idx, Attribute::Nest))
Flags.setNest();
Expand Down
1 change: 1 addition & 0 deletions lib/CodeGen/SelectionDAG/TargetLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ void TargetLowering::ArgListEntry::setAttributes(ImmutableCallSite *CS,
isInAlloca = CS->paramHasAttr(AttrIdx, Attribute::InAlloca);
isReturned = CS->paramHasAttr(AttrIdx, Attribute::Returned);
Alignment = CS->getParamAlignment(AttrIdx);
IndirectSize = CS->getDereferenceableBytes(AttrIdx);
}

/// Generate a libcall taking the given operands as arguments and returning a
Expand Down
8 changes: 0 additions & 8 deletions lib/CodeGen/TargetLoweringBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1523,14 +1523,6 @@ void llvm::GetReturnInfo(Type *ReturnType, AttributeSet attr,
}
}

/// getByValTypeAlignment - Return the desired alignment for ByVal aggregate
/// function arguments in the caller parameter area. This is the actual
/// alignment, not its logarithm.
unsigned TargetLoweringBase::getByValTypeAlignment(Type *Ty,
const DataLayout &DL) const {
return DL.getABITypeAlignment(Ty);
}

bool TargetLoweringBase::allowsMemoryAccess(LLVMContext &Context,
const DataLayout &DL, EVT VT,
unsigned AddrSpace,
Expand Down
Loading