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