Index: llvm/trunk/lib/Target/PowerPC/PPCMachineScheduler.h =================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCMachineScheduler.h +++ llvm/trunk/lib/Target/PowerPC/PPCMachineScheduler.h @@ -22,6 +22,13 @@ public: PPCPreRASchedStrategy(const MachineSchedContext *C) : GenericScheduler(C) {} +protected: + void tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, + SchedBoundary *Zone) const override; +private: + bool biasAddiLoadCandidate(SchedCandidate &Cand, + SchedCandidate &TryCand, + SchedBoundary &Zone) const; }; /// A MachineSchedStrategy implementation for PowerPC post RA scheduling. Index: llvm/trunk/lib/Target/PowerPC/PPCMachineScheduler.cpp =================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCMachineScheduler.cpp +++ llvm/trunk/lib/Target/PowerPC/PPCMachineScheduler.cpp @@ -5,9 +5,60 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// +#include "PPC.h" #include "PPCMachineScheduler.h" using namespace llvm; +static cl::opt +DisableAddiLoadHeuristic("disable-ppc-sched-addi-load", + cl::desc("Disable scheduling addi instruction before" + "load for ppc"), cl::Hidden); + +bool PPCPreRASchedStrategy::biasAddiLoadCandidate(SchedCandidate &Cand, + SchedCandidate &TryCand, + SchedBoundary &Zone) const { + if (DisableAddiLoadHeuristic) + return false; + + auto isADDIInstr = [&] (const MachineInstr &Inst) { + return Inst.getOpcode() == PPC::ADDI || Inst.getOpcode() == PPC::ADDI8; + }; + + SchedCandidate &FirstCand = Zone.isTop() ? TryCand : Cand; + SchedCandidate &SecondCand = Zone.isTop() ? Cand : TryCand; + if (isADDIInstr(*FirstCand.SU->getInstr()) && + SecondCand.SU->getInstr()->mayLoad()) { + TryCand.Reason = Stall; + return true; + } + if (FirstCand.SU->getInstr()->mayLoad() && + isADDIInstr(*SecondCand.SU->getInstr())) { + TryCand.Reason = NoCand; + return true; + } + + return false; +} + +void PPCPreRASchedStrategy::tryCandidate(SchedCandidate &Cand, + SchedCandidate &TryCand, + SchedBoundary *Zone) const { + GenericScheduler::tryCandidate(Cand, TryCand, Zone); + + if (!Cand.isValid() || !Zone) + return; + + // Add powerpc specific heuristic only when TryCand isn't selected or + // selected as node order. + if (TryCand.Reason != NodeOrder && TryCand.Reason != NoCand) + return; + + // There are some benefits to schedule the ADDI before the load to hide the + // latency, as RA may create a true dependency between the load and addi. + if (biasAddiLoadCandidate(Cand, TryCand, *Zone)) + return; +} + void PPCPostRASchedStrategy::enterMBB(MachineBasicBlock *MBB) { // Custom PPC PostRA specific behavior here. PostGenericScheduler::enterMBB(MBB); Index: llvm/trunk/test/CodeGen/PowerPC/schedule-addi-load.mir =================================================================== --- llvm/trunk/test/CodeGen/PowerPC/schedule-addi-load.mir +++ llvm/trunk/test/CodeGen/PowerPC/schedule-addi-load.mir @@ -1,4 +1,7 @@ # RUN: llc -mcpu=pwr9 -mtriple powerpc64le-unknown-linux-gnu -start-before machine-scheduler -stop-after machine-scheduler -verify-machineinstrs %s -o - | FileCheck %s +# RUN: llc -mcpu=pwr9 -mtriple powerpc64le-unknown-linux-gnu -disable-ppc-sched-addi-load -start-before machine-scheduler -stop-after machine-scheduler \ +# RUN: -verify-machineinstrs %s -o - | FileCheck --check-prefix=CHECK-DISABLE %s +# RUN: llc -mcpu=pwr8 -mtriple powerpc64le-unknown-linux-gnu -start-before machine-scheduler -stop-after machine-scheduler -verify-machineinstrs %s -o - | FileCheck --check-prefix=CHECK-P8 %s # Test that if the scheduler moves the addi before the load. --- | @@ -93,11 +96,25 @@ B %bb.2 ; CHECK-LABEL: foo ; CHECK: %5:g8rc_and_g8rc_nox0 = RLDICL %0, 0, 32 + ; CHECK-NEXT: %9:g8rc = ADDI8 %5, 1 ; CHECK-NEXT: %6:gprc = LBZX %2, %5 :: (load 1 from %ir.arrayidx) ; CHECK-NEXT: %7:gprc = LBZX %3, %5 :: (load 1 from %ir.arrayidx4) - ; CHECK-NEXT: %9:g8rc = ADDI8 %5, 1 ; CHECK-NEXT: %8:crrc = CMPLW %6, %7 ; CHECK-NEXT: BCC 76, %8 + ; CHECK-DISABLE-LABEL: foo + ; CHECK-DISABLE: %5:g8rc_and_g8rc_nox0 = RLDICL %0, 0, 32 + ; CHECK-DISABLE-NEXT: %6:gprc = LBZX %2, %5 :: (load 1 from %ir.arrayidx) + ; CHECK-DISABLE-NEXT: %7:gprc = LBZX %3, %5 :: (load 1 from %ir.arrayidx4) + ; CHECK-DISABLE-NEXT: %9:g8rc = ADDI8 %5, 1 + ; CHECK-DISABLE-NEXT: %8:crrc = CMPLW %6, %7 + ; CHECK-DISABLE-NEXT: BCC 76, %8 + ; CHECK-P8-LABEL: foo + ; CHECK-P8: %5:g8rc_and_g8rc_nox0 = RLDICL %0, 0, 32 + ; CHECK-P8-NEXT: %6:gprc = LBZX %2, %5 :: (load 1 from %ir.arrayidx) + ; CHECK-P8-NEXT: %7:gprc = LBZX %3, %5 :: (load 1 from %ir.arrayidx4) + ; CHECK-P8-NEXT: %8:crrc = CMPLW %6, %7 + ; CHECK-P8-NEXT: %9:g8rc = ADDI8 %5, 1 + ; CHECK-P8-NEXT: BCC 76, %8 bb.2.while.end: $x3 = COPY %0