summaryrefslogtreecommitdiff
path: root/test/Transforms/Inline
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2012-03-14 23:19:53 +0000
committerChandler Carruth <chandlerc@gmail.com>2012-03-14 23:19:53 +0000
commit274d377ea68195989c3238fe96ce2ca812a12faf (patch)
treee9a23eb0299a10c12754432f23d2cc04ac536d2b /test/Transforms/Inline
parent8b11fdd8bb78840937ceebdfe44397dd8d2697fd (diff)
downloadllvm-274d377ea68195989c3238fe96ce2ca812a12faf.tar.gz
llvm-274d377ea68195989c3238fe96ce2ca812a12faf.tar.bz2
llvm-274d377ea68195989c3238fe96ce2ca812a12faf.tar.xz
Extend the inline cost calculation to account for bonuses due to
correlated pairs of pointer arguments at the callsite. This is designed to recognize the common C++ idiom of begin/end pointer pairs when the end pointer is a constant offset from the begin pointer. With the C-based idiom of a pointer and size, the inline cost saw the constant size calculation, and this provides the same level of information for begin/end pairs. In order to propagate this information we have to search for candidate operations on a pair of pointer function arguments (or derived from them) which would be simplified if the pointers had a known constant offset. Then the callsite analysis looks for such pointer pairs in the argument list, and applies the appropriate bonus. This helps LLVM detect that half of bounds-checked STL algorithms (such as hash_combine_range, and some hybrid sort implementations) disappear when inlined with a constant size input. However, it's not a complete fix due the inaccuracy of our cost metric for constants in general. I'm looking into that next. Benchmarks showed no significant code size change, and very minor performance changes. However, specific code such as hashing is showing significantly cleaner inlining decisions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152752 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/Transforms/Inline')
-rw-r--r--test/Transforms/Inline/ptr-diff.ll56
1 files changed, 56 insertions, 0 deletions
diff --git a/test/Transforms/Inline/ptr-diff.ll b/test/Transforms/Inline/ptr-diff.ll
new file mode 100644
index 0000000000..0b431d6d90
--- /dev/null
+++ b/test/Transforms/Inline/ptr-diff.ll
@@ -0,0 +1,56 @@
+; RUN: opt -inline < %s -S -o - -inline-threshold=10 | FileCheck %s
+
+define i32 @outer1() {
+; CHECK: @outer1
+; CHECK-NOT: call
+; CHECK: ret i32
+
+ %ptr = alloca i32
+ %ptr1 = getelementptr inbounds i32* %ptr, i32 0
+ %ptr2 = getelementptr inbounds i32* %ptr, i32 42
+ %result = call i32 @inner1(i32* %ptr1, i32* %ptr2)
+ ret i32 %result
+}
+
+define i32 @inner1(i32* %begin, i32* %end) {
+ %begin.i = ptrtoint i32* %begin to i32
+ %end.i = ptrtoint i32* %end to i32
+ %distance = sub i32 %end.i, %begin.i
+ %icmp = icmp sle i32 %distance, 42
+ br i1 %icmp, label %then, label %else
+
+then:
+ ret i32 3
+
+else:
+ %t = load i32* %begin
+ ret i32 %t
+}
+
+define i32 @outer2(i32* %ptr) {
+; Test that an inbounds GEP disables this -- it isn't safe in general as
+; wrapping changes the behavior of lessthan and greaterthan comparisions.
+; CHECK: @outer2
+; CHECK: call i32 @inner2
+; CHECK: ret i32
+
+ %ptr1 = getelementptr i32* %ptr, i32 0
+ %ptr2 = getelementptr i32* %ptr, i32 42
+ %result = call i32 @inner2(i32* %ptr1, i32* %ptr2)
+ ret i32 %result
+}
+
+define i32 @inner2(i32* %begin, i32* %end) {
+ %begin.i = ptrtoint i32* %begin to i32
+ %end.i = ptrtoint i32* %end to i32
+ %distance = sub i32 %end.i, %begin.i
+ %icmp = icmp sle i32 %distance, 42
+ br i1 %icmp, label %then, label %else
+
+then:
+ ret i32 3
+
+else:
+ %t = load i32* %begin
+ ret i32 %t
+}