Files
clang-p2996/llvm/test/CodeGen/X86/call-rv-marker.ll
Simon Pilgrim 6697e3354f [X86] combineADC - fold ADC(C1,C2,Carry) -> ADC(0,C1+C2,Carry)
If we're not relying on the flag result, we can fold the constants together into the RHS immediate operand and set the LHS operand to zero, simplifying for further folds.

We could do something similar if the flag result is in use and the constant fold doesn't affect it, but I don't have any real test cases for this yet.

As suggested by @davezarzycki on Issue #35256

Differential Revision: https://reviews.llvm.org/D122482
2022-03-30 09:11:55 +01:00

264 lines
8.3 KiB
LLVM

; RUN: llc -mtriple=x86_64-apple-macosx -verify-machineinstrs -o - %s | FileCheck --check-prefix=CHECK %s
; TODO: support marker generation with GlobalISel
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
declare i8* @foo0(i32)
declare i8* @foo1()
declare void @llvm.objc.release(i8*)
declare void @objc_object(i8*)
declare void @foo2(i8*)
declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture)
declare %struct.S* @_ZN1SD1Ev(%struct.S* nonnull dereferenceable(1))
declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)
%struct.S = type { i8 }
@g = global i8* null, align 8
@fptr = global i8* ()* null, align 8
define i8* @rv_marker_1_retain() {
; CHECK-LABEL: rv_marker_1_retain:
; CHECK: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: callq _foo1
; CHECK-NEXT: movq %rax, %rdi
; CHECK-NEXT: callq _objc_retainAutoreleasedReturnValue
; CHECK-NEXT: popq %rcx
; CHECK-NEXT: retq
;
entry:
%call = call i8* @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
ret i8* %call
}
define i8* @rv_marker_1_unsafeClaim() {
; CHECK-LABEL: rv_marker_1_unsafeClaim:
; CHECK: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: callq _foo1
; CHECK-NEXT: movq %rax, %rdi
; CHECK-NEXT: callq _objc_unsafeClaimAutoreleasedReturnValue
; CHECK-NEXT: popq %rcx
; CHECK-NEXT: retq
;
entry:
%call = call i8* @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_unsafeClaimAutoreleasedReturnValue) ]
ret i8* %call
}
define void @rv_marker_2_select(i32 %c) {
; CHECK-LABEL: rv_marker_2_select:
; CHECK: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: cmpl $1, %edi
; CHECK-NEXT: adcl $1, %eax
; CHECK-NEXT: movl %eax, %edi
; CHECK-NEXT: callq _foo0
; CHECK-NEXT: movq %rax, %rdi
; CHECK-NEXT: callq _objc_retainAutoreleasedReturnValue
; CHECK-NEXT: movq %rax, %rdi
; CHECK-NEXT: popq %rax
; CHECK-NEXT: jmp _foo2
;
entry:
%tobool.not = icmp eq i32 %c, 0
%.sink = select i1 %tobool.not, i32 2, i32 1
%call1 = call i8* @foo0(i32 %.sink) [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
tail call void @foo2(i8* %call1)
ret void
}
define void @rv_marker_3() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: rv_marker_3
; CHECK: pushq %r14
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 24
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 32
; CHECK-NEXT: .cfi_offset %rbx, -24
; CHECK-NEXT: .cfi_offset %r14, -16
; CHECK-NEXT: callq _foo1
; CHECK-NEXT: movq %rax, %rdi
; CHECK-NEXT: callq _objc_retainAutoreleasedReturnValue
; CHECK-NEXT: movq %rax, %rbx
; CHECK-NEXT: Ltmp0:
;
entry:
%call = call i8* @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
invoke void @objc_object(i8* %call) #5
to label %invoke.cont unwind label %lpad
invoke.cont: ; preds = %entry
tail call void @llvm.objc.release(i8* %call)
ret void
lpad: ; preds = %entry
%0 = landingpad { i8*, i32 }
cleanup
tail call void @llvm.objc.release(i8* %call)
resume { i8*, i32 } %0
}
define void @rv_marker_4() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: rv_marker_4
; CHECK: pushq %r14
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 24
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 32
; CHECK-NEXT: .cfi_offset %rbx, -24
; CHECK-NEXT: .cfi_offset %r14, -16
; CHECK-NEXT: Ltmp3:
; CHECK-NEXT: callq _foo1
; CHECK-NEXT: movq %rax, %rdi
; CHECK-NEXT: callq _objc_retainAutoreleasedReturnValue
; CHECK-NEXT: Ltmp4:
;
entry:
%s = alloca %struct.S, align 1
%0 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 0
call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %0) #2
%call = invoke i8* @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
to label %invoke.cont unwind label %lpad
invoke.cont: ; preds = %entry
invoke void @objc_object(i8* %call) #5
to label %invoke.cont2 unwind label %lpad1
invoke.cont2: ; preds = %invoke.cont
tail call void @llvm.objc.release(i8* %call)
%call3 = call %struct.S* @_ZN1SD1Ev(%struct.S* nonnull dereferenceable(1) %s)
call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %0)
ret void
lpad: ; preds = %entry
%1 = landingpad { i8*, i32 }
cleanup
br label %ehcleanup
lpad1: ; preds = %invoke.cont
%2 = landingpad { i8*, i32 }
cleanup
tail call void @llvm.objc.release(i8* %call)
br label %ehcleanup
ehcleanup: ; preds = %lpad1, %lpad
%.pn = phi { i8*, i32 } [ %2, %lpad1 ], [ %1, %lpad ]
%call4 = call %struct.S* @_ZN1SD1Ev(%struct.S* nonnull dereferenceable(1) %s)
call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %0)
resume { i8*, i32 } %.pn
}
; TODO: This should use "callq *_fptr(%rip)".
define i8* @rv_marker_5_indirect_call() {
; CHECK-LABEL: rv_marker_5_indirect_call
; CHECK: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_offset %rbx, -16
; CHECK-NEXT: movq _fptr(%rip), %rax
; CHECK-NEXT: callq *%rax
; CHECK-NEXT: movq %rax, %rdi
; CHECK-NEXT: callq _objc_retainAutoreleasedReturnValue
; CHECK-NEXT: movq %rax, %rbx
; CHECK-NEXT: movq %rax, %rdi
; CHECK-NEXT: callq _foo2
; CHECK-NEXT: movq %rbx, %rax
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: retq
;
entry:
%lv = load i8* ()*, i8* ()** @fptr, align 8
%call = call i8* %lv() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
tail call void @foo2(i8* %call)
ret i8* %call
}
declare i8* @foo(i64, i64, i64)
define void @rv_marker_multiarg(i64 %a, i64 %b, i64 %c) {
; CHECK-LABEL: rv_marker_multiarg
; CHECK: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: movq %rdx, %rdi
; CHECK-NEXT: movq %rax, %rdx
; CHECK-NEXT: callq _foo
; CHECK-NEXT: movq %rax, %rdi
; CHECK-NEXT: callq _objc_retainAutoreleasedReturnValue
; CHECK-NEXT: popq %rax
; CHECK-NEXT: retq
;
%r = call i8* @foo(i64 %c, i64 %b, i64 %a) [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
ret void
}
define void @test_nonlazybind() {
; CHECK-LABEL: _test_nonlazybind:
; CHECK: bb.0:
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: callq *_foo_nonlazybind@GOTPCREL(%rip)
; CHECK-NEXT: movq %rax, %rdi
; CHECK-NEXT: callq _objc_retainAutoreleasedReturnValue
;
%call1 = notail call i8* @foo_nonlazybind() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
ret void
}
declare i8* @foo_nonlazybind() nonlazybind
declare i8* @objc_retainAutoreleasedReturnValue(i8*)
declare i8* @objc_unsafeClaimAutoreleasedReturnValue(i8*)
declare i32 @__gxx_personality_v0(...)
declare i8* @fn1()
declare i8* @fn2()
define i8* @rv_marker_block_placement(i1 %c.0) {
; CHECK-LABEL: _rv_marker_block_placement:
; CHECK: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: testb $1, %dil
; CHECK-NEXT: je LBB8_2
; CHECK-NEXT: ## %bb.1:
; CHECK-NEXT: callq _fn1
; CHECK-NEXT: movq %rax, %rdi
; CHECK-NEXT: callq _objc_retainAutoreleasedReturnValue
; CHECK-NEXT: jmp LBB8_3
; CHECK-NEXT: LBB8_2:
; CHECK-NEXT: callq _fn2
; CHECK-NEXT: movq %rax, %rdi
; CHECK-NEXT: callq _objc_retainAutoreleasedReturnValue
; CHECK-NEXT: LBB8_3:
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: popq %rcx
; CHECK-NEXT: retq
;
entry:
br i1 %c.0, label %then, label %else
then:
%call.0 = notail call i8* @fn1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
br label %exit
else:
%call.1 = notail call i8* @fn2() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
br label %exit
exit:
ret i8* null
}