summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorArtur Pilipenko <apilipenko@azulsystems.com>2016-01-17 12:35:29 +0000
committerArtur Pilipenko <apilipenko@azulsystems.com>2016-01-17 12:35:29 +0000
commitf84dc06e5b4ba4f96fb6ef24b2df848c512f41d6 (patch)
treeef60cf0b47410ba11641cd6ca9e56c9f3b070dc6 /llvm
parente1f273d900b004ac1d1331794079973f8949e78f (diff)
downloadbcm5719-llvm-f84dc06e5b4ba4f96fb6ef24b2df848c512f41d6.tar.gz
bcm5719-llvm-f84dc06e5b4ba4f96fb6ef24b2df848c512f41d6.zip
Push isDereferenceableAndAlignedPointer down into isSafeToLoadUnconditionally
Reviewed By: reames Differential Revision: http://reviews.llvm.org/D16226 llvm-svn: 258010
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Analysis/Loads.cpp3
-rw-r--r--llvm/lib/Transforms/Scalar/SROA.cpp11
-rw-r--r--llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp11
-rw-r--r--llvm/test/Transforms/InstCombine/select.ll27
-rw-r--r--llvm/test/Transforms/TailCallElim/dont_reorder_load.ll20
-rw-r--r--llvm/test/Transforms/TailCallElim/reorder_load.ll23
6 files changed, 78 insertions, 17 deletions
diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp
index bad745a992d..5b2113a19ee 100644
--- a/llvm/lib/Analysis/Loads.cpp
+++ b/llvm/lib/Analysis/Loads.cpp
@@ -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);
diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp
index bf3ec9616f1..dbbc1758b9f 100644
--- a/llvm/lib/Transforms/Scalar/SROA.cpp
+++ b/llvm/lib/Transforms/Scalar/SROA.cpp
@@ -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;
}
diff --git a/llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp
index 0fc6953350b..c89c763138f 100644
--- a/llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp
+++ b/llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp
@@ -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;
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index fdf1199a66f..7df3ba01998 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -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.
diff --git a/llvm/test/Transforms/TailCallElim/dont_reorder_load.ll b/llvm/test/Transforms/TailCallElim/dont_reorder_load.ll
index ac399a1bf5a..f8542799cc6 100644
--- a/llvm/test/Transforms/TailCallElim/dont_reorder_load.ll
+++ b/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
@@ -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
+}
diff --git a/llvm/test/Transforms/TailCallElim/reorder_load.ll b/llvm/test/Transforms/TailCallElim/reorder_load.ll
index b989bbf9547..2f9b692d099 100644
--- a/llvm/test/Transforms/TailCallElim/reorder_load.ll
+++ b/llvm/test/Transforms/TailCallElim/reorder_load.ll
@@ -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
+}
OpenPOWER on IntegriCloud