@@ -978,6 +978,10 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
978
978
JumpDest LoopHeader = getJumpDestInCurrentScope (" while.cond" );
979
979
EmitBlock (LoopHeader.getBlock ());
980
980
981
+ if (CGM.shouldEmitConvergenceTokens ())
982
+ ConvergenceTokenStack.push_back (emitConvergenceLoopToken (
983
+ LoopHeader.getBlock (), ConvergenceTokenStack.back ()));
984
+
981
985
// Create an exit block for when the condition fails, which will
982
986
// also become the break target.
983
987
JumpDest LoopExit = getJumpDestInCurrentScope (" while.end" );
@@ -1079,6 +1083,9 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
1079
1083
// block.
1080
1084
if (llvm::EnableSingleByteCoverage)
1081
1085
incrementProfileCounter (&S);
1086
+
1087
+ if (CGM.shouldEmitConvergenceTokens ())
1088
+ ConvergenceTokenStack.pop_back ();
1082
1089
}
1083
1090
1084
1091
void CodeGenFunction::EmitDoStmt (const DoStmt &S,
@@ -1098,6 +1105,11 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S,
1098
1105
EmitBlockWithFallThrough (LoopBody, S.getBody ());
1099
1106
else
1100
1107
EmitBlockWithFallThrough (LoopBody, &S);
1108
+
1109
+ if (CGM.shouldEmitConvergenceTokens ())
1110
+ ConvergenceTokenStack.push_back (
1111
+ emitConvergenceLoopToken (LoopBody, ConvergenceTokenStack.back ()));
1112
+
1101
1113
{
1102
1114
RunCleanupsScope BodyScope (*this );
1103
1115
EmitStmt (S.getBody ());
@@ -1151,6 +1163,9 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S,
1151
1163
// block.
1152
1164
if (llvm::EnableSingleByteCoverage)
1153
1165
incrementProfileCounter (&S);
1166
+
1167
+ if (CGM.shouldEmitConvergenceTokens ())
1168
+ ConvergenceTokenStack.pop_back ();
1154
1169
}
1155
1170
1156
1171
void CodeGenFunction::EmitForStmt (const ForStmt &S,
@@ -1170,6 +1185,10 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
1170
1185
llvm::BasicBlock *CondBlock = CondDest.getBlock ();
1171
1186
EmitBlock (CondBlock);
1172
1187
1188
+ if (CGM.shouldEmitConvergenceTokens ())
1189
+ ConvergenceTokenStack.push_back (
1190
+ emitConvergenceLoopToken (CondBlock, ConvergenceTokenStack.back ()));
1191
+
1173
1192
const SourceRange &R = S.getSourceRange ();
1174
1193
LoopStack.push (CondBlock, CGM.getContext (), CGM.getCodeGenOpts (), ForAttrs,
1175
1194
SourceLocToDebugLoc (R.getBegin ()),
@@ -1279,6 +1298,9 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
1279
1298
// block.
1280
1299
if (llvm::EnableSingleByteCoverage)
1281
1300
incrementProfileCounter (&S);
1301
+
1302
+ if (CGM.shouldEmitConvergenceTokens ())
1303
+ ConvergenceTokenStack.pop_back ();
1282
1304
}
1283
1305
1284
1306
void
@@ -1301,6 +1323,10 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
1301
1323
llvm::BasicBlock *CondBlock = createBasicBlock (" for.cond" );
1302
1324
EmitBlock (CondBlock);
1303
1325
1326
+ if (CGM.shouldEmitConvergenceTokens ())
1327
+ ConvergenceTokenStack.push_back (
1328
+ emitConvergenceLoopToken (CondBlock, ConvergenceTokenStack.back ()));
1329
+
1304
1330
const SourceRange &R = S.getSourceRange ();
1305
1331
LoopStack.push (CondBlock, CGM.getContext (), CGM.getCodeGenOpts (), ForAttrs,
1306
1332
SourceLocToDebugLoc (R.getBegin ()),
@@ -1369,6 +1395,9 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
1369
1395
// block.
1370
1396
if (llvm::EnableSingleByteCoverage)
1371
1397
incrementProfileCounter (&S);
1398
+
1399
+ if (CGM.shouldEmitConvergenceTokens ())
1400
+ ConvergenceTokenStack.pop_back ();
1372
1401
}
1373
1402
1374
1403
void CodeGenFunction::EmitReturnOfRValue (RValue RV, QualType Ty) {
@@ -3158,3 +3187,67 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) {
3158
3187
3159
3188
return F;
3160
3189
}
3190
+
3191
+ namespace {
3192
+ // Returns the first convergence entry/loop/anchor instruction found in |BB|.
3193
+ // std::nullptr otherwise.
3194
+ llvm::IntrinsicInst *getConvergenceToken (llvm::BasicBlock *BB) {
3195
+ for (auto &I : *BB) {
3196
+ auto *II = dyn_cast<llvm::IntrinsicInst>(&I);
3197
+ if (II && llvm::isConvergenceControlIntrinsic (II->getIntrinsicID ()))
3198
+ return II;
3199
+ }
3200
+ return nullptr ;
3201
+ }
3202
+
3203
+ } // namespace
3204
+
3205
+ llvm::CallBase *
3206
+ CodeGenFunction::addConvergenceControlToken (llvm::CallBase *Input,
3207
+ llvm::Value *ParentToken) {
3208
+ llvm::Value *bundleArgs[] = {ParentToken};
3209
+ llvm::OperandBundleDef OB (" convergencectrl" , bundleArgs);
3210
+ auto Output = llvm::CallBase::addOperandBundle (
3211
+ Input, llvm::LLVMContext::OB_convergencectrl, OB, Input);
3212
+ Input->replaceAllUsesWith (Output);
3213
+ Input->eraseFromParent ();
3214
+ return Output;
3215
+ }
3216
+
3217
+ llvm::IntrinsicInst *
3218
+ CodeGenFunction::emitConvergenceLoopToken (llvm::BasicBlock *BB,
3219
+ llvm::Value *ParentToken) {
3220
+ CGBuilderTy::InsertPoint IP = Builder.saveIP ();
3221
+ if (BB->empty ())
3222
+ Builder.SetInsertPoint (BB);
3223
+ else
3224
+ Builder.SetInsertPoint (BB->getFirstInsertionPt ());
3225
+
3226
+ llvm::CallBase *CB = Builder.CreateIntrinsic (
3227
+ llvm::Intrinsic::experimental_convergence_loop, {}, {});
3228
+ Builder.restoreIP (IP);
3229
+
3230
+ llvm::CallBase *I = addConvergenceControlToken (CB, ParentToken);
3231
+ return cast<llvm::IntrinsicInst>(I);
3232
+ }
3233
+
3234
+ llvm::IntrinsicInst *
3235
+ CodeGenFunction::getOrEmitConvergenceEntryToken (llvm::Function *F) {
3236
+ llvm::BasicBlock *BB = &F->getEntryBlock ();
3237
+ llvm::IntrinsicInst *Token = getConvergenceToken (BB);
3238
+ if (Token)
3239
+ return Token;
3240
+
3241
+ // Adding a convergence token requires the function to be marked as
3242
+ // convergent.
3243
+ F->setConvergent ();
3244
+
3245
+ CGBuilderTy::InsertPoint IP = Builder.saveIP ();
3246
+ Builder.SetInsertPoint (&BB->front ());
3247
+ llvm::CallBase *I = Builder.CreateIntrinsic (
3248
+ llvm::Intrinsic::experimental_convergence_entry, {}, {});
3249
+ assert (isa<llvm::IntrinsicInst>(I));
3250
+ Builder.restoreIP (IP);
3251
+
3252
+ return cast<llvm::IntrinsicInst>(I);
3253
+ }
0 commit comments