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