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