xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/GlobalISel/Utils.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- llvm/CodeGen/GlobalISel/Utils.cpp -------------------------*- C++ -*-==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file This file implements the utility functions used by the GlobalISel
90b57cec5SDimitry Andric /// pipeline.
100b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/Utils.h"
130b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h"
14e8d8bef9SDimitry Andric #include "llvm/ADT/APInt.h"
15*0fca6ea1SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
16bdd1243dSDimitry Andric #include "llvm/CodeGen/CodeGenCommonISel.h"
175ffd83dbSDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
18e8d8bef9SDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
19349cc55cSDimitry Andric #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
2081ad6265SDimitry Andric #include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h"
21e8d8bef9SDimitry Andric #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
227a6dacacSDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
2781ad6265SDimitry Andric #include "llvm/CodeGen/MachineSizeOpts.h"
2881ad6265SDimitry Andric #include "llvm/CodeGen/RegisterBankInfo.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/StackProtector.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
31e8d8bef9SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
32*0fca6ea1SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h"
330b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
340b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
350b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
36e8d8bef9SDimitry Andric #include "llvm/Target/TargetMachine.h"
3781ad6265SDimitry Andric #include "llvm/Transforms/Utils/SizeOpts.h"
38bdd1243dSDimitry Andric #include <numeric>
39bdd1243dSDimitry Andric #include <optional>
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric #define DEBUG_TYPE "globalisel-utils"
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric using namespace llvm;
44e8d8bef9SDimitry Andric using namespace MIPatternMatch;
450b57cec5SDimitry Andric 
465ffd83dbSDimitry Andric Register llvm::constrainRegToClass(MachineRegisterInfo &MRI,
470b57cec5SDimitry Andric                                    const TargetInstrInfo &TII,
485ffd83dbSDimitry Andric                                    const RegisterBankInfo &RBI, Register Reg,
490b57cec5SDimitry Andric                                    const TargetRegisterClass &RegClass) {
500b57cec5SDimitry Andric   if (!RBI.constrainGenericRegister(Reg, RegClass, MRI))
510b57cec5SDimitry Andric     return MRI.createVirtualRegister(&RegClass);
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   return Reg;
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
565ffd83dbSDimitry Andric Register llvm::constrainOperandRegClass(
570b57cec5SDimitry Andric     const MachineFunction &MF, const TargetRegisterInfo &TRI,
580b57cec5SDimitry Andric     MachineRegisterInfo &MRI, const TargetInstrInfo &TII,
590b57cec5SDimitry Andric     const RegisterBankInfo &RBI, MachineInstr &InsertPt,
60e8d8bef9SDimitry Andric     const TargetRegisterClass &RegClass, MachineOperand &RegMO) {
618bcb0991SDimitry Andric   Register Reg = RegMO.getReg();
620b57cec5SDimitry Andric   // Assume physical registers are properly constrained.
63bdd1243dSDimitry Andric   assert(Reg.isVirtual() && "PhysReg not implemented");
640b57cec5SDimitry Andric 
6581ad6265SDimitry Andric   // Save the old register class to check whether
6681ad6265SDimitry Andric   // the change notifications will be required.
6781ad6265SDimitry Andric   // TODO: A better approach would be to pass
6881ad6265SDimitry Andric   // the observers to constrainRegToClass().
6981ad6265SDimitry Andric   auto *OldRegClass = MRI.getRegClassOrNull(Reg);
705ffd83dbSDimitry Andric   Register ConstrainedReg = constrainRegToClass(MRI, TII, RBI, Reg, RegClass);
710b57cec5SDimitry Andric   // If we created a new virtual register because the class is not compatible
720b57cec5SDimitry Andric   // then create a copy between the new and the old register.
730b57cec5SDimitry Andric   if (ConstrainedReg != Reg) {
740b57cec5SDimitry Andric     MachineBasicBlock::iterator InsertIt(&InsertPt);
750b57cec5SDimitry Andric     MachineBasicBlock &MBB = *InsertPt.getParent();
76349cc55cSDimitry Andric     // FIXME: The copy needs to have the classes constrained for its operands.
77349cc55cSDimitry Andric     // Use operand's regbank to get the class for old register (Reg).
780b57cec5SDimitry Andric     if (RegMO.isUse()) {
790b57cec5SDimitry Andric       BuildMI(MBB, InsertIt, InsertPt.getDebugLoc(),
800b57cec5SDimitry Andric               TII.get(TargetOpcode::COPY), ConstrainedReg)
810b57cec5SDimitry Andric           .addReg(Reg);
820b57cec5SDimitry Andric     } else {
830b57cec5SDimitry Andric       assert(RegMO.isDef() && "Must be a definition");
840b57cec5SDimitry Andric       BuildMI(MBB, std::next(InsertIt), InsertPt.getDebugLoc(),
850b57cec5SDimitry Andric               TII.get(TargetOpcode::COPY), Reg)
860b57cec5SDimitry Andric           .addReg(ConstrainedReg);
870b57cec5SDimitry Andric     }
88e8d8bef9SDimitry Andric     if (GISelChangeObserver *Observer = MF.getObserver()) {
89e8d8bef9SDimitry Andric       Observer->changingInstr(*RegMO.getParent());
90e8d8bef9SDimitry Andric     }
91e8d8bef9SDimitry Andric     RegMO.setReg(ConstrainedReg);
92e8d8bef9SDimitry Andric     if (GISelChangeObserver *Observer = MF.getObserver()) {
93e8d8bef9SDimitry Andric       Observer->changedInstr(*RegMO.getParent());
94e8d8bef9SDimitry Andric     }
9581ad6265SDimitry Andric   } else if (OldRegClass != MRI.getRegClassOrNull(Reg)) {
965ffd83dbSDimitry Andric     if (GISelChangeObserver *Observer = MF.getObserver()) {
975ffd83dbSDimitry Andric       if (!RegMO.isDef()) {
985ffd83dbSDimitry Andric         MachineInstr *RegDef = MRI.getVRegDef(Reg);
995ffd83dbSDimitry Andric         Observer->changedInstr(*RegDef);
1005ffd83dbSDimitry Andric       }
1015ffd83dbSDimitry Andric       Observer->changingAllUsesOfReg(MRI, Reg);
1025ffd83dbSDimitry Andric       Observer->finishedChangingAllUsesOfReg();
1035ffd83dbSDimitry Andric     }
1040b57cec5SDimitry Andric   }
1050b57cec5SDimitry Andric   return ConstrainedReg;
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric 
1085ffd83dbSDimitry Andric Register llvm::constrainOperandRegClass(
1090b57cec5SDimitry Andric     const MachineFunction &MF, const TargetRegisterInfo &TRI,
1100b57cec5SDimitry Andric     MachineRegisterInfo &MRI, const TargetInstrInfo &TII,
1110b57cec5SDimitry Andric     const RegisterBankInfo &RBI, MachineInstr &InsertPt, const MCInstrDesc &II,
112e8d8bef9SDimitry Andric     MachineOperand &RegMO, unsigned OpIdx) {
1138bcb0991SDimitry Andric   Register Reg = RegMO.getReg();
1140b57cec5SDimitry Andric   // Assume physical registers are properly constrained.
115bdd1243dSDimitry Andric   assert(Reg.isVirtual() && "PhysReg not implemented");
1160b57cec5SDimitry Andric 
117349cc55cSDimitry Andric   const TargetRegisterClass *OpRC = TII.getRegClass(II, OpIdx, &TRI, MF);
1180b57cec5SDimitry Andric   // Some of the target independent instructions, like COPY, may not impose any
1190b57cec5SDimitry Andric   // register class constraints on some of their operands: If it's a use, we can
1200b57cec5SDimitry Andric   // skip constraining as the instruction defining the register would constrain
1210b57cec5SDimitry Andric   // it.
1220b57cec5SDimitry Andric 
123349cc55cSDimitry Andric   if (OpRC) {
124349cc55cSDimitry Andric     // Obtain the RC from incoming regbank if it is a proper sub-class. Operands
125349cc55cSDimitry Andric     // can have multiple regbanks for a superclass that combine different
126349cc55cSDimitry Andric     // register types (E.g., AMDGPU's VGPR and AGPR). The regbank ambiguity
127349cc55cSDimitry Andric     // resolved by targets during regbankselect should not be overridden.
128349cc55cSDimitry Andric     if (const auto *SubRC = TRI.getCommonSubClass(
129349cc55cSDimitry Andric             OpRC, TRI.getConstrainedRegClassForOperand(RegMO, MRI)))
130349cc55cSDimitry Andric       OpRC = SubRC;
1310b57cec5SDimitry Andric 
132349cc55cSDimitry Andric     OpRC = TRI.getAllocatableClass(OpRC);
133349cc55cSDimitry Andric   }
134349cc55cSDimitry Andric 
135349cc55cSDimitry Andric   if (!OpRC) {
1360b57cec5SDimitry Andric     assert((!isTargetSpecificOpcode(II.getOpcode()) || RegMO.isUse()) &&
1370b57cec5SDimitry Andric            "Register class constraint is required unless either the "
1380b57cec5SDimitry Andric            "instruction is target independent or the operand is a use");
1390b57cec5SDimitry Andric     // FIXME: Just bailing out like this here could be not enough, unless we
1400b57cec5SDimitry Andric     // expect the users of this function to do the right thing for PHIs and
1410b57cec5SDimitry Andric     // COPY:
1420b57cec5SDimitry Andric     //   v1 = COPY v0
1430b57cec5SDimitry Andric     //   v2 = COPY v1
1440b57cec5SDimitry Andric     // v1 here may end up not being constrained at all. Please notice that to
1450b57cec5SDimitry Andric     // reproduce the issue we likely need a destination pattern of a selection
1460b57cec5SDimitry Andric     // rule producing such extra copies, not just an input GMIR with them as
1470b57cec5SDimitry Andric     // every existing target using selectImpl handles copies before calling it
1480b57cec5SDimitry Andric     // and they never reach this function.
1490b57cec5SDimitry Andric     return Reg;
1500b57cec5SDimitry Andric   }
151349cc55cSDimitry Andric   return constrainOperandRegClass(MF, TRI, MRI, TII, RBI, InsertPt, *OpRC,
1525ffd83dbSDimitry Andric                                   RegMO);
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric bool llvm::constrainSelectedInstRegOperands(MachineInstr &I,
1560b57cec5SDimitry Andric                                             const TargetInstrInfo &TII,
1570b57cec5SDimitry Andric                                             const TargetRegisterInfo &TRI,
1580b57cec5SDimitry Andric                                             const RegisterBankInfo &RBI) {
1590b57cec5SDimitry Andric   assert(!isPreISelGenericOpcode(I.getOpcode()) &&
1600b57cec5SDimitry Andric          "A selected instruction is expected");
1610b57cec5SDimitry Andric   MachineBasicBlock &MBB = *I.getParent();
1620b57cec5SDimitry Andric   MachineFunction &MF = *MBB.getParent();
1630b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   for (unsigned OpI = 0, OpE = I.getNumExplicitOperands(); OpI != OpE; ++OpI) {
1660b57cec5SDimitry Andric     MachineOperand &MO = I.getOperand(OpI);
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric     // There's nothing to be done on non-register operands.
1690b57cec5SDimitry Andric     if (!MO.isReg())
1700b57cec5SDimitry Andric       continue;
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Converting operand: " << MO << '\n');
1730b57cec5SDimitry Andric     assert(MO.isReg() && "Unsupported non-reg operand");
1740b57cec5SDimitry Andric 
1758bcb0991SDimitry Andric     Register Reg = MO.getReg();
1760b57cec5SDimitry Andric     // Physical registers don't need to be constrained.
177bdd1243dSDimitry Andric     if (Reg.isPhysical())
1780b57cec5SDimitry Andric       continue;
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric     // Register operands with a value of 0 (e.g. predicate operands) don't need
1810b57cec5SDimitry Andric     // to be constrained.
1820b57cec5SDimitry Andric     if (Reg == 0)
1830b57cec5SDimitry Andric       continue;
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric     // If the operand is a vreg, we should constrain its regclass, and only
1860b57cec5SDimitry Andric     // insert COPYs if that's impossible.
1870b57cec5SDimitry Andric     // constrainOperandRegClass does that for us.
188e8d8bef9SDimitry Andric     constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, I.getDesc(), MO, OpI);
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric     // Tie uses to defs as indicated in MCInstrDesc if this hasn't already been
1910b57cec5SDimitry Andric     // done.
1920b57cec5SDimitry Andric     if (MO.isUse()) {
1930b57cec5SDimitry Andric       int DefIdx = I.getDesc().getOperandConstraint(OpI, MCOI::TIED_TO);
1940b57cec5SDimitry Andric       if (DefIdx != -1 && !I.isRegTiedToUseOperand(DefIdx))
1950b57cec5SDimitry Andric         I.tieOperands(DefIdx, OpI);
1960b57cec5SDimitry Andric     }
1970b57cec5SDimitry Andric   }
1980b57cec5SDimitry Andric   return true;
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric 
2015ffd83dbSDimitry Andric bool llvm::canReplaceReg(Register DstReg, Register SrcReg,
2025ffd83dbSDimitry Andric                          MachineRegisterInfo &MRI) {
2035ffd83dbSDimitry Andric   // Give up if either DstReg or SrcReg  is a physical register.
2045ffd83dbSDimitry Andric   if (DstReg.isPhysical() || SrcReg.isPhysical())
2055ffd83dbSDimitry Andric     return false;
2065ffd83dbSDimitry Andric   // Give up if the types don't match.
2075ffd83dbSDimitry Andric   if (MRI.getType(DstReg) != MRI.getType(SrcReg))
2085ffd83dbSDimitry Andric     return false;
2095ffd83dbSDimitry Andric   // Replace if either DstReg has no constraints or the register
2105ffd83dbSDimitry Andric   // constraints match.
2115f757f3fSDimitry Andric   const auto &DstRBC = MRI.getRegClassOrRegBank(DstReg);
2125f757f3fSDimitry Andric   if (!DstRBC || DstRBC == MRI.getRegClassOrRegBank(SrcReg))
2135f757f3fSDimitry Andric     return true;
2145f757f3fSDimitry Andric 
2155f757f3fSDimitry Andric   // Otherwise match if the Src is already a regclass that is covered by the Dst
2165f757f3fSDimitry Andric   // RegBank.
2175f757f3fSDimitry Andric   return DstRBC.is<const RegisterBank *>() && MRI.getRegClassOrNull(SrcReg) &&
2185f757f3fSDimitry Andric          DstRBC.get<const RegisterBank *>()->covers(
2195f757f3fSDimitry Andric              *MRI.getRegClassOrNull(SrcReg));
2205ffd83dbSDimitry Andric }
2215ffd83dbSDimitry Andric 
2220b57cec5SDimitry Andric bool llvm::isTriviallyDead(const MachineInstr &MI,
2230b57cec5SDimitry Andric                            const MachineRegisterInfo &MRI) {
224e8d8bef9SDimitry Andric   // FIXME: This logical is mostly duplicated with
225e8d8bef9SDimitry Andric   // DeadMachineInstructionElim::isDead. Why is LOCAL_ESCAPE not considered in
226e8d8bef9SDimitry Andric   // MachineInstr::isLabel?
227e8d8bef9SDimitry Andric 
228e8d8bef9SDimitry Andric   // Don't delete frame allocation labels.
229e8d8bef9SDimitry Andric   if (MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE)
230e8d8bef9SDimitry Andric     return false;
231fe6060f1SDimitry Andric   // LIFETIME markers should be preserved even if they seem dead.
232fe6060f1SDimitry Andric   if (MI.getOpcode() == TargetOpcode::LIFETIME_START ||
233fe6060f1SDimitry Andric       MI.getOpcode() == TargetOpcode::LIFETIME_END)
234fe6060f1SDimitry Andric     return false;
235e8d8bef9SDimitry Andric 
2360b57cec5SDimitry Andric   // If we can move an instruction, we can remove it.  Otherwise, it has
2370b57cec5SDimitry Andric   // a side-effect of some sort.
2380b57cec5SDimitry Andric   bool SawStore = false;
2390b57cec5SDimitry Andric   if (!MI.isSafeToMove(/*AA=*/nullptr, SawStore) && !MI.isPHI())
2400b57cec5SDimitry Andric     return false;
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   // Instructions without side-effects are dead iff they only define dead vregs.
24306c3fb27SDimitry Andric   for (const auto &MO : MI.all_defs()) {
2448bcb0991SDimitry Andric     Register Reg = MO.getReg();
245bdd1243dSDimitry Andric     if (Reg.isPhysical() || !MRI.use_nodbg_empty(Reg))
2460b57cec5SDimitry Andric       return false;
2470b57cec5SDimitry Andric   }
2480b57cec5SDimitry Andric   return true;
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric 
2515ffd83dbSDimitry Andric static void reportGISelDiagnostic(DiagnosticSeverity Severity,
2525ffd83dbSDimitry Andric                                   MachineFunction &MF,
2535ffd83dbSDimitry Andric                                   const TargetPassConfig &TPC,
2545ffd83dbSDimitry Andric                                   MachineOptimizationRemarkEmitter &MORE,
2555ffd83dbSDimitry Andric                                   MachineOptimizationRemarkMissed &R) {
2565ffd83dbSDimitry Andric   bool IsFatal = Severity == DS_Error &&
2575ffd83dbSDimitry Andric                  TPC.isGlobalISelAbortEnabled();
2585ffd83dbSDimitry Andric   // Print the function name explicitly if we don't have a debug location (which
2595ffd83dbSDimitry Andric   // makes the diagnostic less useful) or if we're going to emit a raw error.
2605ffd83dbSDimitry Andric   if (!R.getLocation().isValid() || IsFatal)
2615ffd83dbSDimitry Andric     R << (" (in function: " + MF.getName() + ")").str();
2625ffd83dbSDimitry Andric 
2635ffd83dbSDimitry Andric   if (IsFatal)
264349cc55cSDimitry Andric     report_fatal_error(Twine(R.getMsg()));
2655ffd83dbSDimitry Andric   else
2665ffd83dbSDimitry Andric     MORE.emit(R);
2675ffd83dbSDimitry Andric }
2685ffd83dbSDimitry Andric 
2695ffd83dbSDimitry Andric void llvm::reportGISelWarning(MachineFunction &MF, const TargetPassConfig &TPC,
2705ffd83dbSDimitry Andric                               MachineOptimizationRemarkEmitter &MORE,
2715ffd83dbSDimitry Andric                               MachineOptimizationRemarkMissed &R) {
2725ffd83dbSDimitry Andric   reportGISelDiagnostic(DS_Warning, MF, TPC, MORE, R);
2735ffd83dbSDimitry Andric }
2745ffd83dbSDimitry Andric 
2750b57cec5SDimitry Andric void llvm::reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
2760b57cec5SDimitry Andric                               MachineOptimizationRemarkEmitter &MORE,
2770b57cec5SDimitry Andric                               MachineOptimizationRemarkMissed &R) {
2780b57cec5SDimitry Andric   MF.getProperties().set(MachineFunctionProperties::Property::FailedISel);
2795ffd83dbSDimitry Andric   reportGISelDiagnostic(DS_Error, MF, TPC, MORE, R);
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric void llvm::reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
2830b57cec5SDimitry Andric                               MachineOptimizationRemarkEmitter &MORE,
2840b57cec5SDimitry Andric                               const char *PassName, StringRef Msg,
2850b57cec5SDimitry Andric                               const MachineInstr &MI) {
2860b57cec5SDimitry Andric   MachineOptimizationRemarkMissed R(PassName, "GISelFailure: ",
2870b57cec5SDimitry Andric                                     MI.getDebugLoc(), MI.getParent());
2880b57cec5SDimitry Andric   R << Msg;
2890b57cec5SDimitry Andric   // Printing MI is expensive;  only do it if expensive remarks are enabled.
2900b57cec5SDimitry Andric   if (TPC.isGlobalISelAbortEnabled() || MORE.allowExtraAnalysis(PassName))
2910b57cec5SDimitry Andric     R << ": " << ore::MNV("Inst", MI);
2920b57cec5SDimitry Andric   reportGISelFailure(MF, TPC, MORE, R);
2930b57cec5SDimitry Andric }
2940b57cec5SDimitry Andric 
295bdd1243dSDimitry Andric std::optional<APInt> llvm::getIConstantVRegVal(Register VReg,
2960b57cec5SDimitry Andric                                                const MachineRegisterInfo &MRI) {
297bdd1243dSDimitry Andric   std::optional<ValueAndVReg> ValAndVReg = getIConstantVRegValWithLookThrough(
298349cc55cSDimitry Andric       VReg, MRI, /*LookThroughInstrs*/ false);
2990b57cec5SDimitry Andric   assert((!ValAndVReg || ValAndVReg->VReg == VReg) &&
3000b57cec5SDimitry Andric          "Value found while looking through instrs");
3010b57cec5SDimitry Andric   if (!ValAndVReg)
302bdd1243dSDimitry Andric     return std::nullopt;
3030b57cec5SDimitry Andric   return ValAndVReg->Value;
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric 
306bdd1243dSDimitry Andric std::optional<int64_t>
307349cc55cSDimitry Andric llvm::getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI) {
308bdd1243dSDimitry Andric   std::optional<APInt> Val = getIConstantVRegVal(VReg, MRI);
309e8d8bef9SDimitry Andric   if (Val && Val->getBitWidth() <= 64)
310e8d8bef9SDimitry Andric     return Val->getSExtValue();
311bdd1243dSDimitry Andric   return std::nullopt;
312e8d8bef9SDimitry Andric }
313e8d8bef9SDimitry Andric 
314349cc55cSDimitry Andric namespace {
315349cc55cSDimitry Andric 
316*0fca6ea1SDimitry Andric // This function is used in many places, and as such, it has some
317*0fca6ea1SDimitry Andric // micro-optimizations to try and make it as fast as it can be.
318*0fca6ea1SDimitry Andric //
319*0fca6ea1SDimitry Andric // - We use template arguments to avoid an indirect call caused by passing a
320*0fca6ea1SDimitry Andric // function_ref/std::function
321*0fca6ea1SDimitry Andric // - GetAPCstValue does not return std::optional<APInt> as that's expensive.
322*0fca6ea1SDimitry Andric // Instead it returns true/false and places the result in a pre-constructed
323*0fca6ea1SDimitry Andric // APInt.
324*0fca6ea1SDimitry Andric //
325*0fca6ea1SDimitry Andric // Please change this function carefully and benchmark your changes.
326*0fca6ea1SDimitry Andric template <bool (*IsConstantOpcode)(const MachineInstr *),
327*0fca6ea1SDimitry Andric           bool (*GetAPCstValue)(const MachineInstr *MI, APInt &)>
328*0fca6ea1SDimitry Andric std::optional<ValueAndVReg>
329*0fca6ea1SDimitry Andric getConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI,
330*0fca6ea1SDimitry Andric                                   bool LookThroughInstrs = true,
331349cc55cSDimitry Andric                                   bool LookThroughAnyExt = false) {
3320b57cec5SDimitry Andric   SmallVector<std::pair<unsigned, unsigned>, 4> SeenOpcodes;
3330b57cec5SDimitry Andric   MachineInstr *MI;
334349cc55cSDimitry Andric 
335349cc55cSDimitry Andric   while ((MI = MRI.getVRegDef(VReg)) && !IsConstantOpcode(MI) &&
3368bcb0991SDimitry Andric          LookThroughInstrs) {
3370b57cec5SDimitry Andric     switch (MI->getOpcode()) {
338e8d8bef9SDimitry Andric     case TargetOpcode::G_ANYEXT:
339e8d8bef9SDimitry Andric       if (!LookThroughAnyExt)
340bdd1243dSDimitry Andric         return std::nullopt;
341bdd1243dSDimitry Andric       [[fallthrough]];
3420b57cec5SDimitry Andric     case TargetOpcode::G_TRUNC:
3430b57cec5SDimitry Andric     case TargetOpcode::G_SEXT:
3440b57cec5SDimitry Andric     case TargetOpcode::G_ZEXT:
3450b57cec5SDimitry Andric       SeenOpcodes.push_back(std::make_pair(
3460b57cec5SDimitry Andric           MI->getOpcode(),
3470b57cec5SDimitry Andric           MRI.getType(MI->getOperand(0).getReg()).getSizeInBits()));
3480b57cec5SDimitry Andric       VReg = MI->getOperand(1).getReg();
3490b57cec5SDimitry Andric       break;
3500b57cec5SDimitry Andric     case TargetOpcode::COPY:
3510b57cec5SDimitry Andric       VReg = MI->getOperand(1).getReg();
352bdd1243dSDimitry Andric       if (VReg.isPhysical())
353bdd1243dSDimitry Andric         return std::nullopt;
3540b57cec5SDimitry Andric       break;
3550b57cec5SDimitry Andric     case TargetOpcode::G_INTTOPTR:
3560b57cec5SDimitry Andric       VReg = MI->getOperand(1).getReg();
3570b57cec5SDimitry Andric       break;
3580b57cec5SDimitry Andric     default:
359bdd1243dSDimitry Andric       return std::nullopt;
3600b57cec5SDimitry Andric     }
3610b57cec5SDimitry Andric   }
362349cc55cSDimitry Andric   if (!MI || !IsConstantOpcode(MI))
363bdd1243dSDimitry Andric     return std::nullopt;
3640b57cec5SDimitry Andric 
365*0fca6ea1SDimitry Andric   APInt Val;
366*0fca6ea1SDimitry Andric   if (!GetAPCstValue(MI, Val))
367bdd1243dSDimitry Andric     return std::nullopt;
368*0fca6ea1SDimitry Andric   for (auto &Pair : reverse(SeenOpcodes)) {
369*0fca6ea1SDimitry Andric     switch (Pair.first) {
3700b57cec5SDimitry Andric     case TargetOpcode::G_TRUNC:
371*0fca6ea1SDimitry Andric       Val = Val.trunc(Pair.second);
3720b57cec5SDimitry Andric       break;
373e8d8bef9SDimitry Andric     case TargetOpcode::G_ANYEXT:
3740b57cec5SDimitry Andric     case TargetOpcode::G_SEXT:
375*0fca6ea1SDimitry Andric       Val = Val.sext(Pair.second);
3760b57cec5SDimitry Andric       break;
3770b57cec5SDimitry Andric     case TargetOpcode::G_ZEXT:
378*0fca6ea1SDimitry Andric       Val = Val.zext(Pair.second);
3790b57cec5SDimitry Andric       break;
3800b57cec5SDimitry Andric     }
3810b57cec5SDimitry Andric   }
3820b57cec5SDimitry Andric 
383*0fca6ea1SDimitry Andric   return ValueAndVReg{std::move(Val), VReg};
3840b57cec5SDimitry Andric }
3850b57cec5SDimitry Andric 
386349cc55cSDimitry Andric bool isIConstant(const MachineInstr *MI) {
387349cc55cSDimitry Andric   if (!MI)
388349cc55cSDimitry Andric     return false;
389349cc55cSDimitry Andric   return MI->getOpcode() == TargetOpcode::G_CONSTANT;
390349cc55cSDimitry Andric }
391349cc55cSDimitry Andric 
392349cc55cSDimitry Andric bool isFConstant(const MachineInstr *MI) {
393349cc55cSDimitry Andric   if (!MI)
394349cc55cSDimitry Andric     return false;
395349cc55cSDimitry Andric   return MI->getOpcode() == TargetOpcode::G_FCONSTANT;
396349cc55cSDimitry Andric }
397349cc55cSDimitry Andric 
398349cc55cSDimitry Andric bool isAnyConstant(const MachineInstr *MI) {
399349cc55cSDimitry Andric   if (!MI)
400349cc55cSDimitry Andric     return false;
401349cc55cSDimitry Andric   unsigned Opc = MI->getOpcode();
402349cc55cSDimitry Andric   return Opc == TargetOpcode::G_CONSTANT || Opc == TargetOpcode::G_FCONSTANT;
403349cc55cSDimitry Andric }
404349cc55cSDimitry Andric 
405*0fca6ea1SDimitry Andric bool getCImmAsAPInt(const MachineInstr *MI, APInt &Result) {
406349cc55cSDimitry Andric   const MachineOperand &CstVal = MI->getOperand(1);
407*0fca6ea1SDimitry Andric   if (!CstVal.isCImm())
408*0fca6ea1SDimitry Andric     return false;
409*0fca6ea1SDimitry Andric   Result = CstVal.getCImm()->getValue();
410*0fca6ea1SDimitry Andric   return true;
411349cc55cSDimitry Andric }
412349cc55cSDimitry Andric 
413*0fca6ea1SDimitry Andric bool getCImmOrFPImmAsAPInt(const MachineInstr *MI, APInt &Result) {
414349cc55cSDimitry Andric   const MachineOperand &CstVal = MI->getOperand(1);
415349cc55cSDimitry Andric   if (CstVal.isCImm())
416*0fca6ea1SDimitry Andric     Result = CstVal.getCImm()->getValue();
417*0fca6ea1SDimitry Andric   else if (CstVal.isFPImm())
418*0fca6ea1SDimitry Andric     Result = CstVal.getFPImm()->getValueAPF().bitcastToAPInt();
419*0fca6ea1SDimitry Andric   else
420*0fca6ea1SDimitry Andric     return false;
421*0fca6ea1SDimitry Andric   return true;
422349cc55cSDimitry Andric }
423349cc55cSDimitry Andric 
424349cc55cSDimitry Andric } // end anonymous namespace
425349cc55cSDimitry Andric 
426bdd1243dSDimitry Andric std::optional<ValueAndVReg> llvm::getIConstantVRegValWithLookThrough(
427349cc55cSDimitry Andric     Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs) {
428*0fca6ea1SDimitry Andric   return getConstantVRegValWithLookThrough<isIConstant, getCImmAsAPInt>(
429*0fca6ea1SDimitry Andric       VReg, MRI, LookThroughInstrs);
430349cc55cSDimitry Andric }
431349cc55cSDimitry Andric 
432bdd1243dSDimitry Andric std::optional<ValueAndVReg> llvm::getAnyConstantVRegValWithLookThrough(
433349cc55cSDimitry Andric     Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs,
434349cc55cSDimitry Andric     bool LookThroughAnyExt) {
435*0fca6ea1SDimitry Andric   return getConstantVRegValWithLookThrough<isAnyConstant,
436*0fca6ea1SDimitry Andric                                            getCImmOrFPImmAsAPInt>(
437*0fca6ea1SDimitry Andric       VReg, MRI, LookThroughInstrs, LookThroughAnyExt);
438349cc55cSDimitry Andric }
439349cc55cSDimitry Andric 
440bdd1243dSDimitry Andric std::optional<FPValueAndVReg> llvm::getFConstantVRegValWithLookThrough(
441349cc55cSDimitry Andric     Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs) {
442*0fca6ea1SDimitry Andric   auto Reg =
443*0fca6ea1SDimitry Andric       getConstantVRegValWithLookThrough<isFConstant, getCImmOrFPImmAsAPInt>(
444*0fca6ea1SDimitry Andric           VReg, MRI, LookThroughInstrs);
445349cc55cSDimitry Andric   if (!Reg)
446bdd1243dSDimitry Andric     return std::nullopt;
447349cc55cSDimitry Andric   return FPValueAndVReg{getConstantFPVRegVal(Reg->VReg, MRI)->getValueAPF(),
448349cc55cSDimitry Andric                         Reg->VReg};
449fe6060f1SDimitry Andric }
450fe6060f1SDimitry Andric 
451e8d8bef9SDimitry Andric const ConstantFP *
4525ffd83dbSDimitry Andric llvm::getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI) {
4530b57cec5SDimitry Andric   MachineInstr *MI = MRI.getVRegDef(VReg);
4540b57cec5SDimitry Andric   if (TargetOpcode::G_FCONSTANT != MI->getOpcode())
4550b57cec5SDimitry Andric     return nullptr;
4560b57cec5SDimitry Andric   return MI->getOperand(1).getFPImm();
4570b57cec5SDimitry Andric }
4580b57cec5SDimitry Andric 
459bdd1243dSDimitry Andric std::optional<DefinitionAndSourceRegister>
460e8d8bef9SDimitry Andric llvm::getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI) {
4615ffd83dbSDimitry Andric   Register DefSrcReg = Reg;
4620b57cec5SDimitry Andric   auto *DefMI = MRI.getVRegDef(Reg);
4630b57cec5SDimitry Andric   auto DstTy = MRI.getType(DefMI->getOperand(0).getReg());
4640b57cec5SDimitry Andric   if (!DstTy.isValid())
465bdd1243dSDimitry Andric     return std::nullopt;
466fe6060f1SDimitry Andric   unsigned Opc = DefMI->getOpcode();
467fe6060f1SDimitry Andric   while (Opc == TargetOpcode::COPY || isPreISelGenericOptimizationHint(Opc)) {
4688bcb0991SDimitry Andric     Register SrcReg = DefMI->getOperand(1).getReg();
4690b57cec5SDimitry Andric     auto SrcTy = MRI.getType(SrcReg);
470e8d8bef9SDimitry Andric     if (!SrcTy.isValid())
4710b57cec5SDimitry Andric       break;
4720b57cec5SDimitry Andric     DefMI = MRI.getVRegDef(SrcReg);
4735ffd83dbSDimitry Andric     DefSrcReg = SrcReg;
474fe6060f1SDimitry Andric     Opc = DefMI->getOpcode();
4750b57cec5SDimitry Andric   }
4765ffd83dbSDimitry Andric   return DefinitionAndSourceRegister{DefMI, DefSrcReg};
4775ffd83dbSDimitry Andric }
4785ffd83dbSDimitry Andric 
479e8d8bef9SDimitry Andric MachineInstr *llvm::getDefIgnoringCopies(Register Reg,
4805ffd83dbSDimitry Andric                                          const MachineRegisterInfo &MRI) {
481bdd1243dSDimitry Andric   std::optional<DefinitionAndSourceRegister> DefSrcReg =
4825ffd83dbSDimitry Andric       getDefSrcRegIgnoringCopies(Reg, MRI);
4835ffd83dbSDimitry Andric   return DefSrcReg ? DefSrcReg->MI : nullptr;
4845ffd83dbSDimitry Andric }
4855ffd83dbSDimitry Andric 
4865ffd83dbSDimitry Andric Register llvm::getSrcRegIgnoringCopies(Register Reg,
4875ffd83dbSDimitry Andric                                        const MachineRegisterInfo &MRI) {
488bdd1243dSDimitry Andric   std::optional<DefinitionAndSourceRegister> DefSrcReg =
4895ffd83dbSDimitry Andric       getDefSrcRegIgnoringCopies(Reg, MRI);
4905ffd83dbSDimitry Andric   return DefSrcReg ? DefSrcReg->Reg : Register();
4910b57cec5SDimitry Andric }
4920b57cec5SDimitry Andric 
4937a6dacacSDimitry Andric void llvm::extractParts(Register Reg, LLT Ty, int NumParts,
4947a6dacacSDimitry Andric                         SmallVectorImpl<Register> &VRegs,
4957a6dacacSDimitry Andric                         MachineIRBuilder &MIRBuilder,
4967a6dacacSDimitry Andric                         MachineRegisterInfo &MRI) {
4977a6dacacSDimitry Andric   for (int i = 0; i < NumParts; ++i)
4987a6dacacSDimitry Andric     VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
4997a6dacacSDimitry Andric   MIRBuilder.buildUnmerge(VRegs, Reg);
5007a6dacacSDimitry Andric }
5017a6dacacSDimitry Andric 
5027a6dacacSDimitry Andric bool llvm::extractParts(Register Reg, LLT RegTy, LLT MainTy, LLT &LeftoverTy,
5037a6dacacSDimitry Andric                         SmallVectorImpl<Register> &VRegs,
5047a6dacacSDimitry Andric                         SmallVectorImpl<Register> &LeftoverRegs,
5057a6dacacSDimitry Andric                         MachineIRBuilder &MIRBuilder,
5067a6dacacSDimitry Andric                         MachineRegisterInfo &MRI) {
5077a6dacacSDimitry Andric   assert(!LeftoverTy.isValid() && "this is an out argument");
5087a6dacacSDimitry Andric 
5097a6dacacSDimitry Andric   unsigned RegSize = RegTy.getSizeInBits();
5107a6dacacSDimitry Andric   unsigned MainSize = MainTy.getSizeInBits();
5117a6dacacSDimitry Andric   unsigned NumParts = RegSize / MainSize;
5127a6dacacSDimitry Andric   unsigned LeftoverSize = RegSize - NumParts * MainSize;
5137a6dacacSDimitry Andric 
5147a6dacacSDimitry Andric   // Use an unmerge when possible.
5157a6dacacSDimitry Andric   if (LeftoverSize == 0) {
5167a6dacacSDimitry Andric     for (unsigned I = 0; I < NumParts; ++I)
5177a6dacacSDimitry Andric       VRegs.push_back(MRI.createGenericVirtualRegister(MainTy));
5187a6dacacSDimitry Andric     MIRBuilder.buildUnmerge(VRegs, Reg);
5197a6dacacSDimitry Andric     return true;
5207a6dacacSDimitry Andric   }
5217a6dacacSDimitry Andric 
5227a6dacacSDimitry Andric   // Try to use unmerge for irregular vector split where possible
5237a6dacacSDimitry Andric   // For example when splitting a <6 x i32> into <4 x i32> with <2 x i32>
5247a6dacacSDimitry Andric   // leftover, it becomes:
5257a6dacacSDimitry Andric   //  <2 x i32> %2, <2 x i32>%3, <2 x i32> %4 = G_UNMERGE_VALUE <6 x i32> %1
5267a6dacacSDimitry Andric   //  <4 x i32> %5 = G_CONCAT_VECTOR <2 x i32> %2, <2 x i32> %3
5277a6dacacSDimitry Andric   if (RegTy.isVector() && MainTy.isVector()) {
5287a6dacacSDimitry Andric     unsigned RegNumElts = RegTy.getNumElements();
5297a6dacacSDimitry Andric     unsigned MainNumElts = MainTy.getNumElements();
5307a6dacacSDimitry Andric     unsigned LeftoverNumElts = RegNumElts % MainNumElts;
5317a6dacacSDimitry Andric     // If can unmerge to LeftoverTy, do it
5327a6dacacSDimitry Andric     if (MainNumElts % LeftoverNumElts == 0 &&
5337a6dacacSDimitry Andric         RegNumElts % LeftoverNumElts == 0 &&
5347a6dacacSDimitry Andric         RegTy.getScalarSizeInBits() == MainTy.getScalarSizeInBits() &&
5357a6dacacSDimitry Andric         LeftoverNumElts > 1) {
5367a6dacacSDimitry Andric       LeftoverTy =
5377a6dacacSDimitry Andric           LLT::fixed_vector(LeftoverNumElts, RegTy.getScalarSizeInBits());
5387a6dacacSDimitry Andric 
5397a6dacacSDimitry Andric       // Unmerge the SrcReg to LeftoverTy vectors
5407a6dacacSDimitry Andric       SmallVector<Register, 4> UnmergeValues;
5417a6dacacSDimitry Andric       extractParts(Reg, LeftoverTy, RegNumElts / LeftoverNumElts, UnmergeValues,
5427a6dacacSDimitry Andric                    MIRBuilder, MRI);
5437a6dacacSDimitry Andric 
5447a6dacacSDimitry Andric       // Find how many LeftoverTy makes one MainTy
5457a6dacacSDimitry Andric       unsigned LeftoverPerMain = MainNumElts / LeftoverNumElts;
5467a6dacacSDimitry Andric       unsigned NumOfLeftoverVal =
5477a6dacacSDimitry Andric           ((RegNumElts % MainNumElts) / LeftoverNumElts);
5487a6dacacSDimitry Andric 
5497a6dacacSDimitry Andric       // Create as many MainTy as possible using unmerged value
5507a6dacacSDimitry Andric       SmallVector<Register, 4> MergeValues;
5517a6dacacSDimitry Andric       for (unsigned I = 0; I < UnmergeValues.size() - NumOfLeftoverVal; I++) {
5527a6dacacSDimitry Andric         MergeValues.push_back(UnmergeValues[I]);
5537a6dacacSDimitry Andric         if (MergeValues.size() == LeftoverPerMain) {
5547a6dacacSDimitry Andric           VRegs.push_back(
5557a6dacacSDimitry Andric               MIRBuilder.buildMergeLikeInstr(MainTy, MergeValues).getReg(0));
5567a6dacacSDimitry Andric           MergeValues.clear();
5577a6dacacSDimitry Andric         }
5587a6dacacSDimitry Andric       }
5597a6dacacSDimitry Andric       // Populate LeftoverRegs with the leftovers
5607a6dacacSDimitry Andric       for (unsigned I = UnmergeValues.size() - NumOfLeftoverVal;
5617a6dacacSDimitry Andric            I < UnmergeValues.size(); I++) {
5627a6dacacSDimitry Andric         LeftoverRegs.push_back(UnmergeValues[I]);
5637a6dacacSDimitry Andric       }
5647a6dacacSDimitry Andric       return true;
5657a6dacacSDimitry Andric     }
5667a6dacacSDimitry Andric   }
5677a6dacacSDimitry Andric   // Perform irregular split. Leftover is last element of RegPieces.
5687a6dacacSDimitry Andric   if (MainTy.isVector()) {
5697a6dacacSDimitry Andric     SmallVector<Register, 8> RegPieces;
5707a6dacacSDimitry Andric     extractVectorParts(Reg, MainTy.getNumElements(), RegPieces, MIRBuilder,
5717a6dacacSDimitry Andric                        MRI);
5727a6dacacSDimitry Andric     for (unsigned i = 0; i < RegPieces.size() - 1; ++i)
5737a6dacacSDimitry Andric       VRegs.push_back(RegPieces[i]);
5747a6dacacSDimitry Andric     LeftoverRegs.push_back(RegPieces[RegPieces.size() - 1]);
5757a6dacacSDimitry Andric     LeftoverTy = MRI.getType(LeftoverRegs[0]);
5767a6dacacSDimitry Andric     return true;
5777a6dacacSDimitry Andric   }
5787a6dacacSDimitry Andric 
5797a6dacacSDimitry Andric   LeftoverTy = LLT::scalar(LeftoverSize);
5807a6dacacSDimitry Andric   // For irregular sizes, extract the individual parts.
5817a6dacacSDimitry Andric   for (unsigned I = 0; I != NumParts; ++I) {
5827a6dacacSDimitry Andric     Register NewReg = MRI.createGenericVirtualRegister(MainTy);
5837a6dacacSDimitry Andric     VRegs.push_back(NewReg);
5847a6dacacSDimitry Andric     MIRBuilder.buildExtract(NewReg, Reg, MainSize * I);
5857a6dacacSDimitry Andric   }
5867a6dacacSDimitry Andric 
5877a6dacacSDimitry Andric   for (unsigned Offset = MainSize * NumParts; Offset < RegSize;
5887a6dacacSDimitry Andric        Offset += LeftoverSize) {
5897a6dacacSDimitry Andric     Register NewReg = MRI.createGenericVirtualRegister(LeftoverTy);
5907a6dacacSDimitry Andric     LeftoverRegs.push_back(NewReg);
5917a6dacacSDimitry Andric     MIRBuilder.buildExtract(NewReg, Reg, Offset);
5927a6dacacSDimitry Andric   }
5937a6dacacSDimitry Andric 
5947a6dacacSDimitry Andric   return true;
5957a6dacacSDimitry Andric }
5967a6dacacSDimitry Andric 
5977a6dacacSDimitry Andric void llvm::extractVectorParts(Register Reg, unsigned NumElts,
5987a6dacacSDimitry Andric                               SmallVectorImpl<Register> &VRegs,
5997a6dacacSDimitry Andric                               MachineIRBuilder &MIRBuilder,
6007a6dacacSDimitry Andric                               MachineRegisterInfo &MRI) {
6017a6dacacSDimitry Andric   LLT RegTy = MRI.getType(Reg);
6027a6dacacSDimitry Andric   assert(RegTy.isVector() && "Expected a vector type");
6037a6dacacSDimitry Andric 
6047a6dacacSDimitry Andric   LLT EltTy = RegTy.getElementType();
6057a6dacacSDimitry Andric   LLT NarrowTy = (NumElts == 1) ? EltTy : LLT::fixed_vector(NumElts, EltTy);
6067a6dacacSDimitry Andric   unsigned RegNumElts = RegTy.getNumElements();
6077a6dacacSDimitry Andric   unsigned LeftoverNumElts = RegNumElts % NumElts;
6087a6dacacSDimitry Andric   unsigned NumNarrowTyPieces = RegNumElts / NumElts;
6097a6dacacSDimitry Andric 
6107a6dacacSDimitry Andric   // Perfect split without leftover
6117a6dacacSDimitry Andric   if (LeftoverNumElts == 0)
6127a6dacacSDimitry Andric     return extractParts(Reg, NarrowTy, NumNarrowTyPieces, VRegs, MIRBuilder,
6137a6dacacSDimitry Andric                         MRI);
6147a6dacacSDimitry Andric 
6157a6dacacSDimitry Andric   // Irregular split. Provide direct access to all elements for artifact
6167a6dacacSDimitry Andric   // combiner using unmerge to elements. Then build vectors with NumElts
6177a6dacacSDimitry Andric   // elements. Remaining element(s) will be (used to build vector) Leftover.
6187a6dacacSDimitry Andric   SmallVector<Register, 8> Elts;
6197a6dacacSDimitry Andric   extractParts(Reg, EltTy, RegNumElts, Elts, MIRBuilder, MRI);
6207a6dacacSDimitry Andric 
6217a6dacacSDimitry Andric   unsigned Offset = 0;
6227a6dacacSDimitry Andric   // Requested sub-vectors of NarrowTy.
6237a6dacacSDimitry Andric   for (unsigned i = 0; i < NumNarrowTyPieces; ++i, Offset += NumElts) {
6247a6dacacSDimitry Andric     ArrayRef<Register> Pieces(&Elts[Offset], NumElts);
6257a6dacacSDimitry Andric     VRegs.push_back(MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
6267a6dacacSDimitry Andric   }
6277a6dacacSDimitry Andric 
6287a6dacacSDimitry Andric   // Leftover element(s).
6297a6dacacSDimitry Andric   if (LeftoverNumElts == 1) {
6307a6dacacSDimitry Andric     VRegs.push_back(Elts[Offset]);
6317a6dacacSDimitry Andric   } else {
6327a6dacacSDimitry Andric     LLT LeftoverTy = LLT::fixed_vector(LeftoverNumElts, EltTy);
6337a6dacacSDimitry Andric     ArrayRef<Register> Pieces(&Elts[Offset], LeftoverNumElts);
6347a6dacacSDimitry Andric     VRegs.push_back(
6357a6dacacSDimitry Andric         MIRBuilder.buildMergeLikeInstr(LeftoverTy, Pieces).getReg(0));
6367a6dacacSDimitry Andric   }
6377a6dacacSDimitry Andric }
6387a6dacacSDimitry Andric 
639e8d8bef9SDimitry Andric MachineInstr *llvm::getOpcodeDef(unsigned Opcode, Register Reg,
6400b57cec5SDimitry Andric                                  const MachineRegisterInfo &MRI) {
6410b57cec5SDimitry Andric   MachineInstr *DefMI = getDefIgnoringCopies(Reg, MRI);
6420b57cec5SDimitry Andric   return DefMI && DefMI->getOpcode() == Opcode ? DefMI : nullptr;
6430b57cec5SDimitry Andric }
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric APFloat llvm::getAPFloatFromSize(double Val, unsigned Size) {
6460b57cec5SDimitry Andric   if (Size == 32)
6470b57cec5SDimitry Andric     return APFloat(float(Val));
6480b57cec5SDimitry Andric   if (Size == 64)
6490b57cec5SDimitry Andric     return APFloat(Val);
6500b57cec5SDimitry Andric   if (Size != 16)
6510b57cec5SDimitry Andric     llvm_unreachable("Unsupported FPConstant size");
6520b57cec5SDimitry Andric   bool Ignored;
6530b57cec5SDimitry Andric   APFloat APF(Val);
6540b57cec5SDimitry Andric   APF.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored);
6550b57cec5SDimitry Andric   return APF;
6560b57cec5SDimitry Andric }
6570b57cec5SDimitry Andric 
658bdd1243dSDimitry Andric std::optional<APInt> llvm::ConstantFoldBinOp(unsigned Opcode,
659bdd1243dSDimitry Andric                                              const Register Op1,
6605ffd83dbSDimitry Andric                                              const Register Op2,
6610b57cec5SDimitry Andric                                              const MachineRegisterInfo &MRI) {
662349cc55cSDimitry Andric   auto MaybeOp2Cst = getAnyConstantVRegValWithLookThrough(Op2, MRI, false);
6635ffd83dbSDimitry Andric   if (!MaybeOp2Cst)
664bdd1243dSDimitry Andric     return std::nullopt;
6655ffd83dbSDimitry Andric 
666349cc55cSDimitry Andric   auto MaybeOp1Cst = getAnyConstantVRegValWithLookThrough(Op1, MRI, false);
6675ffd83dbSDimitry Andric   if (!MaybeOp1Cst)
668bdd1243dSDimitry Andric     return std::nullopt;
6695ffd83dbSDimitry Andric 
670349cc55cSDimitry Andric   const APInt &C1 = MaybeOp1Cst->Value;
671349cc55cSDimitry Andric   const APInt &C2 = MaybeOp2Cst->Value;
6720b57cec5SDimitry Andric   switch (Opcode) {
6730b57cec5SDimitry Andric   default:
6740b57cec5SDimitry Andric     break;
6750b57cec5SDimitry Andric   case TargetOpcode::G_ADD:
6760b57cec5SDimitry Andric     return C1 + C2;
677*0fca6ea1SDimitry Andric   case TargetOpcode::G_PTR_ADD:
678*0fca6ea1SDimitry Andric     // Types can be of different width here.
679*0fca6ea1SDimitry Andric     // Result needs to be the same width as C1, so trunc or sext C2.
680*0fca6ea1SDimitry Andric     return C1 + C2.sextOrTrunc(C1.getBitWidth());
6810b57cec5SDimitry Andric   case TargetOpcode::G_AND:
6820b57cec5SDimitry Andric     return C1 & C2;
6830b57cec5SDimitry Andric   case TargetOpcode::G_ASHR:
6840b57cec5SDimitry Andric     return C1.ashr(C2);
6850b57cec5SDimitry Andric   case TargetOpcode::G_LSHR:
6860b57cec5SDimitry Andric     return C1.lshr(C2);
6870b57cec5SDimitry Andric   case TargetOpcode::G_MUL:
6880b57cec5SDimitry Andric     return C1 * C2;
6890b57cec5SDimitry Andric   case TargetOpcode::G_OR:
6900b57cec5SDimitry Andric     return C1 | C2;
6910b57cec5SDimitry Andric   case TargetOpcode::G_SHL:
6920b57cec5SDimitry Andric     return C1 << C2;
6930b57cec5SDimitry Andric   case TargetOpcode::G_SUB:
6940b57cec5SDimitry Andric     return C1 - C2;
6950b57cec5SDimitry Andric   case TargetOpcode::G_XOR:
6960b57cec5SDimitry Andric     return C1 ^ C2;
6970b57cec5SDimitry Andric   case TargetOpcode::G_UDIV:
6980b57cec5SDimitry Andric     if (!C2.getBoolValue())
6990b57cec5SDimitry Andric       break;
7000b57cec5SDimitry Andric     return C1.udiv(C2);
7010b57cec5SDimitry Andric   case TargetOpcode::G_SDIV:
7020b57cec5SDimitry Andric     if (!C2.getBoolValue())
7030b57cec5SDimitry Andric       break;
7040b57cec5SDimitry Andric     return C1.sdiv(C2);
7050b57cec5SDimitry Andric   case TargetOpcode::G_UREM:
7060b57cec5SDimitry Andric     if (!C2.getBoolValue())
7070b57cec5SDimitry Andric       break;
7080b57cec5SDimitry Andric     return C1.urem(C2);
7090b57cec5SDimitry Andric   case TargetOpcode::G_SREM:
7100b57cec5SDimitry Andric     if (!C2.getBoolValue())
7110b57cec5SDimitry Andric       break;
7120b57cec5SDimitry Andric     return C1.srem(C2);
71381ad6265SDimitry Andric   case TargetOpcode::G_SMIN:
71481ad6265SDimitry Andric     return APIntOps::smin(C1, C2);
71581ad6265SDimitry Andric   case TargetOpcode::G_SMAX:
71681ad6265SDimitry Andric     return APIntOps::smax(C1, C2);
71781ad6265SDimitry Andric   case TargetOpcode::G_UMIN:
71881ad6265SDimitry Andric     return APIntOps::umin(C1, C2);
71981ad6265SDimitry Andric   case TargetOpcode::G_UMAX:
72081ad6265SDimitry Andric     return APIntOps::umax(C1, C2);
7210b57cec5SDimitry Andric   }
7225ffd83dbSDimitry Andric 
723bdd1243dSDimitry Andric   return std::nullopt;
7240b57cec5SDimitry Andric }
7250b57cec5SDimitry Andric 
726bdd1243dSDimitry Andric std::optional<APFloat>
727bdd1243dSDimitry Andric llvm::ConstantFoldFPBinOp(unsigned Opcode, const Register Op1,
728bdd1243dSDimitry Andric                           const Register Op2, const MachineRegisterInfo &MRI) {
729fe6060f1SDimitry Andric   const ConstantFP *Op2Cst = getConstantFPVRegVal(Op2, MRI);
730fe6060f1SDimitry Andric   if (!Op2Cst)
731bdd1243dSDimitry Andric     return std::nullopt;
732fe6060f1SDimitry Andric 
733fe6060f1SDimitry Andric   const ConstantFP *Op1Cst = getConstantFPVRegVal(Op1, MRI);
734fe6060f1SDimitry Andric   if (!Op1Cst)
735bdd1243dSDimitry Andric     return std::nullopt;
736fe6060f1SDimitry Andric 
737fe6060f1SDimitry Andric   APFloat C1 = Op1Cst->getValueAPF();
738fe6060f1SDimitry Andric   const APFloat &C2 = Op2Cst->getValueAPF();
739fe6060f1SDimitry Andric   switch (Opcode) {
740fe6060f1SDimitry Andric   case TargetOpcode::G_FADD:
741fe6060f1SDimitry Andric     C1.add(C2, APFloat::rmNearestTiesToEven);
742fe6060f1SDimitry Andric     return C1;
743fe6060f1SDimitry Andric   case TargetOpcode::G_FSUB:
744fe6060f1SDimitry Andric     C1.subtract(C2, APFloat::rmNearestTiesToEven);
745fe6060f1SDimitry Andric     return C1;
746fe6060f1SDimitry Andric   case TargetOpcode::G_FMUL:
747fe6060f1SDimitry Andric     C1.multiply(C2, APFloat::rmNearestTiesToEven);
748fe6060f1SDimitry Andric     return C1;
749fe6060f1SDimitry Andric   case TargetOpcode::G_FDIV:
750fe6060f1SDimitry Andric     C1.divide(C2, APFloat::rmNearestTiesToEven);
751fe6060f1SDimitry Andric     return C1;
752fe6060f1SDimitry Andric   case TargetOpcode::G_FREM:
753fe6060f1SDimitry Andric     C1.mod(C2);
754fe6060f1SDimitry Andric     return C1;
755fe6060f1SDimitry Andric   case TargetOpcode::G_FCOPYSIGN:
756fe6060f1SDimitry Andric     C1.copySign(C2);
757fe6060f1SDimitry Andric     return C1;
758fe6060f1SDimitry Andric   case TargetOpcode::G_FMINNUM:
759fe6060f1SDimitry Andric     return minnum(C1, C2);
760fe6060f1SDimitry Andric   case TargetOpcode::G_FMAXNUM:
761fe6060f1SDimitry Andric     return maxnum(C1, C2);
762fe6060f1SDimitry Andric   case TargetOpcode::G_FMINIMUM:
763fe6060f1SDimitry Andric     return minimum(C1, C2);
764fe6060f1SDimitry Andric   case TargetOpcode::G_FMAXIMUM:
765fe6060f1SDimitry Andric     return maximum(C1, C2);
766fe6060f1SDimitry Andric   case TargetOpcode::G_FMINNUM_IEEE:
767fe6060f1SDimitry Andric   case TargetOpcode::G_FMAXNUM_IEEE:
768fe6060f1SDimitry Andric     // FIXME: These operations were unfortunately named. fminnum/fmaxnum do not
769fe6060f1SDimitry Andric     // follow the IEEE behavior for signaling nans and follow libm's fmin/fmax,
770fe6060f1SDimitry Andric     // and currently there isn't a nice wrapper in APFloat for the version with
771fe6060f1SDimitry Andric     // correct snan handling.
772fe6060f1SDimitry Andric     break;
773fe6060f1SDimitry Andric   default:
774fe6060f1SDimitry Andric     break;
775fe6060f1SDimitry Andric   }
776fe6060f1SDimitry Andric 
777bdd1243dSDimitry Andric   return std::nullopt;
778fe6060f1SDimitry Andric }
779fe6060f1SDimitry Andric 
78081ad6265SDimitry Andric SmallVector<APInt>
78181ad6265SDimitry Andric llvm::ConstantFoldVectorBinop(unsigned Opcode, const Register Op1,
782349cc55cSDimitry Andric                               const Register Op2,
78381ad6265SDimitry Andric                               const MachineRegisterInfo &MRI) {
784349cc55cSDimitry Andric   auto *SrcVec2 = getOpcodeDef<GBuildVector>(Op2, MRI);
785349cc55cSDimitry Andric   if (!SrcVec2)
78681ad6265SDimitry Andric     return SmallVector<APInt>();
78704eeddc0SDimitry Andric 
78804eeddc0SDimitry Andric   auto *SrcVec1 = getOpcodeDef<GBuildVector>(Op1, MRI);
78904eeddc0SDimitry Andric   if (!SrcVec1)
79081ad6265SDimitry Andric     return SmallVector<APInt>();
791349cc55cSDimitry Andric 
79281ad6265SDimitry Andric   SmallVector<APInt> FoldedElements;
793349cc55cSDimitry Andric   for (unsigned Idx = 0, E = SrcVec1->getNumSources(); Idx < E; ++Idx) {
794349cc55cSDimitry Andric     auto MaybeCst = ConstantFoldBinOp(Opcode, SrcVec1->getSourceReg(Idx),
795349cc55cSDimitry Andric                                       SrcVec2->getSourceReg(Idx), MRI);
796349cc55cSDimitry Andric     if (!MaybeCst)
79781ad6265SDimitry Andric       return SmallVector<APInt>();
79881ad6265SDimitry Andric     FoldedElements.push_back(*MaybeCst);
799349cc55cSDimitry Andric   }
80081ad6265SDimitry Andric   return FoldedElements;
801349cc55cSDimitry Andric }
802349cc55cSDimitry Andric 
8030b57cec5SDimitry Andric bool llvm::isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI,
8040b57cec5SDimitry Andric                            bool SNaN) {
8050b57cec5SDimitry Andric   const MachineInstr *DefMI = MRI.getVRegDef(Val);
8060b57cec5SDimitry Andric   if (!DefMI)
8070b57cec5SDimitry Andric     return false;
8080b57cec5SDimitry Andric 
809e8d8bef9SDimitry Andric   const TargetMachine& TM = DefMI->getMF()->getTarget();
810e8d8bef9SDimitry Andric   if (DefMI->getFlag(MachineInstr::FmNoNans) || TM.Options.NoNaNsFPMath)
8110b57cec5SDimitry Andric     return true;
8120b57cec5SDimitry Andric 
813fe6060f1SDimitry Andric   // If the value is a constant, we can obviously see if it is a NaN or not.
814fe6060f1SDimitry Andric   if (const ConstantFP *FPVal = getConstantFPVRegVal(Val, MRI)) {
815fe6060f1SDimitry Andric     return !FPVal->getValueAPF().isNaN() ||
816fe6060f1SDimitry Andric            (SNaN && !FPVal->getValueAPF().isSignaling());
817fe6060f1SDimitry Andric   }
818fe6060f1SDimitry Andric 
819fe6060f1SDimitry Andric   if (DefMI->getOpcode() == TargetOpcode::G_BUILD_VECTOR) {
820fe6060f1SDimitry Andric     for (const auto &Op : DefMI->uses())
821fe6060f1SDimitry Andric       if (!isKnownNeverNaN(Op.getReg(), MRI, SNaN))
822fe6060f1SDimitry Andric         return false;
823fe6060f1SDimitry Andric     return true;
824fe6060f1SDimitry Andric   }
825fe6060f1SDimitry Andric 
826fe6060f1SDimitry Andric   switch (DefMI->getOpcode()) {
827fe6060f1SDimitry Andric   default:
828fe6060f1SDimitry Andric     break;
829bdd1243dSDimitry Andric   case TargetOpcode::G_FADD:
830bdd1243dSDimitry Andric   case TargetOpcode::G_FSUB:
831bdd1243dSDimitry Andric   case TargetOpcode::G_FMUL:
832bdd1243dSDimitry Andric   case TargetOpcode::G_FDIV:
833bdd1243dSDimitry Andric   case TargetOpcode::G_FREM:
834bdd1243dSDimitry Andric   case TargetOpcode::G_FSIN:
835bdd1243dSDimitry Andric   case TargetOpcode::G_FCOS:
836*0fca6ea1SDimitry Andric   case TargetOpcode::G_FTAN:
837*0fca6ea1SDimitry Andric   case TargetOpcode::G_FACOS:
838*0fca6ea1SDimitry Andric   case TargetOpcode::G_FASIN:
839*0fca6ea1SDimitry Andric   case TargetOpcode::G_FATAN:
840*0fca6ea1SDimitry Andric   case TargetOpcode::G_FCOSH:
841*0fca6ea1SDimitry Andric   case TargetOpcode::G_FSINH:
842*0fca6ea1SDimitry Andric   case TargetOpcode::G_FTANH:
843bdd1243dSDimitry Andric   case TargetOpcode::G_FMA:
844bdd1243dSDimitry Andric   case TargetOpcode::G_FMAD:
845bdd1243dSDimitry Andric     if (SNaN)
846bdd1243dSDimitry Andric       return true;
847bdd1243dSDimitry Andric 
848bdd1243dSDimitry Andric     // TODO: Need isKnownNeverInfinity
849bdd1243dSDimitry Andric     return false;
850fe6060f1SDimitry Andric   case TargetOpcode::G_FMINNUM_IEEE:
851fe6060f1SDimitry Andric   case TargetOpcode::G_FMAXNUM_IEEE: {
852fe6060f1SDimitry Andric     if (SNaN)
853fe6060f1SDimitry Andric       return true;
854fe6060f1SDimitry Andric     // This can return a NaN if either operand is an sNaN, or if both operands
855fe6060f1SDimitry Andric     // are NaN.
856fe6060f1SDimitry Andric     return (isKnownNeverNaN(DefMI->getOperand(1).getReg(), MRI) &&
857fe6060f1SDimitry Andric             isKnownNeverSNaN(DefMI->getOperand(2).getReg(), MRI)) ||
858fe6060f1SDimitry Andric            (isKnownNeverSNaN(DefMI->getOperand(1).getReg(), MRI) &&
859fe6060f1SDimitry Andric             isKnownNeverNaN(DefMI->getOperand(2).getReg(), MRI));
860fe6060f1SDimitry Andric   }
861fe6060f1SDimitry Andric   case TargetOpcode::G_FMINNUM:
862fe6060f1SDimitry Andric   case TargetOpcode::G_FMAXNUM: {
863fe6060f1SDimitry Andric     // Only one needs to be known not-nan, since it will be returned if the
864fe6060f1SDimitry Andric     // other ends up being one.
865fe6060f1SDimitry Andric     return isKnownNeverNaN(DefMI->getOperand(1).getReg(), MRI, SNaN) ||
866fe6060f1SDimitry Andric            isKnownNeverNaN(DefMI->getOperand(2).getReg(), MRI, SNaN);
867fe6060f1SDimitry Andric   }
868fe6060f1SDimitry Andric   }
869fe6060f1SDimitry Andric 
8700b57cec5SDimitry Andric   if (SNaN) {
8710b57cec5SDimitry Andric     // FP operations quiet. For now, just handle the ones inserted during
8720b57cec5SDimitry Andric     // legalization.
8730b57cec5SDimitry Andric     switch (DefMI->getOpcode()) {
8740b57cec5SDimitry Andric     case TargetOpcode::G_FPEXT:
8750b57cec5SDimitry Andric     case TargetOpcode::G_FPTRUNC:
8760b57cec5SDimitry Andric     case TargetOpcode::G_FCANONICALIZE:
8770b57cec5SDimitry Andric       return true;
8780b57cec5SDimitry Andric     default:
8790b57cec5SDimitry Andric       return false;
8800b57cec5SDimitry Andric     }
8810b57cec5SDimitry Andric   }
8820b57cec5SDimitry Andric 
8830b57cec5SDimitry Andric   return false;
8840b57cec5SDimitry Andric }
8850b57cec5SDimitry Andric 
8865ffd83dbSDimitry Andric Align llvm::inferAlignFromPtrInfo(MachineFunction &MF,
8875ffd83dbSDimitry Andric                                   const MachinePointerInfo &MPO) {
88806c3fb27SDimitry Andric   auto PSV = dyn_cast_if_present<const PseudoSourceValue *>(MPO.V);
8895ffd83dbSDimitry Andric   if (auto FSPV = dyn_cast_or_null<FixedStackPseudoSourceValue>(PSV)) {
8905ffd83dbSDimitry Andric     MachineFrameInfo &MFI = MF.getFrameInfo();
8915ffd83dbSDimitry Andric     return commonAlignment(MFI.getObjectAlign(FSPV->getFrameIndex()),
8925ffd83dbSDimitry Andric                            MPO.Offset);
8935ffd83dbSDimitry Andric   }
8945ffd83dbSDimitry Andric 
89506c3fb27SDimitry Andric   if (const Value *V = dyn_cast_if_present<const Value *>(MPO.V)) {
896fe6060f1SDimitry Andric     const Module *M = MF.getFunction().getParent();
897fe6060f1SDimitry Andric     return V->getPointerAlignment(M->getDataLayout());
898fe6060f1SDimitry Andric   }
899fe6060f1SDimitry Andric 
9005ffd83dbSDimitry Andric   return Align(1);
9015ffd83dbSDimitry Andric }
9025ffd83dbSDimitry Andric 
903e8d8bef9SDimitry Andric Register llvm::getFunctionLiveInPhysReg(MachineFunction &MF,
904e8d8bef9SDimitry Andric                                         const TargetInstrInfo &TII,
905e8d8bef9SDimitry Andric                                         MCRegister PhysReg,
906e8d8bef9SDimitry Andric                                         const TargetRegisterClass &RC,
90704eeddc0SDimitry Andric                                         const DebugLoc &DL, LLT RegTy) {
908e8d8bef9SDimitry Andric   MachineBasicBlock &EntryMBB = MF.front();
909e8d8bef9SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
910e8d8bef9SDimitry Andric   Register LiveIn = MRI.getLiveInVirtReg(PhysReg);
911e8d8bef9SDimitry Andric   if (LiveIn) {
912e8d8bef9SDimitry Andric     MachineInstr *Def = MRI.getVRegDef(LiveIn);
913e8d8bef9SDimitry Andric     if (Def) {
914e8d8bef9SDimitry Andric       // FIXME: Should the verifier check this is in the entry block?
915e8d8bef9SDimitry Andric       assert(Def->getParent() == &EntryMBB && "live-in copy not in entry block");
916e8d8bef9SDimitry Andric       return LiveIn;
917e8d8bef9SDimitry Andric     }
918e8d8bef9SDimitry Andric 
919e8d8bef9SDimitry Andric     // It's possible the incoming argument register and copy was added during
920e8d8bef9SDimitry Andric     // lowering, but later deleted due to being/becoming dead. If this happens,
921e8d8bef9SDimitry Andric     // re-insert the copy.
922e8d8bef9SDimitry Andric   } else {
923e8d8bef9SDimitry Andric     // The live in register was not present, so add it.
924e8d8bef9SDimitry Andric     LiveIn = MF.addLiveIn(PhysReg, &RC);
925e8d8bef9SDimitry Andric     if (RegTy.isValid())
926e8d8bef9SDimitry Andric       MRI.setType(LiveIn, RegTy);
927e8d8bef9SDimitry Andric   }
928e8d8bef9SDimitry Andric 
929e8d8bef9SDimitry Andric   BuildMI(EntryMBB, EntryMBB.begin(), DL, TII.get(TargetOpcode::COPY), LiveIn)
930e8d8bef9SDimitry Andric     .addReg(PhysReg);
931e8d8bef9SDimitry Andric   if (!EntryMBB.isLiveIn(PhysReg))
932e8d8bef9SDimitry Andric     EntryMBB.addLiveIn(PhysReg);
933e8d8bef9SDimitry Andric   return LiveIn;
934e8d8bef9SDimitry Andric }
935e8d8bef9SDimitry Andric 
936bdd1243dSDimitry Andric std::optional<APInt> llvm::ConstantFoldExtOp(unsigned Opcode,
937bdd1243dSDimitry Andric                                              const Register Op1, uint64_t Imm,
9388bcb0991SDimitry Andric                                              const MachineRegisterInfo &MRI) {
939349cc55cSDimitry Andric   auto MaybeOp1Cst = getIConstantVRegVal(Op1, MRI);
9408bcb0991SDimitry Andric   if (MaybeOp1Cst) {
9418bcb0991SDimitry Andric     switch (Opcode) {
9428bcb0991SDimitry Andric     default:
9438bcb0991SDimitry Andric       break;
944e8d8bef9SDimitry Andric     case TargetOpcode::G_SEXT_INREG: {
945e8d8bef9SDimitry Andric       LLT Ty = MRI.getType(Op1);
946e8d8bef9SDimitry Andric       return MaybeOp1Cst->trunc(Imm).sext(Ty.getScalarSizeInBits());
947e8d8bef9SDimitry Andric     }
9488bcb0991SDimitry Andric     }
9498bcb0991SDimitry Andric   }
950bdd1243dSDimitry Andric   return std::nullopt;
9518bcb0991SDimitry Andric }
9528bcb0991SDimitry Andric 
9535f757f3fSDimitry Andric std::optional<APInt> llvm::ConstantFoldCastOp(unsigned Opcode, LLT DstTy,
9545f757f3fSDimitry Andric                                               const Register Op0,
9555f757f3fSDimitry Andric                                               const MachineRegisterInfo &MRI) {
9565f757f3fSDimitry Andric   std::optional<APInt> Val = getIConstantVRegVal(Op0, MRI);
9575f757f3fSDimitry Andric   if (!Val)
9585f757f3fSDimitry Andric     return Val;
9595f757f3fSDimitry Andric 
9605f757f3fSDimitry Andric   const unsigned DstSize = DstTy.getScalarSizeInBits();
9615f757f3fSDimitry Andric 
9625f757f3fSDimitry Andric   switch (Opcode) {
9635f757f3fSDimitry Andric   case TargetOpcode::G_SEXT:
9645f757f3fSDimitry Andric     return Val->sext(DstSize);
9655f757f3fSDimitry Andric   case TargetOpcode::G_ZEXT:
9665f757f3fSDimitry Andric   case TargetOpcode::G_ANYEXT:
9675f757f3fSDimitry Andric     // TODO: DAG considers target preference when constant folding any_extend.
9685f757f3fSDimitry Andric     return Val->zext(DstSize);
9695f757f3fSDimitry Andric   default:
9705f757f3fSDimitry Andric     break;
9715f757f3fSDimitry Andric   }
9725f757f3fSDimitry Andric 
9735f757f3fSDimitry Andric   llvm_unreachable("unexpected cast opcode to constant fold");
9745f757f3fSDimitry Andric }
9755f757f3fSDimitry Andric 
976bdd1243dSDimitry Andric std::optional<APFloat>
977bdd1243dSDimitry Andric llvm::ConstantFoldIntToFloat(unsigned Opcode, LLT DstTy, Register Src,
978fe6060f1SDimitry Andric                              const MachineRegisterInfo &MRI) {
979fe6060f1SDimitry Andric   assert(Opcode == TargetOpcode::G_SITOFP || Opcode == TargetOpcode::G_UITOFP);
980349cc55cSDimitry Andric   if (auto MaybeSrcVal = getIConstantVRegVal(Src, MRI)) {
981fe6060f1SDimitry Andric     APFloat DstVal(getFltSemanticForLLT(DstTy));
982fe6060f1SDimitry Andric     DstVal.convertFromAPInt(*MaybeSrcVal, Opcode == TargetOpcode::G_SITOFP,
983fe6060f1SDimitry Andric                             APFloat::rmNearestTiesToEven);
984fe6060f1SDimitry Andric     return DstVal;
985fe6060f1SDimitry Andric   }
986bdd1243dSDimitry Andric   return std::nullopt;
987fe6060f1SDimitry Andric }
988fe6060f1SDimitry Andric 
989bdd1243dSDimitry Andric std::optional<SmallVector<unsigned>>
990*0fca6ea1SDimitry Andric llvm::ConstantFoldCountZeros(Register Src, const MachineRegisterInfo &MRI,
991*0fca6ea1SDimitry Andric                              std::function<unsigned(APInt)> CB) {
992349cc55cSDimitry Andric   LLT Ty = MRI.getType(Src);
993349cc55cSDimitry Andric   SmallVector<unsigned> FoldedCTLZs;
994bdd1243dSDimitry Andric   auto tryFoldScalar = [&](Register R) -> std::optional<unsigned> {
995349cc55cSDimitry Andric     auto MaybeCst = getIConstantVRegVal(R, MRI);
996349cc55cSDimitry Andric     if (!MaybeCst)
997bdd1243dSDimitry Andric       return std::nullopt;
998*0fca6ea1SDimitry Andric     return CB(*MaybeCst);
999349cc55cSDimitry Andric   };
1000349cc55cSDimitry Andric   if (Ty.isVector()) {
1001349cc55cSDimitry Andric     // Try to constant fold each element.
1002349cc55cSDimitry Andric     auto *BV = getOpcodeDef<GBuildVector>(Src, MRI);
1003349cc55cSDimitry Andric     if (!BV)
1004bdd1243dSDimitry Andric       return std::nullopt;
1005349cc55cSDimitry Andric     for (unsigned SrcIdx = 0; SrcIdx < BV->getNumSources(); ++SrcIdx) {
1006349cc55cSDimitry Andric       if (auto MaybeFold = tryFoldScalar(BV->getSourceReg(SrcIdx))) {
1007349cc55cSDimitry Andric         FoldedCTLZs.emplace_back(*MaybeFold);
1008349cc55cSDimitry Andric         continue;
1009349cc55cSDimitry Andric       }
1010bdd1243dSDimitry Andric       return std::nullopt;
1011349cc55cSDimitry Andric     }
1012349cc55cSDimitry Andric     return FoldedCTLZs;
1013349cc55cSDimitry Andric   }
1014349cc55cSDimitry Andric   if (auto MaybeCst = tryFoldScalar(Src)) {
1015349cc55cSDimitry Andric     FoldedCTLZs.emplace_back(*MaybeCst);
1016349cc55cSDimitry Andric     return FoldedCTLZs;
1017349cc55cSDimitry Andric   }
1018bdd1243dSDimitry Andric   return std::nullopt;
1019349cc55cSDimitry Andric }
1020349cc55cSDimitry Andric 
1021*0fca6ea1SDimitry Andric std::optional<SmallVector<APInt>>
1022*0fca6ea1SDimitry Andric llvm::ConstantFoldICmp(unsigned Pred, const Register Op1, const Register Op2,
1023*0fca6ea1SDimitry Andric                        const MachineRegisterInfo &MRI) {
1024*0fca6ea1SDimitry Andric   LLT Ty = MRI.getType(Op1);
1025*0fca6ea1SDimitry Andric   if (Ty != MRI.getType(Op2))
1026*0fca6ea1SDimitry Andric     return std::nullopt;
1027*0fca6ea1SDimitry Andric 
1028*0fca6ea1SDimitry Andric   auto TryFoldScalar = [&MRI, Pred](Register LHS,
1029*0fca6ea1SDimitry Andric                                     Register RHS) -> std::optional<APInt> {
1030*0fca6ea1SDimitry Andric     auto LHSCst = getIConstantVRegVal(LHS, MRI);
1031*0fca6ea1SDimitry Andric     auto RHSCst = getIConstantVRegVal(RHS, MRI);
1032*0fca6ea1SDimitry Andric     if (!LHSCst || !RHSCst)
1033*0fca6ea1SDimitry Andric       return std::nullopt;
1034*0fca6ea1SDimitry Andric 
1035*0fca6ea1SDimitry Andric     switch (Pred) {
1036*0fca6ea1SDimitry Andric     case CmpInst::Predicate::ICMP_EQ:
1037*0fca6ea1SDimitry Andric       return APInt(/*numBits=*/1, LHSCst->eq(*RHSCst));
1038*0fca6ea1SDimitry Andric     case CmpInst::Predicate::ICMP_NE:
1039*0fca6ea1SDimitry Andric       return APInt(/*numBits=*/1, LHSCst->ne(*RHSCst));
1040*0fca6ea1SDimitry Andric     case CmpInst::Predicate::ICMP_UGT:
1041*0fca6ea1SDimitry Andric       return APInt(/*numBits=*/1, LHSCst->ugt(*RHSCst));
1042*0fca6ea1SDimitry Andric     case CmpInst::Predicate::ICMP_UGE:
1043*0fca6ea1SDimitry Andric       return APInt(/*numBits=*/1, LHSCst->uge(*RHSCst));
1044*0fca6ea1SDimitry Andric     case CmpInst::Predicate::ICMP_ULT:
1045*0fca6ea1SDimitry Andric       return APInt(/*numBits=*/1, LHSCst->ult(*RHSCst));
1046*0fca6ea1SDimitry Andric     case CmpInst::Predicate::ICMP_ULE:
1047*0fca6ea1SDimitry Andric       return APInt(/*numBits=*/1, LHSCst->ule(*RHSCst));
1048*0fca6ea1SDimitry Andric     case CmpInst::Predicate::ICMP_SGT:
1049*0fca6ea1SDimitry Andric       return APInt(/*numBits=*/1, LHSCst->sgt(*RHSCst));
1050*0fca6ea1SDimitry Andric     case CmpInst::Predicate::ICMP_SGE:
1051*0fca6ea1SDimitry Andric       return APInt(/*numBits=*/1, LHSCst->sge(*RHSCst));
1052*0fca6ea1SDimitry Andric     case CmpInst::Predicate::ICMP_SLT:
1053*0fca6ea1SDimitry Andric       return APInt(/*numBits=*/1, LHSCst->slt(*RHSCst));
1054*0fca6ea1SDimitry Andric     case CmpInst::Predicate::ICMP_SLE:
1055*0fca6ea1SDimitry Andric       return APInt(/*numBits=*/1, LHSCst->sle(*RHSCst));
1056*0fca6ea1SDimitry Andric     default:
1057*0fca6ea1SDimitry Andric       return std::nullopt;
1058*0fca6ea1SDimitry Andric     }
1059*0fca6ea1SDimitry Andric   };
1060*0fca6ea1SDimitry Andric 
1061*0fca6ea1SDimitry Andric   SmallVector<APInt> FoldedICmps;
1062*0fca6ea1SDimitry Andric 
1063*0fca6ea1SDimitry Andric   if (Ty.isVector()) {
1064*0fca6ea1SDimitry Andric     // Try to constant fold each element.
1065*0fca6ea1SDimitry Andric     auto *BV1 = getOpcodeDef<GBuildVector>(Op1, MRI);
1066*0fca6ea1SDimitry Andric     auto *BV2 = getOpcodeDef<GBuildVector>(Op2, MRI);
1067*0fca6ea1SDimitry Andric     if (!BV1 || !BV2)
1068*0fca6ea1SDimitry Andric       return std::nullopt;
1069*0fca6ea1SDimitry Andric     assert(BV1->getNumSources() == BV2->getNumSources() && "Invalid vectors");
1070*0fca6ea1SDimitry Andric     for (unsigned I = 0; I < BV1->getNumSources(); ++I) {
1071*0fca6ea1SDimitry Andric       if (auto MaybeFold =
1072*0fca6ea1SDimitry Andric               TryFoldScalar(BV1->getSourceReg(I), BV2->getSourceReg(I))) {
1073*0fca6ea1SDimitry Andric         FoldedICmps.emplace_back(*MaybeFold);
1074*0fca6ea1SDimitry Andric         continue;
1075*0fca6ea1SDimitry Andric       }
1076*0fca6ea1SDimitry Andric       return std::nullopt;
1077*0fca6ea1SDimitry Andric     }
1078*0fca6ea1SDimitry Andric     return FoldedICmps;
1079*0fca6ea1SDimitry Andric   }
1080*0fca6ea1SDimitry Andric 
1081*0fca6ea1SDimitry Andric   if (auto MaybeCst = TryFoldScalar(Op1, Op2)) {
1082*0fca6ea1SDimitry Andric     FoldedICmps.emplace_back(*MaybeCst);
1083*0fca6ea1SDimitry Andric     return FoldedICmps;
1084*0fca6ea1SDimitry Andric   }
1085*0fca6ea1SDimitry Andric 
1086*0fca6ea1SDimitry Andric   return std::nullopt;
1087*0fca6ea1SDimitry Andric }
1088*0fca6ea1SDimitry Andric 
1089e8d8bef9SDimitry Andric bool llvm::isKnownToBeAPowerOfTwo(Register Reg, const MachineRegisterInfo &MRI,
1090e8d8bef9SDimitry Andric                                   GISelKnownBits *KB) {
1091bdd1243dSDimitry Andric   std::optional<DefinitionAndSourceRegister> DefSrcReg =
1092e8d8bef9SDimitry Andric       getDefSrcRegIgnoringCopies(Reg, MRI);
1093e8d8bef9SDimitry Andric   if (!DefSrcReg)
1094e8d8bef9SDimitry Andric     return false;
1095e8d8bef9SDimitry Andric 
1096e8d8bef9SDimitry Andric   const MachineInstr &MI = *DefSrcReg->MI;
1097e8d8bef9SDimitry Andric   const LLT Ty = MRI.getType(Reg);
1098e8d8bef9SDimitry Andric 
1099e8d8bef9SDimitry Andric   switch (MI.getOpcode()) {
1100e8d8bef9SDimitry Andric   case TargetOpcode::G_CONSTANT: {
1101e8d8bef9SDimitry Andric     unsigned BitWidth = Ty.getScalarSizeInBits();
1102e8d8bef9SDimitry Andric     const ConstantInt *CI = MI.getOperand(1).getCImm();
1103e8d8bef9SDimitry Andric     return CI->getValue().zextOrTrunc(BitWidth).isPowerOf2();
1104e8d8bef9SDimitry Andric   }
1105e8d8bef9SDimitry Andric   case TargetOpcode::G_SHL: {
1106e8d8bef9SDimitry Andric     // A left-shift of a constant one will have exactly one bit set because
1107e8d8bef9SDimitry Andric     // shifting the bit off the end is undefined.
1108e8d8bef9SDimitry Andric 
1109e8d8bef9SDimitry Andric     // TODO: Constant splat
1110349cc55cSDimitry Andric     if (auto ConstLHS = getIConstantVRegVal(MI.getOperand(1).getReg(), MRI)) {
1111e8d8bef9SDimitry Andric       if (*ConstLHS == 1)
1112e8d8bef9SDimitry Andric         return true;
1113e8d8bef9SDimitry Andric     }
1114e8d8bef9SDimitry Andric 
1115e8d8bef9SDimitry Andric     break;
1116e8d8bef9SDimitry Andric   }
1117e8d8bef9SDimitry Andric   case TargetOpcode::G_LSHR: {
1118349cc55cSDimitry Andric     if (auto ConstLHS = getIConstantVRegVal(MI.getOperand(1).getReg(), MRI)) {
1119e8d8bef9SDimitry Andric       if (ConstLHS->isSignMask())
1120e8d8bef9SDimitry Andric         return true;
1121e8d8bef9SDimitry Andric     }
1122e8d8bef9SDimitry Andric 
1123e8d8bef9SDimitry Andric     break;
1124e8d8bef9SDimitry Andric   }
1125fe6060f1SDimitry Andric   case TargetOpcode::G_BUILD_VECTOR: {
1126fe6060f1SDimitry Andric     // TODO: Probably should have a recursion depth guard since you could have
1127fe6060f1SDimitry Andric     // bitcasted vector elements.
11284824e7fdSDimitry Andric     for (const MachineOperand &MO : llvm::drop_begin(MI.operands()))
11294824e7fdSDimitry Andric       if (!isKnownToBeAPowerOfTwo(MO.getReg(), MRI, KB))
1130fe6060f1SDimitry Andric         return false;
1131fe6060f1SDimitry Andric 
1132fe6060f1SDimitry Andric     return true;
1133fe6060f1SDimitry Andric   }
1134fe6060f1SDimitry Andric   case TargetOpcode::G_BUILD_VECTOR_TRUNC: {
1135fe6060f1SDimitry Andric     // Only handle constants since we would need to know if number of leading
1136fe6060f1SDimitry Andric     // zeros is greater than the truncation amount.
1137fe6060f1SDimitry Andric     const unsigned BitWidth = Ty.getScalarSizeInBits();
11384824e7fdSDimitry Andric     for (const MachineOperand &MO : llvm::drop_begin(MI.operands())) {
11394824e7fdSDimitry Andric       auto Const = getIConstantVRegVal(MO.getReg(), MRI);
1140fe6060f1SDimitry Andric       if (!Const || !Const->zextOrTrunc(BitWidth).isPowerOf2())
1141fe6060f1SDimitry Andric         return false;
1142fe6060f1SDimitry Andric     }
1143fe6060f1SDimitry Andric 
1144fe6060f1SDimitry Andric     return true;
1145fe6060f1SDimitry Andric   }
1146e8d8bef9SDimitry Andric   default:
1147e8d8bef9SDimitry Andric     break;
1148e8d8bef9SDimitry Andric   }
1149e8d8bef9SDimitry Andric 
1150e8d8bef9SDimitry Andric   if (!KB)
1151e8d8bef9SDimitry Andric     return false;
1152e8d8bef9SDimitry Andric 
1153e8d8bef9SDimitry Andric   // More could be done here, though the above checks are enough
1154e8d8bef9SDimitry Andric   // to handle some common cases.
1155e8d8bef9SDimitry Andric 
1156e8d8bef9SDimitry Andric   // Fall back to computeKnownBits to catch other known cases.
1157e8d8bef9SDimitry Andric   KnownBits Known = KB->getKnownBits(Reg);
1158e8d8bef9SDimitry Andric   return (Known.countMaxPopulation() == 1) && (Known.countMinPopulation() == 1);
1159e8d8bef9SDimitry Andric }
1160e8d8bef9SDimitry Andric 
11610b57cec5SDimitry Andric void llvm::getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU) {
11620b57cec5SDimitry Andric   AU.addPreserved<StackProtector>();
11630b57cec5SDimitry Andric }
11645ffd83dbSDimitry Andric 
1165e8d8bef9SDimitry Andric LLT llvm::getLCMType(LLT OrigTy, LLT TargetTy) {
1166*0fca6ea1SDimitry Andric   if (OrigTy.getSizeInBits() == TargetTy.getSizeInBits())
1167e8d8bef9SDimitry Andric     return OrigTy;
1168e8d8bef9SDimitry Andric 
1169*0fca6ea1SDimitry Andric   if (OrigTy.isVector() && TargetTy.isVector()) {
1170*0fca6ea1SDimitry Andric     LLT OrigElt = OrigTy.getElementType();
1171*0fca6ea1SDimitry Andric     LLT TargetElt = TargetTy.getElementType();
1172e8d8bef9SDimitry Andric 
1173*0fca6ea1SDimitry Andric     // TODO: The docstring for this function says the intention is to use this
1174*0fca6ea1SDimitry Andric     // function to build MERGE/UNMERGE instructions. It won't be the case that
1175*0fca6ea1SDimitry Andric     // we generate a MERGE/UNMERGE between fixed and scalable vector types. We
1176*0fca6ea1SDimitry Andric     // could implement getLCMType between the two in the future if there was a
1177*0fca6ea1SDimitry Andric     // need, but it is not worth it now as this function should not be used in
1178*0fca6ea1SDimitry Andric     // that way.
1179*0fca6ea1SDimitry Andric     assert(((OrigTy.isScalableVector() && !TargetTy.isFixedVector()) ||
1180*0fca6ea1SDimitry Andric             (OrigTy.isFixedVector() && !TargetTy.isScalableVector())) &&
1181*0fca6ea1SDimitry Andric            "getLCMType not implemented between fixed and scalable vectors.");
1182e8d8bef9SDimitry Andric 
1183e8d8bef9SDimitry Andric     if (OrigElt.getSizeInBits() == TargetElt.getSizeInBits()) {
1184*0fca6ea1SDimitry Andric       int GCDMinElts = std::gcd(OrigTy.getElementCount().getKnownMinValue(),
1185*0fca6ea1SDimitry Andric                                 TargetTy.getElementCount().getKnownMinValue());
1186e8d8bef9SDimitry Andric       // Prefer the original element type.
1187*0fca6ea1SDimitry Andric       ElementCount Mul = OrigTy.getElementCount().multiplyCoefficientBy(
1188*0fca6ea1SDimitry Andric           TargetTy.getElementCount().getKnownMinValue());
1189*0fca6ea1SDimitry Andric       return LLT::vector(Mul.divideCoefficientBy(GCDMinElts),
1190fe6060f1SDimitry Andric                          OrigTy.getElementType());
1191e8d8bef9SDimitry Andric     }
1192*0fca6ea1SDimitry Andric     unsigned LCM = std::lcm(OrigTy.getSizeInBits().getKnownMinValue(),
1193*0fca6ea1SDimitry Andric                             TargetTy.getSizeInBits().getKnownMinValue());
1194*0fca6ea1SDimitry Andric     return LLT::vector(
1195*0fca6ea1SDimitry Andric         ElementCount::get(LCM / OrigElt.getSizeInBits(), OrigTy.isScalable()),
1196*0fca6ea1SDimitry Andric         OrigElt);
11975ffd83dbSDimitry Andric   }
11985ffd83dbSDimitry Andric 
1199*0fca6ea1SDimitry Andric   // One type is scalar, one type is vector
1200*0fca6ea1SDimitry Andric   if (OrigTy.isVector() || TargetTy.isVector()) {
1201*0fca6ea1SDimitry Andric     LLT VecTy = OrigTy.isVector() ? OrigTy : TargetTy;
1202*0fca6ea1SDimitry Andric     LLT ScalarTy = OrigTy.isVector() ? TargetTy : OrigTy;
1203*0fca6ea1SDimitry Andric     LLT EltTy = VecTy.getElementType();
1204*0fca6ea1SDimitry Andric     LLT OrigEltTy = OrigTy.isVector() ? OrigTy.getElementType() : OrigTy;
1205*0fca6ea1SDimitry Andric 
1206*0fca6ea1SDimitry Andric     // Prefer scalar type from OrigTy.
1207*0fca6ea1SDimitry Andric     if (EltTy.getSizeInBits() == ScalarTy.getSizeInBits())
1208*0fca6ea1SDimitry Andric       return LLT::vector(VecTy.getElementCount(), OrigEltTy);
1209*0fca6ea1SDimitry Andric 
1210*0fca6ea1SDimitry Andric     // Different size scalars. Create vector with the same total size.
1211*0fca6ea1SDimitry Andric     // LCM will take fixed/scalable from VecTy.
1212*0fca6ea1SDimitry Andric     unsigned LCM = std::lcm(EltTy.getSizeInBits().getFixedValue() *
1213*0fca6ea1SDimitry Andric                                 VecTy.getElementCount().getKnownMinValue(),
1214*0fca6ea1SDimitry Andric                             ScalarTy.getSizeInBits().getFixedValue());
1215*0fca6ea1SDimitry Andric     // Prefer type from OrigTy
1216*0fca6ea1SDimitry Andric     return LLT::vector(ElementCount::get(LCM / OrigEltTy.getSizeInBits(),
1217*0fca6ea1SDimitry Andric                                          VecTy.getElementCount().isScalable()),
1218*0fca6ea1SDimitry Andric                        OrigEltTy);
12195ffd83dbSDimitry Andric   }
12205ffd83dbSDimitry Andric 
1221*0fca6ea1SDimitry Andric   // At this point, both types are scalars of different size
1222*0fca6ea1SDimitry Andric   unsigned LCM = std::lcm(OrigTy.getSizeInBits().getFixedValue(),
1223*0fca6ea1SDimitry Andric                           TargetTy.getSizeInBits().getFixedValue());
1224e8d8bef9SDimitry Andric   // Preserve pointer types.
1225*0fca6ea1SDimitry Andric   if (LCM == OrigTy.getSizeInBits())
1226e8d8bef9SDimitry Andric     return OrigTy;
1227*0fca6ea1SDimitry Andric   if (LCM == TargetTy.getSizeInBits())
1228e8d8bef9SDimitry Andric     return TargetTy;
1229*0fca6ea1SDimitry Andric   return LLT::scalar(LCM);
12305ffd83dbSDimitry Andric }
12315ffd83dbSDimitry Andric 
12320eae32dcSDimitry Andric LLT llvm::getCoverTy(LLT OrigTy, LLT TargetTy) {
1233*0fca6ea1SDimitry Andric 
1234*0fca6ea1SDimitry Andric   if ((OrigTy.isScalableVector() && TargetTy.isFixedVector()) ||
1235*0fca6ea1SDimitry Andric       (OrigTy.isFixedVector() && TargetTy.isScalableVector()))
1236*0fca6ea1SDimitry Andric     llvm_unreachable(
1237*0fca6ea1SDimitry Andric         "getCoverTy not implemented between fixed and scalable vectors.");
1238*0fca6ea1SDimitry Andric 
12390eae32dcSDimitry Andric   if (!OrigTy.isVector() || !TargetTy.isVector() || OrigTy == TargetTy ||
12400eae32dcSDimitry Andric       (OrigTy.getScalarSizeInBits() != TargetTy.getScalarSizeInBits()))
12410eae32dcSDimitry Andric     return getLCMType(OrigTy, TargetTy);
12420eae32dcSDimitry Andric 
1243*0fca6ea1SDimitry Andric   unsigned OrigTyNumElts = OrigTy.getElementCount().getKnownMinValue();
1244*0fca6ea1SDimitry Andric   unsigned TargetTyNumElts = TargetTy.getElementCount().getKnownMinValue();
12450eae32dcSDimitry Andric   if (OrigTyNumElts % TargetTyNumElts == 0)
12460eae32dcSDimitry Andric     return OrigTy;
12470eae32dcSDimitry Andric 
12480eae32dcSDimitry Andric   unsigned NumElts = alignTo(OrigTyNumElts, TargetTyNumElts);
12490eae32dcSDimitry Andric   return LLT::scalarOrVector(ElementCount::getFixed(NumElts),
12500eae32dcSDimitry Andric                              OrigTy.getElementType());
12510eae32dcSDimitry Andric }
12520eae32dcSDimitry Andric 
12535ffd83dbSDimitry Andric LLT llvm::getGCDType(LLT OrigTy, LLT TargetTy) {
1254*0fca6ea1SDimitry Andric   if (OrigTy.getSizeInBits() == TargetTy.getSizeInBits())
1255e8d8bef9SDimitry Andric     return OrigTy;
1256e8d8bef9SDimitry Andric 
1257*0fca6ea1SDimitry Andric   if (OrigTy.isVector() && TargetTy.isVector()) {
1258e8d8bef9SDimitry Andric     LLT OrigElt = OrigTy.getElementType();
12595ffd83dbSDimitry Andric 
1260*0fca6ea1SDimitry Andric     // TODO: The docstring for this function says the intention is to use this
1261*0fca6ea1SDimitry Andric     // function to build MERGE/UNMERGE instructions. It won't be the case that
1262*0fca6ea1SDimitry Andric     // we generate a MERGE/UNMERGE between fixed and scalable vector types. We
1263*0fca6ea1SDimitry Andric     // could implement getGCDType between the two in the future if there was a
1264*0fca6ea1SDimitry Andric     // need, but it is not worth it now as this function should not be used in
1265*0fca6ea1SDimitry Andric     // that way.
1266*0fca6ea1SDimitry Andric     assert(((OrigTy.isScalableVector() && !TargetTy.isFixedVector()) ||
1267*0fca6ea1SDimitry Andric             (OrigTy.isFixedVector() && !TargetTy.isScalableVector())) &&
1268*0fca6ea1SDimitry Andric            "getGCDType not implemented between fixed and scalable vectors.");
1269*0fca6ea1SDimitry Andric 
1270*0fca6ea1SDimitry Andric     unsigned GCD = std::gcd(OrigTy.getSizeInBits().getKnownMinValue(),
1271*0fca6ea1SDimitry Andric                             TargetTy.getSizeInBits().getKnownMinValue());
1272e8d8bef9SDimitry Andric     if (GCD == OrigElt.getSizeInBits())
1273*0fca6ea1SDimitry Andric       return LLT::scalarOrVector(ElementCount::get(1, OrigTy.isScalable()),
1274*0fca6ea1SDimitry Andric                                  OrigElt);
12755ffd83dbSDimitry Andric 
1276*0fca6ea1SDimitry Andric     // Cannot produce original element type, but both have vscale in common.
1277e8d8bef9SDimitry Andric     if (GCD < OrigElt.getSizeInBits())
1278*0fca6ea1SDimitry Andric       return LLT::scalarOrVector(ElementCount::get(1, OrigTy.isScalable()),
1279*0fca6ea1SDimitry Andric                                  GCD);
1280*0fca6ea1SDimitry Andric 
1281*0fca6ea1SDimitry Andric     return LLT::vector(
1282*0fca6ea1SDimitry Andric         ElementCount::get(GCD / OrigElt.getSizeInBits().getFixedValue(),
1283*0fca6ea1SDimitry Andric                           OrigTy.isScalable()),
1284*0fca6ea1SDimitry Andric         OrigElt);
1285e8d8bef9SDimitry Andric   }
1286e8d8bef9SDimitry Andric 
1287*0fca6ea1SDimitry Andric   // If one type is vector and the element size matches the scalar size, then
1288*0fca6ea1SDimitry Andric   // the gcd is the scalar type.
1289*0fca6ea1SDimitry Andric   if (OrigTy.isVector() &&
1290*0fca6ea1SDimitry Andric       OrigTy.getElementType().getSizeInBits() == TargetTy.getSizeInBits())
1291*0fca6ea1SDimitry Andric     return OrigTy.getElementType();
1292*0fca6ea1SDimitry Andric   if (TargetTy.isVector() &&
1293*0fca6ea1SDimitry Andric       TargetTy.getElementType().getSizeInBits() == OrigTy.getSizeInBits())
1294e8d8bef9SDimitry Andric     return OrigTy;
1295e8d8bef9SDimitry Andric 
1296*0fca6ea1SDimitry Andric   // At this point, both types are either scalars of different type or one is a
1297*0fca6ea1SDimitry Andric   // vector and one is a scalar. If both types are scalars, the GCD type is the
1298*0fca6ea1SDimitry Andric   // GCD between the two scalar sizes. If one is vector and one is scalar, then
1299*0fca6ea1SDimitry Andric   // the GCD type is the GCD between the scalar and the vector element size.
1300*0fca6ea1SDimitry Andric   LLT OrigScalar = OrigTy.getScalarType();
1301*0fca6ea1SDimitry Andric   LLT TargetScalar = TargetTy.getScalarType();
1302*0fca6ea1SDimitry Andric   unsigned GCD = std::gcd(OrigScalar.getSizeInBits().getFixedValue(),
1303*0fca6ea1SDimitry Andric                           TargetScalar.getSizeInBits().getFixedValue());
1304e8d8bef9SDimitry Andric   return LLT::scalar(GCD);
1305e8d8bef9SDimitry Andric }
1306e8d8bef9SDimitry Andric 
1307bdd1243dSDimitry Andric std::optional<int> llvm::getSplatIndex(MachineInstr &MI) {
1308e8d8bef9SDimitry Andric   assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR &&
1309e8d8bef9SDimitry Andric          "Only G_SHUFFLE_VECTOR can have a splat index!");
1310e8d8bef9SDimitry Andric   ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask();
1311e8d8bef9SDimitry Andric   auto FirstDefinedIdx = find_if(Mask, [](int Elt) { return Elt >= 0; });
1312e8d8bef9SDimitry Andric 
1313e8d8bef9SDimitry Andric   // If all elements are undefined, this shuffle can be considered a splat.
1314e8d8bef9SDimitry Andric   // Return 0 for better potential for callers to simplify.
1315e8d8bef9SDimitry Andric   if (FirstDefinedIdx == Mask.end())
1316e8d8bef9SDimitry Andric     return 0;
1317e8d8bef9SDimitry Andric 
1318e8d8bef9SDimitry Andric   // Make sure all remaining elements are either undef or the same
1319e8d8bef9SDimitry Andric   // as the first non-undef value.
1320e8d8bef9SDimitry Andric   int SplatValue = *FirstDefinedIdx;
1321e8d8bef9SDimitry Andric   if (any_of(make_range(std::next(FirstDefinedIdx), Mask.end()),
1322e8d8bef9SDimitry Andric              [&SplatValue](int Elt) { return Elt >= 0 && Elt != SplatValue; }))
1323bdd1243dSDimitry Andric     return std::nullopt;
1324e8d8bef9SDimitry Andric 
1325e8d8bef9SDimitry Andric   return SplatValue;
1326e8d8bef9SDimitry Andric }
1327e8d8bef9SDimitry Andric 
1328e8d8bef9SDimitry Andric static bool isBuildVectorOp(unsigned Opcode) {
1329e8d8bef9SDimitry Andric   return Opcode == TargetOpcode::G_BUILD_VECTOR ||
1330e8d8bef9SDimitry Andric          Opcode == TargetOpcode::G_BUILD_VECTOR_TRUNC;
1331e8d8bef9SDimitry Andric }
1332e8d8bef9SDimitry Andric 
1333349cc55cSDimitry Andric namespace {
1334349cc55cSDimitry Andric 
1335bdd1243dSDimitry Andric std::optional<ValueAndVReg> getAnyConstantSplat(Register VReg,
1336e8d8bef9SDimitry Andric                                                 const MachineRegisterInfo &MRI,
1337349cc55cSDimitry Andric                                                 bool AllowUndef) {
1338349cc55cSDimitry Andric   MachineInstr *MI = getDefIgnoringCopies(VReg, MRI);
1339349cc55cSDimitry Andric   if (!MI)
1340bdd1243dSDimitry Andric     return std::nullopt;
1341e8d8bef9SDimitry Andric 
1342bdd1243dSDimitry Andric   bool isConcatVectorsOp = MI->getOpcode() == TargetOpcode::G_CONCAT_VECTORS;
1343bdd1243dSDimitry Andric   if (!isBuildVectorOp(MI->getOpcode()) && !isConcatVectorsOp)
1344bdd1243dSDimitry Andric     return std::nullopt;
1345349cc55cSDimitry Andric 
1346bdd1243dSDimitry Andric   std::optional<ValueAndVReg> SplatValAndReg;
1347349cc55cSDimitry Andric   for (MachineOperand &Op : MI->uses()) {
1348349cc55cSDimitry Andric     Register Element = Op.getReg();
1349bdd1243dSDimitry Andric     // If we have a G_CONCAT_VECTOR, we recursively look into the
1350bdd1243dSDimitry Andric     // vectors that we're concatenating to see if they're splats.
1351349cc55cSDimitry Andric     auto ElementValAndReg =
1352bdd1243dSDimitry Andric         isConcatVectorsOp
1353bdd1243dSDimitry Andric             ? getAnyConstantSplat(Element, MRI, AllowUndef)
1354bdd1243dSDimitry Andric             : getAnyConstantVRegValWithLookThrough(Element, MRI, true, true);
1355349cc55cSDimitry Andric 
1356349cc55cSDimitry Andric     // If AllowUndef, treat undef as value that will result in a constant splat.
1357349cc55cSDimitry Andric     if (!ElementValAndReg) {
1358349cc55cSDimitry Andric       if (AllowUndef && isa<GImplicitDef>(MRI.getVRegDef(Element)))
1359349cc55cSDimitry Andric         continue;
1360bdd1243dSDimitry Andric       return std::nullopt;
1361349cc55cSDimitry Andric     }
1362349cc55cSDimitry Andric 
1363349cc55cSDimitry Andric     // Record splat value
1364349cc55cSDimitry Andric     if (!SplatValAndReg)
1365349cc55cSDimitry Andric       SplatValAndReg = ElementValAndReg;
1366349cc55cSDimitry Andric 
1367bdd1243dSDimitry Andric     // Different constant than the one already recorded, not a constant splat.
1368349cc55cSDimitry Andric     if (SplatValAndReg->Value != ElementValAndReg->Value)
1369bdd1243dSDimitry Andric       return std::nullopt;
1370349cc55cSDimitry Andric   }
1371349cc55cSDimitry Andric 
1372349cc55cSDimitry Andric   return SplatValAndReg;
1373349cc55cSDimitry Andric }
1374349cc55cSDimitry Andric 
13754824e7fdSDimitry Andric } // end anonymous namespace
13764824e7fdSDimitry Andric 
13774824e7fdSDimitry Andric bool llvm::isBuildVectorConstantSplat(const Register Reg,
1378349cc55cSDimitry Andric                                       const MachineRegisterInfo &MRI,
1379349cc55cSDimitry Andric                                       int64_t SplatValue, bool AllowUndef) {
13804824e7fdSDimitry Andric   if (auto SplatValAndReg = getAnyConstantSplat(Reg, MRI, AllowUndef))
1381349cc55cSDimitry Andric     return mi_match(SplatValAndReg->VReg, MRI, m_SpecificICst(SplatValue));
1382e8d8bef9SDimitry Andric   return false;
1383e8d8bef9SDimitry Andric }
1384e8d8bef9SDimitry Andric 
13854824e7fdSDimitry Andric bool llvm::isBuildVectorConstantSplat(const MachineInstr &MI,
13864824e7fdSDimitry Andric                                       const MachineRegisterInfo &MRI,
13874824e7fdSDimitry Andric                                       int64_t SplatValue, bool AllowUndef) {
13884824e7fdSDimitry Andric   return isBuildVectorConstantSplat(MI.getOperand(0).getReg(), MRI, SplatValue,
13894824e7fdSDimitry Andric                                     AllowUndef);
13904824e7fdSDimitry Andric }
1391e8d8bef9SDimitry Andric 
1392bdd1243dSDimitry Andric std::optional<APInt>
1393bdd1243dSDimitry Andric llvm::getIConstantSplatVal(const Register Reg, const MachineRegisterInfo &MRI) {
1394349cc55cSDimitry Andric   if (auto SplatValAndReg =
139581ad6265SDimitry Andric           getAnyConstantSplat(Reg, MRI, /* AllowUndef */ false)) {
13965f757f3fSDimitry Andric     if (std::optional<ValueAndVReg> ValAndVReg =
13975f757f3fSDimitry Andric         getIConstantVRegValWithLookThrough(SplatValAndReg->VReg, MRI))
139881ad6265SDimitry Andric       return ValAndVReg->Value;
139981ad6265SDimitry Andric   }
140081ad6265SDimitry Andric 
1401bdd1243dSDimitry Andric   return std::nullopt;
140281ad6265SDimitry Andric }
140381ad6265SDimitry Andric 
1404bdd1243dSDimitry Andric std::optional<APInt>
1405bdd1243dSDimitry Andric llvm::getIConstantSplatVal(const MachineInstr &MI,
140681ad6265SDimitry Andric                            const MachineRegisterInfo &MRI) {
140781ad6265SDimitry Andric   return getIConstantSplatVal(MI.getOperand(0).getReg(), MRI);
140881ad6265SDimitry Andric }
140981ad6265SDimitry Andric 
1410bdd1243dSDimitry Andric std::optional<int64_t>
141181ad6265SDimitry Andric llvm::getIConstantSplatSExtVal(const Register Reg,
141281ad6265SDimitry Andric                                const MachineRegisterInfo &MRI) {
141381ad6265SDimitry Andric   if (auto SplatValAndReg =
141481ad6265SDimitry Andric           getAnyConstantSplat(Reg, MRI, /* AllowUndef */ false))
1415349cc55cSDimitry Andric     return getIConstantVRegSExtVal(SplatValAndReg->VReg, MRI);
1416bdd1243dSDimitry Andric   return std::nullopt;
1417e8d8bef9SDimitry Andric }
1418e8d8bef9SDimitry Andric 
1419bdd1243dSDimitry Andric std::optional<int64_t>
142081ad6265SDimitry Andric llvm::getIConstantSplatSExtVal(const MachineInstr &MI,
142181ad6265SDimitry Andric                                const MachineRegisterInfo &MRI) {
142281ad6265SDimitry Andric   return getIConstantSplatSExtVal(MI.getOperand(0).getReg(), MRI);
142381ad6265SDimitry Andric }
142481ad6265SDimitry Andric 
1425bdd1243dSDimitry Andric std::optional<FPValueAndVReg>
1426bdd1243dSDimitry Andric llvm::getFConstantSplat(Register VReg, const MachineRegisterInfo &MRI,
1427349cc55cSDimitry Andric                         bool AllowUndef) {
1428349cc55cSDimitry Andric   if (auto SplatValAndReg = getAnyConstantSplat(VReg, MRI, AllowUndef))
1429349cc55cSDimitry Andric     return getFConstantVRegValWithLookThrough(SplatValAndReg->VReg, MRI);
1430bdd1243dSDimitry Andric   return std::nullopt;
1431e8d8bef9SDimitry Andric }
1432e8d8bef9SDimitry Andric 
1433e8d8bef9SDimitry Andric bool llvm::isBuildVectorAllZeros(const MachineInstr &MI,
1434349cc55cSDimitry Andric                                  const MachineRegisterInfo &MRI,
1435349cc55cSDimitry Andric                                  bool AllowUndef) {
1436349cc55cSDimitry Andric   return isBuildVectorConstantSplat(MI, MRI, 0, AllowUndef);
1437e8d8bef9SDimitry Andric }
1438e8d8bef9SDimitry Andric 
1439e8d8bef9SDimitry Andric bool llvm::isBuildVectorAllOnes(const MachineInstr &MI,
1440349cc55cSDimitry Andric                                 const MachineRegisterInfo &MRI,
1441349cc55cSDimitry Andric                                 bool AllowUndef) {
1442349cc55cSDimitry Andric   return isBuildVectorConstantSplat(MI, MRI, -1, AllowUndef);
1443e8d8bef9SDimitry Andric }
1444e8d8bef9SDimitry Andric 
1445bdd1243dSDimitry Andric std::optional<RegOrConstant>
1446bdd1243dSDimitry Andric llvm::getVectorSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI) {
1447fe6060f1SDimitry Andric   unsigned Opc = MI.getOpcode();
1448fe6060f1SDimitry Andric   if (!isBuildVectorOp(Opc))
1449bdd1243dSDimitry Andric     return std::nullopt;
145081ad6265SDimitry Andric   if (auto Splat = getIConstantSplatSExtVal(MI, MRI))
1451fe6060f1SDimitry Andric     return RegOrConstant(*Splat);
1452fe6060f1SDimitry Andric   auto Reg = MI.getOperand(1).getReg();
14535f757f3fSDimitry Andric   if (any_of(drop_begin(MI.operands(), 2),
1454fe6060f1SDimitry Andric              [&Reg](const MachineOperand &Op) { return Op.getReg() != Reg; }))
1455bdd1243dSDimitry Andric     return std::nullopt;
1456fe6060f1SDimitry Andric   return RegOrConstant(Reg);
1457fe6060f1SDimitry Andric }
1458fe6060f1SDimitry Andric 
145981ad6265SDimitry Andric static bool isConstantScalar(const MachineInstr &MI,
146081ad6265SDimitry Andric                              const MachineRegisterInfo &MRI,
146181ad6265SDimitry Andric                              bool AllowFP = true,
146281ad6265SDimitry Andric                              bool AllowOpaqueConstants = true) {
146381ad6265SDimitry Andric   switch (MI.getOpcode()) {
146481ad6265SDimitry Andric   case TargetOpcode::G_CONSTANT:
146581ad6265SDimitry Andric   case TargetOpcode::G_IMPLICIT_DEF:
146681ad6265SDimitry Andric     return true;
146781ad6265SDimitry Andric   case TargetOpcode::G_FCONSTANT:
146881ad6265SDimitry Andric     return AllowFP;
146981ad6265SDimitry Andric   case TargetOpcode::G_GLOBAL_VALUE:
147081ad6265SDimitry Andric   case TargetOpcode::G_FRAME_INDEX:
147181ad6265SDimitry Andric   case TargetOpcode::G_BLOCK_ADDR:
147281ad6265SDimitry Andric   case TargetOpcode::G_JUMP_TABLE:
147381ad6265SDimitry Andric     return AllowOpaqueConstants;
147481ad6265SDimitry Andric   default:
147581ad6265SDimitry Andric     return false;
147681ad6265SDimitry Andric   }
147781ad6265SDimitry Andric }
147881ad6265SDimitry Andric 
1479349cc55cSDimitry Andric bool llvm::isConstantOrConstantVector(MachineInstr &MI,
1480349cc55cSDimitry Andric                                       const MachineRegisterInfo &MRI) {
1481349cc55cSDimitry Andric   Register Def = MI.getOperand(0).getReg();
1482349cc55cSDimitry Andric   if (auto C = getIConstantVRegValWithLookThrough(Def, MRI))
1483349cc55cSDimitry Andric     return true;
1484349cc55cSDimitry Andric   GBuildVector *BV = dyn_cast<GBuildVector>(&MI);
1485349cc55cSDimitry Andric   if (!BV)
1486349cc55cSDimitry Andric     return false;
1487349cc55cSDimitry Andric   for (unsigned SrcIdx = 0; SrcIdx < BV->getNumSources(); ++SrcIdx) {
1488349cc55cSDimitry Andric     if (getIConstantVRegValWithLookThrough(BV->getSourceReg(SrcIdx), MRI) ||
1489349cc55cSDimitry Andric         getOpcodeDef<GImplicitDef>(BV->getSourceReg(SrcIdx), MRI))
1490349cc55cSDimitry Andric       continue;
1491349cc55cSDimitry Andric     return false;
1492349cc55cSDimitry Andric   }
1493349cc55cSDimitry Andric   return true;
1494349cc55cSDimitry Andric }
1495349cc55cSDimitry Andric 
149681ad6265SDimitry Andric bool llvm::isConstantOrConstantVector(const MachineInstr &MI,
149781ad6265SDimitry Andric                                       const MachineRegisterInfo &MRI,
149881ad6265SDimitry Andric                                       bool AllowFP, bool AllowOpaqueConstants) {
149981ad6265SDimitry Andric   if (isConstantScalar(MI, MRI, AllowFP, AllowOpaqueConstants))
150081ad6265SDimitry Andric     return true;
150181ad6265SDimitry Andric 
150281ad6265SDimitry Andric   if (!isBuildVectorOp(MI.getOpcode()))
150381ad6265SDimitry Andric     return false;
150481ad6265SDimitry Andric 
150581ad6265SDimitry Andric   const unsigned NumOps = MI.getNumOperands();
150681ad6265SDimitry Andric   for (unsigned I = 1; I != NumOps; ++I) {
150781ad6265SDimitry Andric     const MachineInstr *ElementDef = MRI.getVRegDef(MI.getOperand(I).getReg());
150881ad6265SDimitry Andric     if (!isConstantScalar(*ElementDef, MRI, AllowFP, AllowOpaqueConstants))
150981ad6265SDimitry Andric       return false;
151081ad6265SDimitry Andric   }
151181ad6265SDimitry Andric 
151281ad6265SDimitry Andric   return true;
151381ad6265SDimitry Andric }
151481ad6265SDimitry Andric 
1515bdd1243dSDimitry Andric std::optional<APInt>
1516349cc55cSDimitry Andric llvm::isConstantOrConstantSplatVector(MachineInstr &MI,
1517349cc55cSDimitry Andric                                       const MachineRegisterInfo &MRI) {
1518349cc55cSDimitry Andric   Register Def = MI.getOperand(0).getReg();
1519349cc55cSDimitry Andric   if (auto C = getIConstantVRegValWithLookThrough(Def, MRI))
1520349cc55cSDimitry Andric     return C->Value;
152181ad6265SDimitry Andric   auto MaybeCst = getIConstantSplatSExtVal(MI, MRI);
1522349cc55cSDimitry Andric   if (!MaybeCst)
1523bdd1243dSDimitry Andric     return std::nullopt;
1524349cc55cSDimitry Andric   const unsigned ScalarSize = MRI.getType(Def).getScalarSizeInBits();
1525349cc55cSDimitry Andric   return APInt(ScalarSize, *MaybeCst, true);
1526349cc55cSDimitry Andric }
1527349cc55cSDimitry Andric 
152881ad6265SDimitry Andric bool llvm::isNullOrNullSplat(const MachineInstr &MI,
152981ad6265SDimitry Andric                              const MachineRegisterInfo &MRI, bool AllowUndefs) {
153081ad6265SDimitry Andric   switch (MI.getOpcode()) {
153181ad6265SDimitry Andric   case TargetOpcode::G_IMPLICIT_DEF:
153281ad6265SDimitry Andric     return AllowUndefs;
153381ad6265SDimitry Andric   case TargetOpcode::G_CONSTANT:
153481ad6265SDimitry Andric     return MI.getOperand(1).getCImm()->isNullValue();
153581ad6265SDimitry Andric   case TargetOpcode::G_FCONSTANT: {
153681ad6265SDimitry Andric     const ConstantFP *FPImm = MI.getOperand(1).getFPImm();
153781ad6265SDimitry Andric     return FPImm->isZero() && !FPImm->isNegative();
153881ad6265SDimitry Andric   }
153981ad6265SDimitry Andric   default:
154081ad6265SDimitry Andric     if (!AllowUndefs) // TODO: isBuildVectorAllZeros assumes undef is OK already
154181ad6265SDimitry Andric       return false;
154281ad6265SDimitry Andric     return isBuildVectorAllZeros(MI, MRI);
154381ad6265SDimitry Andric   }
154481ad6265SDimitry Andric }
154581ad6265SDimitry Andric 
154681ad6265SDimitry Andric bool llvm::isAllOnesOrAllOnesSplat(const MachineInstr &MI,
154781ad6265SDimitry Andric                                    const MachineRegisterInfo &MRI,
154881ad6265SDimitry Andric                                    bool AllowUndefs) {
154981ad6265SDimitry Andric   switch (MI.getOpcode()) {
155081ad6265SDimitry Andric   case TargetOpcode::G_IMPLICIT_DEF:
155181ad6265SDimitry Andric     return AllowUndefs;
155281ad6265SDimitry Andric   case TargetOpcode::G_CONSTANT:
155381ad6265SDimitry Andric     return MI.getOperand(1).getCImm()->isAllOnesValue();
155481ad6265SDimitry Andric   default:
155581ad6265SDimitry Andric     if (!AllowUndefs) // TODO: isBuildVectorAllOnes assumes undef is OK already
155681ad6265SDimitry Andric       return false;
155781ad6265SDimitry Andric     return isBuildVectorAllOnes(MI, MRI);
155881ad6265SDimitry Andric   }
155981ad6265SDimitry Andric }
156081ad6265SDimitry Andric 
1561fe6060f1SDimitry Andric bool llvm::matchUnaryPredicate(
1562fe6060f1SDimitry Andric     const MachineRegisterInfo &MRI, Register Reg,
1563fe6060f1SDimitry Andric     std::function<bool(const Constant *ConstVal)> Match, bool AllowUndefs) {
1564fe6060f1SDimitry Andric 
1565fe6060f1SDimitry Andric   const MachineInstr *Def = getDefIgnoringCopies(Reg, MRI);
1566fe6060f1SDimitry Andric   if (AllowUndefs && Def->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
1567fe6060f1SDimitry Andric     return Match(nullptr);
1568fe6060f1SDimitry Andric 
1569fe6060f1SDimitry Andric   // TODO: Also handle fconstant
1570fe6060f1SDimitry Andric   if (Def->getOpcode() == TargetOpcode::G_CONSTANT)
1571fe6060f1SDimitry Andric     return Match(Def->getOperand(1).getCImm());
1572fe6060f1SDimitry Andric 
1573fe6060f1SDimitry Andric   if (Def->getOpcode() != TargetOpcode::G_BUILD_VECTOR)
1574fe6060f1SDimitry Andric     return false;
1575fe6060f1SDimitry Andric 
1576fe6060f1SDimitry Andric   for (unsigned I = 1, E = Def->getNumOperands(); I != E; ++I) {
1577fe6060f1SDimitry Andric     Register SrcElt = Def->getOperand(I).getReg();
1578fe6060f1SDimitry Andric     const MachineInstr *SrcDef = getDefIgnoringCopies(SrcElt, MRI);
1579fe6060f1SDimitry Andric     if (AllowUndefs && SrcDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF) {
1580fe6060f1SDimitry Andric       if (!Match(nullptr))
1581fe6060f1SDimitry Andric         return false;
1582fe6060f1SDimitry Andric       continue;
1583fe6060f1SDimitry Andric     }
1584fe6060f1SDimitry Andric 
1585fe6060f1SDimitry Andric     if (SrcDef->getOpcode() != TargetOpcode::G_CONSTANT ||
1586fe6060f1SDimitry Andric         !Match(SrcDef->getOperand(1).getCImm()))
1587fe6060f1SDimitry Andric       return false;
1588fe6060f1SDimitry Andric   }
1589fe6060f1SDimitry Andric 
1590fe6060f1SDimitry Andric   return true;
1591fe6060f1SDimitry Andric }
1592fe6060f1SDimitry Andric 
1593e8d8bef9SDimitry Andric bool llvm::isConstTrueVal(const TargetLowering &TLI, int64_t Val, bool IsVector,
1594e8d8bef9SDimitry Andric                           bool IsFP) {
1595e8d8bef9SDimitry Andric   switch (TLI.getBooleanContents(IsVector, IsFP)) {
1596e8d8bef9SDimitry Andric   case TargetLowering::UndefinedBooleanContent:
1597e8d8bef9SDimitry Andric     return Val & 0x1;
1598e8d8bef9SDimitry Andric   case TargetLowering::ZeroOrOneBooleanContent:
1599e8d8bef9SDimitry Andric     return Val == 1;
1600e8d8bef9SDimitry Andric   case TargetLowering::ZeroOrNegativeOneBooleanContent:
1601e8d8bef9SDimitry Andric     return Val == -1;
1602e8d8bef9SDimitry Andric   }
1603e8d8bef9SDimitry Andric   llvm_unreachable("Invalid boolean contents");
1604e8d8bef9SDimitry Andric }
1605e8d8bef9SDimitry Andric 
1606bdd1243dSDimitry Andric bool llvm::isConstFalseVal(const TargetLowering &TLI, int64_t Val,
1607bdd1243dSDimitry Andric                            bool IsVector, bool IsFP) {
1608bdd1243dSDimitry Andric   switch (TLI.getBooleanContents(IsVector, IsFP)) {
1609bdd1243dSDimitry Andric   case TargetLowering::UndefinedBooleanContent:
1610bdd1243dSDimitry Andric     return ~Val & 0x1;
1611bdd1243dSDimitry Andric   case TargetLowering::ZeroOrOneBooleanContent:
1612bdd1243dSDimitry Andric   case TargetLowering::ZeroOrNegativeOneBooleanContent:
1613bdd1243dSDimitry Andric     return Val == 0;
1614bdd1243dSDimitry Andric   }
1615bdd1243dSDimitry Andric   llvm_unreachable("Invalid boolean contents");
1616bdd1243dSDimitry Andric }
1617bdd1243dSDimitry Andric 
1618e8d8bef9SDimitry Andric int64_t llvm::getICmpTrueVal(const TargetLowering &TLI, bool IsVector,
1619e8d8bef9SDimitry Andric                              bool IsFP) {
1620e8d8bef9SDimitry Andric   switch (TLI.getBooleanContents(IsVector, IsFP)) {
1621e8d8bef9SDimitry Andric   case TargetLowering::UndefinedBooleanContent:
1622e8d8bef9SDimitry Andric   case TargetLowering::ZeroOrOneBooleanContent:
1623e8d8bef9SDimitry Andric     return 1;
1624e8d8bef9SDimitry Andric   case TargetLowering::ZeroOrNegativeOneBooleanContent:
1625e8d8bef9SDimitry Andric     return -1;
1626e8d8bef9SDimitry Andric   }
1627e8d8bef9SDimitry Andric   llvm_unreachable("Invalid boolean contents");
16285ffd83dbSDimitry Andric }
1629fe6060f1SDimitry Andric 
1630fe6060f1SDimitry Andric bool llvm::shouldOptForSize(const MachineBasicBlock &MBB,
1631fe6060f1SDimitry Andric                             ProfileSummaryInfo *PSI, BlockFrequencyInfo *BFI) {
1632fe6060f1SDimitry Andric   const auto &F = MBB.getParent()->getFunction();
1633fe6060f1SDimitry Andric   return F.hasOptSize() || F.hasMinSize() ||
1634fe6060f1SDimitry Andric          llvm::shouldOptimizeForSize(MBB.getBasicBlock(), PSI, BFI);
1635fe6060f1SDimitry Andric }
1636349cc55cSDimitry Andric 
1637349cc55cSDimitry Andric void llvm::saveUsesAndErase(MachineInstr &MI, MachineRegisterInfo &MRI,
1638349cc55cSDimitry Andric                             LostDebugLocObserver *LocObserver,
1639349cc55cSDimitry Andric                             SmallInstListTy &DeadInstChain) {
1640349cc55cSDimitry Andric   for (MachineOperand &Op : MI.uses()) {
1641349cc55cSDimitry Andric     if (Op.isReg() && Op.getReg().isVirtual())
1642349cc55cSDimitry Andric       DeadInstChain.insert(MRI.getVRegDef(Op.getReg()));
1643349cc55cSDimitry Andric   }
1644349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << MI << "Is dead; erasing.\n");
1645349cc55cSDimitry Andric   DeadInstChain.remove(&MI);
1646349cc55cSDimitry Andric   MI.eraseFromParent();
1647349cc55cSDimitry Andric   if (LocObserver)
1648349cc55cSDimitry Andric     LocObserver->checkpoint(false);
1649349cc55cSDimitry Andric }
1650349cc55cSDimitry Andric 
1651349cc55cSDimitry Andric void llvm::eraseInstrs(ArrayRef<MachineInstr *> DeadInstrs,
1652349cc55cSDimitry Andric                        MachineRegisterInfo &MRI,
1653349cc55cSDimitry Andric                        LostDebugLocObserver *LocObserver) {
1654349cc55cSDimitry Andric   SmallInstListTy DeadInstChain;
1655349cc55cSDimitry Andric   for (MachineInstr *MI : DeadInstrs)
1656349cc55cSDimitry Andric     saveUsesAndErase(*MI, MRI, LocObserver, DeadInstChain);
1657349cc55cSDimitry Andric 
1658349cc55cSDimitry Andric   while (!DeadInstChain.empty()) {
1659349cc55cSDimitry Andric     MachineInstr *Inst = DeadInstChain.pop_back_val();
1660349cc55cSDimitry Andric     if (!isTriviallyDead(*Inst, MRI))
1661349cc55cSDimitry Andric       continue;
1662349cc55cSDimitry Andric     saveUsesAndErase(*Inst, MRI, LocObserver, DeadInstChain);
1663349cc55cSDimitry Andric   }
1664349cc55cSDimitry Andric }
1665349cc55cSDimitry Andric 
1666349cc55cSDimitry Andric void llvm::eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI,
1667349cc55cSDimitry Andric                       LostDebugLocObserver *LocObserver) {
1668349cc55cSDimitry Andric   return eraseInstrs({&MI}, MRI, LocObserver);
1669349cc55cSDimitry Andric }
1670bdd1243dSDimitry Andric 
1671bdd1243dSDimitry Andric void llvm::salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI) {
1672bdd1243dSDimitry Andric   for (auto &Def : MI.defs()) {
1673bdd1243dSDimitry Andric     assert(Def.isReg() && "Must be a reg");
1674bdd1243dSDimitry Andric 
1675bdd1243dSDimitry Andric     SmallVector<MachineOperand *, 16> DbgUsers;
1676bdd1243dSDimitry Andric     for (auto &MOUse : MRI.use_operands(Def.getReg())) {
1677bdd1243dSDimitry Andric       MachineInstr *DbgValue = MOUse.getParent();
1678bdd1243dSDimitry Andric       // Ignore partially formed DBG_VALUEs.
1679bdd1243dSDimitry Andric       if (DbgValue->isNonListDebugValue() && DbgValue->getNumOperands() == 4) {
1680bdd1243dSDimitry Andric         DbgUsers.push_back(&MOUse);
1681bdd1243dSDimitry Andric       }
1682bdd1243dSDimitry Andric     }
1683bdd1243dSDimitry Andric 
1684bdd1243dSDimitry Andric     if (!DbgUsers.empty()) {
1685bdd1243dSDimitry Andric       salvageDebugInfoForDbgValue(MRI, MI, DbgUsers);
1686bdd1243dSDimitry Andric     }
1687bdd1243dSDimitry Andric   }
1688bdd1243dSDimitry Andric }
1689*0fca6ea1SDimitry Andric 
1690*0fca6ea1SDimitry Andric bool llvm::isPreISelGenericFloatingPointOpcode(unsigned Opc) {
1691*0fca6ea1SDimitry Andric   switch (Opc) {
1692*0fca6ea1SDimitry Andric   case TargetOpcode::G_FABS:
1693*0fca6ea1SDimitry Andric   case TargetOpcode::G_FADD:
1694*0fca6ea1SDimitry Andric   case TargetOpcode::G_FCANONICALIZE:
1695*0fca6ea1SDimitry Andric   case TargetOpcode::G_FCEIL:
1696*0fca6ea1SDimitry Andric   case TargetOpcode::G_FCONSTANT:
1697*0fca6ea1SDimitry Andric   case TargetOpcode::G_FCOPYSIGN:
1698*0fca6ea1SDimitry Andric   case TargetOpcode::G_FCOS:
1699*0fca6ea1SDimitry Andric   case TargetOpcode::G_FDIV:
1700*0fca6ea1SDimitry Andric   case TargetOpcode::G_FEXP2:
1701*0fca6ea1SDimitry Andric   case TargetOpcode::G_FEXP:
1702*0fca6ea1SDimitry Andric   case TargetOpcode::G_FFLOOR:
1703*0fca6ea1SDimitry Andric   case TargetOpcode::G_FLOG10:
1704*0fca6ea1SDimitry Andric   case TargetOpcode::G_FLOG2:
1705*0fca6ea1SDimitry Andric   case TargetOpcode::G_FLOG:
1706*0fca6ea1SDimitry Andric   case TargetOpcode::G_FMA:
1707*0fca6ea1SDimitry Andric   case TargetOpcode::G_FMAD:
1708*0fca6ea1SDimitry Andric   case TargetOpcode::G_FMAXIMUM:
1709*0fca6ea1SDimitry Andric   case TargetOpcode::G_FMAXNUM:
1710*0fca6ea1SDimitry Andric   case TargetOpcode::G_FMAXNUM_IEEE:
1711*0fca6ea1SDimitry Andric   case TargetOpcode::G_FMINIMUM:
1712*0fca6ea1SDimitry Andric   case TargetOpcode::G_FMINNUM:
1713*0fca6ea1SDimitry Andric   case TargetOpcode::G_FMINNUM_IEEE:
1714*0fca6ea1SDimitry Andric   case TargetOpcode::G_FMUL:
1715*0fca6ea1SDimitry Andric   case TargetOpcode::G_FNEARBYINT:
1716*0fca6ea1SDimitry Andric   case TargetOpcode::G_FNEG:
1717*0fca6ea1SDimitry Andric   case TargetOpcode::G_FPEXT:
1718*0fca6ea1SDimitry Andric   case TargetOpcode::G_FPOW:
1719*0fca6ea1SDimitry Andric   case TargetOpcode::G_FPTRUNC:
1720*0fca6ea1SDimitry Andric   case TargetOpcode::G_FREM:
1721*0fca6ea1SDimitry Andric   case TargetOpcode::G_FRINT:
1722*0fca6ea1SDimitry Andric   case TargetOpcode::G_FSIN:
1723*0fca6ea1SDimitry Andric   case TargetOpcode::G_FTAN:
1724*0fca6ea1SDimitry Andric   case TargetOpcode::G_FACOS:
1725*0fca6ea1SDimitry Andric   case TargetOpcode::G_FASIN:
1726*0fca6ea1SDimitry Andric   case TargetOpcode::G_FATAN:
1727*0fca6ea1SDimitry Andric   case TargetOpcode::G_FCOSH:
1728*0fca6ea1SDimitry Andric   case TargetOpcode::G_FSINH:
1729*0fca6ea1SDimitry Andric   case TargetOpcode::G_FTANH:
1730*0fca6ea1SDimitry Andric   case TargetOpcode::G_FSQRT:
1731*0fca6ea1SDimitry Andric   case TargetOpcode::G_FSUB:
1732*0fca6ea1SDimitry Andric   case TargetOpcode::G_INTRINSIC_ROUND:
1733*0fca6ea1SDimitry Andric   case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
1734*0fca6ea1SDimitry Andric   case TargetOpcode::G_INTRINSIC_TRUNC:
1735*0fca6ea1SDimitry Andric     return true;
1736*0fca6ea1SDimitry Andric   default:
1737*0fca6ea1SDimitry Andric     return false;
1738*0fca6ea1SDimitry Andric   }
1739*0fca6ea1SDimitry Andric }
1740*0fca6ea1SDimitry Andric 
1741*0fca6ea1SDimitry Andric /// Shifts return poison if shiftwidth is larger than the bitwidth.
1742*0fca6ea1SDimitry Andric static bool shiftAmountKnownInRange(Register ShiftAmount,
1743*0fca6ea1SDimitry Andric                                     const MachineRegisterInfo &MRI) {
1744*0fca6ea1SDimitry Andric   LLT Ty = MRI.getType(ShiftAmount);
1745*0fca6ea1SDimitry Andric 
1746*0fca6ea1SDimitry Andric   if (Ty.isScalableVector())
1747*0fca6ea1SDimitry Andric     return false; // Can't tell, just return false to be safe
1748*0fca6ea1SDimitry Andric 
1749*0fca6ea1SDimitry Andric   if (Ty.isScalar()) {
1750*0fca6ea1SDimitry Andric     std::optional<ValueAndVReg> Val =
1751*0fca6ea1SDimitry Andric         getIConstantVRegValWithLookThrough(ShiftAmount, MRI);
1752*0fca6ea1SDimitry Andric     if (!Val)
1753*0fca6ea1SDimitry Andric       return false;
1754*0fca6ea1SDimitry Andric     return Val->Value.ult(Ty.getScalarSizeInBits());
1755*0fca6ea1SDimitry Andric   }
1756*0fca6ea1SDimitry Andric 
1757*0fca6ea1SDimitry Andric   GBuildVector *BV = getOpcodeDef<GBuildVector>(ShiftAmount, MRI);
1758*0fca6ea1SDimitry Andric   if (!BV)
1759*0fca6ea1SDimitry Andric     return false;
1760*0fca6ea1SDimitry Andric 
1761*0fca6ea1SDimitry Andric   unsigned Sources = BV->getNumSources();
1762*0fca6ea1SDimitry Andric   for (unsigned I = 0; I < Sources; ++I) {
1763*0fca6ea1SDimitry Andric     std::optional<ValueAndVReg> Val =
1764*0fca6ea1SDimitry Andric         getIConstantVRegValWithLookThrough(BV->getSourceReg(I), MRI);
1765*0fca6ea1SDimitry Andric     if (!Val)
1766*0fca6ea1SDimitry Andric       return false;
1767*0fca6ea1SDimitry Andric     if (!Val->Value.ult(Ty.getScalarSizeInBits()))
1768*0fca6ea1SDimitry Andric       return false;
1769*0fca6ea1SDimitry Andric   }
1770*0fca6ea1SDimitry Andric 
1771*0fca6ea1SDimitry Andric   return true;
1772*0fca6ea1SDimitry Andric }
1773*0fca6ea1SDimitry Andric 
1774*0fca6ea1SDimitry Andric namespace {
1775*0fca6ea1SDimitry Andric enum class UndefPoisonKind {
1776*0fca6ea1SDimitry Andric   PoisonOnly = (1 << 0),
1777*0fca6ea1SDimitry Andric   UndefOnly = (1 << 1),
1778*0fca6ea1SDimitry Andric   UndefOrPoison = PoisonOnly | UndefOnly,
1779*0fca6ea1SDimitry Andric };
1780*0fca6ea1SDimitry Andric }
1781*0fca6ea1SDimitry Andric 
1782*0fca6ea1SDimitry Andric static bool includesPoison(UndefPoisonKind Kind) {
1783*0fca6ea1SDimitry Andric   return (unsigned(Kind) & unsigned(UndefPoisonKind::PoisonOnly)) != 0;
1784*0fca6ea1SDimitry Andric }
1785*0fca6ea1SDimitry Andric 
1786*0fca6ea1SDimitry Andric static bool includesUndef(UndefPoisonKind Kind) {
1787*0fca6ea1SDimitry Andric   return (unsigned(Kind) & unsigned(UndefPoisonKind::UndefOnly)) != 0;
1788*0fca6ea1SDimitry Andric }
1789*0fca6ea1SDimitry Andric 
1790*0fca6ea1SDimitry Andric static bool canCreateUndefOrPoison(Register Reg, const MachineRegisterInfo &MRI,
1791*0fca6ea1SDimitry Andric                                    bool ConsiderFlagsAndMetadata,
1792*0fca6ea1SDimitry Andric                                    UndefPoisonKind Kind) {
1793*0fca6ea1SDimitry Andric   MachineInstr *RegDef = MRI.getVRegDef(Reg);
1794*0fca6ea1SDimitry Andric 
1795*0fca6ea1SDimitry Andric   if (ConsiderFlagsAndMetadata && includesPoison(Kind))
1796*0fca6ea1SDimitry Andric     if (auto *GMI = dyn_cast<GenericMachineInstr>(RegDef))
1797*0fca6ea1SDimitry Andric       if (GMI->hasPoisonGeneratingFlags())
1798*0fca6ea1SDimitry Andric         return true;
1799*0fca6ea1SDimitry Andric 
1800*0fca6ea1SDimitry Andric   // Check whether opcode is a poison/undef-generating operation.
1801*0fca6ea1SDimitry Andric   switch (RegDef->getOpcode()) {
1802*0fca6ea1SDimitry Andric   case TargetOpcode::G_BUILD_VECTOR:
1803*0fca6ea1SDimitry Andric   case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1804*0fca6ea1SDimitry Andric     return false;
1805*0fca6ea1SDimitry Andric   case TargetOpcode::G_SHL:
1806*0fca6ea1SDimitry Andric   case TargetOpcode::G_ASHR:
1807*0fca6ea1SDimitry Andric   case TargetOpcode::G_LSHR:
1808*0fca6ea1SDimitry Andric     return includesPoison(Kind) &&
1809*0fca6ea1SDimitry Andric            !shiftAmountKnownInRange(RegDef->getOperand(2).getReg(), MRI);
1810*0fca6ea1SDimitry Andric   case TargetOpcode::G_FPTOSI:
1811*0fca6ea1SDimitry Andric   case TargetOpcode::G_FPTOUI:
1812*0fca6ea1SDimitry Andric     // fptosi/ui yields poison if the resulting value does not fit in the
1813*0fca6ea1SDimitry Andric     // destination type.
1814*0fca6ea1SDimitry Andric     return true;
1815*0fca6ea1SDimitry Andric   case TargetOpcode::G_CTLZ:
1816*0fca6ea1SDimitry Andric   case TargetOpcode::G_CTTZ:
1817*0fca6ea1SDimitry Andric   case TargetOpcode::G_ABS:
1818*0fca6ea1SDimitry Andric   case TargetOpcode::G_CTPOP:
1819*0fca6ea1SDimitry Andric   case TargetOpcode::G_BSWAP:
1820*0fca6ea1SDimitry Andric   case TargetOpcode::G_BITREVERSE:
1821*0fca6ea1SDimitry Andric   case TargetOpcode::G_FSHL:
1822*0fca6ea1SDimitry Andric   case TargetOpcode::G_FSHR:
1823*0fca6ea1SDimitry Andric   case TargetOpcode::G_SMAX:
1824*0fca6ea1SDimitry Andric   case TargetOpcode::G_SMIN:
1825*0fca6ea1SDimitry Andric   case TargetOpcode::G_UMAX:
1826*0fca6ea1SDimitry Andric   case TargetOpcode::G_UMIN:
1827*0fca6ea1SDimitry Andric   case TargetOpcode::G_PTRMASK:
1828*0fca6ea1SDimitry Andric   case TargetOpcode::G_SADDO:
1829*0fca6ea1SDimitry Andric   case TargetOpcode::G_SSUBO:
1830*0fca6ea1SDimitry Andric   case TargetOpcode::G_UADDO:
1831*0fca6ea1SDimitry Andric   case TargetOpcode::G_USUBO:
1832*0fca6ea1SDimitry Andric   case TargetOpcode::G_SMULO:
1833*0fca6ea1SDimitry Andric   case TargetOpcode::G_UMULO:
1834*0fca6ea1SDimitry Andric   case TargetOpcode::G_SADDSAT:
1835*0fca6ea1SDimitry Andric   case TargetOpcode::G_UADDSAT:
1836*0fca6ea1SDimitry Andric   case TargetOpcode::G_SSUBSAT:
1837*0fca6ea1SDimitry Andric   case TargetOpcode::G_USUBSAT:
1838*0fca6ea1SDimitry Andric     return false;
1839*0fca6ea1SDimitry Andric   case TargetOpcode::G_SSHLSAT:
1840*0fca6ea1SDimitry Andric   case TargetOpcode::G_USHLSAT:
1841*0fca6ea1SDimitry Andric     return includesPoison(Kind) &&
1842*0fca6ea1SDimitry Andric            !shiftAmountKnownInRange(RegDef->getOperand(2).getReg(), MRI);
1843*0fca6ea1SDimitry Andric   case TargetOpcode::G_INSERT_VECTOR_ELT: {
1844*0fca6ea1SDimitry Andric     GInsertVectorElement *Insert = cast<GInsertVectorElement>(RegDef);
1845*0fca6ea1SDimitry Andric     if (includesPoison(Kind)) {
1846*0fca6ea1SDimitry Andric       std::optional<ValueAndVReg> Index =
1847*0fca6ea1SDimitry Andric           getIConstantVRegValWithLookThrough(Insert->getIndexReg(), MRI);
1848*0fca6ea1SDimitry Andric       if (!Index)
1849*0fca6ea1SDimitry Andric         return true;
1850*0fca6ea1SDimitry Andric       LLT VecTy = MRI.getType(Insert->getVectorReg());
1851*0fca6ea1SDimitry Andric       return Index->Value.uge(VecTy.getElementCount().getKnownMinValue());
1852*0fca6ea1SDimitry Andric     }
1853*0fca6ea1SDimitry Andric     return false;
1854*0fca6ea1SDimitry Andric   }
1855*0fca6ea1SDimitry Andric   case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1856*0fca6ea1SDimitry Andric     GExtractVectorElement *Extract = cast<GExtractVectorElement>(RegDef);
1857*0fca6ea1SDimitry Andric     if (includesPoison(Kind)) {
1858*0fca6ea1SDimitry Andric       std::optional<ValueAndVReg> Index =
1859*0fca6ea1SDimitry Andric           getIConstantVRegValWithLookThrough(Extract->getIndexReg(), MRI);
1860*0fca6ea1SDimitry Andric       if (!Index)
1861*0fca6ea1SDimitry Andric         return true;
1862*0fca6ea1SDimitry Andric       LLT VecTy = MRI.getType(Extract->getVectorReg());
1863*0fca6ea1SDimitry Andric       return Index->Value.uge(VecTy.getElementCount().getKnownMinValue());
1864*0fca6ea1SDimitry Andric     }
1865*0fca6ea1SDimitry Andric     return false;
1866*0fca6ea1SDimitry Andric   }
1867*0fca6ea1SDimitry Andric   case TargetOpcode::G_SHUFFLE_VECTOR: {
1868*0fca6ea1SDimitry Andric     GShuffleVector *Shuffle = cast<GShuffleVector>(RegDef);
1869*0fca6ea1SDimitry Andric     ArrayRef<int> Mask = Shuffle->getMask();
1870*0fca6ea1SDimitry Andric     return includesPoison(Kind) && is_contained(Mask, -1);
1871*0fca6ea1SDimitry Andric   }
1872*0fca6ea1SDimitry Andric   case TargetOpcode::G_FNEG:
1873*0fca6ea1SDimitry Andric   case TargetOpcode::G_PHI:
1874*0fca6ea1SDimitry Andric   case TargetOpcode::G_SELECT:
1875*0fca6ea1SDimitry Andric   case TargetOpcode::G_UREM:
1876*0fca6ea1SDimitry Andric   case TargetOpcode::G_SREM:
1877*0fca6ea1SDimitry Andric   case TargetOpcode::G_FREEZE:
1878*0fca6ea1SDimitry Andric   case TargetOpcode::G_ICMP:
1879*0fca6ea1SDimitry Andric   case TargetOpcode::G_FCMP:
1880*0fca6ea1SDimitry Andric   case TargetOpcode::G_FADD:
1881*0fca6ea1SDimitry Andric   case TargetOpcode::G_FSUB:
1882*0fca6ea1SDimitry Andric   case TargetOpcode::G_FMUL:
1883*0fca6ea1SDimitry Andric   case TargetOpcode::G_FDIV:
1884*0fca6ea1SDimitry Andric   case TargetOpcode::G_FREM:
1885*0fca6ea1SDimitry Andric   case TargetOpcode::G_PTR_ADD:
1886*0fca6ea1SDimitry Andric     return false;
1887*0fca6ea1SDimitry Andric   default:
1888*0fca6ea1SDimitry Andric     return !isa<GCastOp>(RegDef) && !isa<GBinOp>(RegDef);
1889*0fca6ea1SDimitry Andric   }
1890*0fca6ea1SDimitry Andric }
1891*0fca6ea1SDimitry Andric 
1892*0fca6ea1SDimitry Andric static bool isGuaranteedNotToBeUndefOrPoison(Register Reg,
1893*0fca6ea1SDimitry Andric                                              const MachineRegisterInfo &MRI,
1894*0fca6ea1SDimitry Andric                                              unsigned Depth,
1895*0fca6ea1SDimitry Andric                                              UndefPoisonKind Kind) {
1896*0fca6ea1SDimitry Andric   if (Depth >= MaxAnalysisRecursionDepth)
1897*0fca6ea1SDimitry Andric     return false;
1898*0fca6ea1SDimitry Andric 
1899*0fca6ea1SDimitry Andric   MachineInstr *RegDef = MRI.getVRegDef(Reg);
1900*0fca6ea1SDimitry Andric 
1901*0fca6ea1SDimitry Andric   switch (RegDef->getOpcode()) {
1902*0fca6ea1SDimitry Andric   case TargetOpcode::G_FREEZE:
1903*0fca6ea1SDimitry Andric     return true;
1904*0fca6ea1SDimitry Andric   case TargetOpcode::G_IMPLICIT_DEF:
1905*0fca6ea1SDimitry Andric     return !includesUndef(Kind);
1906*0fca6ea1SDimitry Andric   case TargetOpcode::G_CONSTANT:
1907*0fca6ea1SDimitry Andric   case TargetOpcode::G_FCONSTANT:
1908*0fca6ea1SDimitry Andric     return true;
1909*0fca6ea1SDimitry Andric   case TargetOpcode::G_BUILD_VECTOR: {
1910*0fca6ea1SDimitry Andric     GBuildVector *BV = cast<GBuildVector>(RegDef);
1911*0fca6ea1SDimitry Andric     unsigned NumSources = BV->getNumSources();
1912*0fca6ea1SDimitry Andric     for (unsigned I = 0; I < NumSources; ++I)
1913*0fca6ea1SDimitry Andric       if (!::isGuaranteedNotToBeUndefOrPoison(BV->getSourceReg(I), MRI,
1914*0fca6ea1SDimitry Andric                                               Depth + 1, Kind))
1915*0fca6ea1SDimitry Andric         return false;
1916*0fca6ea1SDimitry Andric     return true;
1917*0fca6ea1SDimitry Andric   }
1918*0fca6ea1SDimitry Andric   case TargetOpcode::G_PHI: {
1919*0fca6ea1SDimitry Andric     GPhi *Phi = cast<GPhi>(RegDef);
1920*0fca6ea1SDimitry Andric     unsigned NumIncoming = Phi->getNumIncomingValues();
1921*0fca6ea1SDimitry Andric     for (unsigned I = 0; I < NumIncoming; ++I)
1922*0fca6ea1SDimitry Andric       if (!::isGuaranteedNotToBeUndefOrPoison(Phi->getIncomingValue(I), MRI,
1923*0fca6ea1SDimitry Andric                                               Depth + 1, Kind))
1924*0fca6ea1SDimitry Andric         return false;
1925*0fca6ea1SDimitry Andric     return true;
1926*0fca6ea1SDimitry Andric   }
1927*0fca6ea1SDimitry Andric   default: {
1928*0fca6ea1SDimitry Andric     auto MOCheck = [&](const MachineOperand &MO) {
1929*0fca6ea1SDimitry Andric       if (!MO.isReg())
1930*0fca6ea1SDimitry Andric         return true;
1931*0fca6ea1SDimitry Andric       return ::isGuaranteedNotToBeUndefOrPoison(MO.getReg(), MRI, Depth + 1,
1932*0fca6ea1SDimitry Andric                                                 Kind);
1933*0fca6ea1SDimitry Andric     };
1934*0fca6ea1SDimitry Andric     return !::canCreateUndefOrPoison(Reg, MRI,
1935*0fca6ea1SDimitry Andric                                      /*ConsiderFlagsAndMetadata=*/true, Kind) &&
1936*0fca6ea1SDimitry Andric            all_of(RegDef->uses(), MOCheck);
1937*0fca6ea1SDimitry Andric   }
1938*0fca6ea1SDimitry Andric   }
1939*0fca6ea1SDimitry Andric }
1940*0fca6ea1SDimitry Andric 
1941*0fca6ea1SDimitry Andric bool llvm::canCreateUndefOrPoison(Register Reg, const MachineRegisterInfo &MRI,
1942*0fca6ea1SDimitry Andric                                   bool ConsiderFlagsAndMetadata) {
1943*0fca6ea1SDimitry Andric   return ::canCreateUndefOrPoison(Reg, MRI, ConsiderFlagsAndMetadata,
1944*0fca6ea1SDimitry Andric                                   UndefPoisonKind::UndefOrPoison);
1945*0fca6ea1SDimitry Andric }
1946*0fca6ea1SDimitry Andric 
1947*0fca6ea1SDimitry Andric bool canCreatePoison(Register Reg, const MachineRegisterInfo &MRI,
1948*0fca6ea1SDimitry Andric                      bool ConsiderFlagsAndMetadata = true) {
1949*0fca6ea1SDimitry Andric   return ::canCreateUndefOrPoison(Reg, MRI, ConsiderFlagsAndMetadata,
1950*0fca6ea1SDimitry Andric                                   UndefPoisonKind::PoisonOnly);
1951*0fca6ea1SDimitry Andric }
1952*0fca6ea1SDimitry Andric 
1953*0fca6ea1SDimitry Andric bool llvm::isGuaranteedNotToBeUndefOrPoison(Register Reg,
1954*0fca6ea1SDimitry Andric                                             const MachineRegisterInfo &MRI,
1955*0fca6ea1SDimitry Andric                                             unsigned Depth) {
1956*0fca6ea1SDimitry Andric   return ::isGuaranteedNotToBeUndefOrPoison(Reg, MRI, Depth,
1957*0fca6ea1SDimitry Andric                                             UndefPoisonKind::UndefOrPoison);
1958*0fca6ea1SDimitry Andric }
1959*0fca6ea1SDimitry Andric 
1960*0fca6ea1SDimitry Andric bool llvm::isGuaranteedNotToBePoison(Register Reg,
1961*0fca6ea1SDimitry Andric                                      const MachineRegisterInfo &MRI,
1962*0fca6ea1SDimitry Andric                                      unsigned Depth) {
1963*0fca6ea1SDimitry Andric   return ::isGuaranteedNotToBeUndefOrPoison(Reg, MRI, Depth,
1964*0fca6ea1SDimitry Andric                                             UndefPoisonKind::PoisonOnly);
1965*0fca6ea1SDimitry Andric }
1966*0fca6ea1SDimitry Andric 
1967*0fca6ea1SDimitry Andric bool llvm::isGuaranteedNotToBeUndef(Register Reg,
1968*0fca6ea1SDimitry Andric                                     const MachineRegisterInfo &MRI,
1969*0fca6ea1SDimitry Andric                                     unsigned Depth) {
1970*0fca6ea1SDimitry Andric   return ::isGuaranteedNotToBeUndefOrPoison(Reg, MRI, Depth,
1971*0fca6ea1SDimitry Andric                                             UndefPoisonKind::UndefOnly);
1972*0fca6ea1SDimitry Andric }
1973*0fca6ea1SDimitry Andric 
1974*0fca6ea1SDimitry Andric Type *llvm::getTypeForLLT(LLT Ty, LLVMContext &C) {
1975*0fca6ea1SDimitry Andric   if (Ty.isVector())
1976*0fca6ea1SDimitry Andric     return VectorType::get(IntegerType::get(C, Ty.getScalarSizeInBits()),
1977*0fca6ea1SDimitry Andric                            Ty.getElementCount());
1978*0fca6ea1SDimitry Andric   return IntegerType::get(C, Ty.getSizeInBits());
1979*0fca6ea1SDimitry Andric }
1980