forked from OSchip/llvm-project
Fix load alignement when unpacking aggregates structs
Summary: Store and loads unpacked by instcombine do not always have the right alignement. This explicitely compute the alignement and set it. Reviewers: dblaikie, majnemer, reames, hfinkel, joker.eph Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D17326 llvm-svn: 261139
This commit is contained in:
parent
f48bcb2bd9
commit
61a7d629ec
|
@ -523,16 +523,17 @@ static Instruction *unpackLoadToAggregate(InstCombiner &IC, LoadInst &LI) {
|
|||
if (!T->isAggregateType())
|
||||
return nullptr;
|
||||
|
||||
auto Name = LI.getName();
|
||||
assert(LI.getAlignment() && "Alignment must be set at this point");
|
||||
|
||||
if (auto *ST = dyn_cast<StructType>(T)) {
|
||||
// If the struct only have one element, we unpack.
|
||||
unsigned Count = ST->getNumElements();
|
||||
if (Count == 1) {
|
||||
auto NumElements = ST->getNumElements();
|
||||
if (NumElements == 1) {
|
||||
LoadInst *NewLoad = combineLoadToNewType(IC, LI, ST->getTypeAtIndex(0U),
|
||||
".unpack");
|
||||
return IC.replaceInstUsesWith(LI, IC.Builder->CreateInsertValue(
|
||||
UndefValue::get(T), NewLoad, 0, LI.getName()));
|
||||
UndefValue::get(T), NewLoad, 0, Name));
|
||||
}
|
||||
|
||||
// We don't want to break loads with padding here as we'd loose
|
||||
|
@ -542,23 +543,29 @@ static Instruction *unpackLoadToAggregate(InstCombiner &IC, LoadInst &LI) {
|
|||
if (SL->hasPadding())
|
||||
return nullptr;
|
||||
|
||||
auto Name = LI.getName();
|
||||
auto Align = LI.getAlignment();
|
||||
if (!Align)
|
||||
Align = DL.getABITypeAlignment(ST);
|
||||
|
||||
SmallString<16> LoadName = Name;
|
||||
LoadName += ".unpack";
|
||||
SmallString<16> EltName = Name;
|
||||
EltName += ".elt";
|
||||
|
||||
auto *Addr = LI.getPointerOperand();
|
||||
Value *V = UndefValue::get(T);
|
||||
auto *IdxType = Type::getInt32Ty(ST->getContext());
|
||||
auto *IdxType = Type::getInt32Ty(T->getContext());
|
||||
auto *Zero = ConstantInt::get(IdxType, 0);
|
||||
for (unsigned i = 0; i < Count; i++) {
|
||||
|
||||
Value *V = UndefValue::get(T);
|
||||
for (unsigned i = 0; i < NumElements; i++) {
|
||||
Value *Indices[2] = {
|
||||
Zero,
|
||||
ConstantInt::get(IdxType, i),
|
||||
};
|
||||
auto *Ptr = IC.Builder->CreateInBoundsGEP(ST, Addr, makeArrayRef(Indices), EltName);
|
||||
auto *L = IC.Builder->CreateAlignedLoad(Ptr, LI.getAlignment(),
|
||||
LoadName);
|
||||
auto *Ptr = IC.Builder->CreateInBoundsGEP(ST, Addr,
|
||||
makeArrayRef(Indices), EltName);
|
||||
auto EltAlign = MinAlign(Align, SL->getElementOffset(i));
|
||||
auto *L = IC.Builder->CreateAlignedLoad(Ptr, EltAlign, LoadName);
|
||||
V = IC.Builder->CreateInsertValue(V, L, i);
|
||||
}
|
||||
|
||||
|
@ -948,11 +955,16 @@ static bool unpackStoreToAggregate(InstCombiner &IC, StoreInst &SI) {
|
|||
if (SL->hasPadding())
|
||||
return false;
|
||||
|
||||
auto Align = SI.getAlignment();
|
||||
if (!Align)
|
||||
Align = DL.getABITypeAlignment(ST);
|
||||
|
||||
SmallString<16> EltName = V->getName();
|
||||
EltName += ".elt";
|
||||
auto *Addr = SI.getPointerOperand();
|
||||
SmallString<16> AddrName = Addr->getName();
|
||||
AddrName += ".repack";
|
||||
|
||||
auto *IdxType = Type::getInt32Ty(ST->getContext());
|
||||
auto *Zero = ConstantInt::get(IdxType, 0);
|
||||
for (unsigned i = 0; i < Count; i++) {
|
||||
|
@ -960,9 +972,11 @@ static bool unpackStoreToAggregate(InstCombiner &IC, StoreInst &SI) {
|
|||
Zero,
|
||||
ConstantInt::get(IdxType, i),
|
||||
};
|
||||
auto *Ptr = IC.Builder->CreateInBoundsGEP(ST, Addr, makeArrayRef(Indices), AddrName);
|
||||
auto *Ptr = IC.Builder->CreateInBoundsGEP(ST, Addr,
|
||||
makeArrayRef(Indices), AddrName);
|
||||
auto *Val = IC.Builder->CreateExtractValue(V, i, EltName);
|
||||
IC.Builder->CreateStore(Val, Ptr);
|
||||
auto EltAlign = MinAlign(Align, SL->getElementOffset(i));
|
||||
IC.Builder->CreateAlignedStore(Val, Ptr, EltAlign);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -151,3 +151,30 @@ define i32 @packed_alignment(%struct.S* dereferenceable(9) %s) {
|
|||
%v = extractvalue %struct.T %tv, 1
|
||||
ret i32 %v
|
||||
}
|
||||
|
||||
%struct.U = type {i8, i8, i8, i8, i8, i8, i8, i8, i64}
|
||||
|
||||
define void @check_alignment(%struct.U* %u, %struct.U* %v) {
|
||||
; CHECK-LABEL: check_alignment
|
||||
; CHECK: load i8, i8* {{.*}}, align 8
|
||||
; CHECK: load i8, i8* {{.*}}, align 1
|
||||
; CHECK: load i8, i8* {{.*}}, align 2
|
||||
; CHECK: load i8, i8* {{.*}}, align 1
|
||||
; CHECK: load i8, i8* {{.*}}, align 4
|
||||
; CHECK: load i8, i8* {{.*}}, align 1
|
||||
; CHECK: load i8, i8* {{.*}}, align 2
|
||||
; CHECK: load i8, i8* {{.*}}, align 1
|
||||
; CHECK: load i64, i64* {{.*}}, align 8
|
||||
; CHECK: store i8 {{.*}}, i8* {{.*}}, align 8
|
||||
; CHECK: store i8 {{.*}}, i8* {{.*}}, align 1
|
||||
; CHECK: store i8 {{.*}}, i8* {{.*}}, align 2
|
||||
; CHECK: store i8 {{.*}}, i8* {{.*}}, align 1
|
||||
; CHECK: store i8 {{.*}}, i8* {{.*}}, align 4
|
||||
; CHECK: store i8 {{.*}}, i8* {{.*}}, align 1
|
||||
; CHECK: store i8 {{.*}}, i8* {{.*}}, align 2
|
||||
; CHECK: store i8 {{.*}}, i8* {{.*}}, align 1
|
||||
; CHECK: store i64 {{.*}}, i64* {{.*}}, align 8
|
||||
%1 = load %struct.U, %struct.U* %u
|
||||
store %struct.U %1, %struct.U* %v
|
||||
ret void
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue