blob: 99f6a87e44c0b18b5389a0eea9af0ab1cd27e462 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -S -passes=mergefunc < %s | FileCheck %s
; A function's address is observable when it is used as a value, so it must not
; be replaced with the address of a forwarding thunk's target.
define void @f(ptr %p) {
; CHECK-LABEL: define void @f(
; CHECK-SAME: ptr [[P:%.*]]) {
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], @f
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: ret void
;
%cmp = icmp eq ptr %p, @f
call void @llvm.assume(i1 %cmp)
ret void
}
define void @g(ptr %p) {
; CHECK-LABEL: define void @g(
; CHECK-SAME: ptr [[P:%.*]]) {
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], @g
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: ret void
;
%cmp = icmp eq ptr %p, @g
call void @llvm.assume(i1 %cmp)
ret void
}
; A self-reference passed as an argument is also observable and must remain a
; normal value comparison rather than a call-target comparison.
declare void @consume(ptr)
define void @arg_f() {
; CHECK-LABEL: define void @arg_f() {
; CHECK-NEXT: call void @consume(ptr @arg_f)
; CHECK-NEXT: ret void
;
call void @consume(ptr @arg_f)
ret void
}
define void @arg_g() {
; CHECK-LABEL: define void @arg_g() {
; CHECK-NEXT: call void @consume(ptr @arg_g)
; CHECK-NEXT: ret void
;
call void @consume(ptr @arg_g)
ret void
}
define i32 @main() {
; CHECK-LABEL: define i32 @main() {
; CHECK-NEXT: call void @f(ptr @f)
; CHECK-NEXT: call void @g(ptr @g)
; CHECK-NEXT: call void @arg_f()
; CHECK-NEXT: call void @arg_g()
; CHECK-NEXT: ret i32 0
;
call void @f(ptr @f)
call void @g(ptr @g)
call void @arg_f()
call void @arg_g()
ret i32 0
}