LLVM 22.0.0git
RISCVLoadStoreOptimizer.cpp
Go to the documentation of this file.
1//===----- RISCVLoadStoreOptimizer.cpp ------------------------------------===//
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// Load/Store Pairing: It identifies pairs of load or store instructions
10// operating on consecutive memory locations and merges them into a single
11// paired instruction, leveraging hardware support for paired memory accesses.
12// Much of the pairing logic is adapted from the AArch64LoadStoreOpt pass.
13//
14// Post-allocation Zilsd decomposition: Fixes invalid LD/SD instructions if
15// register allocation didn't provide suitable consecutive registers.
16//
17// NOTE: The AArch64LoadStoreOpt pass performs additional optimizations such as
18// merging zero store instructions, promoting loads that read directly from a
19// preceding store, and merging base register updates with load/store
20// instructions (via pre-/post-indexed addressing). These advanced
21// transformations are not yet implemented in the RISC-V pass but represent
22// potential future enhancements for further optimizing RISC-V memory
23// operations.
24//
25//===----------------------------------------------------------------------===//
26
27#include "RISCV.h"
28#include "RISCVTargetMachine.h"
29#include "llvm/ADT/Statistic.h"
31#include "llvm/CodeGen/Passes.h"
33#include "llvm/Support/Debug.h"
35
36using namespace llvm;
37
38#define DEBUG_TYPE "riscv-load-store-opt"
39#define RISCV_LOAD_STORE_OPT_NAME "RISC-V Load / Store Optimizer"
40
41// The LdStLimit limits number of instructions how far we search for load/store
42// pairs.
43static cl::opt<unsigned> LdStLimit("riscv-load-store-scan-limit", cl::init(128),
45STATISTIC(NumLD2LW, "Number of LD instructions split back to LW");
46STATISTIC(NumSD2SW, "Number of SD instructions split back to SW");
47
48namespace {
49
50struct RISCVLoadStoreOpt : public MachineFunctionPass {
51 static char ID;
52 bool runOnMachineFunction(MachineFunction &Fn) override;
53
54 RISCVLoadStoreOpt() : MachineFunctionPass(ID) {}
55
56 MachineFunctionProperties getRequiredProperties() const override {
57 return MachineFunctionProperties().setNoVRegs();
58 }
59
60 void getAnalysisUsage(AnalysisUsage &AU) const override {
61 AU.addRequired<AAResultsWrapperPass>();
63 }
64
65 StringRef getPassName() const override { return RISCV_LOAD_STORE_OPT_NAME; }
66
67 // Find and pair load/store instructions.
68 bool tryToPairLdStInst(MachineBasicBlock::iterator &MBBI);
69
70 // Convert load/store pairs to single instructions.
71 bool tryConvertToLdStPair(MachineBasicBlock::iterator First,
73 bool tryConvertToXqcilsmLdStPair(MachineFunction *MF,
76 bool tryConvertToMIPSLdStPair(MachineFunction *MF,
79
80 // Scan the instructions looking for a load/store that can be combined
81 // with the current instruction into a load/store pair.
82 // Return the matching instruction if one is found, else MBB->end().
84 bool &MergeForward);
85
87 mergePairedInsns(MachineBasicBlock::iterator I,
88 MachineBasicBlock::iterator Paired, bool MergeForward);
89
90 // Post reg-alloc zilsd part
91 bool fixInvalidRegPairOp(MachineBasicBlock &MBB,
93 bool isValidZilsdRegPair(Register First, Register Second);
94 void splitLdSdIntoTwo(MachineBasicBlock &MBB,
95 MachineBasicBlock::iterator &MBBI, bool IsLoad);
96
97private:
98 AliasAnalysis *AA;
99 MachineRegisterInfo *MRI;
100 const RISCVInstrInfo *TII;
101 const RISCVRegisterInfo *TRI;
102 LiveRegUnits ModifiedRegUnits, UsedRegUnits;
103};
104} // end anonymous namespace
105
106char RISCVLoadStoreOpt::ID = 0;
108 false)
109
110bool RISCVLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
111 if (skipFunction(Fn.getFunction()))
112 return false;
113 const RISCVSubtarget &Subtarget = Fn.getSubtarget<RISCVSubtarget>();
114
115 bool MadeChange = false;
116 TII = Subtarget.getInstrInfo();
117 TRI = Subtarget.getRegisterInfo();
118 MRI = &Fn.getRegInfo();
119 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
120 ModifiedRegUnits.init(*TRI);
121 UsedRegUnits.init(*TRI);
122
123 if (Subtarget.useMIPSLoadStorePairs() || Subtarget.hasVendorXqcilsm()) {
124 for (MachineBasicBlock &MBB : Fn) {
125 LLVM_DEBUG(dbgs() << "MBB: " << MBB.getName() << "\n");
126
127 for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
128 MBBI != E;) {
129 if (TII->isPairableLdStInstOpc(MBBI->getOpcode()) &&
130 tryToPairLdStInst(MBBI))
131 MadeChange = true;
132 else
133 ++MBBI;
134 }
135 }
136 }
137
138 if (!Subtarget.is64Bit() && Subtarget.hasStdExtZilsd()) {
139 for (auto &MBB : Fn) {
140 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E;) {
141 if (fixInvalidRegPairOp(MBB, MBBI)) {
142 MadeChange = true;
143 // Iterator was updated by fixInvalidRegPairOp
144 } else {
145 ++MBBI;
146 }
147 }
148 }
149 }
150
151 return MadeChange;
152}
153
154// Find loads and stores that can be merged into a single load or store pair
155// instruction.
156bool RISCVLoadStoreOpt::tryToPairLdStInst(MachineBasicBlock::iterator &MBBI) {
157 MachineInstr &MI = *MBBI;
158
159 // If this is volatile, it is not a candidate.
160 if (MI.hasOrderedMemoryRef())
161 return false;
162
163 if (!TII->isLdStSafeToPair(MI, TRI))
164 return false;
165
166 // Look ahead for a pairable instruction.
167 MachineBasicBlock::iterator E = MI.getParent()->end();
168 bool MergeForward;
169 MachineBasicBlock::iterator Paired = findMatchingInsn(MBBI, MergeForward);
170 if (Paired != E) {
171 MBBI = mergePairedInsns(MBBI, Paired, MergeForward);
172 return true;
173 }
174 return false;
175}
176
177bool RISCVLoadStoreOpt::tryConvertToXqcilsmLdStPair(
178 MachineFunction *MF, MachineBasicBlock::iterator First,
180 unsigned Opc = First->getOpcode();
181 if ((Opc != RISCV::LW && Opc != RISCV::SW) || Second->getOpcode() != Opc)
182 return false;
183
184 const auto &FirstOp1 = First->getOperand(1);
185 const auto &SecondOp1 = Second->getOperand(1);
186 const auto &FirstOp2 = First->getOperand(2);
187 const auto &SecondOp2 = Second->getOperand(2);
188
189 // Require simple reg+imm addressing for both.
190 if (!FirstOp1.isReg() || !SecondOp1.isReg() || !FirstOp2.isImm() ||
191 !SecondOp2.isImm())
192 return false;
193
194 Register Base1 = FirstOp1.getReg();
195 Register Base2 = SecondOp1.getReg();
196
197 if (Base1 != Base2)
198 return false;
199
200 const MachineMemOperand *MMO = *First->memoperands_begin();
201 Align MMOAlign = MMO->getAlign();
202
203 if (MMOAlign < Align(4))
204 return false;
205
206 auto &FirstOp0 = First->getOperand(0);
207 auto &SecondOp0 = Second->getOperand(0);
208
209 int64_t Off1 = FirstOp2.getImm();
210 int64_t Off2 = SecondOp2.getImm();
211
212 if (Off2 < Off1) {
213 std::swap(FirstOp0, SecondOp0);
214 std::swap(Off1, Off2);
215 }
216
217 Register StartReg = FirstOp0.getReg();
218 Register NextReg = SecondOp0.getReg();
219
220 if (StartReg == RISCV::X0 || NextReg == RISCV::X0)
221 return false;
222
223 // If the base reg gets overwritten by one of the loads then bail out.
224 if (Opc == RISCV::LW && (StartReg == Base1 || NextReg == Base1))
225 return false;
226
227 if (!isShiftedUInt<5, 2>(Off1) || (Off2 - Off1 != 4))
228 return false;
229
230 if (NextReg != StartReg + 1)
231 return false;
232
233 unsigned XqciOpc = (Opc == RISCV::LW) ? RISCV::QC_LWMI : RISCV::QC_SWMI;
234
235 auto StartRegState = (Opc == RISCV::LW) ? RegState::Define
236 : getKillRegState(FirstOp0.isKill());
237 auto NextRegState =
238 (Opc == RISCV::LW)
240 : (RegState::Implicit | getKillRegState(SecondOp0.isKill()));
241
242 DebugLoc DL =
243 First->getDebugLoc() ? First->getDebugLoc() : Second->getDebugLoc();
244 MachineInstrBuilder MIB = BuildMI(*MF, DL, TII->get(XqciOpc));
245 MIB.addReg(StartReg, StartRegState)
246 .addReg(Base1, getKillRegState(FirstOp1.isKill() || SecondOp1.isKill()))
247 .addImm(2)
248 .addImm(Off1)
249 .cloneMergedMemRefs({&*First, &*Second})
250 .addReg(NextReg, NextRegState);
251
252 First->getParent()->insert(First, MIB);
253 First->removeFromParent();
254 Second->removeFromParent();
255
256 return true;
257}
258
259bool RISCVLoadStoreOpt::tryConvertToMIPSLdStPair(
260 MachineFunction *MF, MachineBasicBlock::iterator First,
262 // Try converting to SWP/LWP/LDP/SDP.
263 // SWP/LWP requires 8-byte alignment whereas LDP/SDP needs 16-byte alignment.
264 unsigned PairOpc;
265 Align RequiredAlignment;
266 switch (First->getOpcode()) {
267 default:
268 llvm_unreachable("Unsupported load/store instruction for pairing");
269 case RISCV::SW:
270 PairOpc = RISCV::MIPS_SWP;
271 RequiredAlignment = Align(8);
272 break;
273 case RISCV::LW:
274 PairOpc = RISCV::MIPS_LWP;
275 RequiredAlignment = Align(8);
276 break;
277 case RISCV::SD:
278 PairOpc = RISCV::MIPS_SDP;
279 RequiredAlignment = Align(16);
280 break;
281 case RISCV::LD:
282 PairOpc = RISCV::MIPS_LDP;
283 RequiredAlignment = Align(16);
284 break;
285 }
286
287 const MachineMemOperand *MMO = *First->memoperands_begin();
288 Align MMOAlign = MMO->getAlign();
289
290 if (MMOAlign < RequiredAlignment)
291 return false;
292
293 int64_t Offset = First->getOperand(2).getImm();
294 if (!isUInt<7>(Offset))
295 return false;
296
297 MachineInstrBuilder MIB = BuildMI(
298 *MF, First->getDebugLoc() ? First->getDebugLoc() : Second->getDebugLoc(),
299 TII->get(PairOpc));
300 MIB.add(First->getOperand(0))
301 .add(Second->getOperand(0))
302 .add(First->getOperand(1))
303 .add(First->getOperand(2))
304 .cloneMergedMemRefs({&*First, &*Second});
305
306 First->getParent()->insert(First, MIB);
307
308 First->removeFromParent();
309 Second->removeFromParent();
310
311 return true;
312}
313
314// Merge two adjacent load/store instructions into a paired instruction.
315// This function calls the vendor specific implementation that seelects the
316// appropriate paired opcode, verifies that the memory operand is properly
317// aligned, and checks that the offset is valid. If all conditions are met, it
318// builds and inserts the paired instruction.
319bool RISCVLoadStoreOpt::tryConvertToLdStPair(
321 MachineFunction *MF = First->getMF();
322 const RISCVSubtarget &STI = MF->getSubtarget<RISCVSubtarget>();
323
324 // Try converting to QC_LWMI/QC_SWMI if the XQCILSM extension is enabled.
325 if (!STI.is64Bit() && STI.hasVendorXqcilsm())
326 return tryConvertToXqcilsmLdStPair(MF, First, Second);
327
328 // Else try to convert them into MIPS Paired Loads/Stores.
329 return tryConvertToMIPSLdStPair(MF, First, Second);
330}
331
332static bool mayAlias(MachineInstr &MIa,
334 AliasAnalysis *AA) {
335 for (MachineInstr *MIb : MemInsns)
336 if (MIa.mayAlias(AA, *MIb, /*UseTBAA*/ false))
337 return true;
338
339 return false;
340}
341
342// Scan the instructions looking for a load/store that can be combined with the
343// current instruction into a wider equivalent or a load/store pair.
344// TODO: Extend pairing logic to consider reordering both instructions
345// to a safe "middle" position rather than only merging forward/backward.
346// This requires more sophisticated checks for aliasing, register
347// liveness, and potential scheduling hazards.
349RISCVLoadStoreOpt::findMatchingInsn(MachineBasicBlock::iterator I,
350 bool &MergeForward) {
351 MachineBasicBlock::iterator E = I->getParent()->end();
353 MachineInstr &FirstMI = *I;
354 MBBI = next_nodbg(MBBI, E);
355
356 bool MayLoad = FirstMI.mayLoad();
357 Register Reg = FirstMI.getOperand(0).getReg();
358 Register BaseReg = FirstMI.getOperand(1).getReg();
359 int64_t Offset = FirstMI.getOperand(2).getImm();
360 int64_t OffsetStride = (*FirstMI.memoperands_begin())->getSize().getValue();
361
362 MergeForward = false;
363
364 // Track which register units have been modified and used between the first
365 // insn (inclusive) and the second insn.
366 ModifiedRegUnits.clear();
367 UsedRegUnits.clear();
368
369 // Remember any instructions that read/write memory between FirstMI and MI.
370 SmallVector<MachineInstr *, 4> MemInsns;
371
372 for (unsigned Count = 0; MBBI != E && Count < LdStLimit;
373 MBBI = next_nodbg(MBBI, E)) {
374 MachineInstr &MI = *MBBI;
375
376 // Don't count transient instructions towards the search limit since there
377 // may be different numbers of them if e.g. debug information is present.
378 if (!MI.isTransient())
379 ++Count;
380
381 if (MI.getOpcode() == FirstMI.getOpcode() &&
382 TII->isLdStSafeToPair(MI, TRI)) {
383 Register MIBaseReg = MI.getOperand(1).getReg();
384 int64_t MIOffset = MI.getOperand(2).getImm();
385
386 if (BaseReg == MIBaseReg) {
387 if ((Offset != MIOffset + OffsetStride) &&
388 (Offset + OffsetStride != MIOffset)) {
389 LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits,
390 TRI);
391 MemInsns.push_back(&MI);
392 continue;
393 }
394
395 // If the destination register of one load is the same register or a
396 // sub/super register of the other load, bail and keep looking.
397 if (MayLoad &&
398 TRI->isSuperOrSubRegisterEq(Reg, MI.getOperand(0).getReg())) {
399 LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits,
400 TRI);
401 MemInsns.push_back(&MI);
402 continue;
403 }
404
405 // If the BaseReg has been modified, then we cannot do the optimization.
406 if (!ModifiedRegUnits.available(BaseReg))
407 return E;
408
409 // If the Rt of the second instruction was not modified or used between
410 // the two instructions and none of the instructions between the second
411 // and first alias with the second, we can combine the second into the
412 // first.
413 if (ModifiedRegUnits.available(MI.getOperand(0).getReg()) &&
414 !(MI.mayLoad() &&
415 !UsedRegUnits.available(MI.getOperand(0).getReg())) &&
416 !mayAlias(MI, MemInsns, AA)) {
417
418 MergeForward = false;
419 return MBBI;
420 }
421
422 // Likewise, if the Rt of the first instruction is not modified or used
423 // between the two instructions and none of the instructions between the
424 // first and the second alias with the first, we can combine the first
425 // into the second.
426 if (!(MayLoad &&
427 !UsedRegUnits.available(FirstMI.getOperand(0).getReg())) &&
428 !mayAlias(FirstMI, MemInsns, AA)) {
429
430 if (ModifiedRegUnits.available(FirstMI.getOperand(0).getReg())) {
431 MergeForward = true;
432 return MBBI;
433 }
434 }
435 // Unable to combine these instructions due to interference in between.
436 // Keep looking.
437 }
438 }
439
440 // If the instruction wasn't a matching load or store. Stop searching if we
441 // encounter a call instruction that might modify memory.
442 if (MI.isCall())
443 return E;
444
445 // Update modified / uses register units.
446 LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
447
448 // Otherwise, if the base register is modified, we have no match, so
449 // return early.
450 if (!ModifiedRegUnits.available(BaseReg))
451 return E;
452
453 // Update list of instructions that read/write memory.
454 if (MI.mayLoadOrStore())
455 MemInsns.push_back(&MI);
456 }
457 return E;
458}
459
461RISCVLoadStoreOpt::mergePairedInsns(MachineBasicBlock::iterator I,
463 bool MergeForward) {
464 MachineBasicBlock::iterator E = I->getParent()->end();
466 // If NextI is the second of the two instructions to be merged, we need
467 // to skip one further. Either way we merge will invalidate the iterator,
468 // and we don't need to scan the new instruction, as it's a pairwise
469 // instruction, which we're not considering for further action anyway.
470 if (NextI == Paired)
471 NextI = next_nodbg(NextI, E);
472
473 // Insert our new paired instruction after whichever of the paired
474 // instructions MergeForward indicates.
475 MachineBasicBlock::iterator InsertionPoint = MergeForward ? Paired : I;
476 MachineBasicBlock::iterator DeletionPoint = MergeForward ? I : Paired;
477 int Offset = I->getOperand(2).getImm();
478 int PairedOffset = Paired->getOperand(2).getImm();
479 bool InsertAfter = (Offset < PairedOffset) ^ MergeForward;
480
481 if (!MergeForward)
482 Paired->getOperand(1).setIsKill(false);
483
484 // Kill flags may become invalid when moving stores for pairing.
485 if (I->getOperand(0).isUse()) {
486 if (!MergeForward) {
487 // Check if the Paired store's source register has a kill flag and clear
488 // it only if there are intermediate uses between I and Paired.
489 MachineOperand &PairedRegOp = Paired->getOperand(0);
490 if (PairedRegOp.isKill()) {
491 for (auto It = std::next(I); It != Paired; ++It) {
492 if (It->readsRegister(PairedRegOp.getReg(), TRI)) {
493 PairedRegOp.setIsKill(false);
494 break;
495 }
496 }
497 }
498 } else {
499 // Clear kill flags of the first store's register in the forward
500 // direction.
501 Register Reg = I->getOperand(0).getReg();
502 for (MachineInstr &MI : make_range(std::next(I), std::next(Paired)))
503 MI.clearRegisterKills(Reg, TRI);
504 }
505 }
506
507 MachineInstr *ToInsert = DeletionPoint->removeFromParent();
508 MachineBasicBlock &MBB = *InsertionPoint->getParent();
510
511 if (!InsertAfter) {
512 First = MBB.insert(InsertionPoint, ToInsert);
513 Second = InsertionPoint;
514 } else {
515 Second = MBB.insertAfter(InsertionPoint, ToInsert);
516 First = InsertionPoint;
517 }
518
519 if (tryConvertToLdStPair(First, Second)) {
520 LLVM_DEBUG(dbgs() << "Pairing load/store:\n ");
521 LLVM_DEBUG(prev_nodbg(NextI, MBB.begin())->print(dbgs()));
522 }
523
524 return NextI;
525}
526
527//===----------------------------------------------------------------------===//
528// Post reg-alloc zilsd pass implementation
529//===----------------------------------------------------------------------===//
530
531bool RISCVLoadStoreOpt::isValidZilsdRegPair(Register First, Register Second) {
532 // Special case: First register can not be zero unless both registers are
533 // zeros.
534 // Spec says: LD instructions with destination x0 are processed as any other
535 // load, but the result is discarded entirely and x1 is not written. If using
536 // x0 as src of SD, the entire 64-bit operand is zero — i.e., register x1 is
537 // not accessed.
538 if (First == RISCV::X0)
539 return Second == RISCV::X0;
540
541 // Check if registers form a valid even/odd pair for Zilsd
542 unsigned FirstNum = TRI->getEncodingValue(First);
543 unsigned SecondNum = TRI->getEncodingValue(Second);
544
545 // Must be consecutive and first must be even
546 return (FirstNum % 2 == 0) && (SecondNum == FirstNum + 1);
547}
548
549void RISCVLoadStoreOpt::splitLdSdIntoTwo(MachineBasicBlock &MBB,
551 bool IsLoad) {
552 MachineInstr *MI = &*MBBI;
553 DebugLoc DL = MI->getDebugLoc();
554
555 const MachineOperand &FirstOp = MI->getOperand(0);
556 const MachineOperand &SecondOp = MI->getOperand(1);
557 const MachineOperand &BaseOp = MI->getOperand(2);
558 Register FirstReg = FirstOp.getReg();
559 Register SecondReg = SecondOp.getReg();
560 Register BaseReg = BaseOp.getReg();
561
562 // Handle both immediate and symbolic operands for offset
563 const MachineOperand &OffsetOp = MI->getOperand(3);
564 int BaseOffset;
565 if (OffsetOp.isImm())
566 BaseOffset = OffsetOp.getImm();
567 else
568 // For symbolic operands, extract the embedded offset
569 BaseOffset = OffsetOp.getOffset();
570
571 unsigned Opc = IsLoad ? RISCV::LW : RISCV::SW;
572 MachineInstrBuilder MIB1, MIB2;
573
574 // Create two separate instructions
575 if (IsLoad) {
576 // It's possible that first register is same as base register, when we split
577 // it becomes incorrect because base register is overwritten, e.g.
578 // X10, X13 = PseudoLD_RV32_OPT killed X10, 0
579 // =>
580 // X10 = LW X10, 0
581 // X13 = LW killed X10, 4
582 // we can just switch the order to resolve that:
583 // X13 = LW X10, 4
584 // X10 = LW killed X10, 0
585 if (FirstReg == BaseReg) {
586 MIB2 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
587 .addReg(SecondReg,
589 .addReg(BaseReg);
590 MIB1 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
591 .addReg(FirstReg,
593 .addReg(BaseReg, getKillRegState(BaseOp.isKill()));
594
595 } else {
596 MIB1 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
597 .addReg(FirstReg,
599 .addReg(BaseReg);
600
601 MIB2 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
602 .addReg(SecondReg,
604 .addReg(BaseReg, getKillRegState(BaseOp.isKill()));
605 }
606
607 ++NumLD2LW;
608 LLVM_DEBUG(dbgs() << "Split LD back to two LW instructions\n");
609 } else {
610 assert(
611 FirstReg != SecondReg &&
612 "First register and second register is impossible to be same register");
613 MIB1 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
614 .addReg(FirstReg, getKillRegState(FirstOp.isKill()))
615 .addReg(BaseReg);
616
617 MIB2 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
618 .addReg(SecondReg, getKillRegState(SecondOp.isKill()))
619 .addReg(BaseReg, getKillRegState(BaseOp.isKill()));
620
621 ++NumSD2SW;
622 LLVM_DEBUG(dbgs() << "Split SD back to two SW instructions\n");
623 }
624
625 // Add offset operands - preserve symbolic references
626 MIB1.add(OffsetOp);
627 if (OffsetOp.isImm())
628 MIB2.addImm(BaseOffset + 4);
629 else if (OffsetOp.isGlobal())
630 MIB2.addGlobalAddress(OffsetOp.getGlobal(), BaseOffset + 4,
631 OffsetOp.getTargetFlags());
632 else if (OffsetOp.isCPI())
633 MIB2.addConstantPoolIndex(OffsetOp.getIndex(), BaseOffset + 4,
634 OffsetOp.getTargetFlags());
635 else if (OffsetOp.isBlockAddress())
636 MIB2.addBlockAddress(OffsetOp.getBlockAddress(), BaseOffset + 4,
637 OffsetOp.getTargetFlags());
638
639 // Copy memory operands if the original instruction had them
640 // FIXME: This is overly conservative; the new instruction accesses 4 bytes,
641 // not 8.
642 MIB1.cloneMemRefs(*MI);
643 MIB2.cloneMemRefs(*MI);
644
645 // Remove the original paired instruction and update iterator
646 MBBI = MBB.erase(MBBI);
647}
648
649bool RISCVLoadStoreOpt::fixInvalidRegPairOp(MachineBasicBlock &MBB,
651 MachineInstr *MI = &*MBBI;
652 unsigned Opcode = MI->getOpcode();
653
654 // Check if this is a Zilsd pseudo that needs fixing
655 if (Opcode != RISCV::PseudoLD_RV32_OPT && Opcode != RISCV::PseudoSD_RV32_OPT)
656 return false;
657
658 bool IsLoad = Opcode == RISCV::PseudoLD_RV32_OPT;
659
660 const MachineOperand &FirstOp = MI->getOperand(0);
661 const MachineOperand &SecondOp = MI->getOperand(1);
662 Register FirstReg = FirstOp.getReg();
663 Register SecondReg = SecondOp.getReg();
664
665 if (!isValidZilsdRegPair(FirstReg, SecondReg)) {
666 // Need to split back into two instructions
667 splitLdSdIntoTwo(MBB, MBBI, IsLoad);
668 return true;
669 }
670
671 // Registers are valid, convert to real LD/SD instruction
672 const MachineOperand &BaseOp = MI->getOperand(2);
673 Register BaseReg = BaseOp.getReg();
674 DebugLoc DL = MI->getDebugLoc();
675 // Handle both immediate and symbolic operands for offset
676 const MachineOperand &OffsetOp = MI->getOperand(3);
677
678 unsigned RealOpc = IsLoad ? RISCV::LD_RV32 : RISCV::SD_RV32;
679
680 // Create register pair from the two individual registers
681 unsigned RegPair = TRI->getMatchingSuperReg(FirstReg, RISCV::sub_gpr_even,
682 &RISCV::GPRPairRegClass);
683 // Create the real LD/SD instruction with register pair
684 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(RealOpc));
685
686 if (IsLoad) {
687 // For LD, the register pair is the destination
688 MIB.addReg(RegPair, RegState::Define | getDeadRegState(FirstOp.isDead() &&
689 SecondOp.isDead()));
690 } else {
691 // For SD, the register pair is the source
692 MIB.addReg(RegPair, getKillRegState(FirstOp.isKill() && SecondOp.isKill()));
693 }
694
695 MIB.addReg(BaseReg, getKillRegState(BaseOp.isKill()))
696 .add(OffsetOp)
697 .cloneMemRefs(*MI);
698
699 LLVM_DEBUG(dbgs() << "Converted pseudo to real instruction: " << *MIB
700 << "\n");
701
702 // Remove the pseudo instruction and update iterator
703 MBBI = MBB.erase(MBBI);
704
705 return true;
706}
707
708// Returns an instance of the Load / Store Optimization pass.
710 return new RISCVLoadStoreOpt();
711}
unsigned const MachineRegisterInfo * MRI
static bool mayAlias(MachineInstr &MIa, SmallVectorImpl< MachineInstr * > &MemInsns, AliasAnalysis *AA)
static cl::opt< unsigned > LdStLimit("aarch64-load-store-scan-limit", cl::init(20), cl::Hidden)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
if(PassOpts->AAPipeline)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
#define RISCV_LOAD_STORE_OPT_NAME
static cl::opt< unsigned > LdStLimit("riscv-load-store-scan-limit", cl::init(128), cl::Hidden)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:114
AnalysisUsage & addRequired()
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
static void accumulateUsedDefed(const MachineInstr &MI, LiveRegUnits &ModifiedRegUnits, LiveRegUnits &UsedRegUnits, const TargetRegisterInfo *TRI)
For a machine instruction MI, adds all register units used in UsedRegUnits and defined or clobbered i...
bool available(MCRegister Reg) const
Returns true if no part of physical register Reg is live.
void clear()
Clears the set.
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator insertAfter(iterator I, MachineInstr *MI)
Insert MI into the instruction list after I.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const MachineInstrBuilder & cloneMergedMemRefs(ArrayRef< const MachineInstr * > OtherMIs) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addBlockAddress(const BlockAddress *BA, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
LLVM_ABI bool mayAlias(BatchAAResults *AA, const MachineInstr &Other, bool UseTBAA) const
Returns true if this instruction's memory access aliases the memory access of Other.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
int64_t getImm() const
void setIsKill(bool Val=true)
Register getReg() const
getReg - Returns the register number.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
Definition Attributor.h:165
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
initializer< Ty > init(const Ty &Val)
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
Definition SFrame.h:77
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
FunctionPass * createRISCVLoadStoreOptPass()
@ Offset
Definition DWP.cpp:532
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
unsigned getDeadRegState(bool B)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:189
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
unsigned getKillRegState(bool B)
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
IterT prev_nodbg(IterT It, IterT Begin, bool SkipPseudoOp=true)
Decrement It, then continue decrementing it while it points to a debug instruction.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
Definition MathExtras.h:198
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:872