1 // RUN
: %clang_cc1 -triple spir-unknown-unknown -emit-llvm %s -o - | FileCheck -enable-var-scope %s
3 // This is initially assumed convergent
, but can be deduced to not require it.
5 // CHECK-LABEL
: define
{{.
*}} spir_func void
@non_convfun
() local_unnamed_addr
#0
7 __attribute__
((noinline))
8 void non_convfun
(void) {
13 void convfun
(void) __attribute__
((convergent));
14 void nodupfun
(void) __attribute__
((noduplicate));
16 // External functions should be assumed convergent.
20 // Test two if
's are merged and non_convfun duplicated.
21 // The LLVM IR is equivalent to
:
30 // CHECK-LABEL
: define
{{.
*}} spir_func void
@test_merge_if
(i32 noundef %a
) local_unnamed_addr
#1 {
31 // CHECK
: %
[[tobool
:.
+]] = icmp eq i32 %a
, 0
32 // CHECK
: br i1 %
[[tobool]], label %[[if_end3_critedge:.+]], label %[[if_then:.+]]
34 // CHECK: [[if_then]]:
35 // CHECK: tail call spir_func void @f()
36 // CHECK: tail call spir_func void @non_convfun()
37 // CHECK: tail call spir_func void @g()
39 // CHECK: br label %[[if_end3:.+]]
41 // CHECK: [[if_end3_critedge]]:
42 // CHECK: tail call spir_func void @non_convfun()
43 // CHECK: br label %[[if_end3]]
45 // CHECK: [[if_end3]]:
48 void test_merge_if(int a) {
58 // CHECK-DAG: declare spir_func void @f() local_unnamed_addr #2
59 // CHECK-DAG: declare spir_func void @g() local_unnamed_addr #2
62 // Test two if's are not merged.
63 // CHECK-LABEL: define{{.*}} spir_func void @test_no_merge_if(i32 noundef %a) local_unnamed_addr #1
64 // CHECK: %[[tobool:.+]] = icmp eq i32 %a, 0
65 // CHECK: br i1 %[[tobool]], label %
[[if_end
:.
+]], label %
[[if_then
:.
+]]
66 // CHECK
: [[if_then]]:
67 // CHECK: tail call spir_func void @f()
68 // CHECK-NOT: call spir_func void @convfun()
69 // CHECK-NOT: call spir_func void @g()
70 // CHECK: br label %[[if_end]]
73 // CHECK: tail call spir_func void @convfun() #[[attr4:.+]]
74 // CHECK: br i1 %[[tobool]], label %[[if_end3:.+]], label %[[if_then2:.+]]
75 // CHECK: [[if_then2]]:
76 // CHECK: tail call spir_func void @g()
77 // CHECK: br label %[[if_end3:.+]]
78 // CHECK: [[if_end3]]:
79 // CHECK-LABEL: ret void
81 void test_no_merge_if(int a) {
91 // CHECK: declare spir_func void @convfun(){{[^#]*}} #2
93 // Test loop is unrolled for convergent function.
94 // CHECK-LABEL: define{{.*}} spir_func void @test_unroll() local_unnamed_addr #1
95 // CHECK: tail call spir_func void @convfun() #[[attr4:[0-9]+]]
96 // CHECK: tail call spir_func void @convfun() #[[attr4]]
97 // CHECK: tail call spir_func void @convfun() #[[attr4]]
98 // CHECK: tail call spir_func void @convfun() #[[attr4]]
99 // CHECK: tail call spir_func void @convfun() #[[attr4]]
100 // CHECK: tail call spir_func void @convfun() #[[attr4]]
101 // CHECK: tail call spir_func void @convfun() #[[attr4]]
102 // CHECK: tail call spir_func void @convfun() #[[attr4]]
103 // CHECK: tail call spir_func void @convfun() #[[attr4]]
104 // CHECK: tail call spir_func void @convfun() #[[attr4]]
105 // CHECK-LABEL: ret void
108 for (int i = 0; i < 10; i++)
112 // Test loop is not unrolled for noduplicate function.
113 // CHECK-LABEL: define{{.*}} spir_func void @test_not_unroll()
114 // CHECK: br label %[[for_body:.+]]
115 // CHECK: [[for_cond_cleanup:.+]]:
117 // CHECK: [[for_body]]:
118 // CHECK: tail call spir_func void @nodupfun() #[[attr5:[0-9]+]]
119 // CHECK-NOT: call spir_func void @nodupfun()
120 // CHECK: br i1 %{{.+}}, label %[[for_body]], label %[[for_cond_cleanup]]
122 void test_not_unroll() {
123 for (int i = 0; i < 10; i++)
127 // CHECK: declare spir_func void @nodupfun(){{[^#]*}} #[[attr3:[0-9]+]]
129 // CHECK-LABEL: @assume_convergent_asm
130 // CHECK: tail call void asm sideeffect "s_barrier", ""() #5
131 kernel void assume_convergent_asm()
133 __asm__ volatile("s_barrier");
136 // CHECK: attributes #0 = { nofree noinline norecurse nounwind "
137 // CHECK: attributes #1 = { {{[^}]*}}convergent{{[^}]*}} }
138 // CHECK: attributes #2 = { {{[^}]*}}convergent{{[^}]*}} }
139 // CHECK: attributes #3 = { {{[^}]*}}convergent noduplicate{{[^}]*}} }
140 // CHECK: attributes #4 = { {{[^}]*}}convergent{{[^}]*}} }
141 // CHECK: attributes #5 = { {{[^}]*}}convergent{{[^}]*}} }
142 // CHECK: attributes #6 = { {{[^}]*}}nounwind{{[^}]*}} }
143 // CHECK: attributes #7 = { {{[^}]*}}convergent noduplicate nounwind{{[^}]*}} }