llvm-project

Форк
0
/
cgscc-devirt-iteration.ll 
134 строки · 5.5 Кб
1
; The CGSCC pass manager includes an SCC iteration utility that tracks indirect
2
; calls that are turned into direct calls (devirtualization) and re-visits the
3
; SCC to expose those calls to the SCC-based IPO passes. We trigger
4
; devirtualization here with GVN which forwards a store through a load and to
5
; an indirect call.
6
;
7
; RUN: opt -aa-pipeline=basic-aa -passes='module(inferattrs),cgscc(function-attrs,function(gvn,instcombine))' -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=BEFORE
8
; RUN: opt -aa-pipeline=basic-aa -passes='module(inferattrs),cgscc(devirt<1>(function-attrs,function(gvn,instcombine)))' -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=AFTER --check-prefix=AFTER1
9
; RUN: opt -aa-pipeline=basic-aa -passes='module(inferattrs),cgscc(devirt<2>(function-attrs,function(gvn,instcombine)))' -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=AFTER --check-prefix=AFTER2
10
;
11
; RUN: not --crash opt -abort-on-max-devirt-iterations-reached -aa-pipeline=basic-aa -passes='module(inferattrs),cgscc(devirt<1>(function-attrs,function(gvn,instcombine)))' -S < %s
12
; RUN: opt -abort-on-max-devirt-iterations-reached -aa-pipeline=basic-aa -passes='module(inferattrs),cgscc(devirt<2>(function-attrs,function(gvn,instcombine)))' -S < %s
13
;
14
; We also verify that the real O2 pipeline catches these cases.
15
; RUN: opt -aa-pipeline=basic-aa -passes='default<O2>' -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=AFTER --check-prefix=AFTER2
16

17
declare void @readnone() readnone
18
; CHECK: Function Attrs: nofree nosync memory(none)
19
; CHECK-NEXT: declare void @readnone()
20

21
declare void @unknown()
22
; CHECK-NOT: Function Attrs
23
; CHECK-LABEL: declare void @unknown(){{ *$}}
24

25
; The @test1 function checks that when we refine an indirect call to a direct
26
; call we revisit the SCC passes to reflect the more precise information. This
27
; is the basic functionality.
28

29
define void @test1() {
30
; BEFORE-NOT: Function Attrs
31
; AFTER: Function Attrs: nofree nosync memory(none)
32
; CHECK-LABEL: define void @test1()
33
entry:
34
  %fptr = alloca ptr
35
  store ptr @readnone, ptr %fptr
36
  %f = load ptr, ptr %fptr
37
  call void %f()
38
  ret void
39
}
40

41
; The @test2_* functions check that when we need multiple (in this case 2)
42
; repetitions to compute some state that is incrementally exposed with each
43
; one, the limit on repetitions is enforced. So we make progress with
44
; one repetition but not as much as with three.
45
;
46
; This is somewhat awkward to test because we have to contrive to have a state
47
; repetition triggered and observed with very few passes. The technique here
48
; is to have one indirect call that can only be resolved when the entire SCC is
49
; deduced as readonly, and mark that indirect call at the call site as readonly
50
; to make that possible. This forces us to first deduce readonly, then
51
; devirtualize again, and then deduce readnone.
52

53
declare void @readnone_with_arg(ptr) readnone
54
; CHECK: Function Attrs: nofree nosync memory(none)
55
; CHECK-LABEL: declare void @readnone_with_arg(ptr)
56

57
define void @test2_a(ptr %ignore) {
58
; BEFORE-NOT: Function Attrs
59
; AFTER1: Function Attrs: nofree memory(read)
60
; AFTER2: Function Attrs: nofree nosync memory(none)
61
; BEFORE: define void @test2_a(ptr %ignore)
62
; AFTER: define void @test2_a(ptr readnone %ignore)
63
entry:
64
  %f1ptr = alloca ptr
65
  store ptr @readnone_with_arg, ptr %f1ptr
66
  %f1 = load ptr, ptr %f1ptr
67
  ; This indirect call is the first to be resolved, allowing us to deduce
68
  ; readonly but not (yet) readnone.
69
  call void %f1(ptr %ignore)
70
; CHECK: call void @readnone_with_arg(ptr %ignore)
71

72
  ; Bogus call to test2_b to make this a cycle.
73
  call void @test2_b()
74

75
  ret void
76
}
77

78
define void @test2_b() {
79
; BEFORE-NOT: Function Attrs
80
; AFTER1: Function Attrs: nofree memory(read)
81
; AFTER2: Function Attrs: nofree nosync memory(none)
82
; CHECK-LABEL: define void @test2_b()
83
entry:
84
  %f2ptr = alloca ptr
85
  store ptr @readnone, ptr %f2ptr
86
  ; Call the other function here to prevent forwarding until the SCC has had
87
  ; function attrs deduced.
88
  call void @test2_a(ptr %f2ptr)
89

90
  %f2 = load ptr, ptr %f2ptr
91
  ; This is the second indirect call to be resolved, and can only be resolved
92
  ; after we deduce 'readonly' for the rest of the SCC. Once it is
93
  ; devirtualized, we can deduce readnone for the SCC.
94
  call void %f2() readonly
95
; BEFORE: call void %f2()
96
; AFTER: call void @readnone()
97

98
  ret void
99
}
100

101
declare ptr @memcpy(ptr, ptr, i64)
102
; CHECK-LABEL: ptr @memcpy(
103

104
; The @test3 function checks that when we refine an indirect call to an
105
; intrinsic we still revisit the SCC pass. This also covers cases where the
106
; value handle itself doesn't persist due to the nature of how instcombine
107
; creates the memcpy intrinsic call, and we rely on the count of indirect calls
108
; decreasing and the count of direct calls increasing.
109
; Adding 'noinline' attribute to force attributes for improved matching.
110
define void @test3(ptr %src, ptr %dest, i64 %size) noinline {
111
; CHECK: Function Attrs
112
; CHECK-NOT: read
113
; CHECK-SAME: noinline
114
; BEFORE-LABEL: define void @test3(ptr %src, ptr %dest, i64 %size)
115
; AFTER-LABEL: define void @test3(ptr nocapture readonly %src, ptr nocapture writeonly %dest, i64 %size)
116
  %fptr = alloca ptr
117
  store ptr @memcpy, ptr %fptr
118
  %f = load ptr, ptr %fptr
119
  call ptr %f(ptr %dest, ptr %src, i64 %size)
120
; CHECK: call void @llvm.memcpy
121
  ret void
122
}
123

124
; A boring function that just keeps our declarations around.
125
define void @keep(ptr %sink) {
126
; CHECK-NOT: Function Attrs
127
; CHECK-LABEL: define void @keep(
128
entry:
129
  store volatile ptr @readnone, ptr %sink
130
  store volatile ptr @unknown, ptr %sink
131
  store volatile ptr @memcpy, ptr %sink
132
  call void @unknown()
133
  ret void
134
}
135

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.