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
368/// Generate a machine instruction node for the new circular buffer intrinsics.
369/// The new versions use a CSx register instead of the K field.
371 if (IntN->getOpcode() != ISD::INTRINSIC_W_CHAIN)
372 return false;
373
374 SDLoc DL(IntN);
375 unsigned IntNo = IntN->getConstantOperandVal(1);
377
378 static std::map<unsigned,unsigned> LoadNPcMap = {
379 { Intrinsic::hexagon_L2_loadrub_pci, Hexagon::PS_loadrub_pci },
380 { Intrinsic::hexagon_L2_loadrb_pci, Hexagon::PS_loadrb_pci },
381 { Intrinsic::hexagon_L2_loadruh_pci, Hexagon::PS_loadruh_pci },
382 { Intrinsic::hexagon_L2_loadrh_pci, Hexagon::PS_loadrh_pci },
383 { Intrinsic::hexagon_L2_loadri_pci, Hexagon::PS_loadri_pci },
384 { Intrinsic::hexagon_L2_loadrd_pci, Hexagon::PS_loadrd_pci },
385 { Intrinsic::hexagon_L2_loadrub_pcr, Hexagon::PS_loadrub_pcr },
386 { Intrinsic::hexagon_L2_loadrb_pcr, Hexagon::PS_loadrb_pcr },
387 { Intrinsic::hexagon_L2_loadruh_pcr, Hexagon::PS_loadruh_pcr },
388 { Intrinsic::hexagon_L2_loadrh_pcr, Hexagon::PS_loadrh_pcr },
389 { Intrinsic::hexagon_L2_loadri_pcr, Hexagon::PS_loadri_pcr },
390 { Intrinsic::hexagon_L2_loadrd_pcr, Hexagon::PS_loadrd_pcr }
391 };
392 auto FLI = LoadNPcMap.find (IntNo);
393 if (FLI != LoadNPcMap.end()) {
394 EVT ValTy = MVT::i32;
395 if (IntNo == Intrinsic::hexagon_L2_loadrd_pci ||
396 IntNo == Intrinsic::hexagon_L2_loadrd_pcr)
397 ValTy = MVT::i64;
398 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
399 // Handle load.*_pci case which has 6 operands.
400 if (IntN->getNumOperands() == 6) {
401 auto Inc = cast<ConstantSDNode>(IntN->getOperand(3));
402 SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), DL, MVT::i32);
403 // Operands: { Base, Increment, Modifier, Start, Chain }.
404 Ops = { IntN->getOperand(2), I, IntN->getOperand(4), IntN->getOperand(5),
405 IntN->getOperand(0) };
406 } else
407 // Handle load.*_pcr case which has 5 operands.
408 // Operands: { Base, Modifier, Start, Chain }.
409 Ops = { IntN->getOperand(2), IntN->getOperand(3), IntN->getOperand(4),
410 IntN->getOperand(0) };
411 MachineSDNode *Res = CurDAG->getMachineNode(FLI->second, DL, RTys, Ops);
412 ReplaceUses(SDValue(IntN, 0), SDValue(Res, 0));
413 ReplaceUses(SDValue(IntN, 1), SDValue(Res, 1));
414 ReplaceUses(SDValue(IntN, 2), SDValue(Res, 2));
415 CurDAG->RemoveDeadNode(IntN);
416 return true;
417 }
418
419 static std::map<unsigned,unsigned> StoreNPcMap = {
420 { Intrinsic::hexagon_S2_storerb_pci, Hexagon::PS_storerb_pci },
421 { Intrinsic::hexagon_S2_storerh_pci, Hexagon::PS_storerh_pci },
422 { Intrinsic::hexagon_S2_storerf_pci, Hexagon::PS_storerf_pci },
423 { Intrinsic::hexagon_S2_storeri_pci, Hexagon::PS_storeri_pci },
424 { Intrinsic::hexagon_S2_storerd_pci, Hexagon::PS_storerd_pci },
425 { Intrinsic::hexagon_S2_storerb_pcr, Hexagon::PS_storerb_pcr },
426 { Intrinsic::hexagon_S2_storerh_pcr, Hexagon::PS_storerh_pcr },
427 { Intrinsic::hexagon_S2_storerf_pcr, Hexagon::PS_storerf_pcr },
428 { Intrinsic::hexagon_S2_storeri_pcr, Hexagon::PS_storeri_pcr },
429 { Intrinsic::hexagon_S2_storerd_pcr, Hexagon::PS_storerd_pcr }
430 };
431 auto FSI = StoreNPcMap.find (IntNo);
432 if (FSI != StoreNPcMap.end()) {
433 EVT RTys[] = { MVT::i32, MVT::Other };
434 // Handle store.*_pci case which has 7 operands.
435 if (IntN->getNumOperands() == 7) {
436 auto Inc = cast<ConstantSDNode>(IntN->getOperand(3));
437 SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), DL, MVT::i32);
438 // Operands: { Base, Increment, Modifier, Value, Start, Chain }.
439 Ops = { IntN->getOperand(2), I, IntN->getOperand(4), IntN->getOperand(5),
440 IntN->getOperand(6), IntN->getOperand(0) };
441 } else
442 // Handle store.*_pcr case which has 6 operands.
443 // Operands: { Base, Modifier, Value, Start, Chain }.
444 Ops = { IntN->getOperand(2), IntN->getOperand(3), IntN->getOperand(4),
445 IntN->getOperand(5), IntN->getOperand(0) };
446 MachineSDNode *Res = CurDAG->getMachineNode(FSI->second, DL, RTys, Ops);
447 ReplaceUses(SDValue(IntN, 0), SDValue(Res, 0));
448 ReplaceUses(SDValue(IntN, 1), SDValue(Res, 1));
449 CurDAG->RemoveDeadNode(IntN);
450 return true;
451 }
452
453 return false;
454}
455
457 SDLoc dl(N);
459
460 // Handle indexed loads.
461 ISD::MemIndexedMode AM = LD->getAddressingMode();
462 if (AM != ISD::UNINDEXED) {
463 SelectIndexedLoad(LD, dl);
464 return;
465 }
466
467 // Handle patterns using circ/brev load intrinsics.
469 return;
470
471 SelectCode(LD);
472}
473
475 SDValue Chain = ST->getChain();
476 SDValue Base = ST->getBasePtr();
477 SDValue Offset = ST->getOffset();
478 SDValue Value = ST->getValue();
479 // Get the constant value.
480 int32_t Inc = cast<ConstantSDNode>(Offset.getNode())->getSExtValue();
481 EVT StoredVT = ST->getMemoryVT();
482 EVT ValueVT = Value.getValueType();
483
484 bool IsValidInc = HII->isValidAutoIncImm(StoredVT, Inc);
485 unsigned Opcode = 0;
486
487 assert(StoredVT.isSimple());
488 switch (StoredVT.getSimpleVT().SimpleTy) {
489 case MVT::i8:
490 Opcode = IsValidInc ? Hexagon::S2_storerb_pi : Hexagon::S2_storerb_io;
491 break;
492 case MVT::i16:
493 Opcode = IsValidInc ? Hexagon::S2_storerh_pi : Hexagon::S2_storerh_io;
494 break;
495 case MVT::i32:
496 case MVT::f32:
497 case MVT::v2i16:
498 case MVT::v4i8:
499 Opcode = IsValidInc ? Hexagon::S2_storeri_pi : Hexagon::S2_storeri_io;
500 break;
501 case MVT::i64:
502 case MVT::f64:
503 case MVT::v2i32:
504 case MVT::v4i16:
505 case MVT::v8i8:
506 Opcode = IsValidInc ? Hexagon::S2_storerd_pi : Hexagon::S2_storerd_io;
507 break;
508 case MVT::v64i8:
509 case MVT::v32i16:
510 case MVT::v16i32:
511 case MVT::v8i64:
512 case MVT::v128i8:
513 case MVT::v64i16:
514 case MVT::v32i32:
515 case MVT::v16i64:
516 if (isAlignedMemNode(ST)) {
517 if (ST->isNonTemporal())
518 Opcode = IsValidInc ? Hexagon::V6_vS32b_nt_pi : Hexagon::V6_vS32b_nt_ai;
519 else
520 Opcode = IsValidInc ? Hexagon::V6_vS32b_pi : Hexagon::V6_vS32b_ai;
521 } else {
522 Opcode = IsValidInc ? Hexagon::V6_vS32Ub_pi : Hexagon::V6_vS32Ub_ai;
523 }
524 break;
525 default:
526 llvm_unreachable("Unexpected memory type in indexed store");
527 }
528
529 if (ST->isTruncatingStore() && ValueVT.getSizeInBits() == 64) {
530 assert(StoredVT.getSizeInBits() < 64 && "Not a truncating store");
531 Value = CurDAG->getTargetExtractSubreg(Hexagon::isub_lo,
532 dl, MVT::i32, Value);
533 }
534
535 SDValue IncV = CurDAG->getSignedTargetConstant(Inc, dl, MVT::i32);
536 MachineMemOperand *MemOp = ST->getMemOperand();
537
538 // Next address Chain
539 SDValue From[2] = { SDValue(ST,0), SDValue(ST,1) };
540 SDValue To[2];
541
542 if (IsValidInc) {
543 // Build post increment store.
544 SDValue Ops[] = { Base, IncV, Value, Chain };
545 MachineSDNode *S = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Other,
546 Ops);
547 CurDAG->setNodeMemRefs(S, {MemOp});
548 To[0] = SDValue(S, 0);
549 To[1] = SDValue(S, 1);
550 } else {
551 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);
552 SDValue Ops[] = { Base, Zero, Value, Chain };
553 MachineSDNode *S = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
554 CurDAG->setNodeMemRefs(S, {MemOp});
555 To[1] = SDValue(S, 0);
556 MachineSDNode *A = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
557 Base, IncV);
558 To[0] = SDValue(A, 0);
559 }
560
561 ReplaceUses(From, To, 2);
562 CurDAG->RemoveDeadNode(ST);
563}
564
566 SDLoc dl(N);
568
569 // Handle indexed stores.
570 ISD::MemIndexedMode AM = ST->getAddressingMode();
571 if (AM != ISD::UNINDEXED) {
572 SelectIndexedStore(ST, dl);
573 return;
574 }
575
576 SelectCode(ST);
577}
578
580 SDLoc dl(N);
581 SDValue Shl_0 = N->getOperand(0);
582 SDValue Shl_1 = N->getOperand(1);
583
584 auto Default = [this,N] () -> void { SelectCode(N); };
585
586 if (N->getValueType(0) != MVT::i32 || Shl_1.getOpcode() != ISD::Constant)
587 return Default();
588
589 // RHS is const.
590 int32_t ShlConst = cast<ConstantSDNode>(Shl_1)->getSExtValue();
591
592 if (Shl_0.getOpcode() == ISD::MUL) {
593 SDValue Mul_0 = Shl_0.getOperand(0); // Val
594 SDValue Mul_1 = Shl_0.getOperand(1); // Const
595 // RHS of mul is const.
597 int32_t ValConst = static_cast<int32_t>(
598 static_cast<uint32_t>(C->getSExtValue()) << ShlConst);
599 if (isInt<9>(ValConst)) {
600 SDValue Val = CurDAG->getTargetConstant(ValConst, dl, MVT::i32);
601 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
602 MVT::i32, Mul_0, Val);
603 ReplaceNode(N, Result);
604 return;
605 }
606 }
607 return Default();
608 }
609
610 if (Shl_0.getOpcode() == ISD::SUB) {
611 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0
612 SDValue Sub_1 = Shl_0.getOperand(1); // Val
613 if (ConstantSDNode *C1 = dyn_cast<ConstantSDNode>(Sub_0)) {
614 if (C1->getSExtValue() != 0 || Sub_1.getOpcode() != ISD::SHL)
615 return Default();
616 SDValue Shl2_0 = Sub_1.getOperand(0); // Val
617 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
618 if (ConstantSDNode *C2 = dyn_cast<ConstantSDNode>(Shl2_1)) {
619 int32_t ValConst =
620 static_cast<int32_t>(1U << (ShlConst + C2->getSExtValue()));
621 if (isInt<9>(-ValConst)) {
622 SDValue Val =
623 CurDAG->getSignedTargetConstant(-ValConst, dl, MVT::i32);
624 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
625 MVT::i32, Shl2_0, Val);
626 ReplaceNode(N, Result);
627 return;
628 }
629 }
630 }
631 }
632
633 return Default();
634}
635
636//
637// Handling intrinsics for circular load and bitreverse load.
638//
642 CurDAG->RemoveDeadNode(N);
643 return;
644 }
645
646 // Handle bit-reverse load intrinsics.
648 return;
649
651 return;
652
653 unsigned IntNo = N->getConstantOperandVal(1);
654 if (IntNo == Intrinsic::hexagon_V6_vgathermw ||
655 IntNo == Intrinsic::hexagon_V6_vgathermw_128B ||
656 IntNo == Intrinsic::hexagon_V6_vgathermh ||
657 IntNo == Intrinsic::hexagon_V6_vgathermh_128B ||
658 IntNo == Intrinsic::hexagon_V6_vgathermhw ||
659 IntNo == Intrinsic::hexagon_V6_vgathermhw_128B ||
660 IntNo == Intrinsic::hexagon_V6_vgather_vscattermh ||
661 IntNo == Intrinsic::hexagon_V6_vgather_vscattermh_128B) {
663 return;
664 }
665 if (IntNo == Intrinsic::hexagon_V6_vgathermwq ||
666 IntNo == Intrinsic::hexagon_V6_vgathermwq_128B ||
667 IntNo == Intrinsic::hexagon_V6_vgathermhq ||
668 IntNo == Intrinsic::hexagon_V6_vgathermhq_128B ||
669 IntNo == Intrinsic::hexagon_V6_vgathermhwq ||
670 IntNo == Intrinsic::hexagon_V6_vgathermhwq_128B) {
672 return;
673 }
674
675 SelectCode(N);
676}
677
679 unsigned IID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
680 unsigned Bits;
681
682 // On v79 and above, IEEE HVX instructions are no longer present.
683 // The related intrinsics must be translated to QFloat implicitly in order
684 // to provide backward compatibility.
685 if (HST->useHVXV79Ops() && isIEEEHVXIntrinsic(IID)) {
687 return;
688 }
689
690 switch (IID) {
691 case Intrinsic::hexagon_S2_vsplatrb:
692 Bits = 8;
693 break;
694 case Intrinsic::hexagon_S2_vsplatrh:
695 Bits = 16;
696 break;
697 case Intrinsic::hexagon_V6_vaddcarry:
698 case Intrinsic::hexagon_V6_vaddcarry_128B:
699 case Intrinsic::hexagon_V6_vsubcarry:
700 case Intrinsic::hexagon_V6_vsubcarry_128B:
702 return;
703 default:
704 SelectCode(N);
705 return;
706 }
707
708 SDValue V = N->getOperand(1);
709 SDValue U;
710 // Splat intrinsics.
711 if (keepsLowBits(V, Bits, U)) {
712 SDValue R = CurDAG->getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
713 N->getOperand(0), U);
714 ReplaceNode(N, R.getNode());
715 SelectCode(R.getNode());
716 return;
717 }
718 SelectCode(N);
719}
720
722 SDValue Inp = N->getOperand(0);
723 MVT ResTy = N->getValueType(0).getSimpleVT();
724 unsigned Idx = N->getConstantOperandVal(1);
725
726 [[maybe_unused]] MVT InpTy = Inp.getValueType().getSimpleVT();
727 [[maybe_unused]] unsigned ResLen = ResTy.getVectorNumElements();
729 assert(2 * ResLen == InpTy.getVectorNumElements());
730 assert(ResTy.getSizeInBits() == 32);
731 assert(Idx == 0 || Idx == ResLen);
732
733 unsigned SubReg = Idx == 0 ? Hexagon::isub_lo : Hexagon::isub_hi;
734 SDValue Ext = CurDAG->getTargetExtractSubreg(SubReg, SDLoc(N), ResTy, Inp);
735
736 ReplaceNode(N, Ext.getNode());
737}
738
739//
740// Map floating point constant values.
741//
743 SDLoc dl(N);
744 auto *CN = cast<ConstantFPSDNode>(N);
745 APInt A = CN->getValueAPF().bitcastToAPInt();
746 if (N->getValueType(0) == MVT::f32) {
747 SDValue V = CurDAG->getTargetConstant(A.getZExtValue(), dl, MVT::i32);
748 ReplaceNode(N, CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, V));
749 return;
750 }
751 if (N->getValueType(0) == MVT::f64) {
752 SDValue V = CurDAG->getTargetConstant(A.getZExtValue(), dl, MVT::i64);
753 ReplaceNode(N, CurDAG->getMachineNode(Hexagon::CONST64, dl, MVT::f64, V));
754 return;
755 }
756
757 SelectCode(N);
758}
759
760//
761// Map boolean values.
762//
764 if (N->getValueType(0) == MVT::i1) {
765 assert(!(N->getAsZExtVal() >> 1));
766 unsigned Opc = (cast<ConstantSDNode>(N)->getSExtValue() != 0)
767 ? Hexagon::PS_true
768 : Hexagon::PS_false;
769 ReplaceNode(N, CurDAG->getMachineNode(Opc, SDLoc(N), MVT::i1));
770 return;
771 }
772
773 SelectCode(N);
774}
775
777 MachineFrameInfo &MFI = MF->getFrameInfo();
778 const HexagonFrameLowering *HFI = HST->getFrameLowering();
779 int FX = cast<FrameIndexSDNode>(N)->getIndex();
780 Align StkA = HFI->getStackAlign();
781 Align MaxA = MFI.getMaxAlign();
782 SDValue FI = CurDAG->getTargetFrameIndex(FX, MVT::i32);
783 SDLoc DL(N);
784 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
785 SDNode *R = nullptr;
786
787 // Use PS_fi when:
788 // - the object is fixed, or
789 // - there are no objects with higher-than-default alignment, or
790 // - there are no dynamically allocated objects.
791 // Otherwise, use PS_fia.
792 if (FX < 0 || MaxA <= StkA || !MFI.hasVarSizedObjects()) {
793 R = CurDAG->getMachineNode(Hexagon::PS_fi, DL, MVT::i32, FI, Zero);
794 } else {
795 auto &HMFI = *MF->getInfo<HexagonMachineFunctionInfo>();
796 Register AR = HMFI.getStackAlignBaseReg();
797 assert(AR.isValid() && "Missing stack align base register");
798 SDValue CH = CurDAG->getEntryNode();
799 SDValue Ops[] = { CurDAG->getCopyFromReg(CH, DL, AR, MVT::i32), FI, Zero };
800 R = CurDAG->getMachineNode(Hexagon::PS_fia, DL, MVT::i32, Ops);
801 }
802
803 ReplaceNode(N, R);
804}
805
807 unsigned OpcCarry = N->getOpcode() == HexagonISD::ADDC ? Hexagon::A4_addp_c
808 : Hexagon::A4_subp_c;
809 SDNode *C = CurDAG->getMachineNode(OpcCarry, SDLoc(N), N->getVTList(),
810 { N->getOperand(0), N->getOperand(1),
811 N->getOperand(2) });
812 ReplaceNode(N, C);
813}
814
816 MVT ResTy = N->getValueType(0).getSimpleVT();
817 if (HST->isHVXVectorType(ResTy, true))
818 return SelectHvxVAlign(N);
819
820 const SDLoc &dl(N);
821 unsigned VecLen = ResTy.getSizeInBits();
822 if (VecLen == 32) {
823 SDValue Ops[] = {
824 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
825 N->getOperand(0),
826 CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
827 N->getOperand(1),
828 CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
829 };
830 SDNode *R = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
831 MVT::i64, Ops);
832
833 // Shift right by "(Addr & 0x3) * 8" bytes.
834 SDNode *C;
835 SDValue M0 = CurDAG->getTargetConstant(0x18, dl, MVT::i32);
836 SDValue M1 = CurDAG->getTargetConstant(0x03, dl, MVT::i32);
837 if (HST->useCompound()) {
838 C = CurDAG->getMachineNode(Hexagon::S4_andi_asl_ri, dl, MVT::i32,
839 M0, N->getOperand(2), M1);
840 } else {
841 SDNode *T = CurDAG->getMachineNode(Hexagon::S2_asl_i_r, dl, MVT::i32,
842 N->getOperand(2), M1);
843 C = CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
844 SDValue(T, 0), M0);
845 }
846 SDNode *S = CurDAG->getMachineNode(Hexagon::S2_lsr_r_p, dl, MVT::i64,
847 SDValue(R, 0), SDValue(C, 0));
848 SDValue E = CurDAG->getTargetExtractSubreg(Hexagon::isub_lo, dl, ResTy,
849 SDValue(S, 0));
850 ReplaceNode(N, E.getNode());
851 } else {
852 assert(VecLen == 64);
853 SDNode *Pu = CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::v8i1,
854 N->getOperand(2));
855 SDNode *VA = CurDAG->getMachineNode(Hexagon::S2_valignrb, dl, ResTy,
856 N->getOperand(0), N->getOperand(1),
857 SDValue(Pu,0));
858 ReplaceNode(N, VA);
859 }
860}
861
863 const SDLoc &dl(N);
864 SDValue A = N->getOperand(1);
865 int Mask = -cast<ConstantSDNode>(A.getNode())->getSExtValue();
866 assert(isPowerOf2_32(-Mask));
867
868 SDValue M = CurDAG->getTargetConstant(Mask, dl, MVT::i32);
869 SDNode *AA = CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
870 N->getOperand(0), M);
871 ReplaceNode(N, AA);
872}
873
874// Handle these nodes here to avoid having to write patterns for all
875// combinations of input/output types. In all cases, the resulting
876// instruction is the same.
878 SDValue Op = N->getOperand(0);
879 MVT OpTy = Op.getValueType().getSimpleVT();
880 SDNode *T = CurDAG->MorphNodeTo(N, N->getOpcode(),
881 CurDAG->getVTList(OpTy), {Op});
882 ReplaceNode(T, Op.getNode());
883}
884
886 MVT ResTy = N->getValueType(0).getSimpleVT();
887 SDNode *T = CurDAG->getMachineNode(Hexagon::C2_mask, SDLoc(N), ResTy,
888 N->getOperand(0));
889 ReplaceNode(N, T);
890}
891
893 const SDLoc &dl(N);
894 MVT ResTy = N->getValueType(0).getSimpleVT();
895 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);
896 SDNode *T = CurDAG->getMachineNode(Hexagon::A4_vcmpbgtui, dl, ResTy,
897 N->getOperand(0), Zero);
898 ReplaceNode(N, T);
899}
900
902 const SDLoc &dl(N);
903 MVT ResTy = N->getValueType(0).getSimpleVT();
904 // The argument to V2Q should be a single vector.
905 MVT OpTy = N->getOperand(0).getValueType().getSimpleVT(); (void)OpTy;
906 assert(HST->getVectorLength() * 8 == OpTy.getSizeInBits());
907
908 SDValue C = CurDAG->getSignedTargetConstant(-1, dl, MVT::i32);
909 SDNode *R = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, C);
910 SDNode *T = CurDAG->getMachineNode(Hexagon::V6_vandvrt, dl, ResTy,
911 N->getOperand(0), SDValue(R,0));
912 ReplaceNode(N, T);
913}
914
916 const SDLoc &dl(N);
917 MVT ResTy = N->getValueType(0).getSimpleVT();
918 // The result of V2Q should be a single vector.
919 assert(HST->getVectorLength() * 8 == ResTy.getSizeInBits());
920
921 SDValue C = CurDAG->getSignedTargetConstant(-1, dl, MVT::i32);
922 SDNode *R = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, C);
923 SDNode *T = CurDAG->getMachineNode(Hexagon::V6_vandqrt, dl, ResTy,
924 N->getOperand(0), SDValue(R,0));
925 ReplaceNode(N, T);
926}
927
929 const SDLoc &dl(N);
930 ArrayRef<EVT> ResultType(N->value_begin(), N->value_end());
932 Ops = {N->getOperand(0), N->getOperand(1)};
933 SDVTList VTs;
934 VTs = CurDAG->getVTList(MVT::f32, MVT::f32);
935 SDNode *ResScale = CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs, Ops);
936 SDNode *D = CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32, Ops);
937
938 SDValue C = CurDAG->getTargetConstant(0x3f800000, dl, MVT::i32);
939 SDNode *constNode =
940 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, C);
941
942 SDNode *n = CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32, Ops);
943 SDNode *Err = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
944 SDValue(constNode, 0), SDValue(D, 0),
945 SDValue(ResScale, 0));
946 SDNode *NewRec = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
947 SDValue(ResScale, 0), SDValue(Err, 0),
948 SDValue(ResScale, 0));
949 SDNode *newErr = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
950 SDValue(constNode, 0), SDValue(D, 0),
951 SDValue(NewRec, 0));
952 SDNode *q = CurDAG->getMachineNode(
953 Hexagon::A2_andir, dl, MVT::f32, SDValue(n, 0),
954 CurDAG->getTargetConstant(0x80000000, dl, MVT::i32));
955 SDNode *NewQ =
956 CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(q, 0),
957 SDValue(n, 0), SDValue(NewRec, 0));
958 SDNode *NNewRec = CurDAG->getMachineNode(
959 Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(NewRec, 0),
960 SDValue(newErr, 0), SDValue(NewRec, 0));
961 SDNode *qErr =
962 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, SDValue(n, 0),
963 SDValue(D, 0), SDValue(NewQ, 0));
964 SDNode *NNewQ = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
965 SDValue(NewQ, 0), SDValue(qErr, 0),
966 SDValue(NNewRec, 0));
967
968 SDNode *NqErr =
969 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, SDValue(n, 0),
970 SDValue(NNewQ, 0), SDValue(D, 0));
971 std::array<SDValue, 4> temp1 = {SDValue(NNewQ, 0), SDValue(NqErr, 0),
972 SDValue(NNewRec, 0), SDValue(ResScale, 1)};
973 ArrayRef<SDValue> OpValue1(temp1);
974 SDNode *FinalNewQ =
975 CurDAG->getMachineNode(Hexagon::F2_sffma_sc, dl, MVT::f32, OpValue1);
976 ReplaceNode(N, FinalNewQ);
977}
978
980 const SDLoc &dl(N);
981 ArrayRef<EVT> ResultType(N->value_begin(), N->value_end());
983 Ops = {N->getOperand(0), N->getOperand(1)};
984 SDVTList VTs;
985 VTs = CurDAG->getVTList(MVT::f32, MVT::f32);
986 SDNode *ResScale = CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs, Ops);
987 SDNode *D = CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32, Ops);
988
989 SDValue C = CurDAG->getTargetConstant(0x3f800000, dl, MVT::i32);
990 SDNode *constNode =
991 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, C);
992
993 SDNode *n = CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32, Ops);
994 SDNode *Err = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
995 SDValue(constNode, 0), SDValue(D, 0),
996 SDValue(ResScale, 0));
997 SDNode *NewRec = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
998 SDValue(ResScale, 0), SDValue(Err, 0),
999 SDValue(ResScale, 0));
1000 SDNode *newErr = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
1001 SDValue(constNode, 0), SDValue(D, 0),
1002 SDValue(NewRec, 0));
1003
1004 SDNode *NNewRec = CurDAG->getMachineNode(
1005 Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(NewRec, 0),
1006 SDValue(newErr, 0), SDValue(NewRec, 0));
1007 SDNode *FinalNewQ = CurDAG->getMachineNode(
1008 Hexagon::F2_sfmpy, dl, MVT::f32, SDValue(NNewRec, 0), SDValue(n, 0));
1009 ReplaceNode(N, FinalNewQ);
1010}
1011
1013 if (N->getFlags().hasAllowReassociation())
1014 FastFDiv(N);
1015 else
1016 FDiv(N);
1017}
1018
1020 if (N->isMachineOpcode())
1021 return N->setNodeId(-1); // Already selected.
1022
1023 auto isHvxOp = [this](SDNode *N) {
1024 for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) {
1025 if (HST->isHVXVectorType(N->getValueType(i), true))
1026 return true;
1027 }
1028 for (SDValue I : N->ops()) {
1029 if (HST->isHVXVectorType(I.getValueType(), true))
1030 return true;
1031 }
1032 return false;
1033 };
1034
1035 if (HST->useHVXOps() && isHvxOp(N)) {
1036 switch (N->getOpcode()) {
1037 case ISD::EXTRACT_SUBVECTOR: return SelectHvxExtractSubvector(N);
1038 case ISD::VECTOR_SHUFFLE: return SelectHvxShuffle(N);
1039
1040 case HexagonISD::VROR: return SelectHvxRor(N);
1041 }
1042 }
1043
1044 switch (N->getOpcode()) {
1045 case ISD::Constant: return SelectConstant(N);
1046 case ISD::ConstantFP: return SelectConstantFP(N);
1047 case ISD::FrameIndex: return SelectFrameIndex(N);
1048 case ISD::SHL: return SelectSHL(N);
1049 case ISD::LOAD: return SelectLoad(N);
1050 case ISD::STORE: return SelectStore(N);
1054
1055 case HexagonISD::ADDC:
1056 case HexagonISD::SUBC: return SelectAddSubCarry(N);
1057 case HexagonISD::VALIGN: return SelectVAlign(N);
1058 case HexagonISD::VALIGNADDR: return SelectVAlignAddr(N);
1060 case HexagonISD::P2D: return SelectP2D(N);
1061 case HexagonISD::D2P: return SelectD2P(N);
1062 case HexagonISD::Q2V: return SelectQ2V(N);
1063 case HexagonISD::V2Q: return SelectV2Q(N);
1064 case ISD::FDIV:
1065 return SelectFDiv(N);
1066 }
1067
1068 SelectCode(N);
1069}
1070
1072 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
1073 std::vector<SDValue> &OutOps) {
1074 SDValue Inp = Op, Res;
1075
1076 switch (ConstraintID) {
1077 default:
1078 return true;
1079 case InlineAsm::ConstraintCode::o: // Offsetable.
1080 case InlineAsm::ConstraintCode::v: // Not offsetable.
1081 case InlineAsm::ConstraintCode::m: // Memory.
1082 if (SelectAddrFI(Inp, Res))
1083 OutOps.push_back(Res);
1084 else
1085 OutOps.push_back(Inp);
1086 break;
1087 }
1088
1089 OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32));
1090 return false;
1091}
1092
1093static bool isMemOPCandidate(SDNode *I, SDNode *U) {
1094 // I is an operand of U. Check if U is an arithmetic (binary) operation
1095 // usable in a memop, where the other operand is a loaded value, and the
1096 // result of U is stored in the same location.
1097
1098 if (!U->hasOneUse())
1099 return false;
1100 unsigned Opc = U->getOpcode();
1101 switch (Opc) {
1102 case ISD::ADD:
1103 case ISD::SUB:
1104 case ISD::AND:
1105 case ISD::OR:
1106 break;
1107 default:
1108 return false;
1109 }
1110
1111 SDValue S0 = U->getOperand(0);
1112 SDValue S1 = U->getOperand(1);
1113 SDValue SY = (S0.getNode() == I) ? S1 : S0;
1114
1115 SDNode *UUse = *U->user_begin();
1116 if (UUse->getNumValues() != 1)
1117 return false;
1118
1119 // Check if one of the inputs to U is a load instruction and the output
1120 // is used by a store instruction. If so and they also have the same
1121 // base pointer, then don't preoprocess this node sequence as it
1122 // can be matched to a memop.
1123 SDNode *SYNode = SY.getNode();
1124 if (UUse->getOpcode() == ISD::STORE && SYNode->getOpcode() == ISD::LOAD) {
1125 SDValue LDBasePtr = cast<MemSDNode>(SYNode)->getBasePtr();
1126 SDValue STBasePtr = cast<MemSDNode>(UUse)->getBasePtr();
1127 if (LDBasePtr == STBasePtr)
1128 return true;
1129 }
1130 return false;
1131}
1132
1133
1134// Transform: (or (select c x 0) z) -> (select c (or x z) z)
1135// (or (select c 0 y) z) -> (select c z (or y z))
1136void HexagonDAGToDAGISel::ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes) {
1137 SelectionDAG &DAG = *CurDAG;
1138
1139 for (auto *I : Nodes) {
1140 if (I->getOpcode() != ISD::OR)
1141 continue;
1142
1143 auto IsSelect0 = [](const SDValue &Op) -> bool {
1144 if (Op.getOpcode() != ISD::SELECT)
1145 return false;
1146 return isNullConstant(Op.getOperand(1)) ||
1147 isNullConstant(Op.getOperand(2));
1148 };
1149
1150 SDValue N0 = I->getOperand(0), N1 = I->getOperand(1);
1151 EVT VT = I->getValueType(0);
1152 bool SelN0 = IsSelect0(N0);
1153 SDValue SOp = SelN0 ? N0 : N1;
1154 SDValue VOp = SelN0 ? N1 : N0;
1155
1156 if (SOp.getOpcode() == ISD::SELECT && SOp.getNode()->hasOneUse()) {
1157 SDValue SC = SOp.getOperand(0);
1158 SDValue SX = SOp.getOperand(1);
1159 SDValue SY = SOp.getOperand(2);
1160 SDLoc DLS = SOp;
1161 if (isNullConstant(SY)) {
1162 SDValue NewOr = DAG.getNode(ISD::OR, DLS, VT, SX, VOp);
1163 SDValue NewSel = DAG.getNode(ISD::SELECT, DLS, VT, SC, NewOr, VOp);
1164 DAG.ReplaceAllUsesWith(I, NewSel.getNode());
1165 } else if (isNullConstant(SX)) {
1166 SDValue NewOr = DAG.getNode(ISD::OR, DLS, VT, SY, VOp);
1167 SDValue NewSel = DAG.getNode(ISD::SELECT, DLS, VT, SC, VOp, NewOr);
1168 DAG.ReplaceAllUsesWith(I, NewSel.getNode());
1169 }
1170 }
1171 }
1172}
1173
1174// Transform: (store ch val (add x (add (shl y c) e)))
1175// to: (store ch val (add x (shl (add y d) c))),
1176// where e = (shl d c) for some integer d.
1177// The purpose of this is to enable generation of loads/stores with
1178// shifted addressing mode, i.e. mem(x+y<<#c). For that, the shift
1179// value c must be 0, 1 or 2.
1180void HexagonDAGToDAGISel::ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes) {
1181 SelectionDAG &DAG = *CurDAG;
1182
1183 for (auto *I : Nodes) {
1184 if (I->getOpcode() != ISD::STORE)
1185 continue;
1186
1187 // I matched: (store ch val Off)
1188 SDValue Off = I->getOperand(2);
1189 // Off needs to match: (add x (add (shl y c) (shl d c))))
1190 if (Off.getOpcode() != ISD::ADD)
1191 continue;
1192 // Off matched: (add x T0)
1193 SDValue T0 = Off.getOperand(1);
1194 // T0 needs to match: (add T1 T2):
1195 if (T0.getOpcode() != ISD::ADD)
1196 continue;
1197 // T0 matched: (add T1 T2)
1198 SDValue T1 = T0.getOperand(0);
1199 SDValue T2 = T0.getOperand(1);
1200 // T1 needs to match: (shl y c)
1201 if (T1.getOpcode() != ISD::SHL)
1202 continue;
1203 SDValue C = T1.getOperand(1);
1204 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(C.getNode());
1205 if (CN == nullptr)
1206 continue;
1207 unsigned CV = CN->getZExtValue();
1208 if (CV > 2)
1209 continue;
1210 // T2 needs to match e, where e = (shl d c) for some d.
1211 ConstantSDNode *EN = dyn_cast<ConstantSDNode>(T2.getNode());
1212 if (EN == nullptr)
1213 continue;
1214 unsigned EV = EN->getZExtValue();
1215 if (EV % (1 << CV) != 0)
1216 continue;
1217 unsigned DV = EV / (1 << CV);
1218
1219 // Replace T0 with: (shl (add y d) c)
1220 SDLoc DL = SDLoc(I);
1221 EVT VT = T0.getValueType();
1222 SDValue D = DAG.getConstant(DV, DL, VT);
1223 // NewAdd = (add y d)
1224 SDValue NewAdd = DAG.getNode(ISD::ADD, DL, VT, T1.getOperand(0), D);
1225 // NewShl = (shl NewAdd c)
1226 SDValue NewShl = DAG.getNode(ISD::SHL, DL, VT, NewAdd, C);
1227 ReplaceNode(T0.getNode(), NewShl.getNode());
1228 }
1229}
1230
1231// Transform: (load ch (add x (and (srl y c) Mask)))
1232// to: (load ch (add x (shl (srl y d) d-c)))
1233// where
1234// Mask = 00..0 111..1 0.0
1235// | | +-- d-c 0s, and d-c is 0, 1 or 2.
1236// | +-------- 1s
1237// +-------------- at most c 0s
1238// Motivating example:
1239// DAG combiner optimizes (add x (shl (srl y 5) 2))
1240// to (add x (and (srl y 3) 1FFFFFFC))
1241// which results in a constant-extended and(##...,lsr). This transformation
1242// undoes this simplification for cases where the shl can be folded into
1243// an addressing mode.
1244void HexagonDAGToDAGISel::ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes) {
1245 SelectionDAG &DAG = *CurDAG;
1246
1247 for (SDNode *N : Nodes) {
1248 unsigned Opc = N->getOpcode();
1249 if (Opc != ISD::LOAD && Opc != ISD::STORE)
1250 continue;
1251 SDValue Addr = Opc == ISD::LOAD ? N->getOperand(1) : N->getOperand(2);
1252 // Addr must match: (add x T0)
1253 if (Addr.getOpcode() != ISD::ADD)
1254 continue;
1255 SDValue T0 = Addr.getOperand(1);
1256 // T0 must match: (and T1 Mask)
1257 if (T0.getOpcode() != ISD::AND)
1258 continue;
1259
1260 // We have an AND.
1261 //
1262 // Check the first operand. It must be: (srl y c).
1263 SDValue S = T0.getOperand(0);
1264 if (S.getOpcode() != ISD::SRL)
1265 continue;
1266 ConstantSDNode *SN = dyn_cast<ConstantSDNode>(S.getOperand(1).getNode());
1267 if (SN == nullptr)
1268 continue;
1269 if (SN->getAPIntValue().getBitWidth() != 32)
1270 continue;
1271 uint32_t CV = SN->getZExtValue();
1272
1273 // Check the second operand: the supposed mask.
1274 ConstantSDNode *MN = dyn_cast<ConstantSDNode>(T0.getOperand(1).getNode());
1275 if (MN == nullptr)
1276 continue;
1277 if (MN->getAPIntValue().getBitWidth() != 32)
1278 continue;
1279 uint32_t Mask = MN->getZExtValue();
1280 // Examine the mask.
1281 uint32_t TZ = llvm::countr_zero(Mask);
1282 uint32_t M1 = llvm::countr_one(Mask >> TZ);
1283 uint32_t LZ = llvm::countl_zero(Mask);
1284 // Trailing zeros + middle ones + leading zeros must equal the width.
1285 if (TZ + M1 + LZ != 32)
1286 continue;
1287 // The number of trailing zeros will be encoded in the addressing mode.
1288 if (TZ > 2)
1289 continue;
1290 // The number of leading zeros must be at most c.
1291 if (LZ > CV)
1292 continue;
1293
1294 // All looks good.
1295 SDValue Y = S.getOperand(0);
1296 EVT VT = Addr.getValueType();
1297 SDLoc dl(S);
1298 // TZ = D-C, so D = TZ+C.
1299 SDValue D = DAG.getConstant(TZ+CV, dl, VT);
1300 SDValue DC = DAG.getConstant(TZ, dl, VT);
1301 SDValue NewSrl = DAG.getNode(ISD::SRL, dl, VT, Y, D);
1302 SDValue NewShl = DAG.getNode(ISD::SHL, dl, VT, NewSrl, DC);
1303 ReplaceNode(T0.getNode(), NewShl.getNode());
1304 }
1305}
1306
1307// Transform: (op ... (zext i1 c) ...) -> (select c (op ... 0 ...)
1308// (op ... 1 ...))
1309void HexagonDAGToDAGISel::ppHoistZextI1(std::vector<SDNode*> &&Nodes) {
1310 SelectionDAG &DAG = *CurDAG;
1311
1312 for (SDNode *N : Nodes) {
1313 unsigned Opc = N->getOpcode();
1314 if (Opc != ISD::ZERO_EXTEND)
1315 continue;
1316 SDValue OpI1 = N->getOperand(0);
1317 EVT OpVT = OpI1.getValueType();
1318 if (!OpVT.isSimple() || OpVT.getSimpleVT() != MVT::i1)
1319 continue;
1320 for (SDUse &Use : N->uses()) {
1321 SDNode *U = Use.getUser();
1322 if (U->getNumValues() != 1)
1323 continue;
1324 EVT UVT = U->getValueType(0);
1325 if (!UVT.isSimple() || !UVT.isInteger() || UVT.getSimpleVT() == MVT::i1)
1326 continue;
1327 // Do not generate select for all i1 vector type.
1328 if (UVT.isVectorOf(MVT::i1))
1329 continue;
1330 if (isMemOPCandidate(N, U))
1331 continue;
1332
1333 // Potentially simplifiable operation.
1334 unsigned I1N = Use.getOperandNo();
1335 SmallVector<SDValue,2> Ops(U->getNumOperands());
1336 for (unsigned i = 0, n = U->getNumOperands(); i != n; ++i)
1337 Ops[i] = U->getOperand(i);
1338 EVT BVT = Ops[I1N].getValueType();
1339
1340 const SDLoc &dl(U);
1341 SDValue C0 = DAG.getConstant(0, dl, BVT);
1342 SDValue C1 = DAG.getConstant(1, dl, BVT);
1343 SDValue If0, If1;
1344
1345 if (isa<MachineSDNode>(U)) {
1346 unsigned UseOpc = U->getMachineOpcode();
1347 Ops[I1N] = C0;
1348 If0 = SDValue(DAG.getMachineNode(UseOpc, dl, UVT, Ops), 0);
1349 Ops[I1N] = C1;
1350 If1 = SDValue(DAG.getMachineNode(UseOpc, dl, UVT, Ops), 0);
1351 } else {
1352 unsigned UseOpc = U->getOpcode();
1353 Ops[I1N] = C0;
1354 If0 = DAG.getNode(UseOpc, dl, UVT, Ops);
1355 Ops[I1N] = C1;
1356 If1 = DAG.getNode(UseOpc, dl, UVT, Ops);
1357 }
1358 // We're generating a SELECT way after legalization, so keep the types
1359 // simple.
1360 unsigned UW = UVT.getSizeInBits();
1361 EVT SVT = (UW == 32 || UW == 64) ? MVT::getIntegerVT(UW) : UVT;
1362 SDValue Sel = DAG.getNode(ISD::SELECT, dl, SVT, OpI1,
1363 DAG.getBitcast(SVT, If1),
1364 DAG.getBitcast(SVT, If0));
1365 SDValue Ret = DAG.getBitcast(UVT, Sel);
1366 DAG.ReplaceAllUsesWith(U, Ret.getNode());
1367 }
1368 }
1369}
1370
1372 // Repack all nodes before calling each preprocessing function,
1373 // because each of them can modify the set of nodes.
1374 auto getNodes = [this]() -> std::vector<SDNode *> {
1375 std::vector<SDNode *> T;
1376 T.reserve(CurDAG->allnodes_size());
1377 for (SDNode &N : CurDAG->allnodes())
1378 T.push_back(&N);
1379 return T;
1380 };
1381
1382 if (HST->useHVXOps())
1383 PreprocessHvxISelDAG();
1384
1385 // Transform: (or (select c x 0) z) -> (select c (or x z) z)
1386 // (or (select c 0 y) z) -> (select c z (or y z))
1387 ppSimplifyOrSelect0(getNodes());
1388
1389 // Transform: (store ch val (add x (add (shl y c) e)))
1390 // to: (store ch val (add x (shl (add y d) c))),
1391 // where e = (shl d c) for some integer d.
1392 // The purpose of this is to enable generation of loads/stores with
1393 // shifted addressing mode, i.e. mem(x+y<<#c). For that, the shift
1394 // value c must be 0, 1 or 2.
1395 ppAddrReorderAddShl(getNodes());
1396
1397 // Transform: (load ch (add x (and (srl y c) Mask)))
1398 // to: (load ch (add x (shl (srl y d) d-c)))
1399 // where
1400 // Mask = 00..0 111..1 0.0
1401 // | | +-- d-c 0s, and d-c is 0, 1 or 2.
1402 // | +-------- 1s
1403 // +-------------- at most c 0s
1404 // Motivating example:
1405 // DAG combiner optimizes (add x (shl (srl y 5) 2))
1406 // to (add x (and (srl y 3) 1FFFFFFC))
1407 // which results in a constant-extended and(##...,lsr). This transformation
1408 // undoes this simplification for cases where the shl can be folded into
1409 // an addressing mode.
1410 ppAddrRewriteAndSrl(getNodes());
1411
1412 // Transform: (op ... (zext i1 c) ...) -> (select c (op ... 0 ...)
1413 // (op ... 1 ...))
1414 ppHoistZextI1(getNodes());
1415
1416 DEBUG_WITH_TYPE("isel", {
1417 dbgs() << "Preprocessed (Hexagon) selection DAG:";
1418 CurDAG->dump();
1419 });
1420
1422 rebalanceAddressTrees();
1423
1424 DEBUG_WITH_TYPE("isel", {
1425 dbgs() << "Address tree balanced selection DAG:";
1426 CurDAG->dump();
1427 });
1428 }
1429}
1430
1432 auto &HST = MF->getSubtarget<HexagonSubtarget>();
1433 auto &HFI = *HST.getFrameLowering();
1434 if (!HFI.needsAligna(*MF))
1435 return;
1436
1437 auto &HRI = *HST.getRegisterInfo();
1438 Register AP = HRI.computeStackAlignBaseRegister(*MF);
1439 assert(AP.isValid() && "Couldn't reserve stack align register");
1440 MF->getInfo<HexagonMachineFunctionInfo>()->setStackAlignBaseReg(AP);
1441}
1442
1443// Match a frame index that can be used in an addressing mode.
1445 if (N.getOpcode() != ISD::FrameIndex)
1446 return false;
1447 auto &HFI = *HST->getFrameLowering();
1448 MachineFrameInfo &MFI = MF->getFrameInfo();
1449 int FX = cast<FrameIndexSDNode>(N)->getIndex();
1450 if (!MFI.isFixedObjectIndex(FX) && HFI.needsAligna(*MF))
1451 return false;
1452 R = CurDAG->getTargetFrameIndex(FX, MVT::i32);
1453 return true;
1454}
1455
1457 return SelectGlobalAddress(N, R, false, Align(1));
1458}
1459
1461 return SelectGlobalAddress(N, R, true, Align(1));
1462}
1463
1465 return SelectAnyImmediate(N, R, Align(1));
1466}
1467
1469 return SelectAnyImmediate(N, R, Align(1));
1470}
1472 return SelectAnyImmediate(N, R, Align(2));
1473}
1475 return SelectAnyImmediate(N, R, Align(4));
1476}
1478 return SelectAnyImmediate(N, R, Align(8));
1479}
1480
1482 EVT T = N.getValueType();
1483 if (!T.isInteger() || T.getSizeInBits() != 32 || !isa<ConstantSDNode>(N))
1484 return false;
1485 uint32_t V = cast<const ConstantSDNode>(N)->getZExtValue();
1486 R = CurDAG->getTargetConstant(V, SDLoc(N), N.getValueType());
1487 return true;
1488}
1489
1491 Align Alignment) {
1492 switch (N.getOpcode()) {
1493 case ISD::Constant: {
1494 if (N.getValueType() != MVT::i32)
1495 return false;
1496 uint32_t V = cast<const ConstantSDNode>(N)->getZExtValue();
1497 if (!isAligned(Alignment, V))
1498 return false;
1499 R = CurDAG->getTargetConstant(V, SDLoc(N), N.getValueType());
1500 return true;
1501 }
1502 case HexagonISD::JT:
1503 case HexagonISD::CP:
1504 // These are assumed to always be aligned at least 8-byte boundary.
1505 if (Alignment > Align(8))
1506 return false;
1507 R = N.getOperand(0);
1508 return true;
1510 // Symbols may be aligned at any boundary.
1511 if (Alignment > Align(1))
1512 return false;
1513 R = N;
1514 return true;
1515 case ISD::BlockAddress:
1516 // Block address is always aligned at least 4-byte boundary.
1517 if (Alignment > Align(4) ||
1519 return false;
1520 R = N;
1521 return true;
1522 }
1523
1524 if (SelectGlobalAddress(N, R, false, Alignment) ||
1525 SelectGlobalAddress(N, R, true, Alignment))
1526 return true;
1527
1528 return false;
1529}
1530
1532 bool UseGP, Align Alignment) {
1533 switch (N.getOpcode()) {
1534 case ISD::ADD: {
1535 SDValue N0 = N.getOperand(0);
1536 SDValue N1 = N.getOperand(1);
1537 unsigned GAOpc = N0.getOpcode();
1538 if (UseGP && GAOpc != HexagonISD::CONST32_GP)
1539 return false;
1540 if (!UseGP && GAOpc != HexagonISD::CONST32)
1541 return false;
1542 if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1)) {
1543 if (!isAligned(Alignment, Const->getZExtValue()))
1544 return false;
1545 SDValue Addr = N0.getOperand(0);
1547 if (GA->getOpcode() == ISD::TargetGlobalAddress) {
1548 uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
1549 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(Const),
1550 N.getValueType(), NewOff);
1551 return true;
1552 }
1553 }
1554 }
1555 break;
1556 }
1557 case HexagonISD::CP:
1558 case HexagonISD::JT:
1559 case HexagonISD::CONST32:
1560 // The operand(0) of CONST32 is TargetGlobalAddress, which is what we
1561 // want in the instruction.
1562 if (!UseGP)
1563 R = N.getOperand(0);
1564 return !UseGP;
1565 case HexagonISD::CONST32_GP:
1566 if (UseGP)
1567 R = N.getOperand(0);
1568 return UseGP;
1569 default:
1570 return false;
1571 }
1572
1573 return false;
1574}
1575
1577 // This (complex pattern) function is meant to detect a sign-extension
1578 // i32->i64 on a per-operand basis. This would allow writing single
1579 // patterns that would cover a number of combinations of different ways
1580 // a sign-extensions could be written. For example:
1581 // (mul (DetectUseSxtw x) (DetectUseSxtw y)) -> (M2_dpmpyss_s0 x y)
1582 // could match either one of these:
1583 // (mul (sext x) (sext_inreg y))
1584 // (mul (sext-load *p) (sext_inreg y))
1585 // (mul (sext_inreg x) (sext y))
1586 // etc.
1587 //
1588 // The returned value will have type i64 and its low word will
1589 // contain the value being extended. The high bits are not specified.
1590 // The returned type is i64 because the original type of N was i64,
1591 // but the users of this function should only use the low-word of the
1592 // result, e.g.
1593 // (mul sxtw:x, sxtw:y) -> (M2_dpmpyss_s0 (LoReg sxtw:x), (LoReg sxtw:y))
1594
1595 if (N.getValueType() != MVT::i64)
1596 return false;
1597 unsigned Opc = N.getOpcode();
1598 switch (Opc) {
1599 case ISD::SIGN_EXTEND:
1601 // sext_inreg has the source type as a separate operand.
1603 ? N.getOperand(0).getValueType()
1604 : cast<VTSDNode>(N.getOperand(1))->getVT();
1605 unsigned SW = T.getSizeInBits();
1606 if (SW == 32)
1607 R = N.getOperand(0);
1608 else if (SW < 32)
1609 R = N;
1610 else
1611 return false;
1612 break;
1613 }
1614 case ISD::LOAD: {
1616 if (L->getExtensionType() != ISD::SEXTLOAD)
1617 return false;
1618 // All extending loads extend to i32, so even if the value in
1619 // memory is shorter than 32 bits, it will be i32 after the load.
1620 if (L->getMemoryVT().getSizeInBits() > 32)
1621 return false;
1622 R = N;
1623 break;
1624 }
1625 case ISD::SRA: {
1626 auto *S = dyn_cast<ConstantSDNode>(N.getOperand(1));
1627 if (!S || S->getZExtValue() != 32)
1628 return false;
1629 R = N;
1630 break;
1631 }
1632 case ISD::AssertSext: {
1633 EVT T = cast<VTSDNode>(N.getOperand(1))->getVT();
1634 if (T.getSizeInBits() == 32)
1635 R = N.getOperand(0);
1636 else
1637 return false;
1638 break;
1639 }
1640
1641 default:
1642 return false;
1643 }
1644 EVT RT = R.getValueType();
1645 if (RT == MVT::i64)
1646 return true;
1647 assert(RT == MVT::i32);
1648 // This is only to produce a value of type i64. Do not rely on the
1649 // high bits produced by this.
1650 const SDLoc &dl(N);
1651 SDValue Ops[] = {
1652 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
1653 R, CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
1654 R, CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
1655 };
1656 SDNode *T = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
1657 MVT::i64, Ops);
1658 R = SDValue(T, 0);
1659 return true;
1660}
1661
1662bool HexagonDAGToDAGISel::keepsLowBits(const SDValue &Val, unsigned NumBits,
1663 SDValue &Src) {
1664 unsigned Opc = Val.getOpcode();
1665 switch (Opc) {
1666 case ISD::SIGN_EXTEND:
1667 case ISD::ZERO_EXTEND:
1668 case ISD::ANY_EXTEND: {
1669 const SDValue &Op0 = Val.getOperand(0);
1670 EVT T = Op0.getValueType();
1671 if (T.isInteger() && T.getSizeInBits() == NumBits) {
1672 Src = Op0;
1673 return true;
1674 }
1675 break;
1676 }
1678 case ISD::AssertSext:
1679 case ISD::AssertZext:
1680 if (Val.getOperand(0).getValueType().isInteger()) {
1681 VTSDNode *T = cast<VTSDNode>(Val.getOperand(1));
1682 if (T->getVT().getSizeInBits() == NumBits) {
1683 Src = Val.getOperand(0);
1684 return true;
1685 }
1686 }
1687 break;
1688 case ISD::AND: {
1689 // Check if this is an AND with NumBits of lower bits set to 1.
1690 uint64_t Mask = (1ULL << NumBits) - 1;
1691 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1692 if (C->getZExtValue() == Mask) {
1693 Src = Val.getOperand(1);
1694 return true;
1695 }
1696 }
1697 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1698 if (C->getZExtValue() == Mask) {
1699 Src = Val.getOperand(0);
1700 return true;
1701 }
1702 }
1703 break;
1704 }
1705 case ISD::OR:
1706 case ISD::XOR: {
1707 // OR/XOR with the lower NumBits bits set to 0.
1708 uint64_t Mask = (1ULL << NumBits) - 1;
1709 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1710 if ((C->getZExtValue() & Mask) == 0) {
1711 Src = Val.getOperand(1);
1712 return true;
1713 }
1714 }
1715 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1716 if ((C->getZExtValue() & Mask) == 0) {
1717 Src = Val.getOperand(0);
1718 return true;
1719 }
1720 }
1721 break;
1722 }
1723 default:
1724 break;
1725 }
1726 return false;
1727}
1728
1729bool HexagonDAGToDAGISel::isAlignedMemNode(const MemSDNode *N) const {
1730 return N->getAlign().value() >= N->getMemoryVT().getStoreSize();
1731}
1732
1733bool HexagonDAGToDAGISel::isSmallStackStore(const StoreSDNode *N) const {
1734 unsigned StackSize = MF->getFrameInfo().estimateStackSize(*MF);
1735 switch (N->getMemoryVT().getStoreSize()) {
1736 case 1:
1737 return StackSize <= 56; // 1*2^6 - 8
1738 case 2:
1739 return StackSize <= 120; // 2*2^6 - 8
1740 case 4:
1741 return StackSize <= 248; // 4*2^6 - 8
1742 default:
1743 return false;
1744 }
1745}
1746
1747// Return true when the given node fits in a positive half word.
1748bool HexagonDAGToDAGISel::isPositiveHalfWord(const SDNode *N) const {
1749 if (const ConstantSDNode *CN = dyn_cast<const ConstantSDNode>(N)) {
1750 int64_t V = CN->getSExtValue();
1751 return V > 0 && isInt<16>(V);
1752 }
1753 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) {
1754 const VTSDNode *VN = dyn_cast<const VTSDNode>(N->getOperand(1));
1755 return VN->getVT().getSizeInBits() <= 16;
1756 }
1757 return false;
1758}
1759
1760bool HexagonDAGToDAGISel::hasOneUse(const SDNode *N) const {
1761 return !CheckSingleUse || N->hasOneUse();
1762}
1763
1764////////////////////////////////////////////////////////////////////////////////
1765// Rebalancing of address calculation trees
1766
1767static bool isOpcodeHandled(const SDNode *N) {
1768 switch (N->getOpcode()) {
1769 case ISD::ADD:
1770 case ISD::MUL:
1771 return true;
1772 case ISD::SHL:
1773 // We only handle constant shifts because these can be easily flattened
1774 // into multiplications by 2^Op1.
1775 return N->getNumOperands() >= 2 &&
1776 isa<ConstantSDNode>(N->getOperand(1).getNode());
1777 default:
1778 return false;
1779 }
1780}
1781
1782/// Return the weight of an SDNode
1783int HexagonDAGToDAGISel::getWeight(SDNode *N) {
1784 if (!isOpcodeHandled(N))
1785 return 1;
1786 assert(RootWeights.count(N) && "Cannot get weight of unseen root!");
1787 assert(RootWeights[N] != -1 && "Cannot get weight of unvisited root!");
1788 assert(RootWeights[N] != -2 && "Cannot get weight of RAWU'd root!");
1789 return RootWeights[N];
1790}
1791
1792int HexagonDAGToDAGISel::getHeight(SDNode *N) {
1793 if (!isOpcodeHandled(N))
1794 return 0;
1795 assert(RootWeights.count(N) && RootWeights[N] >= 0 &&
1796 "Cannot query height of unvisited/RAUW'd node!");
1797 return RootHeights[N];
1798}
1799
1800namespace {
1801struct WeightedLeaf {
1802 SDValue Value;
1803 int Weight;
1804 int InsertionOrder;
1805
1806 WeightedLeaf() = default;
1807
1808 WeightedLeaf(SDValue Value, int Weight, int InsertionOrder) :
1809 Value(Value), Weight(Weight), InsertionOrder(InsertionOrder) {
1810 assert(Weight >= 0 && "Weight must be >= 0");
1811 }
1812
1813 static bool Compare(const WeightedLeaf &A, const WeightedLeaf &B) {
1814 assert(A.Value.getNode() && B.Value.getNode());
1815 return A.Weight == B.Weight ?
1816 (A.InsertionOrder > B.InsertionOrder) :
1817 (A.Weight > B.Weight);
1818 }
1819};
1820
1821/// A specialized priority queue for WeigthedLeaves. It automatically folds
1822/// constants and allows removal of non-top elements while maintaining the
1823/// priority order.
1824class LeafPrioQueue {
1826 bool HaveConst;
1827 WeightedLeaf ConstElt;
1828 unsigned Opcode;
1829
1830public:
1831 bool empty() {
1832 return (!HaveConst && Q.empty());
1833 }
1834
1835 size_t size() {
1836 return Q.size() + HaveConst;
1837 }
1838
1839 bool hasConst() {
1840 return HaveConst;
1841 }
1842
1843 const WeightedLeaf &top() {
1844 if (HaveConst)
1845 return ConstElt;
1846 return Q.front();
1847 }
1848
1849 WeightedLeaf pop() {
1850 if (HaveConst) {
1851 HaveConst = false;
1852 return ConstElt;
1853 }
1854 std::pop_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);
1855 return Q.pop_back_val();
1856 }
1857
1858 void push(WeightedLeaf L, bool SeparateConst=true) {
1859 if (!HaveConst && SeparateConst && isa<ConstantSDNode>(L.Value)) {
1860 if (Opcode == ISD::MUL &&
1861 cast<ConstantSDNode>(L.Value)->getSExtValue() == 1)
1862 return;
1863 if (Opcode == ISD::ADD &&
1864 cast<ConstantSDNode>(L.Value)->getSExtValue() == 0)
1865 return;
1866
1867 HaveConst = true;
1868 ConstElt = L;
1869 } else {
1870 Q.push_back(L);
1871 std::push_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);
1872 }
1873 }
1874
1875 /// Push L to the bottom of the queue regardless of its weight. If L is
1876 /// constant, it will not be folded with other constants in the queue.
1877 void pushToBottom(WeightedLeaf L) {
1878 L.Weight = 1000;
1879 push(L, false);
1880 }
1881
1882 /// Search for a SHL(x, [<=MaxAmount]) subtree in the queue, return the one of
1883 /// lowest weight and remove it from the queue.
1884 WeightedLeaf findSHL(uint64_t MaxAmount);
1885
1886 WeightedLeaf findMULbyConst();
1887
1888 LeafPrioQueue(unsigned Opcode) :
1889 HaveConst(false), Opcode(Opcode) { }
1890};
1891} // end anonymous namespace
1892
1893WeightedLeaf LeafPrioQueue::findSHL(uint64_t MaxAmount) {
1894 int ResultPos;
1895 WeightedLeaf Result;
1896
1897 for (int Pos = 0, End = Q.size(); Pos != End; ++Pos) {
1898 const WeightedLeaf &L = Q[Pos];
1899 const SDValue &Val = L.Value;
1900 if (Val.getOpcode() != ISD::SHL || Val.getNumOperands() < 2 ||
1902 Val.getConstantOperandVal(1) > MaxAmount)
1903 continue;
1904 if (!Result.Value.getNode() || Result.Weight > L.Weight ||
1905 (Result.Weight == L.Weight && Result.InsertionOrder > L.InsertionOrder))
1906 {
1907 Result = L;
1908 ResultPos = Pos;
1909 }
1910 }
1911
1912 if (Result.Value.getNode()) {
1913 Q.erase(&Q[ResultPos]);
1914 std::make_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);
1915 }
1916
1917 return Result;
1918}
1919
1920WeightedLeaf LeafPrioQueue::findMULbyConst() {
1921 int ResultPos;
1922 WeightedLeaf Result;
1923
1924 for (int Pos = 0, End = Q.size(); Pos != End; ++Pos) {
1925 const WeightedLeaf &L = Q[Pos];
1926 const SDValue &Val = L.Value;
1927 if (Val.getOpcode() != ISD::MUL || Val.getNumOperands() < 2 ||
1929 Val.getConstantOperandVal(1) > 127)
1930 continue;
1931 if (!Result.Value.getNode() || Result.Weight > L.Weight ||
1932 (Result.Weight == L.Weight && Result.InsertionOrder > L.InsertionOrder))
1933 {
1934 Result = L;
1935 ResultPos = Pos;
1936 }
1937 }
1938
1939 if (Result.Value.getNode()) {
1940 Q.erase(&Q[ResultPos]);
1941 std::make_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);
1942 }
1943
1944 return Result;
1945}
1946
1947SDValue HexagonDAGToDAGISel::getMultiplierForSHL(SDNode *N) {
1948 if (N->getNumOperands() < 2)
1949 return SDValue();
1950 uint64_t MulFactor = 1ull << N->getConstantOperandVal(1);
1951 return CurDAG->getConstant(MulFactor, SDLoc(N),
1952 N->getOperand(1).getValueType());
1953}
1954
1955/// @returns the value x for which 2^x is a factor of Val
1956static unsigned getPowerOf2Factor(SDValue Val) {
1957 if (Val.getOpcode() == ISD::MUL) {
1958 if (Val.getNumOperands() < 2)
1959 return 0;
1960 unsigned MaxFactor = 0;
1961 for (int i = 0; i < 2; ++i) {
1963 if (!C)
1964 continue;
1965 const APInt &CInt = C->getAPIntValue();
1966 if (CInt.getBoolValue())
1967 MaxFactor = CInt.countr_zero();
1968 }
1969 return MaxFactor;
1970 }
1971 if (Val.getOpcode() == ISD::SHL) {
1972 if (Val.getNumOperands() < 2 ||
1974 return 0;
1975 return (unsigned) Val.getConstantOperandVal(1);
1976 }
1977
1978 return 0;
1979}
1980
1981/// @returns true if V>>Amount will eliminate V's operation on its child
1982static bool willShiftRightEliminate(SDValue V, unsigned Amount) {
1983 if (V.getOpcode() == ISD::MUL) {
1984 if (V.getNumOperands() < 2)
1985 return false;
1986 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };
1987 for (int i = 0; i < 2; ++i)
1988 if (isa<ConstantSDNode>(Ops[i].getNode()) &&
1989 V.getConstantOperandVal(i) % (1ULL << Amount) == 0) {
1990 uint64_t NewConst = V.getConstantOperandVal(i) >> Amount;
1991 return (NewConst == 1);
1992 }
1993 } else if (V.getOpcode() == ISD::SHL) {
1994 if (V.getNumOperands() < 2 ||
1995 !isa<ConstantSDNode>(V.getOperand(1).getNode()))
1996 return false;
1997 return (Amount == V.getConstantOperandVal(1));
1998 }
1999
2000 return false;
2001}
2002
2003SDValue HexagonDAGToDAGISel::factorOutPowerOf2(SDValue V, unsigned Power) {
2004 // Ensure the node has at least 2 operands before accessing them.
2005 if (V.getNumOperands() < 2)
2006 return V;
2007
2008 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };
2009 if (V.getOpcode() == ISD::MUL) {
2010 for (int i=0; i < 2; ++i) {
2011 if (isa<ConstantSDNode>(Ops[i].getNode()) &&
2012 V.getConstantOperandVal(i) % ((uint64_t)1 << Power) == 0) {
2013 uint64_t NewConst = V.getConstantOperandVal(i) >> Power;
2014 if (NewConst == 1)
2015 return Ops[!i];
2016 Ops[i] = CurDAG->getConstant(NewConst,
2017 SDLoc(V), V.getValueType());
2018 break;
2019 }
2020 }
2021 } else if (V.getOpcode() == ISD::SHL) {
2022 if (!isa<ConstantSDNode>(V.getOperand(1).getNode()))
2023 return V;
2024 uint64_t ShiftAmount = V.getConstantOperandVal(1);
2025 if (ShiftAmount == Power)
2026 return Ops[0];
2027 Ops[1] = CurDAG->getConstant(ShiftAmount - Power,
2028 SDLoc(V), V.getValueType());
2029 }
2030
2031 return CurDAG->getNode(V.getOpcode(), SDLoc(V), V.getValueType(), Ops);
2032}
2033
2034static bool isTargetConstant(const SDValue &V) {
2035 return V.getOpcode() == HexagonISD::CONST32 ||
2036 V.getOpcode() == HexagonISD::CONST32_GP;
2037}
2038
2039unsigned HexagonDAGToDAGISel::getUsesInFunction(const Value *V) {
2040 auto [It, Inserted] = GAUsesInFunction.try_emplace(V);
2041 if (!Inserted)
2042 return It->second;
2043
2044 unsigned Result = 0;
2045 const Function &CurF = CurDAG->getMachineFunction().getFunction();
2046 for (const User *U : V->users()) {
2047 if (isa<Instruction>(U) &&
2048 cast<Instruction>(U)->getParent()->getParent() == &CurF)
2049 ++Result;
2050 }
2051
2052 It->second = Result;
2053
2054 return Result;
2055}
2056
2057/// Note - After calling this, N may be dead. It may have been replaced by a
2058/// new node, so always use the returned value in place of N.
2059///
2060/// @returns The SDValue taking the place of N (which could be N if it is
2061/// unchanged)
2062SDValue HexagonDAGToDAGISel::balanceSubTree(SDNode *N, bool TopLevel) {
2063 assert(RootWeights.count(N) && "Cannot balance non-root node.");
2064 assert(RootWeights[N] != -2 && "This node was RAUW'd!");
2065 assert(!TopLevel || N->getOpcode() == ISD::ADD);
2066
2067 // Return early if this node was already visited
2068 if (RootWeights[N] != -1)
2069 return SDValue(N, 0);
2070
2072
2073 if (N->getNumOperands() < 2)
2074 return SDValue(N, 0);
2075
2076 SDValue Op0 = N->getOperand(0);
2077 SDValue Op1 = N->getOperand(1);
2078
2079 // Return early if the operands will remain unchanged or are all roots
2080 if ((!isOpcodeHandled(Op0.getNode()) || RootWeights.count(Op0.getNode())) &&
2081 (!isOpcodeHandled(Op1.getNode()) || RootWeights.count(Op1.getNode()))) {
2082 SDNode *Op0N = Op0.getNode();
2083 int Weight;
2084 if (isOpcodeHandled(Op0N) && RootWeights[Op0N] == -1) {
2085 Weight = getWeight(balanceSubTree(Op0N).getNode());
2086 // Weight = calculateWeight(Op0N);
2087 } else
2088 Weight = getWeight(Op0N);
2089
2090 SDNode *Op1N = Op1.getNode();
2091 if (isOpcodeHandled(Op1N) && RootWeights[Op1N] == -1) {
2092 Weight += getWeight(balanceSubTree(Op1N).getNode());
2093 // Weight += calculateWeight(Op1N);
2094 } else
2095 Weight += getWeight(Op1N);
2096
2097 RootWeights[N] = Weight;
2098
2099 // After recursive calls, check if Op0/Op1 are still valid before getting
2100 // height
2101 int Height0 = 0, Height1 = 0;
2102 if (isOpcodeHandled(Op0N) && RootWeights.count(Op0N) &&
2103 RootWeights[Op0N] >= 0)
2104 Height0 = getHeight(Op0N);
2105 if (isOpcodeHandled(Op1N) && RootWeights.count(Op1N) &&
2106 RootWeights[Op1N] >= 0)
2107 Height1 = getHeight(Op1N);
2108
2109 RootHeights[N] = std::max(Height0, Height1) + 1;
2110
2111 LLVM_DEBUG(dbgs() << "--> No need to balance root (Weight=" << Weight
2112 << " Height=" << RootHeights[N] << "): ");
2113 LLVM_DEBUG(N->dump(CurDAG));
2114
2115 return SDValue(N, 0);
2116 }
2117
2118 LLVM_DEBUG(dbgs() << "** Balancing root node: ");
2119 LLVM_DEBUG(N->dump(CurDAG));
2120
2121 unsigned NOpcode = N->getOpcode();
2122
2123 LeafPrioQueue Leaves(NOpcode);
2124 SmallVector<SDValue, 4> Worklist;
2125 Worklist.push_back(SDValue(N, 0));
2126
2127 // SHL nodes will be converted to MUL nodes
2128 if (NOpcode == ISD::SHL)
2129 NOpcode = ISD::MUL;
2130
2131 bool CanFactorize = false;
2132 WeightedLeaf Mul1, Mul2;
2133 unsigned MaxPowerOf2 = 0;
2134 WeightedLeaf GA;
2135
2136 // Do not try to factor out a shift if there is already a shift at the tip of
2137 // the tree.
2138 bool HaveTopLevelShift = false;
2139 if (TopLevel &&
2140 ((isOpcodeHandled(Op0.getNode()) && Op0.getOpcode() == ISD::SHL &&
2141 Op0.getNumOperands() >= 2 && Op0.getConstantOperandVal(1) < 4) ||
2142 (isOpcodeHandled(Op1.getNode()) && Op1.getOpcode() == ISD::SHL &&
2143 Op1.getNumOperands() >= 2 && Op1.getConstantOperandVal(1) < 4)))
2144 HaveTopLevelShift = true;
2145
2146 // Flatten the subtree into an ordered list of leaves; at the same time
2147 // determine whether the tree is already balanced.
2148 int InsertionOrder = 0;
2149 SmallDenseMap<SDValue, int> NodeHeights;
2150 bool Imbalanced = false;
2151 int CurrentWeight = 0;
2152 while (!Worklist.empty()) {
2153 SDValue Child = Worklist.pop_back_val();
2154
2155 if (Child.getNode() != N && RootWeights.count(Child.getNode())) {
2156 // CASE 1: Child is a root note
2157
2158 int Weight = RootWeights[Child.getNode()];
2159 if (Weight == -1) {
2160 Child = balanceSubTree(Child.getNode());
2161 // calculateWeight(Child.getNode());
2162 Weight = getWeight(Child.getNode());
2163 } else if (Weight == -2) {
2164 // Whoops, this node was RAUWd by one of the balanceSubTree calls we
2165 // made. Our worklist isn't up to date anymore.
2166 // Restart the whole process.
2167 LLVM_DEBUG(dbgs() << "--> Subtree was RAUWd. Restarting...\n");
2168 return balanceSubTree(N, TopLevel);
2169 }
2170
2171 NodeHeights[Child] = 1;
2172 CurrentWeight += Weight;
2173
2174 unsigned PowerOf2;
2175 if (TopLevel && !CanFactorize && !HaveTopLevelShift &&
2176 (Child.getOpcode() == ISD::MUL || Child.getOpcode() == ISD::SHL) &&
2177 Child.hasOneUse() && (PowerOf2 = getPowerOf2Factor(Child))) {
2178 // Try to identify two factorizable MUL/SHL children greedily. Leave
2179 // them out of the priority queue for now so we can deal with them
2180 // after.
2181 if (!Mul1.Value.getNode()) {
2182 Mul1 = WeightedLeaf(Child, Weight, InsertionOrder++);
2183 MaxPowerOf2 = PowerOf2;
2184 } else {
2185 Mul2 = WeightedLeaf(Child, Weight, InsertionOrder++);
2186 MaxPowerOf2 = std::min(MaxPowerOf2, PowerOf2);
2187
2188 // Our addressing modes can only shift by a maximum of 3
2189 if (MaxPowerOf2 > 3)
2190 MaxPowerOf2 = 3;
2191
2192 CanFactorize = true;
2193 }
2194 } else
2195 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2196 } else if (!isOpcodeHandled(Child.getNode())) {
2197 // CASE 2: Child is an unhandled kind of node (e.g. constant)
2198 int Weight = getWeight(Child.getNode());
2199
2200 NodeHeights[Child] = getHeight(Child.getNode());
2201 CurrentWeight += Weight;
2202
2203 if (isTargetConstant(Child) && !GA.Value.getNode())
2204 GA = WeightedLeaf(Child, Weight, InsertionOrder++);
2205 else
2206 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2207 } else {
2208 // CASE 3: Child is a subtree of same opcode
2209 // Visit children first, then flatten.
2210 unsigned ChildOpcode = Child.getOpcode();
2211 assert(ChildOpcode == NOpcode ||
2212 (NOpcode == ISD::MUL && ChildOpcode == ISD::SHL));
2213
2214 if (Child->getNumOperands() < 2) {
2215 // Treat as a leaf if not enough operands
2216 int Weight = getWeight(Child.getNode());
2217 NodeHeights[Child] = getHeight(Child.getNode());
2218 CurrentWeight += Weight;
2219 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2220 continue;
2221 }
2222
2223 // Convert SHL to MUL
2224 SDValue Op1;
2225 if (ChildOpcode == ISD::SHL) {
2226 Op1 = getMultiplierForSHL(Child.getNode());
2227 assert(Op1.getNode() && "getMultiplierForSHL returned null");
2228 } else
2229 Op1 = Child->getOperand(1);
2230
2231 if (!NodeHeights.count(Op1) || !NodeHeights.count(Child->getOperand(0))) {
2232 assert(!NodeHeights.count(Child) && "Parent visited before children?");
2233 // Visit children first, then re-visit this node
2234 Worklist.push_back(Child);
2235 Worklist.push_back(Op1);
2236 Worklist.push_back(Child->getOperand(0));
2237 } else {
2238 // Back at this node after visiting the children
2239 if (std::abs(NodeHeights[Op1] - NodeHeights[Child->getOperand(0)]) > 1)
2240 Imbalanced = true;
2241
2242 NodeHeights[Child] = std::max(NodeHeights[Op1],
2243 NodeHeights[Child->getOperand(0)]) + 1;
2244 }
2245 }
2246 }
2247
2248 LLVM_DEBUG(dbgs() << "--> Current height=" << NodeHeights[SDValue(N, 0)]
2249 << " weight=" << CurrentWeight
2250 << " imbalanced=" << Imbalanced << "\n");
2251
2252 // Transform MUL(x, C * 2^Y) + SHL(z, Y) -> SHL(ADD(MUL(x, C), z), Y)
2253 // This factors out a shift in order to match memw(a<<Y+b).
2254 if (CanFactorize && (willShiftRightEliminate(Mul1.Value, MaxPowerOf2) ||
2255 willShiftRightEliminate(Mul2.Value, MaxPowerOf2))) {
2256 LLVM_DEBUG(dbgs() << "--> Found common factor for two MUL children!\n");
2257 int Weight = Mul1.Weight + Mul2.Weight;
2258 int Height = std::max(NodeHeights[Mul1.Value], NodeHeights[Mul2.Value]) + 1;
2259 SDValue Mul1Factored = factorOutPowerOf2(Mul1.Value, MaxPowerOf2);
2260 SDValue Mul2Factored = factorOutPowerOf2(Mul2.Value, MaxPowerOf2);
2261 SDValue Sum = CurDAG->getNode(ISD::ADD, SDLoc(N), Mul1.Value.getValueType(),
2262 Mul1Factored, Mul2Factored);
2263 SDValue Const = CurDAG->getConstant(MaxPowerOf2, SDLoc(N),
2264 Mul1.Value.getValueType());
2265 SDValue New = CurDAG->getNode(ISD::SHL, SDLoc(N), Mul1.Value.getValueType(),
2266 Sum, Const);
2267 NodeHeights[New] = Height;
2268 Leaves.push(WeightedLeaf(New, Weight, Mul1.InsertionOrder));
2269 } else if (Mul1.Value.getNode()) {
2270 // We failed to factorize two MULs, so now the Muls are left outside the
2271 // queue... add them back.
2272 Leaves.push(Mul1);
2273 if (Mul2.Value.getNode())
2274 Leaves.push(Mul2);
2275 CanFactorize = false;
2276 }
2277
2278 // Combine GA + Constant -> GA+Offset, but only if GA is not used elsewhere
2279 // and the root node itself is not used more than twice. This reduces the
2280 // amount of additional constant extenders introduced by this optimization.
2281 bool CombinedGA = false;
2282 if (NOpcode == ISD::ADD && GA.Value.getNode() && Leaves.hasConst() &&
2283 GA.Value.hasOneUse() && N->use_size() < 3 &&
2284 GA.Value.getNumOperands() >= 1) {
2285 GlobalAddressSDNode *GANode =
2287 ConstantSDNode *Offset = cast<ConstantSDNode>(Leaves.top().Value);
2288
2289 if (getUsesInFunction(GANode->getGlobal()) == 1 && Offset->hasOneUse() &&
2290 getTargetLowering()->isOffsetFoldingLegal(GANode)) {
2291 LLVM_DEBUG(dbgs() << "--> Combining GA and offset ("
2292 << Offset->getSExtValue() << "): ");
2293 LLVM_DEBUG(GANode->dump(CurDAG));
2294
2295 SDValue NewTGA =
2296 CurDAG->getTargetGlobalAddress(GANode->getGlobal(), SDLoc(GA.Value),
2297 GANode->getValueType(0),
2298 GANode->getOffset() + (uint64_t)Offset->getSExtValue());
2299 GA.Value = CurDAG->getNode(GA.Value.getOpcode(), SDLoc(GA.Value),
2300 GA.Value.getValueType(), NewTGA);
2301 GA.Weight += Leaves.top().Weight;
2302
2303 NodeHeights[GA.Value] = getHeight(GA.Value.getNode());
2304 CombinedGA = true;
2305
2306 Leaves.pop(); // Remove the offset constant from the queue
2307 }
2308 }
2309
2310 if ((RebalanceOnlyForOptimizations && !CanFactorize && !CombinedGA) ||
2311 (RebalanceOnlyImbalancedTrees && !Imbalanced)) {
2312 RootWeights[N] = CurrentWeight;
2313 RootHeights[N] = NodeHeights[SDValue(N, 0)];
2314
2315 return SDValue(N, 0);
2316 }
2317
2318 // Combine GA + SHL(x, C<=31) so we will match Rx=add(#u8,asl(Rx,#U5))
2319 if (NOpcode == ISD::ADD && GA.Value.getNode()) {
2320 WeightedLeaf SHL = Leaves.findSHL(31);
2321 if (SHL.Value.getNode()) {
2322 int Height = std::max(NodeHeights[GA.Value], NodeHeights[SHL.Value]) + 1;
2323 GA.Value = CurDAG->getNode(ISD::ADD, SDLoc(GA.Value),
2324 GA.Value.getValueType(),
2325 GA.Value, SHL.Value);
2326 GA.Weight = SHL.Weight; // Specifically ignore the GA weight here
2327 NodeHeights[GA.Value] = Height;
2328 }
2329 }
2330
2331 if (GA.Value.getNode())
2332 Leaves.push(GA);
2333
2334 // If this is the top level and we haven't factored out a shift, we should try
2335 // to move a constant to the bottom to match addressing modes like memw(rX+C)
2336 if (TopLevel && !CanFactorize && Leaves.hasConst()) {
2337 LLVM_DEBUG(dbgs() << "--> Pushing constant to tip of tree.");
2338 Leaves.pushToBottom(Leaves.pop());
2339 }
2340
2341 const DataLayout &DL = CurDAG->getDataLayout();
2342 const TargetLowering &TLI = *getTargetLowering();
2343
2344 // Rebuild the tree using Huffman's algorithm
2345 while (Leaves.size() > 1) {
2346 WeightedLeaf L0 = Leaves.pop();
2347
2348 // See whether we can grab a MUL to form an add(Rx,mpyi(Ry,#u6)),
2349 // otherwise just get the next leaf
2350 WeightedLeaf L1 = Leaves.findMULbyConst();
2351 if (!L1.Value.getNode())
2352 L1 = Leaves.pop();
2353
2354 assert(L0.Weight <= L1.Weight && "Priority queue is broken!");
2355
2356 SDValue V0 = L0.Value;
2357 int V0Weight = L0.Weight;
2358 SDValue V1 = L1.Value;
2359 int V1Weight = L1.Weight;
2360
2361 // Make sure that none of these nodes have been RAUW'd
2362 if ((RootWeights.count(V0.getNode()) && RootWeights[V0.getNode()] == -2) ||
2363 (RootWeights.count(V1.getNode()) && RootWeights[V1.getNode()] == -2)) {
2364 LLVM_DEBUG(dbgs() << "--> Subtree was RAUWd. Restarting...\n");
2365 return balanceSubTree(N, TopLevel);
2366 }
2367
2368 ConstantSDNode *V0C = dyn_cast<ConstantSDNode>(V0);
2369 ConstantSDNode *V1C = dyn_cast<ConstantSDNode>(V1);
2370 EVT VT = N->getValueType(0);
2371 SDValue NewNode;
2372
2373 if (V0C && !V1C) {
2374 std::swap(V0, V1);
2375 std::swap(V0C, V1C);
2376 }
2377
2378 // Calculate height of this node
2379 assert(NodeHeights.count(V0) && NodeHeights.count(V1) &&
2380 "Children must have been visited before re-combining them!");
2381 int Height = std::max(NodeHeights[V0], NodeHeights[V1]) + 1;
2382
2383 // Rebuild this node (and restore SHL from MUL if needed)
2384 if (V1C && NOpcode == ISD::MUL && V1C->getAPIntValue().isPowerOf2())
2385 NewNode = CurDAG->getNode(
2386 ISD::SHL, SDLoc(V0), VT, V0,
2387 CurDAG->getConstant(
2388 V1C->getAPIntValue().logBase2(), SDLoc(N),
2389 TLI.getScalarShiftAmountTy(DL, V0.getValueType())));
2390 else
2391 NewNode = CurDAG->getNode(NOpcode, SDLoc(N), VT, V0, V1);
2392
2393 NodeHeights[NewNode] = Height;
2394
2395 int Weight = V0Weight + V1Weight;
2396 Leaves.push(WeightedLeaf(NewNode, Weight, L0.InsertionOrder));
2397
2398 LLVM_DEBUG(dbgs() << "--> Built new node (Weight=" << Weight
2399 << ",Height=" << Height << "):\n");
2400 LLVM_DEBUG(NewNode.dump());
2401 }
2402
2403 assert(Leaves.size() == 1);
2404 SDValue NewRoot = Leaves.top().Value;
2405
2406 assert(NodeHeights.count(NewRoot));
2407 int Height = NodeHeights[NewRoot];
2408
2409 // Restore SHL if we earlier converted it to a MUL
2410 if (NewRoot.getOpcode() == ISD::MUL && NewRoot->getNumOperands() >= 2) {
2411 ConstantSDNode *V1C = dyn_cast<ConstantSDNode>(NewRoot.getOperand(1));
2412 if (V1C && V1C->getAPIntValue().isPowerOf2()) {
2413 EVT VT = NewRoot.getValueType();
2414 SDValue V0 = NewRoot.getOperand(0);
2415 NewRoot = CurDAG->getNode(
2416 ISD::SHL, SDLoc(NewRoot), VT, V0,
2417 CurDAG->getConstant(
2418 V1C->getAPIntValue().logBase2(), SDLoc(NewRoot),
2419 TLI.getScalarShiftAmountTy(DL, V0.getValueType())));
2420 }
2421 }
2422
2423 if (N != NewRoot.getNode()) {
2424 LLVM_DEBUG(dbgs() << "--> Root is now: ");
2425 LLVM_DEBUG(NewRoot.dump());
2426
2427 // Replace all uses of old root by new root
2428 CurDAG->ReplaceAllUsesWith(N, NewRoot.getNode());
2429 // Mark that we have RAUW'd N
2430 RootWeights[N] = -2;
2431 } else {
2432 LLVM_DEBUG(dbgs() << "--> Root unchanged.\n");
2433 }
2434
2435 RootWeights[NewRoot.getNode()] = Leaves.top().Weight;
2436 RootHeights[NewRoot.getNode()] = Height;
2437
2438 return NewRoot;
2439}
2440
2441void HexagonDAGToDAGISel::rebalanceAddressTrees() {
2442 for (SDNode &Node : llvm::make_early_inc_range(CurDAG->allnodes())) {
2443 SDNode *N = &Node;
2444 if (N->getOpcode() != ISD::LOAD && N->getOpcode() != ISD::STORE)
2445 continue;
2446
2447 SDValue BasePtr = cast<MemSDNode>(N)->getBasePtr();
2448 if (BasePtr.getOpcode() != ISD::ADD)
2449 continue;
2450
2451 // We've already processed this node
2452 if (RootWeights.count(BasePtr.getNode()))
2453 continue;
2454
2455 LLVM_DEBUG(dbgs() << "** Rebalancing address calculation in node: ");
2456 LLVM_DEBUG(N->dump(CurDAG));
2457
2458 // FindRoots
2459 SmallVector<SDNode *, 4> Worklist;
2460
2461 if (BasePtr->getNumOperands() < 2)
2462 continue;
2463
2464 Worklist.push_back(BasePtr.getOperand(0).getNode());
2465 Worklist.push_back(BasePtr.getOperand(1).getNode());
2466
2467 while (!Worklist.empty()) {
2468 SDNode *N = Worklist.pop_back_val();
2469 unsigned Opcode = N->getOpcode();
2470
2471 if (!isOpcodeHandled(N))
2472 continue;
2473
2474 if (N->getNumOperands() < 2)
2475 continue;
2476
2477 Worklist.push_back(N->getOperand(0).getNode());
2478 Worklist.push_back(N->getOperand(1).getNode());
2479
2480 // Not a root if it has only one use and same opcode as its parent
2481 if (N->hasOneUse() && Opcode == N->user_begin()->getOpcode())
2482 continue;
2483
2484 // This root node has already been processed
2485 RootWeights.try_emplace(N, -1);
2486 }
2487
2488 // Balance node itself
2489 RootWeights[BasePtr.getNode()] = -1;
2490 SDValue NewBasePtr = balanceSubTree(BasePtr.getNode(), /*TopLevel=*/ true);
2491
2492 if (N->getOpcode() == ISD::LOAD) {
2493 if (N->getNumOperands() >= 3)
2494 N = CurDAG->UpdateNodeOperands(N, N->getOperand(0), NewBasePtr,
2495 N->getOperand(2));
2496 } else {
2497 if (N->getNumOperands() >= 4)
2498 N = CurDAG->UpdateNodeOperands(N, N->getOperand(0), N->getOperand(1),
2499 NewBasePtr, N->getOperand(3));
2500 }
2501
2502 LLVM_DEBUG(dbgs() << "--> Final node: ");
2503 LLVM_DEBUG(N->dump(CurDAG));
2504 }
2505
2506 CurDAG->RemoveDeadNodes();
2507 GAUsesInFunction.clear();
2508 RootHeights.clear();
2509 RootWeights.clear();
2510}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
unsigned 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 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
#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:1509
unsigned countr_zero() const
Count the number of trailing zero bits.
Definition APInt.h:1660
unsigned logBase2() const
Definition APInt.h:1782
bool getBoolValue() const
Convert APInt to a boolean value.
Definition APInt.h:468
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
Definition APInt.h:437
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:219
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
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
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.
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:165
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:264
@ 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:863
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:854
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:806
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition ISDOpcodes.h:185
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:771
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:651
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:616
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:860
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:898
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:205
@ ExternalSymbol
Definition ISDOpcodes.h:93
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:62
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition ISDOpcodes.h:213
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:578
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:1669
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:134
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:633
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:149
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
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
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.