LLVM 24.0.0git
HexagonISelDAGToDAG.cpp
Go to the documentation of this file.
1//===-- HexagonISelDAGToDAG.cpp - A dag to dag inst selector for Hexagon --===//
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//
9// This file defines an instruction selector for the Hexagon target.
10//
11//===----------------------------------------------------------------------===//
12
13#include "HexagonISelDAGToDAG.h"
14#include "Hexagon.h"
15#include "HexagonISelLowering.h"
21#include "llvm/IR/Intrinsics.h"
22#include "llvm/IR/IntrinsicsHexagon.h"
24#include "llvm/Support/Debug.h"
25using namespace llvm;
26
27#define DEBUG_TYPE "hexagon-isel"
28#define PASS_NAME "Hexagon DAG->DAG Pattern Instruction Selection"
29
30static
32EnableAddressRebalancing("isel-rebalance-addr", cl::Hidden, cl::init(true),
33 cl::desc("Rebalance address calculation trees to improve "
34 "instruction selection"));
35
36// Rebalance only if this allows e.g. combining a GA with an offset or
37// factoring out a shift.
38static
41 cl::desc("Rebalance address tree only if this allows optimizations"));
42
43static
46 cl::init(false), cl::desc("Rebalance address tree only if it is imbalanced"));
47
48static cl::opt<bool> CheckSingleUse("hexagon-isel-su", cl::Hidden,
49 cl::init(true), cl::desc("Enable checking of SDNode's single-use status"));
50
51//===----------------------------------------------------------------------===//
52// Instruction Selector Implementation
53//===----------------------------------------------------------------------===//
54
55#define GET_DAGISEL_BODY HexagonDAGToDAGISel
56#include "HexagonGenDAGISel.inc"
57
58namespace llvm {
59/// createHexagonISelDag - This pass converts a legalized DAG into a
60/// Hexagon-specific DAG, ready for instruction scheduling.
65}
66
71
73
75
77 SDValue Chain = LD->getChain();
78 SDValue Base = LD->getBasePtr();
79 SDValue Offset = LD->getOffset();
80 int32_t Inc = cast<ConstantSDNode>(Offset.getNode())->getSExtValue();
81 EVT LoadedVT = LD->getMemoryVT();
82 unsigned Opcode = 0;
83
84 // Check for zero extended loads. Treat any-extend loads as zero extended
85 // loads.
86 ISD::LoadExtType ExtType = LD->getExtensionType();
87 bool IsZeroExt = (ExtType == ISD::ZEXTLOAD || ExtType == ISD::EXTLOAD);
88 bool IsValidInc = HII->isValidAutoIncImm(LoadedVT, Inc);
89
90 assert(LoadedVT.isSimple());
91 switch (LoadedVT.getSimpleVT().SimpleTy) {
92 case MVT::i8:
93 if (IsZeroExt)
94 Opcode = IsValidInc ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrub_io;
95 else
96 Opcode = IsValidInc ? Hexagon::L2_loadrb_pi : Hexagon::L2_loadrb_io;
97 break;
98 case MVT::i16:
99 if (IsZeroExt)
100 Opcode = IsValidInc ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadruh_io;
101 else
102 Opcode = IsValidInc ? Hexagon::L2_loadrh_pi : Hexagon::L2_loadrh_io;
103 break;
104 case MVT::i32:
105 case MVT::f32:
106 case MVT::v2i16:
107 case MVT::v4i8:
108 Opcode = IsValidInc ? Hexagon::L2_loadri_pi : Hexagon::L2_loadri_io;
109 break;
110 case MVT::i64:
111 case MVT::f64:
112 case MVT::v2i32:
113 case MVT::v4i16:
114 case MVT::v8i8:
115 Opcode = IsValidInc ? Hexagon::L2_loadrd_pi : Hexagon::L2_loadrd_io;
116 break;
117 case MVT::v64i8:
118 case MVT::v32i16:
119 case MVT::v16i32:
120 case MVT::v8i64:
121 case MVT::v128i8:
122 case MVT::v64i16:
123 case MVT::v32i32:
124 case MVT::v16i64:
125 if (isAlignedMemNode(LD)) {
126 if (LD->isNonTemporal())
127 Opcode = IsValidInc ? Hexagon::V6_vL32b_nt_pi : Hexagon::V6_vL32b_nt_ai;
128 else
129 Opcode = IsValidInc ? Hexagon::V6_vL32b_pi : Hexagon::V6_vL32b_ai;
130 } else {
131 Opcode = IsValidInc ? Hexagon::V6_vL32Ub_pi : Hexagon::V6_vL32Ub_ai;
132 }
133 break;
134 default:
135 llvm_unreachable("Unexpected memory type in indexed load");
136 }
137
138 SDValue IncV = CurDAG->getSignedTargetConstant(Inc, dl, MVT::i32);
139 MachineMemOperand *MemOp = LD->getMemOperand();
140
141 auto getExt64 = [this,ExtType] (MachineSDNode *N, const SDLoc &dl)
142 -> MachineSDNode* {
143 if (ExtType == ISD::ZEXTLOAD || ExtType == ISD::EXTLOAD) {
144 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);
145 return CurDAG->getMachineNode(Hexagon::A4_combineir, dl, MVT::i64,
146 Zero, SDValue(N, 0));
147 }
148 if (ExtType == ISD::SEXTLOAD)
149 return CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
150 SDValue(N, 0));
151 return N;
152 };
153
154 // Loaded value Next address Chain
155 SDValue From[3] = { SDValue(LD,0), SDValue(LD,1), SDValue(LD,2) };
156 SDValue To[3];
157
158 EVT ValueVT = LD->getValueType(0);
159 if (ValueVT == MVT::i64 && ExtType != ISD::NON_EXTLOAD) {
160 // A load extending to i64 will actually produce i32, which will then
161 // need to be extended to i64.
162 assert(LoadedVT.getSizeInBits() <= 32);
163 ValueVT = MVT::i32;
164 }
165
166 if (IsValidInc) {
167 MachineSDNode *L = CurDAG->getMachineNode(Opcode, dl, ValueVT,
168 MVT::i32, MVT::Other, Base,
169 IncV, Chain);
170 CurDAG->setNodeMemRefs(L, {MemOp});
171 To[1] = SDValue(L, 1); // Next address.
172 To[2] = SDValue(L, 2); // Chain.
173 // Handle special case for extension to i64.
174 if (LD->getValueType(0) == MVT::i64)
175 L = getExt64(L, dl);
176 To[0] = SDValue(L, 0); // Loaded (extended) value.
177 } else {
178 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);
179 MachineSDNode *L = CurDAG->getMachineNode(Opcode, dl, ValueVT, MVT::Other,
180 Base, Zero, Chain);
181 CurDAG->setNodeMemRefs(L, {MemOp});
182 To[2] = SDValue(L, 1); // Chain.
183 MachineSDNode *A = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
184 Base, IncV);
185 To[1] = SDValue(A, 0); // Next address.
186 // Handle special case for extension to i64.
187 if (LD->getValueType(0) == MVT::i64)
188 L = getExt64(L, dl);
189 To[0] = SDValue(L, 0); // Loaded (extended) value.
190 }
191 ReplaceUses(From, To, 3);
192 CurDAG->RemoveDeadNode(LD);
193}
194
196 if (IntN->getOpcode() != ISD::INTRINSIC_W_CHAIN)
197 return nullptr;
198
199 SDLoc dl(IntN);
200 unsigned IntNo = IntN->getConstantOperandVal(1);
201
202 static std::map<unsigned,unsigned> LoadPciMap = {
203 { Intrinsic::hexagon_circ_ldb, Hexagon::L2_loadrb_pci },
204 { Intrinsic::hexagon_circ_ldub, Hexagon::L2_loadrub_pci },
205 { Intrinsic::hexagon_circ_ldh, Hexagon::L2_loadrh_pci },
206 { Intrinsic::hexagon_circ_lduh, Hexagon::L2_loadruh_pci },
207 { Intrinsic::hexagon_circ_ldw, Hexagon::L2_loadri_pci },
208 { Intrinsic::hexagon_circ_ldd, Hexagon::L2_loadrd_pci },
209 };
210 auto FLC = LoadPciMap.find(IntNo);
211 if (FLC != LoadPciMap.end()) {
212 EVT ValTy = (IntNo == Intrinsic::hexagon_circ_ldd) ? MVT::i64 : MVT::i32;
213 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
214 // Operands: { Base, Increment, Modifier, Chain }
215 auto Inc = cast<ConstantSDNode>(IntN->getOperand(5));
216 SDValue I =
217 CurDAG->getSignedTargetConstant(Inc->getSExtValue(), dl, MVT::i32);
218 MachineSDNode *Res = CurDAG->getMachineNode(FLC->second, dl, RTys,
219 { IntN->getOperand(2), I, IntN->getOperand(4),
220 IntN->getOperand(0) });
221 return Res;
222 }
223
224 return nullptr;
225}
226
228 SDNode *IntN) {
229 // The "LoadN" is just a machine load instruction. The intrinsic also
230 // involves storing it. Generate an appropriate store to the location
231 // given in the intrinsic's operand(3).
232 uint64_t F = HII->get(LoadN->getMachineOpcode()).TSFlags;
233 unsigned SizeBits = (F >> HexagonII::MemAccessSizePos) &
235 unsigned Size = 1U << (SizeBits-1);
236
237 SDLoc dl(IntN);
239 SDValue TS;
240 SDValue Loc = IntN->getOperand(3);
241
242 if (Size >= 4)
243 TS = CurDAG->getStore(SDValue(LoadN, 2), dl, SDValue(LoadN, 0), Loc, PI,
244 Align(Size));
245 else
246 TS = CurDAG->getTruncStore(SDValue(LoadN, 2), dl, SDValue(LoadN, 0), Loc,
247 PI, MVT::getIntegerVT(Size * 8), Align(Size));
248
249 SDNode *StoreN;
250 {
251 HandleSDNode Handle(TS);
252 SelectStore(TS.getNode());
253 StoreN = Handle.getValue().getNode();
254 }
255
256 // Load's results are { Loaded value, Updated pointer, Chain }
257 ReplaceUses(SDValue(IntN, 0), SDValue(LoadN, 1));
258 ReplaceUses(SDValue(IntN, 1), SDValue(StoreN, 0));
259 return StoreN;
260}
261
263 // The intrinsics for load circ/brev perform two operations:
264 // 1. Load a value V from the specified location, using the addressing
265 // mode corresponding to the intrinsic.
266 // 2. Store V into a specified location. This location is typically a
267 // local, temporary object.
268 // In many cases, the program using these intrinsics will immediately
269 // load V again from the local object. In those cases, when certain
270 // conditions are met, the last load can be removed.
271 // This function identifies and optimizes this pattern. If the pattern
272 // cannot be optimized, it returns nullptr, which will cause the load
273 // to be selected separately from the intrinsic (which will be handled
274 // in SelectIntrinsicWChain).
275
276 SDValue Ch = N->getOperand(0);
277 SDValue Loc = N->getOperand(1);
278
279 // Assume that the load and the intrinsic are connected directly with a
280 // chain:
281 // t1: i32,ch = int.load ..., ..., ..., Loc, ... // <-- C
282 // t2: i32,ch = load t1:1, Loc, ...
283 SDNode *C = Ch.getNode();
284
285 if (C->getOpcode() != ISD::INTRINSIC_W_CHAIN)
286 return false;
287
288 // The second load can only be eliminated if its extension type matches
289 // that of the load instruction corresponding to the intrinsic. The user
290 // can provide an address of an unsigned variable to store the result of
291 // a sign-extending intrinsic into (or the other way around).
292 ISD::LoadExtType IntExt;
293 switch (C->getConstantOperandVal(1)) {
294 case Intrinsic::hexagon_circ_ldub:
295 case Intrinsic::hexagon_circ_lduh:
296 IntExt = ISD::ZEXTLOAD;
297 break;
298 case Intrinsic::hexagon_circ_ldw:
299 case Intrinsic::hexagon_circ_ldd:
300 IntExt = ISD::NON_EXTLOAD;
301 break;
302 default:
303 IntExt = ISD::SEXTLOAD;
304 break;
305 }
306 if (N->getExtensionType() != IntExt)
307 return false;
308
309 // Make sure the target location for the loaded value in the load intrinsic
310 // is the location from which LD (or N) is loading.
311 if (C->getNumOperands() < 4 || Loc.getNode() != C->getOperand(3).getNode())
312 return false;
313
316 SDValue F[] = { SDValue(N,0), SDValue(N,1), SDValue(C,0), SDValue(C,1) };
317 SDValue T[] = { SDValue(L,0), SDValue(S,0), SDValue(L,1), SDValue(S,0) };
318 ReplaceUses(F, T, std::size(T));
319 // This transformation will leave the intrinsic dead. If it remains in
320 // the DAG, the selection code will see it again, but without the load,
321 // and it will generate a store that is normally required for it.
322 CurDAG->RemoveDeadNode(C);
323 return true;
324 }
325 return false;
326}
327
328// Convert the bit-reverse load intrinsic to appropriate target instruction.
330 if (IntN->getOpcode() != ISD::INTRINSIC_W_CHAIN)
331 return false;
332
333 const SDLoc &dl(IntN);
334 unsigned IntNo = IntN->getConstantOperandVal(1);
335
336 static const std::map<unsigned, unsigned> LoadBrevMap = {
337 { Intrinsic::hexagon_L2_loadrb_pbr, Hexagon::L2_loadrb_pbr },
338 { Intrinsic::hexagon_L2_loadrub_pbr, Hexagon::L2_loadrub_pbr },
339 { Intrinsic::hexagon_L2_loadrh_pbr, Hexagon::L2_loadrh_pbr },
340 { Intrinsic::hexagon_L2_loadruh_pbr, Hexagon::L2_loadruh_pbr },
341 { Intrinsic::hexagon_L2_loadri_pbr, Hexagon::L2_loadri_pbr },
342 { Intrinsic::hexagon_L2_loadrd_pbr, Hexagon::L2_loadrd_pbr }
343 };
344 auto FLI = LoadBrevMap.find(IntNo);
345 if (FLI != LoadBrevMap.end()) {
346 EVT ValTy =
347 (IntNo == Intrinsic::hexagon_L2_loadrd_pbr) ? MVT::i64 : MVT::i32;
348 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
349 // Operands of Intrinsic: {chain, enum ID of intrinsic, baseptr,
350 // modifier}.
351 // Operands of target instruction: { Base, Modifier, Chain }.
352 MachineSDNode *Res = CurDAG->getMachineNode(
353 FLI->second, dl, RTys,
354 {IntN->getOperand(2), IntN->getOperand(3), IntN->getOperand(0)});
355
356 MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(IntN)->getMemOperand();
357 CurDAG->setNodeMemRefs(Res, {MemOp});
358
359 ReplaceUses(SDValue(IntN, 0), SDValue(Res, 0));
360 ReplaceUses(SDValue(IntN, 1), SDValue(Res, 1));
361 ReplaceUses(SDValue(IntN, 2), SDValue(Res, 2));
362 CurDAG->RemoveDeadNode(IntN);
363 return true;
364 }
365 return false;
366}
367
369 unsigned MOp, unsigned CSOp) {
370 SDValue RC = DAG.getTargetConstant(Hexagon::CircRegsRegClassID, DL, MVT::i32);
371 SDValue SubRegCS = DAG.getTargetConstant(Hexagon::isub_lo, DL, MVT::i32);
372 SDValue SubRegM = DAG.getTargetConstant(Hexagon::isub_hi, DL, MVT::i32);
373 const SDValue RegSequenceOps[] = {RC, N->getOperand(MOp), SubRegM,
374 N->getOperand(CSOp), SubRegCS};
375 SDNode *M_CS = DAG.getMachineNode(TargetOpcode::REG_SEQUENCE, DL, MVT::i64,
376 RegSequenceOps);
377 return SDValue(M_CS, 0);
378}
379
380/// Generate a machine instruction node for the new circular buffer intrinsics.
381/// The new versions use a CSx register instead of the K field.
383 if (IntN->getOpcode() != ISD::INTRINSIC_W_CHAIN)
384 return false;
385
386 SDLoc DL(IntN);
387 unsigned IntNo = IntN->getConstantOperandVal(1);
389
390 static std::map<unsigned,unsigned> LoadNPcMap = {
391 { Intrinsic::hexagon_L2_loadrub_pci, Hexagon::PS_loadrub_pci },
392 { Intrinsic::hexagon_L2_loadrb_pci, Hexagon::PS_loadrb_pci },
393 { Intrinsic::hexagon_L2_loadruh_pci, Hexagon::PS_loadruh_pci },
394 { Intrinsic::hexagon_L2_loadrh_pci, Hexagon::PS_loadrh_pci },
395 { Intrinsic::hexagon_L2_loadri_pci, Hexagon::PS_loadri_pci },
396 { Intrinsic::hexagon_L2_loadrd_pci, Hexagon::PS_loadrd_pci },
397 { Intrinsic::hexagon_L2_loadrub_pcr, Hexagon::PS_loadrub_pcr },
398 { Intrinsic::hexagon_L2_loadrb_pcr, Hexagon::PS_loadrb_pcr },
399 { Intrinsic::hexagon_L2_loadruh_pcr, Hexagon::PS_loadruh_pcr },
400 { Intrinsic::hexagon_L2_loadrh_pcr, Hexagon::PS_loadrh_pcr },
401 { Intrinsic::hexagon_L2_loadri_pcr, Hexagon::PS_loadri_pcr },
402 { Intrinsic::hexagon_L2_loadrd_pcr, Hexagon::PS_loadrd_pcr }
403 };
404 auto FLI = LoadNPcMap.find (IntNo);
405 if (FLI != LoadNPcMap.end()) {
406 EVT ValTy = MVT::i32;
407 if (IntNo == Intrinsic::hexagon_L2_loadrd_pci ||
408 IntNo == Intrinsic::hexagon_L2_loadrd_pcr)
409 ValTy = MVT::i64;
410 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
411 // Handle load.*_pci case which has 6 operands.
412 if (IntN->getNumOperands() == 6) {
413 auto Inc = cast<ConstantSDNode>(IntN->getOperand(3));
414 SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), DL, MVT::i32);
415 SDValue M_CS = getCircRegister(*CurDAG, DL, IntN, 4, 5);
416 // Operands: { Base, Increment, Modifier_Start, Chain }.
417 Ops = {IntN->getOperand(2), I, M_CS, IntN->getOperand(0)};
418 } else {
419 // Handle load.*_pcr case which has 5 operands.
420 SDValue M_CS = getCircRegister(*CurDAG, DL, IntN, 3, 4);
421 // Operands: { Base, Modifier_Start, Chain }.
422 Ops = {IntN->getOperand(2), M_CS, IntN->getOperand(0)};
423 }
424 MachineSDNode *Res = CurDAG->getMachineNode(FLI->second, DL, RTys, Ops);
425 ReplaceUses(SDValue(IntN, 0), SDValue(Res, 0));
426 ReplaceUses(SDValue(IntN, 1), SDValue(Res, 1));
427 ReplaceUses(SDValue(IntN, 2), SDValue(Res, 2));
428 CurDAG->RemoveDeadNode(IntN);
429 return true;
430 }
431
432 static std::map<unsigned,unsigned> StoreNPcMap = {
433 { Intrinsic::hexagon_S2_storerb_pci, Hexagon::PS_storerb_pci },
434 { Intrinsic::hexagon_S2_storerh_pci, Hexagon::PS_storerh_pci },
435 { Intrinsic::hexagon_S2_storerf_pci, Hexagon::PS_storerf_pci },
436 { Intrinsic::hexagon_S2_storeri_pci, Hexagon::PS_storeri_pci },
437 { Intrinsic::hexagon_S2_storerd_pci, Hexagon::PS_storerd_pci },
438 { Intrinsic::hexagon_S2_storerb_pcr, Hexagon::PS_storerb_pcr },
439 { Intrinsic::hexagon_S2_storerh_pcr, Hexagon::PS_storerh_pcr },
440 { Intrinsic::hexagon_S2_storerf_pcr, Hexagon::PS_storerf_pcr },
441 { Intrinsic::hexagon_S2_storeri_pcr, Hexagon::PS_storeri_pcr },
442 { Intrinsic::hexagon_S2_storerd_pcr, Hexagon::PS_storerd_pcr }
443 };
444 auto FSI = StoreNPcMap.find (IntNo);
445 if (FSI != StoreNPcMap.end()) {
446 EVT RTys[] = { MVT::i32, MVT::Other };
447 // Handle store.*_pci case which has 7 operands.
448 if (IntN->getNumOperands() == 7) {
449 auto Inc = cast<ConstantSDNode>(IntN->getOperand(3));
450 SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), DL, MVT::i32);
451 SDValue M_CS = getCircRegister(*CurDAG, DL, IntN, 4, 6);
452 // Operands: { Base, Increment, Modifier_Start, Value, Chain }.
453 Ops = {IntN->getOperand(2), I, M_CS, IntN->getOperand(5),
454 IntN->getOperand(0)};
455 } else {
456 // Handle store.*_pcr case which has 6 operands.
457 SDValue M_CS = getCircRegister(*CurDAG, DL, IntN, 3, 5);
458 // Operands: { Base, Modifier_Start, Value, Chain }.
459 Ops = {IntN->getOperand(2), M_CS, IntN->getOperand(4),
460 IntN->getOperand(0)};
461 }
462 MachineSDNode *Res = CurDAG->getMachineNode(FSI->second, DL, RTys, Ops);
463 ReplaceUses(SDValue(IntN, 0), SDValue(Res, 0));
464 ReplaceUses(SDValue(IntN, 1), SDValue(Res, 1));
465 CurDAG->RemoveDeadNode(IntN);
466 return true;
467 }
468
469 return false;
470}
471
473 SDLoc dl(N);
475
476 // Handle indexed loads.
477 ISD::MemIndexedMode AM = LD->getAddressingMode();
478 if (AM != ISD::UNINDEXED) {
479 SelectIndexedLoad(LD, dl);
480 return;
481 }
482
483 // Handle patterns using circ/brev load intrinsics.
485 return;
486
487 SelectCode(LD);
488}
489
491 SDValue Chain = ST->getChain();
492 SDValue Base = ST->getBasePtr();
493 SDValue Offset = ST->getOffset();
494 SDValue Value = ST->getValue();
495 // Get the constant value.
496 int32_t Inc = cast<ConstantSDNode>(Offset.getNode())->getSExtValue();
497 EVT StoredVT = ST->getMemoryVT();
498 EVT ValueVT = Value.getValueType();
499
500 bool IsValidInc = HII->isValidAutoIncImm(StoredVT, Inc);
501 unsigned Opcode = 0;
502
503 assert(StoredVT.isSimple());
504 switch (StoredVT.getSimpleVT().SimpleTy) {
505 case MVT::i8:
506 Opcode = IsValidInc ? Hexagon::S2_storerb_pi : Hexagon::S2_storerb_io;
507 break;
508 case MVT::i16:
509 Opcode = IsValidInc ? Hexagon::S2_storerh_pi : Hexagon::S2_storerh_io;
510 break;
511 case MVT::i32:
512 case MVT::f32:
513 case MVT::v2i16:
514 case MVT::v4i8:
515 Opcode = IsValidInc ? Hexagon::S2_storeri_pi : Hexagon::S2_storeri_io;
516 break;
517 case MVT::i64:
518 case MVT::f64:
519 case MVT::v2i32:
520 case MVT::v4i16:
521 case MVT::v8i8:
522 Opcode = IsValidInc ? Hexagon::S2_storerd_pi : Hexagon::S2_storerd_io;
523 break;
524 case MVT::v64i8:
525 case MVT::v32i16:
526 case MVT::v16i32:
527 case MVT::v8i64:
528 case MVT::v128i8:
529 case MVT::v64i16:
530 case MVT::v32i32:
531 case MVT::v16i64:
532 if (isAlignedMemNode(ST)) {
533 if (ST->isNonTemporal())
534 Opcode = IsValidInc ? Hexagon::V6_vS32b_nt_pi : Hexagon::V6_vS32b_nt_ai;
535 else
536 Opcode = IsValidInc ? Hexagon::V6_vS32b_pi : Hexagon::V6_vS32b_ai;
537 } else {
538 Opcode = IsValidInc ? Hexagon::V6_vS32Ub_pi : Hexagon::V6_vS32Ub_ai;
539 }
540 break;
541 default:
542 llvm_unreachable("Unexpected memory type in indexed store");
543 }
544
545 if (ST->isTruncatingStore() && ValueVT.getSizeInBits() == 64) {
546 assert(StoredVT.getSizeInBits() < 64 && "Not a truncating store");
547 Value = CurDAG->getTargetExtractSubreg(Hexagon::isub_lo,
548 dl, MVT::i32, Value);
549 }
550
551 SDValue IncV = CurDAG->getSignedTargetConstant(Inc, dl, MVT::i32);
552 MachineMemOperand *MemOp = ST->getMemOperand();
553
554 // Next address Chain
555 SDValue From[2] = { SDValue(ST,0), SDValue(ST,1) };
556 SDValue To[2];
557
558 if (IsValidInc) {
559 // Build post increment store.
560 SDValue Ops[] = { Base, IncV, Value, Chain };
561 MachineSDNode *S = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Other,
562 Ops);
563 CurDAG->setNodeMemRefs(S, {MemOp});
564 To[0] = SDValue(S, 0);
565 To[1] = SDValue(S, 1);
566 } else {
567 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);
568 SDValue Ops[] = { Base, Zero, Value, Chain };
569 MachineSDNode *S = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
570 CurDAG->setNodeMemRefs(S, {MemOp});
571 To[1] = SDValue(S, 0);
572 MachineSDNode *A = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
573 Base, IncV);
574 To[0] = SDValue(A, 0);
575 }
576
577 ReplaceUses(From, To, 2);
578 CurDAG->RemoveDeadNode(ST);
579}
580
582 SDLoc dl(N);
584
585 // Handle indexed stores.
586 ISD::MemIndexedMode AM = ST->getAddressingMode();
587 if (AM != ISD::UNINDEXED) {
588 SelectIndexedStore(ST, dl);
589 return;
590 }
591
592 SelectCode(ST);
593}
594
596 SDLoc dl(N);
597 SDValue Shl_0 = N->getOperand(0);
598 SDValue Shl_1 = N->getOperand(1);
599
600 auto Default = [this,N] () -> void { SelectCode(N); };
601
602 if (N->getValueType(0) != MVT::i32 || Shl_1.getOpcode() != ISD::Constant)
603 return Default();
604
605 // RHS is const.
606 int32_t ShlConst = cast<ConstantSDNode>(Shl_1)->getSExtValue();
607
608 if (Shl_0.getOpcode() == ISD::MUL) {
609 SDValue Mul_0 = Shl_0.getOperand(0); // Val
610 SDValue Mul_1 = Shl_0.getOperand(1); // Const
611 // RHS of mul is const.
613 int32_t ValConst = static_cast<int32_t>(
614 static_cast<uint32_t>(C->getSExtValue()) << ShlConst);
615 if (isInt<9>(ValConst)) {
616 SDValue Val = CurDAG->getTargetConstant(ValConst, dl, MVT::i32);
617 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
618 MVT::i32, Mul_0, Val);
619 ReplaceNode(N, Result);
620 return;
621 }
622 }
623 return Default();
624 }
625
626 if (Shl_0.getOpcode() == ISD::SUB) {
627 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0
628 SDValue Sub_1 = Shl_0.getOperand(1); // Val
630 if (C1->getSExtValue() != 0 || Sub_1.getOpcode() != ISD::SHL)
631 return Default();
632 SDValue Shl2_0 = Sub_1.getOperand(0); // Val
633 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
634 if (ConstantSDNode *C2 = dyn_cast<ConstantSDNode>(Shl2_1)) {
635 int32_t ValConst =
636 static_cast<int32_t>(1U << (ShlConst + C2->getSExtValue()));
637 if (isInt<9>(-ValConst)) {
638 SDValue Val =
639 CurDAG->getSignedTargetConstant(-ValConst, dl, MVT::i32);
640 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
641 MVT::i32, Shl2_0, Val);
642 ReplaceNode(N, Result);
643 return;
644 }
645 }
646 }
647 }
648
649 return Default();
650}
651
652//
653// Handling intrinsics for circular load and bitreverse load.
654//
658 CurDAG->RemoveDeadNode(N);
659 return;
660 }
661
662 // Handle bit-reverse load intrinsics.
664 return;
665
667 return;
668
669 unsigned IntNo = N->getConstantOperandVal(1);
670 if (IntNo == Intrinsic::hexagon_V6_vgathermw ||
671 IntNo == Intrinsic::hexagon_V6_vgathermw_128B ||
672 IntNo == Intrinsic::hexagon_V6_vgathermh ||
673 IntNo == Intrinsic::hexagon_V6_vgathermh_128B ||
674 IntNo == Intrinsic::hexagon_V6_vgathermhw ||
675 IntNo == Intrinsic::hexagon_V6_vgathermhw_128B ||
676 IntNo == Intrinsic::hexagon_V6_vgather_vscattermh ||
677 IntNo == Intrinsic::hexagon_V6_vgather_vscattermh_128B) {
679 return;
680 }
681 if (IntNo == Intrinsic::hexagon_V6_vgathermwq ||
682 IntNo == Intrinsic::hexagon_V6_vgathermwq_128B ||
683 IntNo == Intrinsic::hexagon_V6_vgathermhq ||
684 IntNo == Intrinsic::hexagon_V6_vgathermhq_128B ||
685 IntNo == Intrinsic::hexagon_V6_vgathermhwq ||
686 IntNo == Intrinsic::hexagon_V6_vgathermhwq_128B) {
688 return;
689 }
690
691 SelectCode(N);
692}
693
695 unsigned IID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
696 unsigned Bits;
697
698 // On v79 and above, IEEE HVX instructions are no longer present.
699 // The related intrinsics must be translated to QFloat implicitly in order
700 // to provide backward compatibility.
701 if (HST->useHVXV79Ops() && isIEEEHVXIntrinsic(IID)) {
703 return;
704 }
705
706 switch (IID) {
707 case Intrinsic::hexagon_S2_vsplatrb:
708 Bits = 8;
709 break;
710 case Intrinsic::hexagon_S2_vsplatrh:
711 Bits = 16;
712 break;
713 case Intrinsic::hexagon_V6_vaddcarry:
714 case Intrinsic::hexagon_V6_vaddcarry_128B:
715 case Intrinsic::hexagon_V6_vsubcarry:
716 case Intrinsic::hexagon_V6_vsubcarry_128B:
718 return;
719 default:
720 SelectCode(N);
721 return;
722 }
723
724 SDValue V = N->getOperand(1);
725 SDValue U;
726 // Splat intrinsics.
727 if (keepsLowBits(V, Bits, U)) {
728 SDValue R = CurDAG->getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
729 N->getOperand(0), U);
730 ReplaceNode(N, R.getNode());
731 SelectCode(R.getNode());
732 return;
733 }
734 SelectCode(N);
735}
736
738 SDValue Inp = N->getOperand(0);
739 MVT ResTy = N->getValueType(0).getSimpleVT();
740 unsigned Idx = N->getConstantOperandVal(1);
741
742 [[maybe_unused]] MVT InpTy = Inp.getValueType().getSimpleVT();
743 [[maybe_unused]] unsigned ResLen = ResTy.getVectorNumElements();
745 assert(2 * ResLen == InpTy.getVectorNumElements());
746 assert(ResTy.getSizeInBits() == 32);
747 assert(Idx == 0 || Idx == ResLen);
748
749 unsigned SubReg = Idx == 0 ? Hexagon::isub_lo : Hexagon::isub_hi;
750 SDValue Ext = CurDAG->getTargetExtractSubreg(SubReg, SDLoc(N), ResTy, Inp);
751
752 ReplaceNode(N, Ext.getNode());
753}
754
755//
756// Map floating point constant values.
757//
759 SDLoc dl(N);
760 auto *CN = cast<ConstantFPSDNode>(N);
761 APInt A = CN->getValueAPF().bitcastToAPInt();
762 if (N->getValueType(0) == MVT::f32) {
763 SDValue V = CurDAG->getTargetConstant(A.getZExtValue(), dl, MVT::i32);
764 ReplaceNode(N, CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, V));
765 return;
766 }
767 if (N->getValueType(0) == MVT::f64) {
768 SDValue V = CurDAG->getTargetConstant(A.getZExtValue(), dl, MVT::i64);
769 ReplaceNode(N, CurDAG->getMachineNode(Hexagon::CONST64, dl, MVT::f64, V));
770 return;
771 }
772
773 SelectCode(N);
774}
775
776//
777// Map boolean values.
778//
780 if (N->getValueType(0) == MVT::i1) {
781 assert(!(N->getAsZExtVal() >> 1));
782 unsigned Opc = (cast<ConstantSDNode>(N)->getSExtValue() != 0)
783 ? Hexagon::PS_true
784 : Hexagon::PS_false;
785 ReplaceNode(N, CurDAG->getMachineNode(Opc, SDLoc(N), MVT::i1));
786 return;
787 }
788
789 SelectCode(N);
790}
791
793 MachineFrameInfo &MFI = MF->getFrameInfo();
794 const HexagonFrameLowering *HFI = HST->getFrameLowering();
795 int FX = cast<FrameIndexSDNode>(N)->getIndex();
796 Align StkA = HFI->getStackAlign();
797 Align MaxA = MFI.getMaxAlign();
798 SDValue FI = CurDAG->getTargetFrameIndex(FX, MVT::i32);
799 SDLoc DL(N);
800 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
801 SDNode *R = nullptr;
802
803 // Use PS_fi when:
804 // - the object is fixed, or
805 // - there are no objects with higher-than-default alignment, or
806 // - there are no dynamically allocated objects.
807 // Otherwise, use PS_fia.
808 if (FX < 0 || MaxA <= StkA || !MFI.hasVarSizedObjects()) {
809 R = CurDAG->getMachineNode(Hexagon::PS_fi, DL, MVT::i32, FI, Zero);
810 } else {
811 auto &HMFI = *MF->getInfo<HexagonMachineFunctionInfo>();
812 Register AR = HMFI.getStackAlignBaseReg();
813 assert(AR.isValid() && "Missing stack align base register");
814 SDValue CH = CurDAG->getEntryNode();
815 SDValue Ops[] = { CurDAG->getCopyFromReg(CH, DL, AR, MVT::i32), FI, Zero };
816 R = CurDAG->getMachineNode(Hexagon::PS_fia, DL, MVT::i32, Ops);
817 }
818
819 ReplaceNode(N, R);
820}
821
823 unsigned OpcCarry = N->getOpcode() == HexagonISD::ADDC ? Hexagon::A4_addp_c
824 : Hexagon::A4_subp_c;
825 SDNode *C = CurDAG->getMachineNode(OpcCarry, SDLoc(N), N->getVTList(),
826 { N->getOperand(0), N->getOperand(1),
827 N->getOperand(2) });
828 ReplaceNode(N, C);
829}
830
832 MVT ResTy = N->getValueType(0).getSimpleVT();
833 if (HST->isHVXVectorType(ResTy, true))
834 return SelectHvxVAlign(N);
835
836 const SDLoc &dl(N);
837 unsigned VecLen = ResTy.getSizeInBits();
838 if (VecLen == 32) {
839 SDValue Ops[] = {
840 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
841 N->getOperand(0),
842 CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
843 N->getOperand(1),
844 CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
845 };
846 SDNode *R = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
847 MVT::i64, Ops);
848
849 // Shift right by "(Addr & 0x3) * 8" bytes.
850 SDNode *C;
851 SDValue M0 = CurDAG->getTargetConstant(0x18, dl, MVT::i32);
852 SDValue M1 = CurDAG->getTargetConstant(0x03, dl, MVT::i32);
853 if (HST->useCompound()) {
854 C = CurDAG->getMachineNode(Hexagon::S4_andi_asl_ri, dl, MVT::i32,
855 M0, N->getOperand(2), M1);
856 } else {
857 SDNode *T = CurDAG->getMachineNode(Hexagon::S2_asl_i_r, dl, MVT::i32,
858 N->getOperand(2), M1);
859 C = CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
860 SDValue(T, 0), M0);
861 }
862 SDNode *S = CurDAG->getMachineNode(Hexagon::S2_lsr_r_p, dl, MVT::i64,
863 SDValue(R, 0), SDValue(C, 0));
864 SDValue E = CurDAG->getTargetExtractSubreg(Hexagon::isub_lo, dl, ResTy,
865 SDValue(S, 0));
866 ReplaceNode(N, E.getNode());
867 } else {
868 assert(VecLen == 64);
869 SDNode *Pu = CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::v8i1,
870 N->getOperand(2));
871 SDNode *VA = CurDAG->getMachineNode(Hexagon::S2_valignrb, dl, ResTy,
872 N->getOperand(0), N->getOperand(1),
873 SDValue(Pu,0));
874 ReplaceNode(N, VA);
875 }
876}
877
879 const SDLoc &dl(N);
880 SDValue A = N->getOperand(1);
881 int Mask = -cast<ConstantSDNode>(A.getNode())->getSExtValue();
882 assert(isPowerOf2_32(-Mask));
883
884 SDValue M = CurDAG->getTargetConstant(Mask, dl, MVT::i32);
885 SDNode *AA = CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
886 N->getOperand(0), M);
887 ReplaceNode(N, AA);
888}
889
890// Handle these nodes here to avoid having to write patterns for all
891// combinations of input/output types. In all cases, the resulting
892// instruction is the same.
894 SDValue Op = N->getOperand(0);
895 MVT OpTy = Op.getValueType().getSimpleVT();
896 SDNode *T = CurDAG->MorphNodeTo(N, N->getOpcode(),
897 CurDAG->getVTList(OpTy), {Op});
898 ReplaceNode(T, Op.getNode());
899}
900
902 MVT ResTy = N->getValueType(0).getSimpleVT();
903 SDNode *T = CurDAG->getMachineNode(Hexagon::C2_mask, SDLoc(N), ResTy,
904 N->getOperand(0));
905 ReplaceNode(N, T);
906}
907
909 const SDLoc &dl(N);
910 MVT ResTy = N->getValueType(0).getSimpleVT();
911 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);
912 SDNode *T = CurDAG->getMachineNode(Hexagon::A4_vcmpbgtui, dl, ResTy,
913 N->getOperand(0), Zero);
914 ReplaceNode(N, T);
915}
916
918 const SDLoc &dl(N);
919 MVT ResTy = N->getValueType(0).getSimpleVT();
920 // The argument to V2Q should be a single vector.
921 MVT OpTy = N->getOperand(0).getValueType().getSimpleVT(); (void)OpTy;
922 assert(HST->getVectorLength() * 8 == OpTy.getSizeInBits());
923
924 SDValue C = CurDAG->getSignedTargetConstant(-1, dl, MVT::i32);
925 SDNode *R = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, C);
926 SDNode *T = CurDAG->getMachineNode(Hexagon::V6_vandvrt, dl, ResTy,
927 N->getOperand(0), SDValue(R,0));
928 ReplaceNode(N, T);
929}
930
932 const SDLoc &dl(N);
933 MVT ResTy = N->getValueType(0).getSimpleVT();
934 // The result of V2Q should be a single vector.
935 assert(HST->getVectorLength() * 8 == ResTy.getSizeInBits());
936
937 SDValue C = CurDAG->getSignedTargetConstant(-1, dl, MVT::i32);
938 SDNode *R = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, C);
939 SDNode *T = CurDAG->getMachineNode(Hexagon::V6_vandqrt, dl, ResTy,
940 N->getOperand(0), SDValue(R,0));
941 ReplaceNode(N, T);
942}
943
945 const SDLoc &dl(N);
946 ArrayRef<EVT> ResultType(N->value_begin(), N->value_end());
948 Ops = {N->getOperand(0), N->getOperand(1)};
949 SDVTList VTs;
950 VTs = CurDAG->getVTList(MVT::f32, MVT::f32);
951 SDNode *ResScale = CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs, Ops);
952 SDNode *D = CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32, Ops);
953
954 SDValue C = CurDAG->getTargetConstant(0x3f800000, dl, MVT::i32);
955 SDNode *constNode =
956 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, C);
957
958 SDNode *n = CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32, Ops);
959 SDNode *Err = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
960 SDValue(constNode, 0), SDValue(D, 0),
961 SDValue(ResScale, 0));
962 SDNode *NewRec = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
963 SDValue(ResScale, 0), SDValue(Err, 0),
964 SDValue(ResScale, 0));
965 SDNode *newErr = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
966 SDValue(constNode, 0), SDValue(D, 0),
967 SDValue(NewRec, 0));
968 SDNode *q = CurDAG->getMachineNode(
969 Hexagon::A2_andir, dl, MVT::f32, SDValue(n, 0),
970 CurDAG->getTargetConstant(0x80000000, dl, MVT::i32));
971 SDNode *NewQ =
972 CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(q, 0),
973 SDValue(n, 0), SDValue(NewRec, 0));
974 SDNode *NNewRec = CurDAG->getMachineNode(
975 Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(NewRec, 0),
976 SDValue(newErr, 0), SDValue(NewRec, 0));
977 SDNode *qErr =
978 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, SDValue(n, 0),
979 SDValue(D, 0), SDValue(NewQ, 0));
980 SDNode *NNewQ = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
981 SDValue(NewQ, 0), SDValue(qErr, 0),
982 SDValue(NNewRec, 0));
983
984 SDNode *NqErr =
985 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, SDValue(n, 0),
986 SDValue(NNewQ, 0), SDValue(D, 0));
987 std::array<SDValue, 4> temp1 = {SDValue(NNewQ, 0), SDValue(NqErr, 0),
988 SDValue(NNewRec, 0), SDValue(ResScale, 1)};
989 ArrayRef<SDValue> OpValue1(temp1);
990 SDNode *FinalNewQ =
991 CurDAG->getMachineNode(Hexagon::F2_sffma_sc, dl, MVT::f32, OpValue1);
992 ReplaceNode(N, FinalNewQ);
993}
994
996 const SDLoc &dl(N);
997 ArrayRef<EVT> ResultType(N->value_begin(), N->value_end());
999 Ops = {N->getOperand(0), N->getOperand(1)};
1000 SDVTList VTs;
1001 VTs = CurDAG->getVTList(MVT::f32, MVT::f32);
1002 SDNode *ResScale = CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs, Ops);
1003 SDNode *D = CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32, Ops);
1004
1005 SDValue C = CurDAG->getTargetConstant(0x3f800000, dl, MVT::i32);
1006 SDNode *constNode =
1007 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, C);
1008
1009 SDNode *n = CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32, Ops);
1010 SDNode *Err = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
1011 SDValue(constNode, 0), SDValue(D, 0),
1012 SDValue(ResScale, 0));
1013 SDNode *NewRec = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
1014 SDValue(ResScale, 0), SDValue(Err, 0),
1015 SDValue(ResScale, 0));
1016 SDNode *newErr = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
1017 SDValue(constNode, 0), SDValue(D, 0),
1018 SDValue(NewRec, 0));
1019
1020 SDNode *NNewRec = CurDAG->getMachineNode(
1021 Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(NewRec, 0),
1022 SDValue(newErr, 0), SDValue(NewRec, 0));
1023 SDNode *FinalNewQ = CurDAG->getMachineNode(
1024 Hexagon::F2_sfmpy, dl, MVT::f32, SDValue(NNewRec, 0), SDValue(n, 0));
1025 ReplaceNode(N, FinalNewQ);
1026}
1027
1029 if (N->getFlags().hasAllowReassociation())
1030 FastFDiv(N);
1031 else
1032 FDiv(N);
1033}
1034
1036 if (N->isMachineOpcode())
1037 return N->setNodeId(-1); // Already selected.
1038
1039 auto isHvxOp = [this](SDNode *N) {
1040 for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) {
1041 if (HST->isHVXVectorType(N->getValueType(i), true))
1042 return true;
1043 }
1044 for (SDValue I : N->ops()) {
1045 if (HST->isHVXVectorType(I.getValueType(), true))
1046 return true;
1047 }
1048 return false;
1049 };
1050
1051 if (HST->useHVXOps() && isHvxOp(N)) {
1052 switch (N->getOpcode()) {
1053 case ISD::EXTRACT_SUBVECTOR: return SelectHvxExtractSubvector(N);
1054 case ISD::VECTOR_SHUFFLE: return SelectHvxShuffle(N);
1055
1056 case HexagonISD::VROR: return SelectHvxRor(N);
1057 }
1058 }
1059
1060 switch (N->getOpcode()) {
1061 case ISD::Constant: return SelectConstant(N);
1062 case ISD::ConstantFP: return SelectConstantFP(N);
1063 case ISD::FrameIndex: return SelectFrameIndex(N);
1064 case ISD::SHL: return SelectSHL(N);
1065 case ISD::LOAD: return SelectLoad(N);
1066 case ISD::STORE: return SelectStore(N);
1070
1071 case HexagonISD::ADDC:
1072 case HexagonISD::SUBC: return SelectAddSubCarry(N);
1073 case HexagonISD::VALIGN: return SelectVAlign(N);
1074 case HexagonISD::VALIGNADDR: return SelectVAlignAddr(N);
1076 case HexagonISD::P2D: return SelectP2D(N);
1077 case HexagonISD::D2P: return SelectD2P(N);
1078 case HexagonISD::Q2V: return SelectQ2V(N);
1079 case HexagonISD::V2Q: return SelectV2Q(N);
1080 case ISD::FDIV:
1081 return SelectFDiv(N);
1082 }
1083
1084 SelectCode(N);
1085}
1086
1088 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
1089 std::vector<SDValue> &OutOps) {
1090 SDValue Inp = Op, Res;
1091
1092 switch (ConstraintID) {
1093 default:
1094 return true;
1095 case InlineAsm::ConstraintCode::o: // Offsetable.
1096 case InlineAsm::ConstraintCode::v: // Not offsetable.
1097 case InlineAsm::ConstraintCode::m: // Memory.
1098 if (SelectAddrFI(Inp, Res))
1099 OutOps.push_back(Res);
1100 else
1101 OutOps.push_back(Inp);
1102 break;
1103 }
1104
1105 OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32));
1106 return false;
1107}
1108
1109static bool isMemOPCandidate(SDNode *I, SDNode *U) {
1110 // I is an operand of U. Check if U is an arithmetic (binary) operation
1111 // usable in a memop, where the other operand is a loaded value, and the
1112 // result of U is stored in the same location.
1113
1114 if (!U->hasOneUse())
1115 return false;
1116 unsigned Opc = U->getOpcode();
1117 switch (Opc) {
1118 case ISD::ADD:
1119 case ISD::SUB:
1120 case ISD::AND:
1121 case ISD::OR:
1122 break;
1123 default:
1124 return false;
1125 }
1126
1127 SDValue S0 = U->getOperand(0);
1128 SDValue S1 = U->getOperand(1);
1129 SDValue SY = (S0.getNode() == I) ? S1 : S0;
1130
1131 SDNode *UUse = *U->user_begin();
1132 if (UUse->getNumValues() != 1)
1133 return false;
1134
1135 // Check if one of the inputs to U is a load instruction and the output
1136 // is used by a store instruction. If so and they also have the same
1137 // base pointer, then don't preoprocess this node sequence as it
1138 // can be matched to a memop.
1139 SDNode *SYNode = SY.getNode();
1140 if (UUse->getOpcode() == ISD::STORE && SYNode->getOpcode() == ISD::LOAD) {
1141 SDValue LDBasePtr = cast<MemSDNode>(SYNode)->getBasePtr();
1142 SDValue STBasePtr = cast<MemSDNode>(UUse)->getBasePtr();
1143 if (LDBasePtr == STBasePtr)
1144 return true;
1145 }
1146 return false;
1147}
1148
1149
1150// Transform: (or (select c x 0) z) -> (select c (or x z) z)
1151// (or (select c 0 y) z) -> (select c z (or y z))
1152void HexagonDAGToDAGISel::ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes) {
1153 SelectionDAG &DAG = *CurDAG;
1154
1155 for (auto *I : Nodes) {
1156 if (I->getOpcode() != ISD::OR)
1157 continue;
1158
1159 auto IsSelect0 = [](const SDValue &Op) -> bool {
1160 if (Op.getOpcode() != ISD::SELECT)
1161 return false;
1162 return isNullConstant(Op.getOperand(1)) ||
1163 isNullConstant(Op.getOperand(2));
1164 };
1165
1166 SDValue N0 = I->getOperand(0), N1 = I->getOperand(1);
1167 EVT VT = I->getValueType(0);
1168 bool SelN0 = IsSelect0(N0);
1169 SDValue SOp = SelN0 ? N0 : N1;
1170 SDValue VOp = SelN0 ? N1 : N0;
1171
1172 if (SOp.getOpcode() == ISD::SELECT && SOp.getNode()->hasOneUse()) {
1173 SDValue SC = SOp.getOperand(0);
1174 SDValue SX = SOp.getOperand(1);
1175 SDValue SY = SOp.getOperand(2);
1176 SDLoc DLS = SOp;
1177 if (isNullConstant(SY)) {
1178 SDValue NewOr = DAG.getNode(ISD::OR, DLS, VT, SX, VOp);
1179 SDValue NewSel = DAG.getNode(ISD::SELECT, DLS, VT, SC, NewOr, VOp);
1180 DAG.ReplaceAllUsesWith(I, NewSel.getNode());
1181 } else if (isNullConstant(SX)) {
1182 SDValue NewOr = DAG.getNode(ISD::OR, DLS, VT, SY, VOp);
1183 SDValue NewSel = DAG.getNode(ISD::SELECT, DLS, VT, SC, VOp, NewOr);
1184 DAG.ReplaceAllUsesWith(I, NewSel.getNode());
1185 }
1186 }
1187 }
1188}
1189
1190// Transform: (store ch val (add x (add (shl y c) e)))
1191// to: (store ch val (add x (shl (add y d) c))),
1192// where e = (shl d c) for some integer d.
1193// The purpose of this is to enable generation of loads/stores with
1194// shifted addressing mode, i.e. mem(x+y<<#c). For that, the shift
1195// value c must be 0, 1 or 2.
1196void HexagonDAGToDAGISel::ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes) {
1197 SelectionDAG &DAG = *CurDAG;
1198
1199 for (auto *I : Nodes) {
1200 if (I->getOpcode() != ISD::STORE)
1201 continue;
1202
1203 // I matched: (store ch val Off)
1204 SDValue Off = I->getOperand(2);
1205 // Off needs to match: (add x (add (shl y c) (shl d c))))
1206 if (Off.getOpcode() != ISD::ADD)
1207 continue;
1208 // Off matched: (add x T0)
1209 SDValue T0 = Off.getOperand(1);
1210 // T0 needs to match: (add T1 T2):
1211 if (T0.getOpcode() != ISD::ADD)
1212 continue;
1213 // T0 matched: (add T1 T2)
1214 SDValue T1 = T0.getOperand(0);
1215 SDValue T2 = T0.getOperand(1);
1216 // T1 needs to match: (shl y c)
1217 if (T1.getOpcode() != ISD::SHL)
1218 continue;
1219 SDValue C = T1.getOperand(1);
1220 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(C.getNode());
1221 if (CN == nullptr)
1222 continue;
1223 unsigned CV = CN->getZExtValue();
1224 if (CV > 2)
1225 continue;
1226 // T2 needs to match e, where e = (shl d c) for some d.
1227 ConstantSDNode *EN = dyn_cast<ConstantSDNode>(T2.getNode());
1228 if (EN == nullptr)
1229 continue;
1230 unsigned EV = EN->getZExtValue();
1231 if (EV % (1 << CV) != 0)
1232 continue;
1233 unsigned DV = EV / (1 << CV);
1234
1235 // Replace T0 with: (shl (add y d) c)
1236 SDLoc DL = SDLoc(I);
1237 EVT VT = T0.getValueType();
1238 SDValue D = DAG.getConstant(DV, DL, VT);
1239 // NewAdd = (add y d)
1240 SDValue NewAdd = DAG.getNode(ISD::ADD, DL, VT, T1.getOperand(0), D);
1241 // NewShl = (shl NewAdd c)
1242 SDValue NewShl = DAG.getNode(ISD::SHL, DL, VT, NewAdd, C);
1243 ReplaceNode(T0.getNode(), NewShl.getNode());
1244 }
1245}
1246
1247// Transform: (load ch (add x (and (srl y c) Mask)))
1248// to: (load ch (add x (shl (srl y d) d-c)))
1249// where
1250// Mask = 00..0 111..1 0.0
1251// | | +-- d-c 0s, and d-c is 0, 1 or 2.
1252// | +-------- 1s
1253// +-------------- at most c 0s
1254// Motivating example:
1255// DAG combiner optimizes (add x (shl (srl y 5) 2))
1256// to (add x (and (srl y 3) 1FFFFFFC))
1257// which results in a constant-extended and(##...,lsr). This transformation
1258// undoes this simplification for cases where the shl can be folded into
1259// an addressing mode.
1260void HexagonDAGToDAGISel::ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes) {
1261 SelectionDAG &DAG = *CurDAG;
1262
1263 for (SDNode *N : Nodes) {
1264 unsigned Opc = N->getOpcode();
1265 if (Opc != ISD::LOAD && Opc != ISD::STORE)
1266 continue;
1267 SDValue Addr = Opc == ISD::LOAD ? N->getOperand(1) : N->getOperand(2);
1268 // Addr must match: (add x T0)
1269 if (Addr.getOpcode() != ISD::ADD)
1270 continue;
1271 SDValue T0 = Addr.getOperand(1);
1272 // T0 must match: (and T1 Mask)
1273 if (T0.getOpcode() != ISD::AND)
1274 continue;
1275
1276 // We have an AND.
1277 //
1278 // Check the first operand. It must be: (srl y c).
1279 SDValue S = T0.getOperand(0);
1280 if (S.getOpcode() != ISD::SRL)
1281 continue;
1282 ConstantSDNode *SN = dyn_cast<ConstantSDNode>(S.getOperand(1).getNode());
1283 if (SN == nullptr)
1284 continue;
1285 if (SN->getAPIntValue().getBitWidth() != 32)
1286 continue;
1287 uint32_t CV = SN->getZExtValue();
1288
1289 // Check the second operand: the supposed mask.
1290 ConstantSDNode *MN = dyn_cast<ConstantSDNode>(T0.getOperand(1).getNode());
1291 if (MN == nullptr)
1292 continue;
1293 if (MN->getAPIntValue().getBitWidth() != 32)
1294 continue;
1295 uint32_t Mask = MN->getZExtValue();
1296 // Examine the mask.
1297 uint32_t TZ = llvm::countr_zero(Mask);
1298 uint32_t M1 = llvm::countr_one(Mask >> TZ);
1299 uint32_t LZ = llvm::countl_zero(Mask);
1300 // Trailing zeros + middle ones + leading zeros must equal the width.
1301 if (TZ + M1 + LZ != 32)
1302 continue;
1303 // The number of trailing zeros will be encoded in the addressing mode.
1304 if (TZ > 2)
1305 continue;
1306 // The number of leading zeros must be at most c.
1307 if (LZ > CV)
1308 continue;
1309
1310 // All looks good.
1311 SDValue Y = S.getOperand(0);
1312 EVT VT = Addr.getValueType();
1313 SDLoc dl(S);
1314 // TZ = D-C, so D = TZ+C.
1315 SDValue D = DAG.getConstant(TZ+CV, dl, VT);
1316 SDValue DC = DAG.getConstant(TZ, dl, VT);
1317 SDValue NewSrl = DAG.getNode(ISD::SRL, dl, VT, Y, D);
1318 SDValue NewShl = DAG.getNode(ISD::SHL, dl, VT, NewSrl, DC);
1319 ReplaceNode(T0.getNode(), NewShl.getNode());
1320 }
1321}
1322
1323// Transform: (op ... (zext i1 c) ...) -> (select c (op ... 0 ...)
1324// (op ... 1 ...))
1325void HexagonDAGToDAGISel::ppHoistZextI1(std::vector<SDNode*> &&Nodes) {
1326 SelectionDAG &DAG = *CurDAG;
1327
1328 for (SDNode *N : Nodes) {
1329 unsigned Opc = N->getOpcode();
1330 if (Opc != ISD::ZERO_EXTEND)
1331 continue;
1332 SDValue OpI1 = N->getOperand(0);
1333 EVT OpVT = OpI1.getValueType();
1334 if (!OpVT.isSimple() || OpVT.getSimpleVT() != MVT::i1)
1335 continue;
1336 for (SDUse &Use : N->uses()) {
1337 SDNode *U = Use.getUser();
1338 if (U->getNumValues() != 1)
1339 continue;
1340 EVT UVT = U->getValueType(0);
1341 if (!UVT.isSimple() || !UVT.isInteger() || UVT.getSimpleVT() == MVT::i1)
1342 continue;
1343 // Do not generate select for all i1 vector type.
1344 if (UVT.isVectorOf(MVT::i1))
1345 continue;
1346 if (isMemOPCandidate(N, U))
1347 continue;
1348
1349 // Potentially simplifiable operation.
1350 unsigned I1N = Use.getOperandNo();
1351 SmallVector<SDValue,2> Ops(U->getNumOperands());
1352 for (unsigned i = 0, n = U->getNumOperands(); i != n; ++i)
1353 Ops[i] = U->getOperand(i);
1354 EVT BVT = Ops[I1N].getValueType();
1355
1356 const SDLoc &dl(U);
1357 SDValue C0 = DAG.getConstant(0, dl, BVT);
1358 SDValue C1 = DAG.getConstant(1, dl, BVT);
1359 SDValue If0, If1;
1360
1361 if (isa<MachineSDNode>(U)) {
1362 unsigned UseOpc = U->getMachineOpcode();
1363 Ops[I1N] = C0;
1364 If0 = SDValue(DAG.getMachineNode(UseOpc, dl, UVT, Ops), 0);
1365 Ops[I1N] = C1;
1366 If1 = SDValue(DAG.getMachineNode(UseOpc, dl, UVT, Ops), 0);
1367 } else {
1368 unsigned UseOpc = U->getOpcode();
1369 Ops[I1N] = C0;
1370 If0 = DAG.getNode(UseOpc, dl, UVT, Ops);
1371 Ops[I1N] = C1;
1372 If1 = DAG.getNode(UseOpc, dl, UVT, Ops);
1373 }
1374 // We're generating a SELECT way after legalization, so keep the types
1375 // simple.
1376 unsigned UW = UVT.getSizeInBits();
1377 EVT SVT = (UW == 32 || UW == 64) ? MVT::getIntegerVT(UW) : UVT;
1378 SDValue Sel = DAG.getNode(ISD::SELECT, dl, SVT, OpI1,
1379 DAG.getBitcast(SVT, If1),
1380 DAG.getBitcast(SVT, If0));
1381 SDValue Ret = DAG.getBitcast(UVT, Sel);
1382 DAG.ReplaceAllUsesWith(U, Ret.getNode());
1383 }
1384 }
1385}
1386
1388 // Repack all nodes before calling each preprocessing function,
1389 // because each of them can modify the set of nodes.
1390 auto getNodes = [this]() -> std::vector<SDNode *> {
1391 std::vector<SDNode *> T;
1392 T.reserve(CurDAG->allnodes_size());
1393 for (SDNode &N : CurDAG->allnodes())
1394 T.push_back(&N);
1395 return T;
1396 };
1397
1398 if (HST->useHVXOps())
1399 PreprocessHvxISelDAG();
1400
1401 // Transform: (or (select c x 0) z) -> (select c (or x z) z)
1402 // (or (select c 0 y) z) -> (select c z (or y z))
1403 ppSimplifyOrSelect0(getNodes());
1404
1405 // Transform: (store ch val (add x (add (shl y c) e)))
1406 // to: (store ch val (add x (shl (add y d) c))),
1407 // where e = (shl d c) for some integer d.
1408 // The purpose of this is to enable generation of loads/stores with
1409 // shifted addressing mode, i.e. mem(x+y<<#c). For that, the shift
1410 // value c must be 0, 1 or 2.
1411 ppAddrReorderAddShl(getNodes());
1412
1413 // Transform: (load ch (add x (and (srl y c) Mask)))
1414 // to: (load ch (add x (shl (srl y d) d-c)))
1415 // where
1416 // Mask = 00..0 111..1 0.0
1417 // | | +-- d-c 0s, and d-c is 0, 1 or 2.
1418 // | +-------- 1s
1419 // +-------------- at most c 0s
1420 // Motivating example:
1421 // DAG combiner optimizes (add x (shl (srl y 5) 2))
1422 // to (add x (and (srl y 3) 1FFFFFFC))
1423 // which results in a constant-extended and(##...,lsr). This transformation
1424 // undoes this simplification for cases where the shl can be folded into
1425 // an addressing mode.
1426 ppAddrRewriteAndSrl(getNodes());
1427
1428 // Transform: (op ... (zext i1 c) ...) -> (select c (op ... 0 ...)
1429 // (op ... 1 ...))
1430 ppHoistZextI1(getNodes());
1431
1432 DEBUG_WITH_TYPE("isel", {
1433 dbgs() << "Preprocessed (Hexagon) selection DAG:";
1434 CurDAG->dump();
1435 });
1436
1438 rebalanceAddressTrees();
1439
1440 DEBUG_WITH_TYPE("isel", {
1441 dbgs() << "Address tree balanced selection DAG:";
1442 CurDAG->dump();
1443 });
1444 }
1445}
1446
1448 auto &HST = MF->getSubtarget<HexagonSubtarget>();
1449 auto &HFI = *HST.getFrameLowering();
1450 if (!HFI.needsAligna(*MF))
1451 return;
1452
1453 auto &HRI = *HST.getRegisterInfo();
1454 Register AP = HRI.computeStackAlignBaseRegister(*MF);
1455 assert(AP.isValid() && "Couldn't reserve stack align register");
1456 MF->getInfo<HexagonMachineFunctionInfo>()->setStackAlignBaseReg(AP);
1457}
1458
1459// Match a frame index that can be used in an addressing mode.
1461 if (N.getOpcode() != ISD::FrameIndex)
1462 return false;
1463 auto &HFI = *HST->getFrameLowering();
1464 MachineFrameInfo &MFI = MF->getFrameInfo();
1465 int FX = cast<FrameIndexSDNode>(N)->getIndex();
1466 if (!MFI.isFixedObjectIndex(FX) && HFI.needsAligna(*MF))
1467 return false;
1468 R = CurDAG->getTargetFrameIndex(FX, MVT::i32);
1469 return true;
1470}
1471
1473 return SelectGlobalAddress(N, R, false, Align(1));
1474}
1475
1477 return SelectGlobalAddress(N, R, true, Align(1));
1478}
1479
1481 return SelectAnyImmediate(N, R, Align(1));
1482}
1483
1485 return SelectAnyImmediate(N, R, Align(1));
1486}
1488 return SelectAnyImmediate(N, R, Align(2));
1489}
1491 return SelectAnyImmediate(N, R, Align(4));
1492}
1494 return SelectAnyImmediate(N, R, Align(8));
1495}
1496
1498 EVT T = N.getValueType();
1499 if (!T.isInteger() || T.getSizeInBits() != 32 || !isa<ConstantSDNode>(N))
1500 return false;
1501 uint32_t V = cast<const ConstantSDNode>(N)->getZExtValue();
1502 R = CurDAG->getTargetConstant(V, SDLoc(N), N.getValueType());
1503 return true;
1504}
1505
1507 Align Alignment) {
1508 switch (N.getOpcode()) {
1509 case ISD::Constant: {
1510 if (N.getValueType() != MVT::i32)
1511 return false;
1512 uint32_t V = cast<const ConstantSDNode>(N)->getZExtValue();
1513 if (!isAligned(Alignment, V))
1514 return false;
1515 R = CurDAG->getTargetConstant(V, SDLoc(N), N.getValueType());
1516 return true;
1517 }
1518 case HexagonISD::JT:
1519 case HexagonISD::CP:
1520 // These are assumed to always be aligned at least 8-byte boundary.
1521 if (Alignment > Align(8))
1522 return false;
1523 R = N.getOperand(0);
1524 return true;
1526 // Symbols may be aligned at any boundary.
1527 if (Alignment > Align(1))
1528 return false;
1529 R = N;
1530 return true;
1531 case ISD::BlockAddress:
1532 // Block address is always aligned at least 4-byte boundary.
1533 if (Alignment > Align(4) ||
1535 return false;
1536 R = N;
1537 return true;
1538 }
1539
1540 if (SelectGlobalAddress(N, R, false, Alignment) ||
1541 SelectGlobalAddress(N, R, true, Alignment))
1542 return true;
1543
1544 return false;
1545}
1546
1548 bool UseGP, Align Alignment) {
1549 switch (N.getOpcode()) {
1550 case ISD::ADD: {
1551 SDValue N0 = N.getOperand(0);
1552 SDValue N1 = N.getOperand(1);
1553 unsigned GAOpc = N0.getOpcode();
1554 if (UseGP && GAOpc != HexagonISD::CONST32_GP)
1555 return false;
1556 if (!UseGP && GAOpc != HexagonISD::CONST32)
1557 return false;
1558 if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1)) {
1559 if (!isAligned(Alignment, Const->getZExtValue()))
1560 return false;
1561 SDValue Addr = N0.getOperand(0);
1563 if (GA->getOpcode() == ISD::TargetGlobalAddress) {
1564 uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
1565 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(Const),
1566 N.getValueType(), NewOff);
1567 return true;
1568 }
1569 }
1570 }
1571 break;
1572 }
1573 case HexagonISD::CP:
1574 case HexagonISD::JT:
1575 case HexagonISD::CONST32:
1576 // The operand(0) of CONST32 is TargetGlobalAddress, which is what we
1577 // want in the instruction.
1578 if (!UseGP)
1579 R = N.getOperand(0);
1580 return !UseGP;
1581 case HexagonISD::CONST32_GP:
1582 if (UseGP)
1583 R = N.getOperand(0);
1584 return UseGP;
1585 default:
1586 return false;
1587 }
1588
1589 return false;
1590}
1591
1593 // This (complex pattern) function is meant to detect a sign-extension
1594 // i32->i64 on a per-operand basis. This would allow writing single
1595 // patterns that would cover a number of combinations of different ways
1596 // a sign-extensions could be written. For example:
1597 // (mul (DetectUseSxtw x) (DetectUseSxtw y)) -> (M2_dpmpyss_s0 x y)
1598 // could match either one of these:
1599 // (mul (sext x) (sext_inreg y))
1600 // (mul (sext-load *p) (sext_inreg y))
1601 // (mul (sext_inreg x) (sext y))
1602 // etc.
1603 //
1604 // The returned value will have type i64 and its low word will
1605 // contain the value being extended. The high bits are not specified.
1606 // The returned type is i64 because the original type of N was i64,
1607 // but the users of this function should only use the low-word of the
1608 // result, e.g.
1609 // (mul sxtw:x, sxtw:y) -> (M2_dpmpyss_s0 (LoReg sxtw:x), (LoReg sxtw:y))
1610
1611 if (N.getValueType() != MVT::i64)
1612 return false;
1613 unsigned Opc = N.getOpcode();
1614 switch (Opc) {
1615 case ISD::SIGN_EXTEND:
1617 // sext_inreg has the source type as a separate operand.
1619 ? N.getOperand(0).getValueType()
1620 : cast<VTSDNode>(N.getOperand(1))->getVT();
1621 unsigned SW = T.getSizeInBits();
1622 if (SW == 32)
1623 R = N.getOperand(0);
1624 else if (SW < 32)
1625 R = N;
1626 else
1627 return false;
1628 break;
1629 }
1630 case ISD::LOAD: {
1632 if (L->getExtensionType() != ISD::SEXTLOAD)
1633 return false;
1634 // All extending loads extend to i32, so even if the value in
1635 // memory is shorter than 32 bits, it will be i32 after the load.
1636 if (L->getMemoryVT().getSizeInBits() > 32)
1637 return false;
1638 R = N;
1639 break;
1640 }
1641 case ISD::SRA: {
1642 auto *S = dyn_cast<ConstantSDNode>(N.getOperand(1));
1643 if (!S || S->getZExtValue() != 32)
1644 return false;
1645 R = N;
1646 break;
1647 }
1648 case ISD::AssertSext: {
1649 EVT T = cast<VTSDNode>(N.getOperand(1))->getVT();
1650 if (T.getSizeInBits() == 32)
1651 R = N.getOperand(0);
1652 else
1653 return false;
1654 break;
1655 }
1656
1657 default:
1658 return false;
1659 }
1660 EVT RT = R.getValueType();
1661 if (RT == MVT::i64)
1662 return true;
1663 assert(RT == MVT::i32);
1664 // This is only to produce a value of type i64. Do not rely on the
1665 // high bits produced by this.
1666 const SDLoc &dl(N);
1667 SDValue Ops[] = {
1668 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
1669 R, CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
1670 R, CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
1671 };
1672 SDNode *T = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
1673 MVT::i64, Ops);
1674 R = SDValue(T, 0);
1675 return true;
1676}
1677
1678bool HexagonDAGToDAGISel::keepsLowBits(const SDValue &Val, unsigned NumBits,
1679 SDValue &Src) {
1680 unsigned Opc = Val.getOpcode();
1681 switch (Opc) {
1682 case ISD::SIGN_EXTEND:
1683 case ISD::ZERO_EXTEND:
1684 case ISD::ANY_EXTEND: {
1685 const SDValue &Op0 = Val.getOperand(0);
1686 EVT T = Op0.getValueType();
1687 if (T.isInteger() && T.getSizeInBits() == NumBits) {
1688 Src = Op0;
1689 return true;
1690 }
1691 break;
1692 }
1694 case ISD::AssertSext:
1695 case ISD::AssertZext:
1696 if (Val.getOperand(0).getValueType().isInteger()) {
1697 VTSDNode *T = cast<VTSDNode>(Val.getOperand(1));
1698 if (T->getVT().getSizeInBits() == NumBits) {
1699 Src = Val.getOperand(0);
1700 return true;
1701 }
1702 }
1703 break;
1704 case ISD::AND: {
1705 // Check if this is an AND with NumBits of lower bits set to 1.
1706 uint64_t Mask = (1ULL << NumBits) - 1;
1707 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1708 if (C->getZExtValue() == Mask) {
1709 Src = Val.getOperand(1);
1710 return true;
1711 }
1712 }
1713 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1714 if (C->getZExtValue() == Mask) {
1715 Src = Val.getOperand(0);
1716 return true;
1717 }
1718 }
1719 break;
1720 }
1721 case ISD::OR:
1722 case ISD::XOR: {
1723 // OR/XOR with the lower NumBits bits set to 0.
1724 uint64_t Mask = (1ULL << NumBits) - 1;
1725 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1726 if ((C->getZExtValue() & Mask) == 0) {
1727 Src = Val.getOperand(1);
1728 return true;
1729 }
1730 }
1731 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1732 if ((C->getZExtValue() & Mask) == 0) {
1733 Src = Val.getOperand(0);
1734 return true;
1735 }
1736 }
1737 break;
1738 }
1739 default:
1740 break;
1741 }
1742 return false;
1743}
1744
1745bool HexagonDAGToDAGISel::isAlignedMemNode(const MemSDNode *N) const {
1746 return N->getAlign().value() >= N->getMemoryVT().getStoreSize();
1747}
1748
1749bool HexagonDAGToDAGISel::isSmallStackStore(const StoreSDNode *N) const {
1750 unsigned StackSize = MF->getFrameInfo().estimateStackSize(*MF);
1751 switch (N->getMemoryVT().getStoreSize()) {
1752 case 1:
1753 return StackSize <= 56; // 1*2^6 - 8
1754 case 2:
1755 return StackSize <= 120; // 2*2^6 - 8
1756 case 4:
1757 return StackSize <= 248; // 4*2^6 - 8
1758 default:
1759 return false;
1760 }
1761}
1762
1763// Return true when the given node fits in a positive half word.
1764bool HexagonDAGToDAGISel::isPositiveHalfWord(const SDNode *N) const {
1765 if (const ConstantSDNode *CN = dyn_cast<const ConstantSDNode>(N)) {
1766 int64_t V = CN->getSExtValue();
1767 return V > 0 && isInt<16>(V);
1768 }
1769 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) {
1770 const VTSDNode *VN = dyn_cast<const VTSDNode>(N->getOperand(1));
1771 return VN->getVT().getSizeInBits() <= 16;
1772 }
1773 return false;
1774}
1775
1776bool HexagonDAGToDAGISel::hasOneUse(const SDNode *N) const {
1777 return !CheckSingleUse || N->hasOneUse();
1778}
1779
1780////////////////////////////////////////////////////////////////////////////////
1781// Rebalancing of address calculation trees
1782
1783static bool isOpcodeHandled(const SDNode *N) {
1784 switch (N->getOpcode()) {
1785 case ISD::ADD:
1786 case ISD::MUL:
1787 return true;
1788 case ISD::SHL:
1789 // We only handle constant shifts because these can be easily flattened
1790 // into multiplications by 2^Op1.
1791 return N->getNumOperands() >= 2 &&
1792 isa<ConstantSDNode>(N->getOperand(1).getNode());
1793 default:
1794 return false;
1795 }
1796}
1797
1798/// Return the weight of an SDNode
1799int HexagonDAGToDAGISel::getWeight(SDNode *N) {
1800 if (!isOpcodeHandled(N))
1801 return 1;
1802 assert(RootWeights.count(N) && "Cannot get weight of unseen root!");
1803 assert(RootWeights[N] != -1 && "Cannot get weight of unvisited root!");
1804 assert(RootWeights[N] != -2 && "Cannot get weight of RAWU'd root!");
1805 return RootWeights[N];
1806}
1807
1808int HexagonDAGToDAGISel::getHeight(SDNode *N) {
1809 if (!isOpcodeHandled(N))
1810 return 0;
1811 assert(RootWeights.count(N) && RootWeights[N] >= 0 &&
1812 "Cannot query height of unvisited/RAUW'd node!");
1813 return RootHeights[N];
1814}
1815
1816namespace {
1817struct WeightedLeaf {
1818 SDValue Value;
1819 int Weight;
1820 int InsertionOrder;
1821
1822 WeightedLeaf() = default;
1823
1824 WeightedLeaf(SDValue Value, int Weight, int InsertionOrder) :
1825 Value(Value), Weight(Weight), InsertionOrder(InsertionOrder) {
1826 assert(Weight >= 0 && "Weight must be >= 0");
1827 }
1828
1829 static bool Compare(const WeightedLeaf &A, const WeightedLeaf &B) {
1830 assert(A.Value.getNode() && B.Value.getNode());
1831 return A.Weight == B.Weight ?
1832 (A.InsertionOrder > B.InsertionOrder) :
1833 (A.Weight > B.Weight);
1834 }
1835};
1836
1837/// A specialized priority queue for WeigthedLeaves. It automatically folds
1838/// constants and allows removal of non-top elements while maintaining the
1839/// priority order.
1840class LeafPrioQueue {
1842 bool HaveConst;
1843 WeightedLeaf ConstElt;
1844 unsigned Opcode;
1845
1846public:
1847 bool empty() {
1848 return (!HaveConst && Q.empty());
1849 }
1850
1851 size_t size() {
1852 return Q.size() + HaveConst;
1853 }
1854
1855 bool hasConst() {
1856 return HaveConst;
1857 }
1858
1859 const WeightedLeaf &top() {
1860 if (HaveConst)
1861 return ConstElt;
1862 return Q.front();
1863 }
1864
1865 WeightedLeaf pop() {
1866 if (HaveConst) {
1867 HaveConst = false;
1868 return ConstElt;
1869 }
1870 std::pop_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);
1871 return Q.pop_back_val();
1872 }
1873
1874 void push(WeightedLeaf L, bool SeparateConst=true) {
1875 if (!HaveConst && SeparateConst && isa<ConstantSDNode>(L.Value)) {
1876 if (Opcode == ISD::MUL &&
1877 cast<ConstantSDNode>(L.Value)->getSExtValue() == 1)
1878 return;
1879 if (Opcode == ISD::ADD &&
1880 cast<ConstantSDNode>(L.Value)->getSExtValue() == 0)
1881 return;
1882
1883 HaveConst = true;
1884 ConstElt = L;
1885 } else {
1886 Q.push_back(L);
1887 std::push_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);
1888 }
1889 }
1890
1891 /// Push L to the bottom of the queue regardless of its weight. If L is
1892 /// constant, it will not be folded with other constants in the queue.
1893 void pushToBottom(WeightedLeaf L) {
1894 L.Weight = 1000;
1895 push(L, false);
1896 }
1897
1898 /// Search for a SHL(x, [<=MaxAmount]) subtree in the queue, return the one of
1899 /// lowest weight and remove it from the queue.
1900 WeightedLeaf findSHL(uint64_t MaxAmount);
1901
1902 WeightedLeaf findMULbyConst();
1903
1904 LeafPrioQueue(unsigned Opcode) :
1905 HaveConst(false), Opcode(Opcode) { }
1906};
1907} // end anonymous namespace
1908
1909WeightedLeaf LeafPrioQueue::findSHL(uint64_t MaxAmount) {
1910 int ResultPos;
1911 WeightedLeaf Result;
1912
1913 for (int Pos = 0, End = Q.size(); Pos != End; ++Pos) {
1914 const WeightedLeaf &L = Q[Pos];
1915 const SDValue &Val = L.Value;
1916 if (Val.getOpcode() != ISD::SHL || Val.getNumOperands() < 2 ||
1918 Val.getConstantOperandVal(1) > MaxAmount)
1919 continue;
1920 if (!Result.Value.getNode() || Result.Weight > L.Weight ||
1921 (Result.Weight == L.Weight && Result.InsertionOrder > L.InsertionOrder))
1922 {
1923 Result = L;
1924 ResultPos = Pos;
1925 }
1926 }
1927
1928 if (Result.Value.getNode()) {
1929 Q.erase(&Q[ResultPos]);
1930 std::make_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);
1931 }
1932
1933 return Result;
1934}
1935
1936WeightedLeaf LeafPrioQueue::findMULbyConst() {
1937 int ResultPos;
1938 WeightedLeaf Result;
1939
1940 for (int Pos = 0, End = Q.size(); Pos != End; ++Pos) {
1941 const WeightedLeaf &L = Q[Pos];
1942 const SDValue &Val = L.Value;
1943 if (Val.getOpcode() != ISD::MUL || Val.getNumOperands() < 2 ||
1945 Val.getConstantOperandVal(1) > 127)
1946 continue;
1947 if (!Result.Value.getNode() || Result.Weight > L.Weight ||
1948 (Result.Weight == L.Weight && Result.InsertionOrder > L.InsertionOrder))
1949 {
1950 Result = L;
1951 ResultPos = Pos;
1952 }
1953 }
1954
1955 if (Result.Value.getNode()) {
1956 Q.erase(&Q[ResultPos]);
1957 std::make_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);
1958 }
1959
1960 return Result;
1961}
1962
1963SDValue HexagonDAGToDAGISel::getMultiplierForSHL(SDNode *N) {
1964 if (N->getNumOperands() < 2)
1965 return SDValue();
1966 uint64_t MulFactor = 1ull << N->getConstantOperandVal(1);
1967 return CurDAG->getConstant(MulFactor, SDLoc(N),
1968 N->getOperand(1).getValueType());
1969}
1970
1971/// @returns the value x for which 2^x is a factor of Val
1972static unsigned getPowerOf2Factor(SDValue Val) {
1973 if (Val.getOpcode() == ISD::MUL) {
1974 if (Val.getNumOperands() < 2)
1975 return 0;
1976 unsigned MaxFactor = 0;
1977 for (int i = 0; i < 2; ++i) {
1979 if (!C)
1980 continue;
1981 const APInt &CInt = C->getAPIntValue();
1982 if (CInt.getBoolValue())
1983 MaxFactor = CInt.countr_zero();
1984 }
1985 return MaxFactor;
1986 }
1987 if (Val.getOpcode() == ISD::SHL) {
1988 if (Val.getNumOperands() < 2 ||
1990 return 0;
1991 return (unsigned) Val.getConstantOperandVal(1);
1992 }
1993
1994 return 0;
1995}
1996
1997/// @returns true if V>>Amount will eliminate V's operation on its child
1998static bool willShiftRightEliminate(SDValue V, unsigned Amount) {
1999 if (V.getOpcode() == ISD::MUL) {
2000 if (V.getNumOperands() < 2)
2001 return false;
2002 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };
2003 for (int i = 0; i < 2; ++i)
2004 if (isa<ConstantSDNode>(Ops[i].getNode()) &&
2005 V.getConstantOperandVal(i) % (1ULL << Amount) == 0) {
2006 uint64_t NewConst = V.getConstantOperandVal(i) >> Amount;
2007 return (NewConst == 1);
2008 }
2009 } else if (V.getOpcode() == ISD::SHL) {
2010 if (V.getNumOperands() < 2 ||
2011 !isa<ConstantSDNode>(V.getOperand(1).getNode()))
2012 return false;
2013 return (Amount == V.getConstantOperandVal(1));
2014 }
2015
2016 return false;
2017}
2018
2019SDValue HexagonDAGToDAGISel::factorOutPowerOf2(SDValue V, unsigned Power) {
2020 // Ensure the node has at least 2 operands before accessing them.
2021 if (V.getNumOperands() < 2)
2022 return V;
2023
2024 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };
2025 if (V.getOpcode() == ISD::MUL) {
2026 for (int i=0; i < 2; ++i) {
2027 if (isa<ConstantSDNode>(Ops[i].getNode()) &&
2028 V.getConstantOperandVal(i) % ((uint64_t)1 << Power) == 0) {
2029 uint64_t NewConst = V.getConstantOperandVal(i) >> Power;
2030 if (NewConst == 1)
2031 return Ops[!i];
2032 Ops[i] = CurDAG->getConstant(NewConst,
2033 SDLoc(V), V.getValueType());
2034 break;
2035 }
2036 }
2037 } else if (V.getOpcode() == ISD::SHL) {
2038 if (!isa<ConstantSDNode>(V.getOperand(1).getNode()))
2039 return V;
2040 uint64_t ShiftAmount = V.getConstantOperandVal(1);
2041 if (ShiftAmount == Power)
2042 return Ops[0];
2043 Ops[1] = CurDAG->getConstant(ShiftAmount - Power,
2044 SDLoc(V), V.getValueType());
2045 }
2046
2047 return CurDAG->getNode(V.getOpcode(), SDLoc(V), V.getValueType(), Ops);
2048}
2049
2050static bool isTargetConstant(const SDValue &V) {
2051 return V.getOpcode() == HexagonISD::CONST32 ||
2052 V.getOpcode() == HexagonISD::CONST32_GP;
2053}
2054
2055unsigned HexagonDAGToDAGISel::getUsesInFunction(const Value *V) {
2056 auto [It, Inserted] = GAUsesInFunction.try_emplace(V);
2057 if (!Inserted)
2058 return It->second;
2059
2060 unsigned Result = 0;
2061 const Function &CurF = CurDAG->getMachineFunction().getFunction();
2062 for (const User *U : V->users()) {
2063 if (isa<Instruction>(U) &&
2064 cast<Instruction>(U)->getParent()->getParent() == &CurF)
2065 ++Result;
2066 }
2067
2068 It->second = Result;
2069
2070 return Result;
2071}
2072
2073/// Note - After calling this, N may be dead. It may have been replaced by a
2074/// new node, so always use the returned value in place of N.
2075///
2076/// @returns The SDValue taking the place of N (which could be N if it is
2077/// unchanged)
2078SDValue HexagonDAGToDAGISel::balanceSubTree(SDNode *N, bool TopLevel) {
2079 assert(RootWeights.count(N) && "Cannot balance non-root node.");
2080 assert(RootWeights[N] != -2 && "This node was RAUW'd!");
2081 assert(!TopLevel || N->getOpcode() == ISD::ADD);
2082
2083 // Return early if this node was already visited
2084 if (RootWeights[N] != -1)
2085 return SDValue(N, 0);
2086
2088
2089 if (N->getNumOperands() < 2)
2090 return SDValue(N, 0);
2091
2092 SDValue Op0 = N->getOperand(0);
2093 SDValue Op1 = N->getOperand(1);
2094
2095 // Return early if the operands will remain unchanged or are all roots
2096 if ((!isOpcodeHandled(Op0.getNode()) || RootWeights.count(Op0.getNode())) &&
2097 (!isOpcodeHandled(Op1.getNode()) || RootWeights.count(Op1.getNode()))) {
2098 SDNode *Op0N = Op0.getNode();
2099 int Weight;
2100 if (isOpcodeHandled(Op0N) && RootWeights[Op0N] == -1) {
2101 Weight = getWeight(balanceSubTree(Op0N).getNode());
2102 // Weight = calculateWeight(Op0N);
2103 } else
2104 Weight = getWeight(Op0N);
2105
2106 SDNode *Op1N = Op1.getNode();
2107 if (isOpcodeHandled(Op1N) && RootWeights[Op1N] == -1) {
2108 Weight += getWeight(balanceSubTree(Op1N).getNode());
2109 // Weight += calculateWeight(Op1N);
2110 } else
2111 Weight += getWeight(Op1N);
2112
2113 RootWeights[N] = Weight;
2114
2115 // After recursive calls, check if Op0/Op1 are still valid before getting
2116 // height
2117 int Height0 = 0, Height1 = 0;
2118 if (isOpcodeHandled(Op0N) && RootWeights.count(Op0N) &&
2119 RootWeights[Op0N] >= 0)
2120 Height0 = getHeight(Op0N);
2121 if (isOpcodeHandled(Op1N) && RootWeights.count(Op1N) &&
2122 RootWeights[Op1N] >= 0)
2123 Height1 = getHeight(Op1N);
2124
2125 RootHeights[N] = std::max(Height0, Height1) + 1;
2126
2127 LLVM_DEBUG(dbgs() << "--> No need to balance root (Weight=" << Weight
2128 << " Height=" << RootHeights[N] << "): ");
2129 LLVM_DEBUG(N->dump(CurDAG));
2130
2131 return SDValue(N, 0);
2132 }
2133
2134 LLVM_DEBUG(dbgs() << "** Balancing root node: ");
2135 LLVM_DEBUG(N->dump(CurDAG));
2136
2137 unsigned NOpcode = N->getOpcode();
2138
2139 LeafPrioQueue Leaves(NOpcode);
2140 SmallVector<SDValue, 4> Worklist;
2141 Worklist.push_back(SDValue(N, 0));
2142
2143 // SHL nodes will be converted to MUL nodes
2144 if (NOpcode == ISD::SHL)
2145 NOpcode = ISD::MUL;
2146
2147 bool CanFactorize = false;
2148 WeightedLeaf Mul1, Mul2;
2149 unsigned MaxPowerOf2 = 0;
2150 WeightedLeaf GA;
2151
2152 // Do not try to factor out a shift if there is already a shift at the tip of
2153 // the tree.
2154 bool HaveTopLevelShift = false;
2155 if (TopLevel &&
2156 ((isOpcodeHandled(Op0.getNode()) && Op0.getOpcode() == ISD::SHL &&
2157 Op0.getNumOperands() >= 2 && Op0.getConstantOperandVal(1) < 4) ||
2158 (isOpcodeHandled(Op1.getNode()) && Op1.getOpcode() == ISD::SHL &&
2159 Op1.getNumOperands() >= 2 && Op1.getConstantOperandVal(1) < 4)))
2160 HaveTopLevelShift = true;
2161
2162 // Flatten the subtree into an ordered list of leaves; at the same time
2163 // determine whether the tree is already balanced.
2164 int InsertionOrder = 0;
2165 SmallDenseMap<SDValue, int> NodeHeights;
2166 bool Imbalanced = false;
2167 int CurrentWeight = 0;
2168 while (!Worklist.empty()) {
2169 SDValue Child = Worklist.pop_back_val();
2170
2171 if (Child.getNode() != N && RootWeights.count(Child.getNode())) {
2172 // CASE 1: Child is a root note
2173
2174 int Weight = RootWeights[Child.getNode()];
2175 if (Weight == -1) {
2176 Child = balanceSubTree(Child.getNode());
2177 // calculateWeight(Child.getNode());
2178 Weight = getWeight(Child.getNode());
2179 } else if (Weight == -2) {
2180 // Whoops, this node was RAUWd by one of the balanceSubTree calls we
2181 // made. Our worklist isn't up to date anymore.
2182 // Restart the whole process.
2183 LLVM_DEBUG(dbgs() << "--> Subtree was RAUWd. Restarting...\n");
2184 return balanceSubTree(N, TopLevel);
2185 }
2186
2187 NodeHeights[Child] = 1;
2188 CurrentWeight += Weight;
2189
2190 unsigned PowerOf2;
2191 if (TopLevel && !CanFactorize && !HaveTopLevelShift &&
2192 (Child.getOpcode() == ISD::MUL || Child.getOpcode() == ISD::SHL) &&
2193 Child.hasOneUse() && (PowerOf2 = getPowerOf2Factor(Child))) {
2194 // Try to identify two factorizable MUL/SHL children greedily. Leave
2195 // them out of the priority queue for now so we can deal with them
2196 // after.
2197 if (!Mul1.Value.getNode()) {
2198 Mul1 = WeightedLeaf(Child, Weight, InsertionOrder++);
2199 MaxPowerOf2 = PowerOf2;
2200 } else {
2201 Mul2 = WeightedLeaf(Child, Weight, InsertionOrder++);
2202 MaxPowerOf2 = std::min(MaxPowerOf2, PowerOf2);
2203
2204 // Our addressing modes can only shift by a maximum of 3
2205 if (MaxPowerOf2 > 3)
2206 MaxPowerOf2 = 3;
2207
2208 CanFactorize = true;
2209 }
2210 } else
2211 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2212 } else if (!isOpcodeHandled(Child.getNode())) {
2213 // CASE 2: Child is an unhandled kind of node (e.g. constant)
2214 int Weight = getWeight(Child.getNode());
2215
2216 NodeHeights[Child] = getHeight(Child.getNode());
2217 CurrentWeight += Weight;
2218
2219 if (isTargetConstant(Child) && !GA.Value.getNode())
2220 GA = WeightedLeaf(Child, Weight, InsertionOrder++);
2221 else
2222 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2223 } else {
2224 // CASE 3: Child is a subtree of same opcode
2225 // Visit children first, then flatten.
2226 unsigned ChildOpcode = Child.getOpcode();
2227 assert(ChildOpcode == NOpcode ||
2228 (NOpcode == ISD::MUL && ChildOpcode == ISD::SHL));
2229
2230 if (Child->getNumOperands() < 2) {
2231 // Treat as a leaf if not enough operands
2232 int Weight = getWeight(Child.getNode());
2233 NodeHeights[Child] = getHeight(Child.getNode());
2234 CurrentWeight += Weight;
2235 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2236 continue;
2237 }
2238
2239 // Convert SHL to MUL
2240 SDValue Op1;
2241 if (ChildOpcode == ISD::SHL) {
2242 Op1 = getMultiplierForSHL(Child.getNode());
2243 assert(Op1.getNode() && "getMultiplierForSHL returned null");
2244 } else
2245 Op1 = Child->getOperand(1);
2246
2247 if (!NodeHeights.count(Op1) || !NodeHeights.count(Child->getOperand(0))) {
2248 assert(!NodeHeights.count(Child) && "Parent visited before children?");
2249 // Visit children first, then re-visit this node
2250 Worklist.push_back(Child);
2251 Worklist.push_back(Op1);
2252 Worklist.push_back(Child->getOperand(0));
2253 } else {
2254 // Back at this node after visiting the children
2255 if (std::abs(NodeHeights[Op1] - NodeHeights[Child->getOperand(0)]) > 1)
2256 Imbalanced = true;
2257
2258 NodeHeights[Child] = std::max(NodeHeights[Op1],
2259 NodeHeights[Child->getOperand(0)]) + 1;
2260 }
2261 }
2262 }
2263
2264 LLVM_DEBUG(dbgs() << "--> Current height=" << NodeHeights[SDValue(N, 0)]
2265 << " weight=" << CurrentWeight
2266 << " imbalanced=" << Imbalanced << "\n");
2267
2268 // Transform MUL(x, C * 2^Y) + SHL(z, Y) -> SHL(ADD(MUL(x, C), z), Y)
2269 // This factors out a shift in order to match memw(a<<Y+b).
2270 if (CanFactorize && (willShiftRightEliminate(Mul1.Value, MaxPowerOf2) ||
2271 willShiftRightEliminate(Mul2.Value, MaxPowerOf2))) {
2272 LLVM_DEBUG(dbgs() << "--> Found common factor for two MUL children!\n");
2273 int Weight = Mul1.Weight + Mul2.Weight;
2274 int Height = std::max(NodeHeights[Mul1.Value], NodeHeights[Mul2.Value]) + 1;
2275 SDValue Mul1Factored = factorOutPowerOf2(Mul1.Value, MaxPowerOf2);
2276 SDValue Mul2Factored = factorOutPowerOf2(Mul2.Value, MaxPowerOf2);
2277 SDValue Sum = CurDAG->getNode(ISD::ADD, SDLoc(N), Mul1.Value.getValueType(),
2278 Mul1Factored, Mul2Factored);
2279 SDValue Const = CurDAG->getConstant(MaxPowerOf2, SDLoc(N),
2280 Mul1.Value.getValueType());
2281 SDValue New = CurDAG->getNode(ISD::SHL, SDLoc(N), Mul1.Value.getValueType(),
2282 Sum, Const);
2283 NodeHeights[New] = Height;
2284 Leaves.push(WeightedLeaf(New, Weight, Mul1.InsertionOrder));
2285 } else if (Mul1.Value.getNode()) {
2286 // We failed to factorize two MULs, so now the Muls are left outside the
2287 // queue... add them back.
2288 Leaves.push(Mul1);
2289 if (Mul2.Value.getNode())
2290 Leaves.push(Mul2);
2291 CanFactorize = false;
2292 }
2293
2294 // Combine GA + Constant -> GA+Offset, but only if GA is not used elsewhere
2295 // and the root node itself is not used more than twice. This reduces the
2296 // amount of additional constant extenders introduced by this optimization.
2297 bool CombinedGA = false;
2298 if (NOpcode == ISD::ADD && GA.Value.getNode() && Leaves.hasConst() &&
2299 GA.Value.hasOneUse() && N->use_size() < 3 &&
2300 GA.Value.getNumOperands() >= 1) {
2301 GlobalAddressSDNode *GANode =
2303 ConstantSDNode *Offset = cast<ConstantSDNode>(Leaves.top().Value);
2304
2305 if (getUsesInFunction(GANode->getGlobal()) == 1 && Offset->hasOneUse() &&
2306 getTargetLowering()->isOffsetFoldingLegal(GANode)) {
2307 LLVM_DEBUG(dbgs() << "--> Combining GA and offset ("
2308 << Offset->getSExtValue() << "): ");
2309 LLVM_DEBUG(GANode->dump(CurDAG));
2310
2311 SDValue NewTGA =
2312 CurDAG->getTargetGlobalAddress(GANode->getGlobal(), SDLoc(GA.Value),
2313 GANode->getValueType(0),
2314 GANode->getOffset() + (uint64_t)Offset->getSExtValue());
2315 GA.Value = CurDAG->getNode(GA.Value.getOpcode(), SDLoc(GA.Value),
2316 GA.Value.getValueType(), NewTGA);
2317 GA.Weight += Leaves.top().Weight;
2318
2319 NodeHeights[GA.Value] = getHeight(GA.Value.getNode());
2320 CombinedGA = true;
2321
2322 Leaves.pop(); // Remove the offset constant from the queue
2323 }
2324 }
2325
2326 if ((RebalanceOnlyForOptimizations && !CanFactorize && !CombinedGA) ||
2327 (RebalanceOnlyImbalancedTrees && !Imbalanced)) {
2328 RootWeights[N] = CurrentWeight;
2329 RootHeights[N] = NodeHeights[SDValue(N, 0)];
2330
2331 return SDValue(N, 0);
2332 }
2333
2334 // Combine GA + SHL(x, C<=31) so we will match Rx=add(#u8,asl(Rx,#U5))
2335 if (NOpcode == ISD::ADD && GA.Value.getNode()) {
2336 WeightedLeaf SHL = Leaves.findSHL(31);
2337 if (SHL.Value.getNode()) {
2338 int Height = std::max(NodeHeights[GA.Value], NodeHeights[SHL.Value]) + 1;
2339 GA.Value = CurDAG->getNode(ISD::ADD, SDLoc(GA.Value),
2340 GA.Value.getValueType(),
2341 GA.Value, SHL.Value);
2342 GA.Weight = SHL.Weight; // Specifically ignore the GA weight here
2343 NodeHeights[GA.Value] = Height;
2344 }
2345 }
2346
2347 if (GA.Value.getNode())
2348 Leaves.push(GA);
2349
2350 // If this is the top level and we haven't factored out a shift, we should try
2351 // to move a constant to the bottom to match addressing modes like memw(rX+C)
2352 if (TopLevel && !CanFactorize && Leaves.hasConst()) {
2353 LLVM_DEBUG(dbgs() << "--> Pushing constant to tip of tree.");
2354 Leaves.pushToBottom(Leaves.pop());
2355 }
2356
2357 const DataLayout &DL = CurDAG->getDataLayout();
2358 const TargetLowering &TLI = *getTargetLowering();
2359
2360 // Rebuild the tree using Huffman's algorithm
2361 while (Leaves.size() > 1) {
2362 WeightedLeaf L0 = Leaves.pop();
2363
2364 // See whether we can grab a MUL to form an add(Rx,mpyi(Ry,#u6)),
2365 // otherwise just get the next leaf
2366 WeightedLeaf L1 = Leaves.findMULbyConst();
2367 if (!L1.Value.getNode())
2368 L1 = Leaves.pop();
2369
2370 assert(L0.Weight <= L1.Weight && "Priority queue is broken!");
2371
2372 SDValue V0 = L0.Value;
2373 int V0Weight = L0.Weight;
2374 SDValue V1 = L1.Value;
2375 int V1Weight = L1.Weight;
2376
2377 // Make sure that none of these nodes have been RAUW'd
2378 if ((RootWeights.count(V0.getNode()) && RootWeights[V0.getNode()] == -2) ||
2379 (RootWeights.count(V1.getNode()) && RootWeights[V1.getNode()] == -2)) {
2380 LLVM_DEBUG(dbgs() << "--> Subtree was RAUWd. Restarting...\n");
2381 return balanceSubTree(N, TopLevel);
2382 }
2383
2384 ConstantSDNode *V0C = dyn_cast<ConstantSDNode>(V0);
2385 ConstantSDNode *V1C = dyn_cast<ConstantSDNode>(V1);
2386 EVT VT = N->getValueType(0);
2387 SDValue NewNode;
2388
2389 if (V0C && !V1C) {
2390 std::swap(V0, V1);
2391 std::swap(V0C, V1C);
2392 }
2393
2394 // Calculate height of this node
2395 assert(NodeHeights.count(V0) && NodeHeights.count(V1) &&
2396 "Children must have been visited before re-combining them!");
2397 int Height = std::max(NodeHeights[V0], NodeHeights[V1]) + 1;
2398
2399 // Rebuild this node (and restore SHL from MUL if needed)
2400 if (V1C && NOpcode == ISD::MUL && V1C->getAPIntValue().isPowerOf2())
2401 NewNode = CurDAG->getNode(
2402 ISD::SHL, SDLoc(V0), VT, V0,
2403 CurDAG->getConstant(
2404 V1C->getAPIntValue().logBase2(), SDLoc(N),
2405 TLI.getScalarShiftAmountTy(DL, V0.getValueType())));
2406 else
2407 NewNode = CurDAG->getNode(NOpcode, SDLoc(N), VT, V0, V1);
2408
2409 NodeHeights[NewNode] = Height;
2410
2411 int Weight = V0Weight + V1Weight;
2412 Leaves.push(WeightedLeaf(NewNode, Weight, L0.InsertionOrder));
2413
2414 LLVM_DEBUG(dbgs() << "--> Built new node (Weight=" << Weight
2415 << ",Height=" << Height << "):\n");
2416 LLVM_DEBUG(NewNode.dump());
2417 }
2418
2419 assert(Leaves.size() == 1);
2420 SDValue NewRoot = Leaves.top().Value;
2421
2422 assert(NodeHeights.count(NewRoot));
2423 int Height = NodeHeights[NewRoot];
2424
2425 // Restore SHL if we earlier converted it to a MUL
2426 if (NewRoot.getOpcode() == ISD::MUL && NewRoot->getNumOperands() >= 2) {
2427 ConstantSDNode *V1C = dyn_cast<ConstantSDNode>(NewRoot.getOperand(1));
2428 if (V1C && V1C->getAPIntValue().isPowerOf2()) {
2429 EVT VT = NewRoot.getValueType();
2430 SDValue V0 = NewRoot.getOperand(0);
2431 NewRoot = CurDAG->getNode(
2432 ISD::SHL, SDLoc(NewRoot), VT, V0,
2433 CurDAG->getConstant(
2434 V1C->getAPIntValue().logBase2(), SDLoc(NewRoot),
2435 TLI.getScalarShiftAmountTy(DL, V0.getValueType())));
2436 }
2437 }
2438
2439 if (N != NewRoot.getNode()) {
2440 LLVM_DEBUG(dbgs() << "--> Root is now: ");
2441 LLVM_DEBUG(NewRoot.dump());
2442
2443 // Replace all uses of old root by new root
2444 CurDAG->ReplaceAllUsesWith(N, NewRoot.getNode());
2445 // Mark that we have RAUW'd N
2446 RootWeights[N] = -2;
2447 } else {
2448 LLVM_DEBUG(dbgs() << "--> Root unchanged.\n");
2449 }
2450
2451 RootWeights[NewRoot.getNode()] = Leaves.top().Weight;
2452 RootHeights[NewRoot.getNode()] = Height;
2453
2454 return NewRoot;
2455}
2456
2457void HexagonDAGToDAGISel::rebalanceAddressTrees() {
2458 for (SDNode &Node : llvm::make_early_inc_range(CurDAG->allnodes())) {
2459 SDNode *N = &Node;
2460 if (N->getOpcode() != ISD::LOAD && N->getOpcode() != ISD::STORE)
2461 continue;
2462
2463 SDValue BasePtr = cast<MemSDNode>(N)->getBasePtr();
2464 if (BasePtr.getOpcode() != ISD::ADD)
2465 continue;
2466
2467 // We've already processed this node
2468 if (RootWeights.count(BasePtr.getNode()))
2469 continue;
2470
2471 LLVM_DEBUG(dbgs() << "** Rebalancing address calculation in node: ");
2472 LLVM_DEBUG(N->dump(CurDAG));
2473
2474 // FindRoots
2475 SmallVector<SDNode *, 4> Worklist;
2476
2477 if (BasePtr->getNumOperands() < 2)
2478 continue;
2479
2480 Worklist.push_back(BasePtr.getOperand(0).getNode());
2481 Worklist.push_back(BasePtr.getOperand(1).getNode());
2482
2483 while (!Worklist.empty()) {
2484 SDNode *N = Worklist.pop_back_val();
2485 unsigned Opcode = N->getOpcode();
2486
2487 if (!isOpcodeHandled(N))
2488 continue;
2489
2490 if (N->getNumOperands() < 2)
2491 continue;
2492
2493 Worklist.push_back(N->getOperand(0).getNode());
2494 Worklist.push_back(N->getOperand(1).getNode());
2495
2496 // Not a root if it has only one use and same opcode as its parent
2497 if (N->hasOneUse() && Opcode == N->user_begin()->getOpcode())
2498 continue;
2499
2500 // This root node has already been processed
2501 RootWeights.try_emplace(N, -1);
2502 }
2503
2504 // Balance node itself
2505 RootWeights[BasePtr.getNode()] = -1;
2506 SDValue NewBasePtr = balanceSubTree(BasePtr.getNode(), /*TopLevel=*/ true);
2507
2508 if (N->getOpcode() == ISD::LOAD) {
2509 if (N->getNumOperands() >= 3)
2510 N = CurDAG->UpdateNodeOperands(N, N->getOperand(0), NewBasePtr,
2511 N->getOperand(2));
2512 } else {
2513 if (N->getNumOperands() >= 4)
2514 N = CurDAG->UpdateNodeOperands(N, N->getOperand(0), N->getOperand(1),
2515 NewBasePtr, N->getOperand(3));
2516 }
2517
2518 LLVM_DEBUG(dbgs() << "--> Final node: ");
2519 LLVM_DEBUG(N->dump(CurDAG));
2520 }
2521
2522 CurDAG->RemoveDeadNodes();
2523 GAUsesInFunction.clear();
2524 RootHeights.clear();
2525 RootWeights.clear();
2526}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
uint64_t uint64_t
constexpr LLT S1
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis false
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define DEBUG_TYPE
static bool willShiftRightEliminate(SDValue V, unsigned Amount)
static SDValue getCircRegister(SelectionDAG &DAG, SDLoc DL, SDNode *N, unsigned MOp, unsigned CSOp)
static cl::opt< bool > RebalanceOnlyImbalancedTrees("rebalance-only-imbal", cl::Hidden, cl::init(false), cl::desc("Rebalance address tree only if it is imbalanced"))
static unsigned getPowerOf2Factor(SDValue Val)
static cl::opt< bool > CheckSingleUse("hexagon-isel-su", cl::Hidden, cl::init(true), cl::desc("Enable checking of SDNode's single-use status"))
static cl::opt< bool > EnableAddressRebalancing("isel-rebalance-addr", cl::Hidden, cl::init(true), cl::desc("Rebalance address calculation trees to improve " "instruction selection"))
static bool isMemOPCandidate(SDNode *I, SDNode *U)
static bool isTargetConstant(const SDValue &V)
static bool isOpcodeHandled(const SDNode *N)
static cl::opt< bool > RebalanceOnlyForOptimizations("rebalance-only-opt", cl::Hidden, cl::init(false), cl::desc("Rebalance address tree only if this allows optimizations"))
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
#define T1
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
int64_t C1
int64_t C0
#define CH(x, y, z)
Definition SHA256.cpp:34
#define LLVM_DEBUG(...)
Definition Debug.h:119
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
Definition Debug.h:72
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
#define PASS_NAME
Class for arbitrary precision integers.
Definition APInt.h:78
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1508
unsigned countr_zero() const
Count the number of trailing zero bits.
Definition APInt.h:1659
unsigned logBase2() const
Definition APInt.h:1781
bool getBoolValue() const
Convert APInt to a boolean value.
Definition APInt.h:467
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
Definition APInt.h:436
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition DenseMap.h:762
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:312
const GlobalValue * getGlobal() const
This class is used to form a handle around another node that is persistent and is updated across invo...
const SDValue & getValue() const
HexagonDAGToDAGISelLegacy(HexagonTargetMachine &tm, CodeGenOptLevel OptLevel)
void translateIEEEIntrinsicToQFloat(SDNode *N, unsigned &Opcode)
void Select(SDNode *N) override
Main hook for targets to transform nodes into machine nodes.
bool SelectNewCircIntrinsic(SDNode *IntN)
Generate a machine instruction node for the new circular buffer intrinsics.
bool tryLoadOfLoadIntrinsic(LoadSDNode *N)
void SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl)
MachineSDNode * LoadInstrForLoadIntrinsic(SDNode *IntN)
bool SelectAnyImm2(SDValue &N, SDValue &R)
bool SelectAnyImm(SDValue &N, SDValue &R)
bool SelectAnyImm0(SDValue &N, SDValue &R)
bool SelectAnyImm1(SDValue &N, SDValue &R)
bool DetectUseSxtw(SDValue &N, SDValue &R)
bool SelectBrevLdIntrinsic(SDNode *IntN)
bool SelectAddrFI(SDValue &N, SDValue &R)
SDNode * StoreInstrForLoadIntrinsic(MachineSDNode *LoadN, SDNode *IntN)
bool SelectAddrGP(SDValue &N, SDValue &R)
bool SelectAnyImmediate(SDValue &N, SDValue &R, Align Alignment)
bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP, Align Alignment)
bool SelectAnyImm3(SDValue &N, SDValue &R)
bool SelectAnyInt(SDValue &N, SDValue &R)
bool SelectAddrGA(SDValue &N, SDValue &R)
void PreprocessISelDAG() override
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps) override
SelectInlineAsmMemoryOperand - Implement addressing mode selection for inline asm expressions.
void SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl)
Hexagon target-specific information for each MachineFunction.
const HexagonFrameLowering * getFrameLowering() const override
This class is used to represent ISD::LOAD nodes.
Machine Value Type.
SimpleValueType SimpleTy
unsigned getVectorNumElements() const
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
MVT getVectorElementType() const
static MVT getIntegerVT(unsigned BitWidth)
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
Align getMaxAlign() const
Return alignment of this function's frame.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
A description of a memory reference used in the backend.
An SDNode that represents everything that will be needed to construct a MachineInstr.
This is an abstract virtual class for memory operations.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isValid() const
Definition Register.h:112
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
LLVM_ABI void dump() const
Dump this node, for debugging.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
unsigned getNumOperands() const
SelectionDAGISelLegacy(char &ID, std::unique_ptr< SelectionDAGISel > S)
const TargetLowering * TLI
void ReplaceUses(SDValue F, SDValue T)
ReplaceUses - replace all uses of the old node F with the use of the new node T.
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
const TargetLowering * getTargetLowering() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
LLVM Value Representation.
Definition Value.h:75
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
Definition Attributor.h:164
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:266
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:879
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:870
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:822
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition ISDOpcodes.h:187
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:787
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:659
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:619
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:876
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:914
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:757
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:207
@ ExternalSymbol
Definition ISDOpcodes.h:95
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:64
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition ISDOpcodes.h:215
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
initializer< Ty > init(const Ty &Val)
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
bool empty() const
Definition BasicBlock.h:101
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1685
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
Definition bit.h:315
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
Definition Alignment.h:139
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:649
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
unsigned M1(unsigned Val)
Definition VE.h:377
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
Definition bit.h:263
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
CodeGenOptLevel
Code generation optimization level.
Definition CodeGen.h:280
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
FunctionPass * createHexagonISelDag(HexagonTargetMachine &TM, CodeGenOptLevel OptLevel)
createHexagonISelDag - This pass converts a legalized DAG into a Hexagon-specific DAG,...
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
Definition VE.h:376
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:320
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Extended Value Type.
Definition ValueTypes.h:35
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition ValueTypes.h:145
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:339
bool isVectorOf(EVT EltVT) const
Return true if this is a vector with matching element type.
Definition ValueTypes.h:181
bool isInteger() const
Return true if this is an integer or a vector integer type.
Definition ValueTypes.h:160
This class contains a discriminated union of information about pointers in memory operands,...
This represents a list of ValueType's that has been intern'd by a SelectionDAG.