//===-- SILowerControlFlow.cpp - Use predicates for control flow ----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // /// \file /// This pass lowers the pseudo control flow instructions to real /// machine instructions. /// /// All control flow is handled using predicated instructions and /// a predicate stack. Each Scalar ALU controls the operations of 64 Vector /// ALUs. The Scalar ALU can update the predicate for any of the Vector ALUs /// by writing to the 64-bit EXEC register (each bit corresponds to a /// single vector ALU). Typically, for predicates, a vector ALU will write /// to its bit of the VCC register (like EXEC VCC is 64-bits, one for each /// Vector ALU) and then the ScalarALU will AND the VCC register with the /// EXEC to update the predicates. /// /// For example: /// %vcc = V_CMP_GT_F32 %vgpr1, %vgpr2 /// %sgpr0 = SI_IF %vcc /// %vgpr0 = V_ADD_F32 %vgpr0, %vgpr0 /// %sgpr0 = SI_ELSE %sgpr0 /// %vgpr0 = V_SUB_F32 %vgpr0, %vgpr0 /// SI_END_CF %sgpr0 /// /// becomes: /// /// %sgpr0 = S_AND_SAVEEXEC_B64 %vcc // Save and update the exec mask /// %sgpr0 = S_XOR_B64 %sgpr0, %exec // Clear live bits from saved exec mask /// S_CBRANCH_EXECZ label0 // This instruction is an optional /// // optimization which allows us to /// // branch if all the bits of /// // EXEC are zero. /// %vgpr0 = V_ADD_F32 %vgpr0, %vgpr0 // Do the IF block of the branch /// /// label0: /// %sgpr0 = S_OR_SAVEEXEC_B64 %sgpr0 // Restore the exec mask for the Then /// // block /// %exec = S_XOR_B64 %sgpr0, %exec // Update the exec mask /// S_BRANCH_EXECZ label1 // Use our branch optimization /// // instruction again. /// %vgpr0 = V_SUB_F32 %vgpr0, %vgpr // Do the THEN block /// label1: /// %exec = S_OR_B64 %exec, %sgpr0 // Re-enable saved exec mask bits //===----------------------------------------------------------------------===// #include "AMDGPU.h" #include "GCNSubtarget.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" #include "llvm/ADT/SmallSet.h" #include "llvm/CodeGen/LiveIntervals.h" #include "llvm/CodeGen/LiveVariables.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/Target/TargetMachine.h" usingnamespacellvm; #define DEBUG_TYPE … static cl::opt<bool> RemoveRedundantEndcf("amdgpu-remove-redundant-endcf", cl::init(true), cl::ReallyHidden); namespace { class SILowerControlFlow : public MachineFunctionPass { … }; } // end anonymous namespace char SILowerControlFlow::ID = …; INITIALIZE_PASS(…) static void setImpSCCDefDead(MachineInstr &MI, bool IsDead) { … } char &llvm::SILowerControlFlowID = …; bool SILowerControlFlow::hasKill(const MachineBasicBlock *Begin, const MachineBasicBlock *End) { … } static bool isSimpleIf(const MachineInstr &MI, const MachineRegisterInfo *MRI) { … } void SILowerControlFlow::emitIf(MachineInstr &MI) { … } void SILowerControlFlow::emitElse(MachineInstr &MI) { … } void SILowerControlFlow::emitIfBreak(MachineInstr &MI) { … } void SILowerControlFlow::emitLoop(MachineInstr &MI) { … } MachineBasicBlock::iterator SILowerControlFlow::skipIgnoreExecInstsTrivialSucc( MachineBasicBlock &MBB, MachineBasicBlock::iterator It) const { … } MachineBasicBlock *SILowerControlFlow::emitEndCf(MachineInstr &MI) { … } // Returns replace operands for a logical operation, either single result // for exec or two operands if source was another equivalent operation. void SILowerControlFlow::findMaskOperands(MachineInstr &MI, unsigned OpNo, SmallVectorImpl<MachineOperand> &Src) const { … } // Search and combine pairs of equivalent instructions, like // S_AND_B64 x, (S_AND_B64 x, y) => S_AND_B64 x, y // S_OR_B64 x, (S_OR_B64 x, y) => S_OR_B64 x, y // One of the operands is exec mask. void SILowerControlFlow::combineMasks(MachineInstr &MI) { … } void SILowerControlFlow::optimizeEndCf() { … } MachineBasicBlock *SILowerControlFlow::process(MachineInstr &MI) { … } bool SILowerControlFlow::removeMBBifRedundant(MachineBasicBlock &MBB) { … } bool SILowerControlFlow::runOnMachineFunction(MachineFunction &MF) { … }