diff --git a/llvm/lib/Target/Hexagon/CMakeLists.txt b/llvm/lib/Target/Hexagon/CMakeLists.txt index b4716693c3dc9..bd87b9c894292 100644 --- a/llvm/lib/Target/Hexagon/CMakeLists.txt +++ b/llvm/lib/Target/Hexagon/CMakeLists.txt @@ -39,7 +39,6 @@ add_llvm_target(HexagonCodeGen HexagonGenMux.cpp HexagonGenPredicate.cpp HexagonGlobalRegion.cpp - HexagonGlobalScheduler.cpp HexagonLiveVariables.cpp HexagonHardwareLoops.cpp HexagonHazardRecognizer.cpp diff --git a/llvm/lib/Target/Hexagon/Hexagon.h b/llvm/lib/Target/Hexagon/Hexagon.h index 1db2326b274dc..b3be89abd527b 100644 --- a/llvm/lib/Target/Hexagon/Hexagon.h +++ b/llvm/lib/Target/Hexagon/Hexagon.h @@ -41,7 +41,6 @@ void initializeHexagonEarlyIfConversionPass(PassRegistry &); void initializeHexagonExpandCondsetsPass(PassRegistry &); void initializeHexagonGenMemAbsolutePass(PassRegistry &); void initializeHexagonGenMuxPass(PassRegistry &); -void initializeHexagonGlobalSchedulerPass(PassRegistry &); void initializeHexagonHardwareLoopsPass(PassRegistry &); void initializeHexagonLiveVariablesPass(PassRegistry &); void initializeHexagonLoopIdiomRecognizeLegacyPassPass(PassRegistry &); @@ -95,7 +94,6 @@ FunctionPass *createHexagonGenInsert(); FunctionPass *createHexagonGenMemAbsolute(); FunctionPass *createHexagonGenMux(); FunctionPass *createHexagonGenPredicate(); -FunctionPass *createHexagonGlobalScheduler(); FunctionPass *createHexagonHardwareLoops(); FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM, CodeGenOptLevel OptLevel); diff --git a/llvm/lib/Target/Hexagon/HexagonGlobalScheduler.cpp b/llvm/lib/Target/Hexagon/HexagonGlobalScheduler.cpp deleted file mode 100644 index 092d07431e253..0000000000000 --- a/llvm/lib/Target/Hexagon/HexagonGlobalScheduler.cpp +++ /dev/null @@ -1,5319 +0,0 @@ - -//===----- HexagonGlobalScheduler.cpp - Global Scheduler ------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Basic infrastructure for the global scheduling + Hexagon pull-up pass. -// Currently run at the very end of code generation for Hexagon, cleans -// up lost scheduling opportunities. Currently breaks liveness, so no passes -// that rely on liveness info should run afterwards. Will be fixed in future -// versions. -// -//===----------------------------------------------------------------------===// -#include "Hexagon.h" -#include "HexagonGlobalRegion.h" -#include "HexagonMachineFunctionInfo.h" -#include "HexagonRegisterInfo.h" -#include "HexagonSubtarget.h" -#include "HexagonTargetMachine.h" -#include "HexagonVLIWPacketizer.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/ValueTracking.h" -#include "llvm/CodeGen/DFAPacketizer.h" -#include "llvm/CodeGen/LatencyPriorityQueue.h" -#include "llvm/CodeGen/LiveIntervals.h" -#include "llvm/CodeGen/MachineBlockFrequencyInfo.h" -#include "llvm/CodeGen/MachineBranchProbabilityInfo.h" -#include "llvm/CodeGen/MachineDominators.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineLoopInfo.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/PseudoSourceValue.h" -#include "llvm/CodeGen/SchedulerRegistry.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/CodeGen/TargetSchedule.h" -#include "llvm/IR/Operator.h" -#include "llvm/InitializePasses.h" -#include "llvm/MC/MCInstrItineraries.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Transforms/Utils/BasicBlockUtils.h" - -#include -#include - -#define DEBUG_TYPE "global_sched" - -using namespace llvm; - -STATISTIC(HexagonNumPullUps, "Number of instructions pull-ups"); -STATISTIC(HexagonNumDualJumps, "Number of dual jumps formed"); - -static cl::opt DisablePullUp("disable-pull-up", cl::Hidden, - cl::desc("Disable Hexagon pull-up pass")); - -static cl::opt EnableSpeculativePullUp( - "enable-speculative-pull-up", cl::Hidden, - cl::desc("Enable speculation during Hexagon pull-up pass")); - -static cl::opt EnableLocalPullUp( - "enable-local-pull-up", cl::Hidden, cl::init(true), - cl::desc("Enable same BB pull during Hexagon pull-up pass")); - -static cl::opt AllowSpeculateLoads( - "speculate-loads-on-pull-up", cl::Hidden, cl::init(true), - cl::desc("Allow speculative loads during Hexagon pull-up pass")); - -static cl::opt AllowCmpBranchLoads( - "cmp-branch-loads-pull-up", cl::Hidden, cl::init(true), - cl::desc("Allow compare-branch loads during Hexagon pull-up pass")); - -static cl::opt AllowUnlikelyPath("unlikely-path-pull-up", cl::Hidden, - cl::init(true), - cl::desc("Allow unlikely path pull up")); - -static cl::opt - PerformDualJumps("dual-jump-in-pull-up", cl::Hidden, cl::init(true), - cl::desc("Perform dual jump formation during pull up")); - -static cl::opt AllowDependentPullUp( - "enable-dependent-pull-up", cl::Hidden, cl::init(true), - cl::desc("Perform dual jump formation during pull up")); - -static cl::opt - AllowBBPeelPullUp("enable-bb-peel-pull-up", cl::Hidden, cl::init(true), - cl::desc("Peel a reg copy out of a BBloop")); - -static cl::opt PreventCompoundSeparation( - "prevent-compound-separation", cl::Hidden, - cl::desc("Do not destroy existing compounds during pull up")); - -static cl::opt PreventDuplexSeparation( - "prevent-duplex-separation", cl::Hidden, cl::init(true), - cl::desc("Do not destroy existing duplexes during pull up")); - -static cl::opt MainCandidateQueueSize("pull-up-main-queue-size", - cl::Hidden, cl::init(8)); - -static cl::opt SecondaryCandidateQueueSize("pull-up-sec-queue-size", - cl::Hidden, cl::init(2)); - -static cl::opt PostPullUpOpt( - "post-pull-up-opt", cl::Hidden, cl::Optional, cl::init(true), - cl::desc("Enable opt. exposed by pull-up e.g., remove redundant jumps")); - -static cl::opt SpeculateNonPredInsn( - "speculate-non-pred-insn", cl::Hidden, cl::Optional, cl::init(true), - cl::desc("Speculate non-predicable instructions in parent BB")); - -static cl::opt - DisableCheckBundles("disable-hexagon-check-bundles", cl::Hidden, - cl::init(true), - cl::desc("Disable Hexagon check bundles pass")); - -static cl::opt - WarnOnBundleSize("warn-on-bundle-size", cl::Hidden, - cl::desc("Hexagon check bundles and warn on size")); - -static cl::opt - ForceNoopHazards("force-noop-hazards", cl::Hidden, cl::init(false), - cl::desc("Force noop hazards in scheduler")); -static cl::opt OneFloatPerPacket( - "single-float-packet", cl::Hidden, - cl::desc("Allow only one single floating point instruction in a packet")); -static cl::opt OneComplexPerPacket( - "single-complex-packet", cl::Hidden, - cl::desc("Allow only one complex instruction in a packet")); - -namespace llvm { -FunctionPass *createHexagonGlobalScheduler(); -void initializeHexagonGlobalSchedulerPass(PassRegistry &); -} // namespace llvm - -namespace { -class HexagonGlobalSchedulerImpl; - -class HexagonGlobalScheduler : public MachineFunctionPass { -public: - static char ID; - HexagonGlobalScheduler() : MachineFunctionPass(ID) { - initializeHexagonGlobalSchedulerPass(*PassRegistry::getPassRegistry()); - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequiredID(MachineDominatorsID); - AU.addRequired(); - AU.addRequired(); - AU.addRequired(); - AU.addRequired(); - AU.addRequired(); - MachineFunctionPass::getAnalysisUsage(AU); - } - - StringRef getPassName() const override { return "Hexagon Global Scheduler"; } - - bool runOnMachineFunction(MachineFunction &Fn) override; -}; -char HexagonGlobalScheduler::ID = 0; - -// Describes a single pull-up candidate. -class PullUpCandidate { - MachineBasicBlock::instr_iterator CandidateLocation; - MachineBasicBlock::iterator HomeBundle; - bool DependentOp; - signed BenefitCost; - std::vector Backtrack; - -public: - PullUpCandidate(MachineBasicBlock::instr_iterator MII) { - CandidateLocation = MII; - BenefitCost = 0; - } - - PullUpCandidate(MachineBasicBlock::instr_iterator MII, - MachineBasicBlock::iterator HomeBundle, - std::vector &backtrack, bool DependentOp, - signed Cost) - : CandidateLocation(MII), HomeBundle(HomeBundle), - DependentOp(DependentOp), BenefitCost(Cost) { - // Copy of the backtrack. - Backtrack = backtrack; - } - - void populate(MachineBasicBlock::instr_iterator &MII, - MachineBasicBlock::iterator &WorkPoint, - std::vector &backtrack, bool &dependentOp) { - MII = CandidateLocation; - WorkPoint = HomeBundle; - backtrack = Backtrack; - dependentOp = DependentOp; - } - - signed getCost() { return BenefitCost; } - - MachineInstr *getCandidate() { return &*CandidateLocation; } - - void dump() { - dbgs() << "Cost(" << BenefitCost; - dbgs() << ") Dependent(" << DependentOp; - dbgs() << ") backtrack size(" << Backtrack.size() << ")\t"; - CandidateLocation->dump(); - } -}; - -/// PullUpCandidateSorter - A Sort utility for pull-up candidates. -struct PullUpCandidateSorter { - PullUpCandidateSorter() {} - bool operator()(PullUpCandidate *LHS, PullUpCandidate *RHS) { - return LHS->getCost() > RHS->getCost(); - } -}; - -// Describes a single pull-up opportunity: location to which -// pull-up is possible with additional information about it. -// Also contains a list of pull-up candidates for this location. -class PullUpState { - friend class HexagonGlobalSchedulerImpl; - // Available opportunity for pull-up. - // FAIAP a bundle with an empty slot. - MachineBasicBlock::iterator HomeLocation; - // Home bundle copy. This is here for speed of iteration. - SmallVector HomeBundle; - // Multiple candidates for the Home location. - SmallVector PullUpCandidates; - - const HexagonInstrInfo *QII; - -public: - PullUpState(const HexagonInstrInfo *QII) : HomeLocation(NULL), QII(QII) {} - - ~PullUpState() { reset(); } - - void addPullUpCandidate(MachineBasicBlock::instr_iterator MII, - MachineBasicBlock::iterator HomeBundle, - std::vector &backtrack, - bool DependentOp, signed Cost) { - LLVM_DEBUG(dbgs() << "\t[addPullUpCandidate]: "; (*MII).dump()); - PullUpCandidate *PUI = - new PullUpCandidate(MII, HomeBundle, backtrack, DependentOp, Cost); - PullUpCandidates.push_back(PUI); - } - - void dump() { - unsigned element = 0; - for (unsigned i = 0; i < HomeBundle.size(); i++) { - dbgs() << "[" << element++; - dbgs() << "] Home Duplex(" - << QII->getDuplexCandidateGroup(*HomeBundle[i]); - dbgs() << ") Compound (" << QII->getCompoundCandidateGroup(*HomeBundle[i]) - << ") "; - HomeBundle[i]->dump(); - } - dbgs() << "\n"; - element = 0; - for (SmallVector::iterator - I = PullUpCandidates.begin(), - E = PullUpCandidates.end(); - I != E; ++I) { - dbgs() << "[" << element++ << "] Cand: Compound("; - dbgs() << QII->getCompoundCandidateGroup(*(*I)->getCandidate()) << ") "; - (*I)->dump(); - } - } - - void reset() { - HomeLocation = NULL; - for (SmallVector::iterator - I = PullUpCandidates.begin(), - E = PullUpCandidates.end(); - I != E; ++I) - delete *I; - PullUpCandidates.clear(); - HomeBundle.clear(); - } - - void addHomeLocation(MachineBasicBlock::iterator WorkPoint) { - reset(); - HomeLocation = WorkPoint; - } - - unsigned haveCandidates() { return PullUpCandidates.size(); } -}; - -class HexagonGlobalSchedulerImpl : public HexagonPacketizerList { - // List of PullUp regions for this function. - std::vector PullUpRegions; - // Map of approximate distance for each BB from the - // function base. - DenseMap BlockToInstOffset; - // Keep track of multiple pull-up candidates. - PullUpState CurrentState; - // Empty basic blocks as a result of pull-up. - std::vector EmptyBBs; - // Save all the Speculated MachineInstr that were moved - // FROM MachineBasicBlock because we don't want to have - // more than one speculated instructions pulled into one packet. - // TODO: This can be removed once we have a use-def dependency chain - // for all the instructions in a function. - std::map SpeculatedIns; - // All the regs and their aliases used by an instruction. - std::map> MIUseSet; - // All the regs and their aliases defined by an instruction. - std::map> MIDefSet; - - AliasAnalysis *AA; - const MachineBranchProbabilityInfo *MBPI; - const MachineBlockFrequencyInfo *MBFI; - const MachineRegisterInfo *MRI; - const MachineFrameInfo &MFI; - const HexagonRegisterInfo *QRI; - const HexagonInstrInfo *QII; - MachineLoopInfo &MLI; - MachineDominatorTree &MDT; - MachineInstrBuilder Ext; - MachineInstrBuilder Nop; - const unsigned PacketSize; - TargetSchedModel TSchedModel; - -public: - // Ctor. - HexagonGlobalSchedulerImpl(MachineFunction &MF, MachineLoopInfo &MLI, - MachineDominatorTree &MDT, AliasAnalysis *AA, - const MachineBranchProbabilityInfo *MBPI, - const MachineBlockFrequencyInfo *MBFI, - const MachineRegisterInfo *MRI, - const MachineFrameInfo &MFI, - const HexagonRegisterInfo *QRI); - HexagonGlobalSchedulerImpl(const HexagonGlobalSchedulerImpl &) = delete; - HexagonGlobalSchedulerImpl & - operator=(const HexagonGlobalSchedulerImpl &) = delete; - - ~HexagonGlobalSchedulerImpl() { - // Free regions. - for (std::vector::iterator I = PullUpRegions.begin(), - E = PullUpRegions.end(); - I != E; ++I) - delete *I; - MF.deleteMachineInstr(Ext); - MF.deleteMachineInstr(Nop); - } - - // initPacketizerState - initialize some internal flags. - void initPacketizerState() override; - - // ignorePseudoInstruction - Ignore bundling of pseudo instructions. - bool ignoreInstruction(MachineInstr *MI); - - // isSoloInstruction - return true if instruction MI can not be packetized - // with any other instruction, which means that MI itself is a packet. - bool isSoloInstruction(const MachineInstr &MI) override; - - // Add MI to packetizer state. Returns false if it cannot fit in the packet. - bool incrementalAddToPacket(MachineInstr &MI); - - // formPullUpRegions - Top level call to form regions. - bool formPullUpRegions(MachineFunction &Fn); - - // performPullUp - Top level call for pull-up. - bool performPullUp(); - - // performPullUpCFG - Top level call for pull-up CFG. - bool performPullUpCFG(MachineFunction &Fn); - - // performExposedOptimizations - - // Look for optimization opportunities after pullup. - bool performExposedOptimizations(MachineFunction &Fn); - - // optimizeBranching - - // 1. A conditional-jump transfers control to a BB with - // jump as the only instruction. - // if(p0) jump t1 - // // ... - // t1: jump t2 - // 2. When a BB with a single conditional jump, jumps to succ-of-succ and - // falls-through BB with only jump instruction. - // { if(p0) jump t1 } - // { jump t2 } - // t1: { ... } - MachineBasicBlock *optimizeBranches(MachineBasicBlock *MBB, - MachineBasicBlock *TBB, - MachineInstr *FirstTerm, - MachineBasicBlock *FBB); - - // removeRedundantBranches - - // 1. Remove jump to the layout successor. - // 2. Remove multiple (dual) jump to the same target. - bool removeRedundantBranches(MachineBasicBlock *MBB, MachineBasicBlock *TBB, - MachineInstr *FirstTerm, MachineBasicBlock *FBB, - MachineInstr *SecondTerm); - - // optimizeDualJumps - optimize dual jumps in a packet - // For now: Replace dual jump by single jump in case of a fall through. - bool optimizeDualJumps(MachineBasicBlock *MBB, MachineBasicBlock *TBB, - MachineInstr *FirstTerm, MachineBasicBlock *FBB, - MachineInstr *SecondTerm); - - void GenUseDefChain(MachineFunction &Fn); - - // Return region pointer or null if none found. - BasicBlockRegion *getRegionForMBB(std::vector &Regions, - MachineBasicBlock *MBB); - - // Saves all the used-regs and their aliases in Uses. - // Saves all the defined-regs and their aliases in Defs. - void MIUseDefSet(MachineInstr *MI, std::vector &Defs, - std::vector &Uses); - - // This is a very useful debug utility. - unsigned countCompounds(MachineFunction &Fn); - - // Check bundle counts - void checkBundleCounts(MachineFunction &Fn); - -private: - // Get next BB to be included into the region. - MachineBasicBlock *getNextPURBB(MachineBasicBlock *MBB, bool SecondBest); - - void setUsedRegs(BitVector &Set, unsigned Reg); - bool AliasingRegs(unsigned RegA, unsigned RegB); - - // Test is true if the two MIs cannot be safely reordered. - bool ReorderDependencyTest(MachineInstr *MIa, MachineInstr *MIb); - - bool canAddMIToThisPacket( - MachineInstr *MI, - SmallVector &Bundle); - - bool CanPromoteToDotNew(MachineInstr *MI, unsigned Reg); - - bool pullUpPeelBBLoop(MachineBasicBlock *PredBB, MachineBasicBlock *LoopBB); - - MachineInstr *findBundleAndBranch(MachineBasicBlock *BB, - MachineBasicBlock::iterator &Bundle); - - // Does this bundle have any slots left? - bool ResourcesAvailableInBundle(BasicBlockRegion *CurrentRegion, - MachineBasicBlock::iterator &TargetPacket); - - // Perform the actual move. - MachineInstr *MoveAndUpdateLiveness( - BasicBlockRegion *CurrentRegion, MachineBasicBlock *HomeBB, - MachineInstr *InstrToMove, bool NeedToNewify, unsigned DepReg, - bool MovingDependentOp, MachineBasicBlock *OriginBB, - MachineInstr *OriginalInstruction, SmallVector &Cond, - MachineBasicBlock::iterator &SourceLocation, - MachineBasicBlock::iterator &TargetPacket, - MachineBasicBlock::iterator &NextMI, - std::vector &backtrack); - - // Updates incremental kill patterns along the backtrack. - void updateKillAlongThePath(MachineBasicBlock *HomeBB, - MachineBasicBlock *OriginBB, - MachineBasicBlock::instr_iterator &Head, - MachineBasicBlock::instr_iterator &Tail, - MachineBasicBlock::iterator &SourcePacket, - MachineBasicBlock::iterator &TargetPacket, - std::vector &backtrack); - - // Gather list of pull-up candidates. - bool findPullUpCandidates(MachineBasicBlock::iterator &WorkPoint, - MachineBasicBlock::iterator &FromHere, - std::vector &backtrack, - unsigned MaxCandidates); - - // See if the instruction could be pulled up. - bool tryMultipleInstructions( - MachineBasicBlock::iterator &RetVal, /* output parameter */ - std::vector::iterator &CurrentRegion, - MachineBasicBlock::iterator &NextMI, - MachineBasicBlock::iterator &ToThisBBEnd, - MachineBasicBlock::iterator &FromThisBBEnd, bool PathInRegion = true); - - // Try to move MI into existing bundle. - bool MoveMItoBundle(BasicBlockRegion *CurrentRegion, - MachineBasicBlock::instr_iterator &InstrToMove, - MachineBasicBlock::iterator &NextMI, - MachineBasicBlock::iterator &TargetPacket, - MachineBasicBlock::iterator &SourceLocation, - std::vector &backtrack, - bool MovingDependentOp, bool PathInRegion); - - // Insert temporary MI copy into MBB. - MachineBasicBlock::instr_iterator - insertTempCopy(MachineBasicBlock *MBB, - MachineBasicBlock::iterator &TargetPacket, MachineInstr *MI, - bool DeleteOldCopy); - - MachineBasicBlock::instr_iterator - findInsertPositionInBundle(MachineBasicBlock::iterator &Bundle, - MachineInstr *MI, bool &LastInBundle); - - bool NeedToNewify(MachineBasicBlock::instr_iterator NewMI, unsigned *DepReg, - MachineInstr *TargetPacket); - - bool CanNewifiedBeUsedInBundle(MachineBasicBlock::instr_iterator NewMI, - unsigned DepReg, MachineInstr *TargetPacket); - - void addInstructionToExistingBundle(MachineBasicBlock *HomeBB, - MachineBasicBlock::instr_iterator &Head, - MachineBasicBlock::instr_iterator &Tail, - MachineBasicBlock::instr_iterator &NewMI, - MachineBasicBlock::iterator &TargetPacket, - MachineBasicBlock::iterator &NextMI, - std::vector &backtrack); - - void removeInstructionFromExistingBundle( - MachineBasicBlock *HomeBB, MachineBasicBlock::instr_iterator &Head, - MachineBasicBlock::instr_iterator &Tail, - MachineBasicBlock::iterator &SourceLocation, - MachineBasicBlock::iterator &NextMI, bool MovingDependentOp, - std::vector &backtrack); - - // Check for conditional register operaton. - bool MIsCondAssign(MachineInstr *BMI, MachineInstr *MI, - SmallVector &Defs); - - // Test all the conditions required for instruction to be - // speculative. These are just required conditions, cost - // or benefit should be computed elsewhere. - bool canMIBeSpeculated(MachineInstr *MI, MachineBasicBlock *ToBB, - MachineBasicBlock *FromBB, - std::vector &backtrack); - - // See if this branch target belongs to the current region. - bool isBranchWithinRegion(BasicBlockRegion *CurrentRegion, MachineInstr *MI); - - // A collection of low level utilities. - bool MIsAreDependent(MachineInstr *MIa, MachineInstr *MIb); - bool MIsHaveTrueDependency(MachineInstr *MIa, MachineInstr *MIb); - bool canReorderMIs(MachineInstr *MIa, MachineInstr *MIb); - bool canCauseStall(MachineInstr *MI, MachineInstr *MJ); - bool canThisMIBeMoved(MachineInstr *MI, - MachineBasicBlock::iterator &WorkPoint, - bool &MovingDependentOp, int &Cost); - bool MIisDualJumpCandidate(MachineInstr *MI, - MachineBasicBlock::iterator &WorkPoint); - bool DemoteToDotOld(MachineInstr *MI); - bool isNewifiable(MachineBasicBlock::instr_iterator MII, unsigned DepReg, - MachineInstr *TargetPacket); - bool IsNewifyStore(MachineInstr *MI); - bool isJumpOutOfRange(MachineInstr *MI); - bool IsDualJumpFirstCandidate(MachineInstr *MI); - bool IsDualJumpFirstCandidate(MachineBasicBlock *MBB); - bool IsDualJumpFirstCandidate(MachineBasicBlock::iterator &TargetPacket); - bool IsNotDualJumpFirstCandidate(MachineInstr *MI); - bool isJumpOutOfRange(MachineInstr *UnCond, MachineInstr *Cond); - bool IsDualJumpSecondCandidate(MachineInstr *MI); - bool tryAllocateResourcesForConstExt(MachineInstr *MI, bool UpdateState); - bool isCompoundPair(MachineInstr *MIa, MachineInstr *MIb); - bool doesMIDefinesPredicate(MachineInstr *MI, SmallVector &Defs); - bool AnalyzeBBBranches(MachineBasicBlock *MBB, MachineBasicBlock *&TBB, - MachineInstr *&FirstTerm, MachineBasicBlock *&FBB, - MachineInstr *&SecondTerm); - inline bool multipleBranchesFromToBB(MachineBasicBlock *BB) const; -}; -} // namespace - -INITIALIZE_PASS_BEGIN(HexagonGlobalScheduler, "global-sched", - "Hexagon Global Scheduler", false, false) -INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass) -INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass) -INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) -INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfoWrapperPass) -INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfoWrapperPass) -INITIALIZE_PASS_END(HexagonGlobalScheduler, "global-sched", - "Hexagon Global Scheduler", false, false) - -/// HexagonGlobalSchedulerImpl Ctor. -HexagonGlobalSchedulerImpl::HexagonGlobalSchedulerImpl( - MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT, - AliasAnalysis *AA, const MachineBranchProbabilityInfo *MBPI, - const MachineBlockFrequencyInfo *MBFI, const MachineRegisterInfo *MRI, - const MachineFrameInfo &MFI, const HexagonRegisterInfo *QRI) - : HexagonPacketizerList(MF, MLI, AA, nullptr, false), PullUpRegions(0), - CurrentState((const HexagonInstrInfo *)TII), AA(AA), MBPI(MBPI), - MBFI(MBFI), MRI(MRI), MFI(MFI), QRI(QRI), MLI(MLI), MDT(MDT), - PacketSize(MF.getSubtarget().getSchedModel().IssueWidth) { - QII = (const HexagonInstrInfo *)TII; - Ext = BuildMI(MF, DebugLoc(), QII->get(Hexagon::A4_ext)); - Nop = BuildMI(MF, DebugLoc(), QII->get(Hexagon::A2_nop)); - TSchedModel.init(&MF.getSubtarget()); -} - -// Return bundle size without debug instructions. -static unsigned nonDbgBundleSize(MachineBasicBlock::iterator &TargetPacket) { - MachineBasicBlock::instr_iterator MII = TargetPacket.getInstrIterator(); - MachineBasicBlock::instr_iterator End = MII->getParent()->instr_end(); - unsigned count = 0; - for (++MII; MII != End && MII->isInsideBundle(); ++MII) { - if (MII->isDebugInstr()) - continue; - count++; - } - return count; -} - -/// The pass main entry point. -bool HexagonGlobalScheduler::runOnMachineFunction(MachineFunction &Fn) { - auto &HST = Fn.getSubtarget(); - if (DisablePullUp || !HST.usePackets() || skipFunction(Fn.getFunction())) - return false; - - const MachineRegisterInfo *MRI = &Fn.getRegInfo(); - const MachineFrameInfo &MFI = Fn.getFrameInfo(); - const HexagonRegisterInfo *QRI = HST.getRegisterInfo(); - MachineLoopInfo &MLI = getAnalysis().getLI(); - MachineDominatorTree &MDT = - getAnalysis().getDomTree(); - const MachineBranchProbabilityInfo *MBPI = - &getAnalysis().getMBPI(); - const MachineBlockFrequencyInfo *MBFI = - &getAnalysis().getMBFI(); - AliasAnalysis *AA = &getAnalysis().getAAResults(); - - // Preserve comounds if Opt Size. - const Function &F = Fn.getFunction(); - if (F.hasOptSize() && PreventCompoundSeparation.getNumOccurrences() == 0) - PreventCompoundSeparation = true; - - // Instantiate the Scheduler. - HexagonGlobalSchedulerImpl GlobalSchedulerState(Fn, MLI, MDT, AA, MBPI, MBFI, - MRI, MFI, QRI); - - // DFA state table should not be empty. - assert(GlobalSchedulerState.getResourceTracker() && "Empty DFA table!"); - - // Loop over all of the basic blocks. - // PullUp regions are basically traces with no side entrances. - // Might want to traverse BB by frequency. - GlobalSchedulerState.checkBundleCounts(Fn); - - // Pullup does not handle hazards yet. - if (!DisablePullUp.getPosition() && ForceNoopHazards) - return true; - - LLVM_DEBUG(GlobalSchedulerState.countCompounds(Fn)); - GlobalSchedulerState.GenUseDefChain(Fn); - GlobalSchedulerState.formPullUpRegions(Fn); - GlobalSchedulerState.performPullUp(); - GlobalSchedulerState.performPullUpCFG(Fn); - if (PostPullUpOpt) { - GlobalSchedulerState.formPullUpRegions(Fn); - GlobalSchedulerState.performExposedOptimizations(Fn); - } - LLVM_DEBUG(GlobalSchedulerState.countCompounds(Fn)); - - return true; -} - -/// Allocate resources (i.e. 4 bytes) for constant extender. If succeess, return -/// true, otherwise, return false. -bool HexagonGlobalSchedulerImpl::tryAllocateResourcesForConstExt( - MachineInstr *MI, bool UpdateState = true) { - if (ResourceTracker->canReserveResources(*Ext)) { - // We do not always want to change the state of ResourceTracker. - // When we do not want to change it, we need to test for additional - // corner cases. - if (UpdateState) - ResourceTracker->reserveResources(*Ext); - else if (CurrentPacketMIs.size() >= PacketSize - 1) - return false; - return true; - } - - return false; -} - -static bool IsSchedBarrier(const MachineInstr *MI) { - return MI->getOpcode() == Hexagon::Y2_barrier; -} - -static bool IsIndirectCall(const MachineInstr *MI) { - return MI->getOpcode() == Hexagon::J2_callr; -} - -#ifndef NDEBUG -static void DumpLinked(MachineInstr *MI) { - if (MI->isBundledWithPred()) - dbgs() << "^"; - else - dbgs() << " "; - if (MI->isBundledWithSucc()) - dbgs() << "v"; - else - dbgs() << " "; - MI->dump(); -} - -static void DumpPacket(MachineBasicBlock::instr_iterator MII) { - if (MII == MachineBasicBlock::instr_iterator()) { - dbgs() << "\tNULL\n"; - return; - } - MachineInstr *MI = &*MII; - MachineBasicBlock *MBB = MI->getParent(); - // Uninserted instruction. - if (!MBB) { - dbgs() << "\tUnattached: "; - DumpLinked(MI); - return; - } - dbgs() << "\t"; - DumpLinked(MI); - if (MI->isBundle()) { - MachineBasicBlock::instr_iterator MIE = MI->getParent()->instr_end(); - for (++MII; MII != MIE && MII->isInsideBundle() && !MII->isBundle(); - ++MII) { - dbgs() << "\t\t*"; - DumpLinked(&*MII); - } - } -} - -static void DumpPacket(MachineBasicBlock::instr_iterator MII, - MachineBasicBlock::instr_iterator BBEnd) { - if (MII == BBEnd) { - dbgs() << "\tBBEnd\n"; - return; - } - - DumpPacket(MII); -} -#endif - -static bool isBranch(MachineInstr *MI) { - if (MI->isBundle()) { - MachineBasicBlock::instr_iterator MII = MI->getIterator(); - MachineBasicBlock::instr_iterator MIE = MI->getParent()->instr_end(); - for (++MII; MII != MIE && MII->isInsideBundle() && !MII->isBundle(); - ++MII) { - if (MII->isBranch()) - return true; - } - } else - return MI->isBranch(); - return false; -} - -/// Any of those must not be first dual jump. Everything else is OK. -bool HexagonGlobalSchedulerImpl::IsNotDualJumpFirstCandidate(MachineInstr *MI) { - if (MI->isCall() || (MI->isBranch() && !QII->isPredicated(*MI)) || - MI->isReturn() || QII->isEndLoopN(MI->getOpcode())) - return true; - return false; -} - -/// These four functions clearly belong in HexagonInstrInfo.cpp. -/// Is this MI could be first dual jump instruction? -bool HexagonGlobalSchedulerImpl::IsDualJumpFirstCandidate(MachineInstr *MI) { - if (!PerformDualJumps) - return false; - if (MI->isBranch() && QII->isPredicated(*MI) && !QII->isNewValueJump(*MI) && - !MI->isIndirectBranch() && !QII->isEndLoopN(MI->getOpcode())) - return true; - // Missing loopN here, but not sure if there will be any benefit from it. - return false; -} - -/// This version covers the whole packet. -bool HexagonGlobalSchedulerImpl::IsDualJumpFirstCandidate( - MachineBasicBlock::iterator &TargetPacket) { - if (!PerformDualJumps) - return false; - MachineInstr *MI = &*TargetPacket; - - if (MI->isBundle()) { - // If this is a bundle, it must be the last bundle in BB. - if (&(*MI->getParent()->rbegin()) != MI) - return false; - - MachineBasicBlock::instr_iterator MII = MI->getIterator(); - MachineBasicBlock::instr_iterator BBEnd = MI->getParent()->instr_end(); - // If there is a control flow op in this packet, this is the case - // we look for, even if they are dependent on other members. - for (++MII; MII != BBEnd && MII->isInsideBundle() && !MII->isBundle(); - ++MII) - if (IsNotDualJumpFirstCandidate(&*MII)) - return false; - } else - return IsDualJumpFirstCandidate(MI); - - return true; -} - -/// This version cover whole BB. There could be a BB -/// with no control flow in it. In this case we can still pull-up a jump -/// into it. Negative proof. -bool HexagonGlobalSchedulerImpl::IsDualJumpFirstCandidate( - MachineBasicBlock *MBB) { - if (!PerformDualJumps) - return false; - - for (MachineBasicBlock::instr_iterator MII = MBB->instr_begin(), - MBBEnd = MBB->instr_end(); - MII != MBBEnd; ++MII) { - MachineInstr *MI = &*MII; - if (MI->isDebugInstr()) - continue; - if (!MI->isBundle() && IsNotDualJumpFirstCandidate(MI)) - return false; - } - return true; -} - -/// Is this MI could be second dual jump instruction? -bool HexagonGlobalSchedulerImpl::IsDualJumpSecondCandidate(MachineInstr *MI) { - if (!PerformDualJumps) - return false; - if ((MI->isBranch() && !QII->isNewValueJump(*MI) && !MI->isIndirectBranch() && - !QII->isEndLoopN(MI->getOpcode())) || - (MI->isCall() && !IsIndirectCall(MI))) - return true; - return false; -} - -// Since we have no exact knowledge of code layout, -// allow some safety buffer for jump target. -// This is measured in bytes. -static const unsigned SafetyBuffer = 200; - -static MachineBasicBlock::instr_iterator -getHexagonFirstInstrTerminator(MachineBasicBlock *MBB) { - MachineBasicBlock::instr_iterator MIB = MBB->instr_begin(); - MachineBasicBlock::instr_iterator MIE = MBB->instr_end(); - MachineBasicBlock::instr_iterator MII = MIB; - while (MII != MIE) { - if (!MII->isBundle() && MII->isTerminator()) - return MII; - ++MII; - } - return MIE; -} - -/// Check if a given instruction is: -/// - a jump to a distant target -/// - that exceeds its immediate range -/// If both conditions are true, it requires constant extension. -bool HexagonGlobalSchedulerImpl::isJumpOutOfRange(MachineInstr *MI) { - if (!MI || !MI->isBranch()) - return false; - MachineBasicBlock *MBB = MI->getParent(); - auto FirstTerm = getHexagonFirstInstrTerminator(MBB); - if (FirstTerm == MBB->instr_end()) - return false; - - unsigned InstOffset = BlockToInstOffset[MBB]; - unsigned Distance = 0; - MachineBasicBlock::instr_iterator FTMII = FirstTerm; - - // To save time, estimate exact position of a branch instruction - // as one at the end of the MBB. - // Number of instructions times typical instruction size. - InstOffset += (QII->nonDbgBBSize(MBB) * HEXAGON_INSTR_SIZE); - - MachineBasicBlock *TBB = NULL, *FBB = NULL; - SmallVector Cond; - - // Try to analyze this branch. - if (QII->analyzeBranch(*MBB, TBB, FBB, Cond, false)) { - // Could not analyze it. See if this is something we can recognize. - // If it is a NVJ, it should always have its target in - // a fixed location. - if (QII->isNewValueJump(*FirstTerm)) - TBB = FirstTerm->getOperand(QII->getCExtOpNum(*FirstTerm)).getMBB(); - } - if (TBB && (MI == &*FirstTerm)) { - Distance = - (unsigned)std::abs((long long)InstOffset - BlockToInstOffset[TBB]) + - SafetyBuffer; - LLVM_DEBUG(dbgs() << "\tFirst term offset(" << Distance << "): "; - FirstTerm->dump()); - return !QII->isJumpWithinBranchRange(*FirstTerm, Distance); - } - if (FBB) { - // Look for second terminator. - FTMII++; - MachineInstr *SecondTerm = &*FTMII; - assert(FTMII != MBB->instr_end() && - (SecondTerm->isBranch() || SecondTerm->isCall()) && - "Bad second terminator"); - if (MI != SecondTerm) - return false; - // Analyze the second branch in the BB. - Distance = - (unsigned)std::abs((long long)InstOffset - BlockToInstOffset[FBB]) + - SafetyBuffer; - LLVM_DEBUG(dbgs() << "\tSecond term offset(" << Distance << "): "; - FirstTerm->dump()); - return !QII->isJumpWithinBranchRange(*SecondTerm, Distance); - } - return false; -} - -/// Returns true if an instruction can be promoted to .new predicate -/// or new-value store. -/// Performs implicit version checking. -bool HexagonGlobalSchedulerImpl::isNewifiable( - MachineBasicBlock::instr_iterator MII, unsigned DepReg, - MachineInstr *TargetPacket) { - MachineInstr *MI = &*MII; - if (QII->isDotNewInst(*MI) || - !CanNewifiedBeUsedInBundle(MII, DepReg, TargetPacket)) - return false; - return (QII->isPredicated(*MI) && QII->getDotNewPredOp(*MI, nullptr) > 0) || - QII->mayBeNewStore(*MI); -} - -bool HexagonGlobalSchedulerImpl::DemoteToDotOld(MachineInstr *MI) { - int NewOpcode = QII->getDotOldOp(*MI); - MI->setDesc(QII->get(NewOpcode)); - return true; -} - -// initPacketizerState - Initialize packetizer flags -void HexagonGlobalSchedulerImpl::initPacketizerState(void) { - CurrentPacketMIs.clear(); - return; -} - -// ignorePseudoInstruction - Ignore bundling of pseudo instructions. -bool HexagonGlobalSchedulerImpl::ignoreInstruction(MachineInstr *MI) { - if (MI->isDebugInstr()) - return true; - - // We must print out inline assembly - if (MI->isInlineAsm()) - return false; - - // We check if MI has any functional units mapped to it. - // If it doesn't, we ignore the instruction. - const MCInstrDesc &TID = MI->getDesc(); - unsigned SchedClass = TID.getSchedClass(); - const InstrStage *IS = - ResourceTracker->getInstrItins()->beginStage(SchedClass); - unsigned FuncUnits = IS->getUnits(); - return !FuncUnits; -} - -// isSoloInstruction: - Returns true for instructions that must be -// scheduled in their own packet. -bool HexagonGlobalSchedulerImpl::isSoloInstruction(const MachineInstr &MI) { - if (MI.isInlineAsm()) - return true; - - if (MI.isEHLabel()) - return true; - - // From Hexagon V4 Programmer's Reference Manual 3.4.4 Grouping constraints: - // trap, pause, barrier, icinva, isync, and syncht are solo instructions. - // They must not be grouped with other instructions in a packet. - if (IsSchedBarrier(&MI)) - return true; - - if (MI.getOpcode() == Hexagon::A2_nop) - return true; - - return false; -} - -/// Return region ptr or null if non found. -BasicBlockRegion *HexagonGlobalSchedulerImpl::getRegionForMBB( - std::vector &Regions, MachineBasicBlock *MBB) { - for (std::vector::iterator I = Regions.begin(), - E = Regions.end(); - I != E; ++I) { - if ((*I)->findMBB(MBB)) - return *I; - } - return NULL; -} - -/// Select best candidate to form regions. -static inline bool selectBestBB(BlockFrequency &BBaFreq, unsigned BBaSize, - BlockFrequency &BBbFreq, unsigned BBbSize) { - if (BBaFreq.getFrequency() > BBbFreq.getFrequency()) - return true; - // TODO: This needs fine tuning. - // if (BBaSize < BBbSize) - // return true; - if (BBaFreq.getFrequency() == BBbFreq.getFrequency()) - return true; - return false; -} - -/// Returns BB pointer if one of MBB successors should be added to the -/// current PullUp Region, NULL otherwise. -/// If SecondBest is defined, get next one after Best match. -/// Most of the time, since we practically always have only two successors, -/// this is "the other" BB successor which still matches original -/// selection criterion. -MachineBasicBlock * -HexagonGlobalSchedulerImpl::getNextPURBB(MachineBasicBlock *MBB, - bool SecondBest = false) { - if (!MBB) - return NULL; - - BlockFrequency BestBlockFreq = BlockFrequency(0); - unsigned BestBlockSize = 0; - MachineBasicBlock *BestBB = NULL; - MachineBasicBlock *SecondBestBB = NULL; - - // Catch single BB loops. - for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), - SE = MBB->succ_end(); - SI != SE; ++SI) - if (*SI == MBB) - return NULL; - - // Iterate through successors to MBB. - for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), - SE = MBB->succ_end(); - SI != SE; ++SI) { - BlockFrequency BlockFreq = MBFI->getBlockFreq(*SI); - - LLVM_DEBUG(dbgs() << "\tsucc BB(" << (*SI)->getNumber() << ") freq(" - << BlockFreq.getFrequency() << ")"); - - if (!SecondBest && getRegionForMBB(PullUpRegions, *SI)) - continue; - - // If there is more then one predecessor to this block, do not include it. - // It means there is a side entrance to it. - if (std::next((*SI)->pred_begin()) != (*SI)->pred_end()) - continue; - - // If this block is a target of an indirect branch, it should - // also not be included. - if ((*SI)->isEHPad() || (*SI)->hasAddressTaken()) - continue; - - // Get BB edge frequency. - BlockFrequency EdgeFreq = BlockFreq * MBPI->getEdgeProbability(MBB, *SI); - LLVM_DEBUG(dbgs() << "\tedge with freq(" << EdgeFreq.getFrequency() - << ")\n"); - - if (selectBestBB(EdgeFreq, QII->nonDbgBBSize(*SI), BestBlockFreq, - BestBlockSize)) { - BestBlockFreq = EdgeFreq; - BestBlockSize = QII->nonDbgBBSize(*SI); - SecondBestBB = BestBB; - BestBB = *SI; - } else if (!SecondBestBB) { - SecondBestBB = *SI; - } - } - if (SecondBest) - return SecondBestBB; - else - return BestBB; -} - -/// Form region to perform pull-up. -bool HexagonGlobalSchedulerImpl::formPullUpRegions(MachineFunction &Fn) { - const Function &F = Fn.getFunction(); - // Check for single-block functions and skip them. - if (std::next(F.begin()) == F.end()) - return false; - - // Compute map for BB distances. - // Offset of the current instruction from the start. - unsigned InstOffset = 0; - - LLVM_DEBUG(dbgs() << "****** Form PullUpRegions **************\n"); - // Loop over all basic blocks. - // PullUp regions are basically traces with no side entrances. - for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); MBB != MBBe; - ++MBB) { - if (MBB->getAlignment() > llvm::Align(1)) { - // Although we don't know the exact layout of the final code, we need - // to account for alignment padding somehow. This heuristic pads each - // aligned basic block according to the alignment value. - int ByteAlign = MBB->getAlignment().value() - 1; - InstOffset = (InstOffset + ByteAlign) & ~(ByteAlign); - } - // Remember BB layout offset. - BlockToInstOffset[&*MBB] = InstOffset; - for (MachineBasicBlock::instr_iterator MII = MBB->instr_begin(), - MIE = MBB->instr_end(); - MII != MIE; ++MII) - if (!MII->isBundle()) - InstOffset += QII->getSize(*MII); - - // If this BB is already in a region, move on. - if (getRegionForMBB(PullUpRegions, &*MBB)) - continue; - - LLVM_DEBUG(dbgs() << "\nRoot BB(" << MBB->getNumber() << ") name(" - << MBB->getName() << ") size(" << QII->nonDbgBBSize(&*MBB) - << ") freq(" << printBlockFreq(*MBFI, *MBB) - << ") pred_size(" << MBB->pred_size() << ") in_func(" - << MBB->getParent()->getFunction().getName() << ")\n"); - - BasicBlockRegion *PUR = new BasicBlockRegion(TII, QRI, &*MBB); - PullUpRegions.push_back(PUR); - - for (MachineBasicBlock *MBBR = getNextPURBB(&*MBB); MBBR; - MBBR = getNextPURBB(MBBR)) { - LLVM_DEBUG(dbgs() << "Add BB(" << MBBR->getNumber() << ") name(" - << MBBR->getName() << ") size(" - << QII->nonDbgBBSize(MBBR) << ") freq(" - << printBlockFreq(*MBFI, *MBBR) << ") in_func(" - << MBBR->getParent()->getFunction().getName() << ")\n"); - PUR->addBBtoRegion(MBBR); - } - } - return true; -} - -/// Return true if MI is an instruction we are unable to reason about -/// (like something with unmodeled memory side effects). -static inline bool isGlobalMemoryObject(MachineInstr *MI) { - if (MI->hasUnmodeledSideEffects() || MI->hasOrderedMemoryRef() || - MI->isCall() || - (MI->getOpcode() == Hexagon::J2_jump && !MI->getOperand(0).isMBB())) - return true; - return false; -} - -// This MI might have either incomplete info, or known to be unsafe -// to deal with (i.e. volatile object). -static inline bool isUnsafeMemoryObject(MachineInstr *MI) { - if (!MI || MI->memoperands_empty()) - return true; - - // We purposefully do no check for hasOneMemOperand() here - // in hope to trigger an assert downstream in order to - // finish implementation. - if ((*MI->memoperands_begin())->isVolatile() || MI->hasUnmodeledSideEffects()) - return true; - - if (!(*MI->memoperands_begin())->getValue()) - return true; - - return false; -} - -/// This returns true if the two MIs could be memory dependent. -static bool MIsNeedChainEdge(AliasAnalysis *AA, const TargetInstrInfo *TII, - MachineInstr *MIa, MachineInstr *MIb) { - // Cover a trivial case - no edge is need to itself. - if (MIa == MIb) - return false; - - if (TII->areMemAccessesTriviallyDisjoint(*MIa, *MIb)) - return false; - - if (isUnsafeMemoryObject(MIa) || isUnsafeMemoryObject(MIb)) - return true; - - // If we are dealing with two "normal" loads, we do not need an edge - // between them - they could be reordered. - if (!MIa->mayStore() && !MIb->mayStore()) - return false; - - // To this point analysis is generic. From here on we do need AA. - if (!AA) - return true; - - MachineMemOperand *MMOa = *MIa->memoperands_begin(); - MachineMemOperand *MMOb = *MIb->memoperands_begin(); - - // TODO: Need to handle multiple memory operands. - // if either instruction has more than one memory operand, punt. - if (!(MIa->hasOneMemOperand() && MIb->hasOneMemOperand())) - return true; - - if (!MMOa->getSize().hasValue() || !MMOb->getSize().hasValue()) - return true; - - assert((MMOa->getOffset() >= 0) && "Negative MachineMemOperand offset"); - assert((MMOb->getOffset() >= 0) && "Negative MachineMemOperand offset"); - assert((MMOa->getSize().hasValue() && MMOb->getSize().hasValue()) && - "Size 0 memory access"); - - // If the base address of the two memoperands is the same. For instance, - // x and x+4, then we can easily reason about them using the offset and size - // of access. - if (MMOa->getValue() == MMOb->getValue()) { - if (MMOa->getOffset() > MMOb->getOffset()) { - uint64_t offDiff = MMOa->getOffset() - MMOb->getOffset(); - return !(MMOb->getSize().getValue() <= offDiff); - } else if (MMOa->getOffset() < MMOb->getOffset()) { - uint64_t offDiff = MMOb->getOffset() - MMOa->getOffset(); - return !(MMOa->getSize().getValue() <= offDiff); - } - // MMOa->getOffset() == MMOb->getOffset() - return true; - } - - int64_t MinOffset = std::min(MMOa->getOffset(), MMOb->getOffset()); - int64_t Overlapa = MMOa->getSize().getValue() + MMOa->getOffset() - MinOffset; - int64_t Overlapb = MMOb->getSize().getValue() + MMOb->getOffset() - MinOffset; - - AliasResult AAResult = - AA->alias(MemoryLocation(MMOa->getValue(), Overlapa, MMOa->getAAInfo()), - MemoryLocation(MMOb->getValue(), Overlapb, MMOb->getAAInfo())); - - return (AAResult != AliasResult::NoAlias); -} - -/// Gather register def/uses from MI. -/// This treats possible (predicated) defs -/// as actually happening ones (conservatively). -static inline void parseOperands(MachineInstr *MI, - SmallVector &Defs, - SmallVector &Uses) { - Defs.clear(); - Uses.clear(); - - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - - if (MO.isReg()) { - unsigned Reg = MO.getReg(); - if (!Reg) - continue; - assert(Register::isPhysicalRegister(Reg)); - if (MO.isUse()) - Uses.push_back(MO.getReg()); - if (MO.isDef()) - Defs.push_back(MO.getReg()); - } else if (MO.isRegMask()) { - for (unsigned R = 1, NR = Hexagon::NUM_TARGET_REGS; R != NR; ++R) - if (MO.clobbersPhysReg(R)) - Defs.push_back(R); - } - } -} - -void HexagonGlobalSchedulerImpl::MIUseDefSet(MachineInstr *MI, - std::vector &Defs, - std::vector &Uses) { - Defs.clear(); - Uses.clear(); - assert(!MI->isBundle() && "Cannot parse regs of a bundle."); - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - - if (MO.isReg()) { - unsigned Reg = MO.getReg(); - if (!Reg) - continue; - assert(Register::isPhysicalRegister(Reg)); - std::vector &Refs = MO.isUse() ? Uses : Defs; - for (MCRegAliasIterator AI(MO.getReg(), QRI, true); AI.isValid(); ++AI) - Refs.push_back(*AI); - } else if (MO.isRegMask()) { - for (unsigned R = 1, NR = Hexagon::NUM_TARGET_REGS; R != NR; ++R) - if (MO.clobbersPhysReg(R)) - Defs.push_back(R); - } - } -} - -/// Some apparent dependencies are not actually restricting us since there -/// is a delay between assignment and actual usage, like in case of a call. -/// There could be more cases here, but this one seems the most obvious. -static bool isDelayedUseException(MachineInstr *MIa, MachineInstr *MIb) { - if (MIa->isCall() && !MIb->isCall()) - return true; - if (!MIa->isCall() && MIb->isCall()) - return true; - return false; -} - -/// This is a check for resources availability and dependency -/// for an MI being tried for an existing bundle. -/// This is needed because we can: -/// - save time by filtering out trivial cases -/// - we want to reuse infrastructure that does not really knows -/// how to deal with parallel semantics of a bundle that already -/// exists. For instance, the following case: -/// SI %R6 = L2_ploadrif_io %P0, %R7, 4; -/// SJ %R6 = A2_tfr %R0; -/// will be happily allowed by isLegalToPacketizeTogether since in serial -/// semantics it never happens, and even if it does, it is legal. Not so -/// for when we __speculatively__ trying and MI for a bundle. -/// -/// Note: This is not equivalent to MIsAreDependent(). -/// MIsAreDependent only understands serial semantics. -/// These are OK to packetize together: -/// %R0 = L2_loadri_io %R18, 76; mem:LD4[%sunkaddr226](tbaa=!"int") -/// %R2 = ASL %R0, 3; flags: Inside bundle -/// -bool HexagonGlobalSchedulerImpl::canAddMIToThisPacket( - MachineInstr *MI, - SmallVector &Bundle) { - if (!MI) - return false; - LLVM_DEBUG(dbgs() << "\n\t[canAddMIToThisPacket]: "; MI->dump()); - - // Const extenders need custom resource checking... - // Should be OK if we can update the check everywhere. - if ((QII->isConstExtended(*MI) || QII->isExtended(*MI) || - isJumpOutOfRange(MI)) && - !tryAllocateResourcesForConstExt(MI, false)) - return false; - - // Ask DFA if machine resource is available for MI. - if (!ResourceTracker->canReserveResources(*MI) || !shouldAddToPacket(*MI)) { - LLVM_DEBUG(dbgs() << "\tNo DFA resources.\n"); - return false; - } - - SmallVector BundleDefs; - SmallVector BundleUses; - SmallVector Defs; - SmallVector Uses; - MachineInstr *FirstCompound = NULL, *SecondCompound = NULL; - MachineInstr *FirstDuplex = NULL, *SecondDuplex = NULL; - - parseOperands(MI, Defs, Uses); - for (SmallVector::iterator - BI = Bundle.begin(), - BE = Bundle.end(); - BI != BE; ++BI) { - BundleDefs.clear(); - BundleUses.clear(); - parseOperands(*BI, BundleDefs, BundleUses); - - MachineInstr *Inst1 = *BI; - MachineInstr *Inst2 = MI; - - if (Inst1->getParent() && OneFloatPerPacket && QII->isFloat(*Inst1) && - QII->isFloat(*Inst2)) - return false; - - if (Inst1->getParent() && OneComplexPerPacket && QII->isComplex(*Inst1) && - QII->isComplex(*Inst2)) - return false; - - if (PreventCompoundSeparation) - if (QII->getCompoundCandidateGroup(**BI)) { - if (!FirstCompound) - FirstCompound = *BI; - else { - SecondCompound = *BI; - if (isCompoundPair(FirstCompound, SecondCompound)) { - if (MI->mayLoad() || MI->mayStore()) { - LLVM_DEBUG(dbgs() << "\tPrevent compound destruction.\n"); - return false; - } - } - } - } - if (PreventDuplexSeparation) - if (QII->getDuplexCandidateGroup(**BI)) { - if (!FirstDuplex) - FirstDuplex = *BI; - else { - SecondDuplex = *BI; - if (QII->isDuplexPair(*FirstDuplex, *SecondDuplex)) { - if (MI->mayLoad() || MI->mayStore()) { - LLVM_DEBUG(dbgs() << "\tPrevent duplex destruction.\n"); - return false; - } - } - } - } - - for (unsigned i = 0; i < Defs.size(); i++) { - // Check for multiple definitions in the same packet. - for (unsigned j = 0; j < BundleDefs.size(); j++) - // Multiple defs in the same packet. - // Calls are OK here. - // Also if we have multiple defs of PC, this simply means we are - // dealing with dual jumps. - if (AliasingRegs(Defs[i], BundleDefs[j]) && - !isDelayedUseException(MI, *BI) && - !(IsDualJumpFirstCandidate(*BI) && IsDualJumpSecondCandidate(MI))) { - LLVM_DEBUG(dbgs() << "\tMultiple defs.\n\t"; MI->dump(); - dbgs() << "\t"; (*BI)->dump()); - return false; - } - - // See if we are creating a swap case as we go, and disallow - // it for now. - // Also, this is not OK: - // if (!p0) r7 = r5 - // if (!p0) r5 = #0 - // But this is fine: - // if (!p0) r7 = r5 - // if (p0) r5 = #0 - // Aslo - this is not a swap, but an opportunity to newify: - // %P1 = C2_cmpeqi %R0, 0; flags: - // %R0 = L2_ploadrif_io %P1, %R29, 8; - // TODO: Handle this. - for (unsigned j = 0; j < BundleUses.size(); j++) - if (AliasingRegs(Defs[i], BundleUses[j])) { - for (unsigned k = 0; k < BundleDefs.size(); k++) - for (unsigned l = 0; l < Uses.size(); l++) { - if (AliasingRegs(BundleDefs[k], Uses[l]) && - !isDelayedUseException(MI, *BI)) { - LLVM_DEBUG(dbgs() << "\tSwap detected:\n\t"; MI->dump(); - dbgs() << "\t"; (*BI)->dump()); - return false; - } - } - } - } - - for (unsigned i = 0; i < Uses.size(); i++) { - // Check for true data dependency. - for (unsigned j = 0; j < BundleDefs.size(); j++) - if (AliasingRegs(Uses[i], BundleDefs[j]) && - !isDelayedUseException(MI, *BI)) { - LLVM_DEBUG(dbgs() << "\tImmediate Use detected on reg(" - << printReg(Uses[i], QRI) << ")\n\t"; - MI->dump(); dbgs() << "\t"; (*BI)->dump()); - // TODO: This could be an opportunity for newifying: - // %P0 = C2_cmpeqi %R26, 0 - // %R26 = A2_tfr %R0 - // if (CanPromoteToDotNew(MI, Uses[i])) - // LLVM_DEBUG(dbgs() << "\tCan promoto to .new form.\n"); - // else - return false; - } - } - - // For calls we also check callee save regs. - if ((*BI)->isCall()) { - for (const uint16_t *I = QRI->getCalleeSavedRegs(&MF); *I; ++I) { - for (unsigned i = 0; i < Defs.size(); i++) { - if (AliasingRegs(Defs[i], *I)) { - LLVM_DEBUG(dbgs() << "\tAlias with call.\n"); - return false; - } - } - } - } - - // If this is return, we are probably speculating (otherwise - // we could not pull in there) and will not win from pulling - // into this location anyhow. - // Example: a side exit. - // if (!p0) dealloc_return - // TODO: Can check that we do not overwrite return value - // and proceed. - if ((*BI)->isBarrier()) { - LLVM_DEBUG(dbgs() << "\tBarrier interference.\n"); - return false; - } - - // \ref-manual (7.3.4) A loop setup packet in loopN or spNloop0 cannot - // contain a speculative indirect jump, - // a new-value compare jump or a dealloc_return. - // Speculative indirect jumps (predicate + .new + indirect): - // if ([!]Ps.new) jumpr:t Rs - // if ([!]Ps.new) jumpr:nt Rs - // @note: We don't want to pull across a call to be on the safe side. - if (QII->isLoopN(*MI) && - ((QII->isPredicated(**BI) && QII->isPredicatedNew(**BI) && - QII->isJumpR(**BI)) || - QII->isNewValueJump(**BI) || QII->isDeallocRet(**BI) || - (*BI)->isCall())) { - LLVM_DEBUG(dbgs() << "\tLoopN pull interference.\n"); - return false; - } - - // The opposite is also true. - if (QII->isLoopN(**BI) && - ((QII->isPredicated(*MI) && QII->isPredicatedNew(*MI) && - QII->isJumpR(*MI)) || - QII->isNewValueJump(*MI) || QII->isDeallocRet(*MI) || MI->isCall())) { - LLVM_DEBUG(dbgs() << "\tResident LoopN.\n"); - return false; - } - - // @todo \ref-manual 7.6.1 - // Presence of NVJ adds more restrictions. - if (QII->isNewValueJump(**BI) && - (MI->mayStore() || MI->getOpcode() == Hexagon::S2_allocframe || - MI->isCall())) { - LLVM_DEBUG(dbgs() << "\tNew val Jump.\n"); - return false; - } - - // For memory operations, check aliasing. - // First, be conservative on these objects. Might be overly constraining, - // so recheck. - if (isGlobalMemoryObject(*BI) || isGlobalMemoryObject(MI)) - // Currently it catches things like this: - // S2_storerinew_io %R29, 32, %R16 - // S2_storeri_io %R29, 68, %R0 - // which we can reason about. - // TODO: revisit. - return false; - - // If packet has a new-value store, MI can't be a store instruction. - if (QII->isNewValueStore(**BI) && MI->mayStore()) { - LLVM_DEBUG(dbgs() << "\tNew Value Store to store.\n"); - return false; - } - - if ((QII->isMemOp(**BI) && MI->mayStore()) || - (QII->isMemOp(*MI) && (*BI)->mayStore())) { - LLVM_DEBUG( - dbgs() << "\tSlot 0 not available for store because of memop.\n"); - return false; - } - - // If any of these is true, check aliasing. - if ((MI->mayLoad() && (*BI)->mayStore()) || - (MI->mayStore() && (*BI)->mayLoad()) || - (MI->mayStore() && (*BI)->mayStore())) { - if (MIsNeedChainEdge(AA, TII, MI, *BI)) { - LLVM_DEBUG(dbgs() << "\tAliasing detected:\n\t"; MI->dump(); - dbgs() << "\t"; (*BI)->dump()); - return false; - } - } - // Do not move an instruction to this packet if this packet - // already contains a speculated instruction. - std::map::iterator MIMoved; - MIMoved = SpeculatedIns.find(*BI); - if ((MIMoved != SpeculatedIns.end()) && - (MIMoved->second != (*BI)->getParent())) { - LLVM_DEBUG( - dbgs() << "This packet already contains a speculated instruction"; - (*BI)->dump();); - return false; - } - } - - // Do not pull-up vector instructions because these instructions have - // multi-cycle latencies, and the pull-up pass doesn't correctly account - // for instructions that stall for more than one cycle. - if (QII->isHVXVec(*MI)) - return false; - - return true; -} - -/// Test is true if the two MIs cannot be safely reordered. -bool HexagonGlobalSchedulerImpl::ReorderDependencyTest(MachineInstr *MIa, - MachineInstr *MIb) { - SmallVector DefsA; - SmallVector DefsB; - SmallVector UsesA; - SmallVector UsesB; - - parseOperands(MIa, DefsA, UsesA); - parseOperands(MIb, DefsB, UsesB); - - for (SmallVector::iterator IDA = DefsA.begin(), - IDAE = DefsA.end(); - IDA != IDAE; ++IDA) { - for (SmallVector::iterator IUB = UsesB.begin(), - IUBE = UsesB.end(); - IUB != IUBE; ++IUB) - // True data dependency. - if (AliasingRegs(*IDA, *IUB)) - return true; - - for (SmallVector::iterator IDB = DefsB.begin(), - IDBE = DefsB.end(); - IDB != IDBE; ++IDB) - // Output dependency. - if (AliasingRegs(*IDA, *IDB)) - return true; - } - - for (SmallVector::iterator IDB = DefsB.begin(), - IDBE = DefsB.end(); - IDB != IDBE; ++IDB) { - for (SmallVector::iterator IUA = UsesA.begin(), - IUAE = UsesA.end(); - IUA != IUAE; ++IUA) - // True data dependency. - if (AliasingRegs(*IDB, *IUA)) - return true; - } - - // Do not reorder two calls... - if (MIa->isCall() && MIb->isCall()) - return true; - - // For calls we also check callee save regs. - if (MIa->isCall()) - for (const uint16_t *I = QRI->getCalleeSavedRegs(&MF); *I; ++I) { - for (unsigned i = 0; i < DefsB.size(); i++) { - if (AliasingRegs(DefsB[i], *I)) - return true; - } - } - - if (MIb->isCall()) - for (const uint16_t *I = QRI->getCalleeSavedRegs(&MF); *I; ++I) { - for (unsigned i = 0; i < DefsA.size(); i++) { - if (AliasingRegs(DefsA[i], *I)) - return true; - } - } - - // For memory operations, check aliasing. - // First, be conservative on these objects. - // Might be overly constraining, so recheck. - if ((isGlobalMemoryObject(MIa)) || (isGlobalMemoryObject(MIb))) - return true; - - // If any of these is true, check aliasing. - if (((MIa->mayLoad() && MIb->mayStore()) || - (MIa->mayStore() && MIb->mayLoad()) || - (MIa->mayStore() && MIb->mayStore())) && - MIsNeedChainEdge(AA, TII, MIa, MIb)) - return true; - - return false; -} - -/// Serial semantics. -bool HexagonGlobalSchedulerImpl::MIsAreDependent(MachineInstr *MIa, - MachineInstr *MIb) { - if (MIa == MIb) - return false; - - if (ReorderDependencyTest(MIa, MIb)) { - LLVM_DEBUG(dbgs() << "\t\t[MIsAreDependent]:\n\t\t"; MIa->dump(); - dbgs() << "\t\t"; MIb->dump()); - return true; - } - return false; -} - -/// Serial semantics. -bool HexagonGlobalSchedulerImpl::MIsHaveTrueDependency(MachineInstr *MIa, - MachineInstr *MIb) { - if (MIa == MIb) - return false; - - SmallVector DefsA; - SmallVector DefsB; - SmallVector UsesA; - SmallVector UsesB; - - parseOperands(MIa, DefsA, UsesA); - parseOperands(MIb, DefsB, UsesB); - - for (SmallVector::iterator IDA = DefsA.begin(), - IDAE = DefsA.end(); - IDA != IDAE; ++IDA) { - for (SmallVector::iterator IUB = UsesB.begin(), - IUBE = UsesB.end(); - IUB != IUBE; ++IUB) - // True data dependency. - if (AliasingRegs(*IDA, *IUB)) - return true; - } - return false; -} - -/// Sequential semantics. Can these two MIs be reordered? -/// Moving MIa from "behind" to "in front" of MIb. -bool HexagonGlobalSchedulerImpl::canReorderMIs(MachineInstr *MIa, - MachineInstr *MIb) { - if (!MIa || !MIb) - return false; - - // Within bundle semantics are parallel. - if (MIa->isBundle()) { - MachineBasicBlock::instr_iterator MII = MIa->getIterator(); - MachineBasicBlock::instr_iterator MIIE = MIa->getParent()->instr_end(); - for (++MII; MII != MIIE && MII->isInsideBundle(); ++MII) { - if (MII->isDebugInstr()) - continue; - if (MIsAreDependent(&*MII, MIb)) - return false; - } - return true; - } - return !MIsAreDependent(MIa, MIb); -} - -static inline bool MIMustNotBePulledUp(MachineInstr *MI) { - if (MI->isInlineAsm() || MI->isEHLabel() || IsSchedBarrier(MI)) - return true; - return false; -} - -static inline bool MIShouldNotBePulledUp(MachineInstr *MI) { - if (MI->isBranch() || MI->isReturn() || MI->isCall() || MI->isBarrier() || - MI->isTerminator() || MIMustNotBePulledUp(MI)) - return true; - return false; -} - -// Only approve dual jump candidate: -// It is a branch, and we move it to last packet of the target location. -bool HexagonGlobalSchedulerImpl::MIisDualJumpCandidate( - MachineInstr *MI, MachineBasicBlock::iterator &WorkPoint) { - if (!PerformDualJumps || !IsDualJumpSecondCandidate(MI) || - MIMustNotBePulledUp(MI) || ignoreInstruction(MI)) - return false; - - MachineBasicBlock *FromThisBB = MI->getParent(); - MachineBasicBlock *ToThisBB = WorkPoint->getParent(); - - LLVM_DEBUG(dbgs() << "\t\t[MIisDualJumpCandidate] To BB(" - << ToThisBB->getNumber() << ") From BB(" - << FromThisBB->getNumber() << ")\n"); - // If the question is about the same BB, we do not want to get - // dual jump involved - it is a different case. - if (FromThisBB == ToThisBB) - return false; - - // Dual jump could only be done on neigboring BBs. - // The FromThisBB must only have one predecessor - the basic - // block we are trying to merge. - if ((*(FromThisBB->pred_begin()) != ToThisBB) || - (std::next(FromThisBB->pred_begin()) != FromThisBB->pred_end())) - return false; - - // If this block is a target of an indirect branch, it should - // also not be included. - if (FromThisBB->isEHPad() || FromThisBB->hasAddressTaken()) - return false; - - // Now we must preserve original fall through paths. In fact we - // might be dealing with 3way branching. - MachineBasicBlock *ToTBB = NULL, *ToFBB = NULL; - - if (ToThisBB->succ_size() == 2) { - // Check the branch from target block. - // If we have two successors, we must understand the branch. - SmallVector ToCond; - if (!QII->analyzeBranch(*ToThisBB, ToTBB, ToFBB, ToCond, false)) { - // Have the branch. Check the topology. - LLVM_DEBUG(dbgs() << "\t\tToThisBB has two successors: TBB(" - << ToTBB->getNumber() << ") and FBB("; - if (ToFBB) dbgs() << ToFBB->getNumber() << ").\n"; - else dbgs() << "None" - << ").\n";); - if (ToTBB == FromThisBB) { - // If the from BB is not the fall through, we can only handle case - // when second branch is unconditional jump. - return false; - } else if (ToFBB == FromThisBB || !ToFBB) { - // If the fall through path of ToBB is our FromBB, we have more freedom - // of operation. - LLVM_DEBUG(dbgs() << "\t\tFall through jump target.\n"); - } - } else { - LLVM_DEBUG(dbgs() << "\t\tUnable to analyze first branch.\n"); - return false; - } - } else if (ToThisBB->succ_size() == 1) { - ToFBB = *ToThisBB->succ_begin(); - assert(ToFBB == FromThisBB && "Bad CFG layout"); - } else - return false; - - // First unbundled control flow instruction in the BB. - if (!MI->isBundled() && MI == &*FromThisBB->getFirstNonDebugInstr()) - return IsDualJumpFirstCandidate(WorkPoint); - - return false; -} - -// Check whether moving MI to MJ's packet would cause a stall from a previous -// packet. -bool HexagonGlobalSchedulerImpl::canCauseStall(MachineInstr *MI, - MachineInstr *MJ) { - SmallVector DefsMJI; - SmallVector UsesMJI; - SmallVector DefsMI; - SmallVector UsesMI; - parseOperands(MI, DefsMI, UsesMI); - - for (auto Use : UsesMI) { - int UseIdx = MI->findRegisterUseOperandIdx(Use, /*TRI=*/nullptr); - if (UseIdx == -1) - continue; - bool ShouldBreak = false; - int BundleCount = 0; - for (MachineBasicBlock::instr_iterator - Begin = MJ->getParent()->instr_begin(), - MJI = MJ->getIterator(); - MJI != Begin; --MJI) { - if (MJI->isBundle()) { - ++BundleCount; - continue; - } - parseOperands(&*MJI, DefsMJI, UsesMJI); - for (auto Def : DefsMJI) { - if (Def == Use || AliasingRegs(Def, Use)) { - int DefIdx = MJI->findRegisterDefOperandIdx(Def, /*TRI=*/nullptr); - if (DefIdx >= 0) { - int Latency = - TSchedModel.computeOperandLatency(&*MJI, DefIdx, MI, UseIdx); - if (Latency > BundleCount) - // There will be a stall if MI is moved to MJ's packet. - return true; - // We found the def for the use and it does not cause a stall. - // Continue checking the next use for a potential stall. - ShouldBreak = true; - break; - } - } - } - if (ShouldBreak) - break; - if (!MJI->isBundled() && !MJI->isDebugInstr()) - ++BundleCount; - } - } - return false; -} - -/// Analyze this instruction. If this is an unbundled instruction, see -/// if it in theory could be packetized. -/// If it is already part of a packet, see if it has internal -/// dependencies to this packet. -bool HexagonGlobalSchedulerImpl::canThisMIBeMoved( - MachineInstr *MI, MachineBasicBlock::iterator &WorkPoint, - bool &MovingDependentOp, int &Cost) { - if (!MI) - return false; - // By default, it is a normal move. - MovingDependentOp = false; - Cost = 0; - // If MI is a 'formed' compound not potential compound, bail out. - if (QII->isCompoundBranchInstr(*MI)) - return false; - // See if we can potentially break potential compound candidates, - // and do not do it. - if (PreventCompoundSeparation && MI->isBundled()) { - enum HexagonII::CompoundGroup MICG = QII->getCompoundCandidateGroup(*MI); - if (MICG != HexagonII::HCG_None) { - // Check internal dependencies in the bundle. - // First, find the bundle header. - MachineBasicBlock::instr_iterator MII = MI->getIterator(); - for (--MII; MII->isBundled(); --MII) - if (MII->isBundle()) - break; - - MachineBasicBlock::instr_iterator BBEnd = MI->getParent()->instr_end(); - for (++MII; MII != BBEnd && MII->isInsideBundle() && !MII->isBundle(); - ++MII) { - if (&(*MII) == MI) - continue; - if (isCompoundPair(&*MII, MI)) { - LLVM_DEBUG(dbgs() << "\tPrevent Compound separation.\n"); - return false; - } - } - } - } - // Same thing for duplex candidates. - if (PreventDuplexSeparation && MI->isBundled()) { - if (QII->getDuplexCandidateGroup(*MI) != HexagonII::HSIG_None) { - // Check internal dependencies in the bundle. - // First, find the bundle header. - MachineBasicBlock::instr_iterator MII = MI->getIterator(); - for (--MII; MII->isBundled(); --MII) - if (MII->isBundle()) - break; - - MachineBasicBlock::instr_iterator BBEnd = MI->getParent()->instr_end(); - for (++MII; MII != BBEnd && MII->isInsideBundle() && !MII->isBundle(); - ++MII) { - if ((&(*MII) != MI) && QII->isDuplexPair(*MII, *MI)) { - LLVM_DEBUG(dbgs() << "\tPrevent Duplex separation.\n"); - return false; - } - } - } - } - - // If we perform dual jump formation during the pull-up, - // then we want to consider several additional situations. - // a) Allow moving of dependent instruction from a packet - // b) Allow moving some control flow instructions if they meet - // dual jump criteria. - if (MIisDualJumpCandidate(MI, WorkPoint)) { - LLVM_DEBUG(dbgs() << "\t\tDual jump candidate:\t"; MI->dump()); - // Here we are breaking our general assumption about not moving dependent - // instructions. To save us two more expensive checks down the line, - // propagate the information directly. - MovingDependentOp = true; - return true; - } - - // Any of these should not even be tried. - if (MIShouldNotBePulledUp(MI) || ignoreInstruction(MI)) - return false; - // Pulling up these instructions could put them - // out of jump range/offset size. - if (QII->isLoopN(*MI)) { - unsigned dist_looplabel = - BlockToInstOffset.find(MI->getOperand(0).getMBB())->second; - unsigned dist_newloop0 = - BlockToInstOffset.find(WorkPoint->getParent())->second; - // Check if the jump in the last instruction is within range. - unsigned Distance = - (unsigned)std::abs((long long)dist_looplabel - dist_newloop0) + - QII->nonDbgBBSize(WorkPoint->getParent()) * 4 + SafetyBuffer; - const HexagonInstrInfo *HII = (const HexagonInstrInfo *)TII; - if (!HII->isJumpWithinBranchRange(*MI, Distance)) { - LLVM_DEBUG(dbgs() << "\nloopN cannot be moved since Distance: " - << Distance << " outside branch range.";); - return false; - } - LLVM_DEBUG(dbgs() << "\nloopN can be moved since Distance: " << Distance - << " within branch range.";); - } - // If the def-set of an MI is one of the live-ins then MI should - // kill that reg and no instruction before MI should use it. - // For simplicity, allow only if MI is the first instruction in the MBB. - std::map>::const_iterator DefIter = - MIDefSet.find(MI); - MachineBasicBlock *MBB = MI->getParent(); - for (unsigned i = 0; DefIter != MIDefSet.end() && i < DefIter->second.size(); - ++i) { - if (MBB->isLiveIn(DefIter->second[i]) && - &*MBB->getFirstNonDebugInstr() != MI) - return false; - } - // If it is part of a bundle, analyze it. - if (MI->isBundled()) { - // Cannot move bundle header itself. This function is about - // individual MI move. - if (MI->isBundle()) - return false; - - // Check internal dependencies in the bundle. - // First, find the bundle header. - MachineBasicBlock::instr_iterator MII = MI->getIterator(); - for (--MII; MII->isBundled(); --MII) - if (MII->isBundle()) - break; - - MachineBasicBlock::instr_iterator BBEnd = MI->getParent()->instr_end(); - for (++MII; MII != BBEnd && MII->isInsideBundle() && !MII->isBundle(); - ++MII) { - if (MII->isDebugInstr()) - continue; - if (MIsAreDependent(&*MII, MI)) { - if (!AllowDependentPullUp) { - LLVM_DEBUG(dbgs() << "\t\tDependent.\n"); - return false; - } else { - // There are a few cases that we can safely move a dependent - // instruction away from this packet. - // One example is an instruction setting a call operands. - if ((MII->isCall() && !IsIndirectCall(&*MII)) || - IsDualJumpSecondCandidate(&*MII) || MI->isBranch()) { - LLVM_DEBUG(dbgs() << "\t\tDependent, but allow to move.\n"); - MovingDependentOp = true; - Cost -= 10; - continue; - } else { - LLVM_DEBUG(dbgs() << "\t\tDependent, and do not allow for now.\n"); - return false; - } - } - } - } - } - return true; -} - -/// Return true if MI defines a predicate and parse all defs. -bool HexagonGlobalSchedulerImpl::doesMIDefinesPredicate( - MachineInstr *MI, SmallVector &Defs) { - bool defsPredicate = false; - Defs.clear(); - - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - - // Regmasks are considered "implicit". - if (!MO.isReg()) - continue; - unsigned Reg = MO.getReg(); - - if (!Reg || QRI->isFakeReg(Reg)) - continue; - - assert(Register::isPhysicalRegister(Reg)); - - if (MO.isDef() && !MO.isImplicit()) { - const TargetRegisterClass *RC = QRI->getMinimalPhysRegClass(Reg); - if (RC == &Hexagon::PredRegsRegClass) { - defsPredicate = true; - Defs.push_back(MO.getReg()); - } - } - } - return defsPredicate; -} - -/// We have just tentatively added a predicated MI to an existing packet. -/// Now we need to determine if it needs to be changed to .new form. -/// It only handles compare/predicate right now. -/// TODO - clean this logic up. -/// TODO - generalize to handle any .new -bool HexagonGlobalSchedulerImpl::NeedToNewify( - MachineBasicBlock::instr_iterator NewMI, unsigned *DepReg, - MachineInstr *TargetPacket = NULL) { - MachineBasicBlock::instr_iterator MII = NewMI; - SmallVector DefsA; - SmallVector DefsB; - SmallVector UsesB; - - // If this is not a normal bundle, we are probably - // trying to size two lonesome instructions together, - // and trying to say if one of them will need to be - // newified. In this is the case we have something like this: - // BB#5: - // %P0 = CMPGEri %R4, 2 - // S2_pstorerif_io %P0, %R29, 16, %R21 - // BUNDLE %R7, %R4, %R7 - parseOperands(&*NewMI, DefsB, UsesB); - if (TargetPacket && !TargetPacket->isBundled()) { - if (doesMIDefinesPredicate(TargetPacket, DefsA)) { - for (SmallVector::iterator IA = DefsA.begin(), - IAE = DefsA.end(); - IA != IAE; ++IA) - for (SmallVector::iterator IB = UsesB.begin(), - IBE = UsesB.end(); - IB != IBE; ++IB) - if (*IA == *IB) { - *DepReg = *IA; - return true; - } - } - return false; - } - - // Find bundle header. - for (--MII; MII->isBundled(); --MII) - if (MII->isBundle()) - break; - - // Iterate down, if there is data dependent cmp found, need to .newify. - // Also, we can have the following: - // { - // p0 = r7 - // if (!p0.new) jump:t .LBB4_18 - // if (p0.new) r8 = zxth(r12) - // } - MachineBasicBlock::instr_iterator BBEnd = MII->getParent()->instr_end(); - for (++MII; MII != BBEnd && MII->isBundled() && !MII->isBundle(); ++MII) { - if (MII == NewMI) - continue; - if (doesMIDefinesPredicate(&*MII, DefsA)) { - for (SmallVector::iterator IA = DefsA.begin(), - IAE = DefsA.end(); - IA != IAE; ++IA) - for (SmallVector::iterator IB = UsesB.begin(), - IBE = UsesB.end(); - IB != IBE; ++IB) - // We do not have multiple predicate regs defined in any instruction, - // if we ever will, this needs to be generalized. - if (*IA == *IB) { - *DepReg = *IA; - return true; - } - DefsA.clear(); - } - } - LLVM_DEBUG(dbgs() << "\nNo need to newify:"; NewMI->dump()); - return false; -} - -/// We know this instruction needs to be newified to be added to the packet, -/// but not all combinations are legal. -/// It is a complimentary check to NeedToNewify(). -/// The packet actually contains the new instruction during the check. -bool HexagonGlobalSchedulerImpl::CanNewifiedBeUsedInBundle( - MachineBasicBlock::instr_iterator NewMI, unsigned DepReg, - MachineInstr *TargetPacket) { - MachineBasicBlock::instr_iterator MII = NewMI; - if (!TargetPacket || !TargetPacket->isBundled()) - return true; - - // Find the bundle header. - for (--MII; MII->isBundled(); --MII) - if (MII->isBundle()) - break; - - MachineBasicBlock::instr_iterator BBEnd = MII->getParent()->instr_end(); - for (++MII; MII != BBEnd && MII->isBundled() && !MII->isBundle(); ++MII) { - // Effectively we look for the case of late predicates. - // No additional checks at the time. - if (MII == NewMI || !QII->isPredicateLate(MII->getOpcode())) - continue; - SmallVector DefsA; - if (!doesMIDefinesPredicate(&*MII, DefsA)) - continue; - for (auto &IA : DefsA) - if (IA == DepReg) - return false; - } - return true; -} - -/// setUsed - Set the register and its sub-registers as being used. -/// Similar to RegScavenger::setUsed(). -void HexagonGlobalSchedulerImpl::setUsedRegs(BitVector &Set, unsigned Reg) { - Set.reset(Reg); - for (MCSubRegIterator SubRegs(Reg, QRI); SubRegs.isValid(); ++SubRegs) - Set.reset(*SubRegs); -} - -/// Are these two registers overlaping? -bool HexagonGlobalSchedulerImpl::AliasingRegs(unsigned RegA, unsigned RegB) { - if (RegA == RegB) - return true; - - for (MCSubRegIterator SubRegs(RegA, QRI); SubRegs.isValid(); ++SubRegs) - if (RegB == *SubRegs) - return true; - - for (MCSubRegIterator SubRegs(RegB, QRI); SubRegs.isValid(); ++SubRegs) - if (RegA == *SubRegs) - return true; - - return false; -} - -/// Find use with this reg, and unmark the kill flag. -static inline void unmarkKillReg(MachineInstr *MI, unsigned Reg) { - if (MI->isDebugInstr()) - return; - - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - MachineOperand &MO = MI->getOperand(i); - - if (!MO.isReg()) - continue; - - if (MO.isKill() && (MO.getReg() == Reg)) - MO.setIsKill(false); - } -} - -/// Find use with this reg, and unmark the kill flag. -static inline void markKillReg(MachineInstr *MI, unsigned Reg) { - if (MI->isDebugInstr()) - return; - - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - MachineOperand &MO = MI->getOperand(i); - - if (!MO.isReg()) - continue; - - if (MO.isUse() && (MO.getReg() == Reg)) - MO.setIsKill(true); - } -} - -/// We have just moved an instruction that could have changed kill patterns -/// along the path it was moved. We need to update it. -void HexagonGlobalSchedulerImpl::updateKillAlongThePath( - MachineBasicBlock *HomeBB, MachineBasicBlock *OriginBB, - MachineBasicBlock::instr_iterator &Head, - MachineBasicBlock::instr_iterator &Tail, - MachineBasicBlock::iterator &SourcePacket, - MachineBasicBlock::iterator &TargetPacket, - std::vector &backtrack) { - // This is the instruction being moved. - MachineInstr *MI = &*Head; - MachineBasicBlock *CurrentBB = OriginBB; - SmallSet KilledUseSet; - - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - if (!MO.isReg()) - continue; - unsigned Reg = MO.getReg(); - if (!Reg) - continue; - - if (MO.isKill()) - KilledUseSet.insert(Reg); - } - - // If there are no kills here, we are done. - if (KilledUseSet.empty()) - return; - - LLVM_DEBUG(dbgs() << "\n[updateKillAlongThePath]\n"); - LLVM_DEBUG(dbgs() << "\t\tInstrToMove :\t"; MI->dump()); - LLVM_DEBUG(dbgs() << "\t\tSourceLocation:\n"; - DumpPacket(SourcePacket.getInstrIterator())); - LLVM_DEBUG(dbgs() << "\t\tTargetPacket :\n"; - DumpPacket(TargetPacket.getInstrIterator())); - LLVM_DEBUG(dbgs() << "\tUpdate Kills. Need to update (" << KilledUseSet.size() - << ")kills. From BB (" << OriginBB->getNumber() << ")\n"); - LLVM_DEBUG(dbgs() << "\tMove path:\n"); - assert(!backtrack.empty() && "Empty back track"); - - // We have pulled up an instruction, with one of its uses marked as kill. - // If there is any other use of the same register along the move path, - // and there are no side exits with killed register live-in along them, - // we need to mark last use of that reg as kill. - for (signed i = backtrack.size() - 1; i >= 0; --i) { - LLVM_DEBUG(dbgs() << "\t\t[" << i << "]BB(" - << backtrack[i]->getParent()->getNumber() << ")\t"; - backtrack[i]->dump()); - if (CurrentBB != backtrack[i]->getParent()) { - LLVM_DEBUG(dbgs() << "\t\tChange BB from (" << CurrentBB->getNumber() - << ") to(" << backtrack[i]->getParent()->getNumber() - << ")\n"); - for (MachineBasicBlock::const_succ_iterator - SI = backtrack[i]->getParent()->succ_begin(), - SE = backtrack[i]->getParent()->succ_end(); - SI != SE; ++SI) { - if (*SI == CurrentBB) - continue; - - LLVM_DEBUG(dbgs() << "\t\tSide Exit:\n\t"; (*SI)->dump()); - // If any reg kill is live along this side exit, it is not - // a kill any more. - for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(), - E = (*SI)->livein_end(); - I != E; ++I) { - if (KilledUseSet.count((*I).PhysReg)) { - LLVM_DEBUG(dbgs() << "\t\tReg (" << printReg((*I).PhysReg, QRI) - << ") is LiveIn along side exit.\n"); - KilledUseSet.erase((*I).PhysReg); - unmarkKillReg(MI, (*I).PhysReg); - } - if (KilledUseSet.empty()) - return; - } - } - CurrentBB = backtrack[i]->getParent(); - } - - // Done with the whole path. - if (backtrack[i] == &*TargetPacket) - return; - - // Starting the tracking. Do not update source bundle. - // If TargetPacket == SourcePacket we have returned - // in the previous check. - if (backtrack[i] == &*SourcePacket) - continue; - - // Ignore DBG_VALUE. - if (backtrack[i]->isDebugInstr()) - continue; - - // Encountered an intermediary bundle. Process it. - // Beware, sometimes check for backtrack[i] == TargetPacket - // does not work, so this instruction could be one from the target bundle. - SmallVector Defs; - SmallVector Uses; - MachineInstr *MIU = backtrack[i]; - parseOperands(MIU, Defs, Uses); - - for (SmallVector::iterator IA = Uses.begin(), IAE = Uses.end(); - IA != IAE; ++IA) { - if (KilledUseSet.count(*IA)) { - // Now this is new kill point for this Reg. - // Update the bundle, and any local uses. - markKillReg(MIU, *IA); - - // Unmark the current MI. - unmarkKillReg(MI, *IA); - - if (MIU->isBundle()) { - // TODO: Can do this cleaner and faster. - MachineBasicBlock::instr_iterator MII = MIU->getIterator(); - MachineBasicBlock::instr_iterator End = CurrentBB->instr_end(); - for (++MII; MII != End && MII->isInsideBundle(); ++MII) - markKillReg(&*MII, *IA); - } - - // We have updated this kill reg, if there are more, keep on going. - KilledUseSet.erase(*IA); - - // If the set is exhausted, just leave. - if (KilledUseSet.empty()) - return; - } - } - } -} - -/// This is houskeeping for bundle with instruction just added to it. -void HexagonGlobalSchedulerImpl::addInstructionToExistingBundle( - MachineBasicBlock *HomeBB, MachineBasicBlock::instr_iterator &Head, - MachineBasicBlock::instr_iterator &Tail, - MachineBasicBlock::instr_iterator &NewMI, - MachineBasicBlock::iterator &TargetPacket, - MachineBasicBlock::iterator &NextMI, - std::vector &backtrack) { - Tail = getBundleEnd(Head); - LLVM_DEBUG(dbgs() << "\t\t\t[Add] Head home: "; DumpPacket(Head)); - - // Old header to be deleted shortly. - MachineBasicBlock::instr_iterator Outcast = Head; - // Unbundle old header. - if (Outcast->isBundle() && Outcast->isBundledWithSucc()) - Outcast->unbundleFromSucc(); - - bool memShufDisabled = QII->getBundleNoShuf(*Outcast); - - // Create new bundle header and update MI flags. - finalizeBundle(*HomeBB, ++Head, Tail); - MachineBasicBlock::instr_iterator BundleMII = std::prev(Head); - if (memShufDisabled) - QII->setBundleNoShuf(BundleMII); - --Head; - - LLVM_DEBUG(dbgs() << "\t\t\t[Add] New Head : "; DumpPacket(Head)); - - // The old header could be listed in the back tracking, - // so if it is, we need to update it. - for (unsigned i = 0; i < backtrack.size(); ++i) - if (backtrack[i] == &*Outcast) - backtrack[i] = &*Head; - - // Same for top MI iterator. - if (NextMI == Outcast) - NextMI = Head; - - TargetPacket = Head; - HomeBB->erase(Outcast); -} - -/// This handles houskeeping for bundle with instruction just deleted from it. -/// We do not see the original moved instruction in here. -void HexagonGlobalSchedulerImpl::removeInstructionFromExistingBundle( - MachineBasicBlock *HomeBB, MachineBasicBlock::instr_iterator &Head, - MachineBasicBlock::instr_iterator &Tail, - MachineBasicBlock::iterator &SourceLocation, - MachineBasicBlock::iterator &NextMI, bool MovingDependentOp, - std::vector &backtrack) { - // Empty BBs will be deleted shortly. - if (HomeBB->empty()) { - Head = MachineBasicBlock::instr_iterator(); - Tail = MachineBasicBlock::instr_iterator(); - return; - } - - if (!SourceLocation->isBundle()) { - LLVM_DEBUG(dbgs() << "\t\t\tOriginal instruction was not bundled.\n\t\t\t"; - SourceLocation->dump()); - // If original instruction was not bundled, and we have moved it - // and it is in the back track, we probably want to remove it from there. - LLVM_DEBUG(dbgs() << "\t\t\t[Rem] New head: "; backtrack.back()->dump()); - - for (unsigned i = 0; i < backtrack.size(); ++i) { - if (backtrack[i] == &*SourceLocation) { - // By definition, this should be the last instruction in the backtrack. - assert((backtrack[i] == backtrack.back()) && "Lost back track"); - backtrack.pop_back(); - } - // Point the main iterator to the next instruction. - if (NextMI == SourceLocation) - NextMI++; - } - SourceLocation = MachineBasicBlock::iterator(); - Head = MachineBasicBlock::instr_iterator(); - Tail = MachineBasicBlock::instr_iterator(); - return; - } - - // The old header, soon to be deleted. - MachineBasicBlock::instr_iterator Outcast = SourceLocation.getInstrIterator(); - LLVM_DEBUG(dbgs() << "\t\t\t[Rem] SourceLocation after bundle update: "; - DumpPacket(Outcast)); - - // If bundle has been already destroyed. BB->splat seems to do it some times - // but not the other. - // We already know that SourceLocation is bundle header. - if (!SourceLocation->isBundledWithSucc()) { - assert(!Head->isBundledWithSucc() && !Head->isBundledWithPred() && - "Bad bundle"); - } else { - Head = SourceLocation.getInstrIterator(); - Tail = getBundleEnd(Head); - unsigned Size = 0; - unsigned BBSizeWithDbg = 0; - MachineBasicBlock::const_instr_iterator I(Head); - MachineBasicBlock::const_instr_iterator E = Head->getParent()->instr_end(); - - for (++I; I != E && I->isBundledWithPred(); ++I) { - ++BBSizeWithDbg; - if (!I->isDebugInstr()) - ++Size; - } - - LLVM_DEBUG(dbgs() << "\t\t\t[Rem] Size(" << Size << ") Head orig: "; - DumpPacket(Head)); - // The old header, soon to be deleted. - Outcast = Head; - - // The old Header is still counted here. - if (Size > 1) { - if (Outcast->isBundle() && Outcast->isBundledWithSucc()) - Outcast->unbundleFromSucc(); - - bool memShufDisabled = QII->getBundleNoShuf(*Outcast); - // The finalizeBundle() assumes that "original" sequence - // it is finalizing is sequentially correct. That basically - // means that swap case might not be handled properly. - // I find insert point for the pull-up instruction myself, - // and I should try to catch that swap case there, and refuse - // to insert if I cannot guarantee correct serial semantics. - // In the future, I need my own incremental "inserToBundle" - // function. - finalizeBundle(*HomeBB, ++Head, Tail); - MachineBasicBlock::instr_iterator BundleMII = std::prev(Head); - if (memShufDisabled) - QII->setBundleNoShuf(BundleMII); - - --Head; - } else if (Size == 1) { - // There is only one non-debug instruction in the bundle. - if (BBSizeWithDbg > 1) { - // There are some debug instructions that should be unbundled too. - MachineBasicBlock::instr_iterator I(Head); - MachineBasicBlock::instr_iterator E = Head->getParent()->instr_end(); - for (++I; I != E && I->isBundledWithPred(); ++I) { - I->unbundleFromPred(); - // Set Head to the non-debug instruction. - if (!I->isDebugInstr()) - Head = I; - } - } else { - // This means that only one original instruction is - // left in the bundle. We need to "unbundle" it because the - // rest of API will not like it. - ++Head; - if (Head->isBundledWithPred()) - Head->unbundleFromPred(); - if (Head->isBundledWithSucc()) - Head->unbundleFromSucc(); - } - } else - llvm_unreachable("Corrupt bundle"); - } - - LLVM_DEBUG(dbgs() << "\t\t\t[Rem] New Head : "; DumpPacket(Head)); - SourceLocation = Head; - - // The old header could be listed in the back tracking, - // so if it is, we need to update it. - for (unsigned i = 0; i < backtrack.size(); ++i) - if (backtrack[i] == &*Outcast) - backtrack[i] = &*Head; - - // Same for top MI iterator. - if (NextMI == Outcast) - NextMI = Head; - - HomeBB->erase(Outcast); -} - -#ifndef NDEBUG -static void debugLivenessForBB(const MachineBasicBlock *MBB, - const TargetRegisterInfo *TRI) { - LLVM_DEBUG(dbgs() << "\tLiveness for BB:\n"; MBB->dump()); - for (MachineBasicBlock::const_succ_iterator SI = MBB->succ_begin(), - SE = MBB->succ_end(); - SI != SE; ++SI) { - LLVM_DEBUG(dbgs() << "\tSuccessor BB (" << (*SI)->getNumber() << "):"); - for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(), - E = (*SI)->livein_end(); - I != E; ++I) - LLVM_DEBUG(dbgs() << "\t" << printReg((*I).PhysReg, TRI)); - LLVM_DEBUG(dbgs() << "\n"); - } -} -#endif - -// Blocks should be considered empty if they contain only debug info; -// else the debug info would affect codegen. -static bool IsEmptyBlock(MachineBasicBlock *MBB) { - if (MBB->empty()) - return true; - for (MachineBasicBlock::iterator MBBI = MBB->begin(), MBBE = MBB->end(); - MBBI != MBBE; ++MBBI) { - if (!MBBI->isDebugInstr()) - return false; - } - return true; -} - -/// Treat given instruction as a branch, go through its operands -/// and see if any of them is a BB address. If so, return it. -/// Return NULL otherwise. -static inline MachineBasicBlock *getBranchDestination(MachineInstr *MI) { - if (!MI || !MI->isBranch() || MI->isBundle()) - return NULL; - - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - if (MO.isMBB()) - return MO.getMBB(); - } - return NULL; -} - -/// Similar to HexagonInstrInfo::analyzeBranch but handles -/// serveral more general cases including parsing empty BBs when possible. -bool HexagonGlobalSchedulerImpl::AnalyzeBBBranches(MachineBasicBlock *MBB, - MachineBasicBlock *&TBB, - MachineInstr *&FirstTerm, - MachineBasicBlock *&FBB, - MachineInstr *&SecondTerm) { - // Hexagon allowes up to two jumps in MBB. - FirstTerm = NULL; - SecondTerm = NULL; - - LLVM_DEBUG(dbgs() << "\n\t\tAnalyze Branches in BB(" << MBB->getNumber() - << ")\n"); - if (MBB->succ_size() == 0) { - LLVM_DEBUG(dbgs() << "\n\t\tBlock has no successors.\n"); - return true; - } - // Find both jumps. - // We largely rely on implied assumption that BB branching always - // looks like this: - // J2_jumpf %P0, , %PC; - // J2_jump - // Branches also could be in different packets. - MachineBasicBlock::instr_iterator MIB = MBB->instr_begin(); - MachineBasicBlock::instr_iterator MIE = MBB->instr_end(); - MachineBasicBlock::instr_iterator MII = MIB; - - if (QII->nonDbgBBSize(MBB) == 1) { - MII = MBB->getFirstNonDebugInstr().getInstrIterator(); - if (MII->isBranch()) - FirstTerm = &*MII; - } else { - // We have already eliminated the case when MIB == MIE. - while (MII != MIE) { - if (!MII->isBundle() && MII->isBranch()) { - if (!FirstTerm) - FirstTerm = &*MII; - else - SecondTerm = &*MII; - } - ++MII; - } - } - if ((FirstTerm && FirstTerm->isIndirectBranch()) || - (SecondTerm && SecondTerm->isIndirectBranch())) { - LLVM_DEBUG(dbgs() << "\n\t\tCannot analyze BB with indirect branch."); - return true; - } - if ((FirstTerm && FirstTerm->getOpcode() == Hexagon::J2_jump && - !FirstTerm->getOperand(0).isMBB()) || - (SecondTerm && SecondTerm->getOpcode() == Hexagon::J2_jump && - !SecondTerm->getOperand(0).isMBB())) { - LLVM_DEBUG( - dbgs() << "\n\t\tCannot analyze BB with a branch out of function."); - return true; - } - - // Now try to analyze this branch. - SmallVector Cond; - if (QII->analyzeBranch(*MBB, TBB, FBB, Cond, false)) { - LLVM_DEBUG(dbgs() << "\t\tFail to analyze with analyzeBranch.\n"); - LLVM_DEBUG(dbgs() << "\t\tFirst term: "; if (FirstTerm) FirstTerm->dump(); - else dbgs() << "None\n";); - // Could not analyze it. See if this is something we can recognize. - TBB = getBranchDestination(FirstTerm); - } - // There are several cases not handled by HexagonInstrInfo::analyzeBranch. - if (!TBB) { - LLVM_DEBUG(dbgs() << "\t\tMissing TBB.\n"); - // There is a branch, but TBB is not found. - // The BB could also be empty at this point. See if it is a trivial - // layout case. - if (MBB->succ_size() == 1) { - TBB = *MBB->succ_begin(); - LLVM_DEBUG(dbgs() << "\t\tFall through TBB(" << TBB->getNumber() - << ").\n"); - return false; - } else if (MBB->succ_size() == 2) { - // This should cover majority of remaining cases. - if (FirstTerm && SecondTerm && - (QII->isPredicated(*FirstTerm) || QII->isNewValueJump(*FirstTerm)) && - !QII->isPredicated(*SecondTerm)) { - TBB = getBranchDestination(FirstTerm); - FBB = getBranchDestination(SecondTerm); - LLVM_DEBUG(dbgs() << "\t\tCanonical dual jump layout: TBB(" - << TBB->getNumber() << ") FBB(" << FBB->getNumber() - << ").\n"); - return false; - } else if (SecondTerm && SecondTerm->getOpcode() == Hexagon::J2_jump && - SecondTerm->getOperand(0).isMBB()) { - // Look at the second term if I know it, to find out what is the fall - // through for this BB. - FBB = SecondTerm->getOperand(0).getMBB(); - MachineBasicBlock::const_succ_iterator IMBB = MBB->succ_begin(); - if (FBB == *IMBB) - TBB = *(++IMBB); - else - TBB = *IMBB; - LLVM_DEBUG(dbgs() << "\t\tSecond br is J2_jump TBB(" << TBB->getNumber() - << ") FBB(" << FBB->getNumber() << ").\n"); - return false; - } else { - // This might be an empty BB but still with two - // successors set. Try to use CFG layout to sort it out. - // This could happen when last jump was pulled up from a BB, and - // CFG is being updated. At that point this method is called and - // returns best guess possible for TBB/FBB. Fortunately order of those - // is irrelevant, and rather used a worklist for CFG update. - MachineFunction::iterator MBBIter = MBB->getIterator(); - MachineFunction &MF = *MBB->getParent(); - (void)MF; // supress compiler warning - // If there are no other clues, assume next sequential BB - // in CFG as FBB. - ++MBBIter; - assert(MBBIter != MF.end() && "I give up."); - FBB = &(*MBBIter); - MachineBasicBlock::const_succ_iterator MBBSucc = MBB->succ_begin(); - if (FBB == *MBBSucc) - TBB = *(MBBSucc + 1); - else if (FBB == *(MBBSucc + 1)) { - TBB = *MBBSucc; - } else { - // This case can arise when the layout successor basic block (++IMBB) - // got empty during pull-up. - // As a result, ++IMBB is not one of MBB's successors. - MBBIter = MF.begin(); - while (!MBB->isSuccessor(&*MBBIter) && (MBBIter != MF.end())) - ++MBBIter; - assert(MBBIter != MF.end() && "Malformed BB with invalid successors"); - FBB = &*MBBIter; - if (FBB == (*MBBSucc)) - TBB = *(MBBSucc + 1); - else - TBB = *MBBSucc; - } - LLVM_DEBUG(dbgs() << "\t\tUse layout TBB(" << TBB->getNumber() - << ") FBB(" << FBB->getNumber() << ").\n"); - return false; - } - } - assert(!FirstTerm && "Bad BB"); - return true; - } - // Ok, we have TBB, but maybe missing FBB. - if (!FBB && SecondTerm) { - LLVM_DEBUG(dbgs() << "\t\tMissing FBB.\n"); - // analyzeBranch could lie to us, ignore it in this case. - // For the canonical case simply take known branch targets. - if ((QII->isPredicated(*FirstTerm) || QII->isNewValueJump(*FirstTerm)) && - !QII->isPredicated(*SecondTerm)) { - FBB = getBranchDestination(SecondTerm); - } else { - // Second term is also predicated. - // Use CFG layout. Assign layout successor as FBB. - MachineBasicBlock::succ_iterator IMBB = MBB->succ_begin(); - while (IMBB != MBB->succ_end()) { - if (MBB->isLayoutSuccessor(*IMBB)) - FBB = *IMBB; - ++IMBB; - } - if (FBB == NULL) { - LLVM_DEBUG(dbgs() << "\nNo layout successor found."); - LLVM_DEBUG(dbgs() << "Possibly the layout successor is an empty BB"); - return true; - } - if (TBB == FBB) - LLVM_DEBUG(dbgs() << "Malformed branch with useless branch condition";); - } - LLVM_DEBUG(dbgs() << "\t\tSecond term: "; SecondTerm->dump()); - } else if (TBB && !FBB) { - // If BB ends in endloop, and it is a single BB hw loop, - // we will have a single terminator, but we can figure FBB - // easily from CFG. - if (MBB->succ_size() == 2) { - MachineBasicBlock::succ_iterator IMBB = MBB->succ_begin(); - if (TBB == *IMBB) - FBB = *(++IMBB); - else - FBB = *IMBB; - } - } - - LLVM_DEBUG(dbgs() << "\t\tFinal TBB(" << TBB->getNumber() << ").\n"; - if (FBB) dbgs() << "\t\tFinal FBB(" << FBB->getNumber() << ").\n"; - else dbgs() << "\t\tFinal FBB(None)\n";); - return false; -} - -/// updateBranches - Updates all branches to \p From in the basic block \p -/// InBlock to branches to \p To. -static void updateBranches(MachineBasicBlock &InBlock, MachineBasicBlock *From, - MachineBasicBlock *To) { - for (MachineBasicBlock::instr_iterator BI = InBlock.instr_begin(), - E = InBlock.instr_end(); - BI != E; ++BI) { - MachineInstr *Inst = &*BI; - // Ignore anything that is not a branch. - if (!Inst->isBranch()) - continue; - for (MachineInstr::mop_iterator OI = Inst->operands_begin(), - OE = Inst->operands_end(); - OI != OE; ++OI) { - MachineOperand &Opd = *OI; - // Look for basic block "From". - if (!Opd.isMBB() || Opd.getMBB() != From) - continue; - // Update it. - Opd.setMBB(To); - } - } -} - -/// Rewrite all predecessors of the old block to go to the fallthrough -/// instead. -static void updatePredecessors(MachineBasicBlock &MBB, - MachineBasicBlock *MFBB) { - MachineFunction &MF = *MBB.getParent(); - - if (MFBB->getIterator() == MF.end()) - return; - - while (!MBB.pred_empty()) { - MachineBasicBlock *Pred = *(MBB.pred_end() - 1); - Pred->ReplaceUsesOfBlockWith(&MBB, MFBB); - updateBranches(*Pred, &MBB, MFBB); - } -} - -static void UpdateCFG(MachineBasicBlock *HomeBB, MachineBasicBlock *OriginBB, - MachineInstr *MII, MachineBasicBlock *HomeTBB, - MachineBasicBlock *HomeFBB, MachineInstr *FTA, - MachineInstr *STA, - const MachineBranchProbabilityInfo *MBPI) { - MachineBasicBlock *S2Add = NULL, *S2Remove = NULL; - bool RemoveLSIfPresent = false; - if ((&*MII == FTA) && MII->isConditionalBranch()) { - LLVM_DEBUG(dbgs() << "\nNew firstterm conditional jump added to HomeBB";); - S2Add = HomeTBB; - S2Remove = HomeTBB; - } else if ((&*MII == STA) && MII->isConditionalBranch()) { - LLVM_DEBUG(dbgs() << "\nNew secondterm conditional jump added to HomeBB";); - // AnalyzeBBBranches might not give correct information in this case. - // The branch destination may be a symbol, not necessarily a block. - if (MachineBasicBlock *Dest = getBranchDestination(MII)) { - LLVM_DEBUG(dbgs() << "\nBranch destination for pulled instruction is BB#" - << Dest->getNumber();); - S2Add = Dest; - S2Remove = Dest; - } - } else if ((&*MII == FTA) && MII->isUnconditionalBranch()) { - LLVM_DEBUG(dbgs() << "\nNew firstterm unconditional jump added to HomeBB";); - S2Add = HomeTBB; - S2Remove = HomeTBB; - RemoveLSIfPresent = true; - } else if ((&*MII == STA) && MII->isUnconditionalBranch()) { - LLVM_DEBUG( - dbgs() << "\nNew secondterm unconditional jump added to HomeBB";); - S2Add = HomeFBB; - S2Remove = HomeFBB; - RemoveLSIfPresent = true; - } - if (S2Add && !HomeBB->isSuccessor(S2Add)) { - HomeBB->addSuccessor(S2Add, MBPI->getEdgeProbability(OriginBB, S2Add)); - } - if (S2Remove) - OriginBB->removeSuccessor(S2Remove); - if (RemoveLSIfPresent) { - MachineFunction::iterator HomeBBLS = HomeBB->getIterator(); - ++HomeBBLS; - if (HomeBBLS != HomeBB->getParent()->end() && - HomeBB->isLayoutSuccessor(&*HomeBBLS)) { - LLVM_DEBUG(dbgs() << "\nRemoving LayoutSucc BB#" << HomeBBLS->getNumber() - << "from list of successors";); - HomeBB->removeSuccessor(&*HomeBBLS); - } - } -} - -/// Move instruction from/to BB, Update liveness info, -/// return pointer to the newly inserted and modified -/// instruction. -MachineInstr *HexagonGlobalSchedulerImpl::MoveAndUpdateLiveness( - BasicBlockRegion *CurrentRegion, MachineBasicBlock *HomeBB, - MachineInstr *InstrToMove, bool NeedToNewify, unsigned DepReg, - bool MovingDependentOp, MachineBasicBlock *OriginBB, - MachineInstr *OriginalInstruction, SmallVector &Cond, - MachineBasicBlock::iterator &SourceLocation, - MachineBasicBlock::iterator &TargetPacket, - MachineBasicBlock::iterator &NextMI, - std::vector &backtrack) { - LLVM_DEBUG( - dbgs() << "\n...............[MoveAndUpdateLiveness]..............\n"); - LLVM_DEBUG(dbgs() << "\t\tInstrToMove :\t"; InstrToMove->dump()); - LLVM_DEBUG(dbgs() << "\t\tOriginalInstruction:\t"; - OriginalInstruction->dump()); - LLVM_DEBUG(dbgs() << "\t\tSourceLocation :\t"; - DumpPacket(SourceLocation.getInstrIterator())); - LLVM_DEBUG(dbgs() << "\t\tTargetPacket :\t"; - DumpPacket(TargetPacket.getInstrIterator())); - - MachineBasicBlock::instr_iterator OriginalHead = - SourceLocation.getInstrIterator(); - MachineBasicBlock::instr_iterator OriginalTail = getBundleEnd(OriginalHead); - MachineBasicBlock::instr_iterator OutcastFrom = - OriginalInstruction->getIterator(); - - // Remove our temporary instruction. - MachineBasicBlock::instr_iterator kill_it(InstrToMove); - HomeBB->erase(kill_it); - - MachineBasicBlock::instr_iterator TargetHead(TargetPacket.getInstrIterator()); - MachineBasicBlock::instr_iterator TargetTail = getBundleEnd(TargetHead); - - LLVM_DEBUG(dbgs() << "\n\tTo BB before:\n"; debugLivenessForBB(HomeBB, QRI)); - LLVM_DEBUG(dbgs() << "\n\tFrom BB before:\n"; - debugLivenessForBB(OriginBB, QRI)); - - // Before we perform the move, we need to collect the worklist - // of BBs for liveness updated. - std::list WorkList; - - // Insert into the work list all BBs along the backtrace. - for (std::vector::iterator RI = backtrack.begin(), - RIE = backtrack.end(); - RI != RIE; RI++) - WorkList.push_back((*RI)->getParent()); - - // Only keep unique entries. - // TODO: Use a different container here. - WorkList.unique(); - - // Move the original instruction. - // If this instruction is inside a bundle, update the bundle. - MachineBasicBlock::instr_iterator BBEnd = - TargetHead->getParent()->instr_end(); - bool LastInstructionInBundle = false; - MachineBasicBlock::instr_iterator MII = findInsertPositionInBundle( - TargetPacket, &*OutcastFrom, LastInstructionInBundle); - - (void)BBEnd; - LLVM_DEBUG(dbgs() << "\n\t\t\tHead target : "; DumpPacket(TargetHead)); - LLVM_DEBUG(dbgs() << "\t\t\tTail target : "; - DumpPacket(TargetTail, BBEnd)); - LLVM_DEBUG(dbgs() << "\t\t\tInsert right before: "; DumpPacket(MII, BBEnd)); - - MIBundleBuilder Bundle(&*TargetHead); - - // Actual move. One day liveness might be updated here. - if (OriginalInstruction->isBundled()) { - Bundle.insert(MII, OriginalInstruction->removeFromBundle()); - --MII; - } else { - // This is one case currently unhandled by Bundle.insert - // and needs to be fixed upstream. Meanwhile use old way to handle - // this odd case. - if (OriginalInstruction->getIterator() == TargetTail) { - LLVM_DEBUG(dbgs() << "\t\t\tSpecial case move.\n"); - MachineBasicBlock::instr_iterator MIIToPred = MII; - --MIIToPred; - LLVM_DEBUG(dbgs() << "\t\t\tInser after : "; - DumpPacket(MIIToPred, BBEnd)); - // Unbundle it in its current location. - if (OutcastFrom->isBundledWithSucc()) { - OutcastFrom->clearFlag(MachineInstr::BundledSucc); - OutcastFrom->clearFlag(MachineInstr::BundledPred); - } else if (OutcastFrom->isBundledWithPred()) { - OutcastFrom->unbundleFromPred(); - } - HomeBB->splice(MII, OriginBB, OutcastFrom); - if (!MII->isBundledWithPred()) - MII->bundleWithPred(); - if (!LastInstructionInBundle && !MII->isBundledWithSucc()) - MII->bundleWithSucc(); - // This is the instruction after which we have inserted. - if (!MIIToPred->isBundledWithSucc()) - MIIToPred->bundleWithSucc(); - } else { - Bundle.insert(MII, OriginalInstruction->removeFromParent()); - --MII; - } - } - // Source location bundle is updated later in the - // removeInstructionFromExistingBundle(). - - LLVM_DEBUG(dbgs() << "\t\t\tNew packet head: "; DumpPacket(TargetHead)); - LLVM_DEBUG(dbgs() << "\t\t\tInserted op : "; MII->dump()); - LLVM_DEBUG(dbgs() << "\n\tTo BB after move:\n"; - debugLivenessForBB(HomeBB, QRI)); - LLVM_DEBUG(dbgs() << "\n\tFrom BB after:\n"; - debugLivenessForBB(OriginBB, QRI)); - - // Update kill patterns. Do it before we have predicated the moved - // instruction. - updateKillAlongThePath(HomeBB, OriginBB, MII, TargetTail, SourceLocation, - TargetPacket, backtrack); - // I need to know: - // - true/false predication - // - do I need to .new it? - // - do I need to .old it? - // If the original instruction used new value operands, - // it might need to be changed to the generic form - // before further processing. - if (QII->isDotNewInst(*MII)) { - DemoteToDotOld(&*MII); - LLVM_DEBUG(dbgs() << "\t\t\tDemoted to .old\t:"; MII->dump()); - } - - // We have previously checked whether this instruction could - // be placed in this packet, including all possible transformations - // it might need, so if any request will fail now, something is wrong. - // - // Need for predication and the exact condition is determined by - // the path between original and current instruction location. - if (!Cond.empty()) { // To be predicated - LLVM_DEBUG(dbgs() << "\t\t\tPredicating:"; MII->dump()); - assert(TII->isPredicable(*MII) && "MII is not predicable"); - TII->PredicateInstruction(*MII, Cond); - if (NeedToNewify) { - assert((DepReg < std::numeric_limits::max()) && - "Invalid pred reg value"); - LLVM_DEBUG(dbgs() << "\t\t\tNeeds to NEWify on Reg(" - << printReg(DepReg, QRI) << ").\n"); - int NewOpcode = QII->getDotNewPredOp(*MII, MBPI); - MII->setDesc(QII->get(NewOpcode)); - - // Now we need to mark newly created predicate operand as - // internal read. - // TODO: Better look for predicate operand. - for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) { - MachineOperand &MO = MII->getOperand(i); - if (!MO.isReg()) - continue; - if (MO.isDef()) - continue; - if (DepReg == MO.getReg()) - MO.setIsInternalRead(); - } - } - LLVM_DEBUG(dbgs() << "\t\t\tNew predicated form:\t"; MII->dump()); - // If the predicate has changed kill pattern, now we need to propagate - // that again. This is important for liveness computation. - updateKillAlongThePath(HomeBB, OriginBB, MII, TargetTail, SourceLocation, - TargetPacket, backtrack); - } - - // Create new bundle header, remove the old one. - addInstructionToExistingBundle(HomeBB, TargetHead, TargetTail, MII, - TargetPacket, NextMI, backtrack); - - // If moved instruction was inside a bundle, update that bundle. - removeInstructionFromExistingBundle(OriginBB, ++OriginalHead, OriginalTail, - SourceLocation, NextMI, MovingDependentOp, - backtrack); - - // If removed instruction could have been dependent on any - // of the remaining ops, we need to oldify possible affected ones. - LLVM_DEBUG(dbgs() << "\t\tTargetHead:\t"; DumpPacket(TargetHead, BBEnd)); - LLVM_DEBUG(dbgs() << "\t\tOriginalHead:\t"; DumpPacket(OriginalHead, BBEnd)); - LLVM_DEBUG(dbgs() << "\t\tOriginalInstruction:\t"; - DumpPacket(OriginalInstruction->getIterator(), BBEnd)); - LLVM_DEBUG(dbgs() << "\t\tOutcastFrom:\t"; DumpPacket(OutcastFrom, BBEnd)); - - // Clean up the original source bundle on a global scope. - if (OriginalHead != MachineBasicBlock::instr_iterator() && - QII->isEndLoopN(OriginalHead->getOpcode())) { - // Single endloop left. Since it is not a real instruction, - // we can simply add it to a non empty previous bundle, if one exist, - // or let assembler to produce a fake bundle for it. - LLVM_DEBUG(dbgs() << "\t\tOnly endloop in packet.\n"); - MachineBasicBlock::instr_iterator I(OriginalHead); - if (OriginBB->begin() != I) { - --I; - if (I->isBundled()) { - if (!I->isBundledWithSucc()) - I->bundleWithSucc(); - if (!OriginalHead->isBundledWithPred()) - OriginalHead->bundleWithPred(); - } - // else we probably need to create a new bundle here. - // SourceLocation = NULL; - } - } else if (MovingDependentOp && - OriginalHead != MachineBasicBlock::instr_iterator()) { - if (OriginalHead->isBundled()) { - for (MachineBasicBlock::instr_iterator J = ++OriginalHead; - J != OriginalTail && J->isInsideBundle() && !J->isBundle(); ++J) { - // Need to oldify it. - if (MIsHaveTrueDependency(OriginalInstruction, &*J) && - QII->isDotNewInst(*J)) { - LLVM_DEBUG(dbgs() << "\t\tDemoting to .old:\t"; J->dump()); - DemoteToDotOld(&*J); - } - } - } else { - // Single instruction left. - if (MIsHaveTrueDependency(OriginalInstruction, &*OriginalHead) && - QII->isDotNewInst(*OriginalHead)) { - LLVM_DEBUG(dbgs() << "\t\tDemoting to .old op:\t"; - OriginalHead->dump()); - DemoteToDotOld(&*OriginalHead); - } - } - } - - // Now we need to update liveness to all BBs involved - // including those we might have "passed" through on the way here. - LLVM_DEBUG(dbgs() << "\n\tTo BB after bundle update:\n"; HomeBB->dump()); - LLVM_DEBUG(dbgs() << "\n\n\tFrom BB after bundle update:\n"; - OriginBB->dump()); - - // Update global liveness. - LLVM_DEBUG(dbgs() << "\n\tWorkList:\t"); - for (std::list::iterator BBI = WorkList.begin(), - BBIE = WorkList.end(); - BBI != BBIE; BBI++) { - LLVM_DEBUG(dbgs() << "BB#" << (*BBI)->getNumber() << " "); - } - LLVM_DEBUG(dbgs() << "\n"); - - do { - MachineBasicBlock *BB = WorkList.back(); - WorkList.pop_back(); - CurrentRegion->getLivenessInfoForBB(BB)->UpdateLiveness(BB); - } while (!WorkList.empty()); - - // No need to analyze for empty BB or update CFG for same BB pullup. - if (OriginBB == HomeBB) - return &*TargetHead; - // If the instruction moved was a branch we need to update the - // successor/predecessor of OriginBB and HomeBB accordingly. - MachineBasicBlock *HomeTBB, *HomeFBB; - MachineInstr *FTA = NULL, *STA = NULL; - bool HomeBBAnalyzed = !AnalyzeBBBranches(HomeBB, HomeTBB, FTA, HomeFBB, STA); - if (MII->isBranch()) { - if (HomeBBAnalyzed) { - UpdateCFG(HomeBB, OriginBB, &*MII, HomeTBB, HomeFBB, FTA, STA, MBPI); - } else { - llvm_unreachable("Underimplememted AnalyzeBBBranches"); - } - } - // If we have exhausted the OriginBB clean it up. - // Beware that we could have created dual conditional jumps, which - // ultimately means we can have three way jumps. - if (IsEmptyBlock(OriginBB) && !OriginBB->isEHPad() && - !OriginBB->hasAddressTaken() && !OriginBB->succ_empty()) { - // Dead block? Unlikely, but check. - LLVM_DEBUG(dbgs() << "Empty BB(" << OriginBB->getNumber() << ").\n"); - // Update region map. - CurrentRegion->RemoveBBFromRegion(OriginBB); - // Keep the list of empty basic blocks to be freed later. - EmptyBBs.push_back(OriginBB); - if (OriginBB->pred_empty() || OriginBB->succ_empty()) - return &*TargetHead; - - if (OriginBB->succ_size() == 1) { - // Find empty block's successor. - MachineBasicBlock *CommonFBB = *OriginBB->succ_begin(); - updatePredecessors(*OriginBB, CommonFBB); - // Remove the only successor entry for empty BB. - OriginBB->removeSuccessor(CommonFBB); - } else { - // Three way branching is not yet fully supported. - assert((OriginBB->succ_size() == 2) && "Underimplemented 3way branch."); - MachineBasicBlock *OriginTBB, *OriginFBB; - MachineInstr *FTB = NULL, *STB = NULL; - - LLVM_DEBUG(dbgs() << "\tComplex case.\n"); - if (HomeBBAnalyzed && - !AnalyzeBBBranches(OriginBB, OriginTBB, FTB, OriginFBB, STB)) { - assert(OriginFBB && "Missing Origin FBB"); - if (HomeFBB == OriginBB) { - // OriginBB is FBB for HomeBB. - if (HomeTBB == OriginTBB) { - // Shared TBB target, common FBB. - updatePredecessors(*OriginBB, OriginFBB); - } else if (HomeTBB == OriginFBB) { - // Shared TBB target, common FBB. - updatePredecessors(*OriginBB, OriginTBB); - } else { - // Three way branch. Add new successor to HomeBB. - updatePredecessors(*OriginBB, OriginFBB); - // TODO: Update the weight as well. - // Adding the successor to make updatePredecessor happy. - HomeBB->addSuccessor(OriginBB); - updatePredecessors(*OriginBB, OriginTBB); - } - } else if (HomeTBB == OriginBB) { - // OriginBB is TBB for HomeBB. - if (HomeFBB == OriginTBB) { - // Shared TBB target, common FBB. - updatePredecessors(*OriginBB, OriginFBB); - } else if (HomeFBB == OriginFBB) { - // Shared TBB target, common FBB. - updatePredecessors(*OriginBB, OriginTBB); - } else { - // Three way branch. Add new successor to HomeBB. - updatePredecessors(*OriginBB, OriginFBB); - // TODO: Update the weight as well. - // Adding the successor to make updatePredecessor happy. - HomeBB->addSuccessor(OriginBB); - updatePredecessors(*OriginBB, OriginTBB); - } - } else - llvm_unreachable("CFG update failed"); - // The empty BB can now be relieved of its successors. - OriginBB->removeSuccessor(OriginFBB); - OriginBB->removeSuccessor(OriginTBB); - } else - llvm_unreachable("Underimplemented analyzeBranch"); - } - LLVM_DEBUG(dbgs() << "Updated BB(" << HomeBB->getNumber() << ").\n"; - HomeBB->dump()); - } - return &*TargetHead; -} - -// Find where inside a given bundle current instruction should be inserted. -// Instruction will be inserted _before_ this position. -MachineBasicBlock::instr_iterator -HexagonGlobalSchedulerImpl::findInsertPositionInBundle( - MachineBasicBlock::iterator &Bundle, MachineInstr *MI, bool &LastInBundle) { - MachineBasicBlock::instr_iterator MII = Bundle.getInstrIterator(); - MachineBasicBlock *MBB = MII->getParent(); - MachineBasicBlock::instr_iterator BBEnd = MBB->instr_end(); - MachineBasicBlock::instr_iterator FirstBranch = BBEnd; - MachineBasicBlock::instr_iterator LastBundledInstruction = BBEnd; - MachineBasicBlock::instr_iterator DualJumpFirstCandidate = BBEnd; - - assert(MII->isBundle() && "Missing insert location"); - bool isDualJumpSecondCandidate = IsDualJumpSecondCandidate(MI); - LastInBundle = false; - - for (++MII; MII != BBEnd && MII->isInsideBundle() && !MII->isBundle(); - ++MII) { - if (MII->isBranch() && (FirstBranch == BBEnd)) - FirstBranch = MII; - // If what we insert is a dual jump, we need to find - // first jump, and insert new instruction after it. - if (isDualJumpSecondCandidate && IsDualJumpFirstCandidate(&*MII)) - DualJumpFirstCandidate = MII; - LastBundledInstruction = MII; - } - - if (DualJumpFirstCandidate != BBEnd) { - // First respect dual jumps. - ++DualJumpFirstCandidate; - if (DualJumpFirstCandidate == BBEnd || - DualJumpFirstCandidate == LastBundledInstruction) - LastInBundle = true; - return DualJumpFirstCandidate; - } else if (FirstBranch != BBEnd) { - // If we have no dual jumps, but do have a single - // branch in the bundle, add our new instruction - // right before it. - return FirstBranch; - } else if (LastBundledInstruction != BBEnd) { - LastInBundle = true; - return ++LastBundledInstruction; - } else - llvm_unreachable("Lost in bundle"); - return MBB->instr_begin(); -} - -/// This function for now needs to try to insert new instruction -/// in correct serial semantics fashion - i.e. find "correct" insert -/// point for instruction as if inserting in serial sequence. -MachineBasicBlock::instr_iterator HexagonGlobalSchedulerImpl::insertTempCopy( - MachineBasicBlock *MBB, MachineBasicBlock::iterator &TargetPacket, - MachineInstr *MI, bool DeleteOldCopy) { - MachineBasicBlock::instr_iterator MII; - MachineBasicBlock *CurrentBB = MI->getParent(); - - assert(CurrentBB && "Corrupt instruction"); - // Create a temporary copy of the instruction we are considering. - // LLVM refuses to deal with an instruction which was not inserted - // to any BB. We can visit multiple BBs on the way "up", so we - // create a temp copy of the original instruction and delete it later. - // It is way cheaper than using splice and then - // needing to undo it most of the time. - MachineInstr *NewMI = MI->getParent()->getParent()->CloneMachineInstr(MI); - // Make sure all bundling flags are cleared. - if (NewMI->isBundledWithPred()) - NewMI->unbundleFromPred(); - if (NewMI->isBundledWithSucc()) - NewMI->unbundleFromSucc(); - - if (DeleteOldCopy) { - // Remove our temporary instruction. - // MachineBasicBlock::erase method calls unbundleSingleMI() - // prior to deletion, so we do not have to do it here. - MachineBasicBlock::instr_iterator kill_it(MI); - CurrentBB->erase(kill_it); - } - - // If the original instruction used new value operands, - // it might need to be changed to generic form - // before further processing. - if (QII->isDotNewInst(*NewMI)) - DemoteToDotOld(NewMI); - - // Insert new temporary instruction. - // If this is the destination packet, insert the tmp after - // its header. Otherwise, as second instr in BB. - if (TargetPacket->getParent() == MBB) { - MII = TargetPacket.getInstrIterator(); - - if (MII->isBundled()) { - bool LastInBundle = false; - MachineBasicBlock::instr_iterator InsertBefore = - findInsertPositionInBundle(TargetPacket, NewMI, LastInBundle); - MIBundleBuilder Bundle(&*TargetPacket); - Bundle.insert(InsertBefore, NewMI); - } else - MBB->insertAfter(MII, NewMI); - } else { - MII = MBB->instr_begin(); - - // Skip debug instructions. - while (MII->isDebugInstr()) - MII++; - - if (MII->isBundled()) { - MIBundleBuilder Bundle(&*MII); - Bundle.insert(++MII, NewMI); - } else - MBB->insertAfter(MII, NewMI); - } - return NewMI->getIterator(); -} - -// Check for a conditionally assigned register within the block. -bool HexagonGlobalSchedulerImpl::MIsCondAssign(MachineInstr *BMI, - MachineInstr *MI, - SmallVector &Defs) { - if (!QII->isPredicated(*BMI)) - return false; - // Its a conditional instruction, now is it the same registers as MI? - SmallVector CondDefs; - SmallVector CondUses; - parseOperands(BMI, CondDefs, CondUses); - - for (SmallVector::iterator ID = Defs.begin(), IDE = Defs.end(); - ID != IDE; ++ID) { - for (SmallVector::iterator CID = CondDefs.begin(), - CIDE = CondDefs.end(); - CID != CIDE; ++CID) { - if (AliasingRegs(*CID, *ID)) { - LLVM_DEBUG(dbgs() << "\tFound conditional def, can't move\n"; - BMI->dump()); - return true; - } - } - } - return false; -} - -// Returns the Union of all the elements in Set1 and -// Union of all the elements in Set2 separately. -// Constraints: -// Set1 and Set2 should contain an entry for each element in Range. -template -void Unify(std::vector Range, - std::map> &Set1, - std::map> &Set2, - std::pair, std::vector> &UnionSet, - unsigned union_size = 100) { - typedef - typename std::map>::iterator PosIter_t; - typedef typename std::vector::iterator IndexIter_t; - std::vector &Union1 = UnionSet.first; - std::vector &Union2 = UnionSet.second; - Union1.resize(union_size, 0); - Union2.resize(union_size, 0); - LLVM_DEBUG(dbgs() << "\n\t\tElements in the range:\n";); - typename std::vector::iterator iter = Range.begin(); - while (iter != Range.end()) { - if ((*iter)->isDebugInstr()) { - ++iter; - continue; - } - LLVM_DEBUG((*iter)->dump()); - PosIter_t set1_pos = Set1.find(*iter); - assert(set1_pos != Set1.end() && - "Set1 should contain an entry for each element in Range."); - IndexIter_t set1idx = set1_pos->second.begin(); - while (set1idx != set1_pos->second.end()) { - Union1[*set1idx] = 1; - ++set1idx; - } - PosIter_t set2_pos = Set2.find(*iter); - assert(set2_pos != Set2.end() && - "Set2 should contain an entry for each element in Range."); - IndexIter_t set2idx = set2_pos->second.begin(); - while (set2idx != set2_pos->second.end()) { - Union2[*set2idx] = 1; - ++set2idx; - } - ++iter; - } -} - -static void UpdateBundle(MachineInstr *BundleHead) { - assert(BundleHead->isBundle() && "Not a bundle header"); - if (!BundleHead) - return; - unsigned Size = BundleHead->getBundleSize(); - if (Size >= 2) - return; - if (Size == 1) { - MachineBasicBlock::instr_iterator MIter = BundleHead->getIterator(); - MachineInstr *MI = &*(++MIter); - MI->unbundleFromPred(); - } - BundleHead->eraseFromParent(); -} - -/// Gatekeeper for instruction speculation. -/// If all MI defs are dead (not live-in) to any other -/// BB but the one we are moving into, and it could not cause -/// exception by early execution, allow it to be pulled up. -bool HexagonGlobalSchedulerImpl::canMIBeSpeculated( - MachineInstr *MI, MachineBasicBlock *ToBB, MachineBasicBlock *FromBB, - std::vector &backtrack) { - // For now disallow memory accesses from speculation. - // Generally we can check if they potentially may trap/cause an exception. - if (!EnableSpeculativePullUp || !MI || MI->mayStore()) - return false; - - LLVM_DEBUG(dbgs() << "\t[canMIBeSpeculated] From BB(" << FromBB->getNumber() - << "):\t"; - MI->dump()); - LLVM_DEBUG(dbgs() << "\tTo this BB:\n"; ToBB->dump()); - - if (!ToBB->isSuccessor(FromBB)) - return false; - - // This is a very tricky topic. Speculating arithmetic instructions with - // results dead out of a loop more times then required by number of - // iterations is safe, while speculating loads can cause an exception. - // Simplest of checks is to not cross loop exit edge, or in our case - // do not pull-in to a loop exit BB, but there are implications for - // non-natural loops (not recognized by LLVM as loops) and multi-threaded - // code. - if (AllowSpeculateLoads && MI->mayLoad()) { - // Invariant loads should always be safe. - if (!MI->isDereferenceableInvariantLoad()) - return false; - LLVM_DEBUG(dbgs() << "\tSpeculating a Load.\n"); - } - - SmallVector Defs; - SmallVector Uses; - parseOperands(MI, Defs, Uses); - - // Do not speculate instructions that modify reserved global registers. - for (unsigned R : Defs) - if (MRI->isReserved(R) && QRI->isGlobalReg(R)) - return false; - - for (MachineBasicBlock::const_succ_iterator SI = ToBB->succ_begin(), - SE = ToBB->succ_end(); - SI != SE; ++SI) { - // TODO: Allow an instruction (I) which 'defines' the live-in reg (R) - // along the path when I is the first instruction to use the R. - // i.e., I kills R before any other instruction in the BB uses it. - // TODO: We have already parsed live sets - reuse them. - if (*SI == FromBB) - continue; - LLVM_DEBUG(dbgs() << "\tTarget succesor BB to check:\n"; (*SI)->dump()); - LLVM_DEBUG( - for (MachineBasicBlock::const_succ_iterator SII = (*SI)->succ_begin(), - SIE = (*SI)->succ_end(); - SII != SIE; ++SII)(*SII) - ->dump()); - for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(), - E = (*SI)->livein_end(); - I != E; ++I) - for (SmallVector::iterator ID = Defs.begin(), - IDE = Defs.end(); - ID != IDE; ++ID) { - if (AliasingRegs((*I).PhysReg, *ID)) - return false; - } - - // Check the successor blocks for conditional define. - // TODO: We should really test the whole path here. - for (MachineBasicBlock::instr_iterator BI = (*SI)->instr_begin(), - E = (*SI)->instr_end(); - BI != E; ++BI) { - if (BI->isBundle() || BI->isDebugInstr()) - continue; - LLVM_DEBUG(dbgs() << "\t\tcheck against:\t"; BI->dump()); - if (MIsCondAssign(&*BI, MI, Defs)) - return false; - } - } - // Taking a very conservative approach during speculation. - // Traverse the path (FromBB, ToBB] and make sure - // that the def-use set of the instruction to be moved - // are not modified. - std::vector PathBB; - for (unsigned i = 0; i < backtrack.size(); ++i) { - // Insert unique BB along the path but skip FromBB - MachineBasicBlock *MBB = backtrack[i]->getParent(); - if ((MBB != FromBB) && - (std::find(PathBB.begin(), PathBB.end(), MBB) == PathBB.end())) - PathBB.push_back(MBB); - } - bool WaitingForTargetPacket = true; - MachineBasicBlock::instr_iterator MII; - std::vector TraversalRange; - LLVM_DEBUG(dbgs() << "\n\tElements in the range:"); - // TODO: Use just the backtrack to get TraversalRange because it - // contains the path (only when speculated from a path in region). - // Note: We check the dependency of instruction-to-move with - // all the instructions (starting from backtrack[0]) in the parent BBs - // because a BB might have a branching from in between due to packetization - // and just checking packets in the backtrack won't be comprehensive. - for (unsigned i = 0; i < PathBB.size(); ++i) { - for (MII = PathBB[i]->instr_begin(); MII != PathBB[i]->instr_end(); ++MII) { - // Skip instructions until the target packet is found. - // although target packet is already checked for correctness, - // it is good to check here to validate intermediate pullups. - if (backtrack[0] == &*MII) - WaitingForTargetPacket = false; - if (WaitingForTargetPacket) - continue; - if (MII->isBundle()) - continue; - // TODO: Ideally we should check that there is a `linear' control flow - // in the TraversalRange in all possible manner. For e.g., - // BB0 { packet1: if(p0) indirect_jump BB1; - // packet2: jump BB2 } - // BB1 { i1 }. In this case we should not pull `i1' into packet2. - if (MII->isCall() || MII->isReturn() || - (MII->getOpcode() == Hexagon::J2_jump && !MII->getOperand(0).isMBB())) - return false; - if (MI != &*MII) { - TraversalRange.push_back(&*MII); - LLVM_DEBUG(MII->dump();); - } - } - } - // Get the union of def/use set of all the instructions along TraversalRange. - std::pair, std::vector> RangeDefUse; - Unify(TraversalRange, MIDefSet, MIUseSet, RangeDefUse, QRI->getNumRegs()); - // No instruction (along TraversalRange) should 'define' the use set of MI - for (unsigned j = 0; j < Uses.size(); ++j) - if (RangeDefUse.first[Uses[j]]) { - LLVM_DEBUG(dbgs() << "\n\t\tUnresolved dependency along path to HOME for " - << printReg(Uses[j], QRI);); - return false; - } - // No instruction (along TraversalRange) should 'define' or 'use' - // the def set of MI - for (unsigned j = 0; j < Defs.size(); ++j) - if (RangeDefUse.first[Defs[j]] || RangeDefUse.second[Defs[j]]) { - LLVM_DEBUG(dbgs() << "\n\t\tUnresolved dependency along path to HOME for " - << printReg(Defs[j], QRI);); - return false; - } - return true; -} - -/// Try to move InstrToMove to TargetPacket using path stored in backtrack. -/// SourceLocation is current iterator point. It must be updated to the new -/// iteration location after all updates. -/// Alogrithm: -/// To move an instruction (I) from OriginBB through HomeBB via backtrack. -/// for each packet (i) in backtrack, analyzeBranch -/// case 1 (success) -/// case Pulling from conditional branch: -/// if I is predicable -/// Try to predicate on the branch condition -/// else -/// Try to speculate I to backtrack[i]. -/// case Pulling from unconditional branch: -/// Just pullup. (TODO: Speculate here as well) -/// case 2 (fails) -/// Try to speculate I backtrack[i]. -bool HexagonGlobalSchedulerImpl::MoveMItoBundle( - BasicBlockRegion *CurrentRegion, - MachineBasicBlock::instr_iterator &InstrToMove, - MachineBasicBlock::iterator &NextMI, - MachineBasicBlock::iterator &TargetPacket, - MachineBasicBlock::iterator &SourceLocation, - std::vector &backtrack, bool MovingDependentOp, - bool PathInRegion) { - MachineBasicBlock *HomeBB = TargetPacket->getParent(); - MachineBasicBlock *OriginBB = InstrToMove->getParent(); - MachineBasicBlock *CurrentBB = OriginBB; - MachineBasicBlock *CleanupBB = OriginBB; - MachineBasicBlock *PreviousBB = OriginBB; - MachineInstr *OriginalInstructionToMove = &*InstrToMove; - - assert(HomeBB && "Missing HomeBB"); - assert(OriginBB && "Missing OriginBB"); - - LLVM_DEBUG(dbgs() << "\n.........[MoveMItoBundle]..............\n"); - LLVM_DEBUG(dbgs() << "\t\tInstrToMove :\t"; InstrToMove->dump()); - LLVM_DEBUG(dbgs() << "\t\tTargetPacket :\t"; - DumpPacket(TargetPacket.getInstrIterator())); - LLVM_DEBUG(dbgs() << "\t\tSourceLocation:\t"; - DumpPacket(SourceLocation.getInstrIterator())); - - // We do not allow to move instructions in the same BB. - if (HomeBB == OriginBB) { - LLVM_DEBUG(dbgs() << "\t\tSame BB pull-up.\n"); - if (!EnableLocalPullUp) - return false; - } - - if (OneFloatPerPacket && QII->isFloat(*TargetPacket) && - QII->isFloat(*InstrToMove)) - return false; - - if (OneComplexPerPacket && QII->isComplex(*TargetPacket) && - QII->isComplex(*InstrToMove)) - return false; - - LLVM_DEBUG(dbgs() << "\t\tWay home:\n"); - // Test integrity of the back track. - for (unsigned i = 0; i < backtrack.size(); ++i) { - assert(backtrack[i]->getParent() && "Messed back track."); - LLVM_DEBUG(dbgs() << "\t\t[" << i << "] BB(" - << backtrack[i]->getParent()->getNumber() << ")\t"; - backtrack[i]->dump()); - } - LLVM_DEBUG(dbgs() << "\n"); - - bool NeedCleanup = false; - bool NeedToPredicate = false; - bool MINeedToNewify = false; - unsigned DepReg = std::numeric_limits::max(); - bool isDualJump = false; - SmallVector Cond; - SmallVector PredCond; - std::vector PullUpPath; - if (PathInRegion) - PullUpPath = backtrack; - else { - PullUpPath.push_back(&*TargetPacket); - PullUpPath.push_back(&*InstrToMove); - } - - // Now start iterating over all instructions - // preceeding the one we are trying to move, - // and see if they could be reodered/bypassed. - for (std::vector::reverse_iterator RI = backtrack.rbegin(), - RIE = backtrack.rend(); - RI < RIE; ++RI) { - // Once most of debug will be gone, this will be a real assert. - // assert((backtrack.front() == ToThisBundle) && "Lost my way home."); - MachineInstr *MIWH = *RI; - if (QII->isDotNewInst(*InstrToMove)) { - LLVM_DEBUG(dbgs() << "Cannot move a dot new instruction:"; - InstrToMove->dump()); - if (NeedCleanup) - CleanupBB->erase(InstrToMove); - return false; - } - if (canCauseStall(&*InstrToMove, MIWH)) { - if (NeedCleanup) - CleanupBB->erase(InstrToMove); - return false; - } - LLVM_DEBUG(dbgs() << "\t> Step home BB(" << MIWH->getParent()->getNumber() - << "):\t"; - DumpPacket(MIWH->getIterator())); - - // See if we cross a jump, and possibly change the form of instruction. - // Passing through BBs with dual jumps in different packets - // takes extra care. - bool isBranchMIWH = isBranch(MIWH); - if (((&*SourceLocation != MIWH) && isBranchMIWH) || - (CurrentBB != MIWH->getParent())) { - LLVM_DEBUG(dbgs() << "\tChange BB from(" << CurrentBB->getNumber() - << ") to (" << MIWH->getParent()->getNumber() << ")\n"); - PreviousBB = CurrentBB; - CurrentBB = MIWH->getParent(); - - // See what kind of branch we are dealing with. - MachineBasicBlock *PredTBB = NULL; - MachineBasicBlock *PredFBB = NULL; - - if (QII->analyzeBranch(*CurrentBB, PredTBB, PredFBB, Cond, false)) { - // We currently do not handle NV jumps of this kind: - // if (cmp.eq(r0.new, #0)) jump:t .LBB12_69 - // TODO: Need to handle them. - LLVM_DEBUG(dbgs() << "\tCould not analyze branch.\n"); - - // This is the main point of lost performance. - // We could try to speculate here, but for that we need accurate - // liveness info, and it is not ready yet. - if (!canMIBeSpeculated(&*InstrToMove, CurrentBB, PreviousBB, - PullUpPath)) { - if (NeedCleanup) - CleanupBB->erase(InstrToMove); - return false; - } else { - // Save speculated instruction moved. - SpeculatedIns.insert( - std::make_pair(OriginalInstructionToMove, OriginBB)); - LLVM_DEBUG(dbgs() << "\nSpeculatedInsToMove"; InstrToMove->dump()); - } - - LLVM_DEBUG(dbgs() << "\tSpeculating.\n"); - // If we are speculating, we can come through a predication - // into an unconditional branch... - // For now simply bail out. - // TODO: See if this ever happens. - if (NeedToPredicate) { - LLVM_DEBUG(dbgs() - << "\tUnderimplemented pred for speculative move.\n"); - if (NeedCleanup) - CleanupBB->erase(InstrToMove); - return false; - } - InstrToMove = - insertTempCopy(CurrentBB, TargetPacket, &*InstrToMove, NeedCleanup); - NeedCleanup = true; - NeedToPredicate = false; - assert(!NeedToPredicate && "Need to handle predication for this case"); - CleanupBB = CurrentBB; - // No need to recheck for resources - instruction did not change. - LLVM_DEBUG(dbgs() << "\tUpdated BB:\n"; CurrentBB->dump()); - } else { - bool LocalNeedPredication = true; - // We were able to analyze the branch. - if (!isBranchMIWH && !PredTBB) { - LLVM_DEBUG(dbgs() << "\tDo not need predicate for this case.\n"); - LocalNeedPredication = false; - } - // First see if this is a potential dual jump situation. - if (IsDualJumpSecondCandidate(&*InstrToMove) && - IsDualJumpFirstCandidate(TargetPacket)) { - LLVM_DEBUG(dbgs() << "\tPerforming unrestricted dual jump.\n"); - isDualJump = true; - } else if (LocalNeedPredication && (PredFBB != PreviousBB)) { - // Predicate instruction based on condition feeding it. - // This is generally a statefull pull-up path. - // Can this insn be predicated? If so, try to do it. - if (TII->isPredicable(*InstrToMove)) { - if (PredTBB) { - if (PreviousBB != PredTBB) { - // If we "came" not from TBB, we need to invert condition. - if (TII->reverseBranchCondition(Cond)) { - LLVM_DEBUG(dbgs() << "\tUnable to invert condition.\n"); - if (NeedCleanup) - CleanupBB->erase(InstrToMove); - return false; - } - } - LLVM_DEBUG(dbgs() << "\tTBB(" << PredTBB->getNumber() - << ")InvertCondition(" - << (PreviousBB != PredTBB) << ")\n"); - } - // Create a new copy of the instruction we are trying to move. - // It changes enough (new BB, predicated form) and untill we - // reach home, we do not even know if it is going to work. - InstrToMove = insertTempCopy(CurrentBB, TargetPacket, &*InstrToMove, - NeedCleanup); - NeedCleanup = true; - NeedToPredicate = true; - CleanupBB = CurrentBB; - - if (PredCond.empty() && // If not already predicated. - TII->PredicateInstruction(*InstrToMove, Cond)) { - LLVM_DEBUG(dbgs() << "\tNew predicated insn:\t"; - InstrToMove->dump()); - // After predication some instruction could become const extended: - // L2_loadrigp == "$dst=memw(#$global)" - // L4_ploadrit_abs == "if ($src1) $dst=memw(##$global)" - // Resource checking for those is different. - if ((QII->isExtended(*InstrToMove) || - QII->isConstExtended(*InstrToMove) || - isJumpOutOfRange(&*InstrToMove)) && - !tryAllocateResourcesForConstExt(&*InstrToMove, false)) { - // If we cannot, do not modify the state. - LLVM_DEBUG(dbgs() - << "\tEI Could not be added to the packet.\n"); - CleanupBB->erase(InstrToMove); - return false; - } - - if (!ResourceTracker->canReserveResources(*InstrToMove) || - !shouldAddToPacket(*InstrToMove)) { - // It will not fit in its new form... - LLVM_DEBUG(dbgs() << "\tCould not be added in its new form.\n"); - CurrentBB->erase(InstrToMove); - return false; - } - - // Need also verify that we can newify it if we want to. - if (NeedToNewify(InstrToMove, &DepReg, &*TargetPacket)) { - if (isNewifiable(InstrToMove, DepReg, &*TargetPacket)) { - MINeedToNewify = true; - LLVM_DEBUG(dbgs() << "\t\t\tNeeds to NEWify on Reg(" - << printReg(DepReg, QRI) << ").\n"); - } else { - LLVM_DEBUG(dbgs() << "\tNon newifiable in this bundle: "; - InstrToMove->dump()); - CleanupBB->erase(InstrToMove); - return false; - } - } - - LLVM_DEBUG(dbgs() << "\tUpdated BB:\n"; CurrentBB->dump()); - PredCond = Cond; - // Now the instruction uses the pred-reg as well. - if (!Cond.empty() && (Cond.size() == 2)) { - MIUseSet[OriginalInstructionToMove].push_back(Cond[1].getReg()); - } - assert(((Cond.size() <= 2) && - !(QII->isNewValueJump(Cond[0].getImm()))) && - "Update MIUseSet for new-value compare jumps"); - } else { - LLVM_DEBUG(dbgs() << "\tCould not predicate it\n"); - LLVM_DEBUG(dbgs() << "\tTrying to speculate!\t"; - InstrToMove->dump()); - bool DistantSpeculation = false; - std::vector NonPredPullUpPath; - unsigned btidx = 0; - // Generate a backtrack path for instruction to be speculated. - // Original backtrack may start from a different (ancestor) - // target packet. - while (btidx < backtrack.size()) { - const MachineBasicBlock *btBB = backtrack[btidx]->getParent(); - if ((btBB == PreviousBB) || (btBB == CurrentBB)) - NonPredPullUpPath.push_back(backtrack[btidx]); - ++btidx; - } - // Speculate only to immediate predecessor. - if (PreviousBB != CurrentBB) { - if (*(PreviousBB->pred_begin()) != CurrentBB) { - // In a region there are no side entries. - DistantSpeculation = true; - LLVM_DEBUG(dbgs() - << "\n\tMI not in immediate successor of BB#" - << CurrentBB->getNumber() << ", MI is in BB#" - << PreviousBB->getNumber();); - } - assert((PreviousBB->pred_size() < 2) && - "Region with a side entry"); - } - // TODO: Speculate ins. when pulled from unlikely path. - if (DistantSpeculation || /*!PathInRegion ||*/ - InstrToMove->mayLoad() || InstrToMove->mayStore() || - InstrToMove->hasUnmodeledSideEffects() || - !canMIBeSpeculated(&*InstrToMove, CurrentBB, PreviousBB, - NonPredPullUpPath)) { - CleanupBB->erase(InstrToMove); - return false; - } else { - // Save speculated instruction moved. - NeedToPredicate = false; - SpeculatedIns.insert( - std::make_pair(OriginalInstructionToMove, OriginBB)); - LLVM_DEBUG(dbgs() << "\nPredicable+SpeculatedInsToMove"; - InstrToMove->dump()); - } - } - } else { - // This is a non-predicable instruction. We still can try to - // speculate it here. - LLVM_DEBUG(dbgs() << "\tNon predicable insn!\t"; - InstrToMove->dump()); - // TODO: Speculate ins. when pulled from unlikely path. - if (!SpeculateNonPredInsn || !PathInRegion || - InstrToMove->mayLoad() || InstrToMove->mayStore() || - InstrToMove->hasUnmodeledSideEffects() || - !canMIBeSpeculated(&*InstrToMove, CurrentBB, PreviousBB, - PullUpPath)) { - if (NeedCleanup) - CleanupBB->erase(InstrToMove); - return false; - } else { - // Save speculated instruction moved. - SpeculatedIns.insert( - std::make_pair(OriginalInstructionToMove, OriginBB)); - LLVM_DEBUG(dbgs() << "\nNonPredicable+SpeculatedInsToMove"; - InstrToMove->dump()); - } - - InstrToMove = insertTempCopy(CurrentBB, TargetPacket, &*InstrToMove, - NeedCleanup); - NeedCleanup = true; - CleanupBB = CurrentBB; - } - } else { - // No branch. Fall through. - LLVM_DEBUG(dbgs() << "\tFall through BB.\n" - << "\tCurrentBB:" << CurrentBB->getNumber() - << "\tPreviousBB:" << PreviousBB->getNumber(); - if (PredFBB) dbgs() - << "\tPredFBB:" << PredFBB->getNumber();); - // Even though this is a fall though case, we still can - // have a dual jump situation here with a CALL involved. - // For now simply avoid it. - if (IsDualJumpSecondCandidate(&*InstrToMove)) { - llvm_unreachable("Dual jumps with known?"); - LLVM_DEBUG(dbgs() << "\tUnderimplemented dual jump formation.\n"); - if (NeedCleanup) - CleanupBB->erase(InstrToMove); - return false; - } - - if (!CurrentBB->isSuccessor(PreviousBB)) { - LLVM_DEBUG(dbgs() << "\tNon-successor fall through.\n"); - if (NeedCleanup) - CleanupBB->erase(InstrToMove); - return false; - } - SpeculatedIns.insert( - std::make_pair(OriginalInstructionToMove, OriginBB)); - LLVM_DEBUG(dbgs() << "\nSpeculatedInsToMove+FallThroughBB"; - InstrToMove->dump()); - // Create a temp copy. - InstrToMove = insertTempCopy(CurrentBB, TargetPacket, &*InstrToMove, - NeedCleanup); - NeedCleanup = true; - NeedToPredicate = false; - CleanupBB = CurrentBB; - LLVM_DEBUG(dbgs() << "\tUpdated BB:\n"; CurrentBB->dump()); - } - } - } - // If we have reached Home, great. - // Original check should have verified that instruction could be added - // to the target packet, so here we do nothing for deps. - if (MIWH == backtrack.front()) { - LLVM_DEBUG(dbgs() << "\tHOME!\n"); - break; - } - - // Test if we can reorder the two MIs. - // The exception is when we are forming dual jumps - we can pull up - // dependent instruction to the last bundle of an immediate predecesor - // of the current BB if control flow permits it. - // In this special case we also need to update the bundle we are moving - // from. - if (!(MovingDependentOp && (MIWH == &*SourceLocation)) && - !canReorderMIs(MIWH, &*InstrToMove)) { - if (NeedCleanup) - CleanupBB->erase(InstrToMove); - return false; - } - } - // We have previously tested this instruction, but has not updated the state - // for it. Do it now. - if (QII->isExtended(*InstrToMove) || QII->isConstExtended(*InstrToMove) || - isJumpOutOfRange(&*InstrToMove)) { - if (!tryAllocateResourcesForConstExt(&*InstrToMove)) - llvm_unreachable("Missed dependency test"); - } - - // Ok. We can safely move this instruction all the way up. - // We also potentially have a slot for it. - // During move original instruction could have changed (becoming predicated). - // Now try to place the final instance of it into the current packet. - LLVM_DEBUG(dbgs() << "\nWant to move "; - if (MovingDependentOp) dbgs() << "dependent op"; dbgs() << ": "; - InstrToMove->dump(); dbgs() << "To BB:\n"; HomeBB->dump(); - dbgs() << "From BB:\n"; OriginBB->dump()); - - // Keep these two statistics separately. - if (!isDualJump) - HexagonNumPullUps++; - else - HexagonNumDualJumps++; - - // This means we have not yet inserted the temp copy of InstrToMove - // in the target bundle. We are probably inside the same BB. - if (!NeedCleanup) { - InstrToMove = - insertTempCopy(HomeBB, TargetPacket, &*InstrToMove, NeedCleanup); - NeedCleanup = true; - } - - // No problems detected. Add it. - // If we were adding InstrToMove to a single, not yet packetized - // instruction, we need to create bundle header for it before proceeding. - // Be carefull since endPacket also resets the DFA state. - if (!TargetPacket->isBundle()) { - LLVM_DEBUG(dbgs() << "\tForm a new bundle.\n"); - finalizeBundle(*HomeBB, TargetPacket.getInstrIterator(), - std::next(InstrToMove)); - LLVM_DEBUG(HomeBB->dump()); - // Now we need to adjust pointer to the newly created packet header. - MachineBasicBlock::instr_iterator MII = TargetPacket.getInstrIterator(); - MII--; - - // Is it also on the way home? - for (unsigned i = 0; i < backtrack.size(); ++i) - if (backtrack[i] == &*TargetPacket) - backtrack[i] = &*MII; - - // Is it where our next MI is pointing? - if (NextMI == TargetPacket) - NextMI = MII; - TargetPacket = MII; - } - - // Move and Update Liveness info. - MoveAndUpdateLiveness(CurrentRegion, HomeBB, &*InstrToMove, MINeedToNewify, - DepReg, MovingDependentOp, OriginBB, - OriginalInstructionToMove, PredCond, SourceLocation, - TargetPacket, NextMI, backtrack); - - LLVM_DEBUG(dbgs() << "\n______Updated______\n"; HomeBB->dump(); - OriginBB->dump()); - - return true; -} - -/// Verify that we respect CFG layout during pull-up. -bool HexagonGlobalSchedulerImpl::isBranchWithinRegion( - BasicBlockRegion *CurrentRegion, MachineInstr *MI) { - assert(MI && MI->isBranch() && "Missing call info"); - - MachineBasicBlock *MBB = MI->getParent(); - LLVM_DEBUG(dbgs() << "\t[isBranchWithinRegion] BB(" << MBB->getNumber() - << ") Branch instr:\t"; - MI->dump()); - // If there is only one successor, it is safe to pull. - if (MBB->succ_size() <= 1) - return true; - // If there are multiple successors (jump table), we should - // not allow pull up over this instruction. - if (MBB->succ_size() > 2) - return false; - - MachineBasicBlock *NextRegionBB; - MachineBasicBlock *TBB, *FBB; - MachineInstr *FirstTerm = NULL; - MachineInstr *SecondTerm = NULL; - - if (AnalyzeBBBranches(MBB, TBB, FirstTerm, FBB, SecondTerm)) { - LLVM_DEBUG(dbgs() << "\t\tAnalyzeBBBranches failed!\n"); - return false; - } - - // If there is no jump in this BB, it simply falls through. - if (!FirstTerm) { - LLVM_DEBUG(dbgs() << "\t\tNo FirstTerm\n"); - return true; - } else if (QII->isEndLoopN(FirstTerm->getOpcode())) { - // We can easily analyze where endloop would take us - // but here it would be pointless either way since - // the region will not cross it. - LLVM_DEBUG(dbgs() << "\t\tEndloop terminator\n"); - return false; - } - // On some occasions we see code like this: - // BB#142: derived from LLVM BB %init, Align 4 (16 bytes) - // Live Ins: %R17 %R18 - // Predecessors according to CFG: BB#2 - // EH_LABEL - // J2_jump , %PC - // Successors according to CFG: BB#3(1048575) BB#138(1) - // It breaks most assumptions about CFG layout, so untill we know - // the source of it, let's have a safeguard. - if (MBB->succ_size() > 1 && !TII->isPredicated(*FirstTerm) && - !QII->isNewValueJump(*FirstTerm)) { - LLVM_DEBUG(dbgs() << "\t\tBadly formed BB.\n"); - return false; - } - - LLVM_DEBUG(dbgs() << "\t\tFirstTerm: "; FirstTerm->dump()); - LLVM_DEBUG(dbgs() << "\t\tSecondTerm: "; if (SecondTerm) SecondTerm->dump(); - else dbgs() << "None\n";); - - // All cases where there is only one branch in BB are OK to proceed. - if (!SecondTerm) - return true; - - assert(!QII->isEndLoopN(SecondTerm->getOpcode()) && "Found endloop."); - - // Find next BB in this region - if there is none, we will likely - // stop pulling in the next check outside of this function. - // This largely is don't care. - NextRegionBB = CurrentRegion->findNextMBB(MBB); - if (!NextRegionBB) { - LLVM_DEBUG(dbgs() << "\t\tNo next BB in the region...\n"); - return true; - } - LLVM_DEBUG(dbgs() << "\t\tNextRegionBB(" << NextRegionBB->getNumber() - << ")\n"); - assert(TBB && "Corrupt BB layout"); - // This means we are trying to pull into a packet _before_ the first - // branch in the MBB. - if (MI == FirstTerm) { - LLVM_DEBUG(dbgs() << "\t\tTBB(" << TBB->getNumber() - << ") NextBB in the region(" << NextRegionBB->getNumber() - << ")\n"); - return (TBB == NextRegionBB); - } - assert(FBB && "Corrupt BB layout"); - // This means we are trying to pull into the packet _after_ first branch, - // and it is OK if we pull from the second branch target. - // This pull is always speculative. - if ((MI != SecondTerm)) { - LLVM_DEBUG(dbgs() << "\t\tDual terminator not matching SecondTerm.\n"); - return false; - } - // Analyze the second branch in the BB. - LLVM_DEBUG(dbgs() << "\t\tFBB(" << FBB->getNumber() - << ") NextBB in the region(" << NextRegionBB->getNumber() - << ")\n"); - return (FBB == NextRegionBB); -} - -/// Check if a given instruction is: -/// - a jump to a distant target -/// - that exceeds its immediate range -/// If both conditions are true, it requires constant extension. -bool HexagonGlobalSchedulerImpl::isJumpOutOfRange(MachineInstr *UnCond, - MachineInstr *Cond) { - if (!UnCond || !UnCond->isBranch()) - return false; - - MachineBasicBlock *UnCondBB = UnCond->getParent(); - MachineBasicBlock *CondBB = Cond->getParent(); - MachineInstr *FirstTerm = &*(CondBB->getFirstInstrTerminator()); - // This might be worth an assert. - if (FirstTerm == &*CondBB->instr_end()) - return false; - - unsigned InstOffset = BlockToInstOffset[UnCondBB]; - unsigned Distance = 0; - - // To save time, estimate exact position of a branch instruction - // as one at the end of the UnCondBB. - // Number of instructions times typical instruction size. - InstOffset += (QII->nonDbgBBSize(UnCondBB) * HEXAGON_INSTR_SIZE); - - MachineBasicBlock *TBB = NULL, *FBB = NULL; - SmallVector CondList; - - // Find the target of the unconditional branch in UnCondBB, which is returned - // in TBB. Then use the CondBB to extract the FirsTerm. We desire to replace - // the branch target in FirstTerm with the branch location from the UnCondBB, - // provided it is within the distance of the opcode in FirstTerm. - if (QII->analyzeBranch(*UnCondBB, TBB, FBB, CondList, false)) - // Could not analyze it. give up. - return false; - - if (TBB && (Cond == FirstTerm)) { - Distance = - (unsigned)std::abs((long long)InstOffset - BlockToInstOffset[TBB]) + - SafetyBuffer; - return !QII->isJumpWithinBranchRange(*FirstTerm, Distance); - } - return false; -} - -// findBundleAndBranch returns the branch instruction and the -// bundle which contains it. Null is returned if not found. -MachineInstr *HexagonGlobalSchedulerImpl::findBundleAndBranch( - MachineBasicBlock *BB, MachineBasicBlock::iterator &Bundle) { - // Find the conditional branch out of BB. - if (!BB) - return NULL; - MachineInstr *CondBranch = NULL; - Bundle = BB->end(); - for (MachineBasicBlock::instr_iterator MII = BB->getFirstInstrTerminator(), - MBBEnd = BB->instr_end(); - MII != MBBEnd; ++MII) { - MachineInstr *MI = &*MII; - if (MII->isConditionalBranch()) { - CondBranch = MI; - } - } - if (!CondBranch) - return NULL; - MachineBasicBlock::instr_iterator MII = CondBranch->getIterator(); - if (!MII->isBundled()) - return NULL; - // Find bundle header. - for (--MII; MII->isBundled(); --MII) - if (MII->isBundle()) { - Bundle = MII; - break; - } - return CondBranch; -} - -// pullUpPeelBBLoop -// A single BB loop with a register copy at the beginning in its -// own bundle, benefits from eliminating the extra bundle. We do -// this by predicating the register copy in the predecessor BB, and -// again in the last bundle of the loop. -bool HexagonGlobalSchedulerImpl::pullUpPeelBBLoop(MachineBasicBlock *PredBB, - MachineBasicBlock *LoopBB) { - if (!AllowBBPeelPullUp) - return false; - if (!LoopBB || !PredBB) - return false; - - // We consider single BB loops only. Check for it here. - if (LoopBB->isEHPad() || LoopBB->hasAddressTaken()) - return false; - if (LoopBB->succ_size() != 2) - return false; - if (LoopBB->pred_size() != 2) - return false; - // Make sure one of the successors and one of the predecssors is to self. - if (!(LoopBB->isSuccessor(LoopBB) && LoopBB->isPredecessor(LoopBB))) - return false; - - // Find the none self successor block. We know we only have 2 successors. - MachineBasicBlock *SuccBB = NULL; - for (MachineBasicBlock::succ_iterator SI = LoopBB->succ_begin(), - SE = LoopBB->succ_end(); - SI != SE; ++SI) - if (*SI != LoopBB) { - SuccBB = *SI; - break; - } - if (!SuccBB) - return false; - - // Find the conditional branch and its bundle inside PredBB. - MachineBasicBlock::iterator PredBundle; - MachineInstr *PredCondBranch = NULL; - PredCondBranch = findBundleAndBranch(PredBB, PredBundle); - if (!PredCondBranch) - return false; - if (PredBundle == PredBB->end()) - return false; - LLVM_DEBUG(dbgs() << "PredBB's Branch: "); - LLVM_DEBUG(dbgs() << *PredCondBranch); - - // Look for leading reg copy as single bundle and make sure its live in. - MachineBasicBlock::instr_iterator FMI = LoopBB->instr_begin(); - // Skip debug instructions. - while (FMI->isDebugInstr()) - FMI++; - - MachineInstr *RegMI = &*FMI; - if (RegMI->isBundle()) - return false; - int TfrOpcode = RegMI->getOpcode(); - if (TfrOpcode != Hexagon::A2_tfr && TfrOpcode != Hexagon::A2_tfr) - return false; - if (!(RegMI->getOperand(0).isReg() && RegMI->getOperand(1).isReg())) - return false; - unsigned InLoopReg = RegMI->getOperand(1).getReg(); - if (!LoopBB->isLiveIn(InLoopReg)) - return false; - - // Create a region to pass to ResourcesAvailableInBundle. - BasicBlockRegion PUR(BasicBlockRegion(TII, QRI, PredBB)); - PUR.addBBtoRegion(LoopBB); - PUR.addBBtoRegion(SuccBB); - - // Make sure we have space in PredBB's last bundle. - if (!ResourcesAvailableInBundle(&PUR, PredBundle)) - return false; - SmallVector PredBundlePkt( - CurrentState.HomeBundle); - - // Find condition to use for predicating the reg copy into PredBB. - MachineBasicBlock *TBB = NULL, *FBB = NULL; - SmallVector Cond; - if (QII->analyzeBranch(*PredBB, TBB, FBB, Cond, false)) - return false; - if (Cond.empty()) - return false; - - // Find condition to use for predicating the reg copy at the end of LoopBB. - MachineBasicBlock *LTBB = NULL, *LFBB = NULL; - SmallVector LCond; - if (QII->analyzeBranch(*LoopBB, LTBB, LFBB, LCond, false)) - return false; - if (LCond.empty()) - return false; - - // Move predicated reg copy to previous BB's last bundle. - if (!TII->isPredicable(*RegMI)) - return false; - MachineInstr *InstrToMove = - &*insertTempCopy(PredBB, PredBundle, RegMI, false); - if (!canAddMIToThisPacket(InstrToMove, PredBundlePkt)) { - PredBB->erase_instr(InstrToMove); - return false; - } - - if (!TII->PredicateInstruction(*InstrToMove, Cond)) { - // Failed to predicate the copy reg. - PredBB->erase_instr(InstrToMove); - return false; - } - - // Can we newify this instruction? - unsigned DepReg = 0; - if (NeedToNewify(InstrToMove->getIterator(), &DepReg, &*PredBundle) && - !isNewifiable(InstrToMove->getIterator(), DepReg, &*PredBundle)) { - PredBB->erase_instr(InstrToMove); - return false; - } - // Newify it, and then undo it if we determine we are using a .old. - int NewOpcode = QII->getDotNewPredOp(*InstrToMove, MBPI); - // Undo newify if we have a non .new predicated jump we are matching. - if (!QII->isDotNewInst(*PredCondBranch)) - NewOpcode = QII->getDotOldOp(*InstrToMove); - NewOpcode = QII->getInvertedPredicatedOpcode(NewOpcode); - // Properly set the opcode on the new hoisted reg copy instruction. - InstrToMove->setDesc(QII->get(NewOpcode)); - if (!incrementalAddToPacket(*InstrToMove)) { - PredBB->erase_instr(InstrToMove); - return false; - } - - // Find the conditional branch and its bundle for LoopBB. - MachineBasicBlock::iterator LoopBundle; - MachineInstr *LoopCondBranch = NULL; - LoopCondBranch = findBundleAndBranch(LoopBB, LoopBundle); - if (!LoopCondBranch) - return false; - if (LoopBundle == LoopBB->end()) - return false; - LLVM_DEBUG(dbgs() << "LoopBB's Branch: "); - LLVM_DEBUG(dbgs() << *LoopCondBranch); - - // Make sure we have space in LoopBB's last bundle. - if (!ResourcesAvailableInBundle(&PUR, LoopBundle)) - return false; - SmallVector LoopBundlePkt( - CurrentState.HomeBundle); - - // Move predicated reg copy to last bundle of LoopBB. - MachineInstr *InstrToSink = - &*insertTempCopy(LoopBB, LoopBundle, RegMI, false); - if (!canAddMIToThisPacket(InstrToSink, LoopBundlePkt)) { - // Get rid of previous instruction as well. - PredBB->erase_instr(InstrToMove); - LoopBB->erase_instr(InstrToSink); - return false; - } - - if (!TII->PredicateInstruction(*InstrToSink, LCond)) { - // Get rid of previous instruction as well. - PredBB->erase_instr(InstrToMove); - LoopBB->erase_instr(InstrToSink); - return false; - } - // Can we newify this instruction? - if (NeedToNewify(InstrToSink->getIterator(), &DepReg, &*LoopBundle) && - !isNewifiable(InstrToSink->getIterator(), DepReg, &*LoopBundle)) { - // Get rid of previous instruction as well. - PredBB->erase_instr(InstrToMove); - PredBB->erase_instr(InstrToSink); - return false; - } - NewOpcode = QII->getDotNewPredOp(*InstrToSink, MBPI); - // Undo newify if we have a non .new predicated jump we are matching. - if (!QII->isDotNewInst(*LoopCondBranch)) - NewOpcode = QII->getDotOldOp(*InstrToSink); - InstrToSink->setDesc(QII->get(NewOpcode)); - if (!incrementalAddToPacket(*InstrToSink)) { - // Get rid of previous instruction as well. - PredBB->erase_instr(InstrToMove); - LoopBB->erase_instr(InstrToSink); - return false; - } - - // Remove old instruction. - LoopBB->erase_instr(RegMI); - // Set loop alignment to 32. - LoopBB->setAlignment(llvm::Align(32)); - - LLVM_DEBUG(dbgs() << "Peeled Single BBLoop copy\n"); - LLVM_DEBUG(dbgs() << *InstrToMove); - LLVM_DEBUG(dbgs() << *InstrToSink); - LLVM_DEBUG(dbgs() << *PredBB); - LLVM_DEBUG(dbgs() << *LoopBB); - LLVM_DEBUG(dbgs() << *SuccBB); - LLVM_DEBUG(dbgs() << "--- BBLoop ---\n\n"); - return true; -} - -bool HexagonGlobalSchedulerImpl::performPullUpCFG(MachineFunction &Fn) { - const Function &F = Fn.getFunction(); - // Check for single-block functions and skip them. - if (std::next(F.begin()) == F.end()) - return false; - bool Changed = false; - LLVM_DEBUG(dbgs() << "****** PullUpCFG **************\n"); - - // Loop over all basic blocks, asking if 3 consecutive blocks are - // the jump opportunity. - MachineBasicBlock *PrevBlock = NULL; - MachineBasicBlock *JumpBlock = NULL; - for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); MBB != MBBe; - ++MBB) { - MachineBasicBlock *FallBlock = &*MBB; - if (PrevBlock && JumpBlock) { - Changed |= pullUpPeelBBLoop(PrevBlock, JumpBlock); - } - PrevBlock = JumpBlock; - JumpBlock = FallBlock; - } - return Changed; -} - -void HexagonGlobalSchedulerImpl::GenUseDefChain(MachineFunction &Fn) { - std::vector Defs; - std::vector Uses; - for (MachineFunction::iterator MBBIter = Fn.begin(); MBBIter != Fn.end(); - ++MBBIter) { - for (MachineBasicBlock::instr_iterator MIter = MBBIter->instr_begin(); - MIter != MBBIter->instr_end(); ++MIter) { - if (MIter->isBundle() || MIter->isDebugInstr()) - continue; - LLVM_DEBUG(dbgs() << "\n\nInserted Ins:"; MIter->dump()); - MIUseDefSet(&*MIter, Defs, Uses); - LLVM_DEBUG(dbgs() << "\n\tDefs:"; - for (unsigned i = 0; i < Defs.size(); ++i) dbgs() - << printReg(Defs[i], QRI) << ","); - LLVM_DEBUG(dbgs() << "\n\tUses:"; - for (unsigned i = 0; i < Uses.size(); ++i) dbgs() - << printReg(Uses[i], QRI) << ","); - MIDefSet[&*MIter] = Defs; - MIUseSet[&*MIter] = Uses; - } - } -} - -// optimizeBranching - -// 1. A conditional-jump transfers control to a BB with -// jump as the only instruction. -// if(p0) jump t1 -// // ... -// t1: jump t2 -// 2. When a BB with a single conditional jump, jumps to succ-of-succ and -// falls-through BB with only jump instruction. -// { if(p0) jump t1 } -// { jump t2 } -// t1: { ... } -MachineBasicBlock *HexagonGlobalSchedulerImpl::optimizeBranches( - MachineBasicBlock *MBB, MachineBasicBlock *TBB, MachineInstr *FirstTerm, - MachineBasicBlock *FBB) { - LLVM_DEBUG(dbgs() << "\n\t\t[optimizeBranching]\n"); - if ((TBB == MBB) || (FBB == MBB)) - LLVM_DEBUG(dbgs() << "Cannot deal with loops in BB#" << MBB->getNumber();); - - // LLVM_DEBUG(dbgs() << "\n\t\tTBBMIb:"; MII->dump();); - // { if(p) jump t1; } - // t1: { jump t2; } - // --> { if(p) jump t2 - // remove t1: { jump t2; }, if it's address is not taken/not a landing pad. - if (QII->nonDbgBBSize(TBB) == 1) { - MachineInstr *TBBMIb = &*TBB->getFirstNonDebugInstr(); - if (TBBMIb->getOpcode() == Hexagon::J2_jump && - TBBMIb->getOperand(0).isMBB()) { - MachineBasicBlock *NewTarget = TBBMIb->getOperand(0).getMBB(); - if (TBB == NewTarget) // Infinite loop. - return NULL; - - LLVM_DEBUG(dbgs() << "\nSuboptimal branching in TBB"); - // Check if the jump in the last instruction is within range. - int64_t InstOffset = - BlockToInstOffset.find(MBB)->second + QII->nonDbgBBSize(MBB) * 4; - unsigned Distance = (unsigned)std::abs( - InstOffset - BlockToInstOffset.find(NewTarget)->second); - if (!QII->isJumpWithinBranchRange(*FirstTerm, Distance)) { - LLVM_DEBUG(dbgs() << "\nUnconditional jump target:" << Distance - << " out of range."); - return NULL; - } - // We need to make sure that the TBB is _not_ also a target for another - // branch. This is suboptimal since theoretically we can update both - // branches. - if (!TBB->hasAddressTaken() && !TBB->isEHPad() && TBB->pred_size() == 1) { - updatePredecessors(*TBB, NewTarget); - // TBB has only one successor since only one J2_jump instr. - TBB->removeSuccessor(TBB->succ_begin()); - TBBMIb->removeFromParent(); - if (!TBB->empty()) { - // There are only debug instructions in TBB now. Move them to - // the beginning of NewTarget. - NewTarget->splice(NewTarget->getFirstNonPHI(), TBB, TBB->begin(), - TBB->end()); - } - return TBB; - } else { - MBB->ReplaceUsesOfBlockWith(TBB, NewTarget); - return NULL; - } - } - } - // { if(p) jump t1; } may contain more instructions - // { jump t2; } --only one instruction - // t1: {...} - // TBB is layout successor of FBB, then we can change the branch target - // for conditional jump and invert the predicate to remove jump t2. - // { if(!p) jump t2; } - // t1: {...} - if (QII->nonDbgBBSize(FBB) == 1) { - MachineInstr *FBBMIb = &*FBB->getFirstNonDebugInstr(); - if (FBBMIb->getOpcode() == Hexagon::J2_jump && - FBBMIb->getOperand(0).isMBB()) { - MachineBasicBlock *NewTarget = FBBMIb->getOperand(0).getMBB(); - if (FBB->hasAddressTaken() || FBB->isEHPad() || - !FBB->isLayoutSuccessor(TBB) || (FBB == NewTarget /*Infinite loop*/)) - return NULL; - - LLVM_DEBUG(dbgs() << "\nSuboptimal branching in FBB"); - // Check if the jump in the last instruction is within range. - int64_t InstOffset = - BlockToInstOffset.find(MBB)->second + QII->nonDbgBBSize(MBB) * 4; - unsigned Distance = (unsigned)std::abs( - InstOffset - BlockToInstOffset.find(NewTarget)->second); - if (!QII->isJumpWithinBranchRange(*FirstTerm, Distance)) { - LLVM_DEBUG(dbgs() << "\nUnconditional jump target:" << Distance - << " out of range."); - return NULL; - } - if (!QII->invertAndChangeJumpTarget(*FirstTerm, NewTarget)) - return NULL; - LLVM_DEBUG(dbgs() << "\nNew instruction:"; FirstTerm->dump();); - updatePredecessors(*FBB, NewTarget); - // Only one successor remains for FBB - FBB->removeSuccessor(FBB->succ_begin()); - FBBMIb->removeFromParent(); - return FBB; - } - } - return NULL; -} - -// performExposedOptimizations - -// look for optimization opportunities after pullup. -// e.g. jump to adjacent targets -bool HexagonGlobalSchedulerImpl::performExposedOptimizations( - MachineFunction &Fn) { - // Check for single-block functions and skip them. - if (std::next(Fn.getFunction().begin()) == Fn.getFunction().end()) - return true; - LLVM_DEBUG(dbgs() << "\n\t\t[performExposedOptimizations]\n"); - // Erasing the empty basic blocks formed during pullup. - std::vector::iterator ebb = EmptyBBs.begin(); - while (ebb != EmptyBBs.end()) { - assert(IsEmptyBlock(*ebb) && "Pullup inserted packets into an empty BB"); - LLVM_DEBUG(dbgs() << "Removing BB(" << (*ebb)->getNumber() - << ") from parent.\n"); - (*ebb)->eraseFromParent(); - ++ebb; - } - MachineBasicBlock *TBB = NULL, *FBB = NULL; - MachineInstr *FirstTerm = NULL, *SecondTerm = NULL; - - SmallVector Erase; - - for (MachineBasicBlock &MBB : Fn) { - if (MBB.succ_size() > 2 || - AnalyzeBBBranches(&MBB, TBB, FirstTerm, FBB, SecondTerm)) { - LLVM_DEBUG(dbgs() << "\nAnalyzeBBBranches failed in BB#" - << MBB.getNumber() << "\n";); - continue; - } - if (FirstTerm && QII->isCompoundBranchInstr(*FirstTerm)) - continue; - if (TBB && FirstTerm && - removeRedundantBranches(&MBB, TBB, FirstTerm, FBB, SecondTerm)) { - LLVM_DEBUG(dbgs() << "\nRemoved redundant branches in BB#" - << MBB.getNumber();); - continue; - } - if (FirstTerm && SecondTerm && - optimizeDualJumps(&MBB, TBB, FirstTerm, FBB, SecondTerm)) { - LLVM_DEBUG(dbgs() << "\nRemoved dual jumps in in BB#" - << MBB.getNumber();); - continue; - } - if (TBB && FBB && FirstTerm && !SecondTerm) { - MachineBasicBlock *MBBToErase = - optimizeBranches(&MBB, TBB, FirstTerm, FBB); - if (MBBToErase) { - assert(IsEmptyBlock(MBBToErase) && "Erasing non-empty BB"); - Erase.push_back(MBBToErase); - LLVM_DEBUG(dbgs() << "\nOptimized jump from BB#" << MBB.getNumber()); - } - } - } - for (MachineBasicBlock *MBB : Erase) - MBB->eraseFromParent(); - - return false; -} - -// 1. Remove jump to the layout successor. -// 2. Remove multiple (dual) jump to the same target. -bool HexagonGlobalSchedulerImpl::removeRedundantBranches( - MachineBasicBlock *MBB, MachineBasicBlock *TBB, MachineInstr *FirstTerm, - MachineBasicBlock *FBB, MachineInstr *SecondTerm) { - bool Analyzed = false; - LLVM_DEBUG(dbgs() << "\n\t\t[removeRedundantBranches]\n"); - MachineInstr *Head = NULL, *ToErase = NULL; - if (!FBB && (FirstTerm->getOpcode() == Hexagon::J2_jump) && - MBB->isLayoutSuccessor(TBB)) { - // Jmp layout_succ_basic_block <-- Remove - LLVM_DEBUG( - dbgs() << "\nRemoving Uncond. jump to the layout successor in BB#" - << MBB->getNumber()); - ToErase = FirstTerm; - } else if (SecondTerm && (TBB == FBB) && - (SecondTerm->getOpcode() == Hexagon::J2_jump)) { - // If both branching instructions in same packet or are consecutive. - // Jmp_c t1 <-- Remove - // Jmp t1 - // @Note: If they are in different packets or if they are separated - // by packet(s), this opt. cannot be done. - MachineBasicBlock::instr_iterator FirstTermIter = FirstTerm->getIterator(); - MachineBasicBlock::instr_iterator SecondTermIter = - SecondTerm->getIterator(); - if (++FirstTermIter == SecondTermIter) { - LLVM_DEBUG(dbgs() << "\nRemoving multiple branching to same target in BB#" - << MBB->getNumber()); - // TODO: This might make the `p' register assignment instruction dead. - // and can be removed. - ToErase = FirstTerm; - } - } else if (SecondTerm && (SecondTerm->getOpcode() == Hexagon::J2_jump) && - FBB && MBB->isLayoutSuccessor(FBB)) { - // Jmp_c t1 - // Jmp layout_succ_basic_block <-- Remove - LLVM_DEBUG(dbgs() << "\nRemoving fall through branch in BB#" - << MBB->getNumber()); - ToErase = SecondTerm; - } else if (SecondTerm && QII->PredOpcodeHasJMP_c(SecondTerm->getOpcode()) && - MBB->isLayoutSuccessor(getBranchDestination(SecondTerm))) { - // Jmp_c t1 - // Jmp_c layout_succ_basic_block <-- Remove - // In this case AnalyzeBBBranches might assign FBB to some other BB. - // So using the jump target of SecondTerm to check. - LLVM_DEBUG(dbgs() << "\nRemoving Cond. jump to the layout successor in BB#" - << MBB->getNumber()); - ToErase = SecondTerm; - } - // Remove the instruction from the BB - if (ToErase) { - if (ToErase->isBundled()) { - Head = &*getBundleStart(ToErase->getIterator()); - ToErase->eraseFromBundle(); - UpdateBundle(Head); - } else - ToErase->eraseFromParent(); - Analyzed = true; - } - return Analyzed; -} - -// ----- convert -// p = -// if(p) jump layout_succ_basic_block -// jump t -// ----- to -// p = -// if(!p) jump t -// for now only looking at the dual jump -bool HexagonGlobalSchedulerImpl::optimizeDualJumps(MachineBasicBlock *MBB, - MachineBasicBlock *TBB, - MachineInstr *FirstTerm, - MachineBasicBlock *FBB, - MachineInstr *SecondTerm) { - LLVM_DEBUG(dbgs() << "\n******* optimizeDualJumps *******"); - - bool Analyzed = false; - - if (QII->PredOpcodeHasJMP_c(FirstTerm->getOpcode()) && - (SecondTerm->getOpcode() == Hexagon::J2_jump)) { - - if (TBB == FBB) { - LLVM_DEBUG(dbgs() << "\nBoth successors are the same."); - return Analyzed; - } - - // Do not optimize for dual jumps if this MBB - // contains a speculatively pulled-up instruction. - // A speculated instruction is more likely to be at the end of MBB. - MachineBasicBlock::reverse_instr_iterator SII = MBB->instr_rbegin(); - while (SII != MBB->instr_rend()) { - MachineInstr *SI = &*SII; - std::map::iterator MIMoved; - MIMoved = SpeculatedIns.find(SI); - if ((MIMoved != SpeculatedIns.end()) && - (MIMoved->second != SI->getParent())) { - return Analyzed; - } - ++SII; - } - - LLVM_DEBUG(dbgs() << "\nCandidate for jump optimization in BB(" - << MBB->getNumber() << ").\n";); - - // Predicated jump to layout successor followed by an unconditional jump. - if (MBB->isLayoutSuccessor(TBB)) { - - // Check if the jump in the last instruction is within range. - int64_t InstOffset = - BlockToInstOffset.find(&*MBB)->second + QII->nonDbgBBSize(MBB) * 4; - unsigned Distance = - (unsigned)std::abs(InstOffset - BlockToInstOffset.find(FBB)->second) + - SafetyBuffer; - if (!QII->isJumpWithinBranchRange(*FirstTerm, Distance)) { - LLVM_DEBUG(dbgs() << "\nUnconditional jump target:" << Distance - << " out of range."); - return Analyzed; - } - - // modify the second last -predicated- instruction (sense and target) - LLVM_DEBUG(dbgs() << "\nFirst Instr:" << *FirstTerm;); - LLVM_DEBUG(dbgs() << "\nSecond Instr:" << *SecondTerm;); - LLVM_DEBUG(dbgs() << "\nOld Succ BB(" << TBB->getNumber() << ").";); - - QII->invertAndChangeJumpTarget(*FirstTerm, FBB); - - LLVM_DEBUG(dbgs() << "\nNew First Instruction:" << *FirstTerm;); - - // unbundle if there is only one instruction left - MachineInstr *SecondHead, *FirstHead; - FirstHead = FirstTerm->isBundled() - ? &*getBundleStart(FirstTerm->getIterator()) - : nullptr; - SecondHead = SecondTerm->isBundled() - ? &*getBundleStart(SecondTerm->getIterator()) - : nullptr; - - // 1. Both unbundled, 2. FirstTerm inside bundle, second outside. - if (!SecondHead) - SecondTerm->eraseFromParent(); - else if (!FirstHead) { - // 3. FirstHead outside, SecondHead inside. - SecondTerm->eraseFromBundle(); - UpdateBundle(SecondHead); - } else if (FirstHead == SecondHead) { - // 4. Both are in the same bundle - assert((FirstHead && SecondHead) && "Unbundled Instruction"); - SecondTerm->eraseFromBundle(); - if (SecondHead->getBundleSize() < 2) - UpdateBundle(SecondHead); - } else { - // 5. Both are in different bundles - SecondTerm->eraseFromBundle(); - UpdateBundle(SecondHead); - } - Analyzed = true; - } - } - return Analyzed; -} - -/// Are there any resources left in this bundle? -bool HexagonGlobalSchedulerImpl::ResourcesAvailableInBundle( - BasicBlockRegion *CurrentRegion, - MachineBasicBlock::iterator &TargetPacket) { - MachineBasicBlock::instr_iterator MII = TargetPacket.getInstrIterator(); - - // If this is a single instruction, form new packet around it. - if (!TargetPacket->isBundle()) { - if (ignoreInstruction(&*MII) || isSoloInstruction(*MII)) - return false; - - // Before we begin, we need to make sure that we do not - // look at an unconditional jump outside the current region. - if (MII->isBranch() && !isBranchWithinRegion(CurrentRegion, &*MII)) - return false; - - // Build up state for this new packet. - // Note, we cannot create a bundle header for it, - // so this "bundle" only exist in DFA state, and not in code. - initPacketizerState(); - ResourceTracker->clearResources(); - CurrentState.addHomeLocation(MII); - return incrementalAddToPacket(*MII); - } - - MachineBasicBlock::instr_iterator End = MII->getParent()->instr_end(); - - // Build up state for this packet. - initPacketizerState(); - ResourceTracker->clearResources(); - CurrentState.addHomeLocation(MII); - - for (++MII; MII != End && MII->isInsideBundle(); ++MII) { - if (MII->getOpcode() == TargetOpcode::DBG_VALUE || - MII->getOpcode() == TargetOpcode::IMPLICIT_DEF || - MII->getOpcode() == TargetOpcode::CFI_INSTRUCTION || MII->isEHLabel()) - continue; - - // Before we begin, we need to make sure that we do not - // look at an unconditional jump outside the current region. - // TODO: See if we can profit from handling this kind of cases: - // B#15: derived from LLVM BB %if.then22 - // Predecessors according to CFG: BB#13 - // BUNDLE %PC, %P2 - // * J2_jumpf %P2, , %PC; flags: - // * J2_jump , %PC; flags: - // Successors according to CFG: BB#18(62) BB#17(62) - // Curently we do not allow them. - if (MII->isBranch() && !isBranchWithinRegion(CurrentRegion, &*MII)) - return false; - - if (!incrementalAddToPacket(*MII)) - return false; - } - return ResourceTracker->canReserveResources(*Nop); -} - -/// Symmetrical. See if these two instructions are fit for compound pair. -bool HexagonGlobalSchedulerImpl::isCompoundPair(MachineInstr *MIa, - MachineInstr *MIb) { - enum HexagonII::CompoundGroup MIaG = QII->getCompoundCandidateGroup(*MIa), - MIbG = QII->getCompoundCandidateGroup(*MIb); - // We have two candidates - check that this is the same register - // we are talking about. - unsigned Opcb = MIb->getOpcode(); - if (MIaG == HexagonII::HCG_C && MIbG == HexagonII::HCG_A && - (Opcb == Hexagon::A2_tfr || Opcb == Hexagon::A2_tfrsi)) - return true; - unsigned Opca = MIa->getOpcode(); - if (MIbG == HexagonII::HCG_C && MIaG == HexagonII::HCG_A && - (Opca == Hexagon::A2_tfr || Opca == Hexagon::A2_tfrsi)) - return true; - return (((MIaG == HexagonII::HCG_A && MIbG == HexagonII::HCG_B) || - (MIbG == HexagonII::HCG_A && MIaG == HexagonII::HCG_B)) && - (MIa->getOperand(0).getReg() == MIb->getOperand(0).getReg())); -} - -// This is a weird situation when BB conditionally branches + falls through -// to layout successor. \ref bug17792 -inline bool HexagonGlobalSchedulerImpl::multipleBranchesFromToBB( - MachineBasicBlock *BB) const { - if (BB->succ_size() != 1) - return false; - SmallVector Jumpers = QII->getBranchingInstrs(*BB); - return ((Jumpers.size() == 1) && !Jumpers[0]->isUnconditionalBranch()); -} - -/// Gather a worklist of MaxCandidates pull-up candidates. -/// Compute relative cost. -bool HexagonGlobalSchedulerImpl::findPullUpCandidates( - MachineBasicBlock::iterator &WorkPoint, - MachineBasicBlock::iterator &FromHere, - std::vector &backtrack, unsigned MaxCandidates = 1) { - - const HexagonInstrInfo *QII = (const HexagonInstrInfo *)TII; - MachineBasicBlock *FromThisBB = FromHere->getParent(); - bool MovingDependentOp = false; - signed CostBenefit = 0; - - // Do not collect more than that many candidates. - if (CurrentState.haveCandidates() >= MaxCandidates) - return false; - - LLVM_DEBUG(dbgs() << "\n\tTry from BB(" << FromThisBB->getNumber() << "):\n"; - DumpPacket(FromHere.getInstrIterator())); - - if (FromHere->isBundle()) { - MachineBasicBlock::instr_iterator MII = FromHere.getInstrIterator(); - for (++MII; MII != FromThisBB->instr_end() && MII->isInsideBundle(); - ++MII) { - if (MII->isDebugInstr()) - continue; - LLVM_DEBUG(dbgs() << "\tCandidate from BB(" - << MII->getParent()->getNumber() << "): "; - MII->dump()); - - // See if this instruction could be moved. - if (!canThisMIBeMoved(&*MII, WorkPoint, MovingDependentOp, CostBenefit)) - continue; - - MachineBasicBlock::instr_iterator InstrToMove = MII; - if (canAddMIToThisPacket(&*InstrToMove, CurrentState.HomeBundle)) { - CostBenefit -= (backtrack.size() * 4); - // Prefer instructions in empty packets. - CostBenefit += (PacketSize - nonDbgBundleSize(FromHere)) * 2; - // Prefer Compares. - if (MII->isCompare()) - CostBenefit += 10; - // Check duplex conditions; - for (unsigned i = 0; i < CurrentState.HomeBundle.size(); i++) { - if (QII->isDuplexPair(*CurrentState.HomeBundle[i], *MII)) { - LLVM_DEBUG(dbgs() << "\tGot real Duplex (bundle).\n"); - CostBenefit += 20; - } - if (isCompoundPair(CurrentState.HomeBundle[i], &*MII)) { - LLVM_DEBUG(dbgs() << "\tGot compound (bundle).\n"); - CostBenefit += 40; - } - } - // Create a record for this location. - CurrentState.addPullUpCandidate(InstrToMove, WorkPoint, backtrack, - MovingDependentOp, CostBenefit); - } else - LLVM_DEBUG(dbgs() << "\tNo resources in the target packet.\n"); - } - } - // This is a standalone instruction. - // First see if this MI can even be moved. Cost model for a single instruction - // should be rather different from moving something out of a bundle. - else if (canThisMIBeMoved(&*FromHere, WorkPoint, MovingDependentOp, - CostBenefit)) { - MachineBasicBlock::instr_iterator InstrToMove = FromHere.getInstrIterator(); - if (canAddMIToThisPacket(&*InstrToMove, CurrentState.HomeBundle)) { - CostBenefit -= (backtrack.size() * 4); - // Prefer Compares. - if (InstrToMove->isCompare()) - CostBenefit += 10; - // It is better to pull a single instruction in to a bundle - save - // a cycle immediately. - CostBenefit += 10; - // Search for duplex match. - for (unsigned i = 0; i < CurrentState.HomeBundle.size(); i++) { - if (QII->isDuplexPair(*CurrentState.HomeBundle[i], *InstrToMove)) { - LLVM_DEBUG(dbgs() << "\tGot real Duplex (single).\n"); - CostBenefit += 30; - } - if (isCompoundPair(CurrentState.HomeBundle[i], &*InstrToMove)) { - LLVM_DEBUG(dbgs() << "\tGot compound (single).\n"); - CostBenefit += 50; - } - } - // Create a record for this location. - CurrentState.addPullUpCandidate(InstrToMove, WorkPoint, backtrack, - MovingDependentOp, CostBenefit); - } else - LLVM_DEBUG(dbgs() << "\tNo resources for single in the target packet.\n"); - } - return true; -} - -/// Try to move a candidate MI. -/// The move can destroy all iterator system, so we have to drag them -/// around to keep them up to date. -bool HexagonGlobalSchedulerImpl::tryMultipleInstructions( - MachineBasicBlock::iterator &RetVal, /* output parameter */ - std::vector::iterator &CurrentRegion, - MachineBasicBlock::iterator &NextMI, - MachineBasicBlock::iterator &ToThisBBEnd, - MachineBasicBlock::iterator &FromThisBBEnd, bool PathInRegion) { - - MachineBasicBlock::instr_iterator MII; - MachineBasicBlock::iterator WorkPoint; - bool MovingDependentOp = false; - std::vector backtrack; - - LLVM_DEBUG(dbgs() << "\n\tTry Multiple candidates: \n"); - - std::sort(CurrentState.PullUpCandidates.begin(), - CurrentState.PullUpCandidates.end(), PullUpCandidateSorter()); - LLVM_DEBUG(CurrentState.dump()); - // Iterate through candidates in sorted order. - for (SmallVector::iterator - I = CurrentState.PullUpCandidates.begin(), - E = CurrentState.PullUpCandidates.end(); - I != E; ++I) { - (*I)->populate(MII, WorkPoint, backtrack, MovingDependentOp); - - MachineBasicBlock *FromThisBB = MII->getParent(); - MachineBasicBlock *ToThisBB = WorkPoint->getParent(); - - LLVM_DEBUG(dbgs() << "\n\tCandidate: "; MII->dump()); - LLVM_DEBUG(dbgs() << "\tDependent(" << MovingDependentOp << ") FromBB(" - << FromThisBB->getNumber() << ") ToBB(" - << ToThisBB->getNumber() << ") to this packet:\n"; - DumpPacket(WorkPoint.getInstrIterator())); - - MachineBasicBlock::instr_iterator FromHereII = MII; - if (MII->isInsideBundle()) { - while (!FromHereII->isBundle()) - --FromHereII; - LLVM_DEBUG(dbgs() << "\tFrom here:\n"; DumpPacket(FromHereII)); - - MachineBasicBlock::iterator FromHere(FromHereII); - // We have instruction that could be moved from its current position. - if (MoveMItoBundle(*CurrentRegion, MII, NextMI, WorkPoint, FromHere, - backtrack, MovingDependentOp, PathInRegion)) { - // If BB from which we pull is now empty, move on. - if (IsEmptyBlock(FromThisBB)) { - LLVM_DEBUG(dbgs() << "\n\tExhosted BB (bundle).\n"); - return false; - } - FromThisBBEnd = FromThisBB->end(); - ToThisBBEnd = ToThisBB->end(); - - LLVM_DEBUG(dbgs() << "\n\tAfter updates(bundle to bundle):\n"); - LLVM_DEBUG(dbgs() << "\t\tWorkPoint: "; - DumpPacket(WorkPoint.getInstrIterator())); - - // We should not increment current position, - // but rather try one more time to pull from the same bundle. - RetVal = WorkPoint; - return true; - } else - LLVM_DEBUG(dbgs() << "\tCould not move packetized instr.\n"); - } else { - MachineBasicBlock::iterator FromHere(FromHereII); - if (MoveMItoBundle(*CurrentRegion, MII, NextMI, WorkPoint, FromHere, - backtrack, MovingDependentOp, PathInRegion)) { - - // If BB from which we pull is now empty, move on. - if (IsEmptyBlock(FromThisBB)) { - LLVM_DEBUG(dbgs() << "\n\tExhosted BB (single).\n"); - return false; - } - FromThisBBEnd = FromThisBB->end(); - ToThisBBEnd = ToThisBB->end(); - - LLVM_DEBUG(dbgs() << "\tAfter updates (single to bundle):\n"); - LLVM_DEBUG(dbgs() << "\t\tWorkPoint: "; - DumpPacket(WorkPoint.getInstrIterator())); - // We should not increment current position, - // but rather try one more time to pull from the same bundle. - RetVal = WorkPoint; - return true; - } else - LLVM_DEBUG(dbgs() << "\tCould not move single.\n"); - } - } - LLVM_DEBUG(dbgs() << "\tNot a single candidate fit.\n"); - return false; -} - -/// Main function. Iterate all current regions one at a time, -/// and look for pull-up opportunities. -/// Pseudo sequence: -/// - for all bundles and single instructions in region: -/// - see if resources are available (in the same cycle) - this is HOME. -/// - Starting from next BB in region, find an instruction that could be: -/// - removed from its current location -/// - added to underutilized bundle (including bundles with only one op) -/// - If so, trace path back to HOME and check that candidate could be -/// reordered with all the intermediate instructions. -bool HexagonGlobalSchedulerImpl::performPullUp() { - MachineBasicBlock::iterator FromHere; - std::vector backtrack; - - LLVM_DEBUG(dbgs() << "****** PullUpRegions ***********\n"); - // For all regions... - for (std::vector::iterator - CurrentRegion = PullUpRegions.begin(), - E = PullUpRegions.end(); - CurrentRegion != E; ++CurrentRegion) { - - LLVM_DEBUG(dbgs() << "\n\nRegion with(" << (*CurrentRegion)->size() - << ")BBs\n"); - - if (!EnableLocalPullUp && (*CurrentRegion)->size() < 2) - continue; - - // For all MBB in the region... except the last one. - // ...except when we want to allow local pull-up. - for (auto ToThisBB = (*CurrentRegion)->getRootMBB(), - LastBBInRegion = (*CurrentRegion)->getLastMBB(); - ToThisBB != LastBBInRegion; ++ToThisBB) { - // If we do not want to allow same BB pull-up, take an early exit. - if (!EnableLocalPullUp && (std::next(ToThisBB) == LastBBInRegion)) - break; - if (multipleBranchesFromToBB(*ToThisBB)) - break; - - auto FromThisBB = ToThisBB; - MachineBasicBlock::iterator ToThisBBEnd = (*ToThisBB)->end(); - MachineBasicBlock::iterator MI = (*ToThisBB)->begin(); - MachineBasicBlock::iterator FromThisBBEnd; - - LLVM_DEBUG(dbgs() << "\n\tHome iterator moved to new BB(" - << (*ToThisBB)->getNumber() << ")\n"; - (*ToThisBB)->dump()); - - // For all instructions in the BB. - while (MI != ToThisBBEnd) { - MachineBasicBlock::iterator WorkPoint = MI; - ++MI; - - // Trivial check that there are unused resources - // in the current location (cycle). - while (ResourcesAvailableInBundle(*CurrentRegion, WorkPoint)) { - LLVM_DEBUG(dbgs() << "\nxxxx Next Home in BB(" - << (*ToThisBB)->getNumber() << "):\n"; - DumpPacket(WorkPoint.getInstrIterator())); - // Keep the path to the candidate. - // It is the traveled path between home and work point. - // Reset it for the new iteration. - backtrack.clear(); - - // The point of pull-up source (WorkPoint) could begin from the - // current BB, but only if we allow pull-up in the same BB. - // At the moment we do not. - // We also do not process last block in the region, - // so it is safe to always begin with the next BB in the region. - // Start from "next" BB in the region. - if (EnableLocalPullUp) { - FromThisBB = ToThisBB; - FromHere = WorkPoint; - ++FromHere; - FromThisBBEnd = (*FromThisBB)->end(); - - // Initialize backtrack. - // These are instructions between Home location - // and the WorkPoint. - for (MachineBasicBlock::iterator I = WorkPoint, IE = FromHere; - I != IE; ++I) - backtrack.push_back(&*I); - } else { - FromThisBB = ToThisBB; - ++FromThisBB; - FromHere = (*FromThisBB)->begin(); - FromThisBBEnd = (*FromThisBB)->end(); - - // Initialize backtrack. - // These are instructions between Home location - // and the end of the home BB. - for (MachineBasicBlock::iterator I = WorkPoint, IE = ToThisBBEnd; - I != IE; ++I) - backtrack.push_back(&*I); - } - - // Search for pull-up candidate. - while (true) { - // If this BB is over, move onto the next one - // in this region. - if (FromHere == FromThisBBEnd) { - ++FromThisBB; - if (FromThisBB == LastBBInRegion) - break; - else { - LLVM_DEBUG(dbgs() << "\n\tNext BB in this region\n"; - (*FromThisBB)->dump()); - FromThisBBEnd = (*FromThisBB)->end(); - FromHere = (*FromThisBB)->begin(); - if (FromThisBBEnd == FromHere) - break; - } - } - if ((*FromHere).isDebugInstr()) { - ++FromHere; - continue; - } - // This is a step Home. - backtrack.push_back(&*FromHere); - if (!findPullUpCandidates(WorkPoint, FromHere, backtrack, - MainCandidateQueueSize)) - break; - ++FromHere; - } - // Try to pull-up one of the selected candidates. - if (!tryMultipleInstructions(/*output*/ WorkPoint, CurrentRegion, MI, - ToThisBBEnd, FromThisBBEnd)) - break; - } - } - } - // AllowUnlikelyPath is on by default, - // if we wish to disable it, we can do so here. - if (!AllowUnlikelyPath) - continue; - - // We have parsed the likely path through the region. - // Now traverse the other (unlikely) path. - // - // Note: BasicBlockRegion uses a vector for MBB storage, so adding BBs to - // the region while iterating could invalidate iterators. Collect the work - // items first, then process them. - std::vector> - UnlikelyWork; - UnlikelyWork.reserve((*CurrentRegion)->size()); - for (auto ToIt = (*CurrentRegion)->getRootMBB(), - End = (*CurrentRegion)->getLastMBB(); - ToIt != End; ++ToIt) { - MachineBasicBlock *ToBB = *ToIt; - MachineBasicBlock *SecondBest = getNextPURBB(ToBB, true); - if (SecondBest) - UnlikelyWork.emplace_back(ToBB, SecondBest); - } - - for (auto [ToBB, SecondBest] : UnlikelyWork) { - LLVM_DEBUG(dbgs() << "\tFor BB:\n"; ToBB->dump()); - LLVM_DEBUG(dbgs() << "\tHave SecondBest:\n"; SecondBest->dump()); - // Adding this BB to the region should not be done if we - // plan to reuse it(the region) again. For now it is OK. - (*CurrentRegion)->addBBtoRegion(SecondBest); - LLVM_DEBUG(dbgs() << "\tHome iterator moved to new BB(" - << ToBB->getNumber() << ")\n"; - ToBB->dump()); - MachineBasicBlock::iterator ToThisBBEnd = ToBB->end(); - MachineBasicBlock::iterator MI = ToBB->begin(); - MachineBasicBlock::iterator FromThisBBEnd; - - // For all instructions in the BB. - while (MI != ToThisBBEnd) { - MachineBasicBlock::iterator WorkPoint = MI; - ++MI; - - // Trivial check that there are unused resources - // in the current location (cycle). - while (ResourcesAvailableInBundle(*CurrentRegion, WorkPoint)) { - LLVM_DEBUG(dbgs() << "\nxxxx Second visit Home in BB(" - << ToBB->getNumber() << "):\n"; - DumpPacket(WorkPoint.getInstrIterator())); - - FromHere = SecondBest->begin(); - FromThisBBEnd = SecondBest->end(); - - // Keep the path to the candidate. - backtrack.clear(); - - // This is Home location. - for (MachineBasicBlock::iterator I = WorkPoint, IE = ToThisBBEnd; - I != IE; ++I) - backtrack.push_back(&*I); - - while (true) { - // If this BB is over, move onto the next one - // in this region. - if (FromHere == FromThisBBEnd) { - LLVM_DEBUG(dbgs() - << "\tOnly do one successor for the second try\n"); - break; - } - if ((*FromHere).isDebugInstr()) { - ++FromHere; - continue; - } - // This is a step Home. - backtrack.push_back(&*FromHere); - if (!findPullUpCandidates(WorkPoint, FromHere, backtrack, - SecondaryCandidateQueueSize)) - break; - ++FromHere; - } - // Try to pull-up one of selected candidate. - if (!tryMultipleInstructions(/*output*/ WorkPoint, CurrentRegion, MI, - ToThisBBEnd, FromThisBBEnd, false)) - break; - } - } - } - } - return true; -} - -bool HexagonGlobalSchedulerImpl::incrementalAddToPacket(MachineInstr &MI) { - - LLVM_DEBUG(dbgs() << "\t[AddToPacket] (" << CurrentPacketMIs.size() - << ") adding:\t"; - MI.dump()); - - if (!ResourceTracker->canReserveResources(MI) || !shouldAddToPacket(MI)) - return false; - - ResourceTracker->reserveResources(MI); - CurrentPacketMIs.push_back(&MI); - CurrentState.HomeBundle.push_back(&MI); - - if (QII->isExtended(MI) || QII->isConstExtended(MI) || - isJumpOutOfRange(&MI)) { - // If at this point of time we cannot reserve resources, - // this might mean that the packet came into the pull-up - // pass already in danger of overflowing. - // Nevertheless, since this is only a possibility of overflow - // no error should be issued here. - if (ResourceTracker->canReserveResources(*Ext)) { - ResourceTracker->reserveResources(*Ext); - LLVM_DEBUG(dbgs() << "\t[AddToPacket] (" << CurrentPacketMIs.size() - << ") adding:\t immext_i\n"); - CurrentPacketMIs.push_back(Ext); - CurrentState.HomeBundle.push_back(Ext); - return true; - } else { - LLVM_DEBUG(dbgs() << "\t Previous overflow possible.\n"); - return false; - } - } - return true; -} - -void HexagonGlobalSchedulerImpl::checkBundleCounts(MachineFunction &Fn) { - if (DisableCheckBundles) - return; - - unsigned BundleLimit = 4; - - for (MachineFunction::iterator MBBi = Fn.begin(), MBBe = Fn.end(); - MBBi != MBBe; ++MBBi) { - - for (MachineBasicBlock::iterator MI = MBBi->instr_begin(), - ME = MBBi->instr_end(); - MI != ME; ++MI) { - if (MI->isBundle()) { - MachineBasicBlock::instr_iterator MII = MI.getInstrIterator(); - MachineBasicBlock::instr_iterator End = MII->getParent()->instr_end(); - - unsigned InstrCount = 0; - - for (++MII; MII != End && MII->isInsideBundle(); ++MII) { - if (MII->getOpcode() == TargetOpcode::DBG_VALUE || - MII->getOpcode() == TargetOpcode::IMPLICIT_DEF || - MII->getOpcode() == TargetOpcode::CFI_INSTRUCTION || - MII->isEHLabel() || QII->isEndLoopN(MII->getOpcode())) { - continue; - } else { - InstrCount++; - } - } - if (InstrCount > BundleLimit) { - if (WarnOnBundleSize) { - LLVM_DEBUG(dbgs() << "Warning bundle size exceeded " << *MI); - } else { - assert(0 && "Bundle size exceeded"); - } - } - } - } - } -} - -/// Debugging only. Count compound and duplex opportunities. -unsigned HexagonGlobalSchedulerImpl::countCompounds(MachineFunction &Fn) { - unsigned CompoundCount = 0; - [[maybe_unused]] unsigned DuplexCount = 0; - [[maybe_unused]] unsigned InstOffset = 0; - - // Loop over all basic blocks. - for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); MBB != MBBe; - ++MBB) { - LLVM_DEBUG(dbgs() << "\n BB#" << MBB->getNumber() << " " << MBB->getName() - << " in_func " - << MBB->getParent()->getFunction().getName() << " \n"); - for (MachineBasicBlock::iterator MI = MBB->instr_begin(), - ME = MBB->instr_end(); - MI != ME; ++MI) { - if (MI->isDebugInstr()) - continue; - if (MI->isBundle()) { - MachineBasicBlock::instr_iterator MII = MI.getInstrIterator(); - MachineBasicBlock::instr_iterator MIE = MI->getParent()->instr_end(); - MachineInstr *FirstCompound = NULL, *SecondCompound = NULL; - MachineInstr *FirstDuplex = NULL, *SecondDuplex = NULL; - LLVM_DEBUG(dbgs() << "{\n"); - - for (++MII; MII != MIE && MII->isInsideBundle() && !MII->isBundle(); - ++MII) { - if (MII->isDebugInstr()) - continue; - LLVM_DEBUG(dbgs() << "(" << InstOffset << ")\t"); - InstOffset += QII->getSize(*MII); - if (QII->getCompoundCandidateGroup(*MII)) { - if (!FirstCompound) { - FirstCompound = &*MII; - LLVM_DEBUG(dbgs() << "XX "); - } else { - SecondCompound = &*MII; - LLVM_DEBUG(dbgs() << "YY "); - } - } - if (QII->getDuplexCandidateGroup(*MII)) { - if (!FirstDuplex) { - FirstDuplex = &*MII; - LLVM_DEBUG(dbgs() << "AA "); - } else { - SecondDuplex = &*MII; - LLVM_DEBUG(dbgs() << "VV "); - } - } - LLVM_DEBUG(MII->dump()); - } - LLVM_DEBUG(dbgs() << "}\n"); - if (SecondCompound) { - if (isCompoundPair(FirstCompound, SecondCompound)) { - LLVM_DEBUG(dbgs() << "Compound pair (" << CompoundCount << ")\n"); - CompoundCount++; - } - } - if (SecondDuplex) { - if (QII->isDuplexPair(*FirstDuplex, *SecondDuplex)) { - LLVM_DEBUG(dbgs() << "Duplex pair (" << DuplexCount << ")\n"); - DuplexCount++; - } - } - } else { - LLVM_DEBUG(dbgs() << "(" << InstOffset << ")\t"); - if (QII->getCompoundCandidateGroup(*MI)) - LLVM_DEBUG(dbgs() << "XX "); - if (QII->getDuplexCandidateGroup(*MI)) - LLVM_DEBUG(dbgs() << "AA "); - InstOffset += QII->getSize(*MI); - LLVM_DEBUG(MI->dump()); - } - } - } - LLVM_DEBUG(dbgs() << "Total compound(" << CompoundCount << ") duplex(" - << DuplexCount << ")\n"); - return CompoundCount; -} - -//===----------------------------------------------------------------------===// -// Public Constructor Functions -//===----------------------------------------------------------------------===// - -FunctionPass *llvm::createHexagonGlobalScheduler() { - return new HexagonGlobalScheduler(); -} diff --git a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp index a56dfc5f58392..0a18ed8b3b9b6 100644 --- a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp +++ b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp @@ -52,26 +52,6 @@ HexagonRegisterInfo::HexagonRegisterInfo(unsigned HwMode) : HexagonGenRegisterInfo(Hexagon::R31, 0/*DwarfFlavor*/, 0/*EHFlavor*/, 0/*PC*/, HwMode) {} -bool HexagonRegisterInfo::isGlobalReg(MCPhysReg Reg) const { - switch (Reg) { - case Hexagon::R29: - case Hexagon::R30: - case Hexagon::R31: - return true; - } - return false; -} - -bool HexagonRegisterInfo::isFakeReg(MCPhysReg Reg) const { - // VF0-VF31 are fake registers used as sub-registers in HVX vector pairs - if (Reg >= Hexagon::VF0 && Reg <= Hexagon::VF31) - return true; - // VFR0-VFR31 are fake registers used for reversed vector pairs - if (Reg >= Hexagon::VFR0 && Reg <= Hexagon::VFR31) - return true; - return false; -} - bool HexagonRegisterInfo::isEHReturnCalleeSaveReg(Register R) const { return R == Hexagon::R0 || R == Hexagon::R1 || R == Hexagon::R2 || R == Hexagon::R3 || R == Hexagon::D0 || R == Hexagon::D1; diff --git a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h index a6cf0f9cd0074..945b8608cd948 100644 --- a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h +++ b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h @@ -74,16 +74,6 @@ class HexagonRegisterInfo : public HexagonGenRegisterInfo { const TargetRegisterClass * getPointerRegClass(unsigned Kind = 0) const override; - /// Returns true if the given reserved physical register is live across - /// function calls/returns. - bool isGlobalReg(MCPhysReg Reg) const; - - /// Returns true if the given reserved physical register Reg is live - /// across function calls/returns. This function should not be used for - /// non-reserved registers, instead register liveness information should be - /// checked - bool isFakeReg(MCPhysReg Reg) const; - bool isEHReturnCalleeSaveReg(Register Reg) const; }; diff --git a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp index f92655309ab88..cfe898fe767dc 100644 --- a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp +++ b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp @@ -195,7 +195,6 @@ LLVMInitializeHexagonTarget() { initializeHexagonEarlyIfConversionPass(PR); initializeHexagonGenMemAbsolutePass(PR); initializeHexagonGenMuxPass(PR); - initializeHexagonGlobalSchedulerPass(PR); initializeHexagonLiveVariablesPass(PR); initializeHexagonHardwareLoopsPass(PR); initializeHexagonLoopIdiomRecognizeLegacyPassPass(PR); @@ -480,12 +479,8 @@ void HexagonPassConfig::addPreEmitPass() { // Packetization is mandatory: it handles gather/scatter at all opt levels. addPass(createHexagonPacketizer(NoOpt)); - if (!NoOpt) { - // Global pull-up scheduler - addPass(createHexagonGlobalScheduler()); - + if (!NoOpt) addPass(createHexagonLoopAlign()); - } if (EnableVectorPrint) addPass(createHexagonVectorPrint()); diff --git a/llvm/test/CodeGen/Hexagon/autohvx/hfsplat.ll b/llvm/test/CodeGen/Hexagon/autohvx/hfsplat.ll index 6d89005739f51..3b3b3860453cb 100644 --- a/llvm/test/CodeGen/Hexagon/autohvx/hfsplat.ll +++ b/llvm/test/CodeGen/Hexagon/autohvx/hfsplat.ll @@ -1,7 +1,8 @@ ; RUN: llc -mtriple=hexagon < %s | FileCheck %s ; Check that the vsplat instruction is generated -; CHECK: vsplat(r{{[0-9]+}}) +; CHECK: r[[V:[0-9]+]] = #16752 +; CHECK: vsplat(r[[V]]) target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048" target triple = "hexagon" diff --git a/llvm/test/CodeGen/Hexagon/avoid-debug-increment.mir b/llvm/test/CodeGen/Hexagon/avoid-debug-increment.mir deleted file mode 100644 index 05864dc26536a..0000000000000 --- a/llvm/test/CodeGen/Hexagon/avoid-debug-increment.mir +++ /dev/null @@ -1,311 +0,0 @@ -# This test case has been reduced from one of the files from nullstone benchmark. -# It verifies that no stalls are being missed when compiling with '-g'. - -# RUN: llc -march=hexagon -mcpu=hexagonv73 -run-pass=global-sched -debug-only=global_sched %s -o /dev/null 2>&1 | FileCheck %s - -# CHECK: bb.3: -# CHECK: Could not move packetized instr. -# CHECK-NEXT: Not a single candidate fit. -# CHECK: Home iterator moved to new BB(2) -# CHECH-NOT: Want to move dependent op: S4_storeirif_io - ---- | - - %struct._Dnk_filet = type { i16, i8, i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, [2 x i32], ptr, ptr, ptr, %struct._Mbstatet, ptr, [8 x i8], i8 } - %struct._Mbstatet = type { i32, i16, i16 } - - @datafileptr = external dso_local local_unnamed_addr global ptr, align 4 - @_Stderr = external dso_local global %struct._Dnk_filet, align 4 - @.str = private unnamed_addr constant [49 x i8] c"ERROR: File=%s, Line=%d, Data file is not open.\0A\00", align 1, !dbg !0 - @.str.1 = private unnamed_addr constant [6 x i8] c"fem.c\00", align 1, !dbg !7 - @.str.2 = private unnamed_addr constant [28 x i8] c"%s=\09\09File=%s, Line=%d, %s.\0A\00", align 1, !dbg !12 - @.str.3 = private unnamed_addr constant [6 x i8] c"error\00", align 1, !dbg !17 - @.str.4 = private unnamed_addr constant [56 x i8] c"ERROR: File=%s, Line=%d, Unable to write to data file.\0A\00", align 1, !dbg !19 - - ; Function Attrs: noreturn nounwind - define dso_local void @fatal_error_message(ptr noundef %filename, i32 noundef %line, ptr noundef %message) local_unnamed_addr #0 !dbg !31 { - entry: - call void @llvm.dbg.value(metadata ptr %filename, metadata !37, metadata !DIExpression()), !dbg !41 - call void @llvm.dbg.value(metadata i32 %line, metadata !38, metadata !DIExpression()), !dbg !41 - call void @llvm.dbg.value(metadata ptr %message, metadata !39, metadata !DIExpression()), !dbg !41 - call void @llvm.dbg.value(metadata i32 0, metadata !40, metadata !DIExpression()), !dbg !41 - %0 = load ptr, ptr @datafileptr, align 4, !dbg !42, !tbaa !44 - %cmp = icmp eq ptr %0, null, !dbg !48 - br i1 %cmp, label %if.end5.sink.split, label %if.end, !dbg !49 - - if.end: ; preds = %entry - %call1 = tail call i32 (ptr, ptr, ...) @fprintf(ptr noundef nonnull %0, ptr noundef nonnull @.str.2, ptr noundef nonnull @.str.3, ptr noundef %filename, i32 noundef %line, ptr noundef %message) #4, !dbg !50 - call void @llvm.dbg.value(metadata i32 %call1, metadata !40, metadata !DIExpression()), !dbg !41 - %cmp2 = icmp eq i32 %call1, -1, !dbg !51 - br i1 %cmp2, label %if.end5.sink.split, label %if.end5, !dbg !53 - - if.end5.sink.split: ; preds = %if.end, %entry - %.sink = phi i32 [ 30, %entry ], [ 37, %if.end ] - %.str.sink = phi ptr [ @.str, %entry ], [ @.str.4, %if.end ] - %call = tail call i32 (ptr, ptr, ...) @fprintf(ptr noundef nonnull @_Stderr, ptr noundef nonnull %.str.sink, ptr noundef nonnull @.str.1, i32 noundef %.sink) #4, !dbg !41 - br label %if.end5, !dbg !54 - - if.end5: ; preds = %if.end5.sink.split, %if.end - tail call void @exit(i32 noundef 1) #5, !dbg !54 - unreachable, !dbg !54 - } - - ; Function Attrs: nofree nounwind - declare !dbg !55 dso_local noundef i32 @fprintf(ptr nocapture noundef, ptr nocapture noundef readonly, ...) local_unnamed_addr #1 - - ; Function Attrs: noreturn - declare !dbg !104 dso_local void @exit(i32 noundef) local_unnamed_addr #2 - - ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) - declare void @llvm.dbg.value(metadata, metadata, metadata) #3 - - attributes #0 = { noreturn nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="hexagonv73" "target-features"="+v73,-long-calls" } - attributes #1 = { nofree nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="hexagonv73" "target-features"="+v73,-long-calls" } - attributes #2 = { noreturn "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="hexagonv73" "target-features"="+v73,-long-calls" } - attributes #3 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } - attributes #4 = { nounwind } - attributes #5 = { noreturn nounwind } - - !llvm.dbg.cu = !{!24} - !llvm.module.flags = !{!26, !27, !28, !29} - - !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) - !1 = distinct !DIGlobalVariable(scope: null, file: !2, line: 29, type: !3, isLocal: true, isDefinition: true) - !2 = !DIFile(filename: "fem.c", directory: "/tmp/build/v66/benchmark/nullstone/nullstone") - !3 = !DICompositeType(tag: DW_TAG_array_type, baseType: !4, size: 392, elements: !5) - !4 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_unsigned_char) - !5 = !{!6} - !6 = !DISubrange(count: 49) - !7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression()) - !8 = distinct !DIGlobalVariable(scope: null, file: !2, line: 30, type: !9, isLocal: true, isDefinition: true) - !9 = !DICompositeType(tag: DW_TAG_array_type, baseType: !4, size: 48, elements: !10) - !10 = !{!11} - !11 = !DISubrange(count: 6) - !12 = !DIGlobalVariableExpression(var: !13, expr: !DIExpression()) - !13 = distinct !DIGlobalVariable(scope: null, file: !2, line: 33, type: !14, isLocal: true, isDefinition: true) - !14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !4, size: 224, elements: !15) - !15 = !{!16} - !16 = !DISubrange(count: 28) - !17 = !DIGlobalVariableExpression(var: !18, expr: !DIExpression()) - !18 = distinct !DIGlobalVariable(scope: null, file: !2, line: 34, type: !9, isLocal: true, isDefinition: true) - !19 = !DIGlobalVariableExpression(var: !20, expr: !DIExpression()) - !20 = distinct !DIGlobalVariable(scope: null, file: !2, line: 36, type: !21, isLocal: true, isDefinition: true) - !21 = !DICompositeType(tag: DW_TAG_array_type, baseType: !4, size: 448, elements: !22) - !22 = !{!23} - !23 = !DISubrange(count: 56) - !24 = distinct !DICompileUnit(language: DW_LANG_C11, file: !2, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !25, splitDebugInlining: false, debugInfoForProfiling: true, nameTableKind: None) - !25 = !{!0, !7, !12, !17, !19} - !26 = !{i32 7, !"Dwarf Version", i32 4} - !27 = !{i32 2, !"Debug Info Version", i32 3} - !28 = !{i32 1, !"wchar_size", i32 4} - !29 = !{i32 7, !"frame-pointer", i32 2} - !31 = distinct !DISubprogram(name: "fatal_error_message", scope: !2, file: !2, line: 24, type: !32, scopeLine: 25, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !24, retainedNodes: !36) - !32 = !DISubroutineType(types: !33) - !33 = !{null, !34, !35, !34} - !34 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !4, size: 32) - !35 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) - !36 = !{!37, !38, !39, !40} - !37 = !DILocalVariable(name: "filename", arg: 1, scope: !31, file: !2, line: 24, type: !34) - !38 = !DILocalVariable(name: "line", arg: 2, scope: !31, file: !2, line: 24, type: !35) - !39 = !DILocalVariable(name: "message", arg: 3, scope: !31, file: !2, line: 24, type: !34) - !40 = !DILocalVariable(name: "status", scope: !31, file: !2, line: 26, type: !35) - !41 = !DILocation(line: 0, scope: !31) - !42 = !DILocation(line: 28, column: 7, scope: !43) - !43 = distinct !DILexicalBlock(scope: !31, file: !2, line: 28, column: 7) - !44 = !{!45, !45, i64 0} - !45 = !{!"any pointer", !46, i64 0} - !46 = !{!"omnipotent char", !47, i64 0} - !47 = !{!"Simple C/C++ TBAA"} - !48 = !DILocation(line: 28, column: 19, scope: !43) - !49 = !DILocation(line: 28, column: 7, scope: !31) - !50 = !DILocation(line: 32, column: 14, scope: !43) - !51 = !DILocation(line: 35, column: 14, scope: !52) - !52 = distinct !DILexicalBlock(scope: !31, file: !2, line: 35, column: 7) - !53 = !DILocation(line: 35, column: 7, scope: !31) - !54 = !DILocation(line: 38, column: 3, scope: !31) - !55 = !DISubprogram(name: "fprintf", scope: !56, file: !56, line: 129, type: !57, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !103) - !56 = !DIFile(filename: "stdio.h", directory: "/test") - !57 = !DISubroutineType(types: !58) - !58 = !{!35, !59, !101, null} - !59 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !60, size: 32) - !60 = !DIDerivedType(tag: DW_TAG_typedef, name: "FILE", file: !56, line: 107, baseType: !61) - !61 = !DIDerivedType(tag: DW_TAG_typedef, name: "_Filet", file: !56, line: 104, baseType: !62) - !62 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "_Dnk_filet", file: !56, line: 85, size: 640, elements: !63) - !63 = !{!64, !66, !68, !69, !71, !72, !73, !74, !75, !76, !80, !84, !85, !86, !87, !95, !96, !100} - !64 = !DIDerivedType(tag: DW_TAG_member, name: "_Mode", scope: !62, file: !56, line: 87, baseType: !65, size: 16) - !65 = !DIBasicType(name: "unsigned short", size: 16, encoding: DW_ATE_unsigned) - !66 = !DIDerivedType(tag: DW_TAG_member, name: "_Idx", scope: !62, file: !56, line: 88, baseType: !67, size: 8, offset: 16) - !67 = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char) - !68 = !DIDerivedType(tag: DW_TAG_member, name: "_Handle", scope: !62, file: !56, line: 89, baseType: !35, size: 32, offset: 32) - !69 = !DIDerivedType(tag: DW_TAG_member, name: "_Buf", scope: !62, file: !56, line: 91, baseType: !70, size: 32, offset: 64) - !70 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !67, size: 32) - !71 = !DIDerivedType(tag: DW_TAG_member, name: "_Bend", scope: !62, file: !56, line: 91, baseType: !70, size: 32, offset: 96) - !72 = !DIDerivedType(tag: DW_TAG_member, name: "_Next", scope: !62, file: !56, line: 91, baseType: !70, size: 32, offset: 128) - !73 = !DIDerivedType(tag: DW_TAG_member, name: "_Rend", scope: !62, file: !56, line: 92, baseType: !70, size: 32, offset: 160) - !74 = !DIDerivedType(tag: DW_TAG_member, name: "_Wend", scope: !62, file: !56, line: 92, baseType: !70, size: 32, offset: 192) - !75 = !DIDerivedType(tag: DW_TAG_member, name: "_Rback", scope: !62, file: !56, line: 92, baseType: !70, size: 32, offset: 224) - !76 = !DIDerivedType(tag: DW_TAG_member, name: "_WRback", scope: !62, file: !56, line: 94, baseType: !77, size: 32, offset: 256) - !77 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !78, size: 32) - !78 = !DIDerivedType(tag: DW_TAG_typedef, name: "_Wchart", file: !79, line: 851, baseType: !35) - !79 = !DIFile(filename: "yvals.h", directory: "/test") - !80 = !DIDerivedType(tag: DW_TAG_member, name: "_WBack", scope: !62, file: !56, line: 94, baseType: !81, size: 64, offset: 288) - !81 = !DICompositeType(tag: DW_TAG_array_type, baseType: !78, size: 64, elements: !82) - !82 = !{!83} - !83 = !DISubrange(count: 2) - !84 = !DIDerivedType(tag: DW_TAG_member, name: "_Rsave", scope: !62, file: !56, line: 95, baseType: !70, size: 32, offset: 352) - !85 = !DIDerivedType(tag: DW_TAG_member, name: "_WRend", scope: !62, file: !56, line: 95, baseType: !70, size: 32, offset: 384) - !86 = !DIDerivedType(tag: DW_TAG_member, name: "_WWend", scope: !62, file: !56, line: 95, baseType: !70, size: 32, offset: 416) - !87 = !DIDerivedType(tag: DW_TAG_member, name: "_Wstate", scope: !62, file: !56, line: 97, baseType: !88, size: 64, offset: 448) - !88 = !DIDerivedType(tag: DW_TAG_typedef, name: "_Mbstatet", file: !56, line: 64, baseType: !89) - !89 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "_Mbstatet", file: !56, line: 60, size: 64, elements: !90) - !90 = !{!91, !93, !94} - !91 = !DIDerivedType(tag: DW_TAG_member, name: "_Wchar", scope: !89, file: !56, line: 62, baseType: !92, size: 32) - !92 = !DIBasicType(name: "unsigned long", size: 32, encoding: DW_ATE_unsigned) - !93 = !DIDerivedType(tag: DW_TAG_member, name: "_Byte", scope: !89, file: !56, line: 63, baseType: !65, size: 16, offset: 32) - !94 = !DIDerivedType(tag: DW_TAG_member, name: "_State", scope: !89, file: !56, line: 63, baseType: !65, size: 16, offset: 48) - !95 = !DIDerivedType(tag: DW_TAG_member, name: "_Tmpnam", scope: !62, file: !56, line: 98, baseType: !34, size: 32, offset: 512) - !96 = !DIDerivedType(tag: DW_TAG_member, name: "_Back", scope: !62, file: !56, line: 99, baseType: !97, size: 64, offset: 544) - !97 = !DICompositeType(tag: DW_TAG_array_type, baseType: !67, size: 64, elements: !98) - !98 = !{!99} - !99 = !DISubrange(count: 8) - !100 = !DIDerivedType(tag: DW_TAG_member, name: "_Cbuf", scope: !62, file: !56, line: 99, baseType: !67, size: 8, offset: 608) - !101 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !102, size: 32) - !102 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !4) - !103 = !{} - !104 = !DISubprogram(name: "exit", scope: !105, file: !105, line: 82, type: !106, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: DISPFlagOptimized, retainedNodes: !103) - !105 = !DIFile(filename: "stdlib.h", directory: "/test") - !106 = !DISubroutineType(types: !107) - !107 = !{null, !35} - -... ---- -name: fatal_error_message -alignment: 16 -exposesReturnsTwice: false -legalized: false -regBankSelected: false -selected: false -failedISel: false -tracksRegLiveness: true -hasWinCFI: false -callsEHReturn: false -callsUnwindInit: false -hasEHContTarget: false -hasEHScopes: false -hasEHFunclets: false -isOutlined: false -debugInstrRef: false -failsVerification: true -tracksDebugUserValues: true -registers: [] -liveins: - - { reg: '$r0', virtual-reg: '' } - - { reg: '$r1', virtual-reg: '' } - - { reg: '$r2', virtual-reg: '' } -frameInfo: - isFrameAddressTaken: false - isReturnAddressTaken: false - hasStackMap: false - hasPatchPoint: false - stackSize: 16 - offsetAdjustment: 0 - maxAlignment: 4 - adjustsStack: true - hasCalls: true - stackProtector: '' - functionContext: '' - maxCallFrameSize: 16 - cvBytesOfCalleeSavedRegisters: 0 - hasOpaqueSPAdjustment: false - hasVAStart: false - hasMustTailInVarArgFunc: false - hasTailCall: false - localFrameSize: 0 - savePoint: [] - restorePoint: [] -fixedStack: [] -stack: [] -callSites: [] -debugValueSubstitutions: [] -constants: [] -machineFunctionInfo: {} -body: | - bb.0.entry: - successors: %bb.1(0x40000000), %bb.2(0x40000000) - liveins: $r0, $r1, $r2 - - DBG_VALUE $r0, $noreg, !37, !DIExpression(), debug-location !41 - DBG_VALUE $r1, $noreg, !38, !DIExpression(), debug-location !41 - DBG_VALUE $r2, $noreg, !39, !DIExpression(), debug-location !41 - BUNDLE implicit-def $r3, implicit-def $r29, implicit-def $r30, implicit killed $gp, implicit killed $r29, implicit killed $framekey, implicit killed $framelimit, implicit $r30, implicit killed $r31, debug-location !42 { - renamable $r3 = L2_loadrigp @datafileptr, implicit killed $gp, debug-location !42 :: (dereferenceable load (s32) from @datafileptr, !tbaa !44) - $r29 = frame-setup S2_allocframe killed $r29, 16, implicit-def $r30, implicit killed $framekey, implicit killed $framelimit, implicit $r30, implicit killed $r31, debug-location !42 :: (store (s32) into stack) - } - DBG_VALUE 0, $noreg, !40, !DIExpression(), debug-location !41 - DBG_VALUE $r0, $noreg, !37, !DIExpression(), debug-location !41 - BUNDLE implicit-def dead $p0, implicit-def $pc, implicit $r3, debug-location !48 { - renamable $p0 = C2_cmpeqi renamable $r3, 0, debug-location !48 - J2_jumpfnewpt internal killed renamable $p0, %bb.2, implicit-def $pc, debug-location !49 - } - - bb.1: - successors: %bb.4(0x80000000) - - BUNDLE implicit-def $r1, implicit-def $r2, implicit-def $pc { - renamable $r1 = A2_tfrsi @.str - renamable $r2 = A2_tfrsi 30 - J2_jump %bb.4, implicit-def $pc - } - - bb.2.if.end: - successors: %bb.3(0x40000000), %bb.5(0x40000000) - liveins: $r0, $r1, $r2, $r3 - - DBG_VALUE $r4, $noreg, !37, !DIExpression(), debug-location !41 - BUNDLE implicit-def $r4, implicit-def $d0, implicit-def $r0, implicit-def $r1, implicit killed $r0, implicit $r29, implicit killed $r1, implicit killed $r3, debug-location !41 { - $r4 = A2_tfr killed $r0 - S2_storeri_io $r29, 8, killed renamable $r1, debug-location !50 :: (store (s32) into stack + 8) - $d0 = A4_combineir @.str.2, killed $r3, debug-location !50 - } - BUNDLE implicit $r29, implicit killed $r2, implicit killed $r4, debug-location !50 { - S2_storeri_io $r29, 12, killed renamable $r2, debug-location !50 :: (store (s32) into stack + 12) - S2_storeri_io $r29, 4, killed renamable $r4, debug-location !50 :: (store (s32) into stack + 4) - } - DBG_VALUE $r0, $noreg, !40, !DIExpression(), debug-location !41 - BUNDLE implicit-def $pc, implicit-def $r31, implicit-def $r29, implicit-def $r0, implicit $r29, implicit $r0, implicit $r1, debug-location !50 { - S4_storeiri_io $r29, 0, @.str.3, debug-location !50 :: (store (s32) into stack) - J2_call @fprintf, hexagoncsr, implicit-def $pc, implicit-def $r31, implicit $r29, implicit $r0, implicit $r1, implicit-def $r29, implicit-def $r0, debug-location !50 - } - BUNDLE implicit-def dead $p0, implicit-def $pc, implicit killed $r0, debug-location !51 { - renamable $p0 = C2_cmpeqi killed renamable $r0, -1, debug-location !51 - J2_jumpfnewpt internal killed renamable $p0, %bb.5, implicit-def $pc, debug-location !53 - } - - bb.3: - successors: %bb.4(0x80000000) - - BUNDLE implicit-def $r1, implicit-def $r2 { - renamable $r1 = A2_tfrsi @.str.4 - renamable $r2 = A2_tfrsi 37 - } - - bb.4.if.end5.sink.split: - successors: %bb.5(0x80000000) - liveins: $r1, $r2 - - BUNDLE implicit-def $r0, implicit $r29, implicit killed $r2, debug-location !41 { - $r0 = A2_tfrsi @_Stderr, debug-location !41 - S2_storeri_io $r29, 4, killed renamable $r2, debug-location !41 :: (store (s32) into stack + 4) - } - BUNDLE implicit-def $pc, implicit-def $r31, implicit-def $r29, implicit-def $r0, implicit $r29, implicit $r0, implicit $r1, debug-location !41 { - S4_storeiri_io $r29, 0, @.str.1, debug-location !41 :: (store (s32) into stack) - J2_call @fprintf, hexagoncsr, implicit-def $pc, implicit-def $r31, implicit $r29, implicit $r0, implicit $r1, implicit-def $r29, implicit-def $r0, debug-location !41 - } - - bb.5.if.end5: - BUNDLE implicit-def $r0, implicit-def $r29, debug-location !54 { - $r0 = A2_tfrsi 1, debug-location !54 - PS_call_nr @exit, hexagoncsr, implicit internal $r0, implicit-def $r29, debug-location !54 - } - -... diff --git a/llvm/test/CodeGen/Hexagon/cext-check.ll b/llvm/test/CodeGen/Hexagon/cext-check.ll index 7abd2bd6bd9cf..7124b37581737 100644 --- a/llvm/test/CodeGen/Hexagon/cext-check.ll +++ b/llvm/test/CodeGen/Hexagon/cext-check.ll @@ -1,4 +1,4 @@ -; RUN: llc -mtriple=hexagon -hexagon-eif=0 -ifcvt-limit=0 -hexagon-initial-cfg-cleanup=0 -disable-pull-up < %s | FileCheck %s +; RUN: llc -mtriple=hexagon -hexagon-eif=0 -ifcvt-limit=0 -hexagon-initial-cfg-cleanup=0 < %s | FileCheck %s ; Check that we constant extended instructions only when necessary. define i32 @cext_test1(ptr %a) nounwind { diff --git a/llvm/test/CodeGen/Hexagon/dbg-label-pullup.ll b/llvm/test/CodeGen/Hexagon/dbg-label-pullup.ll deleted file mode 100644 index 1965408c2cb31..0000000000000 --- a/llvm/test/CodeGen/Hexagon/dbg-label-pullup.ll +++ /dev/null @@ -1,305 +0,0 @@ -; RUN: llc -O2 < %s -; REQUIRES: asserts - -target triple = "hexagon" - -%struct.wombat.8.56.133.143.153.163.173.183.212.232.281.310.358.406.548.656.666.676.686.696.751.760.850.859 = type { ptr, ptr, ptr, ptr, ptr, ptr, i8, i8, ptr, i32, i32, ptr, %struct.wombat.1.7.55.132.142.152.162.172.182.211.231.280.309.357.405.547.655.665.675.685.695.750.759.849.858 } -%struct.wombat.1.7.55.132.142.152.162.172.182.211.231.280.309.357.405.547.655.665.675.685.695.750.759.849.858 = type { ptr, i32, i32, i32, i32, i32, i32, i32 } - -@global = external dso_local local_unnamed_addr global %struct.wombat.8.56.133.143.153.163.173.183.212.232.281.310.358.406.548.656.666.676.686.696.751.760.850.859, align 4 - -; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) -declare void @llvm.dbg.label(metadata) #0 - -define dso_local i32 @pluto(i8 %arg) local_unnamed_addr #1 !dbg !164 !prof !173 { -bb: - %cond0 = icmp ne i8 %arg, 0, !dbg !174 - br i1 %cond0, label %bb6, label %bb65, !dbg !174 - -bb6: ; preds = %bb - %tmp7 = load i8, ptr getelementptr inbounds (%struct.wombat.8.56.133.143.153.163.173.183.212.232.281.310.358.406.548.656.666.676.686.696.751.760.850.859, ptr @global, i32 0, i32 6), align 4, !dbg !175 - switch i8 %tmp7, label %bb65 [ - i8 0, label %bb24 - i8 2, label %bb24 - ], !dbg !176 - -bb24: ; preds = %bb6, %bb6 - %cond1 = icmp eq i8 %arg, 2, !dbg !184 - br i1 %cond1, label %bb27, label %bb65, !dbg !184 - -bb27: ; preds = %bb24 - switch i8 %arg, label %bb65 [ - i8 0, label %bb28 - i8 2, label %bb45 - ], !dbg !185 - -bb28: ; preds = %bb27 - %tmp35 = tail call i32 @wombat(i32 3, ptr null, i8 zeroext 0) #2, !dbg !211 - br label %bb62, !dbg !212 - -bb45: ; preds = %bb27 - br label %bb62, !dbg !214 - -bb62: ; preds = %bb45, %bb28 - %tmp64 = icmp eq i32 0, 0, !dbg !222 - br i1 %tmp64, label %bb68, label %bb65 - -bb65: ; preds = %bb62, %bb27, %bb24, %bb6, %bb - %tmp66 = phi i32 [ 1, %bb24 ], [ 0, %bb ], [ 1, %bb62 ], [ 3, %bb6 ], [ 3, %bb27 ] - %tmp67 = phi i8 [ %tmp7, %bb24 ], [ 0, %bb ], [ %tmp7, %bb62 ], [ %tmp7, %bb6 ], [ %tmp7, %bb27 ] - call void @llvm.dbg.label(metadata !172), !dbg !223 - store i8 %tmp67, ptr getelementptr inbounds (%struct.wombat.8.56.133.143.153.163.173.183.212.232.281.310.358.406.548.656.666.676.686.696.751.760.850.859, ptr @global, i32 0, i32 6), align 4, !dbg !224 - br label %bb68, !dbg !227 - -bb68: ; preds = %bb65, %bb62 - %tmp69 = phi i32 [ %tmp66, %bb65 ], [ 0, %bb62 ] - ret i32 %tmp69, !dbg !228 -} - -declare dso_local void @barney(ptr) local_unnamed_addr #1 - -declare dso_local i32 @eggs() local_unnamed_addr #1 - -declare dso_local i32 @wombat(i32, ptr, i8) local_unnamed_addr #1 - -declare dso_local void @barney.1(ptr) local_unnamed_addr #1 - -; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) -declare void @llvm.dbg.value(metadata, metadata, metadata) #0 - -attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } -attributes #1 = { "use-soft-float"="false" } -attributes #2 = { nounwind } - -!llvm.dbg.cu = !{!0} -!llvm.module.flags = !{!136, !137} - -!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, debugInfoForProfiling: true, nameTableKind: None) -!1 = !DIFile(filename: "foo.c", directory: "/tmp") -!2 = !{} -!3 = !{!4, !6} -!4 = !DIDerivedType(tag: DW_TAG_typedef, name: "tempName", file: !1, line: 38, baseType: !5) -!5 = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char) -!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32) -!7 = !DIDerivedType(tag: DW_TAG_typedef, name: "tempName", file: !1, line: 44, baseType: !8) -!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "tempName", file: !1, line: 45, size: 96, elements: !9) -!9 = !{!10, !13, !135} -!10 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !8, file: !1, line: 47, baseType: !11, size: 32) -!11 = !DIDerivedType(tag: DW_TAG_typedef, name: "tempName", file: !1, line: 28, baseType: !12) -!12 = !DIBasicType(name: "long unsigned int", size: 32, encoding: DW_ATE_unsigned) -!13 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !8, file: !1, line: 48, baseType: !14, size: 32, offset: 32) -!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 32) -!15 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !16) -!16 = !DIDerivedType(tag: DW_TAG_typedef, name: "tempName", file: !1, line: 26, baseType: !17) -!17 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "tempName", file: !1, line: 27, size: 640, elements: !18) -!18 = !{!19, !97, !102, !106, !110, !114, !115, !116, !122, !126, !130, !131} -!19 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !17, file: !1, line: 29, baseType: !20, size: 288) -!20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "tempName", file: !1, line: 85, size: 288, elements: !21) -!21 = !{!22, !55, !59, !63, !64, !68, !69, !83, !89} -!22 = !DIDerivedType(tag: DW_TAG_member, scope: !20, file: !1, line: 87, baseType: !23, size: 32) -!23 = distinct !DICompositeType(tag: DW_TAG_union_type, scope: !20, file: !1, line: 87, size: 32, elements: !24) -!24 = !{!25, !51} -!25 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !23, file: !1, line: 89, baseType: !26, size: 32) -!26 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !27, size: 32) -!27 = !DISubroutineType(types: !28) -!28 = !{!29, !31, !34, !35} -!29 = !DIDerivedType(tag: DW_TAG_typedef, name: "tempName", file: !1, line: 82, baseType: !30) -!30 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !32, size: 32) -!32 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !33) -!33 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_unsigned_char) -!34 = !DIDerivedType(tag: DW_TAG_typedef, name: "tempName", file: !1, line: 77, baseType: !11) -!35 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !36, size: 32) -!36 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !37, size: 32) -!37 = !DIDerivedType(tag: DW_TAG_typedef, name: "tempName", file: !1, line: 83, baseType: !38) -!38 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "tempName", file: !1, line: 110, size: 128, elements: !39) -!39 = !{!40, !41, !48, !50} -!40 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !38, file: !1, line: 112, baseType: !11, size: 32) -!41 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !38, file: !1, line: 113, baseType: !42, size: 32, offset: 32) -!42 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !43, size: 32) -!43 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !44) -!44 = !DIDerivedType(tag: DW_TAG_typedef, name: "tempName", file: !1, line: 103, baseType: !45) -!45 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "tempName", file: !1, line: 104, size: 288, elements: !46) -!46 = !{!47} -!47 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !45, file: !1, line: 106, baseType: !20, size: 288) -!48 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !38, file: !1, line: 114, baseType: !49, size: 32, offset: 64) -!49 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 32) -!50 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !38, file: !1, line: 115, baseType: !11, size: 32, offset: 96) -!51 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !23, file: !1, line: 90, baseType: !52, size: 32) -!52 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !53, size: 32) -!53 = !DISubroutineType(types: !54) -!54 = !{!29, !31, !34, !35, !30} -!55 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !20, file: !1, line: 92, baseType: !56, size: 32, offset: 32) -!56 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !57, size: 32) -!57 = !DISubroutineType(types: !58) -!58 = !{!11, !11, !36} -!59 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !20, file: !1, line: 93, baseType: !60, size: 32, offset: 64) -!60 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !61, size: 32) -!61 = !DISubroutineType(types: !62) -!62 = !{!29, !11, !36} -!63 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !20, file: !1, line: 94, baseType: !60, size: 32, offset: 96) -!64 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !20, file: !1, line: 95, baseType: !65, size: 32, offset: 128) -!65 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !66, size: 32) -!66 = !DISubroutineType(types: !67) -!67 = !{!29, !11, !36, !11} -!68 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !20, file: !1, line: 96, baseType: !60, size: 32, offset: 160) -!69 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !20, file: !1, line: 97, baseType: !70, size: 32, offset: 192) -!70 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !71, size: 32) -!71 = !DISubroutineType(types: !72) -!72 = !{!29, !11, !36, !73, !11} -!73 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !74, size: 32) -!74 = !DIDerivedType(tag: DW_TAG_typedef, name: "tempName", file: !1, line: 62, baseType: !75) -!75 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "tempName", file: !1, line: 63, size: 320, elements: !76) -!76 = !{!77, !78, !79} -!77 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !75, file: !1, line: 65, baseType: !11, size: 32) -!78 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !75, file: !1, line: 66, baseType: !11, size: 32, offset: 32) -!79 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !75, file: !1, line: 67, baseType: !80, size: 256, offset: 64) -!80 = !DICompositeType(tag: DW_TAG_array_type, baseType: !33, size: 256, elements: !81) -!81 = !{!82} -!82 = !DISubrange(count: 32) -!83 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !20, file: !1, line: 98, baseType: !84, size: 32, offset: 224) -!84 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !85, size: 32) -!85 = !DISubroutineType(types: !86) -!86 = !{!29, !11, !36, !87, !88} -!87 = !DIDerivedType(tag: DW_TAG_typedef, name: "tempName", file: !1, line: 78, baseType: !11) -!88 = !DIDerivedType(tag: DW_TAG_typedef, name: "tempName", file: !1, line: 79, baseType: !11) -!89 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !20, file: !1, line: 99, baseType: !90, size: 32, offset: 256) -!90 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !91, size: 32) -!91 = !DISubroutineType(types: !92) -!92 = !{!29, !11, !36, !93, !94, !11, !49, !11, !96} -!93 = !DIDerivedType(tag: DW_TAG_typedef, name: "tempName", file: !1, line: 80, baseType: !11) -!94 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !95, size: 32) -!95 = !DIDerivedType(tag: DW_TAG_const_type, baseType: null) -!96 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 32) -!97 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !17, file: !1, line: 30, baseType: !98, size: 32, offset: 288) -!98 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !99, size: 32) -!99 = !DISubroutineType(types: !100) -!100 = !{!29, !11, !36, !101} -!101 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !4, size: 32) -!102 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !17, file: !1, line: 31, baseType: !103, size: 32, offset: 320) -!103 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !104, size: 32) -!104 = !DISubroutineType(types: !105) -!105 = !{!29, !11, !36, !4} -!106 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !17, file: !1, line: 32, baseType: !107, size: 32, offset: 352) -!107 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !108, size: 32) -!108 = !DISubroutineType(types: !109) -!109 = !{!29, !11, !36, !96, !96} -!110 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !17, file: !1, line: 33, baseType: !111, size: 32, offset: 384) -!111 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !112, size: 32) -!112 = !DISubroutineType(types: !113) -!113 = !{!29, !11, !36, !11, !11} -!114 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !17, file: !1, line: 35, baseType: !60, size: 32, offset: 416) -!115 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !17, file: !1, line: 36, baseType: !60, size: 32, offset: 448) -!116 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !17, file: !1, line: 37, baseType: !117, size: 32, offset: 480) -!117 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !118, size: 32) -!118 = !DISubroutineType(types: !119) -!119 = !{!29, !11, !36, !120, !11, !96} -!120 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !121, size: 32) -!121 = !DIDerivedType(tag: DW_TAG_typedef, name: "tempName", file: !1, line: 72, baseType: !5) -!122 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !17, file: !1, line: 38, baseType: !123, size: 32, offset: 512) -!123 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !124, size: 32) -!124 = !DISubroutineType(types: !125) -!125 = !{!29, !11, !36, !30} -!126 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !17, file: !1, line: 39, baseType: !127, size: 32, offset: 544) -!127 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !128, size: 32) -!128 = !DISubroutineType(types: !129) -!129 = !{!29, !11, !36, !11, !96} -!130 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !17, file: !1, line: 40, baseType: !111, size: 32, offset: 576) -!131 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !17, file: !1, line: 41, baseType: !132, size: 32, offset: 608) -!132 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !133, size: 32) -!133 = !DISubroutineType(types: !134) -!134 = !{!29, !11, !36, !120, !11} -!135 = !DIDerivedType(tag: DW_TAG_member, name: "tempName", scope: !8, file: !1, line: 49, baseType: !49, size: 32, offset: 64) -!136 = !{i32 2, !"Debug Info Version", i32 3} -!137 = !{i32 1, !"ProfileSummary", !138} -!138 = !{!139, !140, !141, !142, !143, !144, !145, !146} -!139 = !{!"ProfileFormat", !"SampleProfile"} -!140 = !{!"TotalCount", i64 12081434} -!141 = !{!"MaxCount", i64 59842} -!142 = !{!"MaxInternalCount", i64 0} -!143 = !{!"MaxFunctionCount", i64 2338166} -!144 = !{!"NumCounts", i64 63284} -!145 = !{!"NumFunctions", i64 6868} -!146 = !{!"DetailedSummary", !147} -!147 = !{!148, !149, !150, !151, !152, !153, !154, !155, !156, !157, !158, !159, !160, !161, !162, !163} -!148 = !{i32 10000, i64 59838, i32 3} -!149 = !{i32 100000, i64 17206, i32 45} -!150 = !{i32 200000, i64 11480, i32 138} -!151 = !{i32 300000, i64 6378, i32 288} -!152 = !{i32 400000, i64 3286, i32 563} -!153 = !{i32 500000, i64 2201, i32 1035} -!154 = !{i32 600000, i64 1285, i32 1800} -!155 = !{i32 700000, i64 726, i32 3144} -!156 = !{i32 800000, i64 421, i32 5243} -!157 = !{i32 900000, i64 246, i32 9701} -!158 = !{i32 950000, i64 239, i32 12082} -!159 = !{i32 990000, i64 32, i32 17252} -!160 = !{i32 999000, i64 4, i32 27541} -!161 = !{i32 999900, i64 1, i32 33470} -!162 = !{i32 999990, i64 1, i32 33470} -!163 = !{i32 999999, i64 1, i32 33470} -!164 = distinct !DISubprogram(name: "qdss_control_set_sink", scope: !1, file: !1, line: 259, type: !165, scopeLine: 260, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !167) -!165 = !DISubroutineType(types: !166) -!166 = !{!30, !4} -!167 = !{!168, !169, !170, !171, !172} -!168 = !DILocalVariable(name: "sinkid", arg: 1, scope: !164, file: !1, line: 259, type: !4) -!169 = !DILocalVariable(name: "nErr", scope: !164, file: !1, line: 261, type: !30) -!170 = !DILocalVariable(name: "new_trace_sink", scope: !164, file: !1, line: 262, type: !4) -!171 = !DILocalVariable(name: "current_trace_sink", scope: !164, file: !1, line: 263, type: !4) -!172 = !DILabel(scope: !164, name: "tempName", file: !1, line: 282) -!173 = !{!"function_entry_count", i64 -1} -!174 = !DILocation(line: 272, column: 8, scope: !164) -!175 = !DILocation(line: 274, column: 30, scope: !164) -!176 = !DILocation(line: 176, column: 4, scope: !177, inlinedAt: !182) -!177 = distinct !DISubprogram(name: "qdss_trace_sink_stop", scope: !1, file: !1, line: 172, type: !165, scopeLine: 173, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !178) -!178 = !{!179, !180, !181} -!179 = !DILocalVariable(name: "trace_sink", arg: 1, scope: !177, file: !1, line: 172, type: !4) -!180 = !DILocalVariable(name: "nErr", scope: !177, file: !1, line: 174, type: !30) -!181 = !DILabel(scope: !177, name: "tempName", file: !1, line: 192) -!182 = distinct !DILocation(line: 276, column: 22, scope: !183) -!183 = distinct !DILexicalBlock(scope: !164, file: !1, line: 276, column: 8) -!184 = !DILocation(line: 276, column: 8, scope: !164) -!185 = !DILocation(line: 140, column: 4, scope: !186, inlinedAt: !191) -!186 = distinct !DISubprogram(name: "qdss_trace_sink_start", scope: !1, file: !1, line: 136, type: !165, scopeLine: 137, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !187) -!187 = !{!188, !189, !190} -!188 = !DILocalVariable(name: "trace_sink", arg: 1, scope: !186, file: !1, line: 136, type: !4) -!189 = !DILocalVariable(name: "nErr", scope: !186, file: !1, line: 138, type: !30) -!190 = !DILabel(scope: !186, name: "tempName", file: !1, line: 156) -!191 = distinct !DILocation(line: 278, column: 22, scope: !192) -!192 = distinct !DILexicalBlock(scope: !164, file: !1, line: 278, column: 8) -!193 = !DILocation(line: 65, column: 40, scope: !194, inlinedAt: !200) -!194 = distinct !DISubprogram(name: "DalTMC_SetMode", scope: !1, file: !1, line: 63, type: !195, scopeLine: 64, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !197) -!195 = !DISubroutineType(types: !196) -!196 = !{!29, !36, !4} -!197 = !{!198, !199} -!198 = !DILocalVariable(name: "_h", arg: 1, scope: !194, file: !1, line: 63, type: !36) -!199 = !DILocalVariable(name: "mode", arg: 2, scope: !194, file: !1, line: 63, type: !4) -!200 = distinct !DILocation(line: 65, column: 22, scope: !201, inlinedAt: !208) -!201 = distinct !DILexicalBlock(scope: !202, file: !1, line: 65, column: 8) -!202 = distinct !DISubprogram(name: "qdss_trace_cbuf_start", scope: !1, file: !1, line: 61, type: !203, scopeLine: 62, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !205) -!203 = !DISubroutineType(types: !204) -!204 = !{!30} -!205 = !{!206, !207} -!206 = !DILocalVariable(name: "nErr", scope: !202, file: !1, line: 63, type: !30) -!207 = !DILabel(scope: !202, name: "tempName", file: !1, line: 68) -!208 = distinct !DILocation(line: 142, column: 16, scope: !209, inlinedAt: !191) -!209 = distinct !DILexicalBlock(scope: !210, file: !1, line: 142, column: 11) -!210 = distinct !DILexicalBlock(scope: !186, file: !1, line: 140, column: 23) -!211 = !DILocation(line: 65, column: 11, scope: !194, inlinedAt: !200) -!212 = !DILocation(line: 0, scope: !213, inlinedAt: !208) -!213 = distinct !DILexicalBlock(scope: !202, file: !1, line: 66, column: 8) -!214 = !DILocation(line: 0, scope: !215, inlinedAt: !220) -!215 = distinct !DILexicalBlock(scope: !216, file: !1, line: 101, column: 8) -!216 = distinct !DISubprogram(name: "qdss_trace_hwfifo_start", scope: !1, file: !1, line: 95, type: !203, scopeLine: 96, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !217) -!217 = !{!218, !219} -!218 = !DILocalVariable(name: "nErr", scope: !216, file: !1, line: 97, type: !30) -!219 = !DILabel(scope: !216, name: "tempName", file: !1, line: 103) -!220 = distinct !DILocation(line: 147, column: 16, scope: !221, inlinedAt: !191) -!221 = distinct !DILexicalBlock(scope: !210, file: !1, line: 147, column: 11) -!222 = !DILocation(line: 0, scope: !210, inlinedAt: !191) -!223 = !DILocation(line: 282, column: 4, scope: !164) -!224 = !DILocation(line: 284, column: 31, scope: !225) -!225 = distinct !DILexicalBlock(scope: !226, file: !1, line: 282, column: 28) -!226 = distinct !DILexicalBlock(scope: !164, file: !1, line: 282, column: 18) -!227 = !DILocation(line: 285, column: 4, scope: !225) -!228 = !DILocation(line: 290, column: 1, scope: !164) diff --git a/llvm/test/CodeGen/Hexagon/global-sched-skip-vsub_fake.ll b/llvm/test/CodeGen/Hexagon/global-sched-skip-vsub_fake.ll deleted file mode 100644 index 0883e517cdf72..0000000000000 --- a/llvm/test/CodeGen/Hexagon/global-sched-skip-vsub_fake.ll +++ /dev/null @@ -1,831 +0,0 @@ -; RUN: llc -march=hexagon < %s -; REQUIRES: asserts -; -; Check that the compiler does not crash. It was asserting because function -; getMinimalPhysRegClass() was called with vsub_fake and vsub_fake does not -; belong to any target register class. - -target triple = "hexagon" - -@b = common dso_local local_unnamed_addr global i32 0, align 4 -@a = common dso_local local_unnamed_addr global i16 0, align 2 - -define dso_local void @d(i32 noundef %e, ptr nocapture noundef writeonly %g, i16 noundef signext %0, i32 noundef %1) local_unnamed_addr { -entry: - %cmp.not5 = icmp slt i32 %e, 1 - br i1 %cmp.not5, label %for.end, label %vector.body - -vector.body: ; preds = %entry - %n.rnd.up = add nuw i32 %e, 63 - %n.vec = and i32 %n.rnd.up, -64 - %trip.count.minus.1 = add nsw i32 %e, -1 - %broadcast.splatinsert8 = insertelement <64 x i32> poison, i32 %trip.count.minus.1, i64 0 - %broadcast.splat9 = shufflevector <64 x i32> %broadcast.splatinsert8, <64 x i32> poison, <64 x i32> zeroinitializer - %invariant.gep = getelementptr i8, ptr %g, i32 128 - call void @d.llvmint.extracted_region.llvmint.1.0_i32_0(<64 x i32> %broadcast.splat9, ptr %g, ptr %invariant.gep, i32 %n.vec) - br label %for.end - -for.end: ; preds = %vector.body, %entry - ret void -} - -define dso_local void @h(ptr nocapture noundef writeonly %e, ptr nocapture noundef writeonly %g) local_unnamed_addr { -entry: - %call = tail call i32 @c() - %tobool.not = icmp eq i32 %call, 0 - %0 = load i32, ptr @b, align 4 - %cmp.not5.i20 = icmp slt i32 %0, 1 - br i1 %tobool.not, label %if.else, label %if.then - -if.then: ; preds = %entry - br i1 %cmp.not5.i20, label %if.end, label %vector.body347 - -vector.body347: ; preds = %if.then - %n.rnd.up = add nuw i32 %0, 63 - %n.vec = and i32 %n.rnd.up, -64 - %trip.count.minus.1 = add nsw i32 %0, -1 - %broadcast.splatinsert63 = insertelement <64 x i32> poison, i32 %trip.count.minus.1, i64 0 - %broadcast.splat64 = shufflevector <64 x i32> %broadcast.splatinsert63, <64 x i32> poison, <64 x i32> zeroinitializer - call void @d.llvmint.extracted_region(i32 0, <64 x i32> %broadcast.splat64, ptr nonnull @a, ptr getelementptr (i8, ptr @a, i32 128), i32 %n.vec) - %invariant.gep = getelementptr i8, ptr %e, i32 128 - call void @d.llvmint.extracted_region.llvmint.1.0_i32_0(<64 x i32> %broadcast.splat64, ptr %e, ptr %invariant.gep, i32 %n.vec) - %invariant.gep928 = getelementptr i8, ptr %g, i32 128 - call void @d.llvmint.extracted_region.llvmint.1.0_i32_0(<64 x i32> %broadcast.splat64, ptr %g, ptr %invariant.gep928, i32 %n.vec) - br label %if.end - -if.else: ; preds = %entry - br i1 %cmp.not5.i20, label %d.exit42.thread, label %for.body.i28 - -d.exit42.thread: ; preds = %if.else - %arrayidx.i3154 = getelementptr inbounds i8, ptr %e, i32 2 - store i16 1, ptr %arrayidx.i3154, align 2 - %arrayidx.i31.155 = getelementptr inbounds i8, ptr %e, i32 4 - store i16 2, ptr %arrayidx.i31.155, align 2 - br label %if.end - -for.body.i28: ; preds = %if.else - %n.rnd.up488 = add nuw i32 %0, 63 - %n.vec490 = and i32 %n.rnd.up488, -64 - %trip.count.minus.1493 = add nsw i32 %0, -1 - %broadcast.splatinsert501 = insertelement <64 x i32> poison, i32 %trip.count.minus.1493, i64 0 - %broadcast.splat502 = shufflevector <64 x i32> %broadcast.splatinsert501, <64 x i32> poison, <64 x i32> zeroinitializer - call void @d.llvmint.extracted_region(i32 0, <64 x i32> %broadcast.splat502, ptr nonnull @a, ptr getelementptr (i8, ptr @a, i32 128), i32 %n.vec490) - %arrayidx.i31 = getelementptr inbounds i8, ptr %e, i32 2 - store i16 1, ptr %arrayidx.i31, align 2 - %arrayidx.i31.1 = getelementptr inbounds i8, ptr %e, i32 4 - store i16 2, ptr %arrayidx.i31.1, align 2 - %cmp.not5.i35 = icmp eq i32 %0, 1 - br i1 %cmp.not5.i35, label %vector.body788, label %d.exit42 - -d.exit42: ; preds = %for.body.i28 - %arrayidx = getelementptr inbounds i16, ptr %e, i32 %0 - %div60 = lshr i32 %0, 1 - %n.rnd.up635 = add nuw nsw i32 %div60, 63 - %n.vec637 = and i32 %n.rnd.up635, 2147483584 - %trip.count.minus.1640 = add nsw i32 %div60, -1 - %broadcast.splatinsert648 = insertelement <64 x i32> poison, i32 %trip.count.minus.1640, i64 0 - %broadcast.splat649 = shufflevector <64 x i32> %broadcast.splatinsert648, <64 x i32> poison, <64 x i32> zeroinitializer - %invariant.gep931 = getelementptr i8, ptr %arrayidx, i32 128 - call void @d.llvmint.extracted_region.llvmint.1.0_i32_0(<64 x i32> %broadcast.splat649, ptr nonnull %arrayidx, ptr %invariant.gep931, i32 %n.vec637) - br label %vector.body788 - -vector.body788: ; preds = %for.body.i28, %d.exit42 - %invariant.gep933 = getelementptr i8, ptr %g, i32 128 - call void @d.llvmint.extracted_region.llvmint.1.0_i32_0(<64 x i32> %broadcast.splat502, ptr %g, ptr %invariant.gep933, i32 %n.vec490) - br label %if.end - -if.end: ; preds = %vector.body788, %vector.body347, %d.exit42.thread, %if.then - ret void -} - -declare dso_local i32 @c(...) local_unnamed_addr - -define internal void @d.llvmint.extracted_region.llvmint.1.0_i32_0(<64 x i32> %0, ptr %1, ptr %2, i32 %3) { - tail call void @d.llvmint.extracted_region(i32 0, <64 x i32> %0, ptr %1, ptr %2, i32 %3) - ret void -} - -define internal void @d.llvmint.extracted_region(i32 %0, <64 x i32> %1, ptr %2, ptr %3, i32 %4) { -entry: - br label %vector.body.extracted_entry - -vector.body.extracted_entry: ; preds = %entry, %pred.store.continue135 - %index.extracted = phi i32 [ %index.next, %pred.store.continue135 ], [ %0, %entry ] - %5 = trunc i32 %index.extracted to i16 - %broadcast.splatinsert = insertelement <64 x i32> poison, i32 %index.extracted, i64 0 - %broadcast.splat = shufflevector <64 x i32> %broadcast.splatinsert, <64 x i32> poison, <64 x i32> zeroinitializer - %vec.iv = or disjoint <64 x i32> %broadcast.splat, - %6 = icmp ule <64 x i32> %vec.iv, %1 - %7 = extractelement <64 x i1> %6, i64 0 - br i1 %7, label %pred.store.if, label %pred.store.continue - -pred.store.if: ; preds = %vector.body.extracted_entry - %8 = or disjoint i16 %5, 1 - %offset.idx = or disjoint i32 %index.extracted, 1 - %9 = getelementptr inbounds i16, ptr %2, i32 %offset.idx - store i16 %8, ptr %9, align 2 - br label %pred.store.continue - -pred.store.continue: ; preds = %pred.store.if, %vector.body.extracted_entry - %10 = extractelement <64 x i1> %6, i64 1 - br i1 %10, label %pred.store.if10, label %pred.store.continue11 - -pred.store.if10: ; preds = %pred.store.continue - %11 = or disjoint i32 %index.extracted, 2 - %12 = getelementptr inbounds i16, ptr %2, i32 %11 - %13 = or disjoint i16 %5, 2 - store i16 %13, ptr %12, align 2 - br label %pred.store.continue11 - -pred.store.continue11: ; preds = %pred.store.if10, %pred.store.continue - %14 = extractelement <64 x i1> %6, i64 2 - br i1 %14, label %pred.store.if12, label %pred.store.continue13 - -pred.store.if12: ; preds = %pred.store.continue11 - %15 = or disjoint i32 %index.extracted, 3 - %16 = getelementptr inbounds i16, ptr %2, i32 %15 - %17 = or disjoint i16 %5, 3 - store i16 %17, ptr %16, align 2 - br label %pred.store.continue13 - -pred.store.continue13: ; preds = %pred.store.if12, %pred.store.continue11 - %18 = extractelement <64 x i1> %6, i64 3 - br i1 %18, label %pred.store.if14, label %pred.store.continue15 - -pred.store.if14: ; preds = %pred.store.continue13 - %19 = or disjoint i32 %index.extracted, 4 - %20 = getelementptr inbounds i16, ptr %2, i32 %19 - %21 = or disjoint i16 %5, 4 - store i16 %21, ptr %20, align 2 - br label %pred.store.continue15 - -pred.store.continue15: ; preds = %pred.store.if14, %pred.store.continue13 - %22 = extractelement <64 x i1> %6, i64 4 - br i1 %22, label %pred.store.if16, label %pred.store.continue17 - -pred.store.if16: ; preds = %pred.store.continue15 - %23 = or disjoint i32 %index.extracted, 5 - %24 = getelementptr inbounds i16, ptr %2, i32 %23 - %25 = or disjoint i16 %5, 5 - store i16 %25, ptr %24, align 2 - br label %pred.store.continue17 - -pred.store.continue17: ; preds = %pred.store.if16, %pred.store.continue15 - %26 = extractelement <64 x i1> %6, i64 5 - br i1 %26, label %pred.store.if18, label %pred.store.continue19 - -pred.store.if18: ; preds = %pred.store.continue17 - %27 = or disjoint i32 %index.extracted, 6 - %28 = getelementptr inbounds i16, ptr %2, i32 %27 - %29 = or disjoint i16 %5, 6 - store i16 %29, ptr %28, align 2 - br label %pred.store.continue19 - -pred.store.continue19: ; preds = %pred.store.if18, %pred.store.continue17 - %30 = extractelement <64 x i1> %6, i64 6 - br i1 %30, label %pred.store.if20, label %pred.store.continue21 - -pred.store.if20: ; preds = %pred.store.continue19 - %31 = or disjoint i32 %index.extracted, 7 - %32 = getelementptr inbounds i16, ptr %2, i32 %31 - %33 = or disjoint i16 %5, 7 - store i16 %33, ptr %32, align 2 - br label %pred.store.continue21 - -pred.store.continue21: ; preds = %pred.store.if20, %pred.store.continue19 - %34 = extractelement <64 x i1> %6, i64 7 - br i1 %34, label %pred.store.if22, label %pred.store.continue23 - -pred.store.if22: ; preds = %pred.store.continue21 - %35 = or disjoint i32 %index.extracted, 8 - %36 = getelementptr inbounds i16, ptr %2, i32 %35 - %37 = or disjoint i16 %5, 8 - store i16 %37, ptr %36, align 2 - br label %pred.store.continue23 - -pred.store.continue23: ; preds = %pred.store.if22, %pred.store.continue21 - %38 = extractelement <64 x i1> %6, i64 8 - br i1 %38, label %pred.store.if24, label %pred.store.continue25 - -pred.store.if24: ; preds = %pred.store.continue23 - %39 = or disjoint i32 %index.extracted, 9 - %40 = getelementptr inbounds i16, ptr %2, i32 %39 - %41 = or disjoint i16 %5, 9 - store i16 %41, ptr %40, align 2 - br label %pred.store.continue25 - -pred.store.continue25: ; preds = %pred.store.if24, %pred.store.continue23 - %42 = extractelement <64 x i1> %6, i64 9 - br i1 %42, label %pred.store.if26, label %pred.store.continue27 - -pred.store.if26: ; preds = %pred.store.continue25 - %43 = or disjoint i32 %index.extracted, 10 - %44 = getelementptr inbounds i16, ptr %2, i32 %43 - %45 = or disjoint i16 %5, 10 - store i16 %45, ptr %44, align 2 - br label %pred.store.continue27 - -pred.store.continue27: ; preds = %pred.store.if26, %pred.store.continue25 - %46 = extractelement <64 x i1> %6, i64 10 - br i1 %46, label %pred.store.if28, label %pred.store.continue29 - -pred.store.if28: ; preds = %pred.store.continue27 - %47 = or disjoint i32 %index.extracted, 11 - %48 = getelementptr inbounds i16, ptr %2, i32 %47 - %49 = or disjoint i16 %5, 11 - store i16 %49, ptr %48, align 2 - br label %pred.store.continue29 - -pred.store.continue29: ; preds = %pred.store.if28, %pred.store.continue27 - %50 = extractelement <64 x i1> %6, i64 11 - br i1 %50, label %pred.store.if30, label %pred.store.continue31 - -pred.store.if30: ; preds = %pred.store.continue29 - %51 = or disjoint i32 %index.extracted, 12 - %52 = getelementptr inbounds i16, ptr %2, i32 %51 - %53 = or disjoint i16 %5, 12 - store i16 %53, ptr %52, align 2 - br label %pred.store.continue31 - -pred.store.continue31: ; preds = %pred.store.if30, %pred.store.continue29 - %54 = extractelement <64 x i1> %6, i64 12 - br i1 %54, label %pred.store.if32, label %pred.store.continue33 - -pred.store.if32: ; preds = %pred.store.continue31 - %55 = or disjoint i32 %index.extracted, 13 - %56 = getelementptr inbounds i16, ptr %2, i32 %55 - %57 = or disjoint i16 %5, 13 - store i16 %57, ptr %56, align 2 - br label %pred.store.continue33 - -pred.store.continue33: ; preds = %pred.store.if32, %pred.store.continue31 - %58 = extractelement <64 x i1> %6, i64 13 - br i1 %58, label %pred.store.if34, label %pred.store.continue35 - -pred.store.if34: ; preds = %pred.store.continue33 - %59 = or disjoint i32 %index.extracted, 14 - %60 = getelementptr inbounds i16, ptr %2, i32 %59 - %61 = or disjoint i16 %5, 14 - store i16 %61, ptr %60, align 2 - br label %pred.store.continue35 - -pred.store.continue35: ; preds = %pred.store.if34, %pred.store.continue33 - %62 = extractelement <64 x i1> %6, i64 14 - br i1 %62, label %pred.store.if36, label %pred.store.continue37 - -pred.store.if36: ; preds = %pred.store.continue35 - %63 = or disjoint i32 %index.extracted, 15 - %64 = getelementptr inbounds i16, ptr %2, i32 %63 - %65 = or disjoint i16 %5, 15 - store i16 %65, ptr %64, align 2 - br label %pred.store.continue37 - -pred.store.continue37: ; preds = %pred.store.if36, %pred.store.continue35 - %66 = extractelement <64 x i1> %6, i64 15 - br i1 %66, label %pred.store.if38, label %pred.store.continue39 - -pred.store.if38: ; preds = %pred.store.continue37 - %67 = or disjoint i32 %index.extracted, 16 - %68 = getelementptr inbounds i16, ptr %2, i32 %67 - %69 = or disjoint i16 %5, 16 - store i16 %69, ptr %68, align 2 - br label %pred.store.continue39 - -pred.store.continue39: ; preds = %pred.store.if38, %pred.store.continue37 - %70 = extractelement <64 x i1> %6, i64 16 - br i1 %70, label %pred.store.if40, label %pred.store.continue41 - -pred.store.if40: ; preds = %pred.store.continue39 - %71 = or disjoint i32 %index.extracted, 17 - %72 = getelementptr inbounds i16, ptr %2, i32 %71 - %73 = or disjoint i16 %5, 17 - store i16 %73, ptr %72, align 2 - br label %pred.store.continue41 - -pred.store.continue41: ; preds = %pred.store.if40, %pred.store.continue39 - %74 = extractelement <64 x i1> %6, i64 17 - br i1 %74, label %pred.store.if42, label %pred.store.continue43 - -pred.store.if42: ; preds = %pred.store.continue41 - %75 = or disjoint i32 %index.extracted, 18 - %76 = getelementptr inbounds i16, ptr %2, i32 %75 - %77 = or disjoint i16 %5, 18 - store i16 %77, ptr %76, align 2 - br label %pred.store.continue43 - -pred.store.continue43: ; preds = %pred.store.if42, %pred.store.continue41 - %78 = extractelement <64 x i1> %6, i64 18 - br i1 %78, label %pred.store.if44, label %pred.store.continue45 - -pred.store.if44: ; preds = %pred.store.continue43 - %79 = or disjoint i32 %index.extracted, 19 - %80 = getelementptr inbounds i16, ptr %2, i32 %79 - %81 = or disjoint i16 %5, 19 - store i16 %81, ptr %80, align 2 - br label %pred.store.continue45 - -pred.store.continue45: ; preds = %pred.store.if44, %pred.store.continue43 - %82 = extractelement <64 x i1> %6, i64 19 - br i1 %82, label %pred.store.if46, label %pred.store.continue47 - -pred.store.if46: ; preds = %pred.store.continue45 - %83 = or disjoint i32 %index.extracted, 20 - %84 = getelementptr inbounds i16, ptr %2, i32 %83 - %85 = or disjoint i16 %5, 20 - store i16 %85, ptr %84, align 2 - br label %pred.store.continue47 - -pred.store.continue47: ; preds = %pred.store.if46, %pred.store.continue45 - %86 = extractelement <64 x i1> %6, i64 20 - br i1 %86, label %pred.store.if48, label %pred.store.continue49 - -pred.store.if48: ; preds = %pred.store.continue47 - %87 = or disjoint i32 %index.extracted, 21 - %88 = getelementptr inbounds i16, ptr %2, i32 %87 - %89 = or disjoint i16 %5, 21 - store i16 %89, ptr %88, align 2 - br label %pred.store.continue49 - -pred.store.continue49: ; preds = %pred.store.if48, %pred.store.continue47 - %90 = extractelement <64 x i1> %6, i64 21 - br i1 %90, label %pred.store.if50, label %pred.store.continue51 - -pred.store.if50: ; preds = %pred.store.continue49 - %91 = or disjoint i32 %index.extracted, 22 - %92 = getelementptr inbounds i16, ptr %2, i32 %91 - %93 = or disjoint i16 %5, 22 - store i16 %93, ptr %92, align 2 - br label %pred.store.continue51 - -pred.store.continue51: ; preds = %pred.store.if50, %pred.store.continue49 - %94 = extractelement <64 x i1> %6, i64 22 - br i1 %94, label %pred.store.if52, label %pred.store.continue53 - -pred.store.if52: ; preds = %pred.store.continue51 - %95 = or disjoint i32 %index.extracted, 23 - %96 = getelementptr inbounds i16, ptr %2, i32 %95 - %97 = or disjoint i16 %5, 23 - store i16 %97, ptr %96, align 2 - br label %pred.store.continue53 - -pred.store.continue53: ; preds = %pred.store.if52, %pred.store.continue51 - %98 = extractelement <64 x i1> %6, i64 23 - br i1 %98, label %pred.store.if54, label %pred.store.continue55 - -pred.store.if54: ; preds = %pred.store.continue53 - %99 = or disjoint i32 %index.extracted, 24 - %100 = getelementptr inbounds i16, ptr %2, i32 %99 - %101 = or disjoint i16 %5, 24 - store i16 %101, ptr %100, align 2 - br label %pred.store.continue55 - -pred.store.continue55: ; preds = %pred.store.if54, %pred.store.continue53 - %102 = extractelement <64 x i1> %6, i64 24 - br i1 %102, label %pred.store.if56, label %pred.store.continue57 - -pred.store.if56: ; preds = %pred.store.continue55 - %103 = or disjoint i32 %index.extracted, 25 - %104 = getelementptr inbounds i16, ptr %2, i32 %103 - %105 = or disjoint i16 %5, 25 - store i16 %105, ptr %104, align 2 - br label %pred.store.continue57 - -pred.store.continue57: ; preds = %pred.store.if56, %pred.store.continue55 - %106 = extractelement <64 x i1> %6, i64 25 - br i1 %106, label %pred.store.if58, label %pred.store.continue59 - -pred.store.if58: ; preds = %pred.store.continue57 - %107 = or disjoint i32 %index.extracted, 26 - %108 = getelementptr inbounds i16, ptr %2, i32 %107 - %109 = or disjoint i16 %5, 26 - store i16 %109, ptr %108, align 2 - br label %pred.store.continue59 - -pred.store.continue59: ; preds = %pred.store.if58, %pred.store.continue57 - %110 = extractelement <64 x i1> %6, i64 26 - br i1 %110, label %pred.store.if60, label %pred.store.continue61 - -pred.store.if60: ; preds = %pred.store.continue59 - %111 = or disjoint i32 %index.extracted, 27 - %112 = getelementptr inbounds i16, ptr %2, i32 %111 - %113 = or disjoint i16 %5, 27 - store i16 %113, ptr %112, align 2 - br label %pred.store.continue61 - -pred.store.continue61: ; preds = %pred.store.if60, %pred.store.continue59 - %114 = extractelement <64 x i1> %6, i64 27 - br i1 %114, label %pred.store.if62, label %pred.store.continue63 - -pred.store.if62: ; preds = %pred.store.continue61 - %115 = or disjoint i32 %index.extracted, 28 - %116 = getelementptr inbounds i16, ptr %2, i32 %115 - %117 = or disjoint i16 %5, 28 - store i16 %117, ptr %116, align 2 - br label %pred.store.continue63 - -pred.store.continue63: ; preds = %pred.store.if62, %pred.store.continue61 - %118 = extractelement <64 x i1> %6, i64 28 - br i1 %118, label %pred.store.if64, label %pred.store.continue65 - -pred.store.if64: ; preds = %pred.store.continue63 - %119 = or disjoint i32 %index.extracted, 29 - %120 = getelementptr inbounds i16, ptr %2, i32 %119 - %121 = or disjoint i16 %5, 29 - store i16 %121, ptr %120, align 2 - br label %pred.store.continue65 - -pred.store.continue65: ; preds = %pred.store.if64, %pred.store.continue63 - %122 = extractelement <64 x i1> %6, i64 29 - br i1 %122, label %pred.store.if66, label %pred.store.continue67 - -pred.store.if66: ; preds = %pred.store.continue65 - %123 = or disjoint i32 %index.extracted, 30 - %124 = getelementptr inbounds i16, ptr %2, i32 %123 - %125 = or disjoint i16 %5, 30 - store i16 %125, ptr %124, align 2 - br label %pred.store.continue67 - -pred.store.continue67: ; preds = %pred.store.if66, %pred.store.continue65 - %126 = extractelement <64 x i1> %6, i64 30 - br i1 %126, label %pred.store.if68, label %pred.store.continue69 - -pred.store.if68: ; preds = %pred.store.continue67 - %127 = or disjoint i32 %index.extracted, 31 - %128 = getelementptr inbounds i16, ptr %2, i32 %127 - %129 = or disjoint i16 %5, 31 - store i16 %129, ptr %128, align 2 - br label %pred.store.continue69 - -pred.store.continue69: ; preds = %pred.store.if68, %pred.store.continue67 - %130 = extractelement <64 x i1> %6, i64 31 - br i1 %130, label %pred.store.if70, label %pred.store.continue71 - -pred.store.if70: ; preds = %pred.store.continue69 - %131 = or disjoint i32 %index.extracted, 32 - %132 = getelementptr inbounds i16, ptr %2, i32 %131 - %133 = or disjoint i16 %5, 32 - store i16 %133, ptr %132, align 2 - br label %pred.store.continue71 - -pred.store.continue71: ; preds = %pred.store.if70, %pred.store.continue69 - %134 = extractelement <64 x i1> %6, i64 32 - br i1 %134, label %pred.store.if72, label %pred.store.continue73 - -pred.store.if72: ; preds = %pred.store.continue71 - %135 = or disjoint i32 %index.extracted, 33 - %136 = getelementptr inbounds i16, ptr %2, i32 %135 - %137 = or disjoint i16 %5, 33 - store i16 %137, ptr %136, align 2 - br label %pred.store.continue73 - -pred.store.continue73: ; preds = %pred.store.if72, %pred.store.continue71 - %138 = extractelement <64 x i1> %6, i64 33 - br i1 %138, label %pred.store.if74, label %pred.store.continue75 - -pred.store.if74: ; preds = %pred.store.continue73 - %139 = or disjoint i32 %index.extracted, 34 - %140 = getelementptr inbounds i16, ptr %2, i32 %139 - %141 = or disjoint i16 %5, 34 - store i16 %141, ptr %140, align 2 - br label %pred.store.continue75 - -pred.store.continue75: ; preds = %pred.store.if74, %pred.store.continue73 - %142 = extractelement <64 x i1> %6, i64 34 - br i1 %142, label %pred.store.if76, label %pred.store.continue77 - -pred.store.if76: ; preds = %pred.store.continue75 - %143 = or disjoint i32 %index.extracted, 35 - %144 = getelementptr inbounds i16, ptr %2, i32 %143 - %145 = or disjoint i16 %5, 35 - store i16 %145, ptr %144, align 2 - br label %pred.store.continue77 - -pred.store.continue77: ; preds = %pred.store.if76, %pred.store.continue75 - %146 = extractelement <64 x i1> %6, i64 35 - br i1 %146, label %pred.store.if78, label %pred.store.continue79 - -pred.store.if78: ; preds = %pred.store.continue77 - %147 = or disjoint i32 %index.extracted, 36 - %148 = getelementptr inbounds i16, ptr %2, i32 %147 - %149 = or disjoint i16 %5, 36 - store i16 %149, ptr %148, align 2 - br label %pred.store.continue79 - -pred.store.continue79: ; preds = %pred.store.if78, %pred.store.continue77 - %150 = extractelement <64 x i1> %6, i64 36 - br i1 %150, label %pred.store.if80, label %pred.store.continue81 - -pred.store.if80: ; preds = %pred.store.continue79 - %151 = or disjoint i32 %index.extracted, 37 - %152 = getelementptr inbounds i16, ptr %2, i32 %151 - %153 = or disjoint i16 %5, 37 - store i16 %153, ptr %152, align 2 - br label %pred.store.continue81 - -pred.store.continue81: ; preds = %pred.store.if80, %pred.store.continue79 - %154 = extractelement <64 x i1> %6, i64 37 - br i1 %154, label %pred.store.if82, label %pred.store.continue83 - -pred.store.if82: ; preds = %pred.store.continue81 - %155 = or disjoint i32 %index.extracted, 38 - %156 = getelementptr inbounds i16, ptr %2, i32 %155 - %157 = or disjoint i16 %5, 38 - store i16 %157, ptr %156, align 2 - br label %pred.store.continue83 - -pred.store.continue83: ; preds = %pred.store.if82, %pred.store.continue81 - %158 = extractelement <64 x i1> %6, i64 38 - br i1 %158, label %pred.store.if84, label %pred.store.continue85 - -pred.store.if84: ; preds = %pred.store.continue83 - %159 = or disjoint i32 %index.extracted, 39 - %160 = getelementptr inbounds i16, ptr %2, i32 %159 - %161 = or disjoint i16 %5, 39 - store i16 %161, ptr %160, align 2 - br label %pred.store.continue85 - -pred.store.continue85: ; preds = %pred.store.if84, %pred.store.continue83 - %162 = extractelement <64 x i1> %6, i64 39 - br i1 %162, label %pred.store.if86, label %pred.store.continue87 - -pred.store.if86: ; preds = %pred.store.continue85 - %163 = or disjoint i32 %index.extracted, 40 - %164 = getelementptr inbounds i16, ptr %2, i32 %163 - %165 = or disjoint i16 %5, 40 - store i16 %165, ptr %164, align 2 - br label %pred.store.continue87 - -pred.store.continue87: ; preds = %pred.store.if86, %pred.store.continue85 - %166 = extractelement <64 x i1> %6, i64 40 - br i1 %166, label %pred.store.if88, label %pred.store.continue89 - -pred.store.if88: ; preds = %pred.store.continue87 - %167 = or disjoint i32 %index.extracted, 41 - %168 = getelementptr inbounds i16, ptr %2, i32 %167 - %169 = or disjoint i16 %5, 41 - store i16 %169, ptr %168, align 2 - br label %pred.store.continue89 - -pred.store.continue89: ; preds = %pred.store.if88, %pred.store.continue87 - %170 = extractelement <64 x i1> %6, i64 41 - br i1 %170, label %pred.store.if90, label %pred.store.continue91 - -pred.store.if90: ; preds = %pred.store.continue89 - %171 = or disjoint i32 %index.extracted, 42 - %172 = getelementptr inbounds i16, ptr %2, i32 %171 - %173 = or disjoint i16 %5, 42 - store i16 %173, ptr %172, align 2 - br label %pred.store.continue91 - -pred.store.continue91: ; preds = %pred.store.if90, %pred.store.continue89 - %174 = extractelement <64 x i1> %6, i64 42 - br i1 %174, label %pred.store.if92, label %pred.store.continue93 - -pred.store.if92: ; preds = %pred.store.continue91 - %175 = or disjoint i32 %index.extracted, 43 - %176 = getelementptr inbounds i16, ptr %2, i32 %175 - %177 = or disjoint i16 %5, 43 - store i16 %177, ptr %176, align 2 - br label %pred.store.continue93 - -pred.store.continue93: ; preds = %pred.store.if92, %pred.store.continue91 - %178 = extractelement <64 x i1> %6, i64 43 - br i1 %178, label %pred.store.if94, label %pred.store.continue95 - -pred.store.if94: ; preds = %pred.store.continue93 - %179 = or disjoint i32 %index.extracted, 44 - %180 = getelementptr inbounds i16, ptr %2, i32 %179 - %181 = or disjoint i16 %5, 44 - store i16 %181, ptr %180, align 2 - br label %pred.store.continue95 - -pred.store.continue95: ; preds = %pred.store.if94, %pred.store.continue93 - %182 = extractelement <64 x i1> %6, i64 44 - br i1 %182, label %pred.store.if96, label %pred.store.continue97 - -pred.store.if96: ; preds = %pred.store.continue95 - %183 = or disjoint i32 %index.extracted, 45 - %184 = getelementptr inbounds i16, ptr %2, i32 %183 - %185 = or disjoint i16 %5, 45 - store i16 %185, ptr %184, align 2 - br label %pred.store.continue97 - -pred.store.continue97: ; preds = %pred.store.if96, %pred.store.continue95 - %186 = extractelement <64 x i1> %6, i64 45 - br i1 %186, label %pred.store.if98, label %pred.store.continue99 - -pred.store.if98: ; preds = %pred.store.continue97 - %187 = or disjoint i32 %index.extracted, 46 - %188 = getelementptr inbounds i16, ptr %2, i32 %187 - %189 = or disjoint i16 %5, 46 - store i16 %189, ptr %188, align 2 - br label %pred.store.continue99 - -pred.store.continue99: ; preds = %pred.store.if98, %pred.store.continue97 - %190 = extractelement <64 x i1> %6, i64 46 - br i1 %190, label %pred.store.if100, label %pred.store.continue101 - -pred.store.if100: ; preds = %pred.store.continue99 - %191 = or disjoint i32 %index.extracted, 47 - %192 = getelementptr inbounds i16, ptr %2, i32 %191 - %193 = or disjoint i16 %5, 47 - store i16 %193, ptr %192, align 2 - br label %pred.store.continue101 - -pred.store.continue101: ; preds = %pred.store.if100, %pred.store.continue99 - %194 = extractelement <64 x i1> %6, i64 47 - br i1 %194, label %pred.store.if102, label %pred.store.continue103 - -pred.store.if102: ; preds = %pred.store.continue101 - %195 = or disjoint i32 %index.extracted, 48 - %196 = getelementptr inbounds i16, ptr %2, i32 %195 - %197 = or disjoint i16 %5, 48 - store i16 %197, ptr %196, align 2 - br label %pred.store.continue103 - -pred.store.continue103: ; preds = %pred.store.if102, %pred.store.continue101 - %198 = extractelement <64 x i1> %6, i64 48 - br i1 %198, label %pred.store.if104, label %pred.store.continue105 - -pred.store.if104: ; preds = %pred.store.continue103 - %199 = or disjoint i32 %index.extracted, 49 - %200 = getelementptr inbounds i16, ptr %2, i32 %199 - %201 = or disjoint i16 %5, 49 - store i16 %201, ptr %200, align 2 - br label %pred.store.continue105 - -pred.store.continue105: ; preds = %pred.store.if104, %pred.store.continue103 - %202 = extractelement <64 x i1> %6, i64 49 - br i1 %202, label %pred.store.if106, label %pred.store.continue107 - -pred.store.if106: ; preds = %pred.store.continue105 - %203 = or disjoint i32 %index.extracted, 50 - %204 = getelementptr inbounds i16, ptr %2, i32 %203 - %205 = or disjoint i16 %5, 50 - store i16 %205, ptr %204, align 2 - br label %pred.store.continue107 - -pred.store.continue107: ; preds = %pred.store.if106, %pred.store.continue105 - %206 = extractelement <64 x i1> %6, i64 50 - br i1 %206, label %pred.store.if108, label %pred.store.continue109 - -pred.store.if108: ; preds = %pred.store.continue107 - %207 = or disjoint i32 %index.extracted, 51 - %208 = getelementptr inbounds i16, ptr %2, i32 %207 - %209 = or disjoint i16 %5, 51 - store i16 %209, ptr %208, align 2 - br label %pred.store.continue109 - -pred.store.continue109: ; preds = %pred.store.if108, %pred.store.continue107 - %210 = extractelement <64 x i1> %6, i64 51 - br i1 %210, label %pred.store.if110, label %pred.store.continue111 - -pred.store.if110: ; preds = %pred.store.continue109 - %211 = or disjoint i32 %index.extracted, 52 - %212 = getelementptr inbounds i16, ptr %2, i32 %211 - %213 = or disjoint i16 %5, 52 - store i16 %213, ptr %212, align 2 - br label %pred.store.continue111 - -pred.store.continue111: ; preds = %pred.store.if110, %pred.store.continue109 - %214 = extractelement <64 x i1> %6, i64 52 - br i1 %214, label %pred.store.if112, label %pred.store.continue113 - -pred.store.if112: ; preds = %pred.store.continue111 - %215 = or disjoint i32 %index.extracted, 53 - %216 = getelementptr inbounds i16, ptr %2, i32 %215 - %217 = or disjoint i16 %5, 53 - store i16 %217, ptr %216, align 2 - br label %pred.store.continue113 - -pred.store.continue113: ; preds = %pred.store.if112, %pred.store.continue111 - %218 = extractelement <64 x i1> %6, i64 53 - br i1 %218, label %pred.store.if114, label %pred.store.continue115 - -pred.store.if114: ; preds = %pred.store.continue113 - %219 = or disjoint i32 %index.extracted, 54 - %220 = getelementptr inbounds i16, ptr %2, i32 %219 - %221 = or disjoint i16 %5, 54 - store i16 %221, ptr %220, align 2 - br label %pred.store.continue115 - -pred.store.continue115: ; preds = %pred.store.if114, %pred.store.continue113 - %222 = extractelement <64 x i1> %6, i64 54 - br i1 %222, label %pred.store.if116, label %pred.store.continue117 - -pred.store.if116: ; preds = %pred.store.continue115 - %223 = or disjoint i32 %index.extracted, 55 - %224 = getelementptr inbounds i16, ptr %2, i32 %223 - %225 = or disjoint i16 %5, 55 - store i16 %225, ptr %224, align 2 - br label %pred.store.continue117 - -pred.store.continue117: ; preds = %pred.store.if116, %pred.store.continue115 - %226 = extractelement <64 x i1> %6, i64 55 - br i1 %226, label %pred.store.if118, label %pred.store.continue119 - -pred.store.if118: ; preds = %pred.store.continue117 - %227 = or disjoint i32 %index.extracted, 56 - %228 = getelementptr inbounds i16, ptr %2, i32 %227 - %229 = or disjoint i16 %5, 56 - store i16 %229, ptr %228, align 2 - br label %pred.store.continue119 - -pred.store.continue119: ; preds = %pred.store.if118, %pred.store.continue117 - %230 = extractelement <64 x i1> %6, i64 56 - br i1 %230, label %pred.store.if120, label %pred.store.continue121 - -pred.store.if120: ; preds = %pred.store.continue119 - %231 = or disjoint i32 %index.extracted, 57 - %232 = getelementptr inbounds i16, ptr %2, i32 %231 - %233 = or disjoint i16 %5, 57 - store i16 %233, ptr %232, align 2 - br label %pred.store.continue121 - -pred.store.continue121: ; preds = %pred.store.if120, %pred.store.continue119 - %234 = extractelement <64 x i1> %6, i64 57 - br i1 %234, label %pred.store.if122, label %pred.store.continue123 - -pred.store.if122: ; preds = %pred.store.continue121 - %235 = or disjoint i32 %index.extracted, 58 - %236 = getelementptr inbounds i16, ptr %2, i32 %235 - %237 = or disjoint i16 %5, 58 - store i16 %237, ptr %236, align 2 - br label %pred.store.continue123 - -pred.store.continue123: ; preds = %pred.store.if122, %pred.store.continue121 - %238 = extractelement <64 x i1> %6, i64 58 - br i1 %238, label %pred.store.if124, label %pred.store.continue125 - -pred.store.if124: ; preds = %pred.store.continue123 - %239 = or disjoint i32 %index.extracted, 59 - %240 = getelementptr inbounds i16, ptr %2, i32 %239 - %241 = or disjoint i16 %5, 59 - store i16 %241, ptr %240, align 2 - br label %pred.store.continue125 - -pred.store.continue125: ; preds = %pred.store.if124, %pred.store.continue123 - %242 = extractelement <64 x i1> %6, i64 59 - br i1 %242, label %pred.store.if126, label %pred.store.continue127 - -pred.store.if126: ; preds = %pred.store.continue125 - %243 = or disjoint i32 %index.extracted, 60 - %244 = getelementptr inbounds i16, ptr %2, i32 %243 - %245 = or disjoint i16 %5, 60 - store i16 %245, ptr %244, align 2 - br label %pred.store.continue127 - -pred.store.continue127: ; preds = %pred.store.if126, %pred.store.continue125 - %246 = extractelement <64 x i1> %6, i64 60 - br i1 %246, label %pred.store.if128, label %pred.store.continue129 - -pred.store.if128: ; preds = %pred.store.continue127 - %247 = or disjoint i32 %index.extracted, 61 - %248 = getelementptr inbounds i16, ptr %2, i32 %247 - %249 = or disjoint i16 %5, 61 - store i16 %249, ptr %248, align 2 - br label %pred.store.continue129 - -pred.store.continue129: ; preds = %pred.store.if128, %pred.store.continue127 - %250 = extractelement <64 x i1> %6, i64 61 - br i1 %250, label %pred.store.if130, label %pred.store.continue131 - -pred.store.if130: ; preds = %pred.store.continue129 - %251 = or disjoint i32 %index.extracted, 62 - %252 = getelementptr inbounds i16, ptr %2, i32 %251 - %253 = or disjoint i16 %5, 62 - store i16 %253, ptr %252, align 2 - br label %pred.store.continue131 - -pred.store.continue131: ; preds = %pred.store.if130, %pred.store.continue129 - %254 = extractelement <64 x i1> %6, i64 62 - br i1 %254, label %pred.store.if132, label %pred.store.continue133 - -pred.store.if132: ; preds = %pred.store.continue131 - %255 = or disjoint i32 %index.extracted, 63 - %256 = getelementptr inbounds i16, ptr %2, i32 %255 - %257 = or disjoint i16 %5, 63 - store i16 %257, ptr %256, align 2 - br label %pred.store.continue133 - -pred.store.continue133: ; preds = %pred.store.if132, %pred.store.continue131 - %258 = extractelement <64 x i1> %6, i64 63 - br i1 %258, label %pred.store.if134, label %pred.store.continue135 - -pred.store.if134: ; preds = %pred.store.continue133 - %gep = getelementptr i16, ptr %3, i32 %index.extracted - %259 = add i16 %5, 64 - store i16 %259, ptr %gep, align 2 - br label %pred.store.continue135 - -pred.store.continue135: ; preds = %pred.store.if134, %pred.store.continue133 - %index.next = add i32 %index.extracted, 64 - %260 = icmp eq i32 %index.next, %4 - br i1 %260, label %exit, label %vector.body.extracted_entry - -exit: ; preds = %pred.store.continue135 - ret void -} - - - diff --git a/llvm/test/CodeGen/Hexagon/pull-delayed-new.mir b/llvm/test/CodeGen/Hexagon/pull-delayed-new.mir deleted file mode 100644 index ea977c378a59e..0000000000000 --- a/llvm/test/CodeGen/Hexagon/pull-delayed-new.mir +++ /dev/null @@ -1,268 +0,0 @@ -# Make sure we do not create illegal packet. -# RUN: llc -march=hexagon -run-pass global-sched -debug %s -o - | FileCheck %s - -# CHECK-NOT: Non newifiable in this bundle - ---- | - ; ModuleID = 'test.ll' - source_filename = "test.c" - target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048" - target triple = "hexagon-unknown-unknown-elf" - - %struct.S = type { [2 x i64], [128 x i8] } - - ; Function Attrs: nounwind - define dso_local i32 @f0(%struct.S* %ctx, i8* nocapture readnone %input, i32 %ilen) local_unnamed_addr #0 { - entry: - %cmp = icmp eq i32 %ilen, 0 - br i1 %cmp, label %cleanup, label %if.end - - if.end: ; preds = %entry - %cgep58 = bitcast %struct.S* %ctx to %struct.S* - %cgep5259 = bitcast %struct.S* %cgep58 to i64* - %0 = load i64, i64* %cgep5259, align 8 - %1 = trunc i64 %0 to i32 - %conv = and i32 %1, 127 - %conv1 = sext i32 %ilen to i64 - %2 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %0, i64 %conv1) - %math = extractvalue { i64, i1 } %2, 0 - %ov = extractvalue { i64, i1 } %2, 1 - %cgep5360 = bitcast %struct.S* %cgep58 to i64* - store i64 %math, i64* %cgep5360, align 8 - br i1 %ov, label %if.then9, label %if.end12 - - if.then9: ; preds = %if.end - %3 = bitcast %struct.S* %ctx to %struct.S* - %cgep4 = bitcast %struct.S* %3 to %struct.S* - %cgep2 = getelementptr inbounds %struct.S, %struct.S* %cgep4, i32 0, i32 0, i32 1 - %4 = load i64, i64* %cgep2, align 8 - %inc = add i64 %4, 1 - %cgep3 = getelementptr inbounds %struct.S, %struct.S* %cgep4, i32 0, i32 0, i32 1 - store i64 %inc, i64* %cgep3, align 8 - br label %if.end12 - - if.end12: ; preds = %if.then9, %if.end - %tobool = icmp ne i32 %conv, 0 - %cmp13 = icmp sle i32 %conv, %ilen - %or.cond = and i1 %tobool, %cmp13 - br i1 %or.cond, label %if.then15, label %if.end20 - - if.then15: ; preds = %if.end12 - %call = tail call i32 @f1(%struct.S* nonnull %ctx) #3 - %cmp16 = icmp eq i32 %call, 0 - br i1 %cmp16, label %if.end19, label %cleanup - - if.end19: ; preds = %if.then15 - %sub = sub nsw i32 %ilen, %conv - br label %if.end20 - - if.end20: ; preds = %if.end19, %if.end12 - %ilen.addr.0 = phi i32 [ %sub, %if.end19 ], [ %ilen, %if.end12 ] - %cmp2148 = icmp sgt i32 %ilen.addr.0, 127 - br i1 %cmp2148, label %while.body, label %cleanup - - while.cond: ; preds = %while.body - %cmp21 = icmp sgt i32 %sub28, 127 - br i1 %cmp21, label %while.body, label %cleanup - - while.body: ; preds = %if.end20, %while.cond - %ilen.addr.149 = phi i32 [ %sub28, %while.cond ], [ %ilen.addr.0, %if.end20 ] - %call23 = tail call i32 @f1(%struct.S* %ctx) #3 - %cmp24 = icmp eq i32 %call23, 0 - %sub28 = add nsw i32 %ilen.addr.149, -128 - br i1 %cmp24, label %while.cond, label %cleanup - - cleanup: ; preds = %while.body, %while.cond, %if.end20, %if.then15, %entry - %retval.0 = phi i32 [ 0, %entry ], [ %call, %if.then15 ], [ 0, %if.end20 ], [ 0, %while.cond ], [ %call23, %while.body ] - ret i32 %retval.0 - } - - declare dso_local i32 @f1(%struct.S*) local_unnamed_addr - - ; Function Attrs: nounwind readnone speculatable willreturn - declare { i64, i1 } @llvm.uadd.with.overflow.i64(i64, i64) - - ; Function Attrs: nounwind - declare void @llvm.stackprotector(i8*, i8**) - - attributes #0 = { nounwind "target-cpu"="hexagonv71" "target-features"="+v67,-long-calls,-small-data" "use-soft-float"="false" } - -... ---- -name: f0 -alignment: 16 -exposesReturnsTwice: false -legalized: false -regBankSelected: false -selected: false -failedISel: false -tracksRegLiveness: true -hasWinCFI: false -registers: [] -liveins: - - { reg: '$r0', virtual-reg: '' } - - { reg: '$r2', virtual-reg: '' } -frameInfo: - isFrameAddressTaken: false - isReturnAddressTaken: false - hasStackMap: false - hasPatchPoint: false - stackSize: 16 - offsetAdjustment: 0 - maxAlignment: 1 - adjustsStack: true - hasCalls: true - stackProtector: '' - maxCallFrameSize: 0 - cvBytesOfCalleeSavedRegisters: 0 - hasOpaqueSPAdjustment: false - hasVAStart: false - hasMustTailInVarArgFunc: false - localFrameSize: 0 - savePoint: [] - restorePoint: [] -fixedStack: - - { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 8, stack-id: default, - callee-saved-register: '$d8', callee-saved-restored: true, debug-info-variable: '', - debug-info-expression: '', debug-info-location: '' } - - { id: 1, type: spill-slot, offset: -8, size: 8, alignment: 8, stack-id: default, - callee-saved-register: '$d9', callee-saved-restored: true, debug-info-variable: '', - debug-info-expression: '', debug-info-location: '' } -stack: [] -callSites: [] -constants: [] -machineFunctionInfo: {} -body: | - bb.0.entry: - successors: %bb.11(0x30000000), %bb.1(0x50000000) - liveins: $r0:0x00000001, $r2:0x00000001, $d8, $d9, $d8, $d9, $r16, $r17, $r18, $r19 - - frame-setup BUNDLE implicit-def $r29, implicit-def $r30, implicit-def $p0, implicit killed $r29, implicit killed $framekey, implicit killed $framelimit, implicit $r30, implicit killed $r31, implicit $r2, implicit killed $d8 { - $r29 = frame-setup S2_allocframe killed $r29, 16, implicit-def $r30, implicit killed $framekey, implicit killed $framelimit, implicit $r30, implicit killed $r31 :: (store 4 into stack) - renamable $p0 = C2_cmpeqi $r2, 0 - S2_storerd_io internal $r29, -16, killed $d8 :: (store 8 into %fixed-stack.0) - } - BUNDLE implicit-def $pc, implicit killed $r29, implicit killed $d9, implicit $p0 { - S2_storerd_io killed $r29, 0, killed $d9 :: (store 8 into %fixed-stack.1) - J2_jumpt $p0, %bb.11, implicit-def $pc - } - - bb.1.if.end: - successors: %bb.2(0x40000000), %bb.3(0x40000000) - liveins: $p0, $r0, $r2 - - BUNDLE implicit-def $r18, implicit-def $r16, implicit-def $d0, implicit-def $r0, implicit-def $r1, implicit-def $p0, implicit killed $r0, implicit $r2, implicit undef $p0 { - $r18 = A2_tfr $r0 - $r16 = A2_tfr $r2 - renamable $d0 = L2_loadrd_io killed $r0, 0 :: (load 8 from %ir.cgep5259) - $p0 = C2_andn undef $p0, undef $p0 - } - renamable $r17 = S2_asr_i_r killed $r2, 31 - BUNDLE implicit-def $d1, implicit-def $r2, implicit-def $r3, implicit-def $p0, implicit-def $r17, implicit $d0, implicit $d8, implicit $p0, implicit killed $r0 { - renamable $d1, renamable $p0 = A4_addp_c renamable $d0, renamable $d8, renamable $p0 - renamable $r17 = A2_andir killed renamable $r0, 127 - } - BUNDLE implicit-def dead $pc, implicit $r18, implicit killed $d1, implicit $p0 { - S2_storerd_io renamable $r18, 0, killed renamable $d1 :: (store 8 into %ir.cgep5360) - J2_jumpf renamable $p0, %bb.3, implicit-def dead $pc - } - - bb.2.if.then9: - successors: %bb.3(0x80000000) - liveins: $r16, $r17, $r18 - - BUNDLE implicit-def $d0, implicit-def $r0, implicit-def $r1, implicit-def $d1, implicit-def $r2, implicit-def $r3, implicit $r18 { - renamable $d0 = L2_loadrd_io renamable $r18, 8 :: (load 8 from %ir.cgep2) - renamable $d1 = A2_tfrpi 1 - } - renamable $d0 = A2_addp killed renamable $d0, killed renamable $d1 - S2_storerd_io renamable $r18, 8, killed renamable $d0 :: (store 8 into %ir.cgep3) - - bb.3.if.end12: - successors: %bb.4(0x60000000), %bb.7(0x20000000) - liveins: $r16, $r17, $r18 - - BUNDLE implicit-def dead $p0, implicit-def $pc, implicit $r17 { - renamable $p0 = C2_cmpeqi renamable $r17, 0 - J2_jumptnew internal $p0, %bb.7, implicit-def $pc - } - - bb.4.if.end12: - successors: %bb.5(0x55555555), %bb.7(0x2aaaaaab) - liveins: $r16, $r17, $r18 - - BUNDLE implicit-def dead $p0, implicit-def $pc, implicit $r17, implicit $r16 { - renamable $p0 = C2_cmpgt renamable $r17, renamable $r16 - J2_jumptnew internal $p0, %bb.7, implicit-def $pc - } - - bb.5.if.then15: - successors: %bb.7(0x30000000), %bb.13(0x50000000) - liveins: $r16, $r17, $r18 - - BUNDLE implicit-def $r0, implicit-def $pc, implicit-def $r31, implicit-def $r29, implicit $r18, implicit $r29 { - $r0 = A2_tfr $r18 - J2_call @f1, hexagoncsr, implicit-def $pc, implicit-def $r31, implicit $r29, implicit internal $r0, implicit-def $r29, implicit-def $r0 - } - BUNDLE implicit-def $r16, implicit-def dead $p0, implicit-def dead $pc, implicit killed $r16, implicit killed $r17, implicit $r0 { - renamable $r16 = nsw A2_sub killed renamable $r16, killed renamable $r17 - renamable $p0 = C2_cmpeqi renamable $r0, 0 - J2_jumpfnewpt internal renamable $p0, %bb.13, implicit-def dead $pc - } - - bb.7.if.end20: - successors: %bb.8(0x40000000), %bb.13(0x40000000) - liveins: $r16, $r18 - - BUNDLE implicit-def $r0, implicit-def dead $p0, implicit-def $pc, implicit $r16 { - renamable $r0 = A2_tfrsi 0 - renamable $p0 = C2_cmpgti renamable $r16, 127 - J2_jumpfnewpt internal $p0, %bb.13, implicit-def $pc - } - - bb.8.while.body (align 16): - successors: %bb.9(0x7c000000), %bb.13(0x04000000) - liveins: $r16, $r18 - - BUNDLE implicit-def $r0, implicit-def $pc, implicit-def $r31, implicit-def $r29, implicit $r18, implicit $r29 { - $r0 = A2_tfr $r18 - J2_call @f1, hexagoncsr, implicit-def $pc, implicit-def $r31, implicit $r29, implicit internal $r0, implicit-def $r29, implicit-def $r0 - } - BUNDLE implicit-def $r16, implicit-def dead $p0, implicit-def $pc, implicit killed $r16, implicit $r0 { - renamable $r16 = nsw A2_addi killed renamable $r16, -128 - renamable $p0 = C2_cmpeqi renamable $r0, 0 - J2_jumpfnew internal $p0, %bb.13, implicit-def $pc - } - - bb.9.while.cond: - successors: %bb.8(0x7c000000), %bb.10(0x04000000) - liveins: $r16, $r18, $r16 - - BUNDLE implicit-def dead $p0, implicit-def $pc, implicit $r16 { - renamable $p0 = C2_cmpgti renamable $r16, 127 - J2_jumptnewpt internal renamable $p0, %bb.8, implicit-def $pc - } - - bb.10: - successors: %bb.13(0x80000000) - - BUNDLE implicit-def $r0, implicit-def $pc { - renamable $r0 = A2_tfrsi 0 - J2_jump %bb.13, implicit-def $pc - } - - bb.11: - successors: %bb.13(0x80000000) - - renamable $r0 = A2_tfrsi 0 - - bb.13.cleanup: - liveins: $r0 - - BUNDLE implicit-def $d8, implicit-def $r16, implicit-def $r17, implicit-def $d9, implicit-def $r18, implicit-def $r19, implicit killed $r29 { - $d8 = L2_loadrd_io $r29, 8 :: (load 8 from %fixed-stack.0) - $d9 = L2_loadrd_io killed $r29, 0 :: (load 8 from %fixed-stack.1) - } - $d15 = L4_return killed $r30, implicit-def $pc, implicit-def $r29, implicit killed $framekey, implicit-def $pc, implicit killed $r0, implicit killed $d8, implicit killed $d9 - -... diff --git a/llvm/test/CodeGen/Hexagon/pull-no-comp-code.ll b/llvm/test/CodeGen/Hexagon/pull-no-comp-code.ll deleted file mode 100644 index e5ffaec953e2d..0000000000000 --- a/llvm/test/CodeGen/Hexagon/pull-no-comp-code.ll +++ /dev/null @@ -1,91 +0,0 @@ -; RUN: llc -march=hexagon -O3 < %s -; This test checks that compensation code should not be inserted into the -; same packet where MI is to be pulled which prevents the pull-up of MI. -; REQUIRES: asserts -; ModuleID = 'bugpoint-reduced-simplified.bc' - -%class.ggJitterSample2.5.77.107.149.155.167.179.215.251.269.275.281.287.293.317.329.347.425.437.687 = type { %class.ggSample2.4.76.106.148.154.166.178.214.250.268.274.280.286.292.316.328.346.424.436.686, i32, i32, double, double } -%class.ggSample2.4.76.106.148.154.166.178.214.250.268.274.280.286.292.316.328.346.424.436.686 = type { ptr, %class.ggTrain.3.75.105.147.153.165.177.213.249.267.273.279.285.291.315.327.345.423.435.685 } -%class.ggTrain.3.75.105.147.153.165.177.213.249.267.273.279.285.291.315.327.345.423.435.685 = type { ptr, i32, i32 } -%class.ggPoint2.2.74.104.146.152.164.176.212.248.266.272.278.284.290.314.326.344.422.434.684 = type { [2 x double] } - -define void @_ZN15ggJitterSample28GenerateEv(ptr nocapture %this, i1 %cond0, i1 %cond1, i1 %cond2, i1 %cond3) unnamed_addr #0 align 2 { -entry: - %nData.i = getelementptr inbounds %class.ggJitterSample2.5.77.107.149.155.167.179.215.251.269.275.281.287.293.317.329.347.425.437.687, ptr %this, i32 0, i32 0, i32 1, i32 1 - %memset.buf = alloca i8, i32 128, align 8 - %nan.sink = alloca %class.ggPoint2.2.74.104.146.152.164.176.212.248.266.272.278.284.290.314.326.344.422.434.684, align 8 - br i1 %cond0, label %for.cond2.preheader.lr.ph, label %return - -for.cond2.preheader.lr.ph: ; preds = %entry - %data.i = getelementptr inbounds %class.ggJitterSample2.5.77.107.149.155.167.179.215.251.269.275.281.287.293.317.329.347.425.437.687, ptr %this, i32 0, i32 0, i32 1, i32 0 - br label %for.body4 - -for.body4: ; preds = %_ZN7ggTrainI8ggPoint2E6AppendES0_.exit, %for.cond2.preheader.lr.ph - %call.i19 = tail call i32 @_Z7my_randv() - %call.i21 = tail call i32 @_Z7my_randv() - br i1 %cond1, label %if.then.i, label %_ZN7ggTrainI8ggPoint2E6AppendES0_.exit - -if.then.i: ; preds = %for.body4 - %0 = load ptr, ptr %data.i, align 4 - br i1 %cond2, label %for.end.i, label %arrayctor.loop.i - -arrayctor.loop.i: ; preds = %arrayctor.loop.i, %if.then.i - call void @llvm.memset.p0.i64(ptr align 8 %memset.buf, i8 0, i64 128, i1 false) - br i1 %cond3, label %arrayctor.loop.i, label %arrayctor.cont.loopexit.ur-lcssa.i - -arrayctor.cont.loopexit.ur-lcssa.i: ; preds = %arrayctor.loop.i - %.pre.i = load i32, ptr %nData.i, align 4 - %cmp7.i27 = icmp sgt i32 %.pre.i, 1 - br i1 %cmp7.i27, label %for.body.for.body_crit_edge.i, label %for.end.i - -for.body.for.body_crit_edge.i: ; preds = %for.body.for.body_crit_edge.i.for.body.for.body_crit_edge.i_crit_edge, %arrayctor.cont.loopexit.ur-lcssa.i - %.pre24.i = phi ptr [ %.pre24.i.pre, %for.body.for.body_crit_edge.i.for.body.for.body_crit_edge.i_crit_edge ], [ null, %arrayctor.cont.loopexit.ur-lcssa.i ] - %inc.i29 = phi i32 [ %inc.i, %for.body.for.body_crit_edge.i.for.body.for.body_crit_edge.i_crit_edge ], [ 1, %arrayctor.cont.loopexit.ur-lcssa.i ] - %arrayidx9.phi.i28 = phi ptr [ %arrayidx9.inc.i, %for.body.for.body_crit_edge.i.for.body.for.body_crit_edge.i_crit_edge ], [ %0, %arrayctor.cont.loopexit.ur-lcssa.i ] - %arrayidx9.inc.i = getelementptr %class.ggPoint2.2.74.104.146.152.164.176.212.248.266.272.278.284.290.314.326.344.422.434.684, ptr %arrayidx9.phi.i28, i32 1 - %arrayidx.i = getelementptr inbounds %class.ggPoint2.2.74.104.146.152.164.176.212.248.266.272.278.284.290.314.326.344.422.434.684, ptr %.pre24.i, i32 %inc.i29 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %arrayidx.i, ptr align 8 %arrayidx9.inc.i, i32 16, i1 false) - %inc.i = add nsw i32 %inc.i29, 1 - %1 = load i32, ptr %nData.i, align 4 - %cmp7.i = icmp slt i32 %inc.i, %1 - br i1 %cmp7.i, label %for.body.for.body_crit_edge.i.for.body.for.body_crit_edge.i_crit_edge, label %for.end.i - -for.body.for.body_crit_edge.i.for.body.for.body_crit_edge.i_crit_edge: ; preds = %for.body.for.body_crit_edge.i - %.pre24.i.pre = load ptr, ptr %data.i, align 4 - br label %for.body.for.body_crit_edge.i - -for.end.i: ; preds = %for.body.for.body_crit_edge.i, %arrayctor.cont.loopexit.ur-lcssa.i, %if.then.i - %isnull.i = icmp eq ptr %0, null - br i1 %isnull.i, label %_ZN7ggTrainI8ggPoint2E6AppendES0_.exit, label %delete.notnull.i - -delete.notnull.i: ; preds = %for.end.i - tail call void @_ZdaPv() #4 - unreachable - -_ZN7ggTrainI8ggPoint2E6AppendES0_.exit: ; preds = %for.end.i, %for.body4 - %nan.sink.0 = getelementptr inbounds %class.ggPoint2.2.74.104.146.152.164.176.212.248.266.272.278.284.290.314.326.344.422.434.684, ptr %nan.sink, i32 0, i32 0, i32 0 - %nan.sink.1 = getelementptr inbounds %class.ggPoint2.2.74.104.146.152.164.176.212.248.266.272.278.284.290.314.326.344.422.434.684, ptr %nan.sink, i32 0, i32 0, i32 1 - store double 0x7FF8000000000000, ptr %nan.sink.0, align 8 - store double 0x7FF8000000000000, ptr %nan.sink.1, align 8 - br label %for.body4 - -return: ; preds = %entry - ret void -} - -; Function Attrs: nobuiltin nounwind -declare void @_ZdaPv() #1 - -declare i32 @_Z7my_randv() #0 - -; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite) -declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) #2 - -; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write) -declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #3 - -attributes #0 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nobuiltin nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } -attributes #3 = { nocallback nofree nounwind willreturn memory(argmem: write) } -attributes #4 = { builtin nounwind } diff --git a/llvm/test/CodeGen/Hexagon/pull-up-dbg-label.mir b/llvm/test/CodeGen/Hexagon/pull-up-dbg-label.mir deleted file mode 100644 index 1186f27cbed0b..0000000000000 --- a/llvm/test/CodeGen/Hexagon/pull-up-dbg-label.mir +++ /dev/null @@ -1,144 +0,0 @@ -# RUN: llc -march=hexagon -run-pass global-sched -o - %s | FileCheck %s - -# CHECK: bb.7.b6: - ---- | - target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048" - target triple = "hexagon" - - ; Function Attrs: nounwind readnone speculatable - declare void @llvm.dbg.label(metadata) #0 - - define hidden fastcc i32* @f0(i32 %a0, i32* %a1, i32* %a2, i32* %a3) unnamed_addr #1 { - b0: - br i1 undef, label %b6, label %b1 - - b1: ; preds = %b4, %b0 - %v0 = phi i32* [ null, %b4 ], [ %a2, %b0 ] - %v1 = tail call i32* @f1(i32* undef, i64 undef, i32 undef, i32 8) #2 - %v2 = icmp eq i32* %v1, null - br i1 %v2, label %b5, label %b2 - - b2: ; preds = %b1 - %v3 = icmp ult i32* %v0, %a2 - br i1 %v3, label %b4, label %b3 - - b3: ; preds = %b2 - tail call void @f2(i32* nonnull %v1) #2 - br label %b6 - - b4: ; preds = %b2 - %v4 = load i32, i32* undef, align 4 - %v5 = icmp eq i32 %v4, 0 - br i1 %v5, label %b6, label %b1 - - b5: ; preds = %b1 - call void @llvm.dbg.label(metadata !8), !dbg !9 - store i32 -5, i32* %a3, align 4 - br label %b6 - - b6: ; preds = %b5, %b4, %b3, %b0 - ret i32* undef - } - - declare dso_local i32* @f1(i32*, i64, i32, i32) local_unnamed_addr #1 - - declare dso_local void @f2(i32*) local_unnamed_addr #1 - - attributes #0 = { nounwind readnone speculatable } - attributes #1 = { "use-soft-float"="false" } - attributes #2 = { nounwind } - - !llvm.dbg.cu = !{!0} - !llvm.module.flags = !{!3, !4} - - !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, debugInfoForProfiling: true) - !1 = !DIFile(filename: "file.c", directory: "/test") - !2 = !{} - !3 = !{i32 2, !"Debug Info Version", i32 3} - !4 = !{i32 1, !"wchar_size", i32 4} - !5 = distinct !DISubprogram(name: "f0", scope: !1, file: !1, line: 230, type: !6, isLocal: false, isDefinition: true, scopeLine: 235, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !{}) - !6 = !DISubroutineType(types: !7) - !7 = !{} - !8 = !DILabel(scope: !5, name: "failure", file: !1, line: 264) - !9 = !DILocation(line: 264, column: 1, scope: !5) -... - ---- -name: f0 -tracksRegLiveness: true -fixedStack: - - { id: 0, size: 8, alignment: 8, offset: -16 } - - { id: 1, size: 8, alignment: 8, offset: -8 } -body: | - bb.0.b0: - successors: %bb.7(0x40000000), %bb.1(0x40000000); %bb.7(50.00%), %bb.1(50.00%) - liveins: $r2:0x00000001, $r3:0x00000001, $d8, $d9, $d8, $d9, $p0, $r0, $r4, $r16, $r17, $r18, $r19 - frame-setup BUNDLE implicit-def $r29, implicit-def $r30, implicit killed $r29, implicit killed $framekey, implicit killed $framelimit, implicit $r30, implicit killed $r31, implicit $d8 { - $r29 = frame-setup S2_allocframe killed $r29, 16, implicit-def $r30, implicit killed $framekey, implicit killed $framelimit, implicit $r30, implicit killed $r31 :: (store 4 into stack) - S2_storerd_io internal $r29, -16, $d8 :: (store 8 into %fixed-stack.1) - } - BUNDLE implicit-def $pc, implicit killed $r29, implicit killed $d9, implicit undef $p0 { - S2_storerd_io killed $r29, 0, killed $d9 :: (store 8 into %fixed-stack.0) - J2_jumpt undef renamable $p0, %bb.7, implicit-def $pc - } - - bb.1: - successors: %bb.2(0x80000000); %bb.2(100.00%) - liveins: $r0, $r2, $r3, $r4, $r16, $r17 - BUNDLE implicit-def $d8, implicit-def $r16, implicit-def $r17, implicit-def $r18, implicit $r2, implicit $r3 { - $d8 = A2_combinew $r2, $r3 - $r18 = A2_tfr $r2 - } - - bb.2.b1 (align 4): - successors: %bb.5(0x04000000), %bb.3(0x7c000000); %bb.5(3.12%), %bb.3(96.88%) - liveins: $r0, $r2, $r3, $r4, $r16, $r17, $r18 - BUNDLE implicit-def $r5, implicit-def $pc, implicit-def $r31, implicit-def $r29, implicit-def $r0, implicit $r29, implicit undef $r0, implicit undef $d1, implicit undef $r4 { - $r5 = A2_tfrsi 8 - J2_call @f1, hexagoncsr, implicit-def $pc, implicit-def $r31, implicit $r29, implicit undef $r0, implicit undef $d1, implicit undef $r4, implicit internal $r5, implicit-def $r29, implicit-def $r0 - } - BUNDLE implicit-def dead $p0, implicit-def dead $pc, implicit $r0 { - renamable $p0 = C2_cmpeqi renamable $r0, 0 - J2_jumptnew internal renamable $p0, %bb.5, implicit-def dead $pc - } - - bb.3.b2: - successors: %bb.4(0x7c000000), %bb.6(0x04000000); %bb.4(96.88%), %bb.6(3.12%) - liveins: $r0, $r2, $r17, $r18, $r3, $r4, $r16 - BUNDLE implicit-def dead $p0, implicit-def $pc, implicit $r17, implicit killed $r18 { - renamable $p0 = C2_cmpgtu renamable $r17, killed renamable $r18 - J2_jumpfnew internal $p0, %bb.6, implicit-def $pc - } - - bb.4.b4: - successors: %bb.7(0x04000000), %bb.2(0x7c000000); %bb.7(3.12%), %bb.2(96.88%) - liveins: $r2, $r0, $r3, $r4, $r16, $r17 - BUNDLE implicit-def $r18, implicit-def $r2, implicit-def $pc, implicit killed undef $r2 { - renamable $r18 = A2_tfrsi 0 - renamable $r2 = L2_loadri_io killed undef renamable $r2, 0 :: (load 4 from `i32* undef`) - J4_cmpeqi_f_jumpnv_t internal $r2, 0, %bb.2, implicit-def $pc - } - J2_jump %bb.7, implicit-def $pc - - bb.5.b5: - successors: %bb.7(0x80000000); %bb.7(100.00%) - liveins: $r16 - DBG_LABEL !8 - BUNDLE implicit-def $pc, implicit killed $r16 { - S4_storeiri_io killed renamable $r16, 0, -5 :: (store 4 into %ir.a3) - J2_jump %bb.7, implicit-def $pc - } - - bb.6.b3: - successors: %bb.7(0x80000000); %bb.7(100.00%) - liveins: $r0 - J2_call @f2, hexagoncsr, implicit-def $pc, implicit-def $r31, implicit $r29, implicit $r0, implicit-def $r29 - - bb.7.b6: - BUNDLE implicit-def $d8, implicit-def $r16, implicit-def $r17, implicit-def $d9, implicit-def $r18, implicit-def $r19, implicit killed $r29 { - $d8 = L2_loadrd_io $r29, 8 :: (load 8 from %fixed-stack.1) - $d9 = L2_loadrd_io killed $r29, 0 :: (load 8 from %fixed-stack.0) - } - $d15 = L4_return killed $r30, implicit-def $pc, implicit-def $r29, implicit killed $framekey, implicit-def $pc, implicit killed $d8, implicit killed $d9 -... diff --git a/llvm/test/CodeGen/Hexagon/pull-up-slots.mir b/llvm/test/CodeGen/Hexagon/pull-up-slots.mir deleted file mode 100644 index c912538cf422c..0000000000000 --- a/llvm/test/CodeGen/Hexagon/pull-up-slots.mir +++ /dev/null @@ -1,363 +0,0 @@ -# RUN: llc -march=hexagon -mcpu=hexagonv71t -run-pass=global-sched %s -o - | FileCheck %s - -# Test that the global scheduler doesn't create a bundle with 4 instructions. - -# CHECK: bb.15.if.else166: -# CHECK: BUNDLE -# CHECK-NEXT: C2_cmpeq -# CHECK-NEXT: C2_cmovenewit -# CHECK-NEXT: J2_jumptnew - ---- | - - %struct.netbox = type { %struct.netbox*, i32, i32, i32, i32, i32, i32, i16, i16, i16, i8, i8, i8, i8 } - %struct.termbox = type { %struct.termbox*, %struct.netbox*, i32, i32, i16, [2 x i16], [2 x i16], i16 } - - @numRows = external local_unnamed_addr global i32, align 4 - - define i32 @test(i32 %flag) local_unnamed_addr #0 { - prepglob.exit: - br i1 undef, label %if.end, label %for.body - - for.body: - unreachable - - if.end: - br i1 undef, label %for.end1106, label %for.cond16.preheader - - for.cond16.preheader: - br i1 undef, label %for.end1106, label %for.body18.preheader - - for.body18.preheader: - br label %for.body18 - - for.body18: - br i1 undef, label %for.body18, label %if.end23 - - if.end23: - br i1 undef, label %for.body18, label %for.cond29.preheader - - for.cond29.preheader: - %0 = load i32, i32* @numRows, align 4 - %cmp311663 = icmp slt i32 %0, -1 - br i1 %cmp311663, label %for.body46, label %for.body33.lr.ph - - for.body33.lr.ph: - unreachable - - for.body46: - switch i32 %flag, label %if.end215.loopexit [ - i32 0, label %if.then59 - i32 1, label %land.lhs.true54 - ] - - land.lhs.true54: - unreachable - - if.then59: - %1 = zext i16 undef to i32 - switch i32 %1, label %if.else122 [ - i32 1, label %for.inc252 - i32 9, label %for.inc252 - i32 5, label %for.inc252 - i32 7, label %for.inc252 - i32 3, label %for.inc252 - i32 10, label %for.inc252 - i32 6, label %for.inc252 - i32 8, label %for.inc252 - ] - - if.else122: - br i1 undef, label %if.end215, label %if.else166 - - if.else166: - %2 = load %struct.netbox*, %struct.netbox** undef, align 8 - %cmp169 = icmp eq %struct.netbox* undef, %2 - br i1 %cmp169, label %if.then171, label %for.cond185.preheader - - for.cond185.preheader: - br label %for.cond185 - - if.then171: - store %struct.netbox* undef, %struct.netbox** undef, align 8 - %call.i1547 = tail call i32 bitcast (i32 (...)* @safe_free to i32 (%struct.termbox*)*)(%struct.termbox* null) - unreachable - - for.cond185: - %saveptr.0 = phi %struct.netbox* [ %3, %for.cond185 ], [ %2, %for.cond185.preheader ] - %cgep17 = bitcast %struct.netbox* %saveptr.0 to %struct.netbox* - %cgep58 = bitcast %struct.netbox* %cgep17 to %struct.netbox** - %3 = load %struct.netbox*, %struct.netbox** %cgep58, align 4 - %cmp187 = icmp eq %struct.netbox* %3, undef - br i1 %cmp187, label %for.end193, label %for.cond185 - - for.end193: - %4 = bitcast %struct.netbox* %saveptr.0 to %struct.netbox* - %call200 = tail call i32 bitcast (i32 (...)* @safe_free to i32 (%struct.netbox*)*)(%struct.netbox* undef) - %cgep69 = bitcast %struct.netbox* %4 to %struct.netbox** - %5 = load %struct.netbox*, %struct.netbox** %cgep69, align 4 - br label %if.end215 - - if.end215.loopexit: - br label %if.end215 - - if.end215: - %netptr.3 = phi %struct.netbox* [ undef, %if.else122 ], [ undef, %if.end215.loopexit ], [ %5, %for.end193 ] - %cgep10 = bitcast %struct.netbox* %netptr.3 to %struct.netbox* - %cgep3 = getelementptr %struct.netbox, %struct.netbox* %cgep10, i32 0, i32 7 - %6 = load i16, i16* %cgep3, align 4 - %conv217 = sext i16 %6 to i32 - %call247 = tail call i32 @detfeed(i32 %flag, i32 %conv217, i32 undef) - %conv248 = trunc i32 %call247 to i16 - store i16 %conv248, i16* undef, align 2 - unreachable - - for.inc252: - switch i32 %flag, label %for.body289.if.end306_crit_edge [ - i32 0, label %if.end306 - i32 1, label %land.lhs.true300 - ] - - for.body289.if.end306_crit_edge: - unreachable - - land.lhs.true300: - unreachable - - if.end306: - %7 = zext i16 undef to i32 - switch i32 %7, label %for.body18 [ - i32 1, label %if.end371 - i32 9, label %if.end371 - i32 5, label %if.end371 - i32 7, label %if.end371 - i32 3, label %if.end371 - i32 10, label %if.end371 - i32 6, label %if.end371 - i32 8, label %if.end371 - ] - - if.end371: - br i1 undef, label %if.end687, label %if.then394 - - if.then394: - br i1 undef, label %if.then435, label %if.end629 - - if.then435: - unreachable - - if.end629: - unreachable - - if.end687: - unreachable - - for.end1106: - ret i32 undef - } - - declare i32 @safe_free(...) local_unnamed_addr #0 - declare i32 @detfeed(i32, i32, i32) local_unnamed_addr #0 - -... ---- -name: test -alignment: 4 -tracksRegLiveness: true -liveins: - - { reg: '$r0' } -fixedStack: - - { id: 0, type: spill-slot, offset: -8, size: 8, alignment: 8, callee-saved-register: '$d8' } -body: | - bb.0.prepglob.exit: - successors: %bb.1.if.end(0x7ffff800), %bb.28.for.body(0x00000800) - liveins: $r0:0x00000001, $d8, $d8, $p0, $p1, $p2, $r16, $r17, $r2, $r3 - - $r29 = S2_allocframe killed $r29, 8, implicit-def $r30, implicit killed $framekey, implicit killed $framelimit, implicit $r30, implicit killed $r31 :: (store 4) - BUNDLE implicit-def $r16, implicit-def $pc, implicit killed $r29, implicit killed $d8, implicit $r0, implicit killed undef $p0 { - S2_storerd_io killed $r29, 0, killed $d8 :: (store 8 into %fixed-stack.0) - $r16 = A2_tfr $r0 - J2_jumpf killed undef $p0, %bb.28.for.body, implicit-def $pc - } - - bb.1.if.end: - successors: %bb.3.for.end1106(0x40000000), %bb.2.for.cond16.preheader(0x40000000) - liveins: $p1, $p2, $r0, $r16, $r2, $r3 - - J2_jumpt undef $p1, %bb.3.for.end1106, implicit-def dead $pc - - bb.2.for.cond16.preheader: - successors: %bb.3.for.end1106(0x40000000), %bb.4.for.body18.preheader(0x40000000) - liveins: $p2, $r0, $r16, $r2, $r3 - - BUNDLE implicit-def $r3, implicit-def $r2, implicit-def $pc, implicit killed undef $p2 { - $r3 = C2_cmoveif undef $p2, 2026 - $r2 = C2_cmoveif undef $p2, 0 - J2_jumpf killed undef $p2, %bb.4.for.body18.preheader, implicit-def $pc - } - - bb.3.for.end1106 (align 4): - $d8 = L2_loadrd_io killed $r29, 0 :: (load 8 from %fixed-stack.0) - $d15 = L4_return killed $r30, implicit-def $pc, implicit-def $r29, implicit killed $framekey, implicit-def $pc, implicit killed $d8 - - bb.4.for.body18.preheader (align 4): - successors: %bb.5.for.body18(0x80000000) - liveins: $r0, $r2, $r3, $r16, $r3 - - BUNDLE implicit-def $p2, implicit-def $p0, implicit killed $r3, implicit killed $r2, implicit $r16 { - $p1 = C2_cmpeqi $r16, 0 - $p2 = S2_tstbit_r killed $r3, $r2 - $p0 = C2_cmpeqi $r16, 1 - } - - bb.5.for.body18 (align 4): - successors: %bb.5.for.body18(0x40000000), %bb.6.if.end23(0x40000000) - liveins: $p0, $p1, $p2, $r0, $r16, $r2 - - J2_jumpt undef $p0, %bb.5.for.body18, implicit-def dead $pc - - bb.6.if.end23: - successors: %bb.5.for.body18(0x40000000), %bb.7.for.cond29.preheader(0x40000000) - liveins: $p0, $p1, $p2, $r0, $r16, $r2 - - BUNDLE implicit-def $r2, implicit-def dead $pc, implicit undef $p1, implicit killed $gp { - $r2 = L4_ploadrif_abs undef $p1, @numRows, implicit killed $gp :: (dereferenceable load 4 from @numRows) - J2_jumpt undef $p1, %bb.5.for.body18, implicit-def dead $pc - } - - bb.7.for.cond29.preheader: - successors: %bb.8.for.body46(0x7ffff800), %bb.21.for.body33.lr.ph(0x00000800) - liveins: $p0, $p1, $p2, $r0, $r2, $r16, $r2 - - BUNDLE implicit-def dead $p3, implicit-def $pc, implicit $r2 { - $p3 = C2_cmpgti $r2, -2 - J2_jumptnew internal killed $p3, %bb.21.for.body33.lr.ph, implicit-def $pc - } - - bb.8.for.body46: - successors: %bb.9.if.then59(0x7ffff800), %bb.22.for.body46(0x00000800) - liveins: $p0, $p1, $p2, $r0, $r2, $r16 - - J2_jumpf $p1, %bb.22.for.body46, implicit-def $pc - - bb.9.if.then59: - successors: %bb.10.for.inc252(0x7df7df7e), %bb.14.if.else122(0x02082082) - liveins: $p0, $p1, $p2, $r0, $r2, $r16 - - J2_jumpf $p2, %bb.14.if.else122, implicit-def $pc - - bb.10.for.inc252: - successors: %bb.26.land.lhs.true300(0x00000400), %bb.11.if.end306(0x7ffffc00) - liveins: $p0, $p2, $p1, $r0, $r16, $r2 - - J2_jumpt $p0, %bb.26.land.lhs.true300, implicit-def $pc - - bb.11.if.end306: - successors: %bb.12.if.end371(0x00001000), %bb.5.for.body18(0x7ffff000) - liveins: $p0, $p2, $p1, $r0, $r16, $r2 - - J2_jumpf $p2, %bb.5.for.body18, implicit-def $pc - - bb.12.if.end371: - successors: %bb.13.if.end687(0x40000000), %bb.24.if.then394(0x40000000) - liveins: $p0, $p2 - - J2_jumpf undef $p2, %bb.24.if.then394, implicit-def $pc - - bb.13.if.end687: - - bb.14.if.else122 (align 4): - successors: %bb.29(0x00000800), %bb.15.if.else166(0x7ffff800) - liveins: $p1, $r0, $r2, $r16 - - BUNDLE implicit-def $r2, implicit-def $pc, implicit undef $p1, implicit undef $r2 { - $r2 = L2_ploadrif_io undef $p1, undef $r2, 0 :: (load 4 from `%struct.netbox** undef`, align 8) - J2_jumpt undef $p1, %bb.29, implicit-def $pc - } - - bb.15.if.else166: - successors: %bb.30.if.then171(0x00000800), %bb.16.for.cond185(0x7ffff800) - liveins: $r0, $r2, $r16, $r2 - - BUNDLE implicit-def dead $p2, implicit-def $pc, implicit undef $r2 { - $p2 = C2_cmpeq undef $r2, $r2 - J2_jumptnew internal $p2, %bb.30.if.then171, implicit-def $pc - } - - bb.16.for.cond185 (align 4): - successors: %bb.17.for.end193(0x00000800), %bb.16.for.cond185(0x7ffff800) - liveins: $r0, $r2, $r16 - - $r17 = A2_tfr killed $r2 - $r2 = L2_loadri_io $r17, 0 :: (load 4 from %ir.cgep58) - BUNDLE implicit-def dead $p0, implicit-def dead $pc, implicit $r2 { - $p0 = C4_cmpneq $r2, undef $r2 - J2_jumptnewpt internal killed $p0, %bb.16.for.cond185, implicit-def dead $pc - } - - bb.17.for.end193: - successors: %bb.18.for.end193(0x80000000) - liveins: $r0, $r16, $r17 - - J2_call @safe_free, hexagoncsr, implicit-def $pc, implicit-def $r31, implicit $r29, implicit undef $r0, implicit-def $r29, implicit-def $r0 - - bb.18.for.end193 (align 4): - successors: %bb.19.if.end215(0x80000000) - liveins: $r16, $r17 - - $r2 = L2_loadri_io killed $r17, 0 :: (load 4 from %ir.cgep69) - - bb.19.if.end215 (align 4): - successors: %bb.20.if.end215(0x80000000) - liveins: $r2, $r16 - - BUNDLE implicit-def $r1, implicit-def $r0, implicit-def $pc, implicit-def $r31, implicit-def $r29, implicit $r2, implicit killed $r16, implicit $r29 { - $r1 = L2_loadrh_io $r2, 28 :: (load 2 from %ir.cgep3, align 4) - $r0 = A2_tfr killed $r16 - J2_call @detfeed, hexagoncsr, implicit-def $pc, implicit-def $r31, implicit $r29, implicit internal $r0, implicit internal $r1, implicit undef $r2, implicit-def $r29, implicit-def $r0 - } - - bb.20.if.end215 (align 4): - liveins: $r0, $r2 - - S2_storerh_io killed undef $r2, 0, killed $r0 :: (store 2 into `i16* undef`) - - bb.21.for.body33.lr.ph (align 4): - - bb.22.for.body46 (align 4): - successors: %bb.19.if.end215(0x40000000), %bb.23.land.lhs.true54(0x40000000) - liveins: $p0, $r16 - - $r2 = IMPLICIT_DEF - J2_jumpf killed $p0, %bb.19.if.end215, implicit-def $pc - - bb.23.land.lhs.true54: - - bb.24.if.then394 (align 4): - successors: %bb.25.if.then435(0x40000000), %bb.27.if.end629(0x40000000) - liveins: $p0 - - J2_jumpt killed undef $p0, %bb.27.if.end629, implicit-def dead $pc - - bb.25.if.then435: - - bb.26.land.lhs.true300 (align 4): - - bb.27.if.end629 (align 4): - - bb.28.for.body (align 4): - - bb.29 (align 4): - successors: %bb.19.if.end215(0x80000000) - liveins: $r16 - - $r2 = IMPLICIT_DEF - J2_jump %bb.19.if.end215, implicit-def $pc - - bb.30.if.then171 (align 4): - BUNDLE implicit-def $r0, implicit-def $r29 { - $r0 = A2_tfrsi 0 - PS_call_nr @safe_free, hexagoncsr, implicit internal $r0, implicit-def $r29, implicit-def $r0 - } - -... diff --git a/llvm/test/CodeGen/Hexagon/pull-up.ll b/llvm/test/CodeGen/Hexagon/pull-up.ll deleted file mode 100644 index a7ff5022a2fa1..0000000000000 --- a/llvm/test/CodeGen/Hexagon/pull-up.ll +++ /dev/null @@ -1,39 +0,0 @@ -; RUN: llc -march=hexagon -mcpu=hexagonv73 -debug < %s -; This test used to ICE with "[MIisDualJumpCandidate] To BB(0) From BB(1)". - -;REQUIRES: asserts - -target datalayout = "e-m:e-p:32:32-i1:32-i64:64-a:0-v32:32-n16:32" -target triple = "hexagon-unknown--elf" - -define void @main(i1 %cond) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { -entry: - br label %for.body.ur.i.i - -for.body.ur.i.i: ; preds = %for.body.ur.i.i, %entry - br i1 %cond, label %for.inc26.6, label %for.body.ur.i.i - -invoke.cont: ; preds = %for.inc26.6 - %call.i.i.i.i174 = invoke noalias i8* @_Znwj() - to label %_ZNSt6vectorIlSaIlEE12_Construct_nEjRKl.exit unwind label %lpad - -lpad: ; preds = %for.inc26.6, %invoke.cont - %0 = landingpad { i8*, i32 } - cleanup - resume { i8*, i32 } %0 - -_ZNSt6vectorIlSaIlEE12_Construct_nEjRKl.exit: ; preds = %invoke.cont - %incdec.ptr.i.ur.i.1 = getelementptr inbounds i8, i8* %call.i.i.i.i174, i32 36 - call void @llvm.memset.p0i8.i64(i8* %call.i.i.i.i174, i8 0, i64 36, i32 4, i1 false) - call void @llvm.memset.p0i8.i64(i8* %incdec.ptr.i.ur.i.1, i8 0, i64 32, i32 4, i1 false) - unreachable - -for.inc26.6: ; preds = %for.body.ur.i.i - invoke void @_ZNSt6vectorIlSaIlEE7_InsertIPlEEvSt16_Vector_iteratorIlS0_ET_S6_St20forward_iterator_tag() - to label %invoke.cont unwind label %lpad -} - -declare i32 @__gxx_personality_v0(...) -declare noalias i8* @_Znwj() -declare void @_ZNSt6vectorIlSaIlEE7_InsertIPlEEvSt16_Vector_iteratorIlS0_ET_S6_St20forward_iterator_tag() align 2 -declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1)