Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Merging r341094: #124

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions lib/Transforms/Scalar/SROA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3046,6 +3046,42 @@ class llvm::sroa::AllocaSliceRewriter
return true;
}

void fixLoadStoreAlign(Instruction &Root) {
// This algorithm implements the same visitor loop as
// hasUnsafePHIOrSelectUse, and fixes the alignment of each load
// or store found.
SmallPtrSet<Instruction *, 4> Visited;
SmallVector<Instruction *, 4> Uses;
Visited.insert(&Root);
Uses.push_back(&Root);
do {
Instruction *I = Uses.pop_back_val();

if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
unsigned LoadAlign = LI->getAlignment();
if (!LoadAlign)
LoadAlign = DL.getABITypeAlignment(LI->getType());
LI->setAlignment(std::min(LoadAlign, getSliceAlign()));
continue;
}
if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
unsigned StoreAlign = SI->getAlignment();
if (!StoreAlign) {
Value *Op = SI->getOperand(0);
StoreAlign = DL.getABITypeAlignment(Op->getType());
}
SI->setAlignment(std::min(StoreAlign, getSliceAlign()));
continue;
}

assert(isa<BitCastInst>(I) || isa<PHINode>(I) ||
isa<SelectInst>(I) || isa<GetElementPtrInst>(I));
for (User *U : I->users())
if (Visited.insert(cast<Instruction>(U)).second)
Uses.push_back(cast<Instruction>(U));
} while (!Uses.empty());
}

bool visitPHINode(PHINode &PN) {
LLVM_DEBUG(dbgs() << " original: " << PN << "\n");
assert(BeginOffset >= NewAllocaBeginOffset && "PHIs are unsplittable");
Expand All @@ -3069,6 +3105,9 @@ class llvm::sroa::AllocaSliceRewriter
LLVM_DEBUG(dbgs() << " to: " << PN << "\n");
deleteIfTriviallyDead(OldPtr);

// Fix the alignment of any loads or stores using this PHI node.
fixLoadStoreAlign(PN);

// PHIs can't be promoted on their own, but often can be speculated. We
// check the speculation outside of the rewriter so that we see the
// fully-rewritten alloca.
Expand All @@ -3093,6 +3132,9 @@ class llvm::sroa::AllocaSliceRewriter
LLVM_DEBUG(dbgs() << " to: " << SI << "\n");
deleteIfTriviallyDead(OldPtr);

// Fix the alignment of any loads or stores using this select.
fixLoadStoreAlign(SI);

// Selects can't be promoted on their own, but often can be speculated. We
// check the speculation outside of the rewriter so that we see the
// fully-rewritten alloca.
Expand Down
32 changes: 32 additions & 0 deletions test/Transforms/SROA/phi-and-select.ll
Original file line number Diff line number Diff line change
Expand Up @@ -600,3 +600,35 @@ if.then5: ; preds = %if.then2, %if.end
store %struct.S undef, %struct.S* %f1, align 4
ret void
}

define i32 @phi_align(i32* %z) {
; CHECK-LABEL: @phi_align(
entry:
%a = alloca [8 x i8], align 8
; CHECK: alloca [7 x i8]

%a0x = getelementptr [8 x i8], [8 x i8]* %a, i64 0, i32 1
%a0 = bitcast i8* %a0x to i32*
%a1x = getelementptr [8 x i8], [8 x i8]* %a, i64 0, i32 4
%a1 = bitcast i8* %a1x to i32*
; CHECK: store i32 0, {{.*}}, align 1
store i32 0, i32* %a0, align 1
; CHECK: store i32 1, {{.*}}, align 1
store i32 1, i32* %a1, align 4
; CHECK: load {{.*}}, align 1
%v0 = load i32, i32* %a0, align 1
; CHECK: load {{.*}}, align 1
%v1 = load i32, i32* %a1, align 4
%cond = icmp sle i32 %v0, %v1
br i1 %cond, label %then, label %exit

then:
br label %exit

exit:
; CHECK: %phi = phi i32* [ {{.*}}, %then ], [ %z, %entry ]
; CHECK-NEXT: %result = load i32, i32* %phi, align 1
%phi = phi i32* [ %a1, %then ], [ %z, %entry ]
%result = load i32, i32* %phi, align 4
ret i32 %result
}