diff options
author | Artur Pilipenko <apilipenko@azulsystems.com> | 2016-01-17 12:35:29 +0000 |
---|---|---|
committer | Artur Pilipenko <apilipenko@azulsystems.com> | 2016-01-17 12:35:29 +0000 |
commit | f84dc06e5b4ba4f96fb6ef24b2df848c512f41d6 (patch) | |
tree | ef60cf0b47410ba11641cd6ca9e56c9f3b070dc6 /llvm | |
parent | e1f273d900b004ac1d1331794079973f8949e78f (diff) | |
download | bcm5719-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.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/SROA.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp | 11 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/select.ll | 27 | ||||
-rw-r--r-- | llvm/test/Transforms/TailCallElim/dont_reorder_load.ll | 20 | ||||
-rw-r--r-- | llvm/test/Transforms/TailCallElim/reorder_load.ll | 23 |
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 +} |