[llvm] [PowerPC] Peephole address calculation in TOC memops (PR #76488)
Sean Fertile via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 4 12:48:47 PST 2024
================
@@ -7662,241 +7662,212 @@ static void foldADDIForLocalExecAccesses(SDNode *N, SelectionDAG *DAG) {
DAG->RemoveDeadNode(InitialADDI.getNode());
}
-void PPCDAGToDAGISel::PeepholePPC64() {
- SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end();
- bool HasAIXSmallLocalExecTLS = Subtarget->hasAIXSmallLocalExecTLS();
-
- while (Position != CurDAG->allnodes_begin()) {
- SDNode *N = &*--Position;
- // Skip dead nodes and any non-machine opcodes.
- if (N->use_empty() || !N->isMachineOpcode())
- continue;
-
- if (isVSXSwap(SDValue(N, 0)))
- reduceVSXSwap(N, CurDAG);
-
- // This optimization is performed for non-TOC-based local-exec accesses.
- if (HasAIXSmallLocalExecTLS)
- foldADDIForLocalExecAccesses(N, CurDAG);
+static bool isValidOffsetMemOp(SDNode *N, bool &IsLoad,
+ MaybeAlign &ExtraAlign) {
+ switch (N->getMachineOpcode()) {
+ default:
+ return false;
+ // Global must be word-aligned for LD, STD, LWA.
+ case PPC::LWA:
+ case PPC::LD:
+ case PPC::DFLOADf64:
+ case PPC::DFLOADf32:
+ ExtraAlign = Align(4);
+ [[fallthrough]];
+ case PPC::LBZ:
+ case PPC::LBZ8:
+ case PPC::LFD:
+ case PPC::LFS:
+ case PPC::LHA:
+ case PPC::LHA8:
+ case PPC::LHZ:
+ case PPC::LHZ8:
+ case PPC::LWZ:
+ case PPC::LWZ8:
+ IsLoad = true;
+ break;
+ case PPC::STD:
+ case PPC::DFSTOREf64:
+ case PPC::DFSTOREf32:
+ ExtraAlign = Align(4);
+ [[fallthrough]];
+ case PPC::STB:
+ case PPC::STB8:
+ case PPC::STFD:
+ case PPC::STFS:
+ case PPC::STH:
+ case PPC::STH8:
+ case PPC::STW:
+ case PPC::STW8:
+ break;
+ }
+ SDValue Base = N->getOperand(IsLoad ? 1 : 2);
+ if (!Base.isMachineOpcode())
+ return false;
+ switch (Base.getMachineOpcode()) {
+ default:
+ return false;
+ case PPC::ADDI8:
+ case PPC::ADDI:
+ case PPC::ADDIdtprelL:
+ case PPC::ADDItlsldL:
+ case PPC::ADDItocL:
+ case PPC::ADDItoc:
+ case PPC::ADDItoc8:
+ break;
+ }
+ return true;
+}
- unsigned FirstOp;
- unsigned StorageOpcode = N->getMachineOpcode();
- bool RequiresMod4Offset = false;
+static void peepholeMemOffset(SDNode *N, SelectionDAG *DAG,
+ const PPCSubtarget *Subtarget) {
+ // TODO: Enable for AIX 32-bit.
+ if (!Subtarget->isPPC64())
+ return;
- switch (StorageOpcode) {
- default: continue;
+ bool IsLoad = false;
+ MaybeAlign ExtraAlign;
+ if (!isValidOffsetMemOp(N, IsLoad, ExtraAlign))
+ return;
- case PPC::LWA:
- case PPC::LD:
- case PPC::DFLOADf64:
- case PPC::DFLOADf32:
- RequiresMod4Offset = true;
- [[fallthrough]];
- case PPC::LBZ:
- case PPC::LBZ8:
- case PPC::LFD:
- case PPC::LFS:
- case PPC::LHA:
- case PPC::LHA8:
- case PPC::LHZ:
- case PPC::LHZ8:
- case PPC::LWZ:
- case PPC::LWZ8:
- FirstOp = 0;
- break;
+ SDValue MemBase = N->getOperand(IsLoad ? 1 : 2);
+ unsigned BaseOpc = MemBase.getMachineOpcode();
+ auto *MemOffset = dyn_cast<ConstantSDNode>(N->getOperand(IsLoad ? 0 : 1));
- case PPC::STD:
- case PPC::DFSTOREf64:
- case PPC::DFSTOREf32:
- RequiresMod4Offset = true;
- [[fallthrough]];
- case PPC::STB:
- case PPC::STB8:
- case PPC::STFD:
- case PPC::STFS:
- case PPC::STH:
- case PPC::STH8:
- case PPC::STW:
- case PPC::STW8:
- FirstOp = 1;
- break;
- }
+ // Only additions with constant offsets will be folded.
+ if (!MemOffset)
+ return;
+ assert(MemBase.getNumOperands() == 2 && "Invalid base of memop with offset!");
- // If this is a load or store with a zero offset, or within the alignment,
- // we may be able to fold an add-immediate into the memory operation.
- // The check against alignment is below, as it can't occur until we check
- // the arguments to N
- if (!isa<ConstantSDNode>(N->getOperand(FirstOp)))
- continue;
+ SDValue ImmOp, RegOp;
+ // ADDItoc and ADDItoc8 ('la') puts the register at the second operand.
+ if (BaseOpc == PPC::ADDItoc || BaseOpc == PPC::ADDItoc8) {
+ ImmOp = MemBase.getOperand(0);
+ RegOp = MemBase.getOperand(1);
+ } else {
+ ImmOp = MemBase.getOperand(1);
+ RegOp = MemBase.getOperand(0);
+ }
- SDValue Base = N->getOperand(FirstOp + 1);
- if (!Base.isMachineOpcode())
- continue;
+ MaybeAlign ImmAlign;
+ if (auto *GA = dyn_cast<GlobalAddressSDNode>(ImmOp))
+ ImmAlign = GA->getGlobal()->getPointerAlignment(DAG->getDataLayout());
+ else if (auto *CP = dyn_cast<ConstantPoolSDNode>(ImmOp))
+ ImmAlign = CP->getAlign();
- unsigned Flags = 0;
- bool ReplaceFlags = true;
+ if (ImmAlign && ExtraAlign && ImmAlign.value() < ExtraAlign.value())
+ return;
- // When the feeding operation is an add-immediate of some sort,
- // determine whether we need to add relocation information to the
- // target flags on the immediate operand when we fold it into the
- // load instruction.
- //
- // For something like ADDItocL, the relocation information is
- // inferred from the opcode; when we process it in the AsmPrinter,
- // we add the necessary relocation there. A load, though, can receive
- // relocation from various flavors of ADDIxxx, so we need to carry
- // the relocation information in the target flags.
- switch (Base.getMachineOpcode()) {
- default: continue;
-
- case PPC::ADDI8:
- case PPC::ADDI:
- // In some cases (such as TLS) the relocation information
- // is already in place on the operand, so copying the operand
- // is sufficient.
- ReplaceFlags = false;
- break;
- case PPC::ADDIdtprelL:
- Flags = PPCII::MO_DTPREL_LO;
- break;
- case PPC::ADDItlsldL:
- Flags = PPCII::MO_TLSLD_LO;
- break;
- case PPC::ADDItocL:
- Flags = PPCII::MO_TOC_LO;
- break;
+ // On PPC64, the TOC base pointer is guaranteed by the ABI only to have
----------------
mandlebug wrote:
Was the early return on lines 7724-7726 added because this code is only correct on 64 bit right now, or was there some other motivation? (If I am reading the original code correctly we do not have an early return for 64-bit only)
https://github.com/llvm/llvm-project/pull/76488
More information about the llvm-commits
mailing list