1; Test to ensure no inlining is allowed into a caller with fewer nobuiltin attributes.
2; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -S -inline | FileCheck %s
3; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -S -passes='cgscc(inline)' | FileCheck %s
4
5; Make sure we don't inline callees into a caller with a superset of the
6; no builtin attributes when -inline-caller-superset-nobuiltin=false.
7; RUN: opt < %s -inline-caller-superset-nobuiltin=false -mtriple=x86_64-unknown-linux-gnu -S -passes='cgscc(inline)' | FileCheck %s --check-prefix=NOSUPERSET
8
9target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
10target triple = "x86_64-unknown-linux-gnu"
11
12define i32 @allbuiltins() {
13entry:
14  %call = call i32 (...) @externalfunc()
15  ret i32 %call
16; CHECK-LABEL: allbuiltins
17; CHECK: call i32 (...) @externalfunc()
18}
19declare i32 @externalfunc(...)
20
21; We can inline a function that allows all builtins into one with a single
22; nobuiltin.
23define i32 @nobuiltinmemcpy() #0 {
24entry:
25  %call = call i32 @allbuiltins()
26  ret i32 %call
27; CHECK-LABEL: nobuiltinmemcpy
28; CHECK-NOT: call i32 @allbuiltins()
29; NOSUPERSET-LABEL: nobuiltinmemcpy
30; NOSUPERSET: call i32 @allbuiltins()
31}
32
33; We can inline a function that allows all builtins into one with all
34; nobuiltins.
35define i32 @nobuiltins() #1 {
36entry:
37  %call = call i32 @allbuiltins()
38  ret i32 %call
39; CHECK-LABEL: nobuiltins
40; CHECK-NOT: call i32 @allbuiltins()
41; NOSUPERSET-LABEL: nobuiltins
42; NOSUPERSET: call i32 @allbuiltins()
43}
44
45; We can inline a function with a single nobuiltin into one with all nobuiltins.
46define i32 @nobuiltins2() #1 {
47entry:
48  %call = call i32 @nobuiltinmemcpy()
49  ret i32 %call
50; CHECK-LABEL: nobuiltins2
51; CHECK-NOT: call i32 @nobuiltinmemcpy()
52; NOSUPERSET-LABEL: nobuiltins2
53; NOSUPERSET: call i32 @nobuiltinmemcpy()
54}
55
56; We can't inline a function with any given nobuiltin into one that allows all
57; builtins.
58define i32 @allbuiltins2() {
59entry:
60  %call = call i32 @nobuiltinmemcpy()
61  ret i32 %call
62; CHECK-LABEL: allbuiltins2
63; CHECK: call i32 @nobuiltinmemcpy()
64; NOSUPERSET-LABEL: allbuiltins2
65; NOSUPERSET: call i32 @nobuiltinmemcpy()
66}
67
68; We can't inline a function with all nobuiltins into one that allows all
69; builtins.
70define i32 @allbuiltins3() {
71entry:
72  %call = call i32 @nobuiltins()
73  ret i32 %call
74; CHECK-LABEL: allbuiltins3
75; CHECK: call i32 @nobuiltins()
76; NOSUPERSET-LABEL: allbuiltins3
77; NOSUPERSET: call i32 @nobuiltins()
78}
79
80; We can't inline a function with a specific nobuiltin into one with a
81; different specific nobuiltin.
82define i32 @nobuiltinmemset() #2 {
83entry:
84  %call = call i32 @nobuiltinmemcpy()
85  ret i32 %call
86; CHECK-LABEL: nobuiltinmemset
87; CHECK: call i32 @nobuiltinmemcpy()
88; NOSUPERSET-LABEL: nobuiltinmemset
89; NOSUPERSET: call i32 @nobuiltinmemcpy()
90}
91
92attributes #0 = { "no-builtin-memcpy" }
93attributes #1 = { "no-builtins" }
94attributes #2 = { "no-builtin-memset" }
95