1//===- llvm/CodeGen/GlobalISel/Utils.cpp -------------------------*- C++ -*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file This file implements the utility functions used by the GlobalISel
9/// pipeline.
10//===----------------------------------------------------------------------===//
11
12#include "llvm/CodeGen/GlobalISel/Utils.h"
13#include "llvm/ADT/APFloat.h"
14#include "llvm/ADT/APInt.h"
15#include "llvm/Analysis/ValueTracking.h"
16#include "llvm/CodeGen/CodeGenCommonISel.h"
17#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
18#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
19#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
20#include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h"
21#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
22#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
23#include "llvm/CodeGen/MachineInstr.h"
24#include "llvm/CodeGen/MachineInstrBuilder.h"
25#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
26#include "llvm/CodeGen/MachineRegisterInfo.h"
27#include "llvm/CodeGen/MachineSizeOpts.h"
28#include "llvm/CodeGen/RegisterBankInfo.h"
29#include "llvm/CodeGen/StackProtector.h"
30#include "llvm/CodeGen/TargetInstrInfo.h"
31#include "llvm/CodeGen/TargetLowering.h"
32#include "llvm/CodeGen/TargetOpcodes.h"
33#include "llvm/CodeGen/TargetPassConfig.h"
34#include "llvm/CodeGen/TargetRegisterInfo.h"
35#include "llvm/IR/Constants.h"
36#include "llvm/Target/TargetMachine.h"
37#include "llvm/Transforms/Utils/SizeOpts.h"
38#include <numeric>
39#include <optional>
40
41#define DEBUG_TYPE "globalisel-utils"
42
43using namespace llvm;
44using namespace MIPatternMatch;
45
46Register llvm::constrainRegToClass(MachineRegisterInfo &MRI,
47 const TargetInstrInfo &TII,
48 const RegisterBankInfo &RBI, Register Reg,
49 const TargetRegisterClass &RegClass) {
50 if (!RBI.constrainGenericRegister(Reg, RC: RegClass, MRI))
51 return MRI.createVirtualRegister(RegClass: &RegClass);
52
53 return Reg;
54}
55
56Register llvm::constrainOperandRegClass(
57 const MachineFunction &MF, const TargetRegisterInfo &TRI,
58 MachineRegisterInfo &MRI, const TargetInstrInfo &TII,
59 const RegisterBankInfo &RBI, MachineInstr &InsertPt,
60 const TargetRegisterClass &RegClass, MachineOperand &RegMO) {
61 Register Reg = RegMO.getReg();
62 // Assume physical registers are properly constrained.
63 assert(Reg.isVirtual() && "PhysReg not implemented");
64
65 // Save the old register class to check whether
66 // the change notifications will be required.
67 // TODO: A better approach would be to pass
68 // the observers to constrainRegToClass().
69 auto *OldRegClass = MRI.getRegClassOrNull(Reg);
70 Register ConstrainedReg = constrainRegToClass(MRI, TII, RBI, Reg, RegClass);
71 // If we created a new virtual register because the class is not compatible
72 // then create a copy between the new and the old register.
73 if (ConstrainedReg != Reg) {
74 MachineBasicBlock::iterator InsertIt(&InsertPt);
75 MachineBasicBlock &MBB = *InsertPt.getParent();
76 // FIXME: The copy needs to have the classes constrained for its operands.
77 // Use operand's regbank to get the class for old register (Reg).
78 if (RegMO.isUse()) {
79 BuildMI(BB&: MBB, I: InsertIt, MIMD: InsertPt.getDebugLoc(),
80 MCID: TII.get(Opcode: TargetOpcode::COPY), DestReg: ConstrainedReg)
81 .addReg(RegNo: Reg);
82 } else {
83 assert(RegMO.isDef() && "Must be a definition");
84 BuildMI(BB&: MBB, I: std::next(x: InsertIt), MIMD: InsertPt.getDebugLoc(),
85 MCID: TII.get(Opcode: TargetOpcode::COPY), DestReg: Reg)
86 .addReg(RegNo: ConstrainedReg);
87 }
88 if (GISelChangeObserver *Observer = MF.getObserver()) {
89 Observer->changingInstr(MI&: *RegMO.getParent());
90 }
91 RegMO.setReg(ConstrainedReg);
92 if (GISelChangeObserver *Observer = MF.getObserver()) {
93 Observer->changedInstr(MI&: *RegMO.getParent());
94 }
95 } else if (OldRegClass != MRI.getRegClassOrNull(Reg)) {
96 if (GISelChangeObserver *Observer = MF.getObserver()) {
97 if (!RegMO.isDef()) {
98 MachineInstr *RegDef = MRI.getVRegDef(Reg);
99 Observer->changedInstr(MI&: *RegDef);
100 }
101 Observer->changingAllUsesOfReg(MRI, Reg);
102 Observer->finishedChangingAllUsesOfReg();
103 }
104 }
105 return ConstrainedReg;
106}
107
108Register llvm::constrainOperandRegClass(
109 const MachineFunction &MF, const TargetRegisterInfo &TRI,
110 MachineRegisterInfo &MRI, const TargetInstrInfo &TII,
111 const RegisterBankInfo &RBI, MachineInstr &InsertPt, const MCInstrDesc &II,
112 MachineOperand &RegMO, unsigned OpIdx) {
113 Register Reg = RegMO.getReg();
114 // Assume physical registers are properly constrained.
115 assert(Reg.isVirtual() && "PhysReg not implemented");
116
117 const TargetRegisterClass *OpRC = TII.getRegClass(MCID: II, OpNum: OpIdx);
118 // Some of the target independent instructions, like COPY, may not impose any
119 // register class constraints on some of their operands: If it's a use, we can
120 // skip constraining as the instruction defining the register would constrain
121 // it.
122
123 if (OpRC) {
124 // Obtain the RC from incoming regbank if it is a proper sub-class. Operands
125 // can have multiple regbanks for a superclass that combine different
126 // register types (E.g., AMDGPU's VGPR and AGPR). The regbank ambiguity
127 // resolved by targets during regbankselect should not be overridden.
128 if (const auto *SubRC = TRI.getCommonSubClass(
129 A: OpRC, B: TRI.getConstrainedRegClassForOperand(MO: RegMO, MRI)))
130 OpRC = SubRC;
131
132 OpRC = TRI.getAllocatableClass(RC: OpRC);
133 }
134
135 if (!OpRC) {
136 assert((!isTargetSpecificOpcode(II.getOpcode()) || RegMO.isUse()) &&
137 "Register class constraint is required unless either the "
138 "instruction is target independent or the operand is a use");
139 // FIXME: Just bailing out like this here could be not enough, unless we
140 // expect the users of this function to do the right thing for PHIs and
141 // COPY:
142 // v1 = COPY v0
143 // v2 = COPY v1
144 // v1 here may end up not being constrained at all. Please notice that to
145 // reproduce the issue we likely need a destination pattern of a selection
146 // rule producing such extra copies, not just an input GMIR with them as
147 // every existing target using selectImpl handles copies before calling it
148 // and they never reach this function.
149 return Reg;
150 }
151 return constrainOperandRegClass(MF, TRI, MRI, TII, RBI, InsertPt, RegClass: *OpRC,
152 RegMO);
153}
154
155void llvm::constrainSelectedInstRegOperands(MachineInstr &I,
156 const TargetInstrInfo &TII,
157 const TargetRegisterInfo &TRI,
158 const RegisterBankInfo &RBI) {
159 assert(!isPreISelGenericOpcode(I.getOpcode()) &&
160 "A selected instruction is expected");
161 MachineBasicBlock &MBB = *I.getParent();
162 MachineFunction &MF = *MBB.getParent();
163 MachineRegisterInfo &MRI = MF.getRegInfo();
164
165 for (unsigned OpI = 0, OpE = I.getNumExplicitOperands(); OpI != OpE; ++OpI) {
166 MachineOperand &MO = I.getOperand(i: OpI);
167
168 // There's nothing to be done on non-register operands.
169 if (!MO.isReg())
170 continue;
171
172 LLVM_DEBUG(dbgs() << "Converting operand: " << MO << '\n');
173 assert(MO.isReg() && "Unsupported non-reg operand");
174
175 Register Reg = MO.getReg();
176 // Physical registers don't need to be constrained.
177 if (Reg.isPhysical())
178 continue;
179
180 // Register operands with a value of 0 (e.g. predicate operands) don't need
181 // to be constrained.
182 if (Reg == 0)
183 continue;
184
185 // If the operand is a vreg, we should constrain its regclass, and only
186 // insert COPYs if that's impossible.
187 // constrainOperandRegClass does that for us.
188 constrainOperandRegClass(MF, TRI, MRI, TII, RBI, InsertPt&: I, II: I.getDesc(), RegMO&: MO, OpIdx: OpI);
189
190 // Tie uses to defs as indicated in MCInstrDesc if this hasn't already been
191 // done.
192 if (MO.isUse()) {
193 int DefIdx = I.getDesc().getOperandConstraint(OpNum: OpI, Constraint: MCOI::TIED_TO);
194 if (DefIdx != -1 && !I.isRegTiedToUseOperand(DefOpIdx: DefIdx))
195 I.tieOperands(DefIdx, UseIdx: OpI);
196 }
197 }
198}
199
200bool llvm::canReplaceReg(Register DstReg, Register SrcReg,
201 MachineRegisterInfo &MRI) {
202 // Give up if either DstReg or SrcReg is a physical register.
203 if (DstReg.isPhysical() || SrcReg.isPhysical())
204 return false;
205 // Give up if the types don't match.
206 if (MRI.getType(Reg: DstReg) != MRI.getType(Reg: SrcReg))
207 return false;
208 // Replace if either DstReg has no constraints or the register
209 // constraints match.
210 const auto &DstRBC = MRI.getRegClassOrRegBank(Reg: DstReg);
211 if (!DstRBC || DstRBC == MRI.getRegClassOrRegBank(Reg: SrcReg))
212 return true;
213
214 // Otherwise match if the Src is already a regclass that is covered by the Dst
215 // RegBank.
216 return isa<const RegisterBank *>(Val: DstRBC) && MRI.getRegClassOrNull(Reg: SrcReg) &&
217 cast<const RegisterBank *>(Val: DstRBC)->covers(
218 RC: *MRI.getRegClassOrNull(Reg: SrcReg));
219}
220
221bool llvm::isTriviallyDead(const MachineInstr &MI,
222 const MachineRegisterInfo &MRI) {
223 // Instructions without side-effects are dead iff they only define dead regs.
224 // This function is hot and this loop returns early in the common case,
225 // so only perform additional checks before this if absolutely necessary.
226 for (const auto &MO : MI.all_defs()) {
227 Register Reg = MO.getReg();
228 if (Reg.isPhysical() || !MRI.use_nodbg_empty(RegNo: Reg))
229 return false;
230 }
231 return MI.wouldBeTriviallyDead();
232}
233
234static void reportGISelDiagnostic(DiagnosticSeverity Severity,
235 MachineFunction &MF,
236 MachineOptimizationRemarkEmitter &MORE,
237 MachineOptimizationRemarkMissed &R) {
238 bool IsGlobalISelAbortEnabled =
239 MF.getTarget().Options.GlobalISelAbort == GlobalISelAbortMode::Enable;
240 bool IsFatal = Severity == DS_Error && IsGlobalISelAbortEnabled;
241 // Print the function name explicitly if we don't have a debug location (which
242 // makes the diagnostic less useful) or if we're going to emit a raw error.
243 if (!R.getLocation().isValid() || IsFatal)
244 R << (" (in function: " + MF.getName() + ")").str();
245
246 if (IsFatal)
247 reportFatalUsageError(reason: Twine(R.getMsg()));
248 else
249 MORE.emit(OptDiag&: R);
250}
251
252void llvm::reportGISelWarning(MachineFunction &MF,
253 MachineOptimizationRemarkEmitter &MORE,
254 MachineOptimizationRemarkMissed &R) {
255 reportGISelDiagnostic(Severity: DS_Warning, MF, MORE, R);
256}
257
258void llvm::reportGISelFailure(MachineFunction &MF,
259 MachineOptimizationRemarkEmitter &MORE,
260 MachineOptimizationRemarkMissed &R) {
261 MF.getProperties().setFailedISel();
262 reportGISelDiagnostic(Severity: DS_Error, MF, MORE, R);
263}
264
265void llvm::reportGISelFailure(MachineFunction &MF,
266 MachineOptimizationRemarkEmitter &MORE,
267 const char *PassName, StringRef Msg,
268 const MachineInstr &MI) {
269 MachineOptimizationRemarkMissed R(PassName, "GISelFailure: ",
270 MI.getDebugLoc(), MI.getParent());
271 R << Msg;
272 // Printing MI is expensive; only do it if expensive remarks are enabled.
273 if (MF.getTarget().Options.GlobalISelAbort == GlobalISelAbortMode::Enable ||
274 MORE.allowExtraAnalysis(PassName))
275 R << ": " << ore::MNV("Inst", MI);
276 reportGISelFailure(MF, MORE, R);
277}
278
279unsigned llvm::getInverseGMinMaxOpcode(unsigned MinMaxOpc) {
280 switch (MinMaxOpc) {
281 case TargetOpcode::G_SMIN:
282 return TargetOpcode::G_SMAX;
283 case TargetOpcode::G_SMAX:
284 return TargetOpcode::G_SMIN;
285 case TargetOpcode::G_UMIN:
286 return TargetOpcode::G_UMAX;
287 case TargetOpcode::G_UMAX:
288 return TargetOpcode::G_UMIN;
289 default:
290 llvm_unreachable("unrecognized opcode");
291 }
292}
293
294std::optional<APInt> llvm::getIConstantVRegVal(Register VReg,
295 const MachineRegisterInfo &MRI) {
296 std::optional<ValueAndVReg> ValAndVReg = getIConstantVRegValWithLookThrough(
297 VReg, MRI, /*LookThroughInstrs*/ false);
298 assert((!ValAndVReg || ValAndVReg->VReg == VReg) &&
299 "Value found while looking through instrs");
300 if (!ValAndVReg)
301 return std::nullopt;
302 return ValAndVReg->Value;
303}
304
305const APInt &llvm::getIConstantFromReg(Register Reg,
306 const MachineRegisterInfo &MRI) {
307 MachineInstr *Const = MRI.getVRegDef(Reg);
308 assert((Const && Const->getOpcode() == TargetOpcode::G_CONSTANT) &&
309 "expected a G_CONSTANT on Reg");
310 return Const->getOperand(i: 1).getCImm()->getValue();
311}
312
313std::optional<int64_t>
314llvm::getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI) {
315 std::optional<APInt> Val = getIConstantVRegVal(VReg, MRI);
316 if (Val && Val->getBitWidth() <= 64)
317 return Val->getSExtValue();
318 return std::nullopt;
319}
320
321namespace {
322
323// This function is used in many places, and as such, it has some
324// micro-optimizations to try and make it as fast as it can be.
325//
326// - We use template arguments to avoid an indirect call caused by passing a
327// function_ref/std::function
328// - GetAPCstValue does not return std::optional<APInt> as that's expensive.
329// Instead it returns true/false and places the result in a pre-constructed
330// APInt.
331//
332// Please change this function carefully and benchmark your changes.
333template <bool (*IsConstantOpcode)(const MachineInstr *),
334 bool (*GetAPCstValue)(const MachineInstr *MI, APInt &)>
335std::optional<ValueAndVReg>
336getConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI,
337 bool LookThroughInstrs = true,
338 bool LookThroughAnyExt = false) {
339 SmallVector<std::pair<unsigned, unsigned>, 4> SeenOpcodes;
340 MachineInstr *MI;
341
342 while ((MI = MRI.getVRegDef(Reg: VReg)) && !IsConstantOpcode(MI) &&
343 LookThroughInstrs) {
344 switch (MI->getOpcode()) {
345 case TargetOpcode::G_ANYEXT:
346 if (!LookThroughAnyExt)
347 return std::nullopt;
348 [[fallthrough]];
349 case TargetOpcode::G_TRUNC:
350 case TargetOpcode::G_SEXT:
351 case TargetOpcode::G_ZEXT:
352 SeenOpcodes.push_back(Elt: std::make_pair(
353 x: MI->getOpcode(),
354 y: MRI.getType(Reg: MI->getOperand(i: 0).getReg()).getSizeInBits()));
355 VReg = MI->getOperand(i: 1).getReg();
356 break;
357 case TargetOpcode::COPY:
358 VReg = MI->getOperand(i: 1).getReg();
359 if (VReg.isPhysical())
360 return std::nullopt;
361 break;
362 case TargetOpcode::G_INTTOPTR:
363 VReg = MI->getOperand(i: 1).getReg();
364 break;
365 default:
366 return std::nullopt;
367 }
368 }
369 if (!MI || !IsConstantOpcode(MI))
370 return std::nullopt;
371
372 APInt Val;
373 if (!GetAPCstValue(MI, Val))
374 return std::nullopt;
375 for (auto &Pair : reverse(C&: SeenOpcodes)) {
376 switch (Pair.first) {
377 case TargetOpcode::G_TRUNC:
378 Val = Val.trunc(width: Pair.second);
379 break;
380 case TargetOpcode::G_ANYEXT:
381 case TargetOpcode::G_SEXT:
382 Val = Val.sext(width: Pair.second);
383 break;
384 case TargetOpcode::G_ZEXT:
385 Val = Val.zext(width: Pair.second);
386 break;
387 }
388 }
389
390 return ValueAndVReg{.Value: std::move(Val), .VReg: VReg};
391}
392
393bool isIConstant(const MachineInstr *MI) {
394 if (!MI)
395 return false;
396 return MI->getOpcode() == TargetOpcode::G_CONSTANT;
397}
398
399bool isFConstant(const MachineInstr *MI) {
400 if (!MI)
401 return false;
402 return MI->getOpcode() == TargetOpcode::G_FCONSTANT;
403}
404
405bool isAnyConstant(const MachineInstr *MI) {
406 if (!MI)
407 return false;
408 unsigned Opc = MI->getOpcode();
409 return Opc == TargetOpcode::G_CONSTANT || Opc == TargetOpcode::G_FCONSTANT;
410}
411
412bool getCImmAsAPInt(const MachineInstr *MI, APInt &Result) {
413 const MachineOperand &CstVal = MI->getOperand(i: 1);
414 if (!CstVal.isCImm())
415 return false;
416 Result = CstVal.getCImm()->getValue();
417 return true;
418}
419
420bool getCImmOrFPImmAsAPInt(const MachineInstr *MI, APInt &Result) {
421 const MachineOperand &CstVal = MI->getOperand(i: 1);
422 if (CstVal.isCImm())
423 Result = CstVal.getCImm()->getValue();
424 else if (CstVal.isFPImm())
425 Result = CstVal.getFPImm()->getValueAPF().bitcastToAPInt();
426 else
427 return false;
428 return true;
429}
430
431} // end anonymous namespace
432
433std::optional<ValueAndVReg> llvm::getIConstantVRegValWithLookThrough(
434 Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs) {
435 return getConstantVRegValWithLookThrough<isIConstant, getCImmAsAPInt>(
436 VReg, MRI, LookThroughInstrs);
437}
438
439std::optional<ValueAndVReg> llvm::getAnyConstantVRegValWithLookThrough(
440 Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs,
441 bool LookThroughAnyExt) {
442 return getConstantVRegValWithLookThrough<isAnyConstant,
443 getCImmOrFPImmAsAPInt>(
444 VReg, MRI, LookThroughInstrs, LookThroughAnyExt);
445}
446
447std::optional<FPValueAndVReg> llvm::getFConstantVRegValWithLookThrough(
448 Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs) {
449 auto Reg =
450 getConstantVRegValWithLookThrough<isFConstant, getCImmOrFPImmAsAPInt>(
451 VReg, MRI, LookThroughInstrs);
452 if (!Reg)
453 return std::nullopt;
454
455 APFloat FloatVal(getFltSemanticForLLT(Ty: LLT::scalar(SizeInBits: Reg->Value.getBitWidth())),
456 Reg->Value);
457 return FPValueAndVReg{.Value: FloatVal, .VReg: Reg->VReg};
458}
459
460const ConstantFP *
461llvm::getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI) {
462 MachineInstr *MI = MRI.getVRegDef(Reg: VReg);
463 if (TargetOpcode::G_FCONSTANT != MI->getOpcode())
464 return nullptr;
465 return MI->getOperand(i: 1).getFPImm();
466}
467
468std::optional<DefinitionAndSourceRegister>
469llvm::getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI) {
470 Register DefSrcReg = Reg;
471 // This assumes that the code is in SSA form, so there should only be one
472 // definition.
473 auto DefIt = MRI.def_begin(RegNo: Reg);
474 if (DefIt == MRI.def_end())
475 return {};
476 MachineOperand &DefOpnd = *DefIt;
477 MachineInstr *DefMI = DefOpnd.getParent();
478 auto DstTy = MRI.getType(Reg: DefOpnd.getReg());
479 if (!DstTy.isValid())
480 return std::nullopt;
481 unsigned Opc = DefMI->getOpcode();
482 while (Opc == TargetOpcode::COPY || isPreISelGenericOptimizationHint(Opcode: Opc)) {
483 Register SrcReg = DefMI->getOperand(i: 1).getReg();
484 auto SrcTy = MRI.getType(Reg: SrcReg);
485 if (!SrcTy.isValid())
486 break;
487 DefMI = MRI.getVRegDef(Reg: SrcReg);
488 DefSrcReg = SrcReg;
489 Opc = DefMI->getOpcode();
490 }
491 return DefinitionAndSourceRegister{.MI: DefMI, .Reg: DefSrcReg};
492}
493
494MachineInstr *llvm::getDefIgnoringCopies(Register Reg,
495 const MachineRegisterInfo &MRI) {
496 std::optional<DefinitionAndSourceRegister> DefSrcReg =
497 getDefSrcRegIgnoringCopies(Reg, MRI);
498 return DefSrcReg ? DefSrcReg->MI : nullptr;
499}
500
501Register llvm::getSrcRegIgnoringCopies(Register Reg,
502 const MachineRegisterInfo &MRI) {
503 std::optional<DefinitionAndSourceRegister> DefSrcReg =
504 getDefSrcRegIgnoringCopies(Reg, MRI);
505 return DefSrcReg ? DefSrcReg->Reg : Register();
506}
507
508void llvm::extractParts(Register Reg, LLT Ty, int NumParts,
509 SmallVectorImpl<Register> &VRegs,
510 MachineIRBuilder &MIRBuilder,
511 MachineRegisterInfo &MRI) {
512 for (int i = 0; i < NumParts; ++i)
513 VRegs.push_back(Elt: MRI.createGenericVirtualRegister(Ty));
514 MIRBuilder.buildUnmerge(Res: VRegs, Op: Reg);
515}
516
517bool llvm::extractParts(Register Reg, LLT RegTy, LLT MainTy, LLT &LeftoverTy,
518 SmallVectorImpl<Register> &VRegs,
519 SmallVectorImpl<Register> &LeftoverRegs,
520 MachineIRBuilder &MIRBuilder,
521 MachineRegisterInfo &MRI) {
522 assert(!LeftoverTy.isValid() && "this is an out argument");
523
524 unsigned RegSize = RegTy.getSizeInBits();
525 unsigned MainSize = MainTy.getSizeInBits();
526 unsigned NumParts = RegSize / MainSize;
527 unsigned LeftoverSize = RegSize - NumParts * MainSize;
528
529 // Use an unmerge when possible.
530 if (LeftoverSize == 0) {
531 for (unsigned I = 0; I < NumParts; ++I)
532 VRegs.push_back(Elt: MRI.createGenericVirtualRegister(Ty: MainTy));
533 MIRBuilder.buildUnmerge(Res: VRegs, Op: Reg);
534 return true;
535 }
536
537 // Try to use unmerge for irregular vector split where possible
538 // For example when splitting a <6 x i32> into <4 x i32> with <2 x i32>
539 // leftover, it becomes:
540 // <2 x i32> %2, <2 x i32>%3, <2 x i32> %4 = G_UNMERGE_VALUE <6 x i32> %1
541 // <4 x i32> %5 = G_CONCAT_VECTOR <2 x i32> %2, <2 x i32> %3
542 if (RegTy.isVector() && MainTy.isVector()) {
543 unsigned RegNumElts = RegTy.getNumElements();
544 unsigned MainNumElts = MainTy.getNumElements();
545 unsigned LeftoverNumElts = RegNumElts % MainNumElts;
546 // If can unmerge to LeftoverTy, do it
547 if (MainNumElts % LeftoverNumElts == 0 &&
548 RegNumElts % LeftoverNumElts == 0 &&
549 RegTy.getScalarSizeInBits() == MainTy.getScalarSizeInBits() &&
550 LeftoverNumElts > 1) {
551 LeftoverTy = LLT::fixed_vector(NumElements: LeftoverNumElts, ScalarTy: RegTy.getElementType());
552
553 // Unmerge the SrcReg to LeftoverTy vectors
554 SmallVector<Register, 4> UnmergeValues;
555 extractParts(Reg, Ty: LeftoverTy, NumParts: RegNumElts / LeftoverNumElts, VRegs&: UnmergeValues,
556 MIRBuilder, MRI);
557
558 // Find how many LeftoverTy makes one MainTy
559 unsigned LeftoverPerMain = MainNumElts / LeftoverNumElts;
560 unsigned NumOfLeftoverVal =
561 ((RegNumElts % MainNumElts) / LeftoverNumElts);
562
563 // Create as many MainTy as possible using unmerged value
564 SmallVector<Register, 4> MergeValues;
565 for (unsigned I = 0; I < UnmergeValues.size() - NumOfLeftoverVal; I++) {
566 MergeValues.push_back(Elt: UnmergeValues[I]);
567 if (MergeValues.size() == LeftoverPerMain) {
568 VRegs.push_back(
569 Elt: MIRBuilder.buildMergeLikeInstr(Res: MainTy, Ops: MergeValues).getReg(Idx: 0));
570 MergeValues.clear();
571 }
572 }
573 // Populate LeftoverRegs with the leftovers
574 for (unsigned I = UnmergeValues.size() - NumOfLeftoverVal;
575 I < UnmergeValues.size(); I++) {
576 LeftoverRegs.push_back(Elt: UnmergeValues[I]);
577 }
578 return true;
579 }
580 }
581 // Perform irregular split. Leftover is last element of RegPieces.
582 if (MainTy.isVector()) {
583 SmallVector<Register, 8> RegPieces;
584 extractVectorParts(Reg, NumElts: MainTy.getNumElements(), VRegs&: RegPieces, MIRBuilder,
585 MRI);
586 for (unsigned i = 0; i < RegPieces.size() - 1; ++i)
587 VRegs.push_back(Elt: RegPieces[i]);
588 LeftoverRegs.push_back(Elt: RegPieces[RegPieces.size() - 1]);
589 LeftoverTy = MRI.getType(Reg: LeftoverRegs[0]);
590 return true;
591 }
592
593 LeftoverTy = LLT::scalar(SizeInBits: LeftoverSize);
594 // For irregular sizes, extract the individual parts.
595 for (unsigned I = 0; I != NumParts; ++I) {
596 Register NewReg = MRI.createGenericVirtualRegister(Ty: MainTy);
597 VRegs.push_back(Elt: NewReg);
598 MIRBuilder.buildExtract(Res: NewReg, Src: Reg, Index: MainSize * I);
599 }
600
601 for (unsigned Offset = MainSize * NumParts; Offset < RegSize;
602 Offset += LeftoverSize) {
603 Register NewReg = MRI.createGenericVirtualRegister(Ty: LeftoverTy);
604 LeftoverRegs.push_back(Elt: NewReg);
605 MIRBuilder.buildExtract(Res: NewReg, Src: Reg, Index: Offset);
606 }
607
608 return true;
609}
610
611void llvm::extractVectorParts(Register Reg, unsigned NumElts,
612 SmallVectorImpl<Register> &VRegs,
613 MachineIRBuilder &MIRBuilder,
614 MachineRegisterInfo &MRI) {
615 LLT RegTy = MRI.getType(Reg);
616 assert(RegTy.isVector() && "Expected a vector type");
617
618 LLT EltTy = RegTy.getElementType();
619 LLT NarrowTy = (NumElts == 1) ? EltTy : LLT::fixed_vector(NumElements: NumElts, ScalarTy: EltTy);
620 unsigned RegNumElts = RegTy.getNumElements();
621 unsigned LeftoverNumElts = RegNumElts % NumElts;
622 unsigned NumNarrowTyPieces = RegNumElts / NumElts;
623
624 // Perfect split without leftover
625 if (LeftoverNumElts == 0)
626 return extractParts(Reg, Ty: NarrowTy, NumParts: NumNarrowTyPieces, VRegs, MIRBuilder,
627 MRI);
628
629 // Irregular split. Provide direct access to all elements for artifact
630 // combiner using unmerge to elements. Then build vectors with NumElts
631 // elements. Remaining element(s) will be (used to build vector) Leftover.
632 SmallVector<Register, 8> Elts;
633 extractParts(Reg, Ty: EltTy, NumParts: RegNumElts, VRegs&: Elts, MIRBuilder, MRI);
634
635 unsigned Offset = 0;
636 // Requested sub-vectors of NarrowTy.
637 for (unsigned i = 0; i < NumNarrowTyPieces; ++i, Offset += NumElts) {
638 ArrayRef<Register> Pieces(&Elts[Offset], NumElts);
639 VRegs.push_back(Elt: MIRBuilder.buildMergeLikeInstr(Res: NarrowTy, Ops: Pieces).getReg(Idx: 0));
640 }
641
642 // Leftover element(s).
643 if (LeftoverNumElts == 1) {
644 VRegs.push_back(Elt: Elts[Offset]);
645 } else {
646 LLT LeftoverTy = LLT::fixed_vector(NumElements: LeftoverNumElts, ScalarTy: EltTy);
647 ArrayRef<Register> Pieces(&Elts[Offset], LeftoverNumElts);
648 VRegs.push_back(
649 Elt: MIRBuilder.buildMergeLikeInstr(Res: LeftoverTy, Ops: Pieces).getReg(Idx: 0));
650 }
651}
652
653MachineInstr *llvm::getOpcodeDef(unsigned Opcode, Register Reg,
654 const MachineRegisterInfo &MRI) {
655 MachineInstr *DefMI = getDefIgnoringCopies(Reg, MRI);
656 return DefMI && DefMI->getOpcode() == Opcode ? DefMI : nullptr;
657}
658
659APFloat llvm::getAPFloatFromSize(double Val, unsigned Size) {
660 if (Size == 32)
661 return APFloat(float(Val));
662 if (Size == 64)
663 return APFloat(Val);
664 if (Size != 16)
665 llvm_unreachable("Unsupported FPConstant size");
666 bool Ignored;
667 APFloat APF(Val);
668 APF.convert(ToSemantics: APFloat::IEEEhalf(), RM: APFloat::rmNearestTiesToEven, losesInfo: &Ignored);
669 return APF;
670}
671
672std::optional<APInt> llvm::ConstantFoldBinOp(unsigned Opcode,
673 const Register Op1,
674 const Register Op2,
675 const MachineRegisterInfo &MRI) {
676 auto MaybeOp2Cst = getAnyConstantVRegValWithLookThrough(VReg: Op2, MRI, LookThroughInstrs: false);
677 if (!MaybeOp2Cst)
678 return std::nullopt;
679
680 auto MaybeOp1Cst = getAnyConstantVRegValWithLookThrough(VReg: Op1, MRI, LookThroughInstrs: false);
681 if (!MaybeOp1Cst)
682 return std::nullopt;
683
684 const APInt &C1 = MaybeOp1Cst->Value;
685 const APInt &C2 = MaybeOp2Cst->Value;
686 switch (Opcode) {
687 default:
688 break;
689 case TargetOpcode::G_ADD:
690 return C1 + C2;
691 case TargetOpcode::G_PTR_ADD:
692 // Types can be of different width here.
693 // Result needs to be the same width as C1, so trunc or sext C2.
694 return C1 + C2.sextOrTrunc(width: C1.getBitWidth());
695 case TargetOpcode::G_AND:
696 return C1 & C2;
697 case TargetOpcode::G_ASHR:
698 return C1.ashr(ShiftAmt: C2);
699 case TargetOpcode::G_LSHR:
700 return C1.lshr(ShiftAmt: C2);
701 case TargetOpcode::G_MUL:
702 return C1 * C2;
703 case TargetOpcode::G_OR:
704 return C1 | C2;
705 case TargetOpcode::G_SHL:
706 return C1 << C2;
707 case TargetOpcode::G_SUB:
708 return C1 - C2;
709 case TargetOpcode::G_XOR:
710 return C1 ^ C2;
711 case TargetOpcode::G_UDIV:
712 if (!C2.getBoolValue())
713 break;
714 return C1.udiv(RHS: C2);
715 case TargetOpcode::G_SDIV:
716 if (!C2.getBoolValue())
717 break;
718 return C1.sdiv(RHS: C2);
719 case TargetOpcode::G_UREM:
720 if (!C2.getBoolValue())
721 break;
722 return C1.urem(RHS: C2);
723 case TargetOpcode::G_SREM:
724 if (!C2.getBoolValue())
725 break;
726 return C1.srem(RHS: C2);
727 case TargetOpcode::G_SMIN:
728 return APIntOps::smin(A: C1, B: C2);
729 case TargetOpcode::G_SMAX:
730 return APIntOps::smax(A: C1, B: C2);
731 case TargetOpcode::G_UMIN:
732 return APIntOps::umin(A: C1, B: C2);
733 case TargetOpcode::G_UMAX:
734 return APIntOps::umax(A: C1, B: C2);
735 }
736
737 return std::nullopt;
738}
739
740std::optional<APFloat>
741llvm::ConstantFoldFPBinOp(unsigned Opcode, const Register Op1,
742 const Register Op2, const MachineRegisterInfo &MRI) {
743 const ConstantFP *Op2Cst = getConstantFPVRegVal(VReg: Op2, MRI);
744 if (!Op2Cst)
745 return std::nullopt;
746
747 const ConstantFP *Op1Cst = getConstantFPVRegVal(VReg: Op1, MRI);
748 if (!Op1Cst)
749 return std::nullopt;
750
751 APFloat C1 = Op1Cst->getValueAPF();
752 const APFloat &C2 = Op2Cst->getValueAPF();
753 switch (Opcode) {
754 case TargetOpcode::G_FADD:
755 C1.add(RHS: C2, RM: APFloat::rmNearestTiesToEven);
756 return C1;
757 case TargetOpcode::G_FSUB:
758 C1.subtract(RHS: C2, RM: APFloat::rmNearestTiesToEven);
759 return C1;
760 case TargetOpcode::G_FMUL:
761 C1.multiply(RHS: C2, RM: APFloat::rmNearestTiesToEven);
762 return C1;
763 case TargetOpcode::G_FDIV:
764 C1.divide(RHS: C2, RM: APFloat::rmNearestTiesToEven);
765 return C1;
766 case TargetOpcode::G_FREM:
767 C1.mod(RHS: C2);
768 return C1;
769 case TargetOpcode::G_FCOPYSIGN:
770 C1.copySign(RHS: C2);
771 return C1;
772 case TargetOpcode::G_FMINNUM:
773 if (C1.isSignaling() || C2.isSignaling())
774 return std::nullopt;
775 return minnum(A: C1, B: C2);
776 case TargetOpcode::G_FMAXNUM:
777 if (C1.isSignaling() || C2.isSignaling())
778 return std::nullopt;
779 return maxnum(A: C1, B: C2);
780 case TargetOpcode::G_FMINIMUM:
781 return minimum(A: C1, B: C2);
782 case TargetOpcode::G_FMAXIMUM:
783 return maximum(A: C1, B: C2);
784 case TargetOpcode::G_FMINNUM_IEEE:
785 case TargetOpcode::G_FMAXNUM_IEEE:
786 // FIXME: These operations were unfortunately named. fminnum/fmaxnum do not
787 // follow the IEEE behavior for signaling nans and follow libm's fmin/fmax,
788 // and currently there isn't a nice wrapper in APFloat for the version with
789 // correct snan handling.
790 break;
791 default:
792 break;
793 }
794
795 return std::nullopt;
796}
797
798SmallVector<APInt>
799llvm::ConstantFoldVectorBinop(unsigned Opcode, const Register Op1,
800 const Register Op2,
801 const MachineRegisterInfo &MRI) {
802 auto *SrcVec2 = getOpcodeDef<GBuildVector>(Reg: Op2, MRI);
803 if (!SrcVec2)
804 return SmallVector<APInt>();
805
806 auto *SrcVec1 = getOpcodeDef<GBuildVector>(Reg: Op1, MRI);
807 if (!SrcVec1)
808 return SmallVector<APInt>();
809
810 SmallVector<APInt> FoldedElements;
811 for (unsigned Idx = 0, E = SrcVec1->getNumSources(); Idx < E; ++Idx) {
812 auto MaybeCst = ConstantFoldBinOp(Opcode, Op1: SrcVec1->getSourceReg(I: Idx),
813 Op2: SrcVec2->getSourceReg(I: Idx), MRI);
814 if (!MaybeCst)
815 return SmallVector<APInt>();
816 FoldedElements.push_back(Elt: *MaybeCst);
817 }
818 return FoldedElements;
819}
820
821bool llvm::isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI,
822 bool SNaN) {
823 const MachineInstr *DefMI = MRI.getVRegDef(Reg: Val);
824 if (!DefMI)
825 return false;
826
827 if (DefMI->getFlag(Flag: MachineInstr::FmNoNans))
828 return true;
829
830 // If the value is a constant, we can obviously see if it is a NaN or not.
831 if (const ConstantFP *FPVal = getConstantFPVRegVal(VReg: Val, MRI)) {
832 return !FPVal->getValueAPF().isNaN() ||
833 (SNaN && !FPVal->getValueAPF().isSignaling());
834 }
835
836 if (DefMI->getOpcode() == TargetOpcode::G_BUILD_VECTOR) {
837 for (const auto &Op : DefMI->uses())
838 if (!isKnownNeverNaN(Val: Op.getReg(), MRI, SNaN))
839 return false;
840 return true;
841 }
842
843 switch (DefMI->getOpcode()) {
844 default:
845 break;
846 case TargetOpcode::G_FADD:
847 case TargetOpcode::G_FSUB:
848 case TargetOpcode::G_FMUL:
849 case TargetOpcode::G_FDIV:
850 case TargetOpcode::G_FREM:
851 case TargetOpcode::G_FSIN:
852 case TargetOpcode::G_FCOS:
853 case TargetOpcode::G_FTAN:
854 case TargetOpcode::G_FACOS:
855 case TargetOpcode::G_FASIN:
856 case TargetOpcode::G_FATAN:
857 case TargetOpcode::G_FATAN2:
858 case TargetOpcode::G_FCOSH:
859 case TargetOpcode::G_FSINH:
860 case TargetOpcode::G_FTANH:
861 case TargetOpcode::G_FMA:
862 case TargetOpcode::G_FMAD:
863 if (SNaN)
864 return true;
865
866 // TODO: Need isKnownNeverInfinity
867 return false;
868 case TargetOpcode::G_FMINNUM_IEEE:
869 case TargetOpcode::G_FMAXNUM_IEEE: {
870 if (SNaN)
871 return true;
872 // This can return a NaN if either operand is an sNaN, or if both operands
873 // are NaN.
874 return (isKnownNeverNaN(Val: DefMI->getOperand(i: 1).getReg(), MRI) &&
875 isKnownNeverSNaN(Val: DefMI->getOperand(i: 2).getReg(), MRI)) ||
876 (isKnownNeverSNaN(Val: DefMI->getOperand(i: 1).getReg(), MRI) &&
877 isKnownNeverNaN(Val: DefMI->getOperand(i: 2).getReg(), MRI));
878 }
879 case TargetOpcode::G_FMINNUM:
880 case TargetOpcode::G_FMAXNUM: {
881 // Only one needs to be known not-nan, since it will be returned if the
882 // other ends up being one.
883 return isKnownNeverNaN(Val: DefMI->getOperand(i: 1).getReg(), MRI, SNaN) ||
884 isKnownNeverNaN(Val: DefMI->getOperand(i: 2).getReg(), MRI, SNaN);
885 }
886 }
887
888 if (SNaN) {
889 // FP operations quiet. For now, just handle the ones inserted during
890 // legalization.
891 switch (DefMI->getOpcode()) {
892 case TargetOpcode::G_FPEXT:
893 case TargetOpcode::G_FPTRUNC:
894 case TargetOpcode::G_FCANONICALIZE:
895 return true;
896 default:
897 return false;
898 }
899 }
900
901 return false;
902}
903
904Align llvm::inferAlignFromPtrInfo(MachineFunction &MF,
905 const MachinePointerInfo &MPO) {
906 auto PSV = dyn_cast_if_present<const PseudoSourceValue *>(Val: MPO.V);
907 if (auto FSPV = dyn_cast_or_null<FixedStackPseudoSourceValue>(Val: PSV)) {
908 MachineFrameInfo &MFI = MF.getFrameInfo();
909 return commonAlignment(A: MFI.getObjectAlign(ObjectIdx: FSPV->getFrameIndex()),
910 Offset: MPO.Offset);
911 }
912
913 if (const Value *V = dyn_cast_if_present<const Value *>(Val: MPO.V)) {
914 const Module *M = MF.getFunction().getParent();
915 return V->getPointerAlignment(DL: M->getDataLayout());
916 }
917
918 return Align(1);
919}
920
921Register llvm::getFunctionLiveInPhysReg(MachineFunction &MF,
922 const TargetInstrInfo &TII,
923 MCRegister PhysReg,
924 const TargetRegisterClass &RC,
925 const DebugLoc &DL, LLT RegTy) {
926 MachineBasicBlock &EntryMBB = MF.front();
927 MachineRegisterInfo &MRI = MF.getRegInfo();
928 Register LiveIn = MRI.getLiveInVirtReg(PReg: PhysReg);
929 if (LiveIn) {
930 MachineInstr *Def = MRI.getVRegDef(Reg: LiveIn);
931 if (Def) {
932 // FIXME: Should the verifier check this is in the entry block?
933 assert(Def->getParent() == &EntryMBB && "live-in copy not in entry block");
934 return LiveIn;
935 }
936
937 // It's possible the incoming argument register and copy was added during
938 // lowering, but later deleted due to being/becoming dead. If this happens,
939 // re-insert the copy.
940 } else {
941 // The live in register was not present, so add it.
942 LiveIn = MF.addLiveIn(PReg: PhysReg, RC: &RC);
943 if (RegTy.isValid())
944 MRI.setType(VReg: LiveIn, Ty: RegTy);
945 }
946
947 BuildMI(BB&: EntryMBB, I: EntryMBB.begin(), MIMD: DL, MCID: TII.get(Opcode: TargetOpcode::COPY), DestReg: LiveIn)
948 .addReg(RegNo: PhysReg);
949 if (!EntryMBB.isLiveIn(Reg: PhysReg))
950 EntryMBB.addLiveIn(PhysReg);
951 return LiveIn;
952}
953
954std::optional<APInt> llvm::ConstantFoldExtOp(unsigned Opcode,
955 const Register Op1, uint64_t Imm,
956 const MachineRegisterInfo &MRI) {
957 auto MaybeOp1Cst = getIConstantVRegVal(VReg: Op1, MRI);
958 if (MaybeOp1Cst) {
959 switch (Opcode) {
960 default:
961 break;
962 case TargetOpcode::G_SEXT_INREG: {
963 LLT Ty = MRI.getType(Reg: Op1);
964 return MaybeOp1Cst->trunc(width: Imm).sext(width: Ty.getScalarSizeInBits());
965 }
966 }
967 }
968 return std::nullopt;
969}
970
971std::optional<APInt> llvm::ConstantFoldCastOp(unsigned Opcode, LLT DstTy,
972 const Register Op0,
973 const MachineRegisterInfo &MRI) {
974 std::optional<APInt> Val = getIConstantVRegVal(VReg: Op0, MRI);
975 if (!Val)
976 return Val;
977
978 const unsigned DstSize = DstTy.getScalarSizeInBits();
979
980 switch (Opcode) {
981 case TargetOpcode::G_SEXT:
982 return Val->sext(width: DstSize);
983 case TargetOpcode::G_ZEXT:
984 case TargetOpcode::G_ANYEXT:
985 // TODO: DAG considers target preference when constant folding any_extend.
986 return Val->zext(width: DstSize);
987 default:
988 break;
989 }
990
991 llvm_unreachable("unexpected cast opcode to constant fold");
992}
993
994std::optional<APFloat>
995llvm::ConstantFoldIntToFloat(unsigned Opcode, LLT DstTy, Register Src,
996 const MachineRegisterInfo &MRI) {
997 assert(Opcode == TargetOpcode::G_SITOFP || Opcode == TargetOpcode::G_UITOFP);
998 if (auto MaybeSrcVal = getIConstantVRegVal(VReg: Src, MRI)) {
999 APFloat DstVal(getFltSemanticForLLT(Ty: DstTy));
1000 DstVal.convertFromAPInt(Input: *MaybeSrcVal, IsSigned: Opcode == TargetOpcode::G_SITOFP,
1001 RM: APFloat::rmNearestTiesToEven);
1002 return DstVal;
1003 }
1004 return std::nullopt;
1005}
1006
1007std::optional<SmallVector<unsigned>>
1008llvm::ConstantFoldCountZeros(Register Src, const MachineRegisterInfo &MRI,
1009 std::function<unsigned(APInt)> CB) {
1010 LLT Ty = MRI.getType(Reg: Src);
1011 SmallVector<unsigned> FoldedCTLZs;
1012 auto tryFoldScalar = [&](Register R) -> std::optional<unsigned> {
1013 auto MaybeCst = getIConstantVRegVal(VReg: R, MRI);
1014 if (!MaybeCst)
1015 return std::nullopt;
1016 return CB(*MaybeCst);
1017 };
1018 if (Ty.isVector()) {
1019 // Try to constant fold each element.
1020 auto *BV = getOpcodeDef<GBuildVector>(Reg: Src, MRI);
1021 if (!BV)
1022 return std::nullopt;
1023 for (unsigned SrcIdx = 0; SrcIdx < BV->getNumSources(); ++SrcIdx) {
1024 if (auto MaybeFold = tryFoldScalar(BV->getSourceReg(I: SrcIdx))) {
1025 FoldedCTLZs.emplace_back(Args&: *MaybeFold);
1026 continue;
1027 }
1028 return std::nullopt;
1029 }
1030 return FoldedCTLZs;
1031 }
1032 if (auto MaybeCst = tryFoldScalar(Src)) {
1033 FoldedCTLZs.emplace_back(Args&: *MaybeCst);
1034 return FoldedCTLZs;
1035 }
1036 return std::nullopt;
1037}
1038
1039std::optional<SmallVector<APInt>>
1040llvm::ConstantFoldICmp(unsigned Pred, const Register Op1, const Register Op2,
1041 unsigned DstScalarSizeInBits, unsigned ExtOp,
1042 const MachineRegisterInfo &MRI) {
1043 assert(ExtOp == TargetOpcode::G_SEXT || ExtOp == TargetOpcode::G_ZEXT ||
1044 ExtOp == TargetOpcode::G_ANYEXT);
1045
1046 const LLT Ty = MRI.getType(Reg: Op1);
1047
1048 auto GetICmpResultCst = [&](bool IsTrue) {
1049 if (IsTrue)
1050 return ExtOp == TargetOpcode::G_SEXT
1051 ? APInt::getAllOnes(numBits: DstScalarSizeInBits)
1052 : APInt::getOneBitSet(numBits: DstScalarSizeInBits, BitNo: 0);
1053 return APInt::getZero(numBits: DstScalarSizeInBits);
1054 };
1055
1056 auto TryFoldScalar = [&](Register LHS, Register RHS) -> std::optional<APInt> {
1057 auto RHSCst = getIConstantVRegVal(VReg: RHS, MRI);
1058 if (!RHSCst)
1059 return std::nullopt;
1060 auto LHSCst = getIConstantVRegVal(VReg: LHS, MRI);
1061 if (!LHSCst)
1062 return std::nullopt;
1063
1064 switch (Pred) {
1065 case CmpInst::Predicate::ICMP_EQ:
1066 return GetICmpResultCst(LHSCst->eq(RHS: *RHSCst));
1067 case CmpInst::Predicate::ICMP_NE:
1068 return GetICmpResultCst(LHSCst->ne(RHS: *RHSCst));
1069 case CmpInst::Predicate::ICMP_UGT:
1070 return GetICmpResultCst(LHSCst->ugt(RHS: *RHSCst));
1071 case CmpInst::Predicate::ICMP_UGE:
1072 return GetICmpResultCst(LHSCst->uge(RHS: *RHSCst));
1073 case CmpInst::Predicate::ICMP_ULT:
1074 return GetICmpResultCst(LHSCst->ult(RHS: *RHSCst));
1075 case CmpInst::Predicate::ICMP_ULE:
1076 return GetICmpResultCst(LHSCst->ule(RHS: *RHSCst));
1077 case CmpInst::Predicate::ICMP_SGT:
1078 return GetICmpResultCst(LHSCst->sgt(RHS: *RHSCst));
1079 case CmpInst::Predicate::ICMP_SGE:
1080 return GetICmpResultCst(LHSCst->sge(RHS: *RHSCst));
1081 case CmpInst::Predicate::ICMP_SLT:
1082 return GetICmpResultCst(LHSCst->slt(RHS: *RHSCst));
1083 case CmpInst::Predicate::ICMP_SLE:
1084 return GetICmpResultCst(LHSCst->sle(RHS: *RHSCst));
1085 default:
1086 return std::nullopt;
1087 }
1088 };
1089
1090 SmallVector<APInt> FoldedICmps;
1091
1092 if (Ty.isVector()) {
1093 // Try to constant fold each element.
1094 auto *BV1 = getOpcodeDef<GBuildVector>(Reg: Op1, MRI);
1095 auto *BV2 = getOpcodeDef<GBuildVector>(Reg: Op2, MRI);
1096 if (!BV1 || !BV2)
1097 return std::nullopt;
1098 assert(BV1->getNumSources() == BV2->getNumSources() && "Invalid vectors");
1099 for (unsigned I = 0; I < BV1->getNumSources(); ++I) {
1100 if (auto MaybeFold =
1101 TryFoldScalar(BV1->getSourceReg(I), BV2->getSourceReg(I))) {
1102 FoldedICmps.emplace_back(Args&: *MaybeFold);
1103 continue;
1104 }
1105 return std::nullopt;
1106 }
1107 return FoldedICmps;
1108 }
1109
1110 if (auto MaybeCst = TryFoldScalar(Op1, Op2)) {
1111 FoldedICmps.emplace_back(Args&: *MaybeCst);
1112 return FoldedICmps;
1113 }
1114
1115 return std::nullopt;
1116}
1117
1118bool llvm::isKnownToBeAPowerOfTwo(Register Reg, const MachineRegisterInfo &MRI,
1119 GISelValueTracking *VT) {
1120 std::optional<DefinitionAndSourceRegister> DefSrcReg =
1121 getDefSrcRegIgnoringCopies(Reg, MRI);
1122 if (!DefSrcReg)
1123 return false;
1124
1125 const MachineInstr &MI = *DefSrcReg->MI;
1126 const LLT Ty = MRI.getType(Reg);
1127
1128 switch (MI.getOpcode()) {
1129 case TargetOpcode::G_CONSTANT: {
1130 unsigned BitWidth = Ty.getScalarSizeInBits();
1131 const ConstantInt *CI = MI.getOperand(i: 1).getCImm();
1132 return CI->getValue().zextOrTrunc(width: BitWidth).isPowerOf2();
1133 }
1134 case TargetOpcode::G_SHL: {
1135 // A left-shift of a constant one will have exactly one bit set because
1136 // shifting the bit off the end is undefined.
1137
1138 // TODO: Constant splat
1139 if (auto ConstLHS = getIConstantVRegVal(VReg: MI.getOperand(i: 1).getReg(), MRI)) {
1140 if (*ConstLHS == 1)
1141 return true;
1142 }
1143
1144 break;
1145 }
1146 case TargetOpcode::G_LSHR: {
1147 if (auto ConstLHS = getIConstantVRegVal(VReg: MI.getOperand(i: 1).getReg(), MRI)) {
1148 if (ConstLHS->isSignMask())
1149 return true;
1150 }
1151
1152 break;
1153 }
1154 case TargetOpcode::G_BUILD_VECTOR: {
1155 // TODO: Probably should have a recursion depth guard since you could have
1156 // bitcasted vector elements.
1157 for (const MachineOperand &MO : llvm::drop_begin(RangeOrContainer: MI.operands()))
1158 if (!isKnownToBeAPowerOfTwo(Reg: MO.getReg(), MRI, VT))
1159 return false;
1160
1161 return true;
1162 }
1163 case TargetOpcode::G_BUILD_VECTOR_TRUNC: {
1164 // Only handle constants since we would need to know if number of leading
1165 // zeros is greater than the truncation amount.
1166 const unsigned BitWidth = Ty.getScalarSizeInBits();
1167 for (const MachineOperand &MO : llvm::drop_begin(RangeOrContainer: MI.operands())) {
1168 auto Const = getIConstantVRegVal(VReg: MO.getReg(), MRI);
1169 if (!Const || !Const->zextOrTrunc(width: BitWidth).isPowerOf2())
1170 return false;
1171 }
1172
1173 return true;
1174 }
1175 default:
1176 break;
1177 }
1178
1179 if (!VT)
1180 return false;
1181
1182 // More could be done here, though the above checks are enough
1183 // to handle some common cases.
1184
1185 // Fall back to computeKnownBits to catch other known cases.
1186 KnownBits Known = VT->getKnownBits(R: Reg);
1187 return (Known.countMaxPopulation() == 1) && (Known.countMinPopulation() == 1);
1188}
1189
1190void llvm::getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU) {
1191 AU.addPreserved<StackProtector>();
1192}
1193
1194LLT llvm::getLCMType(LLT OrigTy, LLT TargetTy) {
1195 if (OrigTy.getSizeInBits() == TargetTy.getSizeInBits())
1196 return OrigTy;
1197
1198 if (OrigTy.isVector() && TargetTy.isVector()) {
1199 LLT OrigElt = OrigTy.getElementType();
1200 LLT TargetElt = TargetTy.getElementType();
1201
1202 // TODO: The docstring for this function says the intention is to use this
1203 // function to build MERGE/UNMERGE instructions. It won't be the case that
1204 // we generate a MERGE/UNMERGE between fixed and scalable vector types. We
1205 // could implement getLCMType between the two in the future if there was a
1206 // need, but it is not worth it now as this function should not be used in
1207 // that way.
1208 assert(((OrigTy.isScalableVector() && !TargetTy.isFixedVector()) ||
1209 (OrigTy.isFixedVector() && !TargetTy.isScalableVector())) &&
1210 "getLCMType not implemented between fixed and scalable vectors.");
1211
1212 if (OrigElt.getSizeInBits() == TargetElt.getSizeInBits()) {
1213 int GCDMinElts = std::gcd(m: OrigTy.getElementCount().getKnownMinValue(),
1214 n: TargetTy.getElementCount().getKnownMinValue());
1215 // Prefer the original element type.
1216 ElementCount Mul = OrigTy.getElementCount().multiplyCoefficientBy(
1217 RHS: TargetTy.getElementCount().getKnownMinValue());
1218 return LLT::vector(EC: Mul.divideCoefficientBy(RHS: GCDMinElts),
1219 ScalarTy: OrigTy.getElementType());
1220 }
1221 unsigned LCM = std::lcm(m: OrigTy.getSizeInBits().getKnownMinValue(),
1222 n: TargetTy.getSizeInBits().getKnownMinValue());
1223 return LLT::vector(
1224 EC: ElementCount::get(MinVal: LCM / OrigElt.getSizeInBits(), Scalable: OrigTy.isScalable()),
1225 ScalarTy: OrigElt);
1226 }
1227
1228 // One type is scalar, one type is vector
1229 if (OrigTy.isVector() || TargetTy.isVector()) {
1230 LLT VecTy = OrigTy.isVector() ? OrigTy : TargetTy;
1231 LLT ScalarTy = OrigTy.isVector() ? TargetTy : OrigTy;
1232 LLT EltTy = VecTy.getElementType();
1233 LLT OrigEltTy = OrigTy.isVector() ? OrigTy.getElementType() : OrigTy;
1234
1235 // Prefer scalar type from OrigTy.
1236 if (EltTy.getSizeInBits() == ScalarTy.getSizeInBits())
1237 return LLT::vector(EC: VecTy.getElementCount(), ScalarTy: OrigEltTy);
1238
1239 // Different size scalars. Create vector with the same total size.
1240 // LCM will take fixed/scalable from VecTy.
1241 unsigned LCM = std::lcm(m: EltTy.getSizeInBits().getFixedValue() *
1242 VecTy.getElementCount().getKnownMinValue(),
1243 n: ScalarTy.getSizeInBits().getFixedValue());
1244 // Prefer type from OrigTy
1245 return LLT::vector(EC: ElementCount::get(MinVal: LCM / OrigEltTy.getSizeInBits(),
1246 Scalable: VecTy.getElementCount().isScalable()),
1247 ScalarTy: OrigEltTy);
1248 }
1249
1250 // At this point, both types are scalars of different size
1251 unsigned LCM = std::lcm(m: OrigTy.getSizeInBits().getFixedValue(),
1252 n: TargetTy.getSizeInBits().getFixedValue());
1253 // Preserve pointer types.
1254 if (LCM == OrigTy.getSizeInBits())
1255 return OrigTy;
1256 if (LCM == TargetTy.getSizeInBits())
1257 return TargetTy;
1258 return LLT::scalar(SizeInBits: LCM);
1259}
1260
1261LLT llvm::getCoverTy(LLT OrigTy, LLT TargetTy) {
1262
1263 if ((OrigTy.isScalableVector() && TargetTy.isFixedVector()) ||
1264 (OrigTy.isFixedVector() && TargetTy.isScalableVector()))
1265 llvm_unreachable(
1266 "getCoverTy not implemented between fixed and scalable vectors.");
1267
1268 if (!OrigTy.isVector() || !TargetTy.isVector() || OrigTy == TargetTy ||
1269 (OrigTy.getScalarSizeInBits() != TargetTy.getScalarSizeInBits()))
1270 return getLCMType(OrigTy, TargetTy);
1271
1272 unsigned OrigTyNumElts = OrigTy.getElementCount().getKnownMinValue();
1273 unsigned TargetTyNumElts = TargetTy.getElementCount().getKnownMinValue();
1274 if (OrigTyNumElts % TargetTyNumElts == 0)
1275 return OrigTy;
1276
1277 unsigned NumElts = alignTo(Value: OrigTyNumElts, Align: TargetTyNumElts);
1278 return LLT::scalarOrVector(EC: ElementCount::getFixed(MinVal: NumElts),
1279 ScalarTy: OrigTy.getElementType());
1280}
1281
1282LLT llvm::getGCDType(LLT OrigTy, LLT TargetTy) {
1283 if (OrigTy.getSizeInBits() == TargetTy.getSizeInBits())
1284 return OrigTy;
1285
1286 if (OrigTy.isVector() && TargetTy.isVector()) {
1287 LLT OrigElt = OrigTy.getElementType();
1288
1289 // TODO: The docstring for this function says the intention is to use this
1290 // function to build MERGE/UNMERGE instructions. It won't be the case that
1291 // we generate a MERGE/UNMERGE between fixed and scalable vector types. We
1292 // could implement getGCDType between the two in the future if there was a
1293 // need, but it is not worth it now as this function should not be used in
1294 // that way.
1295 assert(((OrigTy.isScalableVector() && !TargetTy.isFixedVector()) ||
1296 (OrigTy.isFixedVector() && !TargetTy.isScalableVector())) &&
1297 "getGCDType not implemented between fixed and scalable vectors.");
1298
1299 unsigned GCD = std::gcd(m: OrigTy.getSizeInBits().getKnownMinValue(),
1300 n: TargetTy.getSizeInBits().getKnownMinValue());
1301 if (GCD == OrigElt.getSizeInBits())
1302 return LLT::scalarOrVector(EC: ElementCount::get(MinVal: 1, Scalable: OrigTy.isScalable()),
1303 ScalarTy: OrigElt);
1304
1305 // Cannot produce original element type, but both have vscale in common.
1306 if (GCD < OrigElt.getSizeInBits())
1307 return LLT::scalarOrVector(EC: ElementCount::get(MinVal: 1, Scalable: OrigTy.isScalable()),
1308 ScalarSize: GCD);
1309
1310 return LLT::vector(
1311 EC: ElementCount::get(MinVal: GCD / OrigElt.getSizeInBits().getFixedValue(),
1312 Scalable: OrigTy.isScalable()),
1313 ScalarTy: OrigElt);
1314 }
1315
1316 // If one type is vector and the element size matches the scalar size, then
1317 // the gcd is the scalar type.
1318 if (OrigTy.isVector() &&
1319 OrigTy.getElementType().getSizeInBits() == TargetTy.getSizeInBits())
1320 return OrigTy.getElementType();
1321 if (TargetTy.isVector() &&
1322 TargetTy.getElementType().getSizeInBits() == OrigTy.getSizeInBits())
1323 return OrigTy;
1324
1325 // At this point, both types are either scalars of different type or one is a
1326 // vector and one is a scalar. If both types are scalars, the GCD type is the
1327 // GCD between the two scalar sizes. If one is vector and one is scalar, then
1328 // the GCD type is the GCD between the scalar and the vector element size.
1329 LLT OrigScalar = OrigTy.getScalarType();
1330 LLT TargetScalar = TargetTy.getScalarType();
1331 unsigned GCD = std::gcd(m: OrigScalar.getSizeInBits().getFixedValue(),
1332 n: TargetScalar.getSizeInBits().getFixedValue());
1333 return LLT::scalar(SizeInBits: GCD);
1334}
1335
1336std::optional<int> llvm::getSplatIndex(MachineInstr &MI) {
1337 assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR &&
1338 "Only G_SHUFFLE_VECTOR can have a splat index!");
1339 ArrayRef<int> Mask = MI.getOperand(i: 3).getShuffleMask();
1340 auto FirstDefinedIdx = find_if(Range&: Mask, P: [](int Elt) { return Elt >= 0; });
1341
1342 // If all elements are undefined, this shuffle can be considered a splat.
1343 // Return 0 for better potential for callers to simplify.
1344 if (FirstDefinedIdx == Mask.end())
1345 return 0;
1346
1347 // Make sure all remaining elements are either undef or the same
1348 // as the first non-undef value.
1349 int SplatValue = *FirstDefinedIdx;
1350 if (any_of(Range: make_range(x: std::next(x: FirstDefinedIdx), y: Mask.end()),
1351 P: [&SplatValue](int Elt) { return Elt >= 0 && Elt != SplatValue; }))
1352 return std::nullopt;
1353
1354 return SplatValue;
1355}
1356
1357static bool isBuildVectorOp(unsigned Opcode) {
1358 return Opcode == TargetOpcode::G_BUILD_VECTOR ||
1359 Opcode == TargetOpcode::G_BUILD_VECTOR_TRUNC;
1360}
1361
1362namespace {
1363
1364std::optional<ValueAndVReg> getAnyConstantSplat(Register VReg,
1365 const MachineRegisterInfo &MRI,
1366 bool AllowUndef) {
1367 MachineInstr *MI = getDefIgnoringCopies(Reg: VReg, MRI);
1368 if (!MI)
1369 return std::nullopt;
1370
1371 bool isConcatVectorsOp = MI->getOpcode() == TargetOpcode::G_CONCAT_VECTORS;
1372 if (!isBuildVectorOp(Opcode: MI->getOpcode()) && !isConcatVectorsOp)
1373 return std::nullopt;
1374
1375 std::optional<ValueAndVReg> SplatValAndReg;
1376 for (MachineOperand &Op : MI->uses()) {
1377 Register Element = Op.getReg();
1378 // If we have a G_CONCAT_VECTOR, we recursively look into the
1379 // vectors that we're concatenating to see if they're splats.
1380 auto ElementValAndReg =
1381 isConcatVectorsOp
1382 ? getAnyConstantSplat(VReg: Element, MRI, AllowUndef)
1383 : getAnyConstantVRegValWithLookThrough(VReg: Element, MRI, LookThroughInstrs: true, LookThroughAnyExt: true);
1384
1385 // If AllowUndef, treat undef as value that will result in a constant splat.
1386 if (!ElementValAndReg) {
1387 if (AllowUndef && isa<GImplicitDef>(Val: MRI.getVRegDef(Reg: Element)))
1388 continue;
1389 return std::nullopt;
1390 }
1391
1392 // Record splat value
1393 if (!SplatValAndReg)
1394 SplatValAndReg = ElementValAndReg;
1395
1396 // Different constant than the one already recorded, not a constant splat.
1397 if (SplatValAndReg->Value != ElementValAndReg->Value)
1398 return std::nullopt;
1399 }
1400
1401 return SplatValAndReg;
1402}
1403
1404} // end anonymous namespace
1405
1406bool llvm::isBuildVectorConstantSplat(const Register Reg,
1407 const MachineRegisterInfo &MRI,
1408 int64_t SplatValue, bool AllowUndef) {
1409 if (auto SplatValAndReg = getAnyConstantSplat(VReg: Reg, MRI, AllowUndef))
1410 return SplatValAndReg->Value.getSExtValue() == SplatValue;
1411
1412 return false;
1413}
1414
1415bool llvm::isBuildVectorConstantSplat(const Register Reg,
1416 const MachineRegisterInfo &MRI,
1417 const APInt &SplatValue,
1418 bool AllowUndef) {
1419 if (auto SplatValAndReg = getAnyConstantSplat(VReg: Reg, MRI, AllowUndef)) {
1420 if (SplatValAndReg->Value.getBitWidth() < SplatValue.getBitWidth())
1421 return APInt::isSameValue(
1422 I1: SplatValAndReg->Value.sext(width: SplatValue.getBitWidth()), I2: SplatValue);
1423 return APInt::isSameValue(
1424 I1: SplatValAndReg->Value,
1425 I2: SplatValue.sext(width: SplatValAndReg->Value.getBitWidth()));
1426 }
1427
1428 return false;
1429}
1430
1431bool llvm::isBuildVectorConstantSplat(const MachineInstr &MI,
1432 const MachineRegisterInfo &MRI,
1433 int64_t SplatValue, bool AllowUndef) {
1434 return isBuildVectorConstantSplat(Reg: MI.getOperand(i: 0).getReg(), MRI, SplatValue,
1435 AllowUndef);
1436}
1437
1438bool llvm::isBuildVectorConstantSplat(const MachineInstr &MI,
1439 const MachineRegisterInfo &MRI,
1440 const APInt &SplatValue,
1441 bool AllowUndef) {
1442 return isBuildVectorConstantSplat(Reg: MI.getOperand(i: 0).getReg(), MRI, SplatValue,
1443 AllowUndef);
1444}
1445
1446std::optional<APInt>
1447llvm::getIConstantSplatVal(const Register Reg, const MachineRegisterInfo &MRI) {
1448 if (auto SplatValAndReg =
1449 getAnyConstantSplat(VReg: Reg, MRI, /* AllowUndef */ false)) {
1450 if (std::optional<ValueAndVReg> ValAndVReg =
1451 getIConstantVRegValWithLookThrough(VReg: SplatValAndReg->VReg, MRI))
1452 return ValAndVReg->Value;
1453 }
1454
1455 return std::nullopt;
1456}
1457
1458std::optional<APInt>
1459llvm::getIConstantSplatVal(const MachineInstr &MI,
1460 const MachineRegisterInfo &MRI) {
1461 return getIConstantSplatVal(Reg: MI.getOperand(i: 0).getReg(), MRI);
1462}
1463
1464std::optional<int64_t>
1465llvm::getIConstantSplatSExtVal(const Register Reg,
1466 const MachineRegisterInfo &MRI) {
1467 if (auto SplatValAndReg =
1468 getAnyConstantSplat(VReg: Reg, MRI, /* AllowUndef */ false))
1469 return getIConstantVRegSExtVal(VReg: SplatValAndReg->VReg, MRI);
1470 return std::nullopt;
1471}
1472
1473std::optional<int64_t>
1474llvm::getIConstantSplatSExtVal(const MachineInstr &MI,
1475 const MachineRegisterInfo &MRI) {
1476 return getIConstantSplatSExtVal(Reg: MI.getOperand(i: 0).getReg(), MRI);
1477}
1478
1479std::optional<FPValueAndVReg>
1480llvm::getFConstantSplat(Register VReg, const MachineRegisterInfo &MRI,
1481 bool AllowUndef) {
1482 if (auto SplatValAndReg = getAnyConstantSplat(VReg, MRI, AllowUndef))
1483 return getFConstantVRegValWithLookThrough(VReg: SplatValAndReg->VReg, MRI);
1484 return std::nullopt;
1485}
1486
1487bool llvm::isBuildVectorAllZeros(const MachineInstr &MI,
1488 const MachineRegisterInfo &MRI,
1489 bool AllowUndef) {
1490 return isBuildVectorConstantSplat(MI, MRI, SplatValue: 0, AllowUndef);
1491}
1492
1493bool llvm::isBuildVectorAllOnes(const MachineInstr &MI,
1494 const MachineRegisterInfo &MRI,
1495 bool AllowUndef) {
1496 return isBuildVectorConstantSplat(MI, MRI, SplatValue: -1, AllowUndef);
1497}
1498
1499std::optional<RegOrConstant>
1500llvm::getVectorSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI) {
1501 unsigned Opc = MI.getOpcode();
1502 if (!isBuildVectorOp(Opcode: Opc))
1503 return std::nullopt;
1504 if (auto Splat = getIConstantSplatSExtVal(MI, MRI))
1505 return RegOrConstant(*Splat);
1506 auto Reg = MI.getOperand(i: 1).getReg();
1507 if (any_of(Range: drop_begin(RangeOrContainer: MI.operands(), N: 2),
1508 P: [&Reg](const MachineOperand &Op) { return Op.getReg() != Reg; }))
1509 return std::nullopt;
1510 return RegOrConstant(Reg);
1511}
1512
1513static bool isConstantScalar(const MachineInstr &MI,
1514 const MachineRegisterInfo &MRI,
1515 bool AllowFP = true,
1516 bool AllowOpaqueConstants = true) {
1517 switch (MI.getOpcode()) {
1518 case TargetOpcode::G_CONSTANT:
1519 case TargetOpcode::G_IMPLICIT_DEF:
1520 return true;
1521 case TargetOpcode::G_FCONSTANT:
1522 return AllowFP;
1523 case TargetOpcode::G_GLOBAL_VALUE:
1524 case TargetOpcode::G_FRAME_INDEX:
1525 case TargetOpcode::G_BLOCK_ADDR:
1526 case TargetOpcode::G_JUMP_TABLE:
1527 return AllowOpaqueConstants;
1528 default:
1529 return false;
1530 }
1531}
1532
1533bool llvm::isConstantOrConstantVector(MachineInstr &MI,
1534 const MachineRegisterInfo &MRI) {
1535 Register Def = MI.getOperand(i: 0).getReg();
1536 if (auto C = getIConstantVRegValWithLookThrough(VReg: Def, MRI))
1537 return true;
1538 GBuildVector *BV = dyn_cast<GBuildVector>(Val: &MI);
1539 if (!BV)
1540 return false;
1541 for (unsigned SrcIdx = 0; SrcIdx < BV->getNumSources(); ++SrcIdx) {
1542 if (getIConstantVRegValWithLookThrough(VReg: BV->getSourceReg(I: SrcIdx), MRI) ||
1543 getOpcodeDef<GImplicitDef>(Reg: BV->getSourceReg(I: SrcIdx), MRI))
1544 continue;
1545 return false;
1546 }
1547 return true;
1548}
1549
1550bool llvm::isConstantOrConstantVector(const MachineInstr &MI,
1551 const MachineRegisterInfo &MRI,
1552 bool AllowFP, bool AllowOpaqueConstants) {
1553 if (isConstantScalar(MI, MRI, AllowFP, AllowOpaqueConstants))
1554 return true;
1555
1556 if (!isBuildVectorOp(Opcode: MI.getOpcode()))
1557 return false;
1558
1559 const unsigned NumOps = MI.getNumOperands();
1560 for (unsigned I = 1; I != NumOps; ++I) {
1561 const MachineInstr *ElementDef = MRI.getVRegDef(Reg: MI.getOperand(i: I).getReg());
1562 if (!isConstantScalar(MI: *ElementDef, MRI, AllowFP, AllowOpaqueConstants))
1563 return false;
1564 }
1565
1566 return true;
1567}
1568
1569std::optional<APInt>
1570llvm::isConstantOrConstantSplatVector(MachineInstr &MI,
1571 const MachineRegisterInfo &MRI) {
1572 Register Def = MI.getOperand(i: 0).getReg();
1573 if (auto C = getIConstantVRegValWithLookThrough(VReg: Def, MRI))
1574 return C->Value;
1575 auto MaybeCst = getIConstantSplatSExtVal(MI, MRI);
1576 if (!MaybeCst)
1577 return std::nullopt;
1578 const unsigned ScalarSize = MRI.getType(Reg: Def).getScalarSizeInBits();
1579 return APInt(ScalarSize, *MaybeCst, true);
1580}
1581
1582std::optional<APFloat>
1583llvm::isConstantOrConstantSplatVectorFP(MachineInstr &MI,
1584 const MachineRegisterInfo &MRI) {
1585 Register Def = MI.getOperand(i: 0).getReg();
1586 if (auto FpConst = getFConstantVRegValWithLookThrough(VReg: Def, MRI))
1587 return FpConst->Value;
1588 auto MaybeCstFP = getFConstantSplat(VReg: Def, MRI, /*allowUndef=*/AllowUndef: false);
1589 if (!MaybeCstFP)
1590 return std::nullopt;
1591 return MaybeCstFP->Value;
1592}
1593
1594bool llvm::isNullOrNullSplat(const MachineInstr &MI,
1595 const MachineRegisterInfo &MRI, bool AllowUndefs) {
1596 switch (MI.getOpcode()) {
1597 case TargetOpcode::G_IMPLICIT_DEF:
1598 return AllowUndefs;
1599 case TargetOpcode::G_CONSTANT:
1600 return MI.getOperand(i: 1).getCImm()->isNullValue();
1601 case TargetOpcode::G_FCONSTANT: {
1602 const ConstantFP *FPImm = MI.getOperand(i: 1).getFPImm();
1603 return FPImm->isZero() && !FPImm->isNegative();
1604 }
1605 default:
1606 if (!AllowUndefs) // TODO: isBuildVectorAllZeros assumes undef is OK already
1607 return false;
1608 return isBuildVectorAllZeros(MI, MRI);
1609 }
1610}
1611
1612bool llvm::isAllOnesOrAllOnesSplat(const MachineInstr &MI,
1613 const MachineRegisterInfo &MRI,
1614 bool AllowUndefs) {
1615 switch (MI.getOpcode()) {
1616 case TargetOpcode::G_IMPLICIT_DEF:
1617 return AllowUndefs;
1618 case TargetOpcode::G_CONSTANT:
1619 return MI.getOperand(i: 1).getCImm()->isAllOnesValue();
1620 default:
1621 if (!AllowUndefs) // TODO: isBuildVectorAllOnes assumes undef is OK already
1622 return false;
1623 return isBuildVectorAllOnes(MI, MRI);
1624 }
1625}
1626
1627bool llvm::matchUnaryPredicate(
1628 const MachineRegisterInfo &MRI, Register Reg,
1629 std::function<bool(const Constant *ConstVal)> Match, bool AllowUndefs) {
1630
1631 const MachineInstr *Def = getDefIgnoringCopies(Reg, MRI);
1632 if (AllowUndefs && Def->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
1633 return Match(nullptr);
1634
1635 // TODO: Also handle fconstant
1636 if (Def->getOpcode() == TargetOpcode::G_CONSTANT)
1637 return Match(Def->getOperand(i: 1).getCImm());
1638
1639 if (Def->getOpcode() != TargetOpcode::G_BUILD_VECTOR)
1640 return false;
1641
1642 for (unsigned I = 1, E = Def->getNumOperands(); I != E; ++I) {
1643 Register SrcElt = Def->getOperand(i: I).getReg();
1644 const MachineInstr *SrcDef = getDefIgnoringCopies(Reg: SrcElt, MRI);
1645 if (AllowUndefs && SrcDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF) {
1646 if (!Match(nullptr))
1647 return false;
1648 continue;
1649 }
1650
1651 if (SrcDef->getOpcode() != TargetOpcode::G_CONSTANT ||
1652 !Match(SrcDef->getOperand(i: 1).getCImm()))
1653 return false;
1654 }
1655
1656 return true;
1657}
1658
1659bool llvm::isConstTrueVal(const TargetLowering &TLI, int64_t Val, bool IsVector,
1660 bool IsFP) {
1661 switch (TLI.getBooleanContents(isVec: IsVector, isFloat: IsFP)) {
1662 case TargetLowering::UndefinedBooleanContent:
1663 return Val & 0x1;
1664 case TargetLowering::ZeroOrOneBooleanContent:
1665 return Val == 1;
1666 case TargetLowering::ZeroOrNegativeOneBooleanContent:
1667 return Val == -1;
1668 }
1669 llvm_unreachable("Invalid boolean contents");
1670}
1671
1672bool llvm::isConstFalseVal(const TargetLowering &TLI, int64_t Val,
1673 bool IsVector, bool IsFP) {
1674 switch (TLI.getBooleanContents(isVec: IsVector, isFloat: IsFP)) {
1675 case TargetLowering::UndefinedBooleanContent:
1676 return ~Val & 0x1;
1677 case TargetLowering::ZeroOrOneBooleanContent:
1678 case TargetLowering::ZeroOrNegativeOneBooleanContent:
1679 return Val == 0;
1680 }
1681 llvm_unreachable("Invalid boolean contents");
1682}
1683
1684int64_t llvm::getICmpTrueVal(const TargetLowering &TLI, bool IsVector,
1685 bool IsFP) {
1686 switch (TLI.getBooleanContents(isVec: IsVector, isFloat: IsFP)) {
1687 case TargetLowering::UndefinedBooleanContent:
1688 case TargetLowering::ZeroOrOneBooleanContent:
1689 return 1;
1690 case TargetLowering::ZeroOrNegativeOneBooleanContent:
1691 return -1;
1692 }
1693 llvm_unreachable("Invalid boolean contents");
1694}
1695
1696void llvm::saveUsesAndErase(MachineInstr &MI, MachineRegisterInfo &MRI,
1697 LostDebugLocObserver *LocObserver,
1698 SmallInstListTy &DeadInstChain) {
1699 for (MachineOperand &Op : MI.uses()) {
1700 if (Op.isReg() && Op.getReg().isVirtual())
1701 DeadInstChain.insert(I: MRI.getVRegDef(Reg: Op.getReg()));
1702 }
1703 LLVM_DEBUG(dbgs() << MI << "Is dead; erasing.\n");
1704 DeadInstChain.remove(I: &MI);
1705 MI.eraseFromParent();
1706 if (LocObserver)
1707 LocObserver->checkpoint(CheckDebugLocs: false);
1708}
1709
1710void llvm::eraseInstrs(ArrayRef<MachineInstr *> DeadInstrs,
1711 MachineRegisterInfo &MRI,
1712 LostDebugLocObserver *LocObserver) {
1713 SmallInstListTy DeadInstChain;
1714 for (MachineInstr *MI : DeadInstrs)
1715 saveUsesAndErase(MI&: *MI, MRI, LocObserver, DeadInstChain);
1716
1717 while (!DeadInstChain.empty()) {
1718 MachineInstr *Inst = DeadInstChain.pop_back_val();
1719 if (!isTriviallyDead(MI: *Inst, MRI))
1720 continue;
1721 saveUsesAndErase(MI&: *Inst, MRI, LocObserver, DeadInstChain);
1722 }
1723}
1724
1725void llvm::eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI,
1726 LostDebugLocObserver *LocObserver) {
1727 return eraseInstrs(DeadInstrs: {&MI}, MRI, LocObserver);
1728}
1729
1730void llvm::salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI) {
1731 for (auto &Def : MI.defs()) {
1732 assert(Def.isReg() && "Must be a reg");
1733
1734 SmallVector<MachineOperand *, 16> DbgUsers;
1735 for (auto &MOUse : MRI.use_operands(Reg: Def.getReg())) {
1736 MachineInstr *DbgValue = MOUse.getParent();
1737 // Ignore partially formed DBG_VALUEs.
1738 if (DbgValue->isNonListDebugValue() && DbgValue->getNumOperands() == 4) {
1739 DbgUsers.push_back(Elt: &MOUse);
1740 }
1741 }
1742
1743 if (!DbgUsers.empty()) {
1744 salvageDebugInfoForDbgValue(MRI, MI, DbgUsers);
1745 }
1746 }
1747}
1748
1749bool llvm::isPreISelGenericFloatingPointOpcode(unsigned Opc) {
1750 switch (Opc) {
1751 case TargetOpcode::G_FABS:
1752 case TargetOpcode::G_FADD:
1753 case TargetOpcode::G_FCANONICALIZE:
1754 case TargetOpcode::G_FCEIL:
1755 case TargetOpcode::G_FCONSTANT:
1756 case TargetOpcode::G_FCOPYSIGN:
1757 case TargetOpcode::G_FCOS:
1758 case TargetOpcode::G_FDIV:
1759 case TargetOpcode::G_FEXP2:
1760 case TargetOpcode::G_FEXP:
1761 case TargetOpcode::G_FFLOOR:
1762 case TargetOpcode::G_FLOG10:
1763 case TargetOpcode::G_FLOG2:
1764 case TargetOpcode::G_FLOG:
1765 case TargetOpcode::G_FMA:
1766 case TargetOpcode::G_FMAD:
1767 case TargetOpcode::G_FMAXIMUM:
1768 case TargetOpcode::G_FMAXIMUMNUM:
1769 case TargetOpcode::G_FMAXNUM:
1770 case TargetOpcode::G_FMAXNUM_IEEE:
1771 case TargetOpcode::G_FMINIMUM:
1772 case TargetOpcode::G_FMINIMUMNUM:
1773 case TargetOpcode::G_FMINNUM:
1774 case TargetOpcode::G_FMINNUM_IEEE:
1775 case TargetOpcode::G_FMUL:
1776 case TargetOpcode::G_FNEARBYINT:
1777 case TargetOpcode::G_FNEG:
1778 case TargetOpcode::G_FPEXT:
1779 case TargetOpcode::G_FPOW:
1780 case TargetOpcode::G_FPTRUNC:
1781 case TargetOpcode::G_FREM:
1782 case TargetOpcode::G_FRINT:
1783 case TargetOpcode::G_FSIN:
1784 case TargetOpcode::G_FTAN:
1785 case TargetOpcode::G_FACOS:
1786 case TargetOpcode::G_FASIN:
1787 case TargetOpcode::G_FATAN:
1788 case TargetOpcode::G_FATAN2:
1789 case TargetOpcode::G_FCOSH:
1790 case TargetOpcode::G_FSINH:
1791 case TargetOpcode::G_FTANH:
1792 case TargetOpcode::G_FSQRT:
1793 case TargetOpcode::G_FSUB:
1794 case TargetOpcode::G_INTRINSIC_ROUND:
1795 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
1796 case TargetOpcode::G_INTRINSIC_TRUNC:
1797 return true;
1798 default:
1799 return false;
1800 }
1801}
1802
1803/// Shifts return poison if shiftwidth is larger than the bitwidth.
1804static bool shiftAmountKnownInRange(Register ShiftAmount,
1805 const MachineRegisterInfo &MRI) {
1806 LLT Ty = MRI.getType(Reg: ShiftAmount);
1807
1808 if (Ty.isScalableVector())
1809 return false; // Can't tell, just return false to be safe
1810
1811 if (Ty.isScalar()) {
1812 std::optional<ValueAndVReg> Val =
1813 getIConstantVRegValWithLookThrough(VReg: ShiftAmount, MRI);
1814 if (!Val)
1815 return false;
1816 return Val->Value.ult(RHS: Ty.getScalarSizeInBits());
1817 }
1818
1819 GBuildVector *BV = getOpcodeDef<GBuildVector>(Reg: ShiftAmount, MRI);
1820 if (!BV)
1821 return false;
1822
1823 unsigned Sources = BV->getNumSources();
1824 for (unsigned I = 0; I < Sources; ++I) {
1825 std::optional<ValueAndVReg> Val =
1826 getIConstantVRegValWithLookThrough(VReg: BV->getSourceReg(I), MRI);
1827 if (!Val)
1828 return false;
1829 if (!Val->Value.ult(RHS: Ty.getScalarSizeInBits()))
1830 return false;
1831 }
1832
1833 return true;
1834}
1835
1836namespace {
1837enum class UndefPoisonKind {
1838 PoisonOnly = (1 << 0),
1839 UndefOnly = (1 << 1),
1840 UndefOrPoison = PoisonOnly | UndefOnly,
1841};
1842}
1843
1844static bool includesPoison(UndefPoisonKind Kind) {
1845 return (unsigned(Kind) & unsigned(UndefPoisonKind::PoisonOnly)) != 0;
1846}
1847
1848static bool includesUndef(UndefPoisonKind Kind) {
1849 return (unsigned(Kind) & unsigned(UndefPoisonKind::UndefOnly)) != 0;
1850}
1851
1852static bool canCreateUndefOrPoison(Register Reg, const MachineRegisterInfo &MRI,
1853 bool ConsiderFlagsAndMetadata,
1854 UndefPoisonKind Kind) {
1855 MachineInstr *RegDef = MRI.getVRegDef(Reg);
1856
1857 if (ConsiderFlagsAndMetadata && includesPoison(Kind))
1858 if (auto *GMI = dyn_cast<GenericMachineInstr>(Val: RegDef))
1859 if (GMI->hasPoisonGeneratingFlags())
1860 return true;
1861
1862 // Check whether opcode is a poison/undef-generating operation.
1863 switch (RegDef->getOpcode()) {
1864 case TargetOpcode::G_BUILD_VECTOR:
1865 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1866 return false;
1867 case TargetOpcode::G_SHL:
1868 case TargetOpcode::G_ASHR:
1869 case TargetOpcode::G_LSHR:
1870 return includesPoison(Kind) &&
1871 !shiftAmountKnownInRange(ShiftAmount: RegDef->getOperand(i: 2).getReg(), MRI);
1872 case TargetOpcode::G_FPTOSI:
1873 case TargetOpcode::G_FPTOUI:
1874 // fptosi/ui yields poison if the resulting value does not fit in the
1875 // destination type.
1876 return true;
1877 case TargetOpcode::G_CTLZ:
1878 case TargetOpcode::G_CTTZ:
1879 case TargetOpcode::G_CTLS:
1880 case TargetOpcode::G_ABS:
1881 case TargetOpcode::G_CTPOP:
1882 case TargetOpcode::G_BSWAP:
1883 case TargetOpcode::G_BITREVERSE:
1884 case TargetOpcode::G_FSHL:
1885 case TargetOpcode::G_FSHR:
1886 case TargetOpcode::G_SMAX:
1887 case TargetOpcode::G_SMIN:
1888 case TargetOpcode::G_SCMP:
1889 case TargetOpcode::G_UMAX:
1890 case TargetOpcode::G_UMIN:
1891 case TargetOpcode::G_UCMP:
1892 case TargetOpcode::G_PTRMASK:
1893 case TargetOpcode::G_SADDO:
1894 case TargetOpcode::G_SSUBO:
1895 case TargetOpcode::G_UADDO:
1896 case TargetOpcode::G_USUBO:
1897 case TargetOpcode::G_SMULO:
1898 case TargetOpcode::G_UMULO:
1899 case TargetOpcode::G_SADDSAT:
1900 case TargetOpcode::G_UADDSAT:
1901 case TargetOpcode::G_SSUBSAT:
1902 case TargetOpcode::G_USUBSAT:
1903 case TargetOpcode::G_SBFX:
1904 case TargetOpcode::G_UBFX:
1905 return false;
1906 case TargetOpcode::G_SSHLSAT:
1907 case TargetOpcode::G_USHLSAT:
1908 return includesPoison(Kind) &&
1909 !shiftAmountKnownInRange(ShiftAmount: RegDef->getOperand(i: 2).getReg(), MRI);
1910 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1911 GInsertVectorElement *Insert = cast<GInsertVectorElement>(Val: RegDef);
1912 if (includesPoison(Kind)) {
1913 std::optional<ValueAndVReg> Index =
1914 getIConstantVRegValWithLookThrough(VReg: Insert->getIndexReg(), MRI);
1915 if (!Index)
1916 return true;
1917 LLT VecTy = MRI.getType(Reg: Insert->getVectorReg());
1918 return Index->Value.uge(RHS: VecTy.getElementCount().getKnownMinValue());
1919 }
1920 return false;
1921 }
1922 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1923 GExtractVectorElement *Extract = cast<GExtractVectorElement>(Val: RegDef);
1924 if (includesPoison(Kind)) {
1925 std::optional<ValueAndVReg> Index =
1926 getIConstantVRegValWithLookThrough(VReg: Extract->getIndexReg(), MRI);
1927 if (!Index)
1928 return true;
1929 LLT VecTy = MRI.getType(Reg: Extract->getVectorReg());
1930 return Index->Value.uge(RHS: VecTy.getElementCount().getKnownMinValue());
1931 }
1932 return false;
1933 }
1934 case TargetOpcode::G_SHUFFLE_VECTOR: {
1935 GShuffleVector *Shuffle = cast<GShuffleVector>(Val: RegDef);
1936 ArrayRef<int> Mask = Shuffle->getMask();
1937 return includesPoison(Kind) && is_contained(Range&: Mask, Element: -1);
1938 }
1939 case TargetOpcode::G_FNEG:
1940 case TargetOpcode::G_PHI:
1941 case TargetOpcode::G_SELECT:
1942 case TargetOpcode::G_UREM:
1943 case TargetOpcode::G_SREM:
1944 case TargetOpcode::G_FREEZE:
1945 case TargetOpcode::G_ICMP:
1946 case TargetOpcode::G_FCMP:
1947 case TargetOpcode::G_FADD:
1948 case TargetOpcode::G_FSUB:
1949 case TargetOpcode::G_FMUL:
1950 case TargetOpcode::G_FDIV:
1951 case TargetOpcode::G_FREM:
1952 case TargetOpcode::G_PTR_ADD:
1953 return false;
1954 default:
1955 return !isa<GCastOp>(Val: RegDef) && !isa<GBinOp>(Val: RegDef);
1956 }
1957}
1958
1959static bool isGuaranteedNotToBeUndefOrPoison(Register Reg,
1960 const MachineRegisterInfo &MRI,
1961 unsigned Depth,
1962 UndefPoisonKind Kind) {
1963 if (Depth >= MaxAnalysisRecursionDepth)
1964 return false;
1965
1966 MachineInstr *RegDef = MRI.getVRegDef(Reg);
1967
1968 switch (RegDef->getOpcode()) {
1969 case TargetOpcode::G_FREEZE:
1970 return true;
1971 case TargetOpcode::G_IMPLICIT_DEF:
1972 return !includesUndef(Kind);
1973 case TargetOpcode::G_CONSTANT:
1974 case TargetOpcode::G_FCONSTANT:
1975 return true;
1976 case TargetOpcode::G_BUILD_VECTOR: {
1977 GBuildVector *BV = cast<GBuildVector>(Val: RegDef);
1978 unsigned NumSources = BV->getNumSources();
1979 for (unsigned I = 0; I < NumSources; ++I)
1980 if (!::isGuaranteedNotToBeUndefOrPoison(Reg: BV->getSourceReg(I), MRI,
1981 Depth: Depth + 1, Kind))
1982 return false;
1983 return true;
1984 }
1985 case TargetOpcode::G_PHI: {
1986 GPhi *Phi = cast<GPhi>(Val: RegDef);
1987 unsigned NumIncoming = Phi->getNumIncomingValues();
1988 for (unsigned I = 0; I < NumIncoming; ++I)
1989 if (!::isGuaranteedNotToBeUndefOrPoison(Reg: Phi->getIncomingValue(I), MRI,
1990 Depth: Depth + 1, Kind))
1991 return false;
1992 return true;
1993 }
1994 default: {
1995 auto MOCheck = [&](const MachineOperand &MO) {
1996 if (!MO.isReg())
1997 return true;
1998 return ::isGuaranteedNotToBeUndefOrPoison(Reg: MO.getReg(), MRI, Depth: Depth + 1,
1999 Kind);
2000 };
2001 return !::canCreateUndefOrPoison(Reg, MRI,
2002 /*ConsiderFlagsAndMetadata=*/true, Kind) &&
2003 all_of(Range: RegDef->uses(), P: MOCheck);
2004 }
2005 }
2006}
2007
2008bool llvm::canCreateUndefOrPoison(Register Reg, const MachineRegisterInfo &MRI,
2009 bool ConsiderFlagsAndMetadata) {
2010 return ::canCreateUndefOrPoison(Reg, MRI, ConsiderFlagsAndMetadata,
2011 Kind: UndefPoisonKind::UndefOrPoison);
2012}
2013
2014bool canCreatePoison(Register Reg, const MachineRegisterInfo &MRI,
2015 bool ConsiderFlagsAndMetadata = true) {
2016 return ::canCreateUndefOrPoison(Reg, MRI, ConsiderFlagsAndMetadata,
2017 Kind: UndefPoisonKind::PoisonOnly);
2018}
2019
2020bool llvm::isGuaranteedNotToBeUndefOrPoison(Register Reg,
2021 const MachineRegisterInfo &MRI,
2022 unsigned Depth) {
2023 return ::isGuaranteedNotToBeUndefOrPoison(Reg, MRI, Depth,
2024 Kind: UndefPoisonKind::UndefOrPoison);
2025}
2026
2027bool llvm::isGuaranteedNotToBePoison(Register Reg,
2028 const MachineRegisterInfo &MRI,
2029 unsigned Depth) {
2030 return ::isGuaranteedNotToBeUndefOrPoison(Reg, MRI, Depth,
2031 Kind: UndefPoisonKind::PoisonOnly);
2032}
2033
2034bool llvm::isGuaranteedNotToBeUndef(Register Reg,
2035 const MachineRegisterInfo &MRI,
2036 unsigned Depth) {
2037 return ::isGuaranteedNotToBeUndefOrPoison(Reg, MRI, Depth,
2038 Kind: UndefPoisonKind::UndefOnly);
2039}
2040
2041Type *llvm::getTypeForLLT(LLT Ty, LLVMContext &C) {
2042 if (Ty.isVector())
2043 return VectorType::get(ElementType: IntegerType::get(C, NumBits: Ty.getScalarSizeInBits()),
2044 EC: Ty.getElementCount());
2045 return IntegerType::get(C, NumBits: Ty.getSizeInBits());
2046}
2047
2048bool llvm::isAssertMI(const MachineInstr &MI) {
2049 switch (MI.getOpcode()) {
2050 default:
2051 return false;
2052 case TargetOpcode::G_ASSERT_ALIGN:
2053 case TargetOpcode::G_ASSERT_SEXT:
2054 case TargetOpcode::G_ASSERT_ZEXT:
2055 return true;
2056 }
2057}
2058
2059APInt llvm::GIConstant::getScalarValue() const {
2060 assert(Kind == GIConstantKind::Scalar && "Expected scalar constant");
2061
2062 return Value;
2063}
2064
2065std::optional<GIConstant>
2066llvm::GIConstant::getConstant(Register Const, const MachineRegisterInfo &MRI) {
2067 MachineInstr *Constant = getDefIgnoringCopies(Reg: Const, MRI);
2068
2069 if (GSplatVector *Splat = dyn_cast<GSplatVector>(Val: Constant)) {
2070 std::optional<ValueAndVReg> MayBeConstant =
2071 getIConstantVRegValWithLookThrough(VReg: Splat->getScalarReg(), MRI);
2072 if (!MayBeConstant)
2073 return std::nullopt;
2074 return GIConstant(MayBeConstant->Value, GIConstantKind::ScalableVector);
2075 }
2076
2077 if (GBuildVector *Build = dyn_cast<GBuildVector>(Val: Constant)) {
2078 SmallVector<APInt> Values;
2079 unsigned NumSources = Build->getNumSources();
2080 for (unsigned I = 0; I < NumSources; ++I) {
2081 Register SrcReg = Build->getSourceReg(I);
2082 std::optional<ValueAndVReg> MayBeConstant =
2083 getIConstantVRegValWithLookThrough(VReg: SrcReg, MRI);
2084 if (!MayBeConstant)
2085 return std::nullopt;
2086 Values.push_back(Elt: MayBeConstant->Value);
2087 }
2088 return GIConstant(Values);
2089 }
2090
2091 std::optional<ValueAndVReg> MayBeConstant =
2092 getIConstantVRegValWithLookThrough(VReg: Const, MRI);
2093 if (!MayBeConstant)
2094 return std::nullopt;
2095
2096 return GIConstant(MayBeConstant->Value, GIConstantKind::Scalar);
2097}
2098
2099APFloat llvm::GFConstant::getScalarValue() const {
2100 assert(Kind == GFConstantKind::Scalar && "Expected scalar constant");
2101
2102 return Values[0];
2103}
2104
2105std::optional<GFConstant>
2106llvm::GFConstant::getConstant(Register Const, const MachineRegisterInfo &MRI) {
2107 MachineInstr *Constant = getDefIgnoringCopies(Reg: Const, MRI);
2108
2109 if (GSplatVector *Splat = dyn_cast<GSplatVector>(Val: Constant)) {
2110 std::optional<FPValueAndVReg> MayBeConstant =
2111 getFConstantVRegValWithLookThrough(VReg: Splat->getScalarReg(), MRI);
2112 if (!MayBeConstant)
2113 return std::nullopt;
2114 return GFConstant(MayBeConstant->Value, GFConstantKind::ScalableVector);
2115 }
2116
2117 if (GBuildVector *Build = dyn_cast<GBuildVector>(Val: Constant)) {
2118 SmallVector<APFloat> Values;
2119 unsigned NumSources = Build->getNumSources();
2120 for (unsigned I = 0; I < NumSources; ++I) {
2121 Register SrcReg = Build->getSourceReg(I);
2122 std::optional<FPValueAndVReg> MayBeConstant =
2123 getFConstantVRegValWithLookThrough(VReg: SrcReg, MRI);
2124 if (!MayBeConstant)
2125 return std::nullopt;
2126 Values.push_back(Elt: MayBeConstant->Value);
2127 }
2128 return GFConstant(Values);
2129 }
2130
2131 std::optional<FPValueAndVReg> MayBeConstant =
2132 getFConstantVRegValWithLookThrough(VReg: Const, MRI);
2133 if (!MayBeConstant)
2134 return std::nullopt;
2135
2136 return GFConstant(MayBeConstant->Value, GFConstantKind::Scalar);
2137}
2138