mirror of
https://github.com/RPCSX/llvm.git
synced 2026-01-31 01:05:23 +01:00
Recommiting after adding check to avoid miscomputing alias information on addresses of the same base but different subindices. Memory accesses offset from frame indices may alias, e.g., we may merge write from function arguments passed on the stack when they are contiguous. As a result, when checking aliasing, we consider the underlying frame index's offset from the stack pointer. Static allocs are realized as stack objects in SelectionDAG, but its offset is not set until post-DAG causing DAGCombiner's alias check to consider access to static allocas to frequently alias. Modify isAlias to consider access between static allocas and access from other frame objects to be considered aliasing. Many test changes are included here. Most are fixes for tests which indirectly relied on our aliasing ability and needed to be modified to preserve their original intent. The remaining tests have minor improvements due to relaxed ordering. The exception is CodeGen/X86/2011-10-19-widen_vselect.ll which has a minor degradation dispite though the pre-legalized DAG is improved. Reviewers: rnk, mkuper, jonpa, hfinkel, uweigand Reviewed By: rnk Subscribers: sdardis, nemanjai, javed.absar, llvm-commits Differential Revision: https://reviews.llvm.org/D33345 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@308025 91177308-0d34-0410-b5e6-96231b3b80d8
137 lines
8.3 KiB
LLVM
137 lines
8.3 KiB
LLVM
; RUN: llc -verify-machineinstrs -stack-symbol-ordering=0 < %s | FileCheck %s
|
|
|
|
target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
|
|
target triple = "x86_64-pc-linux-gnu"
|
|
|
|
; This test is checking to make sure that we reuse the same stack slots
|
|
; for GC values spilled over two different call sites. Since the order
|
|
; of GC arguments differ, niave lowering code would insert loads and
|
|
; stores to rearrange items on the stack. We need to make sure (for
|
|
; performance) that this doesn't happen.
|
|
define i32 @back_to_back_calls(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c) #1 gc "statepoint-example" {
|
|
; CHECK-LABEL: back_to_back_calls
|
|
; The exact stores don't matter, but there need to be three stack slots created
|
|
; CHECK-DAG: movq %rdi, 16(%rsp)
|
|
; CHECK-DAG: movq %rdx, 8(%rsp)
|
|
; CHECK-DAG: movq %rsi, (%rsp)
|
|
; There should be no more than three moves
|
|
; CHECK-NOT: movq
|
|
%safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c)
|
|
%a1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 12, i32 12)
|
|
%b1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 12, i32 13)
|
|
%c1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 12, i32 14)
|
|
; CHECK: callq
|
|
; This is the key check. There should NOT be any memory moves here
|
|
; CHECK-NOT: movq
|
|
%safepoint_token2 = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %c1, i32 addrspace(1)* %b1, i32 addrspace(1)* %a1)
|
|
%a2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2, i32 12, i32 14)
|
|
%b2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2, i32 12, i32 13)
|
|
%c2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2, i32 12, i32 12)
|
|
; CHECK: callq
|
|
ret i32 1
|
|
}
|
|
|
|
; This test simply checks that minor changes in vm state don't prevent slots
|
|
; being reused for gc values.
|
|
define i32 @reserve_first(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c) #1 gc "statepoint-example" {
|
|
; CHECK-LABEL: reserve_first
|
|
; The exact stores don't matter, but there need to be three stack slots created
|
|
; CHECK-DAG: movq %rdi, 16(%rsp)
|
|
; CHECK-DAG: movq %rdx, 8(%rsp)
|
|
; CHECK-DAG: movq %rsi, (%rsp)
|
|
%safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c)
|
|
%a1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 12, i32 12)
|
|
%b1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 12, i32 13)
|
|
%c1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 12, i32 14)
|
|
; CHECK: callq
|
|
; This is the key check. There should NOT be any memory moves here
|
|
; CHECK-NOT: movq
|
|
%safepoint_token2 = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 addrspace(1)* %a1, i32 0, i32 addrspace(1)* %c1, i32 0, i32 0, i32 addrspace(1)* %c1, i32 addrspace(1)* %b1, i32 addrspace(1)* %a1)
|
|
%a2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2, i32 12, i32 14)
|
|
%b2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2, i32 12, i32 13)
|
|
%c2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2, i32 12, i32 12)
|
|
; CHECK: callq
|
|
ret i32 1
|
|
}
|
|
|
|
; Check that we reuse the same stack slot across multiple calls. The use of
|
|
; more than two calls here is critical. We've had a bug which allowed reuse
|
|
; exactly once which went undetected for a long time.
|
|
define i32 @back_to_back_deopt(i32 %a, i32 %b, i32 %c) #1
|
|
gc "statepoint-example" {
|
|
; CHECK-LABEL: back_to_back_deopt
|
|
; The exact stores don't matter, but there need to be three stack slots created
|
|
; CHECK-DAG: movl %ebx, 12(%rsp)
|
|
; CHECK-DAG: movl %ebp, 8(%rsp)
|
|
; CHECK-DAG: movl %r14d, 4(%rsp)
|
|
; CHECK: callq
|
|
; CHECK-DAG: movl %ebx, 12(%rsp)
|
|
; CHECK-DAG: movl %ebp, 8(%rsp)
|
|
; CHECK-DAG: movl %r14d, 4(%rsp)
|
|
; CHECK: callq
|
|
; CHECK-DAG: movl %ebx, 12(%rsp)
|
|
; CHECK-DAG: movl %ebp, 8(%rsp)
|
|
; CHECK-DAG: movl %r14d, 4(%rsp)
|
|
; CHECK: callq
|
|
; CHECK-DAG: movl %ebx, 12(%rsp)
|
|
; CHECK-DAG: movl %ebp, 8(%rsp)
|
|
; CHECK-DAG: movl %r14d, 4(%rsp)
|
|
; CHECK: callq
|
|
call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 3, i32 %a, i32 %b, i32 %c)
|
|
call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 3, i32 %a, i32 %b, i32 %c)
|
|
call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 3, i32 %a, i32 %b, i32 %c)
|
|
call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 3, i32 %a, i32 %b, i32 %c)
|
|
ret i32 1
|
|
}
|
|
|
|
; Test that stack slots are reused for invokes
|
|
define i32 @back_to_back_invokes(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c) #1 gc "statepoint-example" personality i32 ()* @"personality_function" {
|
|
; CHECK-LABEL: back_to_back_invokes
|
|
entry:
|
|
; The exact stores don't matter, but there need to be three stack slots created
|
|
; CHECK-DAG: movq %rdi, 16(%rsp)
|
|
; CHECK-DAG: movq %rdx, 8(%rsp)
|
|
; CHECK-DAG: movq %rsi, (%rsp)
|
|
; CHECK: callq
|
|
%safepoint_token = invoke token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c)
|
|
to label %normal_return unwind label %exceptional_return
|
|
|
|
normal_return:
|
|
%a1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 12, i32 12)
|
|
%b1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 12, i32 13)
|
|
%c1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 12, i32 14)
|
|
; Should work even through bitcasts
|
|
%c1.casted = bitcast i32 addrspace(1)* %c1 to i8 addrspace(1)*
|
|
; This is the key check. There should NOT be any memory moves here
|
|
; CHECK-NOT: movq
|
|
; CHECK: callq
|
|
%safepoint_token2 = invoke token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %c1.casted, i32 addrspace(1)* %b1, i32 addrspace(1)* %a1)
|
|
to label %normal_return2 unwind label %exceptional_return2
|
|
|
|
normal_return2:
|
|
%a2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2, i32 12, i32 14)
|
|
%b2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2, i32 12, i32 13)
|
|
%c2 = tail call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token2, i32 12, i32 12)
|
|
ret i32 1
|
|
|
|
exceptional_return:
|
|
%landing_pad = landingpad { i8*, i32 }
|
|
cleanup
|
|
ret i32 0
|
|
|
|
exceptional_return2:
|
|
%landing_pad2 = landingpad { i8*, i32 }
|
|
cleanup
|
|
ret i32 0
|
|
}
|
|
|
|
; Function Attrs: nounwind
|
|
declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) #3
|
|
declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32) #3
|
|
|
|
declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
|
|
|
|
declare i32 @"personality_function"()
|
|
|
|
attributes #1 = { uwtable }
|