summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2018-08-31 15:53:05 +0000
committerHans Wennborg <hans@hanshq.net>2018-08-31 15:53:05 +0000
commit8be5c4fc9a8f2bb3f77d5175e021fcc350d6236a (patch)
tree9c90d5f14a286487f4f218cd0abf63612b68b917
parent485d2110bdd3de0d65aa932fe98a6b5f910a9c03 (diff)
Merging r341094:
------------------------------------------------------------------------ r341094 | efriedma | 2018-08-30 20:59:24 +0200 (Thu, 30 Aug 2018) | 11 lines [SROA] Fix alignment for uses of PHI nodes. Splitting an alloca can decrease the alignment of GEPs into the partition. Normally, rewriting accounts for this, but the code was missing for uses of PHI nodes and select instructions. Fixes https://bugs.llvm.org/show_bug.cgi?id=38707 . Differential Revision: https://reviews.llvm.org/D51335 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_70@341220 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Scalar/SROA.cpp42
-rw-r--r--test/Transforms/SROA/phi-and-select.ll32
2 files changed, 74 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/SROA.cpp b/lib/Transforms/Scalar/SROA.cpp
index de16b608f75..bf482bf5272 100644
--- a/lib/Transforms/Scalar/SROA.cpp
+++ b/lib/Transforms/Scalar/SROA.cpp
@@ -3046,6 +3046,42 @@ private:
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");
@@ -3069,6 +3105,9 @@ private:
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.
@@ -3093,6 +3132,9 @@ private:
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.
diff --git a/test/Transforms/SROA/phi-and-select.ll b/test/Transforms/SROA/phi-and-select.ll
index fb76548b1d1..e7ba2e89d79 100644
--- a/test/Transforms/SROA/phi-and-select.ll
+++ b/test/Transforms/SROA/phi-and-select.ll
@@ -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
+}