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 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
