| //===- MachineConvergenceVerifier.cpp - Verify convergencectrl ------------===// |
| // |
| // 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/CodeGen/MachineConvergenceVerifier.h" |
| #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" |
| #include "llvm/CodeGen/MachineDominators.h" |
| #include "llvm/CodeGen/MachineRegisterInfo.h" |
| #include "llvm/CodeGen/MachineSSAContext.h" |
| #include "llvm/IR/GenericConvergenceVerifierImpl.h" |
| |
| using namespace llvm; |
| |
| template <> |
| auto GenericConvergenceVerifier<MachineSSAContext>::getConvOp( |
| const MachineInstr &MI) -> ConvOpKind { |
| switch (MI.getOpcode()) { |
| default: |
| return CONV_NONE; |
| case TargetOpcode::CONVERGENCECTRL_ENTRY: |
| return CONV_ENTRY; |
| case TargetOpcode::CONVERGENCECTRL_ANCHOR: |
| return CONV_ANCHOR; |
| case TargetOpcode::CONVERGENCECTRL_LOOP: |
| return CONV_LOOP; |
| } |
| } |
| |
| template <> |
| void GenericConvergenceVerifier< |
| MachineSSAContext>::checkConvergenceTokenProduced(const MachineInstr &MI) { |
| Check(!MI.hasImplicitDef(), |
| "Convergence control tokens are defined explicitly.", |
| {Context.print(&MI)}); |
| const MachineOperand &Def = MI.getOperand(0); |
| const MachineRegisterInfo &MRI = Context.getFunction()->getRegInfo(); |
| Check(MRI.getUniqueVRegDef(Def.getReg()), |
| "Convergence control tokens must have unique definitions.", |
| {Context.print(&MI)}); |
| } |
| |
| template <> |
| const MachineInstr * |
| GenericConvergenceVerifier<MachineSSAContext>::findAndCheckConvergenceTokenUsed( |
| const MachineInstr &MI) { |
| const MachineRegisterInfo &MRI = Context.getFunction()->getRegInfo(); |
| const MachineInstr *TokenDef = nullptr; |
| |
| for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) { |
| const MachineOperand &MO = MI.getOperand(I); |
| if (!MO.isReg() || !MO.isUse()) |
| continue; |
| Register OpReg = MO.getReg(); |
| if (!OpReg.isVirtual()) |
| continue; |
| |
| const MachineInstr *Def = MRI.getUniqueVRegDef(OpReg); |
| if (!Def) |
| continue; |
| if (getConvOp(*Def) == CONV_NONE) |
| continue; |
| |
| CheckOrNull( |
| MI.isConvergent(), |
| "Convergence control tokens can only be used by convergent operations.", |
| {Context.print(OpReg), Context.print(&MI)}); |
| |
| CheckOrNull(!TokenDef, |
| "An operation can use at most one convergence control token.", |
| {Context.print(OpReg), Context.print(&MI)}); |
| |
| TokenDef = Def; |
| } |
| |
| if (TokenDef) |
| Tokens[&MI] = TokenDef; |
| |
| return TokenDef; |
| } |
| |
| template <> |
| bool GenericConvergenceVerifier<MachineSSAContext>::isInsideConvergentFunction( |
| const MachineInstr &MI) { |
| // The class MachineFunction does not have any property to indicate whether it |
| // is convergent. Trivially return true so that the check always passes. |
| return true; |
| } |
| |
| template <> |
| bool GenericConvergenceVerifier<MachineSSAContext>::isConvergent( |
| const MachineInstr &MI) { |
| return MI.isConvergent(); |
| } |
| |
| template class llvm::GenericConvergenceVerifier<MachineSSAContext>; |