mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-03 17:24:24 +00:00
Push isDereferenceableAndAlignedPointer down into isSafeToLoadUnconditionally
Reviewed By: reames Differential Revision: http://reviews.llvm.org/D16226 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@258010 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e74c24049c
commit
ae316aa098
@ -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);
|
||||
|
@ -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;
|
||||
@ -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);
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -1141,8 +1141,6 @@ public:
|
||||
/// 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);
|
||||
@ -1150,12 +1148,10 @@ 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(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;
|
||||
}
|
||||
@ -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;
|
||||
|
@ -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.
|
||||
@ -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.
|
||||
|
@ -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
|
||||
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user