[llvm-branch-commits] [llvm] [5/7][PISA] Add PISAInstructionSelector (PR #214378)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Aug 5 17:49:19 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-globalisel

Author: Michal Paszkowski (michalpaszkowski)

<details>
<summary>Changes</summary>

Add the PISAInstructionSelector, the final Subtarget/TargetMachine wiring, and selection tests.

---

Patch is 81.43 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/214378.diff


9 Files Affected:

- (modified) llvm/lib/Target/PISA/CMakeLists.txt (+1) 
- (added) llvm/lib/Target/PISA/PISAInstructionSelector.cpp (+1794) 
- (modified) llvm/lib/Target/PISA/PISASubtarget.cpp (+2-1) 
- (modified) llvm/lib/Target/PISA/PISATargetMachine.cpp (+8-2) 
- (added) llvm/test/CodeGen/PISA/GlobalISel/inst-select-build-vector-v64.mir (+24) 
- (added) llvm/test/CodeGen/PISA/GlobalISel/inst-select-constant-float-type.mir (+36) 
- (added) llvm/test/CodeGen/PISA/GlobalISel/inst-select-ctlz.mir (+103) 
- (added) llvm/test/CodeGen/PISA/GlobalISel/inst-select-cttz.mir (+103) 
- (added) llvm/test/CodeGen/PISA/GlobalISel/inst-select-debug-trace.mir (+41) 


``````````diff
diff --git a/llvm/lib/Target/PISA/CMakeLists.txt b/llvm/lib/Target/PISA/CMakeLists.txt
index 0a666058c14d2..a51c8cfafc728 100644
--- a/llvm/lib/Target/PISA/CMakeLists.txt
+++ b/llvm/lib/Target/PISA/CMakeLists.txt
@@ -21,6 +21,7 @@ add_llvm_target(PISACodeGen
   PISACallLowering.cpp
   PISAISelLowering.cpp
   PISAInstrInfo.cpp
+  PISAInstructionSelector.cpp
   PISALegalizerInfo.cpp
   PISAMCInstLower.cpp
   PISAMachineFunctionInfo.cpp
diff --git a/llvm/lib/Target/PISA/PISAInstructionSelector.cpp b/llvm/lib/Target/PISA/PISAInstructionSelector.cpp
new file mode 100644
index 0000000000000..178d24ff75fe3
--- /dev/null
+++ b/llvm/lib/Target/PISA/PISAInstructionSelector.cpp
@@ -0,0 +1,1794 @@
+//===-- PISAInstructionSelector.cpp ---------------------------------------===//
+//
+// 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 "MCTargetDesc/PISAEnum.h"
+#include "PISA.h"
+#include "PISAGenInstrInfo.inc"
+#include "PISAInstrInfo.h"
+#include "PISARegisterBankInfo.h"
+#include "PISARegisterInfo.h"
+#include "PISATargetMachine.h"
+#include "PISAUtils.h"
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/FloatingPointMode.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringTable.h"
+#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
+#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
+#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
+#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/IR/IntrinsicsPISA.h"
+#include "llvm/IR/PISAIntrinsicUtils.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/PISAAddrSpace.h"
+
+namespace llvm {
+namespace PISA {
+struct Name2InstrEntry {
+  StringTable::Offset Name;
+  unsigned Opcode;
+};
+
+#define GET_Name2InstrOpTable_DECL
+#define GET_Name2InstrOpTable_IMPL
+#include "PISAGenSearchableTables.inc"
+
+} // namespace PISA
+} // namespace llvm
+
+#define DEBUG_TYPE "pisa-isel"
+
+using namespace llvm;
+using namespace MIPatternMatch;
+
+namespace {
+
+struct SyncScopeInfo {
+  static const StringMap<unsigned> Name2Opcode;
+  DenseMap<llvm::SyncScope::ID, unsigned> ID2Opcode;
+  SyncScope::ID SystemGenericID = SyncScope::System;
+
+  SyncScopeInfo() {}
+  SyncScopeInfo(llvm::LLVMContext &Context) {
+    for (const auto &[Name, Opcode] : Name2Opcode) {
+      auto ID = Context.getOrInsertSyncScopeID(Name);
+      ID2Opcode.emplace_or_assign(ID, Opcode);
+    }
+    ID2Opcode.emplace_or_assign(SyncScope::SingleThread, PISA::fence_subgroup);
+    ID2Opcode.emplace_or_assign(SyncScope::System, PISA::fence_global_system);
+    SystemGenericID = Context.getOrInsertSyncScopeID("system-generic");
+  }
+};
+
+const StringMap<unsigned> SyncScopeInfo::Name2Opcode = {
+    {"workitem", PISA::fence_subgroup},
+    {"workitem-shared", PISA::fence_subgroup},
+    {"workitem-global", PISA::fence_subgroup},
+    {"workitem-generic", PISA::fence_subgroup},
+    {"subgroup", PISA::fence_subgroup},
+    {"subgroup-shared", PISA::fence_subgroup},
+    {"subgroup-global", PISA::fence_subgroup},
+    {"subgroup-generic", PISA::fence_subgroup},
+    {"workgroup", PISA::fence_generic_workgroup},
+    {"workgroup-shared", PISA::fence_shared_workgroup},
+    {"workgroup-global", PISA::fence_global_workgroup},
+    {"workgroup-generic", PISA::fence_generic_workgroup},
+    {"gpu", PISA::fence_generic_gpu},
+    {"gpu-shared", PISA::fence_shared_gpu},
+    {"gpu-global", PISA::fence_global_gpu},
+    {"gpu-generic", PISA::fence_generic_gpu},
+    {"system", PISA::fence_global_system},
+    {"system-shared", PISA::fence_shared_gpu},
+    {"system-global", PISA::fence_global_system},
+};
+
+#define GET_GLOBALISEL_PREDICATE_BITSET
+#include "PISAGenGlobalISel.inc"
+#undef GET_GLOBALISEL_PREDICATE_BITSET
+
+class PISAInstructionSelector : public InstructionSelector {
+  const PISASubtarget &STI;
+  const PISAInstrInfo &TII;
+  const PISARegisterInfo &TRI;
+  const RegisterBankInfo &RBI;
+  MachineRegisterInfo *MRI = nullptr;
+  SyncScopeInfo SSI;
+  MachineFrameInfo *MFI = nullptr;
+
+public:
+  PISAInstructionSelector(const PISATargetMachine &TM, const PISASubtarget &ST,
+                          const RegisterBankInfo &RBI);
+  void setupMF(MachineFunction &MF, GISelValueTracking *KB,
+               CodeGenCoverage *CoverageInfo, ProfileSummaryInfo *PSI,
+               BlockFrequencyInfo *BFI) override;
+  bool select(MachineInstr &I) override;
+  static const char *getName() { return DEBUG_TYPE; }
+
+#define GET_GLOBALISEL_PREDICATES_DECL
+#include "PISAGenGlobalISel.inc"
+#undef GET_GLOBALISEL_PREDICATES_DECL
+
+#define GET_GLOBALISEL_TEMPORARIES_DECL
+#include "PISAGenGlobalISel.inc"
+#undef GET_GLOBALISEL_TEMPORARIES_DECL
+
+private:
+  // tblgen-erated 'select' implementation, used as the initial selector for
+  // the patterns that don't require complex C++.
+  bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
+  bool selectFrameIndex(MachineInstr &I) const;
+  bool selectGlobalValue(MachineInstr &I) const;
+  bool selectPhiOrImplicitDef(MachineInstr &I) const;
+  bool selectAddSubWithOverflow(MachineInstr &I) const;
+  bool selectSignedAddSubWithOverflow(MachineInstr &I) const;
+  bool selectBitcast(MachineInstr &I) const;
+  // NOLINTBEGIN(readability-identifier-naming)
+  bool selectG_BUILD_VECTOR(MachineInstr &I) const;
+  bool selectConvPtrInt(MachineInstr &I) const;
+  bool selectCopy(MachineInstr &I) const;
+  bool selectG_INTRINSIC(MachineInstr &I) const;
+  bool selectG_INTRINSIC_WITH_SIDEFFECTS(MachineInstr &I) const;
+  bool selectDbgValue(MachineInstr &I) const;
+  bool selectG_FCANONICALIZE(MachineInstr &I) const;
+  bool selectG_LROUND(MachineInstr &I) const;
+  bool selectG_MERGE_VALUES(MachineInstr &MI) const;
+  bool selectG_UNMERGE_VALUES(MachineInstr &MI) const;
+  bool selectG_BFX(MachineInstr &I, bool Signed) const;
+  bool selectG_CONSTANT(MachineInstr &I) const;
+  bool selectG_FENCE(MachineInstr &I) const;
+  bool selectG_INSERT_SUBVECTOR(MachineInstr &MI) const;
+  bool selectG_EXTRACT_SUBVECTOR(MachineInstr &MI) const;
+  bool selectG_INSERT_VECTOR_ELT(MachineInstr &MI) const;
+  bool selectG_EXTRACT_VECTOR_ELT(MachineInstr &MI) const;
+  bool selectG_ADDRSPACE_CAST(llvm::MachineInstr &I) const;
+  MachineInstr *findPtrBaseDefinition(MachineInstr *StartDef,
+                                      const MachineRegisterInfo &MRI) const;
+
+  InstructionSelector::ComplexRendererFns
+  SelectAddr_rr(MachineOperand &Root) const;
+  InstructionSelector::ComplexRendererFns
+  SelectAddr_ri(MachineOperand &Root) const;
+  InstructionSelector::ComplexRendererFns
+  selectParamSlot_ii(MachineOperand &Root) const;
+  InstructionSelector::ComplexRendererFns
+  selectParamSlot_ir(MachineOperand &Root) const;
+
+  // NOLINTEND(readability-identifier-naming)
+
+  bool emitBuildVector(MachineInstr &InsertPt, Register DstReg,
+                       ArrayRef<Register> Srcs) const;
+
+  bool useFastFP(const MachineInstr &I) const {
+    return I.getFlag(MachineInstr::MIFlag::FmAfn);
+  }
+};
+
+} // namespace
+
+#define GET_GLOBALISEL_IMPL
+#include "PISAGenGlobalISel.inc"
+#undef GET_GLOBALISEL_IMPL
+
+PISAInstructionSelector::PISAInstructionSelector(const PISATargetMachine &TM,
+                                                 const PISASubtarget &ST,
+                                                 const RegisterBankInfo &RBI)
+    : InstructionSelector(), STI(ST), TII(*ST.getInstrInfo()),
+      TRI(*ST.getRegisterInfo()), RBI(RBI),
+#define GET_GLOBALISEL_PREDICATES_INIT
+#include "PISAGenGlobalISel.inc"
+#undef GET_GLOBALISEL_PREDICATES_INIT
+#define GET_GLOBALISEL_TEMPORARIES_INIT
+#include "PISAGenGlobalISel.inc"
+#undef GET_GLOBALISEL_TEMPORARIES_INIT
+{
+}
+
+void PISAInstructionSelector::setupMF(MachineFunction &MF,
+                                      GISelValueTracking *KB,
+                                      CodeGenCoverage *CoverageInfo,
+                                      ProfileSummaryInfo *PSI,
+                                      BlockFrequencyInfo *BFI) {
+  constexpr unsigned SharedAS = unsigned(PISAAS::AddressSpace::SHARED);
+
+  SSI = SyncScopeInfo(MF.getFunction().getContext());
+  InstructionSelector::setupMF(MF, KB, CoverageInfo, PSI, BFI);
+  MRI = &MF.getRegInfo();
+  MFI = &MF.getFrameInfo();
+  // Setup the correct stack ID.
+  for (int Idx = MFI->getObjectIndexBegin(), EndIdx = MFI->getObjectIndexEnd();
+       Idx != EndIdx; ++Idx) {
+    if (auto *AI = MFI->getObjectAllocation(Idx)) {
+      const auto AS = AI->getAddressSpace();
+      Type *AllocatedTy = AI->getAllocatedType();
+      if (auto *ATy = dyn_cast<ArrayType>(AllocatedTy))
+        AllocatedTy = ATy->getElementType();
+
+      auto *TExtTy = dyn_cast<TargetExtType>(AllocatedTy);
+
+      if (AS == SharedAS) {
+        assert(MF.getFunction().getCallingConv() == CallingConv::PISA_KERNEL &&
+               "shared variables are not supported in functions!");
+        unsigned StackID = TargetStackID::PISAShared;
+        if (TExtTy)
+          StackID = llvm::StringSwitch<unsigned>(TExtTy->getName())
+                        .Default(TargetStackID::PISAShared);
+        MFI->setStackID(Idx, StackID);
+      }
+    }
+  }
+}
+
+bool PISAInstructionSelector::select(MachineInstr &I) {
+  assert(I.getParent() && "Instruction should be in a basic block!");
+  assert(I.getParent()->getParent() && "Instruction should be in a function!");
+
+  unsigned Opcode = I.getOpcode();
+
+  // If it's not a GMIR instruction, we've selected it already.
+  if (!I.isPreISelOpcode() && Opcode != TargetOpcode::DBG_VALUE) {
+    if (I.isCopy())
+      return selectCopy(I);
+    constrainSelectedInstRegOperands(I, TII, TRI, RBI);
+    return true;
+  }
+
+  switch (Opcode) {
+  default:
+    break;
+  case TargetOpcode::G_ADDRSPACE_CAST:
+    if (selectG_ADDRSPACE_CAST(I))
+      return true;
+    break;
+  }
+
+  if (selectImpl(I, *CoverageInfo))
+    return true;
+
+  if (I.getNumOperands() != I.getNumExplicitOperands()) {
+    LLVM_DEBUG(errs() << "Generic instr has unexpected implicit operands\n");
+    return false;
+  }
+
+  switch (Opcode) {
+  case TargetOpcode::G_FRAME_INDEX:
+    return selectFrameIndex(I);
+  case TargetOpcode::G_GLOBAL_VALUE:
+    return selectGlobalValue(I);
+  case TargetOpcode::G_PHI:
+  case TargetOpcode::G_IMPLICIT_DEF:
+    return selectPhiOrImplicitDef(I);
+  case TargetOpcode::G_UADDO:
+  case TargetOpcode::G_USUBO:
+  case TargetOpcode::G_UADDE:
+  case TargetOpcode::G_USUBE:
+    return selectAddSubWithOverflow(I);
+  case TargetOpcode::G_SADDO:
+  case TargetOpcode::G_SSUBO:
+  case TargetOpcode::G_SADDE:
+  case TargetOpcode::G_SSUBE:
+    return selectSignedAddSubWithOverflow(I);
+  case TargetOpcode::G_BITCAST:
+    return selectBitcast(I);
+  case TargetOpcode::G_UNMERGE_VALUES:
+    return selectG_UNMERGE_VALUES(I);
+  case TargetOpcode::G_CONCAT_VECTORS:
+  case TargetOpcode::G_MERGE_VALUES:
+    return selectG_MERGE_VALUES(I);
+  case TargetOpcode::G_BUILD_VECTOR:
+    return selectG_BUILD_VECTOR(I);
+  case TargetOpcode::G_PTRTOINT:
+  case TargetOpcode::G_INTTOPTR:
+    return selectConvPtrInt(I);
+  case TargetOpcode::G_FREEZE:
+    return selectCopy(I);
+  case TargetOpcode::G_INTRINSIC:
+  case TargetOpcode::G_INTRINSIC_CONVERGENT:
+    return selectG_INTRINSIC(I);
+  case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
+  case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
+    return selectG_INTRINSIC_WITH_SIDEFFECTS(I);
+  case TargetOpcode::DBG_VALUE:
+    return selectDbgValue(I);
+  case TargetOpcode::G_FCANONICALIZE:
+    return selectG_FCANONICALIZE(I);
+  case TargetOpcode::G_LROUND:
+  case TargetOpcode::G_LLROUND:
+    return selectG_LROUND(I);
+  case TargetOpcode::G_UBFX:
+    return selectG_BFX(I, false);
+  case TargetOpcode::G_SBFX:
+    return selectG_BFX(I, true);
+  case TargetOpcode::G_CONSTANT:
+    return selectG_CONSTANT(I);
+  case TargetOpcode::G_FENCE:
+    return selectG_FENCE(I);
+  case TargetOpcode::G_INSERT_SUBVECTOR:
+    return selectG_INSERT_SUBVECTOR(I);
+  case TargetOpcode::G_EXTRACT_SUBVECTOR:
+    return selectG_EXTRACT_SUBVECTOR(I);
+  case TargetOpcode::G_INSERT_VECTOR_ELT:
+    return selectG_INSERT_VECTOR_ELT(I);
+  case TargetOpcode::G_EXTRACT_VECTOR_ELT:
+    return selectG_EXTRACT_VECTOR_ELT(I);
+  default:
+    return false;
+  }
+}
+
+MachineInstr *PISAInstructionSelector::findPtrBaseDefinition(
+    MachineInstr *StartDef, const MachineRegisterInfo &MRI) const {
+  if (!StartDef)
+    return nullptr;
+
+  SmallVector<MachineInstr *, 8> WorkList;
+  SmallPtrSet<MachineInstr *, 8> Visited;
+  MachineInstr *DefMI = StartDef;
+  WorkList.push_back(DefMI);
+
+  while (!WorkList.empty()) {
+    DefMI = WorkList.pop_back_val();
+    if (!Visited.insert(DefMI).second)
+      continue;
+
+    auto Opcode = DefMI->getOpcode();
+    switch (Opcode) {
+    default:
+      // If we see an instruction that we don't recognize, stop looking and try
+      // to select the G_ADDRSPACE_CAST as is.
+      WorkList.clear();
+      break;
+    case TargetOpcode::G_PTR_ADD: {
+      MachineInstr *BaseDef =
+          getDefIgnoringCopies(DefMI->getOperand(1).getReg(), MRI);
+      if (BaseDef)
+        WorkList.push_back(BaseDef);
+    } break;
+    case TargetOpcode::G_PHI:
+      for (unsigned I = 1, E = DefMI->getNumOperands(); I < E; I += 2) {
+        MachineInstr *PhiDef =
+            getDefIgnoringCopies(DefMI->getOperand(I).getReg(), MRI);
+        if (PhiDef)
+          WorkList.push_back(PhiDef);
+      }
+      break;
+    case TargetOpcode::G_SELECT:
+      for (unsigned I = 2, E = DefMI->getNumOperands(); I < E; I++) {
+        MachineInstr *SelectDef =
+            getDefIgnoringCopies(DefMI->getOperand(I).getReg(), MRI);
+        if (SelectDef)
+          WorkList.push_back(SelectDef);
+      }
+      break;
+    }
+  }
+
+  return DefMI;
+}
+
+bool PISAInstructionSelector::selectG_ADDRSPACE_CAST(
+    llvm::MachineInstr &I) const {
+  constexpr unsigned GenericAS =
+      static_cast<unsigned>(PISAAS::AddressSpace::GENERIC);
+  [[maybe_unused]] constexpr unsigned SharedAS =
+      static_cast<unsigned>(PISAAS::AddressSpace::SHARED);
+  [[maybe_unused]] constexpr unsigned PrivateAS =
+      static_cast<unsigned>(PISAAS::AddressSpace::PRIVATE);
+
+  auto [Dst, DstTy, Src, SrcTy] = I.getFirst2RegLLTs();
+  const unsigned DstAS = DstTy.getAddressSpace();
+  [[maybe_unused]] const unsigned SrcAS = SrcTy.getAddressSpace();
+
+  if (DstAS != GenericAS)
+    return false;
+
+  MachineInstr *DefMI =
+      findPtrBaseDefinition(getDefIgnoringCopies(Src, *MRI), *MRI);
+
+  if (!DefMI || DefMI->getOpcode() != TargetOpcode::G_FRAME_INDEX)
+    return false;
+
+  int FI = DefMI->getOperand(1).getIndex();
+  switch (MFI->getStackID(FI)) {
+  default: // No custom selection needed
+    break;
+  }
+
+  return false;
+}
+
+bool PISAInstructionSelector::selectG_INTRINSIC(MachineInstr &I) const {
+  // While we want to select special reg intrinsics in tablegen using
+  // SpecialRegPat<>, there is an issue in llvm that prevents us from doing
+  // so when the output value is a pointer. It fails in:
+  // GlobalISelEmitter::createAndImportSelDAGMatcher()
+  // because isOutOperandAPointer() will always return false for G_INTRINSIC
+  // as its OutOperandList = (outs). This then causes addTypeCheckPredicate()
+  // to not generate a pointer matcher, so tablegen fails saying that we have
+  // an unsupported type (even though it is an iPTR). Until this is fixed,
+  // manually select these cases here.
+
+  switch (cast<GIntrinsic>(I).getIntrinsicID()) {
+  default:
+    return false;
+  }
+}
+
+bool PISAInstructionSelector::selectG_INTRINSIC_WITH_SIDEFFECTS(
+    MachineInstr &I) const {
+  // Find the intrinsic ID.
+  unsigned IntrinID = cast<GIntrinsic>(I).getIntrinsicID();
+  switch (IntrinID) {
+  default:
+    return false;
+  }
+}
+
+bool PISAInstructionSelector::selectFrameIndex(MachineInstr &I) const {
+  I.setDesc(TII.get(PISA::addrof_32b));
+  // need to set dst reg-class
+  const Register DefReg = I.getOperand(0).getReg();
+  const LLT DefTy = MRI->getType(DefReg);
+
+  const RegClassOrRegBank &RegClassOrBank = MRI->getRegClassOrRegBank(DefReg);
+  const TargetRegisterClass *DefRC =
+      RegClassOrBank.dyn_cast<const TargetRegisterClass *>();
+  if (!DefRC)
+    DefRC = TRI.getRegClassFromLLT(DefTy);
+  return RBI.constrainGenericRegister(DefReg, *DefRC, *MRI);
+}
+
+bool PISAInstructionSelector::selectGlobalValue(MachineInstr &I) const {
+  I.setDesc(TII.get(PISA::addrof_64b));
+
+  Register DefReg = I.getOperand(0).getReg();
+  const LLT DefTy = MRI->getType(DefReg);
+
+  const RegClassOrRegBank &RegClassOrBank = MRI->getRegClassOrRegBank(DefReg);
+  const TargetRegisterClass *DefRC =
+      RegClassOrBank.dyn_cast<const TargetRegisterClass *>();
+  if (!DefRC)
+    DefRC = TRI.getRegClassFromLLT(DefTy);
+
+  return RBI.constrainGenericRegister(DefReg, *DefRC, *MRI);
+}
+
+bool PISAInstructionSelector::selectPhiOrImplicitDef(MachineInstr &I) const {
+  MachineBasicBlock *BB = I.getParent();
+  MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
+
+  const Register DefReg = I.getOperand(0).getReg();
+  const LLT DefTy = MRI.getType(DefReg);
+
+  const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(DefReg);
+
+  const TargetRegisterClass *DefRC =
+      RegClassOrBank.dyn_cast<const TargetRegisterClass *>();
+
+  if (!DefRC)
+    DefRC = TRI.getRegClassFromLLT(DefTy);
+
+  unsigned Opcode = (I.getOpcode() == TargetOpcode::G_PHI)
+                        ? TargetOpcode::PHI
+                        : TargetOpcode::IMPLICIT_DEF;
+  I.setDesc(TII.get(Opcode));
+
+  return RBI.constrainGenericRegister(DefReg, *DefRC, MRI);
+}
+
+bool PISAInstructionSelector::selectAddSubWithOverflow(MachineInstr &I) const {
+  MachineBasicBlock *BB = I.getParent();
+  const DebugLoc &DL = I.getDebugLoc();
+
+  const bool IsAdd = I.getOpcode() == TargetOpcode::G_UADDO ||
+                     I.getOpcode() == TargetOpcode::G_UADDE;
+  const bool HasCarryIn = I.getOpcode() == TargetOpcode::G_UADDE ||
+                          I.getOpcode() == TargetOpcode::G_USUBE;
+
+  auto [DstReg, CarryOutReg, Src0Reg, Src1Reg] = I.getFirst4Regs();
+  const auto *DstRC = TRI.getRegClassFromLLT(MRI->getType(DstReg));
+  const auto *PredRC = &PISA::PredRegClass;
+
+  // Is there any reason to support 16b addc/subb?
+  assert(DstRC == &PISA::Reg32bRegClass);
+
+  auto Src0C = getIConstantVRegValWithLookThrough(Src0Reg, *MRI);
+  auto Src1C = getIConstantVRegValWithLookThrough(Src1Reg, *MRI);
+  unsigned RegReg = Src0C ? 0 : (Src1C ? 1 : 2);
+
+  const bool HasCarryOut = !HasCarryIn || !MRI->use_nodbg_empty(CarryOutReg);
+
+  unsigned PISAOps[] = {PISA::uaddc_co_32b_ir,    PISA::uaddc_co_32b_ri,
+                        PISA::uaddc_co_32b_rr,    PISA::usubb_co_32b_ir,
+                        PISA::usubb_co_32b_ri,    PISA::usubb_co_32b_rr,
+                        PISA::uaddc_ci_32b_ir,    PISA::uaddc_ci_32b_ri,
+                        PISA::uaddc_ci_32b_rr,    PISA::usubb_ci_32b_ir,
+                        PISA::usubb_ci_32b_ri,    PISA::usubb_ci_32b_rr,
+                        PISA::uaddc_ci_co_32b_ir, PISA::uaddc_ci_co_32b_ri,
+                        PISA::uaddc_ci_co_32b_rr, PISA::usubb_ci_co_32b_ir,
+                        PISA::usubb_ci_co_32b_ri, PISA::usubb_ci_co_32b_rr};
+
+  unsigned CarryOutOpc = PISAOps[(IsAdd ? 0 : 3) + RegReg];
+  unsigned CarryInOpc = PISAOps[6 + (IsAdd ? 0 : 3) + RegReg];
+  unsigned CarryInOutOpc = PISAOps[12 + (IsAdd ? 0 : 3) + RegReg];
+
+  unsigned Opc = (HasCarryIn && HasCarryOut)
+                     ? CarryInOutOpc
+                     : (HasCarryOut ? CarryOutOpc : CarryInOpc);
+
+  auto MIB = BuildMI(*BB, &I, DL, TII.get(Opc), DstReg);
+  if (HasCarryOut)
+    MIB.addDef(CarryOutReg);
+  if (Src0C)
+    MIB.addImm(Src0C->Value.getSExtValue());
+  else
+    MIB.add(I.getOperand(2));
+  if (Src1C && !Src0C)
+    MIB.addImm(Src1C->Value.getSExtValue());
+  else
+    MIB.add(I.getOperand(3...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/214378


More information about the llvm-branch-commits mailing list