1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[Alignment] TargetLowering::hasPairedLoad must use Align for RequiredAlignment

As per documentation of `hasPairLoad`:
"`RequiredAlignment` gives the minimal alignment constraints that must be met to be able to select this paired load."
In this sense, `0` is strictly equivalent to `1`. We make this obvious by using `Align` instead of unsigned.
There is only one implementor of this interface.

Differential Revision: https://reviews.llvm.org/D82958
This commit is contained in:
Guillaume Chatelet 2020-07-01 14:32:30 +00:00
parent feb84bcc0e
commit ac895f6f89
5 changed files with 71 additions and 74 deletions

View File

@ -1472,7 +1472,7 @@ public:
/// type has the alignment requirement of another type.
virtual Align getABIAlignmentForCallingConv(Type *ArgTy,
DataLayout DL) const {
return Align(DL.getABITypeAlignment(ArgTy));
return DL.getABITypeAlign(ArgTy);
}
/// If true, then instruction selection should seek to shrink the FP constant
@ -2572,7 +2572,7 @@ public:
/// this information should not be provided because it will generate more
/// loads.
virtual bool hasPairedLoad(EVT /*LoadedType*/,
unsigned & /*RequiredAlignment*/) const {
Align & /*RequiredAlignment*/) const {
return false;
}

View File

@ -93,9 +93,8 @@ namespace {
void visitFunction(Function &F);
void visitCallBase(CallBase &CB);
void visitMemoryReference(Instruction &I, Value *Ptr,
uint64_t Size, unsigned Align,
Type *Ty, unsigned Flags);
void visitMemoryReference(Instruction &I, Value *Ptr, uint64_t Size,
MaybeAlign Alignment, Type *Ty, unsigned Flags);
void visitEHBeginCatch(IntrinsicInst *II);
void visitEHEndCatch(IntrinsicInst *II);
@ -222,7 +221,7 @@ void Lint::visitFunction(Function &F) {
void Lint::visitCallBase(CallBase &I) {
Value *Callee = I.getCalledOperand();
visitMemoryReference(I, Callee, MemoryLocation::UnknownSize, 0, nullptr,
visitMemoryReference(I, Callee, MemoryLocation::UnknownSize, None, nullptr,
MemRef::Callee);
if (Function *F = dyn_cast<Function>(findValue(Callee,
@ -285,7 +284,7 @@ void Lint::visitCallBase(CallBase &I) {
Type *Ty =
cast<PointerType>(Formal->getType())->getElementType();
visitMemoryReference(I, Actual, DL->getTypeStoreSize(Ty),
DL->getABITypeAlignment(Ty), Ty,
DL->getABITypeAlign(Ty), Ty,
MemRef::Read | MemRef::Write);
}
}
@ -321,9 +320,9 @@ void Lint::visitCallBase(CallBase &I) {
MemCpyInst *MCI = cast<MemCpyInst>(&I);
// TODO: If the size is known, use it.
visitMemoryReference(I, MCI->getDest(), MemoryLocation::UnknownSize,
MCI->getDestAlignment(), nullptr, MemRef::Write);
MCI->getDestAlign(), nullptr, MemRef::Write);
visitMemoryReference(I, MCI->getSource(), MemoryLocation::UnknownSize,
MCI->getSourceAlignment(), nullptr, MemRef::Read);
MCI->getSourceAlign(), nullptr, MemRef::Read);
// Check that the memcpy arguments don't overlap. The AliasAnalysis API
// isn't expressive enough for what we really want to do. Known partial
@ -342,10 +341,10 @@ void Lint::visitCallBase(CallBase &I) {
case Intrinsic::memcpy_inline: {
MemCpyInlineInst *MCII = cast<MemCpyInlineInst>(&I);
const uint64_t Size = MCII->getLength()->getValue().getLimitedValue();
visitMemoryReference(I, MCII->getDest(), Size, MCII->getDestAlignment(),
visitMemoryReference(I, MCII->getDest(), Size, MCII->getDestAlign(),
nullptr, MemRef::Write);
visitMemoryReference(I, MCII->getSource(), Size,
MCII->getSourceAlignment(), nullptr, MemRef::Read);
visitMemoryReference(I, MCII->getSource(), Size, MCII->getSourceAlign(),
nullptr, MemRef::Read);
// Check that the memcpy arguments don't overlap. The AliasAnalysis API
// isn't expressive enough for what we really want to do. Known partial
@ -359,16 +358,16 @@ void Lint::visitCallBase(CallBase &I) {
MemMoveInst *MMI = cast<MemMoveInst>(&I);
// TODO: If the size is known, use it.
visitMemoryReference(I, MMI->getDest(), MemoryLocation::UnknownSize,
MMI->getDestAlignment(), nullptr, MemRef::Write);
MMI->getDestAlign(), nullptr, MemRef::Write);
visitMemoryReference(I, MMI->getSource(), MemoryLocation::UnknownSize,
MMI->getSourceAlignment(), nullptr, MemRef::Read);
MMI->getSourceAlign(), nullptr, MemRef::Read);
break;
}
case Intrinsic::memset: {
MemSetInst *MSI = cast<MemSetInst>(&I);
// TODO: If the size is known, use it.
visitMemoryReference(I, MSI->getDest(), MemoryLocation::UnknownSize,
MSI->getDestAlignment(), nullptr, MemRef::Write);
MSI->getDestAlign(), nullptr, MemRef::Write);
break;
}
@ -378,17 +377,17 @@ void Lint::visitCallBase(CallBase &I) {
&I);
visitMemoryReference(I, I.getArgOperand(0), MemoryLocation::UnknownSize,
0, nullptr, MemRef::Read | MemRef::Write);
None, nullptr, MemRef::Read | MemRef::Write);
break;
case Intrinsic::vacopy:
visitMemoryReference(I, I.getArgOperand(0), MemoryLocation::UnknownSize,
0, nullptr, MemRef::Write);
None, nullptr, MemRef::Write);
visitMemoryReference(I, I.getArgOperand(1), MemoryLocation::UnknownSize,
0, nullptr, MemRef::Read);
None, nullptr, MemRef::Read);
break;
case Intrinsic::vaend:
visitMemoryReference(I, I.getArgOperand(0), MemoryLocation::UnknownSize,
0, nullptr, MemRef::Read | MemRef::Write);
None, nullptr, MemRef::Read | MemRef::Write);
break;
case Intrinsic::stackrestore:
@ -396,7 +395,7 @@ void Lint::visitCallBase(CallBase &I) {
// stack pointer, which the compiler may read from or write to
// at any time, so check it for both readability and writeability.
visitMemoryReference(I, I.getArgOperand(0), MemoryLocation::UnknownSize,
0, nullptr, MemRef::Read | MemRef::Write);
None, nullptr, MemRef::Read | MemRef::Write);
break;
}
}
@ -414,9 +413,8 @@ void Lint::visitReturnInst(ReturnInst &I) {
// TODO: Check that the reference is in bounds.
// TODO: Check readnone/readonly function attributes.
void Lint::visitMemoryReference(Instruction &I,
Value *Ptr, uint64_t Size, unsigned Align,
Type *Ty, unsigned Flags) {
void Lint::visitMemoryReference(Instruction &I, Value *Ptr, uint64_t Size,
MaybeAlign Align, Type *Ty, unsigned Flags) {
// If no memory is being referenced, it doesn't matter if the pointer
// is valid.
if (Size == 0)
@ -467,15 +465,13 @@ void Lint::visitMemoryReference(Instruction &I,
// something we can handle and if so extract the size of this base object
// along with its alignment.
uint64_t BaseSize = MemoryLocation::UnknownSize;
unsigned BaseAlign = 0;
MaybeAlign BaseAlign;
if (AllocaInst *AI = dyn_cast<AllocaInst>(Base)) {
Type *ATy = AI->getAllocatedType();
if (!AI->isArrayAllocation() && ATy->isSized())
BaseSize = DL->getTypeAllocSize(ATy);
BaseAlign = AI->getAlignment();
if (BaseAlign == 0 && ATy->isSized())
BaseAlign = DL->getABITypeAlignment(ATy);
BaseAlign = AI->getAlign();
} else if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) {
// If the global may be defined differently in another compilation unit
// then don't warn about funky memory accesses.
@ -483,9 +479,9 @@ void Lint::visitMemoryReference(Instruction &I,
Type *GTy = GV->getValueType();
if (GTy->isSized())
BaseSize = DL->getTypeAllocSize(GTy);
BaseAlign = GV->getAlignment();
if (BaseAlign == 0 && GTy->isSized())
BaseAlign = DL->getABITypeAlignment(GTy);
BaseAlign = GV->getAlign();
if (!BaseAlign && GTy->isSized())
BaseAlign = DL->getABITypeAlign(GTy);
}
}
@ -498,24 +494,24 @@ void Lint::visitMemoryReference(Instruction &I,
// Accesses that say that the memory is more aligned than it is are not
// defined.
if (Align == 0 && Ty && Ty->isSized())
Align = DL->getABITypeAlignment(Ty);
Assert(!BaseAlign || Align <= MinAlign(BaseAlign, Offset),
"Undefined behavior: Memory reference address is misaligned", &I);
if (!Align && Ty && Ty->isSized())
Align = DL->getABITypeAlign(Ty);
if (BaseAlign && Align)
Assert(*Align <= commonAlignment(*BaseAlign, Offset),
"Undefined behavior: Memory reference address is misaligned", &I);
}
}
void Lint::visitLoadInst(LoadInst &I) {
visitMemoryReference(I, I.getPointerOperand(),
DL->getTypeStoreSize(I.getType()), I.getAlignment(),
DL->getTypeStoreSize(I.getType()), I.getAlign(),
I.getType(), MemRef::Read);
}
void Lint::visitStoreInst(StoreInst &I) {
visitMemoryReference(I, I.getPointerOperand(),
DL->getTypeStoreSize(I.getOperand(0)->getType()),
I.getAlignment(),
I.getOperand(0)->getType(), MemRef::Write);
I.getAlign(), I.getOperand(0)->getType(), MemRef::Write);
}
void Lint::visitXor(BinaryOperator &I) {
@ -614,12 +610,12 @@ void Lint::visitAllocaInst(AllocaInst &I) {
}
void Lint::visitVAArgInst(VAArgInst &I) {
visitMemoryReference(I, I.getOperand(0), MemoryLocation::UnknownSize, 0,
visitMemoryReference(I, I.getOperand(0), MemoryLocation::UnknownSize, None,
nullptr, MemRef::Read | MemRef::Write);
}
void Lint::visitIndirectBrInst(IndirectBrInst &I) {
visitMemoryReference(I, I.getAddress(), MemoryLocation::UnknownSize, 0,
visitMemoryReference(I, I.getAddress(), MemoryLocation::UnknownSize, None,
nullptr, MemRef::Branchee);
Assert(I.getNumDestinations() != 0,

View File

@ -11455,14 +11455,14 @@ SDValue DAGCombiner::CombineConsecutiveLoads(SDNode *N, EVT VT) {
unsigned LD1Bytes = LD1VT.getStoreSize();
if (ISD::isNON_EXTLoad(LD2) && LD2->hasOneUse() &&
DAG.areNonVolatileConsecutiveLoads(LD2, LD1, LD1Bytes, 1)) {
unsigned Align = LD1->getAlignment();
unsigned NewAlign = DAG.getDataLayout().getABITypeAlignment(
Align Alignment = LD1->getAlign();
Align NewAlign = DAG.getDataLayout().getABITypeAlign(
VT.getTypeForEVT(*DAG.getContext()));
if (NewAlign <= Align &&
if (NewAlign <= Alignment &&
(!LegalOperations || TLI.isOperationLegal(ISD::LOAD, VT)))
return DAG.getLoad(VT, SDLoc(N), LD1->getChain(), LD1->getBasePtr(),
LD1->getPointerInfo(), Align);
LD1->getPointerInfo(), Alignment);
}
return SDValue();
@ -15011,11 +15011,11 @@ struct LoadedSlice {
}
/// Get the alignment of the load used for this slice.
unsigned getAlignment() const {
unsigned Alignment = Origin->getAlignment();
Align getAlign() const {
Align Alignment = Origin->getAlign();
uint64_t Offset = getOffsetFromBase();
if (Offset != 0)
Alignment = MinAlign(Alignment, Alignment + Offset);
Alignment = commonAlignment(Alignment, Alignment.value() + Offset);
return Alignment;
}
@ -15111,8 +15111,8 @@ struct LoadedSlice {
// Create the load for the slice.
SDValue LastInst =
DAG->getLoad(SliceType, SDLoc(Origin), Origin->getChain(), BaseAddr,
Origin->getPointerInfo().getWithOffset(Offset),
getAlignment(), Origin->getMemOperand()->getFlags());
Origin->getPointerInfo().getWithOffset(Offset), getAlign(),
Origin->getMemOperand()->getFlags());
// If the final type is not the same as the loaded type, this means that
// we have to pad with zero. Create a zero extend for that.
EVT FinalType = Inst->getValueType(0);
@ -15153,10 +15153,10 @@ struct LoadedSlice {
// Check if it will be merged with the load.
// 1. Check the alignment constraint.
unsigned RequiredAlignment = DAG->getDataLayout().getABITypeAlignment(
Align RequiredAlignment = DAG->getDataLayout().getABITypeAlign(
ResVT.getTypeForEVT(*DAG->getContext()));
if (RequiredAlignment > getAlignment())
if (RequiredAlignment > getAlign())
return false;
// 2. Check that the load is a legal operation for that type.
@ -15242,14 +15242,14 @@ static void adjustCostForPairing(SmallVectorImpl<LoadedSlice> &LoadedSlices,
continue;
// Check if the target supplies paired loads for this type.
unsigned RequiredAlignment = 0;
Align RequiredAlignment;
if (!TLI.hasPairedLoad(LoadedType, RequiredAlignment)) {
// move to the next pair, this type is hopeless.
Second = nullptr;
continue;
}
// Check if we meet the alignment requirement.
if (RequiredAlignment > First->getAlignment())
if (First->getAlign() < RequiredAlignment)
continue;
// Check that both loads are next to each other in memory.
@ -15644,9 +15644,9 @@ SDValue DAGCombiner::ReduceLoadOpStoreWidth(SDNode *N) {
if (DAG.getDataLayout().isBigEndian())
PtrOff = (BitWidth + 7 - NewBW) / 8 - PtrOff;
unsigned NewAlign = MinAlign(LD->getAlignment(), PtrOff);
Align NewAlign = commonAlignment(LD->getAlign(), PtrOff);
Type *NewVTTy = NewVT.getTypeForEVT(*DAG.getContext());
if (NewAlign < DAG.getDataLayout().getABITypeAlignment(NewVTTy))
if (NewAlign < DAG.getDataLayout().getABITypeAlign(NewVTTy))
return SDValue();
SDValue NewPtr = DAG.getMemBasePlusOffset(Ptr, PtrOff, SDLoc(LD));
@ -15699,10 +15699,10 @@ SDValue DAGCombiner::TransformFPLoadStorePair(SDNode *N) {
!TLI.isDesirableToTransformToIntegerOp(ISD::STORE, VT))
return SDValue();
unsigned LDAlign = LD->getAlignment();
unsigned STAlign = ST->getAlignment();
Align LDAlign = LD->getAlign();
Align STAlign = ST->getAlign();
Type *IntVTTy = IntVT.getTypeForEVT(*DAG.getContext());
unsigned ABIAlign = DAG.getDataLayout().getABITypeAlignment(IntVTTy);
Align ABIAlign = DAG.getDataLayout().getABITypeAlign(IntVTTy);
if (LDAlign < ABIAlign || STAlign < ABIAlign)
return SDValue();
@ -16523,10 +16523,10 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
while (NumConsecutiveStores >= 2 && LoadNodes.size() >= 2) {
// If we have load/store pair instructions and we only have two values,
// don't bother merging.
unsigned RequiredAlignment;
Align RequiredAlignment;
if (LoadNodes.size() == 2 &&
TLI.hasPairedLoad(MemVT, RequiredAlignment) &&
StoreNodes[0].MemNode->getAlignment() >= RequiredAlignment) {
StoreNodes[0].MemNode->getAlign() >= RequiredAlignment) {
StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + 2);
LoadNodes.erase(LoadNodes.begin(), LoadNodes.begin() + 2);
break;
@ -17428,11 +17428,12 @@ SDValue DAGCombiner::scalarizeExtractedVectorLoad(SDNode *EVE, EVT InVecVT,
EVT ResultVT = EVE->getValueType(0);
EVT VecEltVT = InVecVT.getVectorElementType();
unsigned Align = OriginalLoad->getAlignment();
unsigned NewAlign = DAG.getDataLayout().getABITypeAlignment(
Align Alignment = OriginalLoad->getAlign();
Align NewAlign = DAG.getDataLayout().getABITypeAlign(
VecEltVT.getTypeForEVT(*DAG.getContext()));
if (NewAlign > Align || !TLI.isOperationLegalOrCustom(ISD::LOAD, VecEltVT))
if (NewAlign > Alignment ||
!TLI.isOperationLegalOrCustom(ISD::LOAD, VecEltVT))
return SDValue();
ISD::LoadExtType ExtTy = ResultVT.bitsGT(VecEltVT) ?
@ -17440,7 +17441,7 @@ SDValue DAGCombiner::scalarizeExtractedVectorLoad(SDNode *EVE, EVT InVecVT,
if (!TLI.shouldReduceLoadWidth(OriginalLoad, ExtTy, VecEltVT))
return SDValue();
Align = NewAlign;
Alignment = NewAlign;
SDValue NewPtr = OriginalLoad->getBasePtr();
SDValue Offset;
@ -17480,13 +17481,13 @@ SDValue DAGCombiner::scalarizeExtractedVectorLoad(SDNode *EVE, EVT InVecVT,
: ISD::EXTLOAD;
Load = DAG.getExtLoad(ExtType, SDLoc(EVE), ResultVT,
OriginalLoad->getChain(), NewPtr, MPI, VecEltVT,
Align, OriginalLoad->getMemOperand()->getFlags(),
Alignment, OriginalLoad->getMemOperand()->getFlags(),
OriginalLoad->getAAInfo());
Chain = Load.getValue(1);
} else {
Load = DAG.getLoad(VecEltVT, SDLoc(EVE), OriginalLoad->getChain(), NewPtr,
MPI, Align, OriginalLoad->getMemOperand()->getFlags(),
OriginalLoad->getAAInfo());
Load = DAG.getLoad(
VecEltVT, SDLoc(EVE), OriginalLoad->getChain(), NewPtr, MPI, Alignment,
OriginalLoad->getMemOperand()->getFlags(), OriginalLoad->getAAInfo());
Chain = Load.getValue(1);
if (ResultVT.bitsLT(VecEltVT))
Load = DAG.getNode(ISD::TRUNCATE, SDLoc(EVE), ResultVT, Load);

View File

@ -9250,7 +9250,7 @@ bool AArch64TargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
Info.memVT = MVT::getVT(PtrTy->getElementType());
Info.ptrVal = I.getArgOperand(0);
Info.offset = 0;
Info.align = MaybeAlign(DL.getABITypeAlignment(PtrTy->getElementType()));
Info.align = DL.getABITypeAlign(PtrTy->getElementType());
Info.flags = MachineMemOperand::MOLoad | MachineMemOperand::MOVolatile;
return true;
}
@ -9261,7 +9261,7 @@ bool AArch64TargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
Info.memVT = MVT::getVT(PtrTy->getElementType());
Info.ptrVal = I.getArgOperand(1);
Info.offset = 0;
Info.align = MaybeAlign(DL.getABITypeAlignment(PtrTy->getElementType()));
Info.align = DL.getABITypeAlign(PtrTy->getElementType());
Info.flags = MachineMemOperand::MOStore | MachineMemOperand::MOVolatile;
return true;
}
@ -9289,7 +9289,7 @@ bool AArch64TargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
Info.memVT = MVT::getVT(I.getType());
Info.ptrVal = I.getArgOperand(1);
Info.offset = 0;
Info.align = MaybeAlign(DL.getABITypeAlignment(PtrTy->getElementType()));
Info.align = DL.getABITypeAlign(PtrTy->getElementType());
Info.flags = MachineMemOperand::MOLoad;
if (Intrinsic == Intrinsic::aarch64_sve_ldnt1)
Info.flags |= MachineMemOperand::MONonTemporal;
@ -9301,7 +9301,7 @@ bool AArch64TargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
Info.memVT = MVT::getVT(I.getOperand(0)->getType());
Info.ptrVal = I.getArgOperand(2);
Info.offset = 0;
Info.align = MaybeAlign(DL.getABITypeAlignment(PtrTy->getElementType()));
Info.align = DL.getABITypeAlign(PtrTy->getElementType());
Info.flags = MachineMemOperand::MOStore;
if (Intrinsic == Intrinsic::aarch64_sve_stnt1)
Info.flags |= MachineMemOperand::MONonTemporal;
@ -9606,12 +9606,12 @@ bool AArch64TargetLowering::shouldSinkOperands(
}
bool AArch64TargetLowering::hasPairedLoad(EVT LoadedType,
unsigned &RequiredAligment) const {
Align &RequiredAligment) const {
if (!LoadedType.isSimple() ||
(!LoadedType.isInteger() && !LoadedType.isFloatingPoint()))
return false;
// Cyclone supports unaligned accesses.
RequiredAligment = 0;
RequiredAligment = Align(1);
unsigned NumBits = LoadedType.getSizeInBits();
return NumBits == 32 || NumBits == 64;
}

View File

@ -505,7 +505,7 @@ public:
bool shouldSinkOperands(Instruction *I,
SmallVectorImpl<Use *> &Ops) const override;
bool hasPairedLoad(EVT LoadedType, unsigned &RequiredAligment) const override;
bool hasPairedLoad(EVT LoadedType, Align &RequiredAligment) const override;
unsigned getMaxSupportedInterleaveFactor() const override { return 4; }