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 if (!isShiftedUInt<5, 2>(Off1) || (Off2 - Off1 != 4))
218 return false;
219
220 Register StartReg = FirstOp0.getReg();
221 Register NextReg = SecondOp0.getReg();
222
223 unsigned XqciOpc;
224 unsigned StartRegState;
225 unsigned NextRegState = 0;
226 bool AddNextReg = true;
227
228 if (Opc == RISCV::LW) {
229
230 if (StartReg == RISCV::X0)
231 return false;
232
233 // If the base reg gets overwritten by one of the loads bail out.
234 if (StartReg == Base1 || NextReg == Base1)
235 return false;
236
237 // The registers need to be consecutive.
238 if (NextReg != StartReg + 1)
239 return false;
240
241 XqciOpc = RISCV::QC_LWMI;
242 StartRegState = static_cast<unsigned>(RegState::Define);
243 NextRegState = static_cast<unsigned>(RegState::ImplicitDefine);
244 } else {
245 assert(Opc == RISCV::SW && "Expected a SW instruction");
246 if (StartReg == NextReg) {
247 XqciOpc = RISCV::QC_SETWMI;
248 StartRegState = getKillRegState(FirstOp0.isKill() || SecondOp0.isKill());
249 AddNextReg = false;
250 } else if (NextReg == StartReg + 1) {
251 XqciOpc = RISCV::QC_SWMI;
252 StartRegState = getKillRegState(FirstOp0.isKill());
253 NextRegState = RegState::Implicit | getKillRegState(SecondOp0.isKill());
254 } else {
255 return false;
256 }
257 }
258
259 DebugLoc DL =
260 First->getDebugLoc() ? First->getDebugLoc() : Second->getDebugLoc();
261 MachineInstrBuilder MIB = BuildMI(*MF, DL, TII->get(XqciOpc));
262 MIB.addReg(StartReg, StartRegState)
263 .addReg(Base1, getKillRegState(FirstOp1.isKill() || SecondOp1.isKill()))
264 .addImm(2)
265 .addImm(Off1)
266 .cloneMergedMemRefs({&*First, &*Second});
267
268 if (AddNextReg)
269 MIB.addReg(NextReg, NextRegState);
270
271 First->getParent()->insert(First, MIB);
272 First->removeFromParent();
273 Second->removeFromParent();
274
275 return true;
276}
277
278bool RISCVLoadStoreOpt::tryConvertToMIPSLdStPair(
279 MachineFunction *MF, MachineBasicBlock::iterator First,
281 // Try converting to SWP/LWP/LDP/SDP.
282 // SWP/LWP requires 8-byte alignment whereas LDP/SDP needs 16-byte alignment.
283 unsigned PairOpc;
284 Align RequiredAlignment;
285 switch (First->getOpcode()) {
286 default:
287 llvm_unreachable("Unsupported load/store instruction for pairing");
288 case RISCV::SW:
289 PairOpc = RISCV::MIPS_SWP;
290 RequiredAlignment = Align(8);
291 break;
292 case RISCV::LW:
293 PairOpc = RISCV::MIPS_LWP;
294 RequiredAlignment = Align(8);
295 break;
296 case RISCV::SD:
297 PairOpc = RISCV::MIPS_SDP;
298 RequiredAlignment = Align(16);
299 break;
300 case RISCV::LD:
301 PairOpc = RISCV::MIPS_LDP;
302 RequiredAlignment = Align(16);
303 break;
304 }
305
306 const MachineMemOperand *MMO = *First->memoperands_begin();
307 Align MMOAlign = MMO->getAlign();
308
309 if (MMOAlign < RequiredAlignment)
310 return false;
311
312 int64_t Offset = First->getOperand(2).getImm();
313 if (!isUInt<7>(Offset))
314 return false;
315
316 MachineInstrBuilder MIB = BuildMI(
317 *MF, First->getDebugLoc() ? First->getDebugLoc() : Second->getDebugLoc(),
318 TII->get(PairOpc));
319 MIB.add(First->getOperand(0))
320 .add(Second->getOperand(0))
321 .add(First->getOperand(1))
322 .add(First->getOperand(2))
323 .cloneMergedMemRefs({&*First, &*Second});
324
325 First->getParent()->insert(First, MIB);
326
327 First->removeFromParent();
328 Second->removeFromParent();
329
330 return true;
331}
332
333// Merge two adjacent load/store instructions into a paired instruction.
334// This function calls the vendor specific implementation that seelects the
335// appropriate paired opcode, verifies that the memory operand is properly
336// aligned, and checks that the offset is valid. If all conditions are met, it
337// builds and inserts the paired instruction.
338bool RISCVLoadStoreOpt::tryConvertToLdStPair(
340 MachineFunction *MF = First->getMF();
341 const RISCVSubtarget &STI = MF->getSubtarget<RISCVSubtarget>();
342
343 // Try converting to QC_LWMI/QC_SWMI if the XQCILSM extension is enabled.
344 if (!STI.is64Bit() && STI.hasVendorXqcilsm())
345 return tryConvertToXqcilsmLdStPair(MF, First, Second);
346
347 // Else try to convert them into MIPS Paired Loads/Stores.
348 return tryConvertToMIPSLdStPair(MF, First, Second);
349}
350
351static bool mayAlias(MachineInstr &MIa,
353 AliasAnalysis *AA) {
354 for (MachineInstr *MIb : MemInsns)
355 if (MIa.mayAlias(AA, *MIb, /*UseTBAA*/ false))
356 return true;
357
358 return false;
359}
360
361// Scan the instructions looking for a load/store that can be combined with the
362// current instruction into a wider equivalent or a load/store pair.
363// TODO: Extend pairing logic to consider reordering both instructions
364// to a safe "middle" position rather than only merging forward/backward.
365// This requires more sophisticated checks for aliasing, register
366// liveness, and potential scheduling hazards.
368RISCVLoadStoreOpt::findMatchingInsn(MachineBasicBlock::iterator I,
369 bool &MergeForward) {
370 MachineBasicBlock::iterator E = I->getParent()->end();
372 MachineInstr &FirstMI = *I;
373 MBBI = next_nodbg(MBBI, E);
374
375 bool MayLoad = FirstMI.mayLoad();
376 Register Reg = FirstMI.getOperand(0).getReg();
377 Register BaseReg = FirstMI.getOperand(1).getReg();
378 int64_t Offset = FirstMI.getOperand(2).getImm();
379 int64_t OffsetStride = (*FirstMI.memoperands_begin())->getSize().getValue();
380
381 MergeForward = false;
382
383 // Track which register units have been modified and used between the first
384 // insn (inclusive) and the second insn.
385 ModifiedRegUnits.clear();
386 UsedRegUnits.clear();
387
388 // Remember any instructions that read/write memory between FirstMI and MI.
389 SmallVector<MachineInstr *, 4> MemInsns;
390
391 for (unsigned Count = 0; MBBI != E && Count < LdStLimit;
392 MBBI = next_nodbg(MBBI, E)) {
393 MachineInstr &MI = *MBBI;
394
395 // Don't count transient instructions towards the search limit since there
396 // may be different numbers of them if e.g. debug information is present.
397 if (!MI.isTransient())
398 ++Count;
399
400 if (MI.getOpcode() == FirstMI.getOpcode() &&
401 TII->isLdStSafeToPair(MI, TRI)) {
402 Register MIBaseReg = MI.getOperand(1).getReg();
403 int64_t MIOffset = MI.getOperand(2).getImm();
404
405 if (BaseReg == MIBaseReg) {
406 if ((Offset != MIOffset + OffsetStride) &&
407 (Offset + OffsetStride != MIOffset)) {
408 LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits,
409 TRI);
410 MemInsns.push_back(&MI);
411 continue;
412 }
413
414 // If the destination register of one load is the same register or a
415 // sub/super register of the other load, bail and keep looking.
416 if (MayLoad &&
417 TRI->isSuperOrSubRegisterEq(Reg, MI.getOperand(0).getReg())) {
418 LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits,
419 TRI);
420 MemInsns.push_back(&MI);
421 continue;
422 }
423
424 // If the BaseReg has been modified, then we cannot do the optimization.
425 if (!ModifiedRegUnits.available(BaseReg))
426 return E;
427
428 // If the Rt of the second instruction was not modified or used between
429 // the two instructions and none of the instructions between the second
430 // and first alias with the second, we can combine the second into the
431 // first.
432 if (ModifiedRegUnits.available(MI.getOperand(0).getReg()) &&
433 !(MI.mayLoad() &&
434 !UsedRegUnits.available(MI.getOperand(0).getReg())) &&
435 !mayAlias(MI, MemInsns, AA)) {
436
437 MergeForward = false;
438 return MBBI;
439 }
440
441 // Likewise, if the Rt of the first instruction is not modified or used
442 // between the two instructions and none of the instructions between the
443 // first and the second alias with the first, we can combine the first
444 // into the second.
445 if (!(MayLoad &&
446 !UsedRegUnits.available(FirstMI.getOperand(0).getReg())) &&
447 !mayAlias(FirstMI, MemInsns, AA)) {
448
449 if (ModifiedRegUnits.available(FirstMI.getOperand(0).getReg())) {
450 MergeForward = true;
451 return MBBI;
452 }
453 }
454 // Unable to combine these instructions due to interference in between.
455 // Keep looking.
456 }
457 }
458
459 // If the instruction wasn't a matching load or store. Stop searching if we
460 // encounter a call instruction that might modify memory.
461 if (MI.isCall())
462 return E;
463
464 // Update modified / uses register units.
465 LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
466
467 // Otherwise, if the base register is modified, we have no match, so
468 // return early.
469 if (!ModifiedRegUnits.available(BaseReg))
470 return E;
471
472 // Update list of instructions that read/write memory.
473 if (MI.mayLoadOrStore())
474 MemInsns.push_back(&MI);
475 }
476 return E;
477}
478
480RISCVLoadStoreOpt::mergePairedInsns(MachineBasicBlock::iterator I,
482 bool MergeForward) {
483 MachineBasicBlock::iterator E = I->getParent()->end();
485 // If NextI is the second of the two instructions to be merged, we need
486 // to skip one further. Either way we merge will invalidate the iterator,
487 // and we don't need to scan the new instruction, as it's a pairwise
488 // instruction, which we're not considering for further action anyway.
489 if (NextI == Paired)
490 NextI = next_nodbg(NextI, E);
491
492 // Insert our new paired instruction after whichever of the paired
493 // instructions MergeForward indicates.
494 MachineBasicBlock::iterator InsertionPoint = MergeForward ? Paired : I;
495 MachineBasicBlock::iterator DeletionPoint = MergeForward ? I : Paired;
496 int Offset = I->getOperand(2).getImm();
497 int PairedOffset = Paired->getOperand(2).getImm();
498 bool InsertAfter = (Offset < PairedOffset) ^ MergeForward;
499
500 if (!MergeForward)
501 Paired->getOperand(1).setIsKill(false);
502
503 // Kill flags may become invalid when moving stores for pairing.
504 if (I->getOperand(0).isUse()) {
505 if (!MergeForward) {
506 // Check if the Paired store's source register has a kill flag and clear
507 // it only if there are intermediate uses between I and Paired.
508 MachineOperand &PairedRegOp = Paired->getOperand(0);
509 if (PairedRegOp.isKill()) {
510 for (auto It = std::next(I); It != Paired; ++It) {
511 if (It->readsRegister(PairedRegOp.getReg(), TRI)) {
512 PairedRegOp.setIsKill(false);
513 break;
514 }
515 }
516 }
517 } else {
518 // Clear kill flags of the first store's register in the forward
519 // direction.
520 Register Reg = I->getOperand(0).getReg();
521 for (MachineInstr &MI : make_range(std::next(I), std::next(Paired)))
522 MI.clearRegisterKills(Reg, TRI);
523 }
524 }
525
526 MachineInstr *ToInsert = DeletionPoint->removeFromParent();
527 MachineBasicBlock &MBB = *InsertionPoint->getParent();
529
530 if (!InsertAfter) {
531 First = MBB.insert(InsertionPoint, ToInsert);
532 Second = InsertionPoint;
533 } else {
534 Second = MBB.insertAfter(InsertionPoint, ToInsert);
535 First = InsertionPoint;
536 }
537
538 if (tryConvertToLdStPair(First, Second)) {
539 LLVM_DEBUG(dbgs() << "Pairing load/store:\n ");
540 LLVM_DEBUG(prev_nodbg(NextI, MBB.begin())->print(dbgs()));
541 }
542
543 return NextI;
544}
545
546//===----------------------------------------------------------------------===//
547// Post reg-alloc zilsd pass implementation
548//===----------------------------------------------------------------------===//
549
550bool RISCVLoadStoreOpt::isValidZilsdRegPair(Register First, Register Second) {
551 // Special case: First register can not be zero unless both registers are
552 // zeros.
553 // Spec says: LD instructions with destination x0 are processed as any other
554 // load, but the result is discarded entirely and x1 is not written. If using
555 // x0 as src of SD, the entire 64-bit operand is zero — i.e., register x1 is
556 // not accessed.
557 if (First == RISCV::X0)
558 return Second == RISCV::X0;
559
560 // Check if registers form a valid even/odd pair for Zilsd
561 unsigned FirstNum = TRI->getEncodingValue(First);
562 unsigned SecondNum = TRI->getEncodingValue(Second);
563
564 // Must be consecutive and first must be even
565 return (FirstNum % 2 == 0) && (SecondNum == FirstNum + 1);
566}
567
568void RISCVLoadStoreOpt::splitLdSdIntoTwo(MachineBasicBlock &MBB,
570 bool IsLoad) {
571 MachineInstr *MI = &*MBBI;
572 DebugLoc DL = MI->getDebugLoc();
573
574 const MachineOperand &FirstOp = MI->getOperand(0);
575 const MachineOperand &SecondOp = MI->getOperand(1);
576 const MachineOperand &BaseOp = MI->getOperand(2);
577 Register FirstReg = FirstOp.getReg();
578 Register SecondReg = SecondOp.getReg();
579 Register BaseReg = BaseOp.getReg();
580
581 // Handle both immediate and symbolic operands for offset
582 const MachineOperand &OffsetOp = MI->getOperand(3);
583 int BaseOffset;
584 if (OffsetOp.isImm())
585 BaseOffset = OffsetOp.getImm();
586 else
587 // For symbolic operands, extract the embedded offset
588 BaseOffset = OffsetOp.getOffset();
589
590 unsigned Opc = IsLoad ? RISCV::LW : RISCV::SW;
591 MachineInstrBuilder MIB1, MIB2;
592
593 // Create two separate instructions
594 if (IsLoad) {
595 // It's possible that first register is same as base register, when we split
596 // it becomes incorrect because base register is overwritten, e.g.
597 // X10, X13 = PseudoLD_RV32_OPT killed X10, 0
598 // =>
599 // X10 = LW X10, 0
600 // X13 = LW killed X10, 4
601 // we can just switch the order to resolve that:
602 // X13 = LW X10, 4
603 // X10 = LW killed X10, 0
604 if (FirstReg == BaseReg) {
605 MIB2 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
606 .addReg(SecondReg,
608 .addReg(BaseReg);
609 MIB1 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
610 .addReg(FirstReg,
612 .addReg(BaseReg, getKillRegState(BaseOp.isKill()));
613
614 } else {
615 MIB1 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
616 .addReg(FirstReg,
618 .addReg(BaseReg);
619
620 MIB2 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
621 .addReg(SecondReg,
623 .addReg(BaseReg, getKillRegState(BaseOp.isKill()));
624 }
625
626 ++NumLD2LW;
627 LLVM_DEBUG(dbgs() << "Split LD back to two LW instructions\n");
628 } else {
629 assert(
630 FirstReg != SecondReg &&
631 "First register and second register is impossible to be same register");
632 MIB1 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
633 .addReg(FirstReg, getKillRegState(FirstOp.isKill()))
634 .addReg(BaseReg);
635
636 MIB2 = BuildMI(MBB, MBBI, DL, TII->get(Opc))
637 .addReg(SecondReg, getKillRegState(SecondOp.isKill()))
638 .addReg(BaseReg, getKillRegState(BaseOp.isKill()));
639
640 ++NumSD2SW;
641 LLVM_DEBUG(dbgs() << "Split SD back to two SW instructions\n");
642 }
643
644 // Add offset operands - preserve symbolic references
645 MIB1.add(OffsetOp);
646 if (OffsetOp.isImm())
647 MIB2.addImm(BaseOffset + 4);
648 else if (OffsetOp.isGlobal())
649 MIB2.addGlobalAddress(OffsetOp.getGlobal(), BaseOffset + 4,
650 OffsetOp.getTargetFlags());
651 else if (OffsetOp.isCPI())
652 MIB2.addConstantPoolIndex(OffsetOp.getIndex(), BaseOffset + 4,
653 OffsetOp.getTargetFlags());
654 else if (OffsetOp.isBlockAddress())
655 MIB2.addBlockAddress(OffsetOp.getBlockAddress(), BaseOffset + 4,
656 OffsetOp.getTargetFlags());
657
658 // Copy memory operands if the original instruction had them
659 // FIXME: This is overly conservative; the new instruction accesses 4 bytes,
660 // not 8.
661 MIB1.cloneMemRefs(*MI);
662 MIB2.cloneMemRefs(*MI);
663
664 // Remove the original paired instruction and update iterator
665 MBBI = MBB.erase(MBBI);
666}
667
668bool RISCVLoadStoreOpt::fixInvalidRegPairOp(MachineBasicBlock &MBB,
670 MachineInstr *MI = &*MBBI;
671 unsigned Opcode = MI->getOpcode();
672
673 // Check if this is a Zilsd pseudo that needs fixing
674 if (Opcode != RISCV::PseudoLD_RV32_OPT && Opcode != RISCV::PseudoSD_RV32_OPT)
675 return false;
676
677 bool IsLoad = Opcode == RISCV::PseudoLD_RV32_OPT;
678
679 const MachineOperand &FirstOp = MI->getOperand(0);
680 const MachineOperand &SecondOp = MI->getOperand(1);
681 Register FirstReg = FirstOp.getReg();
682 Register SecondReg = SecondOp.getReg();
683
684 if (!isValidZilsdRegPair(FirstReg, SecondReg)) {
685 // Need to split back into two instructions
686 splitLdSdIntoTwo(MBB, MBBI, IsLoad);
687 return true;
688 }
689
690 // Registers are valid, convert to real LD/SD instruction
691 const MachineOperand &BaseOp = MI->getOperand(2);
692 Register BaseReg = BaseOp.getReg();
693 DebugLoc DL = MI->getDebugLoc();
694 // Handle both immediate and symbolic operands for offset
695 const MachineOperand &OffsetOp = MI->getOperand(3);
696
697 unsigned RealOpc = IsLoad ? RISCV::LD_RV32 : RISCV::SD_RV32;
698
699 // Create register pair from the two individual registers
700 unsigned RegPair = TRI->getMatchingSuperReg(FirstReg, RISCV::sub_gpr_even,
701 &RISCV::GPRPairRegClass);
702 // Create the real LD/SD instruction with register pair
703 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(RealOpc));
704
705 if (IsLoad) {
706 // For LD, the register pair is the destination
707 MIB.addReg(RegPair, RegState::Define | getDeadRegState(FirstOp.isDead() &&
708 SecondOp.isDead()));
709 } else {
710 // For SD, the register pair is the source
711 MIB.addReg(RegPair, getKillRegState(FirstOp.isKill() && SecondOp.isKill()));
712 }
713
714 MIB.addReg(BaseReg, getKillRegState(BaseOp.isKill()))
715 .add(OffsetOp)
716 .cloneMemRefs(*MI);
717
718 LLVM_DEBUG(dbgs() << "Converted pseudo to real instruction: " << *MIB
719 << "\n");
720
721 // Remove the pseudo instruction and update iterator
722 MBBI = MBB.erase(MBBI);
723
724 return true;
725}
726
727// Returns an instance of the Load / Store Optimization pass.
729 return new RISCVLoadStoreOpt();
730}
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