mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 05:06:06 +00:00

[GlobalISel] Implement convergence control tokens and intrinsics in GMIR In the IR translator, convert the LLVM token type to LLT::token(), which is an alias for the s0 type. These show up as implicit uses on convergent operations. Differential Revision: https://reviews.llvm.org/D158147
93 lines
2.7 KiB
C++
93 lines
2.7 KiB
C++
//===- ConvergenceVerifier.cpp - Verify convergence control -----*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/IR/ConvergenceVerifier.h"
|
|
#include "llvm/IR/Dominators.h"
|
|
#include "llvm/IR/GenericConvergenceVerifierImpl.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/IR/SSAContext.h"
|
|
|
|
using namespace llvm;
|
|
|
|
template <>
|
|
auto GenericConvergenceVerifier<SSAContext>::getConvOp(const Instruction &I)
|
|
-> ConvOpKind {
|
|
const auto *CB = dyn_cast<CallBase>(&I);
|
|
if (!CB)
|
|
return CONV_NONE;
|
|
switch (CB->getIntrinsicID()) {
|
|
default:
|
|
return CONV_NONE;
|
|
case Intrinsic::experimental_convergence_anchor:
|
|
return CONV_ANCHOR;
|
|
case Intrinsic::experimental_convergence_entry:
|
|
return CONV_ENTRY;
|
|
case Intrinsic::experimental_convergence_loop:
|
|
return CONV_LOOP;
|
|
}
|
|
}
|
|
|
|
template <>
|
|
void GenericConvergenceVerifier<SSAContext>::checkConvergenceTokenProduced(
|
|
const Instruction &I) {
|
|
return;
|
|
}
|
|
|
|
template <>
|
|
const Instruction *
|
|
GenericConvergenceVerifier<SSAContext>::findAndCheckConvergenceTokenUsed(
|
|
const Instruction &I) {
|
|
auto *CB = dyn_cast<CallBase>(&I);
|
|
if (!CB)
|
|
return nullptr;
|
|
|
|
unsigned Count =
|
|
CB->countOperandBundlesOfType(LLVMContext::OB_convergencectrl);
|
|
CheckOrNull(Count <= 1,
|
|
"The 'convergencectrl' bundle can occur at most once on a call",
|
|
{Context.print(CB)});
|
|
if (!Count)
|
|
return nullptr;
|
|
|
|
auto Bundle = CB->getOperandBundle(LLVMContext::OB_convergencectrl);
|
|
CheckOrNull(Bundle->Inputs.size() == 1 &&
|
|
Bundle->Inputs[0]->getType()->isTokenTy(),
|
|
"The 'convergencectrl' bundle requires exactly one token use.",
|
|
{Context.print(CB)});
|
|
auto *Token = Bundle->Inputs[0].get();
|
|
auto *Def = dyn_cast<Instruction>(Token);
|
|
|
|
CheckOrNull(Def && getConvOp(*Def) != CONV_NONE,
|
|
"Convergence control tokens can only be produced by calls to the "
|
|
"convergence control intrinsics.",
|
|
{Context.print(Token), Context.print(&I)});
|
|
|
|
if (Def)
|
|
Tokens[&I] = Def;
|
|
|
|
return Def;
|
|
}
|
|
|
|
template <>
|
|
bool GenericConvergenceVerifier<SSAContext>::isInsideConvergentFunction(
|
|
const Instruction &I) {
|
|
auto *F = I.getFunction();
|
|
return F->isConvergent();
|
|
}
|
|
|
|
template <>
|
|
bool GenericConvergenceVerifier<SSAContext>::isConvergent(
|
|
const Instruction &I) {
|
|
if (auto *CB = dyn_cast<CallBase>(&I)) {
|
|
return CB->isConvergent();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template class llvm::GenericConvergenceVerifier<SSAContext>;
|