From 346aecdb8b3b658f8f4c138b360b46c1de2123d0 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 25 Jun 2010 22:42:03 +0000 Subject: [PATCH] Change if-conversion block size limit checks to add some flexibility. llvm-svn: 106901 --- include/llvm/Target/TargetInstrInfo.h | 25 +++++++++++++++ include/llvm/Target/TargetLowering.h | 34 --------------------- lib/CodeGen/IfConversion.cpp | 30 ++++++++++-------- lib/CodeGen/SelectionDAG/TargetLowering.cpp | 2 -- lib/Target/ARM/ARMBaseInstrInfo.cpp | 18 +++++++++++ lib/Target/ARM/ARMBaseInstrInfo.h | 11 +++++++ lib/Target/ARM/ARMISelLowering.cpp | 17 ----------- lib/Target/ARM/Thumb2InstrInfo.cpp | 23 ++++++++++++++ lib/Target/ARM/Thumb2InstrInfo.h | 5 +++ test/CodeGen/ARM/lsr-code-insertion.ll | 2 +- 10 files changed, 101 insertions(+), 66 deletions(-) diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index e586a06ce2e..2c6080bd099 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -331,6 +331,31 @@ public: MachineBasicBlock::iterator MBBI) const { return true; } + + /// isProfitableToIfCvt - Return true if it's profitable to first "NumInstrs" + /// of the specified basic block. + virtual + bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumInstrs) const { + return false; + } + + /// isProfitableToIfCvt - Second variant of isProfitableToIfCvt, this one + /// checks for the case where two basic blocks from true and false path + /// of a if-then-else (diamond) are predicated on mutally exclusive + /// predicates. + virtual bool + isProfitableToIfCvt(MachineBasicBlock &TMBB, unsigned NumTInstrs, + MachineBasicBlock &FMBB, unsigned NumFInstrs) const { + return false; + } + + /// isProfitableToDupForIfCvt - Return true if it's profitable for + /// if-converter to duplicate a specific number of instructions in the + /// specified MBB to enable if-conversion. + virtual bool + isProfitableToDupForIfCvt(MachineBasicBlock &MBB,unsigned NumInstrs) const { + return false; + } /// copyRegToReg - Emit instructions to copy between a pair of registers. It /// returns false if the target does not how to copy between the specified diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 4aa8a4de9f9..eb048f6d9fa 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -683,19 +683,6 @@ public: return JumpBufAlignment; } - /// getIfCvtBlockLimit - returns the target specific if-conversion block size - /// limit. Any block whose size is greater should not be predicated. - unsigned getIfCvtBlockSizeLimit() const { - return IfCvtBlockSizeLimit; - } - - /// getIfCvtDupBlockLimit - returns the target specific size limit for a - /// block to be considered for duplication. Any block whose size is greater - /// should not be duplicated to facilitate its predication. - unsigned getIfCvtDupBlockSizeLimit() const { - return IfCvtDupBlockSizeLimit; - } - /// getPrefLoopAlignment - return the preferred loop alignment. /// unsigned getPrefLoopAlignment() const { @@ -1078,19 +1065,6 @@ protected: JumpBufAlignment = Align; } - /// setIfCvtBlockSizeLimit - Set the target's if-conversion block size - /// limit (in number of instructions); default is 2. - void setIfCvtBlockSizeLimit(unsigned Limit) { - IfCvtBlockSizeLimit = Limit; - } - - /// setIfCvtDupBlockSizeLimit - Set the target's block size limit (in number - /// of instructions) to be considered for code duplication during - /// if-conversion; default is 2. - void setIfCvtDupBlockSizeLimit(unsigned Limit) { - IfCvtDupBlockSizeLimit = Limit; - } - /// setPrefLoopAlignment - Set the target's preferred loop alignment. Default /// alignment is zero, it means the target does not care about loop alignment. void setPrefLoopAlignment(unsigned Align) { @@ -1538,14 +1512,6 @@ private: /// buffers unsigned JumpBufAlignment; - /// IfCvtBlockSizeLimit - The maximum allowed size for a block to be - /// if-converted. - unsigned IfCvtBlockSizeLimit; - - /// IfCvtDupBlockSizeLimit - The maximum allowed size for a block to be - /// duplicated during if-conversion. - unsigned IfCvtDupBlockSizeLimit; - /// PrefLoopAlignment - The perferred loop alignment. /// unsigned PrefLoopAlignment; diff --git a/lib/CodeGen/IfConversion.cpp b/lib/CodeGen/IfConversion.cpp index 0b40d8e0389..ea4e68dbdaf 100644 --- a/lib/CodeGen/IfConversion.cpp +++ b/lib/CodeGen/IfConversion.cpp @@ -188,8 +188,14 @@ namespace { bool IgnoreBr = false); void MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI); - bool MeetIfcvtSizeLimit(unsigned Size) const { - return Size > 0 && Size <= TLI->getIfCvtBlockSizeLimit(); + bool MeetIfcvtSizeLimit(MachineBasicBlock &BB, unsigned Size) const { + return Size > 0 && TII->isProfitableToIfCvt(BB, Size); + } + + bool MeetIfcvtSizeLimit(MachineBasicBlock &TBB, unsigned TSize, + MachineBasicBlock &FBB, unsigned FSize) const { + return TSize > 0 && FSize > 0 && + TII->isProfitableToIfCvt(TBB, TSize, FBB, FSize); } // blockAlwaysFallThrough - Block ends without a terminator. @@ -436,7 +442,7 @@ bool IfConverter::ValidSimple(BBInfo &TrueBBI, unsigned &Dups) const { if (TrueBBI.BB->pred_size() > 1) { if (TrueBBI.CannotBeCopied || - TrueBBI.NonPredSize > TLI->getIfCvtDupBlockSizeLimit()) + !TII->isProfitableToDupForIfCvt(*TrueBBI.BB, TrueBBI.NonPredSize)) return false; Dups = TrueBBI.NonPredSize; } @@ -473,7 +479,7 @@ bool IfConverter::ValidTriangle(BBInfo &TrueBBI, BBInfo &FalseBBI, ++Size; } } - if (Size > TLI->getIfCvtDupBlockSizeLimit()) + if (!TII->isProfitableToDupForIfCvt(*TrueBBI.BB, Size)) return false; Dups = Size; } @@ -761,8 +767,8 @@ IfConverter::BBInfo &IfConverter::AnalyzeBlock(MachineBasicBlock *BB, bool FNeedSub = FalseBBI.Predicate.size() > 0; bool Enqueued = false; if (CanRevCond && ValidDiamond(TrueBBI, FalseBBI, Dups, Dups2) && - MeetIfcvtSizeLimit(TrueBBI.NonPredSize - (Dups + Dups2)) && - MeetIfcvtSizeLimit(FalseBBI.NonPredSize - (Dups + Dups2)) && + MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize - (Dups + Dups2), + *FalseBBI.BB, FalseBBI.NonPredSize - (Dups + Dups2)) && FeasibilityAnalysis(TrueBBI, BBI.BrCond) && FeasibilityAnalysis(FalseBBI, RevCond)) { // Diamond: @@ -779,7 +785,7 @@ IfConverter::BBInfo &IfConverter::AnalyzeBlock(MachineBasicBlock *BB, } if (ValidTriangle(TrueBBI, FalseBBI, false, Dups) && - MeetIfcvtSizeLimit(TrueBBI.NonPredSize) && + MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize) && FeasibilityAnalysis(TrueBBI, BBI.BrCond, true)) { // Triangle: // EBB @@ -793,14 +799,14 @@ IfConverter::BBInfo &IfConverter::AnalyzeBlock(MachineBasicBlock *BB, } if (ValidTriangle(TrueBBI, FalseBBI, true, Dups) && - MeetIfcvtSizeLimit(TrueBBI.NonPredSize) && + MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize) && FeasibilityAnalysis(TrueBBI, BBI.BrCond, true, true)) { Tokens.push_back(new IfcvtToken(BBI, ICTriangleRev, TNeedSub, Dups)); Enqueued = true; } if (ValidSimple(TrueBBI, Dups) && - MeetIfcvtSizeLimit(TrueBBI.NonPredSize) && + MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize) && FeasibilityAnalysis(TrueBBI, BBI.BrCond)) { // Simple (split, no rejoin): // EBB @@ -816,21 +822,21 @@ IfConverter::BBInfo &IfConverter::AnalyzeBlock(MachineBasicBlock *BB, if (CanRevCond) { // Try the other path... if (ValidTriangle(FalseBBI, TrueBBI, false, Dups) && - MeetIfcvtSizeLimit(FalseBBI.NonPredSize) && + MeetIfcvtSizeLimit(*FalseBBI.BB, FalseBBI.NonPredSize) && FeasibilityAnalysis(FalseBBI, RevCond, true)) { Tokens.push_back(new IfcvtToken(BBI, ICTriangleFalse, FNeedSub, Dups)); Enqueued = true; } if (ValidTriangle(FalseBBI, TrueBBI, true, Dups) && - MeetIfcvtSizeLimit(FalseBBI.NonPredSize) && + MeetIfcvtSizeLimit(*FalseBBI.BB, FalseBBI.NonPredSize) && FeasibilityAnalysis(FalseBBI, RevCond, true, true)) { Tokens.push_back(new IfcvtToken(BBI, ICTriangleFRev, FNeedSub, Dups)); Enqueued = true; } if (ValidSimple(FalseBBI, Dups) && - MeetIfcvtSizeLimit(FalseBBI.NonPredSize) && + MeetIfcvtSizeLimit(*FalseBBI.BB, FalseBBI.NonPredSize) && FeasibilityAnalysis(FalseBBI, RevCond)) { Tokens.push_back(new IfcvtToken(BBI, ICSimpleFalse, FNeedSub, Dups)); Enqueued = true; diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 7ad0d386110..80191167b30 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -578,8 +578,6 @@ TargetLowering::TargetLowering(const TargetMachine &tm, SchedPreferenceInfo = Sched::Latency; JumpBufSize = 0; JumpBufAlignment = 0; - IfCvtBlockSizeLimit = 2; - IfCvtDupBlockSizeLimit = 0; PrefLoopAlignment = 0; ShouldFoldAtomicFences = false; diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 7ef7fd689a8..c0d05091be5 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -1447,6 +1447,24 @@ bool ARMBaseInstrInfo::isSchedulingBoundary(const MachineInstr *MI, return false; } +bool ARMBaseInstrInfo:: +isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumInstrs) const { + if (!NumInstrs) + return false; + if (Subtarget.getCPUString() == "generic") + // Generic (and overly aggressive) if-conversion limits for testing. + return NumInstrs <= 10; + else if (Subtarget.hasV7Ops()) + return NumInstrs <= 3; + return NumInstrs <= 2; +} + +bool ARMBaseInstrInfo:: +isProfitableToIfCvt(MachineBasicBlock &TMBB, unsigned NumT, + MachineBasicBlock &FMBB, unsigned NumF) const { + return NumT && NumF && NumT <= 2 && NumF <= 2; +} + /// getInstrPredicate - If instruction is predicated, returns its predicate /// condition, otherwise returns AL. It also returns the condition code /// register by reference. diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index d7d9f525c56..f673c99dbeb 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -343,6 +343,17 @@ public: virtual bool isSchedulingBoundary(const MachineInstr *MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const; + + virtual bool isProfitableToIfCvt(MachineBasicBlock &MBB, + unsigned NumInstrs) const; + + virtual bool isProfitableToIfCvt(MachineBasicBlock &TMBB,unsigned NumT, + MachineBasicBlock &FMBB,unsigned NumF) const; + + virtual bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, + unsigned NumInstrs) const { + return NumInstrs && NumInstrs == 1; + } }; static inline diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 07de1ddbbf0..d4332f00a7e 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -531,23 +531,6 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) else setSchedulingPreference(Sched::Hybrid); - // FIXME: If-converter should use instruction latency to determine - // profitability rather than relying on fixed limits. - if (Subtarget->getCPUString() == "generic") { - // Generic (and overly aggressive) if-conversion limits. - setIfCvtBlockSizeLimit(10); - setIfCvtDupBlockSizeLimit(2); - } else if (Subtarget->hasV7Ops()) { - setIfCvtBlockSizeLimit(3); - setIfCvtDupBlockSizeLimit(1); - } else if (Subtarget->hasV6Ops()) { - setIfCvtBlockSizeLimit(2); - setIfCvtDupBlockSizeLimit(1); - } else { - setIfCvtBlockSizeLimit(3); - setIfCvtDupBlockSizeLimit(2); - } - maxStoresPerMemcpy = 1; //// temporary - rewrite interface to use type // Do not enable CodePlacementOpt for now: it currently runs after the // ARMConstantIslandPass and messes up branch relaxation and placement diff --git a/lib/Target/ARM/Thumb2InstrInfo.cpp b/lib/Target/ARM/Thumb2InstrInfo.cpp index 42fe5092f7e..d7c86c6b942 100644 --- a/lib/Target/ARM/Thumb2InstrInfo.cpp +++ b/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -24,9 +24,18 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; +static cl::opt +IfCvtLimit("thumb2-ifcvt-limit (default 3)", + cl::Hidden, cl::init(3)); + +static cl::opt +IfCvtDiamondLimit("thumb2-ifcvt-diamond-limit (default 3)", + cl::Hidden, cl::init(3)); + Thumb2InstrInfo::Thumb2InstrInfo(const ARMSubtarget &STI) : ARMBaseInstrInfo(STI), RI(*this, STI) { } @@ -94,6 +103,20 @@ Thumb2InstrInfo::isLegalToSplitMBBAt(MachineBasicBlock &MBB, return llvm::getITInstrPredicate(MBBI, PredReg) == ARMCC::AL; } +bool Thumb2InstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB, + unsigned NumInstrs) const { + return NumInstrs && NumInstrs <= IfCvtLimit; +} + +bool Thumb2InstrInfo:: +isProfitableToIfCvt(MachineBasicBlock &TMBB, unsigned NumT, + MachineBasicBlock &FMBB, unsigned NumF) const { + // FIXME: Catch optimization such as: + // r0 = movne + // r0 = moveq + return NumT && NumF && + NumT <= (IfCvtDiamondLimit) && NumF <= (IfCvtDiamondLimit); +} bool Thumb2InstrInfo::copyRegToReg(MachineBasicBlock &MBB, diff --git a/lib/Target/ARM/Thumb2InstrInfo.h b/lib/Target/ARM/Thumb2InstrInfo.h index 8b01bcbb46d..13b801a3ef0 100644 --- a/lib/Target/ARM/Thumb2InstrInfo.h +++ b/lib/Target/ARM/Thumb2InstrInfo.h @@ -38,6 +38,11 @@ public: bool isLegalToSplitMBBAt(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const; + bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumInstrs) const; + + bool isProfitableToIfCvt(MachineBasicBlock &TMBB, unsigned NumTInstrs, + MachineBasicBlock &FMBB, unsigned NumFInstrs) const; + bool copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned DestReg, unsigned SrcReg, diff --git a/test/CodeGen/ARM/lsr-code-insertion.ll b/test/CodeGen/ARM/lsr-code-insertion.ll index 1bbb96deeef..b8c543b1bd1 100644 --- a/test/CodeGen/ARM/lsr-code-insertion.ll +++ b/test/CodeGen/ARM/lsr-code-insertion.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -stats |& grep {39.*Number of machine instrs printed} +; RUN: llc < %s -stats |& grep {38.*Number of machine instrs printed} ; RUN: llc < %s -stats |& not grep {.*Number of re-materialization} ; This test really wants to check that the resultant "cond_true" block only ; has a single store in it, and that cond_true55 only has code to materialize