Skip to content

Commit

Permalink
Push isDereferenceableAndAlignedPointer down into isSafeToLoadUncondi…
Browse files Browse the repository at this point in the history
…tionally

Reviewed By: reames

Differential Revision: http://reviews.llvm.org/D16226

llvm-svn: 258010
  • Loading branch information
arpilipe committed Jan 17, 2016
1 parent e1f273d commit f84dc06
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 17 deletions.
3 changes: 3 additions & 0 deletions llvm/lib/Analysis/Loads.cpp
Expand Up @@ -71,6 +71,9 @@ bool llvm::isSafeToLoadUnconditionally(Value *V, unsigned Align,
Align = DL.getABITypeAlignment(V->getType()->getPointerElementType());
assert(isPowerOf2_32(Align));

if (isDereferenceableAndAlignedPointer(V, Align, DL))
return true;

int64_t ByteOffset = 0;
Value *Base = V;
Base = GetPointerBaseWithConstantOffset(V, ByteOffset, DL);
Expand Down
11 changes: 3 additions & 8 deletions llvm/lib/Transforms/Scalar/SROA.cpp
Expand Up @@ -1192,8 +1192,7 @@ static bool isSafePHIToSpeculate(PHINode &PN) {
// If this pointer is always safe to load, or if we can prove that there
// is already a load in the block, then we can move the load to the pred
// block.
if (isDereferenceablePointer(InVal, DL) ||
isSafeToLoadUnconditionally(InVal, MaxAlign, TI))
if (isSafeToLoadUnconditionally(InVal, MaxAlign, TI))
continue;

return false;
Expand Down Expand Up @@ -1262,8 +1261,6 @@ static bool isSafeSelectToSpeculate(SelectInst &SI) {
Value *TValue = SI.getTrueValue();
Value *FValue = SI.getFalseValue();
const DataLayout &DL = SI.getModule()->getDataLayout();
bool TDerefable = isDereferenceablePointer(TValue, DL);
bool FDerefable = isDereferenceablePointer(FValue, DL);

for (User *U : SI.users()) {
LoadInst *LI = dyn_cast<LoadInst>(U);
Expand All @@ -1273,11 +1270,9 @@ static bool isSafeSelectToSpeculate(SelectInst &SI) {
// Both operands to the select need to be dereferencable, either
// absolutely (e.g. allocas) or at this point because we can see other
// accesses to it.
if (!TDerefable &&
!isSafeToLoadUnconditionally(TValue, LI->getAlignment(), LI))
if (!isSafeToLoadUnconditionally(TValue, LI->getAlignment(), LI))
return false;
if (!FDerefable &&
!isSafeToLoadUnconditionally(FValue, LI->getAlignment(), LI))
if (!isSafeToLoadUnconditionally(FValue, LI->getAlignment(), LI))
return false;
}

Expand Down
11 changes: 3 additions & 8 deletions llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp
Expand Up @@ -1141,21 +1141,17 @@ class AllocaPromoter : public LoadAndStorePromoter {
/// the select can be loaded unconditionally.
static bool isSafeSelectToSpeculate(SelectInst *SI) {
const DataLayout &DL = SI->getModule()->getDataLayout();
bool TDerefable = isDereferenceablePointer(SI->getTrueValue(), DL);
bool FDerefable = isDereferenceablePointer(SI->getFalseValue(), DL);

for (User *U : SI->users()) {
LoadInst *LI = dyn_cast<LoadInst>(U);
if (!LI || !LI->isSimple()) return false;

// Both operands to the select need to be dereferencable, either absolutely
// (e.g. allocas) or at this point because we can see other accesses to it.
if (!TDerefable &&
!isSafeToLoadUnconditionally(SI->getTrueValue(), LI->getAlignment(),
if (!isSafeToLoadUnconditionally(SI->getTrueValue(), LI->getAlignment(),
LI))
return false;
if (!FDerefable &&
!isSafeToLoadUnconditionally(SI->getFalseValue(), LI->getAlignment(),
if (!isSafeToLoadUnconditionally(SI->getFalseValue(), LI->getAlignment(),
LI))
return false;
}
Expand Down Expand Up @@ -1229,8 +1225,7 @@ static bool isSafePHIToSpeculate(PHINode *PN) {

// If this pointer is always safe to load, or if we can prove that there is
// already a load in the block, then we can move the load to the pred block.
if (isDereferenceablePointer(InVal, DL) ||
isSafeToLoadUnconditionally(InVal, MaxAlign, Pred->getTerminator()))
if (isSafeToLoadUnconditionally(InVal, MaxAlign, Pred->getTerminator()))
continue;

return false;
Expand Down
27 changes: 27 additions & 0 deletions llvm/test/Transforms/InstCombine/select.ll
Expand Up @@ -1296,6 +1296,20 @@ entry:
ret i32 %v
}

define i32 @test78_deref(i1 %flag, i32* dereferenceable(4) %x, i32* dereferenceable(4) %y, i32* %z) {
; Test that we can speculate the loads around the select even when we can't
; fold the load completely away.
; CHECK-LABEL: @test78_deref(
; CHECK: %[[V1:.*]] = load i32, i32* %x
; CHECK-NEXT: %[[V2:.*]] = load i32, i32* %y
; CHECK-NEXT: %[[S:.*]] = select i1 %flag, i32 %[[V1]], i32 %[[V2]]
; CHECK-NEXT: ret i32 %[[S]]
entry:
%p = select i1 %flag, i32* %x, i32* %y
%v = load i32, i32* %p
ret i32 %v
}

define i32 @test78_neg(i1 %flag, i32* %x, i32* %y, i32* %z) {
; The same as @test78 but we can't speculate the load because it can trap
; if under-aligned.
Expand All @@ -1313,6 +1327,19 @@ entry:
ret i32 %v
}

define i32 @test78_deref_neg(i1 %flag, i32* dereferenceable(2) %x, i32* dereferenceable(4) %y, i32* %z) {
; The same as @test78_deref but we can't speculate the load because
; one of the arguments is not sufficiently dereferenceable.
; CHECK-LABEL: @test78_deref_neg(
; CHECK: %p = select i1 %flag, i32* %x, i32* %y
; CHECK-NEXT: %v = load i32, i32* %p
; CHECK-NEXT: ret i32 %v
entry:
%p = select i1 %flag, i32* %x, i32* %y
%v = load i32, i32* %p
ret i32 %v
}

define float @test79(i1 %flag, float* %x, i32* %y, i32* %z) {
; Test that we can speculate the loads around the select even when we can't
; fold the load completely away.
Expand Down
20 changes: 19 additions & 1 deletion llvm/test/Transforms/TailCallElim/dont_reorder_load.ll
@@ -1,4 +1,4 @@
; RUN: opt < %s -tailcallelim -S | grep call | count 3
; RUN: opt < %s -tailcallelim -S | grep call | count 4
; PR4323

; Several cases where tail call elimination should not move the load above the
Expand Down Expand Up @@ -62,3 +62,21 @@ else: ; preds = %entry
%tmp10 = add i32 %tmp9, %tmp8 ; <i32> [#uses=1]
ret i32 %tmp10
}

; This load can NOT be moved above the call because the a_arg is not
; sufficiently dereferenceable.
define fastcc i32 @no_tailrecelim_4(i32* dereferenceable(2) %a_arg, i32 %a_len_arg, i32 %start_arg) readonly {
entry:
%tmp2 = icmp sge i32 %start_arg, %a_len_arg ; <i1> [#uses=1]
br i1 %tmp2, label %if, label %else

if: ; preds = %entry
ret i32 0

else: ; preds = %entry
%tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1]
%tmp8 = call fastcc i32 @no_tailrecelim_4(i32* %a_arg, i32 %a_len_arg, i32 %tmp7) ; <i32> [#uses=1]
%tmp9 = load i32, i32* %a_arg ; <i32> [#uses=1]
%tmp10 = add i32 %tmp9, %tmp8 ; <i32> [#uses=1]
ret i32 %tmp10
}
23 changes: 23 additions & 0 deletions llvm/test/Transforms/TailCallElim/reorder_load.ll
Expand Up @@ -122,3 +122,26 @@ recurse: ; preds = %else
%tmp10 = add i32 %second, %tmp8 ; <i32> [#uses=1]
ret i32 %tmp10
}

; This load can be moved above the call because the function won't write to it
; and the a_arg is dereferenceable.
define fastcc i32 @raise_load_5(i32* dereferenceable(4) %a_arg, i32 %a_len_arg, i32 %start_arg) readonly {
; CHECK-LABEL: @raise_load_5(
; CHECK-NOT: call
; CHECK: load i32, i32*
; CHECK-NOT: call
; CHECK: }
entry:
%tmp2 = icmp sge i32 %start_arg, %a_len_arg ; <i1> [#uses=1]
br i1 %tmp2, label %if, label %else

if: ; preds = %entry
ret i32 0

else: ; preds = %entry
%tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1]
%tmp8 = call fastcc i32 @raise_load_5(i32* %a_arg, i32 %a_len_arg, i32 %tmp7) ; <i32> [#uses=1]
%tmp9 = load i32, i32* %a_arg ; <i32> [#uses=1]
%tmp10 = add i32 %tmp9, %tmp8 ; <i32> [#uses=1]
ret i32 %tmp10
}

0 comments on commit f84dc06

Please sign in to comment.