blob: 66c32c287a32b08c0e65a015d2c479cbd555a90a [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc -mtriple=x86_64-linux -O0 -regalloc-fast-tied -verify-machineinstrs < %s | FileCheck %s
;; Tied operands, which the allocator rewrites itself instead of leaving to
;; TwoAddressInstructionPass.
;; The tied use dies at the instruction, so it takes over the tied def's
;; register and no copy is needed.
define i32 @tied_use_dies(i32 %a, i32 %b) nounwind {
; CHECK-LABEL: tied_use_dies:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: addl %esi, %eax
; CHECK-NEXT: retq
%c = add i32 %a, %b
ret i32 %c
}
;; The tied use is read again afterwards, so it has to be copied into the def's
;; register first, as TwoAddressInstructionPass would have done.
define i32 @tied_use_lives_on(i32 %a, i32 %b) nounwind {
; CHECK-LABEL: tied_use_lives_on:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: addl %esi, %eax
; CHECK-NEXT: addl %edi, %eax
; CHECK-NEXT: retq
%c = add i32 %a, %b
%d = add i32 %c, %a
ret i32 %d
}
;; The result is allocated first and has no copy to take a hint from; tracing
;; the hint through the tied def to the tied use reaches the argument's
;; register, so the argument copy coalesces away and the add runs in %edi.
define void @tied_hint_follows_tie(i32 %a, i32 %b, ptr %p) nounwind {
; CHECK-LABEL: tied_hint_follows_tie:
; CHECK: # %bb.0:
; CHECK-NEXT: addl %esi, %edi
; CHECK-NEXT: movl %edi, (%rdx)
; CHECK-NEXT: retq
%r = add i32 %a, %b
store volatile i32 %r, ptr %p
ret void
}
;; The early-clobber scan finds no other read: the use takes the register over.
define i32 @tied_early_clobber(i32 %a) nounwind {
; CHECK-LABEL: tied_early_clobber:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: #APP
; CHECK-NEXT: # %eax %eax %edi
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: retq
%r = call i32 asm "// $0 $1 $2", "=&r,0,r"(i32 %a, i32 %a)
ret i32 %r
}