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