1// RUN: %clang_cc1 -triple spir-unknown-unknown -emit-llvm %s -o - -fno-experimental-new-pass-manager | opt -instnamer -S | FileCheck -enable-var-scope %s 2// RUN: %clang_cc1 -triple spir-unknown-unknown -emit-llvm %s -o - -fexperimental-new-pass-manager | opt -instnamer -S | FileCheck -enable-var-scope %s 3 4// This is initially assumed convergent, but can be deduced to not require it. 5 6// CHECK-LABEL: define spir_func void @non_convfun() local_unnamed_addr #0 7// CHECK: ret void 8__attribute__((noinline)) 9void non_convfun(void) { 10 volatile int* p; 11 *p = 0; 12} 13 14void convfun(void) __attribute__((convergent)); 15void nodupfun(void) __attribute__((noduplicate)); 16 17// External functions should be assumed convergent. 18void f(void); 19void g(void); 20 21// Test two if's are merged and non_convfun duplicated. 22// The LLVM IR is equivalent to: 23// if (a) { 24// f(); 25// non_convfun(); 26// g(); 27// } else { 28// non_convfun(); 29// } 30// 31// CHECK-LABEL: define spir_func void @test_merge_if(i32 %a) local_unnamed_addr #1 { 32// CHECK: %[[tobool:.+]] = icmp eq i32 %a, 0 33// CHECK: br i1 %[[tobool]], label %[[if_end3_critedge:.+]], label %[[if_then:.+]] 34 35// CHECK: [[if_then]]: 36// CHECK: tail call spir_func void @f() 37// CHECK: tail call spir_func void @non_convfun() 38// CHECK: tail call spir_func void @g() 39 40// CHECK: br label %[[if_end3:.+]] 41 42// CHECK: [[if_end3_critedge]]: 43// CHECK: tail call spir_func void @non_convfun() 44// CHECK: br label %[[if_end3]] 45 46// CHECK: [[if_end3]]: 47// CHECK: ret void 48 49void test_merge_if(int a) { 50 if (a) { 51 f(); 52 } 53 non_convfun(); 54 if (a) { 55 g(); 56 } 57} 58 59// CHECK-DAG: declare spir_func void @f() local_unnamed_addr #2 60// CHECK-DAG: declare spir_func void @g() local_unnamed_addr #2 61 62 63// Test two if's are not merged. 64// CHECK-LABEL: define spir_func void @test_no_merge_if(i32 %a) local_unnamed_addr #1 65// CHECK: %[[tobool:.+]] = icmp eq i32 %a, 0 66// CHECK: br i1 %[[tobool]], label %[[if_end:.+]], label %[[if_then:.+]] 67// CHECK: [[if_then]]: 68// CHECK: tail call spir_func void @f() 69// CHECK-NOT: call spir_func void @convfun() 70// CHECK-NOT: call spir_func void @g() 71// CHECK: br label %[[if_end]] 72// CHECK: [[if_end]]: 73// CHECK-NOT: phi i1 74// CHECK: tail call spir_func void @convfun() #[[attr4:.+]] 75// CHECK: br i1 %[[tobool]], label %[[if_end3:.+]], label %[[if_then2:.+]] 76// CHECK: [[if_then2]]: 77// CHECK: tail call spir_func void @g() 78// CHECK: br label %[[if_end3:.+]] 79// CHECK: [[if_end3]]: 80// CHECK-LABEL: ret void 81 82void test_no_merge_if(int a) { 83 if (a) { 84 f(); 85 } 86 convfun(); 87 if(a) { 88 g(); 89 } 90} 91 92// CHECK: declare spir_func void @convfun(){{[^#]*}} #2 93 94// Test loop is unrolled for convergent function. 95// CHECK-LABEL: define spir_func void @test_unroll() local_unnamed_addr #1 96// CHECK: tail call spir_func void @convfun() #[[attr4:[0-9]+]] 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: tail call spir_func void @convfun() #[[attr4]] 106// CHECK-LABEL: ret void 107 108void test_unroll() { 109 for (int i = 0; i < 10; i++) 110 convfun(); 111} 112 113// Test loop is not unrolled for noduplicate function. 114// CHECK-LABEL: define spir_func void @test_not_unroll() 115// CHECK: br label %[[for_body:.+]] 116// CHECK: [[for_cond_cleanup:.+]]: 117// CHECK: ret void 118// CHECK: [[for_body]]: 119// CHECK: tail call spir_func void @nodupfun() #[[attr5:[0-9]+]] 120// CHECK-NOT: call spir_func void @nodupfun() 121// CHECK: br i1 %{{.+}}, label %[[for_body]], label %[[for_cond_cleanup]] 122 123void test_not_unroll() { 124 for (int i = 0; i < 10; i++) 125 nodupfun(); 126} 127 128// CHECK: declare spir_func void @nodupfun(){{[^#]*}} #[[attr3:[0-9]+]] 129 130// CHECK-LABEL: @assume_convergent_asm 131// CHECK: tail call void asm sideeffect "s_barrier", ""() #5 132kernel void assume_convergent_asm() 133{ 134 __asm__ volatile("s_barrier"); 135} 136 137// CHECK: attributes #0 = { nofree noinline norecurse nounwind " 138// CHECK: attributes #1 = { {{[^}]*}}convergent{{[^}]*}} } 139// CHECK: attributes #2 = { {{[^}]*}}convergent{{[^}]*}} } 140// CHECK: attributes #3 = { {{[^}]*}}convergent noduplicate{{[^}]*}} } 141// CHECK: attributes #4 = { {{[^}]*}}convergent{{[^}]*}} } 142// CHECK: attributes #5 = { {{[^}]*}}convergent{{[^}]*}} } 143// CHECK: attributes #6 = { {{[^}]*}}convergent noduplicate{{[^}]*}} } 144