FW: [PATCH] D16353: [mips] MIPS32R6 compact branch support
Simon Dardis via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 27 08:26:23 PST 2016
Adding Daniel to this thread.
> -----Original Message-----
> From: llvm-commits [mailto:llvm-commits-bounces at lists.llvm.org] On Behalf
> Of Simon Dardis via llvm-commits
> Sent: 27 January 2016 13:39
> To: Vasileios Kalintiris
> Cc: llvm-commits at lists.llvm.org
> Subject: Re: [PATCH] D16353: [mips] MIPS32R6 compact branch support
>
> sdardis added inline comments.
>
> ================
> Comment at: lib/Target/Mips/MipsDelaySlotFiller.cpp:549-613
> @@ -566,1 +548,67 @@
>
> +// The forbidden slot is the instruction immediately following a
> +compact // branch. A forbidden slot hazard occurs when a compact branch
> +instruction // is executed and the adjacent instruction in memory is a
> +control transfer // instruction such as a branch or jump, ERET, ERETNC,
> +DERET, WAIT and // PAUSE.
> +//
> +// In such cases, the processor is required to signal a Reserved
> +Instruction // exception. Forbidden slot hazards are defined for MIPSR6, no
> microMIPS.
> +//
> +// There are three sources of forbidden slot hazards:
> +//
> +// A) Transforming a delay slot branch into compact branch.
> +// B) A previous pass has created a compact branch directly.
> +// C) Filling a delay slot using a backwards search when the instruction
> +// moved was in a forbidden slot. This case will create hazards in already
> +// processed code.
> +//
> +bool Filler::clearFSHazards(MachineFunction &F) {
> + bool Changed = false;
> + const MipsSubtarget &STI = F.getSubtarget<MipsSubtarget>();
> + const MipsSEInstrInfo *TII =
> + static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo());
> +
> + for (MachineFunction::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) {
> + for (Iter I = (*FI).begin(); I != (*FI).end(); ++I) {
> + if (TII->HasForbiddenSlot(I)) {
> + if (std::next(I) != (*FI).end() &&
> + !TII->SafeInForbiddenSlot(&*std::next(I))) {
> + BuildMI((*FI), std::next(I), I->getDebugLoc(), TII->get(Mips::NOP));
> + Changed = true;
> + } else {
> + for (auto *Succ : (*FI).successors()) {
> + if ((*FI).isLayoutSuccessor(Succ) &&
> + (Succ->getFirstNonDebugInstr()) != Succ->end() &&
> + !TII->SafeInForbiddenSlot((Succ->getFirstNonDebugInstr()))) {
> + BuildMI(&(*FI), I->getDebugLoc(), TII->get(Mips::NOP));
> + Changed = true;
> + }
> + }
> + }
> + if (Changed)
> + MIBundleBuilder(*FI, I, std::next(I, 2));
> + }
> + }
> + }
> + return Changed;
> +}
> +
> +bool Filler::runOnMachineFunction(MachineFunction &F) {
> + bool Changed = false;
> + for (MachineFunction::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
> + Changed |= runOnMachineBasicBlock(*FI);
> +
> + // Make a second pass over the instructions to clear hazards.
> + const MipsSubtarget &STI = F.getSubtarget<MipsSubtarget>(); if
> + (STI.hasMips32r6() && !STI.inMicroMipsMode())
> + Changed |= clearFSHazards(F);
> +
> + // This pass invalidates liveness information when it reorders //
> + instructions to fill delay slot. Without this, -verify-machineinstrs
> + // will fail.
> + if (Changed)
> + F.getRegInfo().invalidateLiveness();
> +
> + return Changed;
> +}
> ----------------
> vkalintiris wrote:
> > The (C) case will happen when filling the delay slot of a normal branch, ie.
> inside the MipsDelaySlotFiller pass. We can teach the "search-backwards"
> part of the delay slot filler (DSF) algorithm to handle this by checking the last
> instruction of the BB's layout predecessor. If there are other issues that
> conceptually belong to the DSF pass, then we should add them too by
> modifying the pass accordingly.
> >
> > I don't see how (B) can happen as we only emit compact branches at this
> pass for the time being. From my perspective, if a previous pass would like to
> add a compact-branch, then I can think of two options: (a) insert the compact
> branch only if the next instruction is not a CTI-hazard and leave the task of
> fixing the corner cases that happen during the filling of normal branches by
> the DSF, or (b) insert a NOP and just offload everything to the DSF. I can't
> think of any reason for a post-DSF pass to insert new/additional compact-
> branches or move non-CTI instructions from a forbidden slot.
> >
> > Even if we find ourselves constrained by having the DSF pass handling
> everything, then we can add a separate/final pass that fixes every case left
> over from previous passes. However, with this design we would achieve the
> minimum number of places were our code is wrong/invalid.
> >
> > If we'd want to be on the really safe side and make sure that we are aware
> of every possible case that we might haven't consider yet, then we can add a
> separate pass and enable it only for debug builds. It could assert upon finding
> a compact-branch that contains a CTI in its forbidden slot.
> >
> > Even if we find ourselves constrained by having the DSF pass handling
> everything, then we can add a separate/final pass that fixes every case left
> over from previous passes. However, with this design we would achieve the
> minimum number of places were our code is wrong/invalid.
>
> Rather than wiring FS hazard handling logic into the DSF, we could split it off
> into a separate pass and enable it after the delay slot filler, like the first diff.
> Thoughts dsanders? It keeps the implementation safer and simpler.
>
>
> http://reviews.llvm.org/D16353
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list