Path: blob/main/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonCFGOptimizer.cpp
35266 views
//===- HexagonCFGOptimizer.cpp - CFG optimizations ------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "Hexagon.h"9#include "MCTargetDesc/HexagonMCTargetDesc.h"10#include "llvm/CodeGen/MachineBasicBlock.h"11#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"12#include "llvm/CodeGen/MachineFunction.h"13#include "llvm/CodeGen/MachineFunctionPass.h"14#include "llvm/CodeGen/MachineInstr.h"15#include "llvm/CodeGen/MachineOperand.h"16#include "llvm/CodeGen/TargetInstrInfo.h"17#include "llvm/CodeGen/TargetSubtargetInfo.h"18#include "llvm/Pass.h"19#include "llvm/Support/ErrorHandling.h"20#include <cassert>21#include <vector>2223using namespace llvm;2425#define DEBUG_TYPE "hexagon_cfg"2627namespace llvm {2829FunctionPass *createHexagonCFGOptimizer();30void initializeHexagonCFGOptimizerPass(PassRegistry&);3132} // end namespace llvm3334namespace {3536class HexagonCFGOptimizer : public MachineFunctionPass {37private:38void InvertAndChangeJumpTarget(MachineInstr &, MachineBasicBlock *);39bool isOnFallThroughPath(MachineBasicBlock *MBB);4041public:42static char ID;4344HexagonCFGOptimizer() : MachineFunctionPass(ID) {45initializeHexagonCFGOptimizerPass(*PassRegistry::getPassRegistry());46}4748StringRef getPassName() const override { return "Hexagon CFG Optimizer"; }49bool runOnMachineFunction(MachineFunction &Fn) override;5051MachineFunctionProperties getRequiredProperties() const override {52return MachineFunctionProperties().set(53MachineFunctionProperties::Property::NoVRegs);54}55};5657} // end anonymous namespace5859char HexagonCFGOptimizer::ID = 0;6061static bool IsConditionalBranch(int Opc) {62switch (Opc) {63case Hexagon::J2_jumpt:64case Hexagon::J2_jumptpt:65case Hexagon::J2_jumpf:66case Hexagon::J2_jumpfpt:67case Hexagon::J2_jumptnew:68case Hexagon::J2_jumpfnew:69case Hexagon::J2_jumptnewpt:70case Hexagon::J2_jumpfnewpt:71return true;72}73return false;74}7576static bool IsUnconditionalJump(int Opc) {77return (Opc == Hexagon::J2_jump);78}7980void HexagonCFGOptimizer::InvertAndChangeJumpTarget(81MachineInstr &MI, MachineBasicBlock *NewTarget) {82const TargetInstrInfo *TII =83MI.getParent()->getParent()->getSubtarget().getInstrInfo();84int NewOpcode = 0;85switch (MI.getOpcode()) {86case Hexagon::J2_jumpt:87NewOpcode = Hexagon::J2_jumpf;88break;89case Hexagon::J2_jumpf:90NewOpcode = Hexagon::J2_jumpt;91break;92case Hexagon::J2_jumptnewpt:93NewOpcode = Hexagon::J2_jumpfnewpt;94break;95case Hexagon::J2_jumpfnewpt:96NewOpcode = Hexagon::J2_jumptnewpt;97break;98default:99llvm_unreachable("Cannot handle this case");100}101102MI.setDesc(TII->get(NewOpcode));103MI.getOperand(1).setMBB(NewTarget);104}105106bool HexagonCFGOptimizer::isOnFallThroughPath(MachineBasicBlock *MBB) {107if (MBB->canFallThrough())108return true;109for (MachineBasicBlock *PB : MBB->predecessors())110if (PB->isLayoutSuccessor(MBB) && PB->canFallThrough())111return true;112return false;113}114115bool HexagonCFGOptimizer::runOnMachineFunction(MachineFunction &Fn) {116if (skipFunction(Fn.getFunction()))117return false;118119// Loop over all of the basic blocks.120for (MachineBasicBlock &MBB : Fn) {121// Traverse the basic block.122MachineBasicBlock::iterator MII = MBB.getFirstTerminator();123if (MII != MBB.end()) {124MachineInstr &MI = *MII;125int Opc = MI.getOpcode();126if (IsConditionalBranch(Opc)) {127// (Case 1) Transform the code if the following condition occurs:128// BB1: if (p0) jump BB3129// ...falls-through to BB2 ...130// BB2: jump BB4131// ...next block in layout is BB3...132// BB3: ...133//134// Transform this to:135// BB1: if (!p0) jump BB4136// Remove BB2137// BB3: ...138//139// (Case 2) A variation occurs when BB3 contains a JMP to BB4:140// BB1: if (p0) jump BB3141// ...falls-through to BB2 ...142// BB2: jump BB4143// ...other basic blocks ...144// BB4:145// ...not a fall-thru146// BB3: ...147// jump BB4148//149// Transform this to:150// BB1: if (!p0) jump BB4151// Remove BB2152// BB3: ...153// BB4: ...154unsigned NumSuccs = MBB.succ_size();155MachineBasicBlock::succ_iterator SI = MBB.succ_begin();156MachineBasicBlock* FirstSucc = *SI;157MachineBasicBlock* SecondSucc = *(++SI);158MachineBasicBlock* LayoutSucc = nullptr;159MachineBasicBlock* JumpAroundTarget = nullptr;160161if (MBB.isLayoutSuccessor(FirstSucc)) {162LayoutSucc = FirstSucc;163JumpAroundTarget = SecondSucc;164} else if (MBB.isLayoutSuccessor(SecondSucc)) {165LayoutSucc = SecondSucc;166JumpAroundTarget = FirstSucc;167} else {168// Odd case...cannot handle.169}170171// The target of the unconditional branch must be JumpAroundTarget.172// TODO: If not, we should not invert the unconditional branch.173MachineBasicBlock* CondBranchTarget = nullptr;174if (MI.getOpcode() == Hexagon::J2_jumpt ||175MI.getOpcode() == Hexagon::J2_jumpf) {176CondBranchTarget = MI.getOperand(1).getMBB();177}178179if (!LayoutSucc || (CondBranchTarget != JumpAroundTarget)) {180continue;181}182183if ((NumSuccs == 2) && LayoutSucc && (LayoutSucc->pred_size() == 1)) {184// Ensure that BB2 has one instruction -- an unconditional jump.185if ((LayoutSucc->size() == 1) &&186IsUnconditionalJump(LayoutSucc->front().getOpcode())) {187assert(JumpAroundTarget && "jump target is needed to process second basic block");188MachineBasicBlock* UncondTarget =189LayoutSucc->front().getOperand(0).getMBB();190// Check if the layout successor of BB2 is BB3.191bool case1 = LayoutSucc->isLayoutSuccessor(JumpAroundTarget);192bool case2 = JumpAroundTarget->isSuccessor(UncondTarget) &&193!JumpAroundTarget->empty() &&194IsUnconditionalJump(JumpAroundTarget->back().getOpcode()) &&195JumpAroundTarget->pred_size() == 1 &&196JumpAroundTarget->succ_size() == 1;197198if (case1 || case2) {199InvertAndChangeJumpTarget(MI, UncondTarget);200MBB.replaceSuccessor(JumpAroundTarget, UncondTarget);201202// Remove the unconditional branch in LayoutSucc.203LayoutSucc->erase(LayoutSucc->begin());204LayoutSucc->replaceSuccessor(UncondTarget, JumpAroundTarget);205206// This code performs the conversion for case 2, which moves207// the block to the fall-thru case (BB3 in the code above).208if (case2 && !case1) {209JumpAroundTarget->moveAfter(LayoutSucc);210// only move a block if it doesn't have a fall-thru. otherwise211// the CFG will be incorrect.212if (!isOnFallThroughPath(UncondTarget))213UncondTarget->moveAfter(JumpAroundTarget);214}215216// Correct live-in information. Is used by post-RA scheduler217// The live-in to LayoutSucc is now all values live-in to218// JumpAroundTarget.219std::vector<MachineBasicBlock::RegisterMaskPair> OrigLiveIn(220LayoutSucc->livein_begin(), LayoutSucc->livein_end());221std::vector<MachineBasicBlock::RegisterMaskPair> NewLiveIn(222JumpAroundTarget->livein_begin(),223JumpAroundTarget->livein_end());224for (const auto &OrigLI : OrigLiveIn)225LayoutSucc->removeLiveIn(OrigLI.PhysReg);226for (const auto &NewLI : NewLiveIn)227LayoutSucc->addLiveIn(NewLI);228}229}230}231}232}233}234return true;235}236237//===----------------------------------------------------------------------===//238// Public Constructor Functions239//===----------------------------------------------------------------------===//240241INITIALIZE_PASS(HexagonCFGOptimizer, "hexagon-cfg", "Hexagon CFG Optimizer",242false, false)243244FunctionPass *llvm::createHexagonCFGOptimizer() {245return new HexagonCFGOptimizer();246}247248249