1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
declare void @unknown()
declare void @bar(ptr)
define void @foo() {
; CHECK-LABEL: define {{[^@]+}}@foo() {
; CHECK-NEXT: [[X:%.*]] = alloca i32, align 4
; CHECK-NEXT: call void @unknown()
; CHECK-NEXT: call void @bar(ptr noundef nonnull align 4 dereferenceable(4) [[X]])
; CHECK-NEXT: ret void
;
%x = alloca i32
call void @unknown()
call void @bar(ptr %x)
ret void
}
define internal ptr @returned_dead() {
; CHECK-LABEL: define {{[^@]+}}@returned_dead() {
; CHECK-NEXT: call void @unknown()
; CHECK-NEXT: ret ptr undef
;
call void @unknown()
ret ptr null
}
define void @caller1() {
; CHECK-LABEL: define {{[^@]+}}@caller1() {
; CHECK-NEXT: [[TMP1:%.*]] = call ptr @returned_dead()
; CHECK-NEXT: ret void
;
call ptr @returned_dead()
ret void
}
define internal void @argument_dead_callback_callee(ptr %c) {
; CHECK-LABEL: define {{[^@]+}}@argument_dead_callback_callee
; CHECK-SAME: (ptr noalias nocapture nofree readnone align 4294967296 [[C:%.*]]) {
; CHECK-NEXT: call void @unknown()
; CHECK-NEXT: ret void
;
call void @unknown()
ret void
}
define void @callback_caller() {
; TUNIT-LABEL: define {{[^@]+}}@callback_caller() {
; TUNIT-NEXT: call void @callback_broker(ptr noundef @argument_dead_callback_callee, ptr noalias nocapture nofree readnone align 4294967296 undef)
; TUNIT-NEXT: ret void
;
; CGSCC-LABEL: define {{[^@]+}}@callback_caller() {
; CGSCC-NEXT: call void @callback_broker(ptr noundef @argument_dead_callback_callee, ptr noalias nocapture nofree noundef readnone align 4294967296 null)
; CGSCC-NEXT: ret void
;
call void @callback_broker(ptr @argument_dead_callback_callee, ptr null)
ret void
}
; Drop the noundef if when we replace the call argument with `undef`. We use a
; varargs function as we cannot (yet) rewrite their signature. If we ever can,
; try to come up with a different scheme to verify the `noundef` is dropped if
; signature rewriting is not happening.
define internal void @callee_with_dead_noundef_arg(i1 noundef %create, ...) {
; TUNIT-LABEL: define {{[^@]+}}@callee_with_dead_noundef_arg
; TUNIT-SAME: (i1 [[CREATE:%.*]], ...) {
; TUNIT-NEXT: call void @unknown()
; TUNIT-NEXT: ret void
;
; CGSCC-LABEL: define {{[^@]+}}@callee_with_dead_noundef_arg
; CGSCC-SAME: (i1 noundef [[CREATE:%.*]], ...) {
; CGSCC-NEXT: call void @unknown()
; CGSCC-NEXT: ret void
;
call void @unknown()
ret void
}
define void @caller_with_unused_arg(i1 %c) {
; TUNIT-LABEL: define {{[^@]+}}@caller_with_unused_arg
; TUNIT-SAME: (i1 [[C:%.*]]) {
; TUNIT-NEXT: call void (i1, ...) @callee_with_dead_noundef_arg(i1 undef)
; TUNIT-NEXT: ret void
;
; CGSCC-LABEL: define {{[^@]+}}@caller_with_unused_arg
; CGSCC-SAME: (i1 noundef [[C:%.*]]) {
; CGSCC-NEXT: call void (i1, ...) @callee_with_dead_noundef_arg(i1 noundef [[C]])
; CGSCC-NEXT: ret void
;
call void (i1, ...) @callee_with_dead_noundef_arg(i1 %c)
ret void
}
define internal void @callee_with_dead_arg(i1 %create, ...) {
;
; CHECK-LABEL: define {{[^@]+}}@callee_with_dead_arg
; CHECK-SAME: (i1 [[CREATE:%.*]], ...) {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[IF_THEN3:%.*]]
; CHECK: if.then:
; CHECK-NEXT: unreachable
; CHECK: if.then3:
; CHECK-NEXT: call void @unknown()
; CHECK-NEXT: ret void
;
entry:
br i1 %create, label %if.then3, label %if.then
if.then: ; preds = %entry
ret void
if.then3: ; preds = %entry
call void @unknown()
ret void
}
; Drop the noundef if when we replace the call argument with `undef`. We use a
; varargs function as we cannot (yet) rewrite their signature. If we ever can,
; try to come up with a different scheme to verify the `noundef` is dropped if
; signature rewriting is not happening.
define void @caller_with_noundef_arg() {
;
; TUNIT-LABEL: define {{[^@]+}}@caller_with_noundef_arg() {
; TUNIT-NEXT: call void (i1, ...) @callee_with_dead_arg(i1 undef)
; TUNIT-NEXT: ret void
;
; CGSCC-LABEL: define {{[^@]+}}@caller_with_noundef_arg() {
; CGSCC-NEXT: call void (i1, ...) @callee_with_dead_arg(i1 noundef true)
; CGSCC-NEXT: ret void
;
call void (i1, ...) @callee_with_dead_arg(i1 noundef true)
ret void
}
declare !callback !0 void @callback_broker(ptr, ptr)
!1 = !{i64 0, i64 1, i1 false}
!0 = !{!1}
;.
; CHECK: [[META0:![0-9]+]] = !{!1}
; CHECK: [[META1:![0-9]+]] = !{i64 0, i64 1, i1 false}
;.
|