
`weightCalcHelper` is responsible for adding hints to MRI. Prior to this PR, we fell back on register ID as the last tie breaker for sorting hints. However, there is an opportunity to add an additional sorting characteristic: whether or not a register is a callee-saved-register. I thought of this idea because I saw that `AllocationOrder::create` calls `RegisterClassInfo::getOrder`, which returns a list of registers such that the registers which alias callee-saved-registers come last. From this, I conclude that the register allocator prefers an order such that callee-saved-registers are allocated after non-callee-saved-registers to avoid having to spill the CSR. This sorting characteristic occurs only as a tie breaker to the Weight calculation. This is a good idea since the weight calculation is pretty complex and I'm sure it is a pretty stable metric. I think its pretty reasonable to agree that whether a register is callee-saved or not is a better tie breaker than register ID. I think this is evident by the test diff, since the changes all seem to have no impact or improve the register allocation.
218 lines
7.3 KiB
LLVM
218 lines
7.3 KiB
LLVM
; RUN: split-file %s %t
|
|
; RUN: cat %t/main.ll %t/_align32.ll > %t/align32.ll
|
|
; RUN: llc -mtriple=x86_64-pc-linux-gnu -mattr=+mwaitx -x86-use-base-pointer=true -stackrealign %t/align32.ll -o - | FileCheck --check-prefix=CHECK --check-prefix=USE_BASE_64 %s
|
|
; RUN: llc -mtriple=x86_64-pc-linux-gnux32 -mattr=+mwaitx -x86-use-base-pointer=true -stackrealign %t/align32.ll -o - | FileCheck --check-prefix=CHECK --check-prefix=USE_BASE_32 %s
|
|
; RUN: llc -mtriple=x86_64-pc-linux-gnu -mattr=+mwaitx -x86-use-base-pointer=true %t/main.ll -o - | FileCheck --check-prefix=CHECK --check-prefix=NO_BASE_64 %s
|
|
; RUN: llc -mtriple=x86_64-pc-linux-gnux32 -mattr=+mwaitx -x86-use-base-pointer=true %t/main.ll -o - | FileCheck --check-prefix=CHECK --check-prefix=NO_BASE_32 %s
|
|
|
|
;--- main.ll
|
|
|
|
; This test checks that we save and restore the base pointer (ebx or rbx) in the
|
|
; presence of the mwaitx intrinsic which requires to use ebx for one of its
|
|
; argument.
|
|
; This function uses a dynamically allocated stack to force the use
|
|
; of a base pointer.
|
|
; After the call to the mwaitx intrinsic we do a volatile store to the
|
|
; dynamically allocated memory which will require the use of the base pointer.
|
|
; The base pointer should therefore be restored straight after the mwaitx
|
|
; instruction.
|
|
|
|
define void @test_baseptr(i64 %x, i64 %y, i32 %E, i32 %H, i32 %C) nounwind {
|
|
entry:
|
|
%ptr = alloca ptr, align 8
|
|
%0 = alloca i8, i64 %x, align 16
|
|
store ptr %0, ptr %ptr, align 8
|
|
call void @llvm.x86.mwaitx(i32 %E, i32 %H, i32 %C)
|
|
%1 = load ptr, ptr %ptr, align 8
|
|
%arrayidx = getelementptr inbounds i8, ptr %1, i64 %y
|
|
store volatile i8 42, ptr %arrayidx, align 1
|
|
ret void
|
|
}
|
|
; CHECK-LABEL: test_baseptr:
|
|
; USE_BASE_64: movq %rsp, %rbx
|
|
; Pass mwaitx first 2 arguments in eax and ecx respectively.
|
|
; USE_BASE_64: movl %ecx, %eax
|
|
; USE_BASE_64: movl %edx, %ecx
|
|
; Save base pointer.
|
|
; USE_BASE_64: movq %rbx, [[SAVE_rbx:%r([8-9]|1[0-5]|di|si)]]
|
|
; Set mwaitx ebx argument.
|
|
; USE_BASE_64: movl %r8d, %ebx
|
|
; USE_BASE_64-NEXT: mwaitx
|
|
; Restore base pointer.
|
|
; USE_BASE_64-NEXT: movq [[SAVE_rbx]], %rbx
|
|
|
|
; USE_BASE_32: movl %esp, %ebx
|
|
; Pass mwaitx first 2 arguments in eax and ecx respectively.
|
|
; USE_BASE_32: movl %ecx, %eax
|
|
; USE_BASE_32: movl %edx, %ecx
|
|
; Save base pointer.
|
|
; USE_BASE_32: movq %rbx, [[SAVE_rbx:%r(di|si)]]
|
|
; Set mwaitx ebx argument.
|
|
; USE_BASE_32: movl %r8d, %ebx
|
|
; USE_BASE_32-NEXT: mwaitx
|
|
; Restore base pointer.
|
|
; USE_BASE_32-NEXT: movq [[SAVE_rbx]], %rbx
|
|
|
|
; Pass mwaitx 3 arguments in eax, ecx, ebx
|
|
; NO_BASE_64: movl %ecx, %eax
|
|
; NO_BASE_64: movl %edx, %ecx
|
|
; NO_BASE_64: movl %r8d, %ebx
|
|
; No need to save base pointer.
|
|
; NO_BASE_64-NOT: movq %rbx
|
|
; NO_BASE_64: mwaitx
|
|
; No need to restore base pointer.
|
|
; NO_BASE_64-NOT: movq {{.*}}, %rbx
|
|
; NO_BASE_64-NEXT: {{.+$}}
|
|
|
|
; Pass mwaitx 3 arguments in eax, ecx, ebx
|
|
; NO_BASE_32: movl %ecx, %eax
|
|
; NO_BASE_32: movl %edx, %ecx
|
|
; NO_BASE_32: movl %r8d, %ebx
|
|
; No need to save base pointer.
|
|
; NO_BASE_32-NOT: movl %ebx
|
|
; NO_BASE_32: mwaitx
|
|
; No need to restore base pointer.
|
|
; NO_BASE_32-NOT: movl {{.*}}, %ebx
|
|
; NO_BASE_32-NEXT: {{.+$}}
|
|
|
|
; Test of the case where an opaque sp adjustement is introduced by a separate
|
|
; basic block which, combined with stack realignment, requires a base pointer.
|
|
@g = global i32 0, align 8
|
|
|
|
define void @test_opaque_sp_adjustment(i32 %E, i32 %H, i32 %C, i64 %x) {
|
|
entry:
|
|
%ptr = alloca ptr, align 8
|
|
call void @llvm.x86.mwaitx(i32 %E, i32 %H, i32 %C)
|
|
%g = load i32, ptr @g, align 4
|
|
%tobool = icmp ne i32 %g, 0
|
|
br i1 %tobool, label %if.then, label %if.end
|
|
|
|
if.then:
|
|
call void asm sideeffect "", "~{rsp},~{esp},~{dirflag},~{fpsr},~{flags}"()
|
|
br label %if.end
|
|
|
|
if.end:
|
|
%ptr2 = load ptr, ptr %ptr, align 8
|
|
%arrayidx = getelementptr inbounds i8, ptr %ptr2, i64 %x
|
|
store volatile i8 42, ptr %arrayidx, align 1
|
|
ret void
|
|
}
|
|
; CHECK-LABEL: test_opaque_sp_adjustment:
|
|
; USE_BASE_64: movq %rsp, %rbx
|
|
; Pass mwaitx first 2 arguments in eax and ecx respectively.
|
|
; USE_BASE_64: movl %esi, %eax
|
|
; USE_BASE_64: movl %edi, %ecx
|
|
; Save base pointer.
|
|
; USE_BASE_64: movq %rbx, [[SAVE_rbx:%r([8-9]|1[0-5]|di|si)]]
|
|
; Set mwaitx ebx argument.
|
|
; USE_BASE_64: movl %edx, %ebx
|
|
; USE_BASE_64-NEXT: mwaitx
|
|
; Restore base pointer.
|
|
; USE_BASE_64-NEXT: movq [[SAVE_rbx]], %rbx
|
|
|
|
; USE_BASE_32: movl %esp, %ebx
|
|
; Pass mwaitx first 2 arguments in eax and ecx respectively.
|
|
; USE_BASE_32: movl %esi, %eax
|
|
; USE_BASE_32: movl %edi, %ecx
|
|
; Save base pointer.
|
|
; USE_BASE_32: movq %rbx, [[SAVE_rbx:%r(di|si)]]
|
|
; Set mwaitx ebx argument.
|
|
; USE_BASE_32: movl %edx, %ebx
|
|
; USE_BASE_32-NEXT: mwaitx
|
|
; Restore base pointer.
|
|
; USE_BASE_32-NEXT: movq [[SAVE_rbx]], %rbx
|
|
|
|
; Pass mwaitx 3 arguments in eax, ecx, ebx
|
|
; NO_BASE_64: movl %esi, %eax
|
|
; NO_BASE_64: movl %edi, %ecx
|
|
; NO_BASE_64: movl %edx, %ebx
|
|
; No need to save base pointer.
|
|
; NO_BASE_64-NOT: movq %rbx
|
|
; NO_BASE_64: mwaitx
|
|
; NO_BASE_64-NOT: movq {{.*}}, %rbx
|
|
; NO_BASE_64-NEXT: {{.+$}}
|
|
|
|
; Pass mwaitx 3 arguments in eax, ecx, ebx
|
|
; NO_BASE_32: movl %esi, %eax
|
|
; NO_BASE_32: movl %edi, %ecx
|
|
; NO_BASE_32: movl %edx, %ebx
|
|
; No need to save base pointer.
|
|
; NO_BASE_32-NOT: movl %ebx
|
|
; NO_BASE_32: mwaitx
|
|
; No need to restore base pointer.
|
|
; NO_BASE_32-NOT: movl {{.*}}, %ebx
|
|
; NO_BASE_32-NEXT: {{.+$}}
|
|
|
|
; Test of the case where a variable size object is introduced by a separate
|
|
; basic block which, combined with stack realignment, requires a base pointer.
|
|
define void @test_variable_size_object(i32 %E, i32 %H, i32 %C, i64 %x) {
|
|
entry:
|
|
%ptr = alloca ptr, align 8
|
|
call void @llvm.x86.mwaitx(i32 %E, i32 %H, i32 %C)
|
|
%g = load i32, ptr @g, align 4
|
|
%tobool = icmp ne i32 %g, 0
|
|
br i1 %tobool, label %if.then, label %if.end
|
|
|
|
if.then:
|
|
%i5 = alloca i8, i64 %x, align 16
|
|
store ptr %i5, ptr %ptr, align 8
|
|
br label %if.end
|
|
|
|
if.end:
|
|
%ptr2 = load ptr, ptr %ptr, align 8
|
|
%arrayidx = getelementptr inbounds i8, ptr %ptr2, i64 %x
|
|
store volatile i8 42, ptr %arrayidx, align 1
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: test_variable_size_object:
|
|
; USE_BASE_64: movq %rsp, %rbx
|
|
; Pass mwaitx first 2 arguments in eax and ecx respectively.
|
|
; USE_BASE_64: movl %esi, %eax
|
|
; USE_BASE_64: movl %edi, %ecx
|
|
; Save base pointer.
|
|
; USE_BASE_64: movq %rbx, [[SAVE_rbx:%r([8-9]|1[0-5]|di|si)]]
|
|
; Set mwaitx ebx argument.
|
|
; USE_BASE_64: movl %edx, %ebx
|
|
; USE_BASE_64-NEXT: mwaitx
|
|
; Restore base pointer.
|
|
; USE_BASE_64-NEXT: movq [[SAVE_rbx]], %rbx
|
|
|
|
; USE_BASE_32: movl %esp, %ebx
|
|
; Pass mwaitx first 2 arguments in eax and ecx respectively.
|
|
; USE_BASE_32: movl %esi, %eax
|
|
; USE_BASE_32: movl %edi, %ecx
|
|
; Save base pointer.
|
|
; USE_BASE_32: movq %rbx, [[SAVE_rbx:%r(di|si)]]
|
|
; Set mwaitx ebx argument.
|
|
; USE_BASE_32: movl %edx, %ebx
|
|
; USE_BASE_32-NEXT: mwaitx
|
|
; Restore base pointer.
|
|
; USE_BASE_32-NEXT: movq [[SAVE_rbx]], %rbx
|
|
|
|
; Pass mwaitx 3 arguments in eax, ecx, ebx
|
|
; NO_BASE_64: movl %esi, %eax
|
|
; NO_BASE_64: movl %edi, %ecx
|
|
; NO_BASE_64: movl %edx, %ebx
|
|
; No need to save base pointer.
|
|
; NO_BASE_64-NOT: movq %rbx
|
|
; NO_BASE_64: mwaitx
|
|
; NO_BASE_64-NOT: movq {{.*}}, %rbx
|
|
; NO_BASE_64-NEXT: {{.+$}}
|
|
|
|
; Pass mwaitx 3 arguments in eax, ecx, ebx
|
|
; NO_BASE_32: movl %esi, %eax
|
|
; NO_BASE_32: movl %edi, %ecx
|
|
; NO_BASE_32: movl %edx, %ebx
|
|
; No need to save base pointer.
|
|
; NO_BASE_32-NOT: movl %ebx
|
|
; NO_BASE_32: mwaitx
|
|
; No need to restore base pointer.
|
|
; NO_BASE_32-NOT: movl {{.*}}, %ebx
|
|
; NO_BASE_32-NEXT: {{.+$}}
|
|
|
|
declare void @llvm.x86.mwaitx(i32, i32, i32) nounwind
|
|
;--- _align32.ll
|
|
!llvm.module.flags = !{!0}
|
|
!0 = !{i32 2, !"override-stack-alignment", i32 32}
|