Teach InlineCost about address spaces
Summary:
I basically copied this patch from here:
https://reviews.llvm.org/D1251
But I skipped some of the refactoring to make the patch more clean.
The new outer3/inner3 test case in ptr-diff.ll triggers the
following assert without this patch:
lib/IR/Constants.cpp:1834: static llvm::Constant *llvm::ConstantExpr::getCompare(unsigned short, llvm::Constant *, llvm::Constant *, bool): Assertion `C1->getType() == C2->getType() && "Op types should be identical!"' failed.
The other new test cases makes sure that there is code coverage
for all modifications in InlineCost.cpp (getting different values
due to not fetching sizes for address space zero). I only guarantee
code coverage for those tests. The tests are not written in a way
that they would break if not having the corrections in
InlineCost.cpp. I found it quite hard to fine tune the tests into
getting different results based on the pointer sizes (except for
the test case where we hit an assert if not teaching InlineCost
about address spaces).
Reviewers: chandlerc, arsenm, haicheng
Reviewed By: arsenm
Subscribers: wdng, eraman, llvm-commits, haicheng
Differential Revision: https://reviews.llvm.org/D40455
llvm-svn: 321809
diff --git a/llvm/test/Transforms/Inline/ptr-diff.ll b/llvm/test/Transforms/Inline/ptr-diff.ll
index d4647b7..5ad3994 100644
--- a/llvm/test/Transforms/Inline/ptr-diff.ll
+++ b/llvm/test/Transforms/Inline/ptr-diff.ll
@@ -30,6 +30,33 @@
ret i32 %t
}
+define i32 @outer1_as1(i32 addrspace(1)* %ptr) {
+; CHECK-LABEL: @outer1_as1(
+; CHECK-NOT: call
+; CHECK: ret i32
+ %ptr1 = getelementptr inbounds i32, i32 addrspace(1)* %ptr, i32 0
+ %ptr2 = getelementptr inbounds i32, i32 addrspace(1)* %ptr, i32 42
+ %result = call i32 @inner1_as1(i32 addrspace(1)* %ptr1, i32 addrspace(1)* %ptr2)
+ ret i32 %result
+}
+
+; Make sure that the address space's larger size makes the ptrtoints
+; not no-ops preventing inlining
+define i32 @inner1_as1(i32 addrspace(1)* %begin, i32 addrspace(1)* %end) {
+ %begin.i = ptrtoint i32 addrspace(1)* %begin to i32
+ %end.i = ptrtoint i32 addrspace(1)* %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, i32 addrspace(1)* %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 comparisons.
@@ -59,6 +86,30 @@
ret i32 %t
}
+define i32 @outer3(i16* addrspace(1)* %ptr) {
+; CHECK-LABEL: @outer3(
+; CHECK-NOT: call i32
+; CHECK: ret i32 3
+; CHECK-LABEL: @inner3(
+ %result = call i32 @inner3(i16* addrspace(1)* %ptr)
+ ret i32 %result
+}
+
+define i32 @inner3(i16* addrspace(1)* %ptr) {
+ call void @extern()
+ %ptr.i = ptrtoint i16* addrspace(1)* %ptr to i64
+ %distance = sub i64 %ptr.i, %ptr.i
+ %icmp = icmp eq i64 %distance, 0
+ br i1 %icmp, label %then, label %else
+
+then:
+ ret i32 3
+
+else:
+ ret i32 5
+}
+
+
; The inttoptrs are free since it is a smaller integer to a larger
; pointer size
define i32 @inttoptr_free_cost(i32 %a, i32 %b, i32 %c) {