Skip to content

Commit

Permalink
LICM: Do not loose alignment on promotion
Browse files Browse the repository at this point in the history
The promotion code lost any alignment information, when hoisting loads and
stores out of the loop. This lead to incorrect aligned memory accesses. We now
use the largest alignment we can prove to be correct.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134520 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
tobiasgrosser committed Jul 6, 2011
1 parent 2905776 commit df7102b
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 8 deletions.
38 changes: 30 additions & 8 deletions lib/Transforms/Scalar/LICM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,14 +606,16 @@ namespace {
SmallVectorImpl<BasicBlock*> &LoopExitBlocks;
AliasSetTracker &AST;
DebugLoc DL;
int Alignment;
public:
LoopPromoter(Value *SP,
const SmallVectorImpl<Instruction*> &Insts, SSAUpdater &S,
SmallPtrSet<Value*, 4> &PMA,
SmallVectorImpl<BasicBlock*> &LEB, AliasSetTracker &ast,
DebugLoc dl)
DebugLoc dl, int alignment)
: LoadAndStorePromoter(Insts, S, 0, 0), SomePtr(SP),
PointerMustAliases(PMA), LoopExitBlocks(LEB), AST(ast), DL(dl) {}
PointerMustAliases(PMA), LoopExitBlocks(LEB), AST(ast), DL(dl),
Alignment(alignment) {}

virtual bool isInstInList(Instruction *I,
const SmallVectorImpl<Instruction*> &) const {
Expand All @@ -635,6 +637,7 @@ namespace {
Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock);
Instruction *InsertPos = ExitBlock->getFirstNonPHI();
StoreInst *NewSI = new StoreInst(LiveInValue, SomePtr, InsertPos);
NewSI->setAlignment(Alignment);
NewSI->setDebugLoc(DL);
}
}
Expand Down Expand Up @@ -680,10 +683,14 @@ void LICM::PromoteAliasSet(AliasSet &AS) {
// It is safe to promote P if all uses are direct load/stores and if at
// least one is guaranteed to be executed.
bool GuaranteedToExecute = false;

SmallVector<Instruction*, 64> LoopUses;
SmallPtrSet<Value*, 4> PointerMustAliases;

// We start with an alignment of one and try to find instructions that allow
// us to prove better alignment.
unsigned Alignment = 1;

// Check that all of the pointers in the alias set have the same type. We
// cannot (yet) promote a memory location that is loaded and stored in
// different sizes.
Expand All @@ -706,24 +713,38 @@ void LICM::PromoteAliasSet(AliasSet &AS) {

// If there is an non-load/store instruction in the loop, we can't promote
// it.
if (isa<LoadInst>(Use))
unsigned InstAlignment;
if (LoadInst *load = dyn_cast<LoadInst>(Use)) {
assert(!cast<LoadInst>(Use)->isVolatile() && "AST broken");
else if (isa<StoreInst>(Use)) {
InstAlignment = load->getAlignment();
} else if (StoreInst *store = dyn_cast<StoreInst>(Use)) {
// Stores *of* the pointer are not interesting, only stores *to* the
// pointer.
if (Use->getOperand(1) != ASIV)
continue;
InstAlignment = store->getAlignment();
assert(!cast<StoreInst>(Use)->isVolatile() && "AST broken");
} else
return; // Not a load or store.


// If the alignment of this instruction allows us to specify a more
// restrictive (and performant) alignment and if we are sure this
// instruction will be executed, update the alignment.
// Larger is better, with the exception of 0 being the best alignment.
if ((InstAlignment > Alignment || InstAlignment == 0)
&& (Alignment != 0))
if (isSafeToExecuteUnconditionally(*Use)) {
GuaranteedToExecute = true;
Alignment = InstAlignment;
}

if (!GuaranteedToExecute)
GuaranteedToExecute = isSafeToExecuteUnconditionally(*Use);

LoopUses.push_back(Use);
}
}

// If there isn't a guaranteed-to-execute instruction, we can't promote.
if (!GuaranteedToExecute)
return;
Expand All @@ -746,13 +767,14 @@ void LICM::PromoteAliasSet(AliasSet &AS) {
SmallVector<PHINode*, 16> NewPHIs;
SSAUpdater SSA(&NewPHIs);
LoopPromoter Promoter(SomePtr, LoopUses, SSA, PointerMustAliases, ExitBlocks,
*CurAST, DL);
*CurAST, DL, Alignment);

// Set up the preheader to have a definition of the value. It is the live-out
// value from the preheader that uses in the loop will use.
LoadInst *PreheaderLoad =
new LoadInst(SomePtr, SomePtr->getName()+".promoted",
Preheader->getTerminator());
PreheaderLoad->setAlignment(Alignment);
PreheaderLoad->setDebugLoc(DL);
SSA.AddAvailableValue(Preheader, PreheaderLoad);

Expand Down
26 changes: 26 additions & 0 deletions test/Transforms/LICM/2011-07-06-Alignment.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
; RUN: opt -licm -S %s | FileCheck %s

@A = common global [1024 x float] zeroinitializer, align 4

define i32 @main() nounwind {
entry:
br label %for.cond

for.cond:
%indvar = phi i64 [ %indvar.next, %for.body ], [ 0, %entry ]
%arrayidx = getelementptr [1024 x float]* @A, i64 0, i64 3
%vecidx = bitcast float* %arrayidx to <4 x float>*
store <4 x float> zeroinitializer, <4 x float>* %vecidx, align 4
%indvar.next = add i64 %indvar, 1
%exitcond = icmp ne i64 %indvar, 1024
br i1 %exitcond, label %for.body, label %for.end

for.body:
br label %for.cond

for.end:
ret i32 0
}

;CHECK: store <4 x float> {{.*}} align 4

0 comments on commit df7102b

Please sign in to comment.