1; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s 2 3; CHECK: Entry or anchor intrinsic cannot have a convergencectrl token operand. 4; CHECK-NEXT: %t04_tok2 = call token 5; CHECK: Loop intrinsic must have a convergencectrl token operand. 6; CHECK-NEXT: %t04_tok3 = call token 7define void @basic_syntax() { 8 %t04_tok1 = call token @llvm.experimental.convergence.anchor() 9 %t04_tok2 = call token @llvm.experimental.convergence.anchor() [ "convergencectrl"(token %t04_tok1) ] 10 %t04_tok3 = call token @llvm.experimental.convergence.loop() 11 ret void 12} 13 14; CHECK: Convergence control tokens can only be produced by calls to the convergence control intrinsics. 15; CHECK-NEXT: %t04_tok1 = call token @produce_token() 16; CHECK-NEXT: call void @f() [ "convergencectrl"(token %t04_tok1) ] 17define void @wrong_token() { 18 %t04_tok1 = call token @produce_token() 19 call void @f() [ "convergencectrl"(token %t04_tok1) ] 20 ret void 21} 22 23; CHECK: Convergence control token can only be used in a convergent call. 24; CHECK-NEXT call void @g(){{.*}}%t05_tok1 25define void @missing.attribute() { 26 %t05_tok1 = call token @llvm.experimental.convergence.anchor() 27 call void @g() [ "convergencectrl"(token %t05_tok1) ] 28 ret void 29} 30 31; CHECK: The 'convergencectrl' bundle requires exactly one token use. 32; CHECK-NEXT: call void @g() 33define void @multiple_tokens() { 34 %t06_tok1 = call token @llvm.experimental.convergence.anchor() 35 %t06_tok2 = call token @llvm.experimental.convergence.anchor() 36 call void @g() [ "convergencectrl"(token %t06_tok2, token %t06_tok1) ] 37 ret void 38} 39 40; CHECK: The 'convergencectrl' bundle can occur at most once on a call 41; CHECK-NEXT: call void @g() 42define void @multiple_bundles() { 43 %t07_tok1 = call token @llvm.experimental.convergence.anchor() 44 %t07_tok2 = call token @llvm.experimental.convergence.anchor() 45 call void @g() [ "convergencectrl"(token %t07_tok2), "convergencectrl"(token %t07_tok1) ] 46 ret void 47} 48 49; CHECK: Cannot mix controlled and uncontrolled convergence in the same function 50; CHECK-NEXT call void @f() 51define void @mixed1() { 52 call void @g() ; not convergent 53 %t10_tok1 = call token @llvm.experimental.convergence.anchor() 54 call void @f() [ "convergencectrl"(token %t10_tok1) ] 55 call void @g() 56 call void @f() ; uncontrolled convergent 57 ret void 58} 59 60; CHECK: Cannot mix controlled and uncontrolled convergence in the same function 61; CHECK: %t20_tok1 = call token @llvm.experimental.convergence.anchor() 62; CHECK: Cannot mix controlled and uncontrolled convergence in the same function 63; CHECK: call void @f() [ "convergencectrl"(token %t20_tok1) ] 64define void @mixed2() { 65 call void @g() ; not convergent 66 call void @f() ; uncontrolled convergent 67 call void @g() 68 %t20_tok1 = call token @llvm.experimental.convergence.anchor() 69 call void @f() [ "convergencectrl"(token %t20_tok1) ] 70 ret void 71} 72 73; CHECK: Convergence region is not well-nested. 74; CHECK: %t30_tok2 75define void @region_nesting1() { 76 %t30_tok1 = call token @llvm.experimental.convergence.anchor() 77 %t30_tok2 = call token @llvm.experimental.convergence.anchor() 78 call void @f() [ "convergencectrl"(token %t30_tok1) ] 79 call void @f() [ "convergencectrl"(token %t30_tok2) ] 80 ret void 81} 82 83; CHECK: Convergence region is not well-nested. 84; CHECK: %t40_tok2 85define void @region_nesting2(i1 %cond) { 86A: 87 %t40_tok1 = call token @llvm.experimental.convergence.anchor() 88 %t40_tok2 = call token @llvm.experimental.convergence.anchor() 89 br i1 %cond, label %B, label %C 90 91B: 92 call void @f() [ "convergencectrl"(token %t40_tok1) ] 93 br label %C 94 95C: 96 call void @f() [ "convergencectrl"(token %t40_tok2) ] 97 ret void 98} 99 100; CHECK: Convergence token used by an instruction other than llvm.experimental.convergence.loop in a cycle that does not contain the token's definition. 101; CHECK: token %t50_tok1 102define void @use_in_cycle() { 103A: 104 %t50_tok1 = call token @llvm.experimental.convergence.anchor() 105 br label %B 106 107B: 108 call void @f() [ "convergencectrl"(token %t50_tok1) ] 109 br label %B 110} 111 112; CHECK: Entry intrinsic cannot be preceded by a convergent operation in the same basic block. 113; CHECK: %t60_tok1 114define void @entry_at_start(i32 %x, i32 %y) convergent { 115 %z = add i32 %x, %y 116 call void @f() 117 %t60_tok1 = call token @llvm.experimental.convergence.entry() 118 ret void 119} 120 121; CHECK: Entry intrinsic can occur only in a convergent function. 122; CHECK: %t60_tok2 123define void @entry_in_convergent(i32 %x, i32 %y) { 124 %t60_tok2 = call token @llvm.experimental.convergence.entry() 125 ret void 126} 127 128; CHECK: Loop intrinsic cannot be preceded by a convergent operation in the same basic block. 129; CHECK-NEXT: %h1 130; CHECK-SAME: %t60_tok3 131define void @loop_at_start(i32 %x, i32 %y) convergent { 132A: 133 %t60_tok3 = call token @llvm.experimental.convergence.entry() 134 br label %B 135B: 136 %z = add i32 %x, %y 137 ; This is not an error 138 %h2 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %t60_tok3) ] 139 br label %C 140C: 141 call void @f() 142 %h1 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %t60_tok3) ] 143 ret void 144} 145 146; CHECK: Entry intrinsic can occur only in the entry block. 147; CHECK: %t60_tok4 148define void @entry_at_entry(i32 %x, i32 %y) convergent { 149A: 150 %z = add i32 %x, %y 151 br label %B 152B: 153 %t60_tok4 = call token @llvm.experimental.convergence.entry() 154 ret void 155} 156 157; CHECK: Two static convergence token uses in a cycle that does not contain either token's definition. 158; CHECK: token %t70_tok1 159; CHECK: token %t70_tok2 160define void @multiple_hearts() { 161A: 162 %t70_tok1 = call token @llvm.experimental.convergence.anchor() 163 %t70_tok2 = call token @llvm.experimental.convergence.anchor() 164 br label %B 165 166B: 167 %h2 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %t70_tok2) ] 168 %h1 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %t70_tok1) ] 169 br label %B 170} 171 172; CHECK: Two static convergence token uses in a cycle that does not contain either token's definition. 173; CHECK: token %h0 174; CHECK: token %h0 175define void @multiple_hearts_nested(i1 %cond1, i1 %cond2) { 176A: 177 %t70_tok3 = call token @llvm.experimental.convergence.anchor() 178 br label %B 179 180B: 181 %h0 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %t70_tok3) ] 182 br i1 %cond1, label %C, label %B 183 184C: 185 %h1 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %h0) ] 186 %h2 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %h0) ] 187 br i1 %cond2, label %C, label %B 188} 189 190; CHECK: Cycle heart must dominate all blocks in the cycle. 191; CHECK: %h3 = call token 192; CHECK: label %C 193define void @invalid_heart_nested(i1 %cond1, i1 %cond2) { 194A: 195 %t70_tok4 = call token @llvm.experimental.convergence.anchor() 196 br label %B 197 198B: 199 br i1 %cond1, label %C, label %B 200 201C: 202 %h3 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %t70_tok4) ] 203 br i1 %cond2, label %C, label %B 204} 205 206; CHECK: Cycle heart must dominate all blocks in the cycle. 207; CHECK: %h4 = call token 208; CHECK: label %C 209define void @irreducible1(i1 %cond) { 210A: 211 %a = call token @llvm.experimental.convergence.anchor() 212 br i1 %cond, label %B, label %C 213 214B: 215 %b = call token @llvm.experimental.convergence.anchor() 216 br i1 %cond, label %C, label %D 217 218C: 219 %h4 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %a) ] 220 br i1 %cond, label %B, label %E 221 222D: 223 call void @f() [ "convergencectrl"(token %b) ] 224 br i1 %cond, label %B, label %F 225 226E: 227 call void @f() [ "convergencectrl"(token %h4) ] 228 br i1 %cond, label %C, label %F 229 230F: 231 call void @f() [ "convergencectrl"(token %a) ] 232 ret void 233} 234 235; Mirror image of @irreducible1 236; CHECK: Cycle heart must dominate all blocks in the cycle. 237; CHECK: %h5 = call token 238; CHECK: label %B 239define void @irreducible2(i1 %cond) { 240A: 241 %a = call token @llvm.experimental.convergence.anchor() 242 br i1 %cond, label %B, label %C 243 244B: 245 %h5 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %a) ] 246 br i1 %cond, label %C, label %D 247 248C: 249 %c = call token @llvm.experimental.convergence.anchor() 250 br i1 %cond, label %B, label %E 251 252D: 253 call void @f() [ "convergencectrl"(token %h5) ] 254 br i1 %cond, label %B, label %F 255 256E: 257 call void @f() [ "convergencectrl"(token %c) ] 258 br i1 %cond, label %C, label %F 259 260F: 261 call void @f() [ "convergencectrl"(token %a) ] 262 ret void 263} 264 265declare token @produce_token() 266 267declare void @f() convergent 268declare void @g() 269 270declare token @llvm.experimental.convergence.entry() 271declare token @llvm.experimental.convergence.anchor() 272declare token @llvm.experimental.convergence.loop() 273