10b57cec5SDimitry Andric //===- PPCMachineScheduler.cpp - MI Scheduler for PowerPC -------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "PPCMachineScheduler.h" 100b57cec5SDimitry Andric #include "MCTargetDesc/PPCMCTargetDesc.h" 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric using namespace llvm; 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric static cl::opt<bool> 150b57cec5SDimitry Andric DisableAddiLoadHeuristic("disable-ppc-sched-addi-load", 160b57cec5SDimitry Andric cl::desc("Disable scheduling addi instruction before" 170b57cec5SDimitry Andric "load for ppc"), cl::Hidden); 18*5ffd83dbSDimitry Andric static cl::opt<bool> 19*5ffd83dbSDimitry Andric EnableAddiHeuristic("ppc-postra-bias-addi", 20*5ffd83dbSDimitry Andric cl::desc("Enable scheduling addi instruction as early" 21*5ffd83dbSDimitry Andric "as possible post ra"), 22*5ffd83dbSDimitry Andric cl::Hidden, cl::init(true)); 23*5ffd83dbSDimitry Andric 24*5ffd83dbSDimitry Andric static bool isADDIInstr(const GenericScheduler::SchedCandidate &Cand) { 25*5ffd83dbSDimitry Andric return Cand.SU->getInstr()->getOpcode() == PPC::ADDI || 26*5ffd83dbSDimitry Andric Cand.SU->getInstr()->getOpcode() == PPC::ADDI8; 27*5ffd83dbSDimitry Andric } 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric bool PPCPreRASchedStrategy::biasAddiLoadCandidate(SchedCandidate &Cand, 300b57cec5SDimitry Andric SchedCandidate &TryCand, 310b57cec5SDimitry Andric SchedBoundary &Zone) const { 320b57cec5SDimitry Andric if (DisableAddiLoadHeuristic) 330b57cec5SDimitry Andric return false; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric SchedCandidate &FirstCand = Zone.isTop() ? TryCand : Cand; 360b57cec5SDimitry Andric SchedCandidate &SecondCand = Zone.isTop() ? Cand : TryCand; 37*5ffd83dbSDimitry Andric if (isADDIInstr(FirstCand) && SecondCand.SU->getInstr()->mayLoad()) { 380b57cec5SDimitry Andric TryCand.Reason = Stall; 390b57cec5SDimitry Andric return true; 400b57cec5SDimitry Andric } 41*5ffd83dbSDimitry Andric if (FirstCand.SU->getInstr()->mayLoad() && isADDIInstr(SecondCand)) { 420b57cec5SDimitry Andric TryCand.Reason = NoCand; 430b57cec5SDimitry Andric return true; 440b57cec5SDimitry Andric } 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric return false; 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric void PPCPreRASchedStrategy::tryCandidate(SchedCandidate &Cand, 500b57cec5SDimitry Andric SchedCandidate &TryCand, 510b57cec5SDimitry Andric SchedBoundary *Zone) const { 520b57cec5SDimitry Andric GenericScheduler::tryCandidate(Cand, TryCand, Zone); 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric if (!Cand.isValid() || !Zone) 550b57cec5SDimitry Andric return; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric // Add powerpc specific heuristic only when TryCand isn't selected or 580b57cec5SDimitry Andric // selected as node order. 590b57cec5SDimitry Andric if (TryCand.Reason != NodeOrder && TryCand.Reason != NoCand) 600b57cec5SDimitry Andric return; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric // There are some benefits to schedule the ADDI before the load to hide the 630b57cec5SDimitry Andric // latency, as RA may create a true dependency between the load and addi. 640b57cec5SDimitry Andric if (biasAddiLoadCandidate(Cand, TryCand, *Zone)) 650b57cec5SDimitry Andric return; 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric 68*5ffd83dbSDimitry Andric bool PPCPostRASchedStrategy::biasAddiCandidate(SchedCandidate &Cand, 69*5ffd83dbSDimitry Andric SchedCandidate &TryCand) const { 70*5ffd83dbSDimitry Andric if (!EnableAddiHeuristic) 71*5ffd83dbSDimitry Andric return false; 72*5ffd83dbSDimitry Andric 73*5ffd83dbSDimitry Andric if (isADDIInstr(TryCand) && !isADDIInstr(Cand)) { 74*5ffd83dbSDimitry Andric TryCand.Reason = Stall; 75*5ffd83dbSDimitry Andric return true; 76*5ffd83dbSDimitry Andric } 77*5ffd83dbSDimitry Andric return false; 78*5ffd83dbSDimitry Andric } 79*5ffd83dbSDimitry Andric 80*5ffd83dbSDimitry Andric void PPCPostRASchedStrategy::tryCandidate(SchedCandidate &Cand, 81*5ffd83dbSDimitry Andric SchedCandidate &TryCand) { 82*5ffd83dbSDimitry Andric PostGenericScheduler::tryCandidate(Cand, TryCand); 83*5ffd83dbSDimitry Andric 84*5ffd83dbSDimitry Andric if (!Cand.isValid()) 85*5ffd83dbSDimitry Andric return; 86*5ffd83dbSDimitry Andric 87*5ffd83dbSDimitry Andric // Add powerpc post ra specific heuristic only when TryCand isn't selected or 88*5ffd83dbSDimitry Andric // selected as node order. 89*5ffd83dbSDimitry Andric if (TryCand.Reason != NodeOrder && TryCand.Reason != NoCand) 90*5ffd83dbSDimitry Andric return; 91*5ffd83dbSDimitry Andric 92*5ffd83dbSDimitry Andric // There are some benefits to schedule the ADDI as early as possible post ra 93*5ffd83dbSDimitry Andric // to avoid stalled by vector instructions which take up all the hw units. 94*5ffd83dbSDimitry Andric // And ADDI is usually used to post inc the loop indvar, which matters the 95*5ffd83dbSDimitry Andric // performance. 96*5ffd83dbSDimitry Andric if (biasAddiCandidate(Cand, TryCand)) 97*5ffd83dbSDimitry Andric return; 98*5ffd83dbSDimitry Andric } 99*5ffd83dbSDimitry Andric 1000b57cec5SDimitry Andric void PPCPostRASchedStrategy::enterMBB(MachineBasicBlock *MBB) { 1010b57cec5SDimitry Andric // Custom PPC PostRA specific behavior here. 1020b57cec5SDimitry Andric PostGenericScheduler::enterMBB(MBB); 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric void PPCPostRASchedStrategy::leaveMBB() { 1060b57cec5SDimitry Andric // Custom PPC PostRA specific behavior here. 1070b57cec5SDimitry Andric PostGenericScheduler::leaveMBB(); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric void PPCPostRASchedStrategy::initialize(ScheduleDAGMI *Dag) { 1110b57cec5SDimitry Andric // Custom PPC PostRA specific initialization here. 1120b57cec5SDimitry Andric PostGenericScheduler::initialize(Dag); 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric SUnit *PPCPostRASchedStrategy::pickNode(bool &IsTopNode) { 1160b57cec5SDimitry Andric // Custom PPC PostRA specific scheduling here. 1170b57cec5SDimitry Andric return PostGenericScheduler::pickNode(IsTopNode); 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric 120