1b4e71185SQuentin Colombet //===- llvm/CodeGen/GlobalISel/Utils.cpp -------------------------*- C++ -*-==//
2b4e71185SQuentin Colombet //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b4e71185SQuentin Colombet //
7b4e71185SQuentin Colombet //===----------------------------------------------------------------------===//
8b4e71185SQuentin Colombet /// \file This file implements the utility functions used by the GlobalISel
9b4e71185SQuentin Colombet /// pipeline.
10b4e71185SQuentin Colombet //===----------------------------------------------------------------------===//
11b4e71185SQuentin Colombet 
12b4e71185SQuentin Colombet #include "llvm/CodeGen/GlobalISel/Utils.h"
1391fc4e09SAditya Nandakumar #include "llvm/ADT/APFloat.h"
14520ab710SAmara Emerson #include "llvm/ADT/APInt.h"
15520ab710SAmara Emerson #include "llvm/ADT/Optional.h"
16b91d9ec0SAditya Nandakumar #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
17a427f15dSMatt Arsenault #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
188bc71856SPetar Avramovic #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
19ed98c1b3Sserge-sans-paille #include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h"
205c5e6d95SMatt Arsenault #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
21b4e71185SQuentin Colombet #include "llvm/CodeGen/MachineInstr.h"
22b4e71185SQuentin Colombet #include "llvm/CodeGen/MachineInstrBuilder.h"
23ae9dadecSAhmed Bougacha #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
24b4e71185SQuentin Colombet #include "llvm/CodeGen/MachineRegisterInfo.h"
259a6e0afaSBenjamin Kramer #include "llvm/CodeGen/MachineSizeOpts.h"
26cb216076SMircea Trofin #include "llvm/CodeGen/RegisterBankInfo.h"
2790ad6835SMatthias Braun #include "llvm/CodeGen/StackProtector.h"
283f833edcSDavid Blaikie #include "llvm/CodeGen/TargetInstrInfo.h"
29898e42dbSSimon Pilgrim #include "llvm/CodeGen/TargetLowering.h"
30ae9dadecSAhmed Bougacha #include "llvm/CodeGen/TargetPassConfig.h"
31b3bde2eaSDavid Blaikie #include "llvm/CodeGen/TargetRegisterInfo.h"
3275ad9ccbSAditya Nandakumar #include "llvm/IR/Constants.h"
336e2a86edSPetar Avramovic #include "llvm/Target/TargetMachine.h"
3460ca2569Sserge-sans-paille #include "llvm/Transforms/Utils/SizeOpts.h"
35b4e71185SQuentin Colombet 
36b4e71185SQuentin Colombet #define DEBUG_TYPE "globalisel-utils"
37b4e71185SQuentin Colombet 
38b4e71185SQuentin Colombet using namespace llvm;
395c5e6d95SMatt Arsenault using namespace MIPatternMatch;
40b4e71185SQuentin Colombet 
constrainRegToClass(MachineRegisterInfo & MRI,const TargetInstrInfo & TII,const RegisterBankInfo & RBI,Register Reg,const TargetRegisterClass & RegClass)41eb7f74e3SMatt Arsenault Register llvm::constrainRegToClass(MachineRegisterInfo &MRI,
42a6e2cebfSDaniel Sanders                                    const TargetInstrInfo &TII,
43eb7f74e3SMatt Arsenault                                    const RegisterBankInfo &RBI, Register Reg,
44a6e2cebfSDaniel Sanders                                    const TargetRegisterClass &RegClass) {
45c596584fSMarcello Maggioni   if (!RBI.constrainGenericRegister(Reg, RegClass, MRI))
46c596584fSMarcello Maggioni     return MRI.createVirtualRegister(&RegClass);
47a6e2cebfSDaniel Sanders 
48a6e2cebfSDaniel Sanders   return Reg;
49a6e2cebfSDaniel Sanders }
50a6e2cebfSDaniel Sanders 
constrainOperandRegClass(const MachineFunction & MF,const TargetRegisterInfo & TRI,MachineRegisterInfo & MRI,const TargetInstrInfo & TII,const RegisterBankInfo & RBI,MachineInstr & InsertPt,const TargetRegisterClass & RegClass,MachineOperand & RegMO)51eb7f74e3SMatt Arsenault Register llvm::constrainOperandRegClass(
52b4e71185SQuentin Colombet     const MachineFunction &MF, const TargetRegisterInfo &TRI,
53b4e71185SQuentin Colombet     MachineRegisterInfo &MRI, const TargetInstrInfo &TII,
54c596584fSMarcello Maggioni     const RegisterBankInfo &RBI, MachineInstr &InsertPt,
552aeaaf84SGabriel Hjort Åkerlund     const TargetRegisterClass &RegClass, MachineOperand &RegMO) {
560c476111SDaniel Sanders   Register Reg = RegMO.getReg();
57c596584fSMarcello Maggioni   // Assume physical registers are properly constrained.
582bea69bfSDaniel Sanders   assert(Register::isVirtualRegister(Reg) && "PhysReg not implemented");
59c596584fSMarcello Maggioni 
6093977f37SDaniel Sanders   // Save the old register class to check whether
6193977f37SDaniel Sanders   // the change notifications will be required.
6293977f37SDaniel Sanders   // TODO: A better approach would be to pass
6393977f37SDaniel Sanders   // the observers to constrainRegToClass().
6493977f37SDaniel Sanders   auto *OldRegClass = MRI.getRegClassOrNull(Reg);
65eb7f74e3SMatt Arsenault   Register ConstrainedReg = constrainRegToClass(MRI, TII, RBI, Reg, RegClass);
66c596584fSMarcello Maggioni   // If we created a new virtual register because the class is not compatible
67c596584fSMarcello Maggioni   // then create a copy between the new and the old register.
68c596584fSMarcello Maggioni   if (ConstrainedReg != Reg) {
69c596584fSMarcello Maggioni     MachineBasicBlock::iterator InsertIt(&InsertPt);
70c596584fSMarcello Maggioni     MachineBasicBlock &MBB = *InsertPt.getParent();
71aa2d3b59SChristudasan Devadasan     // FIXME: The copy needs to have the classes constrained for its operands.
72aa2d3b59SChristudasan Devadasan     // Use operand's regbank to get the class for old register (Reg).
73c596584fSMarcello Maggioni     if (RegMO.isUse()) {
74c596584fSMarcello Maggioni       BuildMI(MBB, InsertIt, InsertPt.getDebugLoc(),
75c596584fSMarcello Maggioni               TII.get(TargetOpcode::COPY), ConstrainedReg)
76c596584fSMarcello Maggioni           .addReg(Reg);
77c596584fSMarcello Maggioni     } else {
78c596584fSMarcello Maggioni       assert(RegMO.isDef() && "Must be a definition");
79c596584fSMarcello Maggioni       BuildMI(MBB, std::next(InsertIt), InsertPt.getDebugLoc(),
80c596584fSMarcello Maggioni               TII.get(TargetOpcode::COPY), Reg)
81c596584fSMarcello Maggioni           .addReg(ConstrainedReg);
82c596584fSMarcello Maggioni     }
832aeaaf84SGabriel Hjort Åkerlund     if (GISelChangeObserver *Observer = MF.getObserver()) {
842aeaaf84SGabriel Hjort Åkerlund       Observer->changingInstr(*RegMO.getParent());
852aeaaf84SGabriel Hjort Åkerlund     }
862aeaaf84SGabriel Hjort Åkerlund     RegMO.setReg(ConstrainedReg);
872aeaaf84SGabriel Hjort Åkerlund     if (GISelChangeObserver *Observer = MF.getObserver()) {
882aeaaf84SGabriel Hjort Åkerlund       Observer->changedInstr(*RegMO.getParent());
892aeaaf84SGabriel Hjort Åkerlund     }
9093977f37SDaniel Sanders   } else if (OldRegClass != MRI.getRegClassOrNull(Reg)) {
91b91d9ec0SAditya Nandakumar     if (GISelChangeObserver *Observer = MF.getObserver()) {
92b91d9ec0SAditya Nandakumar       if (!RegMO.isDef()) {
93b91d9ec0SAditya Nandakumar         MachineInstr *RegDef = MRI.getVRegDef(Reg);
94b91d9ec0SAditya Nandakumar         Observer->changedInstr(*RegDef);
95b91d9ec0SAditya Nandakumar       }
96b91d9ec0SAditya Nandakumar       Observer->changingAllUsesOfReg(MRI, Reg);
97b91d9ec0SAditya Nandakumar       Observer->finishedChangingAllUsesOfReg();
98b91d9ec0SAditya Nandakumar     }
99c596584fSMarcello Maggioni   }
100c596584fSMarcello Maggioni   return ConstrainedReg;
101c596584fSMarcello Maggioni }
102c596584fSMarcello Maggioni 
constrainOperandRegClass(const MachineFunction & MF,const TargetRegisterInfo & TRI,MachineRegisterInfo & MRI,const TargetInstrInfo & TII,const RegisterBankInfo & RBI,MachineInstr & InsertPt,const MCInstrDesc & II,MachineOperand & RegMO,unsigned OpIdx)103eb7f74e3SMatt Arsenault Register llvm::constrainOperandRegClass(
104c596584fSMarcello Maggioni     const MachineFunction &MF, const TargetRegisterInfo &TRI,
105c596584fSMarcello Maggioni     MachineRegisterInfo &MRI, const TargetInstrInfo &TII,
106b4e71185SQuentin Colombet     const RegisterBankInfo &RBI, MachineInstr &InsertPt, const MCInstrDesc &II,
1072aeaaf84SGabriel Hjort Åkerlund     MachineOperand &RegMO, unsigned OpIdx) {
1080c476111SDaniel Sanders   Register Reg = RegMO.getReg();
109b4e71185SQuentin Colombet   // Assume physical registers are properly constrained.
1102bea69bfSDaniel Sanders   assert(Register::isVirtualRegister(Reg) && "PhysReg not implemented");
111b4e71185SQuentin Colombet 
112aa2d3b59SChristudasan Devadasan   const TargetRegisterClass *OpRC = TII.getRegClass(II, OpIdx, &TRI, MF);
11308464524SDaniel Sanders   // Some of the target independent instructions, like COPY, may not impose any
11459999053SAditya Nandakumar   // register class constraints on some of their operands: If it's a use, we can
11559999053SAditya Nandakumar   // skip constraining as the instruction defining the register would constrain
11659999053SAditya Nandakumar   // it.
117abc9871dSTom Stellard 
118aa2d3b59SChristudasan Devadasan   if (OpRC) {
119aa2d3b59SChristudasan Devadasan     // Obtain the RC from incoming regbank if it is a proper sub-class. Operands
120aa2d3b59SChristudasan Devadasan     // can have multiple regbanks for a superclass that combine different
121aa2d3b59SChristudasan Devadasan     // register types (E.g., AMDGPU's VGPR and AGPR). The regbank ambiguity
122aa2d3b59SChristudasan Devadasan     // resolved by targets during regbankselect should not be overridden.
123aa2d3b59SChristudasan Devadasan     if (const auto *SubRC = TRI.getCommonSubClass(
124aa2d3b59SChristudasan Devadasan             OpRC, TRI.getConstrainedRegClassForOperand(RegMO, MRI)))
125aa2d3b59SChristudasan Devadasan       OpRC = SubRC;
126abc9871dSTom Stellard 
127aa2d3b59SChristudasan Devadasan     OpRC = TRI.getAllocatableClass(OpRC);
128aa2d3b59SChristudasan Devadasan   }
129aa2d3b59SChristudasan Devadasan 
130aa2d3b59SChristudasan Devadasan   if (!OpRC) {
13159999053SAditya Nandakumar     assert((!isTargetSpecificOpcode(II.getOpcode()) || RegMO.isUse()) &&
13259999053SAditya Nandakumar            "Register class constraint is required unless either the "
13359999053SAditya Nandakumar            "instruction is target independent or the operand is a use");
13408464524SDaniel Sanders     // FIXME: Just bailing out like this here could be not enough, unless we
13508464524SDaniel Sanders     // expect the users of this function to do the right thing for PHIs and
13608464524SDaniel Sanders     // COPY:
13708464524SDaniel Sanders     //   v1 = COPY v0
13808464524SDaniel Sanders     //   v2 = COPY v1
13908464524SDaniel Sanders     // v1 here may end up not being constrained at all. Please notice that to
14008464524SDaniel Sanders     // reproduce the issue we likely need a destination pattern of a selection
14108464524SDaniel Sanders     // rule producing such extra copies, not just an input GMIR with them as
14208464524SDaniel Sanders     // every existing target using selectImpl handles copies before calling it
14308464524SDaniel Sanders     // and they never reach this function.
14408464524SDaniel Sanders     return Reg;
14508464524SDaniel Sanders   }
146aa2d3b59SChristudasan Devadasan   return constrainOperandRegClass(MF, TRI, MRI, TII, RBI, InsertPt, *OpRC,
1473bb0ff83SMatt Arsenault                                   RegMO);
148b4e71185SQuentin Colombet }
149ae9dadecSAhmed Bougacha 
constrainSelectedInstRegOperands(MachineInstr & I,const TargetInstrInfo & TII,const TargetRegisterInfo & TRI,const RegisterBankInfo & RBI)15018b3f9d3SAditya Nandakumar bool llvm::constrainSelectedInstRegOperands(MachineInstr &I,
15118b3f9d3SAditya Nandakumar                                             const TargetInstrInfo &TII,
15218b3f9d3SAditya Nandakumar                                             const TargetRegisterInfo &TRI,
15318b3f9d3SAditya Nandakumar                                             const RegisterBankInfo &RBI) {
15408464524SDaniel Sanders   assert(!isPreISelGenericOpcode(I.getOpcode()) &&
15508464524SDaniel Sanders          "A selected instruction is expected");
15618b3f9d3SAditya Nandakumar   MachineBasicBlock &MBB = *I.getParent();
15718b3f9d3SAditya Nandakumar   MachineFunction &MF = *MBB.getParent();
15818b3f9d3SAditya Nandakumar   MachineRegisterInfo &MRI = MF.getRegInfo();
15918b3f9d3SAditya Nandakumar 
16018b3f9d3SAditya Nandakumar   for (unsigned OpI = 0, OpE = I.getNumExplicitOperands(); OpI != OpE; ++OpI) {
16118b3f9d3SAditya Nandakumar     MachineOperand &MO = I.getOperand(OpI);
16218b3f9d3SAditya Nandakumar 
16318b3f9d3SAditya Nandakumar     // There's nothing to be done on non-register operands.
16418b3f9d3SAditya Nandakumar     if (!MO.isReg())
16518b3f9d3SAditya Nandakumar       continue;
16618b3f9d3SAditya Nandakumar 
167d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Converting operand: " << MO << '\n');
16818b3f9d3SAditya Nandakumar     assert(MO.isReg() && "Unsupported non-reg operand");
16918b3f9d3SAditya Nandakumar 
1700c476111SDaniel Sanders     Register Reg = MO.getReg();
17118b3f9d3SAditya Nandakumar     // Physical registers don't need to be constrained.
1722bea69bfSDaniel Sanders     if (Register::isPhysicalRegister(Reg))
17318b3f9d3SAditya Nandakumar       continue;
17418b3f9d3SAditya Nandakumar 
17518b3f9d3SAditya Nandakumar     // Register operands with a value of 0 (e.g. predicate operands) don't need
17618b3f9d3SAditya Nandakumar     // to be constrained.
17718b3f9d3SAditya Nandakumar     if (Reg == 0)
17818b3f9d3SAditya Nandakumar       continue;
17918b3f9d3SAditya Nandakumar 
18018b3f9d3SAditya Nandakumar     // If the operand is a vreg, we should constrain its regclass, and only
18118b3f9d3SAditya Nandakumar     // insert COPYs if that's impossible.
18218b3f9d3SAditya Nandakumar     // constrainOperandRegClass does that for us.
1832aeaaf84SGabriel Hjort Åkerlund     constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, I.getDesc(), MO, OpI);
18418b3f9d3SAditya Nandakumar 
18518b3f9d3SAditya Nandakumar     // Tie uses to defs as indicated in MCInstrDesc if this hasn't already been
18618b3f9d3SAditya Nandakumar     // done.
18718b3f9d3SAditya Nandakumar     if (MO.isUse()) {
18818b3f9d3SAditya Nandakumar       int DefIdx = I.getDesc().getOperandConstraint(OpI, MCOI::TIED_TO);
18918b3f9d3SAditya Nandakumar       if (DefIdx != -1 && !I.isRegTiedToUseOperand(DefIdx))
19018b3f9d3SAditya Nandakumar         I.tieOperands(DefIdx, OpI);
19118b3f9d3SAditya Nandakumar     }
19218b3f9d3SAditya Nandakumar   }
19318b3f9d3SAditya Nandakumar   return true;
19418b3f9d3SAditya Nandakumar }
19518b3f9d3SAditya Nandakumar 
canReplaceReg(Register DstReg,Register SrcReg,MachineRegisterInfo & MRI)196187686a2SVolkan Keles bool llvm::canReplaceReg(Register DstReg, Register SrcReg,
197187686a2SVolkan Keles                          MachineRegisterInfo &MRI) {
198187686a2SVolkan Keles   // Give up if either DstReg or SrcReg  is a physical register.
199187686a2SVolkan Keles   if (DstReg.isPhysical() || SrcReg.isPhysical())
200187686a2SVolkan Keles     return false;
201187686a2SVolkan Keles   // Give up if the types don't match.
202187686a2SVolkan Keles   if (MRI.getType(DstReg) != MRI.getType(SrcReg))
203187686a2SVolkan Keles     return false;
204187686a2SVolkan Keles   // Replace if either DstReg has no constraints or the register
205187686a2SVolkan Keles   // constraints match.
206187686a2SVolkan Keles   return !MRI.getRegClassOrRegBank(DstReg) ||
207187686a2SVolkan Keles          MRI.getRegClassOrRegBank(DstReg) == MRI.getRegClassOrRegBank(SrcReg);
208187686a2SVolkan Keles }
209187686a2SVolkan Keles 
isTriviallyDead(const MachineInstr & MI,const MachineRegisterInfo & MRI)21047debaeeSVolkan Keles bool llvm::isTriviallyDead(const MachineInstr &MI,
21147debaeeSVolkan Keles                            const MachineRegisterInfo &MRI) {
2123e16e215SMatt Arsenault   // FIXME: This logical is mostly duplicated with
2133e16e215SMatt Arsenault   // DeadMachineInstructionElim::isDead. Why is LOCAL_ESCAPE not considered in
2143e16e215SMatt Arsenault   // MachineInstr::isLabel?
2153e16e215SMatt Arsenault 
2163e16e215SMatt Arsenault   // Don't delete frame allocation labels.
2173e16e215SMatt Arsenault   if (MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE)
2183e16e215SMatt Arsenault     return false;
21928963d89SAmara Emerson   // LIFETIME markers should be preserved even if they seem dead.
22028963d89SAmara Emerson   if (MI.getOpcode() == TargetOpcode::LIFETIME_START ||
22128963d89SAmara Emerson       MI.getOpcode() == TargetOpcode::LIFETIME_END)
22228963d89SAmara Emerson     return false;
2233e16e215SMatt Arsenault 
22447debaeeSVolkan Keles   // If we can move an instruction, we can remove it.  Otherwise, it has
22547debaeeSVolkan Keles   // a side-effect of some sort.
22647debaeeSVolkan Keles   bool SawStore = false;
227cd04e366SAditya Nandakumar   if (!MI.isSafeToMove(/*AA=*/nullptr, SawStore) && !MI.isPHI())
22847debaeeSVolkan Keles     return false;
22947debaeeSVolkan Keles 
23047debaeeSVolkan Keles   // Instructions without side-effects are dead iff they only define dead vregs.
231*9e6d1f4bSKazu Hirata   for (const auto &MO : MI.operands()) {
23247debaeeSVolkan Keles     if (!MO.isReg() || !MO.isDef())
23347debaeeSVolkan Keles       continue;
23447debaeeSVolkan Keles 
2350c476111SDaniel Sanders     Register Reg = MO.getReg();
2362bea69bfSDaniel Sanders     if (Register::isPhysicalRegister(Reg) || !MRI.use_nodbg_empty(Reg))
23747debaeeSVolkan Keles       return false;
23847debaeeSVolkan Keles   }
23947debaeeSVolkan Keles   return true;
24047debaeeSVolkan Keles }
24147debaeeSVolkan Keles 
reportGISelDiagnostic(DiagnosticSeverity Severity,MachineFunction & MF,const TargetPassConfig & TPC,MachineOptimizationRemarkEmitter & MORE,MachineOptimizationRemarkMissed & R)2427c6ca18fSDaniel Sanders static void reportGISelDiagnostic(DiagnosticSeverity Severity,
2437c6ca18fSDaniel Sanders                                   MachineFunction &MF,
2447c6ca18fSDaniel Sanders                                   const TargetPassConfig &TPC,
2457c6ca18fSDaniel Sanders                                   MachineOptimizationRemarkEmitter &MORE,
2467c6ca18fSDaniel Sanders                                   MachineOptimizationRemarkMissed &R) {
2477c6ca18fSDaniel Sanders   bool IsFatal = Severity == DS_Error &&
2487c6ca18fSDaniel Sanders                  TPC.isGlobalISelAbortEnabled();
2497c6ca18fSDaniel Sanders   // Print the function name explicitly if we don't have a debug location (which
2507c6ca18fSDaniel Sanders   // makes the diagnostic less useful) or if we're going to emit a raw error.
2517c6ca18fSDaniel Sanders   if (!R.getLocation().isValid() || IsFatal)
2527c6ca18fSDaniel Sanders     R << (" (in function: " + MF.getName() + ")").str();
2537c6ca18fSDaniel Sanders 
2547c6ca18fSDaniel Sanders   if (IsFatal)
25521661607SSimon Pilgrim     report_fatal_error(Twine(R.getMsg()));
2567c6ca18fSDaniel Sanders   else
2577c6ca18fSDaniel Sanders     MORE.emit(R);
2587c6ca18fSDaniel Sanders }
2597c6ca18fSDaniel Sanders 
reportGISelWarning(MachineFunction & MF,const TargetPassConfig & TPC,MachineOptimizationRemarkEmitter & MORE,MachineOptimizationRemarkMissed & R)2607c6ca18fSDaniel Sanders void llvm::reportGISelWarning(MachineFunction &MF, const TargetPassConfig &TPC,
2617c6ca18fSDaniel Sanders                               MachineOptimizationRemarkEmitter &MORE,
2627c6ca18fSDaniel Sanders                               MachineOptimizationRemarkMissed &R) {
2637c6ca18fSDaniel Sanders   reportGISelDiagnostic(DS_Warning, MF, TPC, MORE, R);
2647c6ca18fSDaniel Sanders }
2657c6ca18fSDaniel Sanders 
reportGISelFailure(MachineFunction & MF,const TargetPassConfig & TPC,MachineOptimizationRemarkEmitter & MORE,MachineOptimizationRemarkMissed & R)266ae9dadecSAhmed Bougacha void llvm::reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
267ae9dadecSAhmed Bougacha                               MachineOptimizationRemarkEmitter &MORE,
268ae9dadecSAhmed Bougacha                               MachineOptimizationRemarkMissed &R) {
269ae9dadecSAhmed Bougacha   MF.getProperties().set(MachineFunctionProperties::Property::FailedISel);
2707c6ca18fSDaniel Sanders   reportGISelDiagnostic(DS_Error, MF, TPC, MORE, R);
271ae9dadecSAhmed Bougacha }
272ae9dadecSAhmed Bougacha 
reportGISelFailure(MachineFunction & MF,const TargetPassConfig & TPC,MachineOptimizationRemarkEmitter & MORE,const char * PassName,StringRef Msg,const MachineInstr & MI)273ae9dadecSAhmed Bougacha void llvm::reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
274ae9dadecSAhmed Bougacha                               MachineOptimizationRemarkEmitter &MORE,
275ae9dadecSAhmed Bougacha                               const char *PassName, StringRef Msg,
276ae9dadecSAhmed Bougacha                               const MachineInstr &MI) {
277ae9dadecSAhmed Bougacha   MachineOptimizationRemarkMissed R(PassName, "GISelFailure: ",
278ae9dadecSAhmed Bougacha                                     MI.getDebugLoc(), MI.getParent());
279d630a92bSAhmed Bougacha   R << Msg;
280d630a92bSAhmed Bougacha   // Printing MI is expensive;  only do it if expensive remarks are enabled.
281abf75940SAditya Nandakumar   if (TPC.isGlobalISelAbortEnabled() || MORE.allowExtraAnalysis(PassName))
282d630a92bSAhmed Bougacha     R << ": " << ore::MNV("Inst", MI);
283ae9dadecSAhmed Bougacha   reportGISelFailure(MF, TPC, MORE, R);
284ae9dadecSAhmed Bougacha }
28575ad9ccbSAditya Nandakumar 
getIConstantVRegVal(Register VReg,const MachineRegisterInfo & MRI)286d477a7c2SPetar Avramovic Optional<APInt> llvm::getIConstantVRegVal(Register VReg,
28775ad9ccbSAditya Nandakumar                                           const MachineRegisterInfo &MRI) {
288d477a7c2SPetar Avramovic   Optional<ValueAndVReg> ValAndVReg = getIConstantVRegValWithLookThrough(
289d477a7c2SPetar Avramovic       VReg, MRI, /*LookThroughInstrs*/ false);
290e77e5f44SQuentin Colombet   assert((!ValAndVReg || ValAndVReg->VReg == VReg) &&
291e77e5f44SQuentin Colombet          "Value found while looking through instrs");
292e77e5f44SQuentin Colombet   if (!ValAndVReg)
293e77e5f44SQuentin Colombet     return None;
294e77e5f44SQuentin Colombet   return ValAndVReg->Value;
295e77e5f44SQuentin Colombet }
296e77e5f44SQuentin Colombet 
297d477a7c2SPetar Avramovic Optional<int64_t>
getIConstantVRegSExtVal(Register VReg,const MachineRegisterInfo & MRI)298d477a7c2SPetar Avramovic llvm::getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI) {
299d477a7c2SPetar Avramovic   Optional<APInt> Val = getIConstantVRegVal(VReg, MRI);
300581d13f8SMatt Arsenault   if (Val && Val->getBitWidth() <= 64)
301581d13f8SMatt Arsenault     return Val->getSExtValue();
302581d13f8SMatt Arsenault   return None;
303581d13f8SMatt Arsenault }
304581d13f8SMatt Arsenault 
305d477a7c2SPetar Avramovic namespace {
306d477a7c2SPetar Avramovic 
307d477a7c2SPetar Avramovic typedef std::function<bool(const MachineInstr *)> IsOpcodeFn;
308d477a7c2SPetar Avramovic typedef std::function<Optional<APInt>(const MachineInstr *MI)> GetAPCstFn;
309d477a7c2SPetar Avramovic 
getConstantVRegValWithLookThrough(Register VReg,const MachineRegisterInfo & MRI,IsOpcodeFn IsConstantOpcode,GetAPCstFn getAPCstValue,bool LookThroughInstrs=true,bool LookThroughAnyExt=false)310d477a7c2SPetar Avramovic Optional<ValueAndVReg> getConstantVRegValWithLookThrough(
311d477a7c2SPetar Avramovic     Register VReg, const MachineRegisterInfo &MRI, IsOpcodeFn IsConstantOpcode,
312d477a7c2SPetar Avramovic     GetAPCstFn getAPCstValue, bool LookThroughInstrs = true,
313d477a7c2SPetar Avramovic     bool LookThroughAnyExt = false) {
314e77e5f44SQuentin Colombet   SmallVector<std::pair<unsigned, unsigned>, 4> SeenOpcodes;
315e77e5f44SQuentin Colombet   MachineInstr *MI;
316d477a7c2SPetar Avramovic 
317d477a7c2SPetar Avramovic   while ((MI = MRI.getVRegDef(VReg)) && !IsConstantOpcode(MI) &&
3180112123eSMarcello Maggioni          LookThroughInstrs) {
319e77e5f44SQuentin Colombet     switch (MI->getOpcode()) {
320a6a72dfdSMirko Brkusanin     case TargetOpcode::G_ANYEXT:
321a6a72dfdSMirko Brkusanin       if (!LookThroughAnyExt)
322a6a72dfdSMirko Brkusanin         return None;
323a6a72dfdSMirko Brkusanin       LLVM_FALLTHROUGH;
324e77e5f44SQuentin Colombet     case TargetOpcode::G_TRUNC:
325e77e5f44SQuentin Colombet     case TargetOpcode::G_SEXT:
326e77e5f44SQuentin Colombet     case TargetOpcode::G_ZEXT:
327e77e5f44SQuentin Colombet       SeenOpcodes.push_back(std::make_pair(
328e77e5f44SQuentin Colombet           MI->getOpcode(),
329e77e5f44SQuentin Colombet           MRI.getType(MI->getOperand(0).getReg()).getSizeInBits()));
330e77e5f44SQuentin Colombet       VReg = MI->getOperand(1).getReg();
331e77e5f44SQuentin Colombet       break;
332e77e5f44SQuentin Colombet     case TargetOpcode::COPY:
333e77e5f44SQuentin Colombet       VReg = MI->getOperand(1).getReg();
3342bea69bfSDaniel Sanders       if (Register::isPhysicalRegister(VReg))
335e77e5f44SQuentin Colombet         return None;
336e77e5f44SQuentin Colombet       break;
3377a4d2df0SAmara Emerson     case TargetOpcode::G_INTTOPTR:
3387a4d2df0SAmara Emerson       VReg = MI->getOperand(1).getReg();
3397a4d2df0SAmara Emerson       break;
340e77e5f44SQuentin Colombet     default:
341e77e5f44SQuentin Colombet       return None;
342e77e5f44SQuentin Colombet     }
343e77e5f44SQuentin Colombet   }
344d477a7c2SPetar Avramovic   if (!MI || !IsConstantOpcode(MI))
34575ad9ccbSAditya Nandakumar     return None;
34675ad9ccbSAditya Nandakumar 
347d477a7c2SPetar Avramovic   Optional<APInt> MaybeVal = getAPCstValue(MI);
3480112123eSMarcello Maggioni   if (!MaybeVal)
3490112123eSMarcello Maggioni     return None;
3500112123eSMarcello Maggioni   APInt &Val = *MaybeVal;
351e77e5f44SQuentin Colombet   while (!SeenOpcodes.empty()) {
352e77e5f44SQuentin Colombet     std::pair<unsigned, unsigned> OpcodeAndSize = SeenOpcodes.pop_back_val();
353e77e5f44SQuentin Colombet     switch (OpcodeAndSize.first) {
354e77e5f44SQuentin Colombet     case TargetOpcode::G_TRUNC:
355e77e5f44SQuentin Colombet       Val = Val.trunc(OpcodeAndSize.second);
356e77e5f44SQuentin Colombet       break;
357a6a72dfdSMirko Brkusanin     case TargetOpcode::G_ANYEXT:
358e77e5f44SQuentin Colombet     case TargetOpcode::G_SEXT:
359e77e5f44SQuentin Colombet       Val = Val.sext(OpcodeAndSize.second);
360e77e5f44SQuentin Colombet       break;
361e77e5f44SQuentin Colombet     case TargetOpcode::G_ZEXT:
362e77e5f44SQuentin Colombet       Val = Val.zext(OpcodeAndSize.second);
363e77e5f44SQuentin Colombet       break;
364e77e5f44SQuentin Colombet     }
365e77e5f44SQuentin Colombet   }
36675ad9ccbSAditya Nandakumar 
367581d13f8SMatt Arsenault   return ValueAndVReg{Val, VReg};
36875ad9ccbSAditya Nandakumar }
3692a735421SAditya Nandakumar 
isIConstant(const MachineInstr * MI)370d477a7c2SPetar Avramovic bool isIConstant(const MachineInstr *MI) {
371d477a7c2SPetar Avramovic   if (!MI)
372d477a7c2SPetar Avramovic     return false;
373d477a7c2SPetar Avramovic   return MI->getOpcode() == TargetOpcode::G_CONSTANT;
374d477a7c2SPetar Avramovic }
375d477a7c2SPetar Avramovic 
isFConstant(const MachineInstr * MI)376d477a7c2SPetar Avramovic bool isFConstant(const MachineInstr *MI) {
377d477a7c2SPetar Avramovic   if (!MI)
378d477a7c2SPetar Avramovic     return false;
379d477a7c2SPetar Avramovic   return MI->getOpcode() == TargetOpcode::G_FCONSTANT;
380d477a7c2SPetar Avramovic }
381d477a7c2SPetar Avramovic 
isAnyConstant(const MachineInstr * MI)382d477a7c2SPetar Avramovic bool isAnyConstant(const MachineInstr *MI) {
383d477a7c2SPetar Avramovic   if (!MI)
384d477a7c2SPetar Avramovic     return false;
385d477a7c2SPetar Avramovic   unsigned Opc = MI->getOpcode();
386d477a7c2SPetar Avramovic   return Opc == TargetOpcode::G_CONSTANT || Opc == TargetOpcode::G_FCONSTANT;
387d477a7c2SPetar Avramovic }
388d477a7c2SPetar Avramovic 
getCImmAsAPInt(const MachineInstr * MI)389d477a7c2SPetar Avramovic Optional<APInt> getCImmAsAPInt(const MachineInstr *MI) {
390d477a7c2SPetar Avramovic   const MachineOperand &CstVal = MI->getOperand(1);
391d477a7c2SPetar Avramovic   if (CstVal.isCImm())
392d477a7c2SPetar Avramovic     return CstVal.getCImm()->getValue();
393d477a7c2SPetar Avramovic   return None;
394d477a7c2SPetar Avramovic }
395d477a7c2SPetar Avramovic 
getCImmOrFPImmAsAPInt(const MachineInstr * MI)396d477a7c2SPetar Avramovic Optional<APInt> getCImmOrFPImmAsAPInt(const MachineInstr *MI) {
397d477a7c2SPetar Avramovic   const MachineOperand &CstVal = MI->getOperand(1);
398d477a7c2SPetar Avramovic   if (CstVal.isCImm())
399d477a7c2SPetar Avramovic     return CstVal.getCImm()->getValue();
400d477a7c2SPetar Avramovic   if (CstVal.isFPImm())
401d477a7c2SPetar Avramovic     return CstVal.getFPImm()->getValueAPF().bitcastToAPInt();
402d477a7c2SPetar Avramovic   return None;
403d477a7c2SPetar Avramovic }
404d477a7c2SPetar Avramovic 
405d477a7c2SPetar Avramovic } // end anonymous namespace
406d477a7c2SPetar Avramovic 
getIConstantVRegValWithLookThrough(Register VReg,const MachineRegisterInfo & MRI,bool LookThroughInstrs)407d477a7c2SPetar Avramovic Optional<ValueAndVReg> llvm::getIConstantVRegValWithLookThrough(
408d477a7c2SPetar Avramovic     Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs) {
409d477a7c2SPetar Avramovic   return getConstantVRegValWithLookThrough(VReg, MRI, isIConstant,
410d477a7c2SPetar Avramovic                                            getCImmAsAPInt, LookThroughInstrs);
411d477a7c2SPetar Avramovic }
412d477a7c2SPetar Avramovic 
getAnyConstantVRegValWithLookThrough(Register VReg,const MachineRegisterInfo & MRI,bool LookThroughInstrs,bool LookThroughAnyExt)413d477a7c2SPetar Avramovic Optional<ValueAndVReg> llvm::getAnyConstantVRegValWithLookThrough(
414d477a7c2SPetar Avramovic     Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs,
415d477a7c2SPetar Avramovic     bool LookThroughAnyExt) {
416d477a7c2SPetar Avramovic   return getConstantVRegValWithLookThrough(
417d477a7c2SPetar Avramovic       VReg, MRI, isAnyConstant, getCImmOrFPImmAsAPInt, LookThroughInstrs,
418d477a7c2SPetar Avramovic       LookThroughAnyExt);
419d477a7c2SPetar Avramovic }
420d477a7c2SPetar Avramovic 
getFConstantVRegValWithLookThrough(Register VReg,const MachineRegisterInfo & MRI,bool LookThroughInstrs)421d477a7c2SPetar Avramovic Optional<FPValueAndVReg> llvm::getFConstantVRegValWithLookThrough(
422d477a7c2SPetar Avramovic     Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs) {
423d477a7c2SPetar Avramovic   auto Reg = getConstantVRegValWithLookThrough(
424d477a7c2SPetar Avramovic       VReg, MRI, isFConstant, getCImmOrFPImmAsAPInt, LookThroughInstrs);
425d477a7c2SPetar Avramovic   if (!Reg)
426d477a7c2SPetar Avramovic     return None;
427d477a7c2SPetar Avramovic   return FPValueAndVReg{getConstantFPVRegVal(Reg->VReg, MRI)->getValueAPF(),
428d477a7c2SPetar Avramovic                         Reg->VReg};
4290713c82bSPetar Avramovic }
4300713c82bSPetar Avramovic 
43104a288f0SMatt Arsenault const ConstantFP *
getConstantFPVRegVal(Register VReg,const MachineRegisterInfo & MRI)432ce963363SShu-Chun Weng llvm::getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI) {
4332a735421SAditya Nandakumar   MachineInstr *MI = MRI.getVRegDef(VReg);
4342a735421SAditya Nandakumar   if (TargetOpcode::G_FCONSTANT != MI->getOpcode())
4352a735421SAditya Nandakumar     return nullptr;
4362a735421SAditya Nandakumar   return MI->getOperand(1).getFPImm();
4372a735421SAditya Nandakumar }
438954eea07SAditya Nandakumar 
439c67e1a98SMatt Arsenault Optional<DefinitionAndSourceRegister>
getDefSrcRegIgnoringCopies(Register Reg,const MachineRegisterInfo & MRI)440c67e1a98SMatt Arsenault llvm::getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI) {
441ce963363SShu-Chun Weng   Register DefSrcReg = Reg;
442954eea07SAditya Nandakumar   auto *DefMI = MRI.getVRegDef(Reg);
443954eea07SAditya Nandakumar   auto DstTy = MRI.getType(DefMI->getOperand(0).getReg());
444954eea07SAditya Nandakumar   if (!DstTy.isValid())
445ce963363SShu-Chun Weng     return None;
446daffab19SJessica Paquette   unsigned Opc = DefMI->getOpcode();
447daffab19SJessica Paquette   while (Opc == TargetOpcode::COPY || isPreISelGenericOptimizationHint(Opc)) {
4480c476111SDaniel Sanders     Register SrcReg = DefMI->getOperand(1).getReg();
449954eea07SAditya Nandakumar     auto SrcTy = MRI.getType(SrcReg);
450924f31bcSMatt Arsenault     if (!SrcTy.isValid())
451954eea07SAditya Nandakumar       break;
452954eea07SAditya Nandakumar     DefMI = MRI.getVRegDef(SrcReg);
453ce963363SShu-Chun Weng     DefSrcReg = SrcReg;
454daffab19SJessica Paquette     Opc = DefMI->getOpcode();
455954eea07SAditya Nandakumar   }
456ce963363SShu-Chun Weng   return DefinitionAndSourceRegister{DefMI, DefSrcReg};
457ce963363SShu-Chun Weng }
458ce963363SShu-Chun Weng 
getDefIgnoringCopies(Register Reg,const MachineRegisterInfo & MRI)45904a288f0SMatt Arsenault MachineInstr *llvm::getDefIgnoringCopies(Register Reg,
460ce963363SShu-Chun Weng                                          const MachineRegisterInfo &MRI) {
461ce963363SShu-Chun Weng   Optional<DefinitionAndSourceRegister> DefSrcReg =
462ce963363SShu-Chun Weng       getDefSrcRegIgnoringCopies(Reg, MRI);
463ce963363SShu-Chun Weng   return DefSrcReg ? DefSrcReg->MI : nullptr;
464ce963363SShu-Chun Weng }
465ce963363SShu-Chun Weng 
getSrcRegIgnoringCopies(Register Reg,const MachineRegisterInfo & MRI)466ce963363SShu-Chun Weng Register llvm::getSrcRegIgnoringCopies(Register Reg,
467ce963363SShu-Chun Weng                                        const MachineRegisterInfo &MRI) {
468ce963363SShu-Chun Weng   Optional<DefinitionAndSourceRegister> DefSrcReg =
469ce963363SShu-Chun Weng       getDefSrcRegIgnoringCopies(Reg, MRI);
470ce963363SShu-Chun Weng   return DefSrcReg ? DefSrcReg->Reg : Register();
47114a44951SMatt Arsenault }
47214a44951SMatt Arsenault 
getOpcodeDef(unsigned Opcode,Register Reg,const MachineRegisterInfo & MRI)47304a288f0SMatt Arsenault MachineInstr *llvm::getOpcodeDef(unsigned Opcode, Register Reg,
47414a44951SMatt Arsenault                                  const MachineRegisterInfo &MRI) {
47514a44951SMatt Arsenault   MachineInstr *DefMI = getDefIgnoringCopies(Reg, MRI);
47614a44951SMatt Arsenault   return DefMI && DefMI->getOpcode() == Opcode ? DefMI : nullptr;
477954eea07SAditya Nandakumar }
47891fc4e09SAditya Nandakumar 
getAPFloatFromSize(double Val,unsigned Size)47991fc4e09SAditya Nandakumar APFloat llvm::getAPFloatFromSize(double Val, unsigned Size) {
48091fc4e09SAditya Nandakumar   if (Size == 32)
48191fc4e09SAditya Nandakumar     return APFloat(float(Val));
48291fc4e09SAditya Nandakumar   if (Size == 64)
48391fc4e09SAditya Nandakumar     return APFloat(Val);
48491fc4e09SAditya Nandakumar   if (Size != 16)
48591fc4e09SAditya Nandakumar     llvm_unreachable("Unsupported FPConstant size");
48691fc4e09SAditya Nandakumar   bool Ignored;
48791fc4e09SAditya Nandakumar   APFloat APF(Val);
48891fc4e09SAditya Nandakumar   APF.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored);
48991fc4e09SAditya Nandakumar   return APF;
49091fc4e09SAditya Nandakumar }
49190ad6835SMatthias Braun 
ConstantFoldBinOp(unsigned Opcode,const Register Op1,const Register Op2,const MachineRegisterInfo & MRI)4925f7e38d8SMatt Arsenault Optional<APInt> llvm::ConstantFoldBinOp(unsigned Opcode, const Register Op1,
4935f7e38d8SMatt Arsenault                                         const Register Op2,
494500e3eadSAditya Nandakumar                                         const MachineRegisterInfo &MRI) {
495d477a7c2SPetar Avramovic   auto MaybeOp2Cst = getAnyConstantVRegValWithLookThrough(Op2, MRI, false);
4968a3340d2SMatt Arsenault   if (!MaybeOp2Cst)
4978a3340d2SMatt Arsenault     return None;
4988a3340d2SMatt Arsenault 
499d477a7c2SPetar Avramovic   auto MaybeOp1Cst = getAnyConstantVRegValWithLookThrough(Op1, MRI, false);
5008a3340d2SMatt Arsenault   if (!MaybeOp1Cst)
5018a3340d2SMatt Arsenault     return None;
5028a3340d2SMatt Arsenault 
503d477a7c2SPetar Avramovic   const APInt &C1 = MaybeOp1Cst->Value;
504d477a7c2SPetar Avramovic   const APInt &C2 = MaybeOp2Cst->Value;
505500e3eadSAditya Nandakumar   switch (Opcode) {
506500e3eadSAditya Nandakumar   default:
507500e3eadSAditya Nandakumar     break;
508500e3eadSAditya Nandakumar   case TargetOpcode::G_ADD:
5095af0f097SMatt Arsenault   case TargetOpcode::G_PTR_ADD:
510500e3eadSAditya Nandakumar     return C1 + C2;
511500e3eadSAditya Nandakumar   case TargetOpcode::G_AND:
512500e3eadSAditya Nandakumar     return C1 & C2;
513500e3eadSAditya Nandakumar   case TargetOpcode::G_ASHR:
514500e3eadSAditya Nandakumar     return C1.ashr(C2);
515500e3eadSAditya Nandakumar   case TargetOpcode::G_LSHR:
516500e3eadSAditya Nandakumar     return C1.lshr(C2);
517500e3eadSAditya Nandakumar   case TargetOpcode::G_MUL:
518500e3eadSAditya Nandakumar     return C1 * C2;
519500e3eadSAditya Nandakumar   case TargetOpcode::G_OR:
520500e3eadSAditya Nandakumar     return C1 | C2;
521500e3eadSAditya Nandakumar   case TargetOpcode::G_SHL:
522500e3eadSAditya Nandakumar     return C1 << C2;
523500e3eadSAditya Nandakumar   case TargetOpcode::G_SUB:
524500e3eadSAditya Nandakumar     return C1 - C2;
525500e3eadSAditya Nandakumar   case TargetOpcode::G_XOR:
526500e3eadSAditya Nandakumar     return C1 ^ C2;
527500e3eadSAditya Nandakumar   case TargetOpcode::G_UDIV:
528500e3eadSAditya Nandakumar     if (!C2.getBoolValue())
529500e3eadSAditya Nandakumar       break;
530500e3eadSAditya Nandakumar     return C1.udiv(C2);
531500e3eadSAditya Nandakumar   case TargetOpcode::G_SDIV:
532500e3eadSAditya Nandakumar     if (!C2.getBoolValue())
533500e3eadSAditya Nandakumar       break;
534500e3eadSAditya Nandakumar     return C1.sdiv(C2);
535500e3eadSAditya Nandakumar   case TargetOpcode::G_UREM:
536500e3eadSAditya Nandakumar     if (!C2.getBoolValue())
537500e3eadSAditya Nandakumar       break;
538500e3eadSAditya Nandakumar     return C1.urem(C2);
539500e3eadSAditya Nandakumar   case TargetOpcode::G_SREM:
540500e3eadSAditya Nandakumar     if (!C2.getBoolValue())
541500e3eadSAditya Nandakumar       break;
542500e3eadSAditya Nandakumar     return C1.srem(C2);
543930f2498SMatt Arsenault   case TargetOpcode::G_SMIN:
544930f2498SMatt Arsenault     return APIntOps::smin(C1, C2);
545930f2498SMatt Arsenault   case TargetOpcode::G_SMAX:
546930f2498SMatt Arsenault     return APIntOps::smax(C1, C2);
547930f2498SMatt Arsenault   case TargetOpcode::G_UMIN:
548930f2498SMatt Arsenault     return APIntOps::umin(C1, C2);
549930f2498SMatt Arsenault   case TargetOpcode::G_UMAX:
550930f2498SMatt Arsenault     return APIntOps::umax(C1, C2);
551500e3eadSAditya Nandakumar   }
5528a3340d2SMatt Arsenault 
553500e3eadSAditya Nandakumar   return None;
554500e3eadSAditya Nandakumar }
555500e3eadSAditya Nandakumar 
ConstantFoldFPBinOp(unsigned Opcode,const Register Op1,const Register Op2,const MachineRegisterInfo & MRI)5569fdfd8ddSMatt Arsenault Optional<APFloat> llvm::ConstantFoldFPBinOp(unsigned Opcode, const Register Op1,
5579fdfd8ddSMatt Arsenault                                             const Register Op2,
5589fdfd8ddSMatt Arsenault                                             const MachineRegisterInfo &MRI) {
5599fdfd8ddSMatt Arsenault   const ConstantFP *Op2Cst = getConstantFPVRegVal(Op2, MRI);
5609fdfd8ddSMatt Arsenault   if (!Op2Cst)
5619fdfd8ddSMatt Arsenault     return None;
5629fdfd8ddSMatt Arsenault 
5639fdfd8ddSMatt Arsenault   const ConstantFP *Op1Cst = getConstantFPVRegVal(Op1, MRI);
5649fdfd8ddSMatt Arsenault   if (!Op1Cst)
5659fdfd8ddSMatt Arsenault     return None;
5669fdfd8ddSMatt Arsenault 
5679fdfd8ddSMatt Arsenault   APFloat C1 = Op1Cst->getValueAPF();
5689fdfd8ddSMatt Arsenault   const APFloat &C2 = Op2Cst->getValueAPF();
5699fdfd8ddSMatt Arsenault   switch (Opcode) {
5709fdfd8ddSMatt Arsenault   case TargetOpcode::G_FADD:
5719fdfd8ddSMatt Arsenault     C1.add(C2, APFloat::rmNearestTiesToEven);
5729fdfd8ddSMatt Arsenault     return C1;
5739fdfd8ddSMatt Arsenault   case TargetOpcode::G_FSUB:
5749fdfd8ddSMatt Arsenault     C1.subtract(C2, APFloat::rmNearestTiesToEven);
5759fdfd8ddSMatt Arsenault     return C1;
5769fdfd8ddSMatt Arsenault   case TargetOpcode::G_FMUL:
5779fdfd8ddSMatt Arsenault     C1.multiply(C2, APFloat::rmNearestTiesToEven);
5789fdfd8ddSMatt Arsenault     return C1;
5799fdfd8ddSMatt Arsenault   case TargetOpcode::G_FDIV:
5809fdfd8ddSMatt Arsenault     C1.divide(C2, APFloat::rmNearestTiesToEven);
5819fdfd8ddSMatt Arsenault     return C1;
5829fdfd8ddSMatt Arsenault   case TargetOpcode::G_FREM:
5839fdfd8ddSMatt Arsenault     C1.mod(C2);
5849fdfd8ddSMatt Arsenault     return C1;
5859fdfd8ddSMatt Arsenault   case TargetOpcode::G_FCOPYSIGN:
5869fdfd8ddSMatt Arsenault     C1.copySign(C2);
5879fdfd8ddSMatt Arsenault     return C1;
5889fdfd8ddSMatt Arsenault   case TargetOpcode::G_FMINNUM:
5899fdfd8ddSMatt Arsenault     return minnum(C1, C2);
5909fdfd8ddSMatt Arsenault   case TargetOpcode::G_FMAXNUM:
5919fdfd8ddSMatt Arsenault     return maxnum(C1, C2);
5929fdfd8ddSMatt Arsenault   case TargetOpcode::G_FMINIMUM:
5939fdfd8ddSMatt Arsenault     return minimum(C1, C2);
5949fdfd8ddSMatt Arsenault   case TargetOpcode::G_FMAXIMUM:
5959fdfd8ddSMatt Arsenault     return maximum(C1, C2);
5969fdfd8ddSMatt Arsenault   case TargetOpcode::G_FMINNUM_IEEE:
5979fdfd8ddSMatt Arsenault   case TargetOpcode::G_FMAXNUM_IEEE:
5989fdfd8ddSMatt Arsenault     // FIXME: These operations were unfortunately named. fminnum/fmaxnum do not
5999fdfd8ddSMatt Arsenault     // follow the IEEE behavior for signaling nans and follow libm's fmin/fmax,
6009fdfd8ddSMatt Arsenault     // and currently there isn't a nice wrapper in APFloat for the version with
6019fdfd8ddSMatt Arsenault     // correct snan handling.
6029fdfd8ddSMatt Arsenault     break;
6039fdfd8ddSMatt Arsenault   default:
6049fdfd8ddSMatt Arsenault     break;
6059fdfd8ddSMatt Arsenault   }
6069fdfd8ddSMatt Arsenault 
6079fdfd8ddSMatt Arsenault   return None;
6089fdfd8ddSMatt Arsenault }
6099fdfd8ddSMatt Arsenault 
61026e1ebd3SJay Foad SmallVector<APInt>
ConstantFoldVectorBinop(unsigned Opcode,const Register Op1,const Register Op2,const MachineRegisterInfo & MRI)61126e1ebd3SJay Foad llvm::ConstantFoldVectorBinop(unsigned Opcode, const Register Op1,
6125abce56eSAmara Emerson                               const Register Op2,
61326e1ebd3SJay Foad                               const MachineRegisterInfo &MRI) {
6145abce56eSAmara Emerson   auto *SrcVec2 = getOpcodeDef<GBuildVector>(Op2, MRI);
6155abce56eSAmara Emerson   if (!SrcVec2)
61626e1ebd3SJay Foad     return SmallVector<APInt>();
6175abce56eSAmara Emerson 
6185599c431SMatt Arsenault   auto *SrcVec1 = getOpcodeDef<GBuildVector>(Op1, MRI);
6195599c431SMatt Arsenault   if (!SrcVec1)
62026e1ebd3SJay Foad     return SmallVector<APInt>();
6215599c431SMatt Arsenault 
62226e1ebd3SJay Foad   SmallVector<APInt> FoldedElements;
6235abce56eSAmara Emerson   for (unsigned Idx = 0, E = SrcVec1->getNumSources(); Idx < E; ++Idx) {
6245abce56eSAmara Emerson     auto MaybeCst = ConstantFoldBinOp(Opcode, SrcVec1->getSourceReg(Idx),
6255abce56eSAmara Emerson                                       SrcVec2->getSourceReg(Idx), MRI);
6265abce56eSAmara Emerson     if (!MaybeCst)
62726e1ebd3SJay Foad       return SmallVector<APInt>();
62826e1ebd3SJay Foad     FoldedElements.push_back(*MaybeCst);
6295abce56eSAmara Emerson   }
63026e1ebd3SJay Foad   return FoldedElements;
6315abce56eSAmara Emerson }
6325abce56eSAmara Emerson 
isKnownNeverNaN(Register Val,const MachineRegisterInfo & MRI,bool SNaN)6336ce1b4feSMatt Arsenault bool llvm::isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI,
6346ce1b4feSMatt Arsenault                            bool SNaN) {
6356ce1b4feSMatt Arsenault   const MachineInstr *DefMI = MRI.getVRegDef(Val);
6366ce1b4feSMatt Arsenault   if (!DefMI)
6376ce1b4feSMatt Arsenault     return false;
6386ce1b4feSMatt Arsenault 
6396e2a86edSPetar Avramovic   const TargetMachine& TM = DefMI->getMF()->getTarget();
6406e2a86edSPetar Avramovic   if (DefMI->getFlag(MachineInstr::FmNoNans) || TM.Options.NoNaNsFPMath)
6416ce1b4feSMatt Arsenault     return true;
6426ce1b4feSMatt Arsenault 
643122c649cSPetar Avramovic   // If the value is a constant, we can obviously see if it is a NaN or not.
644122c649cSPetar Avramovic   if (const ConstantFP *FPVal = getConstantFPVRegVal(Val, MRI)) {
645122c649cSPetar Avramovic     return !FPVal->getValueAPF().isNaN() ||
646122c649cSPetar Avramovic            (SNaN && !FPVal->getValueAPF().isSignaling());
647122c649cSPetar Avramovic   }
648122c649cSPetar Avramovic 
649122c649cSPetar Avramovic   if (DefMI->getOpcode() == TargetOpcode::G_BUILD_VECTOR) {
650122c649cSPetar Avramovic     for (const auto &Op : DefMI->uses())
651122c649cSPetar Avramovic       if (!isKnownNeverNaN(Op.getReg(), MRI, SNaN))
652122c649cSPetar Avramovic         return false;
653122c649cSPetar Avramovic     return true;
654122c649cSPetar Avramovic   }
655122c649cSPetar Avramovic 
656f0d65f40SPetar Avramovic   switch (DefMI->getOpcode()) {
657f0d65f40SPetar Avramovic   default:
658f0d65f40SPetar Avramovic     break;
659f0d65f40SPetar Avramovic   case TargetOpcode::G_FMINNUM_IEEE:
660f0d65f40SPetar Avramovic   case TargetOpcode::G_FMAXNUM_IEEE: {
661f0d65f40SPetar Avramovic     if (SNaN)
662f0d65f40SPetar Avramovic       return true;
663f0d65f40SPetar Avramovic     // This can return a NaN if either operand is an sNaN, or if both operands
664f0d65f40SPetar Avramovic     // are NaN.
665f0d65f40SPetar Avramovic     return (isKnownNeverNaN(DefMI->getOperand(1).getReg(), MRI) &&
666f0d65f40SPetar Avramovic             isKnownNeverSNaN(DefMI->getOperand(2).getReg(), MRI)) ||
667f0d65f40SPetar Avramovic            (isKnownNeverSNaN(DefMI->getOperand(1).getReg(), MRI) &&
668f0d65f40SPetar Avramovic             isKnownNeverNaN(DefMI->getOperand(2).getReg(), MRI));
669f0d65f40SPetar Avramovic   }
670f0d65f40SPetar Avramovic   case TargetOpcode::G_FMINNUM:
671f0d65f40SPetar Avramovic   case TargetOpcode::G_FMAXNUM: {
672f0d65f40SPetar Avramovic     // Only one needs to be known not-nan, since it will be returned if the
673f0d65f40SPetar Avramovic     // other ends up being one.
674f0d65f40SPetar Avramovic     return isKnownNeverNaN(DefMI->getOperand(1).getReg(), MRI, SNaN) ||
675f0d65f40SPetar Avramovic            isKnownNeverNaN(DefMI->getOperand(2).getReg(), MRI, SNaN);
676f0d65f40SPetar Avramovic   }
677f0d65f40SPetar Avramovic   }
678f0d65f40SPetar Avramovic 
6796ce1b4feSMatt Arsenault   if (SNaN) {
6806ce1b4feSMatt Arsenault     // FP operations quiet. For now, just handle the ones inserted during
6816ce1b4feSMatt Arsenault     // legalization.
6826ce1b4feSMatt Arsenault     switch (DefMI->getOpcode()) {
6836ce1b4feSMatt Arsenault     case TargetOpcode::G_FPEXT:
6846ce1b4feSMatt Arsenault     case TargetOpcode::G_FPTRUNC:
6856ce1b4feSMatt Arsenault     case TargetOpcode::G_FCANONICALIZE:
6866ce1b4feSMatt Arsenault       return true;
6876ce1b4feSMatt Arsenault     default:
6886ce1b4feSMatt Arsenault       return false;
6896ce1b4feSMatt Arsenault     }
6906ce1b4feSMatt Arsenault   }
6916ce1b4feSMatt Arsenault 
6926ce1b4feSMatt Arsenault   return false;
6936ce1b4feSMatt Arsenault }
6946ce1b4feSMatt Arsenault 
inferAlignFromPtrInfo(MachineFunction & MF,const MachinePointerInfo & MPO)695d2d6c9f5SGuillaume Chatelet Align llvm::inferAlignFromPtrInfo(MachineFunction &MF,
696fb0c35faSMatt Arsenault                                   const MachinePointerInfo &MPO) {
697fb0c35faSMatt Arsenault   auto PSV = MPO.V.dyn_cast<const PseudoSourceValue *>();
698fb0c35faSMatt Arsenault   if (auto FSPV = dyn_cast_or_null<FixedStackPseudoSourceValue>(PSV)) {
699fb0c35faSMatt Arsenault     MachineFrameInfo &MFI = MF.getFrameInfo();
700d2d6c9f5SGuillaume Chatelet     return commonAlignment(MFI.getObjectAlign(FSPV->getFrameIndex()),
701d2d6c9f5SGuillaume Chatelet                            MPO.Offset);
702fb0c35faSMatt Arsenault   }
703fb0c35faSMatt Arsenault 
704b9a03849SMatt Arsenault   if (const Value *V = MPO.V.dyn_cast<const Value *>()) {
705b9a03849SMatt Arsenault     const Module *M = MF.getFunction().getParent();
706b9a03849SMatt Arsenault     return V->getPointerAlignment(M->getDataLayout());
707b9a03849SMatt Arsenault   }
708b9a03849SMatt Arsenault 
709d2d6c9f5SGuillaume Chatelet   return Align(1);
710fb0c35faSMatt Arsenault }
711fb0c35faSMatt Arsenault 
getFunctionLiveInPhysReg(MachineFunction & MF,const TargetInstrInfo & TII,MCRegister PhysReg,const TargetRegisterClass & RC,const DebugLoc & DL,LLT RegTy)712f8fb7835SMatt Arsenault Register llvm::getFunctionLiveInPhysReg(MachineFunction &MF,
713f8fb7835SMatt Arsenault                                         const TargetInstrInfo &TII,
714f8fb7835SMatt Arsenault                                         MCRegister PhysReg,
715f8fb7835SMatt Arsenault                                         const TargetRegisterClass &RC,
7160ba4e4b5SMatt Arsenault                                         const DebugLoc &DL, LLT RegTy) {
717f8fb7835SMatt Arsenault   MachineBasicBlock &EntryMBB = MF.front();
718f8fb7835SMatt Arsenault   MachineRegisterInfo &MRI = MF.getRegInfo();
719f8fb7835SMatt Arsenault   Register LiveIn = MRI.getLiveInVirtReg(PhysReg);
720f8fb7835SMatt Arsenault   if (LiveIn) {
721f8fb7835SMatt Arsenault     MachineInstr *Def = MRI.getVRegDef(LiveIn);
722f8fb7835SMatt Arsenault     if (Def) {
723f8fb7835SMatt Arsenault       // FIXME: Should the verifier check this is in the entry block?
724f8fb7835SMatt Arsenault       assert(Def->getParent() == &EntryMBB && "live-in copy not in entry block");
725f8fb7835SMatt Arsenault       return LiveIn;
726f8fb7835SMatt Arsenault     }
727f8fb7835SMatt Arsenault 
728f8fb7835SMatt Arsenault     // It's possible the incoming argument register and copy was added during
729f8fb7835SMatt Arsenault     // lowering, but later deleted due to being/becoming dead. If this happens,
730f8fb7835SMatt Arsenault     // re-insert the copy.
731f8fb7835SMatt Arsenault   } else {
732f8fb7835SMatt Arsenault     // The live in register was not present, so add it.
733f8fb7835SMatt Arsenault     LiveIn = MF.addLiveIn(PhysReg, &RC);
734f8fb7835SMatt Arsenault     if (RegTy.isValid())
735f8fb7835SMatt Arsenault       MRI.setType(LiveIn, RegTy);
736f8fb7835SMatt Arsenault   }
737f8fb7835SMatt Arsenault 
738f8fb7835SMatt Arsenault   BuildMI(EntryMBB, EntryMBB.begin(), DL, TII.get(TargetOpcode::COPY), LiveIn)
739f8fb7835SMatt Arsenault     .addReg(PhysReg);
740f8fb7835SMatt Arsenault   if (!EntryMBB.isLiveIn(PhysReg))
741f8fb7835SMatt Arsenault     EntryMBB.addLiveIn(PhysReg);
742f8fb7835SMatt Arsenault   return LiveIn;
743f8fb7835SMatt Arsenault }
744f8fb7835SMatt Arsenault 
ConstantFoldExtOp(unsigned Opcode,const Register Op1,uint64_t Imm,const MachineRegisterInfo & MRI)7455f7e38d8SMatt Arsenault Optional<APInt> llvm::ConstantFoldExtOp(unsigned Opcode, const Register Op1,
746e9a57c2bSDaniel Sanders                                         uint64_t Imm,
747e9a57c2bSDaniel Sanders                                         const MachineRegisterInfo &MRI) {
748d477a7c2SPetar Avramovic   auto MaybeOp1Cst = getIConstantVRegVal(Op1, MRI);
749e9a57c2bSDaniel Sanders   if (MaybeOp1Cst) {
750e9a57c2bSDaniel Sanders     switch (Opcode) {
751e9a57c2bSDaniel Sanders     default:
752e9a57c2bSDaniel Sanders       break;
753581d13f8SMatt Arsenault     case TargetOpcode::G_SEXT_INREG: {
754581d13f8SMatt Arsenault       LLT Ty = MRI.getType(Op1);
755581d13f8SMatt Arsenault       return MaybeOp1Cst->trunc(Imm).sext(Ty.getScalarSizeInBits());
756581d13f8SMatt Arsenault     }
757e9a57c2bSDaniel Sanders     }
758e9a57c2bSDaniel Sanders   }
759e9a57c2bSDaniel Sanders   return None;
760e9a57c2bSDaniel Sanders }
761e9a57c2bSDaniel Sanders 
ConstantFoldIntToFloat(unsigned Opcode,LLT DstTy,Register Src,const MachineRegisterInfo & MRI)762dc4ca0dbSJay Foad Optional<APFloat> llvm::ConstantFoldIntToFloat(unsigned Opcode, LLT DstTy,
763dc4ca0dbSJay Foad                                                Register Src,
764dc4ca0dbSJay Foad                                                const MachineRegisterInfo &MRI) {
765dc4ca0dbSJay Foad   assert(Opcode == TargetOpcode::G_SITOFP || Opcode == TargetOpcode::G_UITOFP);
766d477a7c2SPetar Avramovic   if (auto MaybeSrcVal = getIConstantVRegVal(Src, MRI)) {
767dc4ca0dbSJay Foad     APFloat DstVal(getFltSemanticForLLT(DstTy));
768dc4ca0dbSJay Foad     DstVal.convertFromAPInt(*MaybeSrcVal, Opcode == TargetOpcode::G_SITOFP,
769dc4ca0dbSJay Foad                             APFloat::rmNearestTiesToEven);
770dc4ca0dbSJay Foad     return DstVal;
771dc4ca0dbSJay Foad   }
772dc4ca0dbSJay Foad   return None;
773dc4ca0dbSJay Foad }
774dc4ca0dbSJay Foad 
77508b3c0d9SAmara Emerson Optional<SmallVector<unsigned>>
ConstantFoldCTLZ(Register Src,const MachineRegisterInfo & MRI)77608b3c0d9SAmara Emerson llvm::ConstantFoldCTLZ(Register Src, const MachineRegisterInfo &MRI) {
77708b3c0d9SAmara Emerson   LLT Ty = MRI.getType(Src);
77808b3c0d9SAmara Emerson   SmallVector<unsigned> FoldedCTLZs;
77908b3c0d9SAmara Emerson   auto tryFoldScalar = [&](Register R) -> Optional<unsigned> {
78008b3c0d9SAmara Emerson     auto MaybeCst = getIConstantVRegVal(R, MRI);
78108b3c0d9SAmara Emerson     if (!MaybeCst)
78208b3c0d9SAmara Emerson       return None;
78308b3c0d9SAmara Emerson     return MaybeCst->countLeadingZeros();
78408b3c0d9SAmara Emerson   };
78508b3c0d9SAmara Emerson   if (Ty.isVector()) {
78608b3c0d9SAmara Emerson     // Try to constant fold each element.
78708b3c0d9SAmara Emerson     auto *BV = getOpcodeDef<GBuildVector>(Src, MRI);
78808b3c0d9SAmara Emerson     if (!BV)
78908b3c0d9SAmara Emerson       return None;
79008b3c0d9SAmara Emerson     for (unsigned SrcIdx = 0; SrcIdx < BV->getNumSources(); ++SrcIdx) {
79108b3c0d9SAmara Emerson       if (auto MaybeFold = tryFoldScalar(BV->getSourceReg(SrcIdx))) {
79208b3c0d9SAmara Emerson         FoldedCTLZs.emplace_back(*MaybeFold);
79308b3c0d9SAmara Emerson         continue;
79408b3c0d9SAmara Emerson       }
79508b3c0d9SAmara Emerson       return None;
79608b3c0d9SAmara Emerson     }
79708b3c0d9SAmara Emerson     return FoldedCTLZs;
79808b3c0d9SAmara Emerson   }
79908b3c0d9SAmara Emerson   if (auto MaybeCst = tryFoldScalar(Src)) {
80008b3c0d9SAmara Emerson     FoldedCTLZs.emplace_back(*MaybeCst);
80108b3c0d9SAmara Emerson     return FoldedCTLZs;
80208b3c0d9SAmara Emerson   }
80308b3c0d9SAmara Emerson   return None;
80408b3c0d9SAmara Emerson }
80508b3c0d9SAmara Emerson 
isKnownToBeAPowerOfTwo(Register Reg,const MachineRegisterInfo & MRI,GISelKnownBits * KB)806a427f15dSMatt Arsenault bool llvm::isKnownToBeAPowerOfTwo(Register Reg, const MachineRegisterInfo &MRI,
807a427f15dSMatt Arsenault                                   GISelKnownBits *KB) {
808a427f15dSMatt Arsenault   Optional<DefinitionAndSourceRegister> DefSrcReg =
809a427f15dSMatt Arsenault       getDefSrcRegIgnoringCopies(Reg, MRI);
810a427f15dSMatt Arsenault   if (!DefSrcReg)
811a427f15dSMatt Arsenault     return false;
812a427f15dSMatt Arsenault 
813a427f15dSMatt Arsenault   const MachineInstr &MI = *DefSrcReg->MI;
814a427f15dSMatt Arsenault   const LLT Ty = MRI.getType(Reg);
815a427f15dSMatt Arsenault 
816a427f15dSMatt Arsenault   switch (MI.getOpcode()) {
817a427f15dSMatt Arsenault   case TargetOpcode::G_CONSTANT: {
818a427f15dSMatt Arsenault     unsigned BitWidth = Ty.getScalarSizeInBits();
819a427f15dSMatt Arsenault     const ConstantInt *CI = MI.getOperand(1).getCImm();
820a427f15dSMatt Arsenault     return CI->getValue().zextOrTrunc(BitWidth).isPowerOf2();
821a427f15dSMatt Arsenault   }
822a427f15dSMatt Arsenault   case TargetOpcode::G_SHL: {
823a427f15dSMatt Arsenault     // A left-shift of a constant one will have exactly one bit set because
824a427f15dSMatt Arsenault     // shifting the bit off the end is undefined.
825a427f15dSMatt Arsenault 
826a427f15dSMatt Arsenault     // TODO: Constant splat
827d477a7c2SPetar Avramovic     if (auto ConstLHS = getIConstantVRegVal(MI.getOperand(1).getReg(), MRI)) {
828a427f15dSMatt Arsenault       if (*ConstLHS == 1)
829a427f15dSMatt Arsenault         return true;
830a427f15dSMatt Arsenault     }
831a427f15dSMatt Arsenault 
832a427f15dSMatt Arsenault     break;
833a427f15dSMatt Arsenault   }
834a427f15dSMatt Arsenault   case TargetOpcode::G_LSHR: {
835d477a7c2SPetar Avramovic     if (auto ConstLHS = getIConstantVRegVal(MI.getOperand(1).getReg(), MRI)) {
836a427f15dSMatt Arsenault       if (ConstLHS->isSignMask())
837a427f15dSMatt Arsenault         return true;
838a427f15dSMatt Arsenault     }
839a427f15dSMatt Arsenault 
840a427f15dSMatt Arsenault     break;
841a427f15dSMatt Arsenault   }
842c34819afSMatt Arsenault   case TargetOpcode::G_BUILD_VECTOR: {
843c34819afSMatt Arsenault     // TODO: Probably should have a recursion depth guard since you could have
844c34819afSMatt Arsenault     // bitcasted vector elements.
845bfd5dd15SKazu Hirata     for (const MachineOperand &MO : llvm::drop_begin(MI.operands()))
846bfd5dd15SKazu Hirata       if (!isKnownToBeAPowerOfTwo(MO.getReg(), MRI, KB))
847c34819afSMatt Arsenault         return false;
848c34819afSMatt Arsenault 
849c34819afSMatt Arsenault     return true;
850c34819afSMatt Arsenault   }
851c34819afSMatt Arsenault   case TargetOpcode::G_BUILD_VECTOR_TRUNC: {
852c34819afSMatt Arsenault     // Only handle constants since we would need to know if number of leading
853c34819afSMatt Arsenault     // zeros is greater than the truncation amount.
854c34819afSMatt Arsenault     const unsigned BitWidth = Ty.getScalarSizeInBits();
855bfd5dd15SKazu Hirata     for (const MachineOperand &MO : llvm::drop_begin(MI.operands())) {
856bfd5dd15SKazu Hirata       auto Const = getIConstantVRegVal(MO.getReg(), MRI);
857c34819afSMatt Arsenault       if (!Const || !Const->zextOrTrunc(BitWidth).isPowerOf2())
858c34819afSMatt Arsenault         return false;
859c34819afSMatt Arsenault     }
860c34819afSMatt Arsenault 
861c34819afSMatt Arsenault     return true;
862c34819afSMatt Arsenault   }
863a427f15dSMatt Arsenault   default:
864a427f15dSMatt Arsenault     break;
865a427f15dSMatt Arsenault   }
866a427f15dSMatt Arsenault 
867a427f15dSMatt Arsenault   if (!KB)
868a427f15dSMatt Arsenault     return false;
869a427f15dSMatt Arsenault 
870a427f15dSMatt Arsenault   // More could be done here, though the above checks are enough
871a427f15dSMatt Arsenault   // to handle some common cases.
872a427f15dSMatt Arsenault 
873a427f15dSMatt Arsenault   // Fall back to computeKnownBits to catch other known cases.
874a427f15dSMatt Arsenault   KnownBits Known = KB->getKnownBits(Reg);
875a427f15dSMatt Arsenault   return (Known.countMaxPopulation() == 1) && (Known.countMinPopulation() == 1);
876a427f15dSMatt Arsenault }
877a427f15dSMatt Arsenault 
getSelectionDAGFallbackAnalysisUsage(AnalysisUsage & AU)87890ad6835SMatthias Braun void llvm::getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU) {
87990ad6835SMatthias Braun   AU.addPreserved<StackProtector>();
88090ad6835SMatthias Braun }
881b71203a7SMatt Arsenault 
getLCMSize(unsigned OrigSize,unsigned TargetSize)8821ef3ed0eSMatt Arsenault static unsigned getLCMSize(unsigned OrigSize, unsigned TargetSize) {
8831ef3ed0eSMatt Arsenault   unsigned Mul = OrigSize * TargetSize;
8841ef3ed0eSMatt Arsenault   unsigned GCDSize = greatestCommonDivisor(OrigSize, TargetSize);
8851ef3ed0eSMatt Arsenault   return Mul / GCDSize;
886b71203a7SMatt Arsenault }
887b71203a7SMatt Arsenault 
getLCMType(LLT OrigTy,LLT TargetTy)8881ef3ed0eSMatt Arsenault LLT llvm::getLCMType(LLT OrigTy, LLT TargetTy) {
8891ef3ed0eSMatt Arsenault   const unsigned OrigSize = OrigTy.getSizeInBits();
8901ef3ed0eSMatt Arsenault   const unsigned TargetSize = TargetTy.getSizeInBits();
8911ef3ed0eSMatt Arsenault 
8921ef3ed0eSMatt Arsenault   if (OrigSize == TargetSize)
8931ef3ed0eSMatt Arsenault     return OrigTy;
8941ef3ed0eSMatt Arsenault 
8951ef3ed0eSMatt Arsenault   if (OrigTy.isVector()) {
8961ef3ed0eSMatt Arsenault     const LLT OrigElt = OrigTy.getElementType();
8971ef3ed0eSMatt Arsenault 
8981ef3ed0eSMatt Arsenault     if (TargetTy.isVector()) {
8991ef3ed0eSMatt Arsenault       const LLT TargetElt = TargetTy.getElementType();
9001ef3ed0eSMatt Arsenault 
9011ef3ed0eSMatt Arsenault       if (OrigElt.getSizeInBits() == TargetElt.getSizeInBits()) {
9021ef3ed0eSMatt Arsenault         int GCDElts = greatestCommonDivisor(OrigTy.getNumElements(),
9031ef3ed0eSMatt Arsenault                                             TargetTy.getNumElements());
9041ef3ed0eSMatt Arsenault         // Prefer the original element type.
905d5e14ba8SSander de Smalen         ElementCount Mul = OrigTy.getElementCount() * TargetTy.getNumElements();
906d5e14ba8SSander de Smalen         return LLT::vector(Mul.divideCoefficientBy(GCDElts),
907d5e14ba8SSander de Smalen                            OrigTy.getElementType());
9081ef3ed0eSMatt Arsenault       }
9091ef3ed0eSMatt Arsenault     } else {
9101ef3ed0eSMatt Arsenault       if (OrigElt.getSizeInBits() == TargetSize)
9111ef3ed0eSMatt Arsenault         return OrigTy;
912b71203a7SMatt Arsenault     }
913b71203a7SMatt Arsenault 
9141ef3ed0eSMatt Arsenault     unsigned LCMSize = getLCMSize(OrigSize, TargetSize);
915d5e14ba8SSander de Smalen     return LLT::fixed_vector(LCMSize / OrigElt.getSizeInBits(), OrigElt);
916b71203a7SMatt Arsenault   }
917b71203a7SMatt Arsenault 
9181ef3ed0eSMatt Arsenault   if (TargetTy.isVector()) {
9191ef3ed0eSMatt Arsenault     unsigned LCMSize = getLCMSize(OrigSize, TargetSize);
920d5e14ba8SSander de Smalen     return LLT::fixed_vector(LCMSize / OrigSize, OrigTy);
921b71203a7SMatt Arsenault   }
922b71203a7SMatt Arsenault 
9231ef3ed0eSMatt Arsenault   unsigned LCMSize = getLCMSize(OrigSize, TargetSize);
9241ef3ed0eSMatt Arsenault 
9251ef3ed0eSMatt Arsenault   // Preserve pointer types.
9261ef3ed0eSMatt Arsenault   if (LCMSize == OrigSize)
9271ef3ed0eSMatt Arsenault     return OrigTy;
9281ef3ed0eSMatt Arsenault   if (LCMSize == TargetSize)
9291ef3ed0eSMatt Arsenault     return TargetTy;
9301ef3ed0eSMatt Arsenault 
9311ef3ed0eSMatt Arsenault   return LLT::scalar(LCMSize);
932b71203a7SMatt Arsenault }
933b71203a7SMatt Arsenault 
getCoverTy(LLT OrigTy,LLT TargetTy)93429f88b93SPetar Avramovic LLT llvm::getCoverTy(LLT OrigTy, LLT TargetTy) {
93529f88b93SPetar Avramovic   if (!OrigTy.isVector() || !TargetTy.isVector() || OrigTy == TargetTy ||
93629f88b93SPetar Avramovic       (OrigTy.getScalarSizeInBits() != TargetTy.getScalarSizeInBits()))
93729f88b93SPetar Avramovic     return getLCMType(OrigTy, TargetTy);
93829f88b93SPetar Avramovic 
93929f88b93SPetar Avramovic   unsigned OrigTyNumElts = OrigTy.getNumElements();
94029f88b93SPetar Avramovic   unsigned TargetTyNumElts = TargetTy.getNumElements();
94129f88b93SPetar Avramovic   if (OrigTyNumElts % TargetTyNumElts == 0)
94229f88b93SPetar Avramovic     return OrigTy;
94329f88b93SPetar Avramovic 
94429f88b93SPetar Avramovic   unsigned NumElts = alignTo(OrigTyNumElts, TargetTyNumElts);
94529f88b93SPetar Avramovic   return LLT::scalarOrVector(ElementCount::getFixed(NumElts),
94629f88b93SPetar Avramovic                              OrigTy.getElementType());
94729f88b93SPetar Avramovic }
94829f88b93SPetar Avramovic 
getGCDType(LLT OrigTy,LLT TargetTy)949b71203a7SMatt Arsenault LLT llvm::getGCDType(LLT OrigTy, LLT TargetTy) {
95012d5bec8SMatt Arsenault   const unsigned OrigSize = OrigTy.getSizeInBits();
95112d5bec8SMatt Arsenault   const unsigned TargetSize = TargetTy.getSizeInBits();
95212d5bec8SMatt Arsenault 
95312d5bec8SMatt Arsenault   if (OrigSize == TargetSize)
95412d5bec8SMatt Arsenault     return OrigTy;
95512d5bec8SMatt Arsenault 
95612d5bec8SMatt Arsenault   if (OrigTy.isVector()) {
95712d5bec8SMatt Arsenault     LLT OrigElt = OrigTy.getElementType();
95812d5bec8SMatt Arsenault     if (TargetTy.isVector()) {
95912d5bec8SMatt Arsenault       LLT TargetElt = TargetTy.getElementType();
96012d5bec8SMatt Arsenault       if (OrigElt.getSizeInBits() == TargetElt.getSizeInBits()) {
961b71203a7SMatt Arsenault         int GCD = greatestCommonDivisor(OrigTy.getNumElements(),
962b71203a7SMatt Arsenault                                         TargetTy.getNumElements());
963968980efSSander de Smalen         return LLT::scalarOrVector(ElementCount::getFixed(GCD), OrigElt);
96412d5bec8SMatt Arsenault       }
96512d5bec8SMatt Arsenault     } else {
96612d5bec8SMatt Arsenault       // If the source is a vector of pointers, return a pointer element.
96712d5bec8SMatt Arsenault       if (OrigElt.getSizeInBits() == TargetSize)
96812d5bec8SMatt Arsenault         return OrigElt;
969b71203a7SMatt Arsenault     }
970b71203a7SMatt Arsenault 
97112d5bec8SMatt Arsenault     unsigned GCD = greatestCommonDivisor(OrigSize, TargetSize);
97212d5bec8SMatt Arsenault     if (GCD == OrigElt.getSizeInBits())
97312d5bec8SMatt Arsenault       return OrigElt;
97412d5bec8SMatt Arsenault 
97512d5bec8SMatt Arsenault     // If we can't produce the original element type, we have to use a smaller
97612d5bec8SMatt Arsenault     // scalar.
97712d5bec8SMatt Arsenault     if (GCD < OrigElt.getSizeInBits())
97812d5bec8SMatt Arsenault       return LLT::scalar(GCD);
979d5e14ba8SSander de Smalen     return LLT::fixed_vector(GCD / OrigElt.getSizeInBits(), OrigElt);
980b71203a7SMatt Arsenault   }
981b71203a7SMatt Arsenault 
98212d5bec8SMatt Arsenault   if (TargetTy.isVector()) {
98312d5bec8SMatt Arsenault     // Try to preserve the original element type.
98412d5bec8SMatt Arsenault     LLT TargetElt = TargetTy.getElementType();
98512d5bec8SMatt Arsenault     if (TargetElt.getSizeInBits() == OrigSize)
98612d5bec8SMatt Arsenault       return OrigTy;
98712d5bec8SMatt Arsenault   }
988b71203a7SMatt Arsenault 
98912d5bec8SMatt Arsenault   unsigned GCD = greatestCommonDivisor(OrigSize, TargetSize);
990b71203a7SMatt Arsenault   return LLT::scalar(GCD);
991b71203a7SMatt Arsenault }
992d8ba6222SAmara Emerson 
getSplatIndex(MachineInstr & MI)993d8ba6222SAmara Emerson Optional<int> llvm::getSplatIndex(MachineInstr &MI) {
994d8ba6222SAmara Emerson   assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR &&
995d8ba6222SAmara Emerson          "Only G_SHUFFLE_VECTOR can have a splat index!");
996d8ba6222SAmara Emerson   ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask();
997d8ba6222SAmara Emerson   auto FirstDefinedIdx = find_if(Mask, [](int Elt) { return Elt >= 0; });
998d8ba6222SAmara Emerson 
999d8ba6222SAmara Emerson   // If all elements are undefined, this shuffle can be considered a splat.
1000d8ba6222SAmara Emerson   // Return 0 for better potential for callers to simplify.
1001d8ba6222SAmara Emerson   if (FirstDefinedIdx == Mask.end())
1002d8ba6222SAmara Emerson     return 0;
1003d8ba6222SAmara Emerson 
1004d8ba6222SAmara Emerson   // Make sure all remaining elements are either undef or the same
1005d8ba6222SAmara Emerson   // as the first non-undef value.
1006d8ba6222SAmara Emerson   int SplatValue = *FirstDefinedIdx;
1007d8ba6222SAmara Emerson   if (any_of(make_range(std::next(FirstDefinedIdx), Mask.end()),
1008d8ba6222SAmara Emerson              [&SplatValue](int Elt) { return Elt >= 0 && Elt != SplatValue; }))
1009d8ba6222SAmara Emerson     return None;
1010d8ba6222SAmara Emerson 
1011d8ba6222SAmara Emerson   return SplatValue;
1012d8ba6222SAmara Emerson }
10135c5e6d95SMatt Arsenault 
isBuildVectorOp(unsigned Opcode)10145c5e6d95SMatt Arsenault static bool isBuildVectorOp(unsigned Opcode) {
10155c5e6d95SMatt Arsenault   return Opcode == TargetOpcode::G_BUILD_VECTOR ||
10165c5e6d95SMatt Arsenault          Opcode == TargetOpcode::G_BUILD_VECTOR_TRUNC;
10175c5e6d95SMatt Arsenault }
10185c5e6d95SMatt Arsenault 
10198bc71856SPetar Avramovic namespace {
10208bc71856SPetar Avramovic 
getAnyConstantSplat(Register VReg,const MachineRegisterInfo & MRI,bool AllowUndef)10218bc71856SPetar Avramovic Optional<ValueAndVReg> getAnyConstantSplat(Register VReg,
10225c5e6d95SMatt Arsenault                                            const MachineRegisterInfo &MRI,
10238bc71856SPetar Avramovic                                            bool AllowUndef) {
10248bc71856SPetar Avramovic   MachineInstr *MI = getDefIgnoringCopies(VReg, MRI);
10258bc71856SPetar Avramovic   if (!MI)
10268bc71856SPetar Avramovic     return None;
10275c5e6d95SMatt Arsenault 
10288bc71856SPetar Avramovic   if (!isBuildVectorOp(MI->getOpcode()))
10298bc71856SPetar Avramovic     return None;
10308bc71856SPetar Avramovic 
10318bc71856SPetar Avramovic   Optional<ValueAndVReg> SplatValAndReg = None;
10328bc71856SPetar Avramovic   for (MachineOperand &Op : MI->uses()) {
10338bc71856SPetar Avramovic     Register Element = Op.getReg();
10348bc71856SPetar Avramovic     auto ElementValAndReg =
10358bc71856SPetar Avramovic         getAnyConstantVRegValWithLookThrough(Element, MRI, true, true);
10368bc71856SPetar Avramovic 
10378bc71856SPetar Avramovic     // If AllowUndef, treat undef as value that will result in a constant splat.
10388bc71856SPetar Avramovic     if (!ElementValAndReg) {
10398bc71856SPetar Avramovic       if (AllowUndef && isa<GImplicitDef>(MRI.getVRegDef(Element)))
10408bc71856SPetar Avramovic         continue;
10418bc71856SPetar Avramovic       return None;
10428bc71856SPetar Avramovic     }
10438bc71856SPetar Avramovic 
10448bc71856SPetar Avramovic     // Record splat value
10458bc71856SPetar Avramovic     if (!SplatValAndReg)
10468bc71856SPetar Avramovic       SplatValAndReg = ElementValAndReg;
10478bc71856SPetar Avramovic 
10488bc71856SPetar Avramovic     // Different constant then the one already recorded, not a constant splat.
10498bc71856SPetar Avramovic     if (SplatValAndReg->Value != ElementValAndReg->Value)
10508bc71856SPetar Avramovic       return None;
10518bc71856SPetar Avramovic   }
10528bc71856SPetar Avramovic 
10538bc71856SPetar Avramovic   return SplatValAndReg;
10548bc71856SPetar Avramovic }
10558bc71856SPetar Avramovic 
1056bc5dbb0bSAbinav Puthan Purayil } // end anonymous namespace
1057bc5dbb0bSAbinav Puthan Purayil 
isBuildVectorConstantSplat(const Register Reg,const MachineRegisterInfo & MRI,int64_t SplatValue,bool AllowUndef)1058bc5dbb0bSAbinav Puthan Purayil bool llvm::isBuildVectorConstantSplat(const Register Reg,
10598bc71856SPetar Avramovic                                       const MachineRegisterInfo &MRI,
10608bc71856SPetar Avramovic                                       int64_t SplatValue, bool AllowUndef) {
1061bc5dbb0bSAbinav Puthan Purayil   if (auto SplatValAndReg = getAnyConstantSplat(Reg, MRI, AllowUndef))
10628bc71856SPetar Avramovic     return mi_match(SplatValAndReg->VReg, MRI, m_SpecificICst(SplatValue));
10635c5e6d95SMatt Arsenault   return false;
10645c5e6d95SMatt Arsenault }
10655c5e6d95SMatt Arsenault 
isBuildVectorConstantSplat(const MachineInstr & MI,const MachineRegisterInfo & MRI,int64_t SplatValue,bool AllowUndef)1066bc5dbb0bSAbinav Puthan Purayil bool llvm::isBuildVectorConstantSplat(const MachineInstr &MI,
1067bc5dbb0bSAbinav Puthan Purayil                                       const MachineRegisterInfo &MRI,
1068bc5dbb0bSAbinav Puthan Purayil                                       int64_t SplatValue, bool AllowUndef) {
1069bc5dbb0bSAbinav Puthan Purayil   return isBuildVectorConstantSplat(MI.getOperand(0).getReg(), MRI, SplatValue,
1070bc5dbb0bSAbinav Puthan Purayil                                     AllowUndef);
1071bc5dbb0bSAbinav Puthan Purayil }
10725c5e6d95SMatt Arsenault 
getIConstantSplatVal(const Register Reg,const MachineRegisterInfo & MRI)1073485dd0b7SAbinav Puthan Purayil Optional<APInt> llvm::getIConstantSplatVal(const Register Reg,
1074520ab710SAmara Emerson                                            const MachineRegisterInfo &MRI) {
10758bc71856SPetar Avramovic   if (auto SplatValAndReg =
1076485dd0b7SAbinav Puthan Purayil           getAnyConstantSplat(Reg, MRI, /* AllowUndef */ false)) {
1077485dd0b7SAbinav Puthan Purayil     Optional<ValueAndVReg> ValAndVReg =
1078485dd0b7SAbinav Puthan Purayil         getIConstantVRegValWithLookThrough(SplatValAndReg->VReg, MRI);
1079485dd0b7SAbinav Puthan Purayil     return ValAndVReg->Value;
1080485dd0b7SAbinav Puthan Purayil   }
1081485dd0b7SAbinav Puthan Purayil 
1082485dd0b7SAbinav Puthan Purayil   return None;
1083485dd0b7SAbinav Puthan Purayil }
1084485dd0b7SAbinav Puthan Purayil 
getIConstantSplatVal(const MachineInstr & MI,const MachineRegisterInfo & MRI)1085485dd0b7SAbinav Puthan Purayil Optional<APInt> getIConstantSplatVal(const MachineInstr &MI,
1086485dd0b7SAbinav Puthan Purayil                                      const MachineRegisterInfo &MRI) {
1087485dd0b7SAbinav Puthan Purayil   return getIConstantSplatVal(MI.getOperand(0).getReg(), MRI);
1088485dd0b7SAbinav Puthan Purayil }
1089485dd0b7SAbinav Puthan Purayil 
1090485dd0b7SAbinav Puthan Purayil Optional<int64_t>
getIConstantSplatSExtVal(const Register Reg,const MachineRegisterInfo & MRI)1091485dd0b7SAbinav Puthan Purayil llvm::getIConstantSplatSExtVal(const Register Reg,
1092485dd0b7SAbinav Puthan Purayil                                const MachineRegisterInfo &MRI) {
1093485dd0b7SAbinav Puthan Purayil   if (auto SplatValAndReg =
1094485dd0b7SAbinav Puthan Purayil           getAnyConstantSplat(Reg, MRI, /* AllowUndef */ false))
10958bc71856SPetar Avramovic     return getIConstantVRegSExtVal(SplatValAndReg->VReg, MRI);
1096520ab710SAmara Emerson   return None;
1097520ab710SAmara Emerson }
1098520ab710SAmara Emerson 
1099485dd0b7SAbinav Puthan Purayil Optional<int64_t>
getIConstantSplatSExtVal(const MachineInstr & MI,const MachineRegisterInfo & MRI)1100485dd0b7SAbinav Puthan Purayil llvm::getIConstantSplatSExtVal(const MachineInstr &MI,
1101485dd0b7SAbinav Puthan Purayil                                const MachineRegisterInfo &MRI) {
1102485dd0b7SAbinav Puthan Purayil   return getIConstantSplatSExtVal(MI.getOperand(0).getReg(), MRI);
1103485dd0b7SAbinav Puthan Purayil }
1104485dd0b7SAbinav Puthan Purayil 
getFConstantSplat(Register VReg,const MachineRegisterInfo & MRI,bool AllowUndef)11058bc71856SPetar Avramovic Optional<FPValueAndVReg> llvm::getFConstantSplat(Register VReg,
11068bc71856SPetar Avramovic                                                  const MachineRegisterInfo &MRI,
11078bc71856SPetar Avramovic                                                  bool AllowUndef) {
11088bc71856SPetar Avramovic   if (auto SplatValAndReg = getAnyConstantSplat(VReg, MRI, AllowUndef))
11098bc71856SPetar Avramovic     return getFConstantVRegValWithLookThrough(SplatValAndReg->VReg, MRI);
11108bc71856SPetar Avramovic   return None;
1111520ab710SAmara Emerson }
1112520ab710SAmara Emerson 
isBuildVectorAllZeros(const MachineInstr & MI,const MachineRegisterInfo & MRI,bool AllowUndef)11135c5e6d95SMatt Arsenault bool llvm::isBuildVectorAllZeros(const MachineInstr &MI,
11148bc71856SPetar Avramovic                                  const MachineRegisterInfo &MRI,
11158bc71856SPetar Avramovic                                  bool AllowUndef) {
11168bc71856SPetar Avramovic   return isBuildVectorConstantSplat(MI, MRI, 0, AllowUndef);
11175c5e6d95SMatt Arsenault }
11185c5e6d95SMatt Arsenault 
isBuildVectorAllOnes(const MachineInstr & MI,const MachineRegisterInfo & MRI,bool AllowUndef)11195c5e6d95SMatt Arsenault bool llvm::isBuildVectorAllOnes(const MachineInstr &MI,
11208bc71856SPetar Avramovic                                 const MachineRegisterInfo &MRI,
11218bc71856SPetar Avramovic                                 bool AllowUndef) {
11228bc71856SPetar Avramovic   return isBuildVectorConstantSplat(MI, MRI, -1, AllowUndef);
11235c5e6d95SMatt Arsenault }
1124520ab710SAmara Emerson 
getVectorSplat(const MachineInstr & MI,const MachineRegisterInfo & MRI)11255c26be21SJessica Paquette Optional<RegOrConstant> llvm::getVectorSplat(const MachineInstr &MI,
11265c26be21SJessica Paquette                                              const MachineRegisterInfo &MRI) {
11275c26be21SJessica Paquette   unsigned Opc = MI.getOpcode();
11285c26be21SJessica Paquette   if (!isBuildVectorOp(Opc))
11295c26be21SJessica Paquette     return None;
1130485dd0b7SAbinav Puthan Purayil   if (auto Splat = getIConstantSplatSExtVal(MI, MRI))
11315c26be21SJessica Paquette     return RegOrConstant(*Splat);
11325c26be21SJessica Paquette   auto Reg = MI.getOperand(1).getReg();
11335c26be21SJessica Paquette   if (any_of(make_range(MI.operands_begin() + 2, MI.operands_end()),
11345c26be21SJessica Paquette              [&Reg](const MachineOperand &Op) { return Op.getReg() != Reg; }))
11355c26be21SJessica Paquette     return None;
11365c26be21SJessica Paquette   return RegOrConstant(Reg);
11375c26be21SJessica Paquette }
11385c26be21SJessica Paquette 
isConstantScalar(const MachineInstr & MI,const MachineRegisterInfo & MRI,bool AllowFP=true,bool AllowOpaqueConstants=true)11390877fbccSMatt Arsenault static bool isConstantScalar(const MachineInstr &MI,
11400877fbccSMatt Arsenault                              const MachineRegisterInfo &MRI,
11410877fbccSMatt Arsenault                              bool AllowFP = true,
11420877fbccSMatt Arsenault                              bool AllowOpaqueConstants = true) {
11430877fbccSMatt Arsenault   switch (MI.getOpcode()) {
11440877fbccSMatt Arsenault   case TargetOpcode::G_CONSTANT:
11450877fbccSMatt Arsenault   case TargetOpcode::G_IMPLICIT_DEF:
11460877fbccSMatt Arsenault     return true;
11470877fbccSMatt Arsenault   case TargetOpcode::G_FCONSTANT:
11480877fbccSMatt Arsenault     return AllowFP;
11490877fbccSMatt Arsenault   case TargetOpcode::G_GLOBAL_VALUE:
11500877fbccSMatt Arsenault   case TargetOpcode::G_FRAME_INDEX:
11510877fbccSMatt Arsenault   case TargetOpcode::G_BLOCK_ADDR:
11520877fbccSMatt Arsenault   case TargetOpcode::G_JUMP_TABLE:
11530877fbccSMatt Arsenault     return AllowOpaqueConstants;
11540877fbccSMatt Arsenault   default:
11550877fbccSMatt Arsenault     return false;
11560877fbccSMatt Arsenault   }
11570877fbccSMatt Arsenault }
11580877fbccSMatt Arsenault 
isConstantOrConstantVector(MachineInstr & MI,const MachineRegisterInfo & MRI)11598bfc0e06SAmara Emerson bool llvm::isConstantOrConstantVector(MachineInstr &MI,
11608bfc0e06SAmara Emerson                                       const MachineRegisterInfo &MRI) {
11618bfc0e06SAmara Emerson   Register Def = MI.getOperand(0).getReg();
11628bfc0e06SAmara Emerson   if (auto C = getIConstantVRegValWithLookThrough(Def, MRI))
11638bfc0e06SAmara Emerson     return true;
11648bfc0e06SAmara Emerson   GBuildVector *BV = dyn_cast<GBuildVector>(&MI);
11658bfc0e06SAmara Emerson   if (!BV)
11668bfc0e06SAmara Emerson     return false;
11678bfc0e06SAmara Emerson   for (unsigned SrcIdx = 0; SrcIdx < BV->getNumSources(); ++SrcIdx) {
11688bfc0e06SAmara Emerson     if (getIConstantVRegValWithLookThrough(BV->getSourceReg(SrcIdx), MRI) ||
11698bfc0e06SAmara Emerson         getOpcodeDef<GImplicitDef>(BV->getSourceReg(SrcIdx), MRI))
11708bfc0e06SAmara Emerson       continue;
11718bfc0e06SAmara Emerson     return false;
11728bfc0e06SAmara Emerson   }
11738bfc0e06SAmara Emerson   return true;
11748bfc0e06SAmara Emerson }
11758bfc0e06SAmara Emerson 
isConstantOrConstantVector(const MachineInstr & MI,const MachineRegisterInfo & MRI,bool AllowFP,bool AllowOpaqueConstants)11760877fbccSMatt Arsenault bool llvm::isConstantOrConstantVector(const MachineInstr &MI,
11770877fbccSMatt Arsenault                                       const MachineRegisterInfo &MRI,
11780877fbccSMatt Arsenault                                       bool AllowFP, bool AllowOpaqueConstants) {
11790877fbccSMatt Arsenault   if (isConstantScalar(MI, MRI, AllowFP, AllowOpaqueConstants))
11800877fbccSMatt Arsenault     return true;
11810877fbccSMatt Arsenault 
11820877fbccSMatt Arsenault   if (!isBuildVectorOp(MI.getOpcode()))
11830877fbccSMatt Arsenault     return false;
11840877fbccSMatt Arsenault 
11850877fbccSMatt Arsenault   const unsigned NumOps = MI.getNumOperands();
11860877fbccSMatt Arsenault   for (unsigned I = 1; I != NumOps; ++I) {
11870877fbccSMatt Arsenault     const MachineInstr *ElementDef = MRI.getVRegDef(MI.getOperand(I).getReg());
11880877fbccSMatt Arsenault     if (!isConstantScalar(*ElementDef, MRI, AllowFP, AllowOpaqueConstants))
11890877fbccSMatt Arsenault       return false;
11900877fbccSMatt Arsenault   }
11910877fbccSMatt Arsenault 
11920877fbccSMatt Arsenault   return true;
11930877fbccSMatt Arsenault }
11940877fbccSMatt Arsenault 
119580f4bb5cSAmara Emerson Optional<APInt>
isConstantOrConstantSplatVector(MachineInstr & MI,const MachineRegisterInfo & MRI)119680f4bb5cSAmara Emerson llvm::isConstantOrConstantSplatVector(MachineInstr &MI,
119780f4bb5cSAmara Emerson                                       const MachineRegisterInfo &MRI) {
119880f4bb5cSAmara Emerson   Register Def = MI.getOperand(0).getReg();
119980f4bb5cSAmara Emerson   if (auto C = getIConstantVRegValWithLookThrough(Def, MRI))
120080f4bb5cSAmara Emerson     return C->Value;
1201485dd0b7SAbinav Puthan Purayil   auto MaybeCst = getIConstantSplatSExtVal(MI, MRI);
120280f4bb5cSAmara Emerson   if (!MaybeCst)
120380f4bb5cSAmara Emerson     return None;
120480f4bb5cSAmara Emerson   const unsigned ScalarSize = MRI.getType(Def).getScalarSizeInBits();
120580f4bb5cSAmara Emerson   return APInt(ScalarSize, *MaybeCst, true);
120680f4bb5cSAmara Emerson }
120780f4bb5cSAmara Emerson 
isNullOrNullSplat(const MachineInstr & MI,const MachineRegisterInfo & MRI,bool AllowUndefs)12080877fbccSMatt Arsenault bool llvm::isNullOrNullSplat(const MachineInstr &MI,
12090877fbccSMatt Arsenault                              const MachineRegisterInfo &MRI, bool AllowUndefs) {
12100877fbccSMatt Arsenault   switch (MI.getOpcode()) {
12110877fbccSMatt Arsenault   case TargetOpcode::G_IMPLICIT_DEF:
12120877fbccSMatt Arsenault     return AllowUndefs;
12130877fbccSMatt Arsenault   case TargetOpcode::G_CONSTANT:
12140877fbccSMatt Arsenault     return MI.getOperand(1).getCImm()->isNullValue();
12150877fbccSMatt Arsenault   case TargetOpcode::G_FCONSTANT: {
12160877fbccSMatt Arsenault     const ConstantFP *FPImm = MI.getOperand(1).getFPImm();
12170877fbccSMatt Arsenault     return FPImm->isZero() && !FPImm->isNegative();
12180877fbccSMatt Arsenault   }
12190877fbccSMatt Arsenault   default:
12200877fbccSMatt Arsenault     if (!AllowUndefs) // TODO: isBuildVectorAllZeros assumes undef is OK already
12210877fbccSMatt Arsenault       return false;
12220877fbccSMatt Arsenault     return isBuildVectorAllZeros(MI, MRI);
12230877fbccSMatt Arsenault   }
12240877fbccSMatt Arsenault }
12250877fbccSMatt Arsenault 
isAllOnesOrAllOnesSplat(const MachineInstr & MI,const MachineRegisterInfo & MRI,bool AllowUndefs)12260877fbccSMatt Arsenault bool llvm::isAllOnesOrAllOnesSplat(const MachineInstr &MI,
12270877fbccSMatt Arsenault                                    const MachineRegisterInfo &MRI,
12280877fbccSMatt Arsenault                                    bool AllowUndefs) {
12290877fbccSMatt Arsenault   switch (MI.getOpcode()) {
12300877fbccSMatt Arsenault   case TargetOpcode::G_IMPLICIT_DEF:
12310877fbccSMatt Arsenault     return AllowUndefs;
12320877fbccSMatt Arsenault   case TargetOpcode::G_CONSTANT:
12330877fbccSMatt Arsenault     return MI.getOperand(1).getCImm()->isAllOnesValue();
12340877fbccSMatt Arsenault   default:
12350877fbccSMatt Arsenault     if (!AllowUndefs) // TODO: isBuildVectorAllOnes assumes undef is OK already
12360877fbccSMatt Arsenault       return false;
12370877fbccSMatt Arsenault     return isBuildVectorAllOnes(MI, MRI);
12380877fbccSMatt Arsenault   }
12390877fbccSMatt Arsenault }
12400877fbccSMatt Arsenault 
matchUnaryPredicate(const MachineRegisterInfo & MRI,Register Reg,std::function<bool (const Constant * ConstVal)> Match,bool AllowUndefs)1241b24436acSMatt Arsenault bool llvm::matchUnaryPredicate(
1242b24436acSMatt Arsenault     const MachineRegisterInfo &MRI, Register Reg,
1243b24436acSMatt Arsenault     std::function<bool(const Constant *ConstVal)> Match, bool AllowUndefs) {
1244b24436acSMatt Arsenault 
1245b24436acSMatt Arsenault   const MachineInstr *Def = getDefIgnoringCopies(Reg, MRI);
1246b24436acSMatt Arsenault   if (AllowUndefs && Def->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
1247b24436acSMatt Arsenault     return Match(nullptr);
1248b24436acSMatt Arsenault 
1249b24436acSMatt Arsenault   // TODO: Also handle fconstant
1250b24436acSMatt Arsenault   if (Def->getOpcode() == TargetOpcode::G_CONSTANT)
1251b24436acSMatt Arsenault     return Match(Def->getOperand(1).getCImm());
1252b24436acSMatt Arsenault 
1253b24436acSMatt Arsenault   if (Def->getOpcode() != TargetOpcode::G_BUILD_VECTOR)
1254b24436acSMatt Arsenault     return false;
1255b24436acSMatt Arsenault 
1256b24436acSMatt Arsenault   for (unsigned I = 1, E = Def->getNumOperands(); I != E; ++I) {
1257b24436acSMatt Arsenault     Register SrcElt = Def->getOperand(I).getReg();
1258b24436acSMatt Arsenault     const MachineInstr *SrcDef = getDefIgnoringCopies(SrcElt, MRI);
1259b24436acSMatt Arsenault     if (AllowUndefs && SrcDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF) {
1260b24436acSMatt Arsenault       if (!Match(nullptr))
1261b24436acSMatt Arsenault         return false;
1262b24436acSMatt Arsenault       continue;
1263b24436acSMatt Arsenault     }
1264b24436acSMatt Arsenault 
1265b24436acSMatt Arsenault     if (SrcDef->getOpcode() != TargetOpcode::G_CONSTANT ||
1266b24436acSMatt Arsenault         !Match(SrcDef->getOperand(1).getCImm()))
1267b24436acSMatt Arsenault       return false;
1268b24436acSMatt Arsenault   }
1269b24436acSMatt Arsenault 
1270b24436acSMatt Arsenault   return true;
1271b24436acSMatt Arsenault }
1272b24436acSMatt Arsenault 
isConstTrueVal(const TargetLowering & TLI,int64_t Val,bool IsVector,bool IsFP)1273520ab710SAmara Emerson bool llvm::isConstTrueVal(const TargetLowering &TLI, int64_t Val, bool IsVector,
1274520ab710SAmara Emerson                           bool IsFP) {
1275520ab710SAmara Emerson   switch (TLI.getBooleanContents(IsVector, IsFP)) {
1276520ab710SAmara Emerson   case TargetLowering::UndefinedBooleanContent:
1277520ab710SAmara Emerson     return Val & 0x1;
1278520ab710SAmara Emerson   case TargetLowering::ZeroOrOneBooleanContent:
1279520ab710SAmara Emerson     return Val == 1;
1280520ab710SAmara Emerson   case TargetLowering::ZeroOrNegativeOneBooleanContent:
1281520ab710SAmara Emerson     return Val == -1;
1282520ab710SAmara Emerson   }
1283520ab710SAmara Emerson   llvm_unreachable("Invalid boolean contents");
1284520ab710SAmara Emerson }
1285cc76da7aSAmara Emerson 
getICmpTrueVal(const TargetLowering & TLI,bool IsVector,bool IsFP)1286cc76da7aSAmara Emerson int64_t llvm::getICmpTrueVal(const TargetLowering &TLI, bool IsVector,
1287cc76da7aSAmara Emerson                              bool IsFP) {
1288cc76da7aSAmara Emerson   switch (TLI.getBooleanContents(IsVector, IsFP)) {
1289cc76da7aSAmara Emerson   case TargetLowering::UndefinedBooleanContent:
1290cc76da7aSAmara Emerson   case TargetLowering::ZeroOrOneBooleanContent:
1291cc76da7aSAmara Emerson     return 1;
1292cc76da7aSAmara Emerson   case TargetLowering::ZeroOrNegativeOneBooleanContent:
1293cc76da7aSAmara Emerson     return -1;
1294cc76da7aSAmara Emerson   }
1295cc76da7aSAmara Emerson   llvm_unreachable("Invalid boolean contents");
1296cc76da7aSAmara Emerson }
12978a316045SAmara Emerson 
shouldOptForSize(const MachineBasicBlock & MBB,ProfileSummaryInfo * PSI,BlockFrequencyInfo * BFI)12988a316045SAmara Emerson bool llvm::shouldOptForSize(const MachineBasicBlock &MBB,
12998a316045SAmara Emerson                             ProfileSummaryInfo *PSI, BlockFrequencyInfo *BFI) {
13008a316045SAmara Emerson   const auto &F = MBB.getParent()->getFunction();
13018a316045SAmara Emerson   return F.hasOptSize() || F.hasMinSize() ||
13028a316045SAmara Emerson          llvm::shouldOptimizeForSize(MBB.getBasicBlock(), PSI, BFI);
13038a316045SAmara Emerson }
1304e4c46dddSPetar Avramovic 
saveUsesAndErase(MachineInstr & MI,MachineRegisterInfo & MRI,LostDebugLocObserver * LocObserver,SmallInstListTy & DeadInstChain)1305e4c46dddSPetar Avramovic void llvm::saveUsesAndErase(MachineInstr &MI, MachineRegisterInfo &MRI,
1306e4c46dddSPetar Avramovic                             LostDebugLocObserver *LocObserver,
1307e4c46dddSPetar Avramovic                             SmallInstListTy &DeadInstChain) {
1308e4c46dddSPetar Avramovic   for (MachineOperand &Op : MI.uses()) {
1309e4c46dddSPetar Avramovic     if (Op.isReg() && Op.getReg().isVirtual())
1310e4c46dddSPetar Avramovic       DeadInstChain.insert(MRI.getVRegDef(Op.getReg()));
1311e4c46dddSPetar Avramovic   }
1312e4c46dddSPetar Avramovic   LLVM_DEBUG(dbgs() << MI << "Is dead; erasing.\n");
1313e4c46dddSPetar Avramovic   DeadInstChain.remove(&MI);
13147091a7f7SAmara Emerson   MI.eraseFromParent();
1315e4c46dddSPetar Avramovic   if (LocObserver)
1316e4c46dddSPetar Avramovic     LocObserver->checkpoint(false);
1317e4c46dddSPetar Avramovic }
1318e4c46dddSPetar Avramovic 
eraseInstrs(ArrayRef<MachineInstr * > DeadInstrs,MachineRegisterInfo & MRI,LostDebugLocObserver * LocObserver)1319e4c46dddSPetar Avramovic void llvm::eraseInstrs(ArrayRef<MachineInstr *> DeadInstrs,
1320e4c46dddSPetar Avramovic                        MachineRegisterInfo &MRI,
1321e4c46dddSPetar Avramovic                        LostDebugLocObserver *LocObserver) {
1322e4c46dddSPetar Avramovic   SmallInstListTy DeadInstChain;
1323e4c46dddSPetar Avramovic   for (MachineInstr *MI : DeadInstrs)
1324e4c46dddSPetar Avramovic     saveUsesAndErase(*MI, MRI, LocObserver, DeadInstChain);
1325e4c46dddSPetar Avramovic 
1326e4c46dddSPetar Avramovic   while (!DeadInstChain.empty()) {
1327e4c46dddSPetar Avramovic     MachineInstr *Inst = DeadInstChain.pop_back_val();
1328e4c46dddSPetar Avramovic     if (!isTriviallyDead(*Inst, MRI))
1329e4c46dddSPetar Avramovic       continue;
1330e4c46dddSPetar Avramovic     saveUsesAndErase(*Inst, MRI, LocObserver, DeadInstChain);
1331e4c46dddSPetar Avramovic   }
1332e4c46dddSPetar Avramovic }
1333e4c46dddSPetar Avramovic 
eraseInstr(MachineInstr & MI,MachineRegisterInfo & MRI,LostDebugLocObserver * LocObserver)1334e4c46dddSPetar Avramovic void llvm::eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI,
1335e4c46dddSPetar Avramovic                       LostDebugLocObserver *LocObserver) {
1336e4c46dddSPetar Avramovic   return eraseInstrs({&MI}, MRI, LocObserver);
1337e4c46dddSPetar Avramovic }
1338