Clang Project

clang_source_code/test/CodeGenOpenCL/convergent.cl
1// RUN: %clang_cc1 -triple spir-unknown-unknown -emit-llvm %s -o - | opt -instnamer -S | FileCheck -enable-var-scope %s
2
3// This is initially assumed convergent, but can be deduced to not require it.
4
5// CHECK-LABEL: define spir_func void @non_convfun() local_unnamed_addr #0
6// CHECK: ret void
7__attribute__((noinline))
8void non_convfun(void) {
9  volatile int* p;
10  *p = 0;
11}
12
13void convfun(void) __attribute__((convergent));
14void nodupfun(void) __attribute__((noduplicate));
15
16// External functions should be assumed convergent.
17void f(void);
18void g(void);
19
20// Test two if's are merged and non_convfun duplicated.
21// The LLVM IR is equivalent to:
22//    if (a) {
23//      f();
24//      non_convfun();
25//      g();
26//    } else {
27//      non_convfun();
28//    }
29//
30// CHECK-LABEL: define spir_func void @test_merge_if(i32 %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:.+]]
33
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()
38
39// CHECK: br label %[[if_end3:.+]]
40
41// CHECK: [[if_end3_critedge]]:
42// CHECK: tail call spir_func void @non_convfun()
43// CHECK: br label %[[if_end3]]
44
45// CHECK: [[if_end3]]:
46// CHECK: ret void
47
48void test_merge_if(int a) {
49  if (a) {
50    f();
51  }
52  non_convfun();
53  if (a) {
54    g();
55  }
56}
57
58// CHECK-DAG: declare spir_func void @f() local_unnamed_addr #2
59// CHECK-DAG: declare spir_func void @g() local_unnamed_addr #2
60
61
62// Test two if's are not merged.
63// CHECK-LABEL: define spir_func void @test_no_merge_if(i32 %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]]
71// CHECK: [[if_end]]:
72// CHECK:  %[[tobool_pr:.+]] = phi i1 [ true, %[[if_then]] ], [ false, %{{.+}} ]
73// CHECK:  tail call spir_func void @convfun() #[[attr4:.+]]
74// CHECK:  br i1 %[[tobool_pr]], label %[[if_then2:.+]], label %[[if_end3:.+]]
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
80
81void test_no_merge_if(int a) {
82  if (a) {
83    f();
84  }
85  convfun();
86  if(a) {
87    g();
88  }
89}
90
91// CHECK: declare spir_func void @convfun(){{[^#]*}} #2
92
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
106
107void test_unroll() {
108  for (int i = 0; i < 10; i++)
109    convfun();
110}
111
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:.+]]:
116// CHECK:  ret void
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]]
121
122void test_not_unroll() {
123  for (int i = 0; i < 10; i++)
124    nodupfun();
125}
126
127// CHECK: declare spir_func void @nodupfun(){{[^#]*}} #[[attr3:[0-9]+]]
128
129// CHECK-LABEL: @assume_convergent_asm
130// CHECK: tail call void asm sideeffect "s_barrier", ""() #5
131kernel void assume_convergent_asm()
132{
133  __asm__ volatile("s_barrier");
134}
135
136// CHECK: attributes #0 = { 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 = { {{[^}]*}}convergent noduplicate{{[^}]*}} }
143