[llvm] [CodeGen] Add target-independent conditional-compare formation pass (PR #219359)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 27 21:23:21 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: Feng Zou (fzou1)
<details>
<summary>Changes</summary>
Unify the X86ConditionalCompares and AArch64ConditionalCompares passes into a single target-independent MachineConditionalCompares pass in lib/CodeGen, modeled on EarlyIfConversion. The pass folds a CFG triangle of chained short-circuit conditions into a conditional-compare chain (CCMP/CTEST on X86; CCMP/CCMN/FCCMP on AArch64), eliminating a branch.
All target-specific behavior is delegated through new hooks:
- TargetInstrInfo::getConditionalCompareFlagReg / canConvertToCCMP / convertToCCMP / getCCMPCodeSizeDelta
- TargetSubtargetInfo::enableCCMPFormation and a CCmpConvHeuristics tuning struct (a code-size-delta path when minimizing size).
The engine (SSACCmpConv) is heuristics-free and stores condition codes opaquely, round-tripping them through the target hooks. The driver carries the shared MachineTraceMetrics cost model: a 3/4-misprediction- penalty branch-delay budget plus a resource-depth check, applied identically on both targets. The only per-target difference is the CCmpConvHeuristics tuning struct: AArch64 enables the MinSize code-size-delta path (getCCMPCodeSizeDelta), while X86 leaves it off. This reproduces each target's historical cost model.
Both targets are migrated onto the new pass (legacy and new-PM, registered as "machine-ccmp") and their private passes removed. X86 gains new-PM support for the first time; AArch64 keeps its dual registration via the generic pass.
Assisted-by: Claude Opus 4.8 (1M context) <noreply@<!-- -->anthropic.com>
---
Patch is 108.92 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/219359.diff
34 Files Affected:
- (added) llvm/include/llvm/CodeGen/MachineConditionalCompares.h (+25)
- (modified) llvm/include/llvm/CodeGen/Passes.h (+4)
- (modified) llvm/include/llvm/CodeGen/TargetInstrInfo.h (+72)
- (modified) llvm/include/llvm/CodeGen/TargetSubtargetInfo.h (+15)
- (modified) llvm/include/llvm/InitializePasses.h (+1)
- (modified) llvm/include/llvm/Passes/MachinePassRegistry.def (+1)
- (modified) llvm/lib/CodeGen/CMakeLists.txt (+1)
- (modified) llvm/lib/CodeGen/CodeGen.cpp (+1)
- (renamed) llvm/lib/CodeGen/MachineConditionalCompares.cpp (+215-445)
- (modified) llvm/lib/Passes/PassBuilder.cpp (+1)
- (modified) llvm/lib/Target/AArch64/AArch64.h (-9)
- (modified) llvm/lib/Target/AArch64/AArch64InstrInfo.cpp (+316)
- (modified) llvm/lib/Target/AArch64/AArch64InstrInfo.h (+14)
- (modified) llvm/lib/Target/AArch64/AArch64PassRegistry.def (-1)
- (modified) llvm/lib/Target/AArch64/AArch64Subtarget.cpp (+14)
- (modified) llvm/lib/Target/AArch64/AArch64Subtarget.h (+4)
- (modified) llvm/lib/Target/AArch64/AArch64TargetMachine.cpp (+1-6)
- (modified) llvm/lib/Target/AArch64/CMakeLists.txt (-1)
- (modified) llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp (+2)
- (modified) llvm/lib/Target/X86/X86InstrInfo.cpp (+262)
- (modified) llvm/lib/Target/X86/X86InstrInfo.h (+12)
- (modified) llvm/lib/Target/X86/X86Subtarget.cpp (+9)
- (modified) llvm/lib/Target/X86/X86Subtarget.h (+2)
- (modified) llvm/lib/Target/X86/X86TargetMachine.cpp (+1)
- (modified) llvm/test/CodeGen/AArch64/O3-pipeline.ll (+3-1)
- (modified) llvm/test/CodeGen/AArch64/arm64-ccmp.ll (+2-2)
- (modified) llvm/test/CodeGen/AArch64/ccmp-look-through-copy.mir (+2-2)
- (modified) llvm/test/CodeGen/AArch64/ccmp-successor-probs.mir (+2-2)
- (added) llvm/test/CodeGen/X86/apx/ccmp-cost-model.mir (+164)
- (added) llvm/test/CodeGen/X86/apx/ccmp-look-through-copy.mir (+41)
- (added) llvm/test/CodeGen/X86/apx/ccmp-reject.mir (+411)
- (modified) llvm/test/CodeGen/X86/apx/ccmp.ll (+18-11)
- (modified) llvm/test/CodeGen/X86/llc-pipeline-npm.ll (+2)
- (modified) llvm/test/CodeGen/X86/opt-pipeline.ll (+3)
``````````diff
diff --git a/llvm/include/llvm/CodeGen/MachineConditionalCompares.h b/llvm/include/llvm/CodeGen/MachineConditionalCompares.h
new file mode 100644
index 0000000000000..63ddf90617710
--- /dev/null
+++ b/llvm/include/llvm/CodeGen/MachineConditionalCompares.h
@@ -0,0 +1,25 @@
+//===- llvm/CodeGen/MachineConditionalCompares.h ---------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_MACHINECONDITIONALCOMPARES_H
+#define LLVM_CODEGEN_MACHINECONDITIONALCOMPARES_H
+
+#include "llvm/CodeGen/MachinePassManager.h"
+
+namespace llvm {
+
+class MachineConditionalComparesPass
+ : public OptionalPassInfoMixin<MachineConditionalComparesPass> {
+public:
+ LLVM_ABI PreservedAnalyses run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM);
+};
+
+} // namespace llvm
+
+#endif // LLVM_CODEGEN_MACHINECONDITIONALCOMPARES_H
diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h
index 8c2b923aeb807..a912caebcd853 100644
--- a/llvm/include/llvm/CodeGen/Passes.h
+++ b/llvm/include/llvm/CodeGen/Passes.h
@@ -321,6 +321,10 @@ LLVM_ABI extern char &EarlyIfPredicatorID;
/// critical-path and resource depth.
LLVM_ABI extern char &MachineCombinerID;
+/// MachineConditionalCompares - This pass performs target-independent
+/// conditional-compare formation on SSA form, reducing branching.
+LLVM_ABI extern char &MachineConditionalComparesLegacyID;
+
/// StackSlotColoring - This pass performs stack coloring and merging.
/// It merges disjoint allocas to reduce the stack size.
LLVM_ABI extern char &StackColoringLegacyID;
diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index 4749d06501cb2..635564acd0107 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -1050,6 +1050,78 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
llvm_unreachable("Target didn't implement TargetInstrInfo::insertSelect!");
}
+ /// Carries the state that canConvertToCCMP() computes and convertToCCMP()
+ /// consumes when the target-independent conditional-compare formation pass
+ /// (see MachineConditionalCompares) folds a CFG triangle into a conditional
+ /// compare. All fields except CmpMI are target-owned scratch; the generic
+ /// pass never interprets them.
+ struct CCmpConvInfo {
+ /// The convertible compare instruction found in CmpBB.
+ MachineInstr *CmpMI = nullptr;
+ /// Opaque target scratch (parsed condition codes, chosen opcode, operand
+ /// layout, etc.). Sized to hold the needs of any target.
+ int64_t TargetData[5] = {};
+ };
+
+ /// Return the physical flag/status register clobbered by conditional-compare
+ /// candidates (EFLAGS on X86, NZCV on AArch64), or a null register if the
+ /// target does not support conditional-compare formation. Used by the generic
+ /// MachineConditionalCompares pass to scan for flag reads/defs.
+ virtual MCRegister getConditionalCompareFlagReg() const {
+ return MCRegister();
+ }
+
+ /// Analyze whether the compare controlling CmpBB's terminator can be folded
+ /// into a conditional compare merged into Head (a triangle Head->CmpBB->Tail).
+ ///
+ /// HeadCond and CmpBBCond are the opaque condition-operand arrays returned by
+ /// analyzeBranch; the generic caller never interprets them. HeadTBBIsCmpBB is
+ /// true when analyzeBranch's TBB for Head is CmpBB (else it is Tail), and
+ /// CmpBBTBBIsTail is true when analyzeBranch's TBB for CmpBB is Tail; the
+ /// target uses these to apply its own condition-code inversion.
+ ///
+ /// On success, fills Info (including Info.CmpMI) and returns true.
+ virtual bool canConvertToCCMP(MachineBasicBlock &Head,
+ MachineBasicBlock &CmpBB,
+ ArrayRef<MachineOperand> HeadCond,
+ bool HeadTBBIsCmpBB,
+ ArrayRef<MachineOperand> CmpBBCond,
+ bool CmpBBTBBIsTail,
+ const MachineRegisterInfo &MRI,
+ CCmpConvInfo &Info) const {
+ return false;
+ }
+
+ /// Emit the conditional compare that replaces Info.CmpMI, using the target
+ /// data stashed by canConvertToCCMP(). This is invoked after the generic pass
+ /// has spliced CmpBB into Head and removed Head's branch, so the target only
+ /// performs the instruction rewrite (and any Head-terminator fixup, e.g.
+ /// synthesizing a compare for a cbz/cbnz head, or re-inserting a conditional
+ /// branch when the folded compare was itself a terminator).
+ ///
+ /// SpliceLoc is the first instruction spliced from CmpBB into Head (the splice
+ /// boundary), the insertion point for any synthesized Head compare. HeadTermDL
+ /// is the debug location of the (now-removed) Head terminator. HeadCond is the
+ /// condition array captured before the branch was removed. The generic caller
+ /// erases Info.CmpMI and fixes up Head's terminator afterwards. Returns the
+ /// new conditional-compare instruction.
+ virtual MachineInstr *convertToCCMP(MachineBasicBlock &Head,
+ MachineBasicBlock::iterator SpliceLoc,
+ const DebugLoc &HeadTermDL,
+ ArrayRef<MachineOperand> HeadCond,
+ const CCmpConvInfo &Info,
+ MachineRegisterInfo &MRI) const {
+ llvm_unreachable("Target didn't implement TargetInstrInfo::convertToCCMP!");
+ }
+
+ /// Return the expected code-size delta (in number of instructions) of
+ /// converting the candidate described by Info into a conditional compare.
+ /// Used by the MinSize heuristic. Defaults to 0 (no size change assumed).
+ virtual int getCCMPCodeSizeDelta(const CCmpConvInfo &Info,
+ ArrayRef<MachineOperand> HeadCond) const {
+ return 0;
+ }
+
/// Given an instruction marked as `isSelect = true`, attempt to optimize MI
/// by merging it with one of its operands. Returns nullptr on failure.
///
diff --git a/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h b/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
index 0dc8b339e8ebb..7cf3e1c8d4568 100644
--- a/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
@@ -343,6 +343,21 @@ class LLVM_ABI TargetSubtargetInfo : public MCSubtargetInfo {
/// Enable the use of the early if conversion pass.
virtual bool enableEarlyIfConversion() const { return false; }
+ /// Per-target tuning for the conditional-compare formation pass
+ /// (MachineConditionalCompares). The defaults reproduce the historical
+ /// AArch64 cost model.
+ struct CCmpConvHeuristics {
+ /// Convert whenever it does not grow code when the function is MinSize.
+ bool UseCodeSizeDeltaOnMinSize = false;
+ };
+
+ /// Enable the target-independent conditional-compare formation pass
+ /// (MachineConditionalCompares) for this subtarget.
+ virtual bool enableCCMPFormation() const { return false; }
+
+ /// Return the tunable heuristics for conditional-compare formation.
+ virtual CCmpConvHeuristics getCCmpConvHeuristics() const { return {}; }
+
/// Return PBQPConstraint(s) for the target.
///
/// Override to provide custom PBQP constraints.
diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h
index dec7a5ff0845d..09aa8caf5aaf6 100644
--- a/llvm/include/llvm/InitializePasses.h
+++ b/llvm/include/llvm/InitializePasses.h
@@ -199,6 +199,7 @@ initializeMachineBranchProbabilityInfoWrapperPassPass(PassRegistry &);
LLVM_ABI void initializeMachineCFGPrinterLegacyPass(PassRegistry &);
LLVM_ABI void initializeMachineCSELegacyPass(PassRegistry &);
LLVM_ABI void initializeMachineCombinerLegacyPass(PassRegistry &);
+LLVM_ABI void initializeMachineConditionalComparesLegacyPass(PassRegistry &);
LLVM_ABI void initializeMachineCopyPropagationLegacyPass(PassRegistry &);
LLVM_ABI void initializeMachineCycleInfoPrinterLegacyPass(PassRegistry &);
LLVM_ABI void initializeMachineCycleInfoWrapperPassPass(PassRegistry &);
diff --git a/llvm/include/llvm/Passes/MachinePassRegistry.def b/llvm/include/llvm/Passes/MachinePassRegistry.def
index 1bdfd72c9d736..88828667c036f 100644
--- a/llvm/include/llvm/Passes/MachinePassRegistry.def
+++ b/llvm/include/llvm/Passes/MachinePassRegistry.def
@@ -92,6 +92,7 @@ MACHINE_FUNCTION_PASS("legalizer", LegalizerPass())
MACHINE_FUNCTION_PASS("load-store-opt", LoadStoreOptPass())
MACHINE_FUNCTION_PASS("localizer", LocalizerPass())
MACHINE_FUNCTION_PASS("localstackalloc", LocalStackSlotAllocationPass())
+MACHINE_FUNCTION_PASS("machine-ccmp", MachineConditionalComparesPass())
MACHINE_FUNCTION_PASS("machine-combiner", MachineCombinerPass())
MACHINE_FUNCTION_PASS("machine-cp", MachineCopyPropagationPass())
MACHINE_FUNCTION_PASS("machine-cse", MachineCSEPass())
diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt
index 99dfb4bb09df7..b39d9a1a8b71c 100644
--- a/llvm/lib/CodeGen/CMakeLists.txt
+++ b/llvm/lib/CodeGen/CMakeLists.txt
@@ -125,6 +125,7 @@ add_llvm_component_library(LLVMCodeGen
MachineBranchProbabilityInfo.cpp
MachineCFGPrinter.cpp
MachineCombiner.cpp
+ MachineConditionalCompares.cpp
MachineConvergenceVerifier.cpp
MachineCopyPropagation.cpp
MachineCSE.cpp
diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp
index 7fb2fca6b6494..a7ebd7ae6e0ed 100644
--- a/llvm/lib/CodeGen/CodeGen.cpp
+++ b/llvm/lib/CodeGen/CodeGen.cpp
@@ -89,6 +89,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
initializeMachineCFGPrinterLegacyPass(Registry);
initializeMachineCSELegacyPass(Registry);
initializeMachineCombinerLegacyPass(Registry);
+ initializeMachineConditionalComparesLegacyPass(Registry);
initializeMachineDominanceFrontierWrapperPassPass(Registry);
initializeMachineCopyPropagationLegacyPass(Registry);
initializeMachineCycleInfoPrinterLegacyPass(Registry);
diff --git a/llvm/lib/Target/AArch64/AArch64ConditionalCompares.cpp b/llvm/lib/CodeGen/MachineConditionalCompares.cpp
similarity index 55%
rename from llvm/lib/Target/AArch64/AArch64ConditionalCompares.cpp
rename to llvm/lib/CodeGen/MachineConditionalCompares.cpp
index f490b5f94fe0d..ec06a55014703 100644
--- a/llvm/lib/Target/AArch64/AArch64ConditionalCompares.cpp
+++ b/llvm/lib/CodeGen/MachineConditionalCompares.cpp
@@ -1,4 +1,4 @@
-//===-- AArch64ConditionalCompares.cpp --- CCMP formation for AArch64 -----===//
+//===-- MachineConditionalCompares.cpp --- CCMP formation -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,32 +6,41 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements the AArch64ConditionalCompares pass which reduces
-// branching and code size by using the conditional compare instructions CCMP,
-// CCMN, and FCMP.
+// This file implements the target-independent MachineConditionalCompares pass
+// which reduces branching by using the conditional-compare instructions
+// (CCMP/CTEST on X86; CCMP/CCMN/FCCMP on AArch64).
//
// The CFG transformations for forming conditional compares are very similar to
// if-conversion, and this pass should run immediately before the early
-// if-conversion pass.
+// if-conversion pass. The transform itself is target-independent; the
+// recognition of a convertible compare and the emission of the conditional
+// compare are delegated to the target via TargetInstrInfo hooks
+// (getConditionalCompareFlagReg / canConvertToCCMP / convertToCCMP /
+// getCCMPCodeSizeDelta) and the pass is gated and tuned per target via
+// TargetSubtargetInfo (enableCCMPFormation / getCCmpConvHeuristics).
//
//===----------------------------------------------------------------------===//
-#include "AArch64.h"
+#include "llvm/CodeGen/MachineConditionalCompares.h"
#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
-#include "llvm/CodeGen/MachinePassManager.h"
+#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MachineTraceMetrics.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/IR/Function.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -39,17 +48,17 @@
using namespace llvm;
-#define DEBUG_TYPE "aarch64-ccmp"
+#define DEBUG_TYPE "machine-ccmp"
// Absolute maximum number of instructions allowed per speculated block.
// This bypasses all other heuristics, so it should be set fairly high.
static cl::opt<unsigned> BlockInstrLimit(
- "aarch64-ccmp-limit", cl::init(30), cl::Hidden,
+ "machine-ccmp-limit", cl::init(30), cl::Hidden,
cl::desc("Maximum number of instructions per speculated block."));
// Stress testing mode - disable heuristics.
-static cl::opt<bool> Stress("aarch64-stress-ccmp", cl::Hidden,
- cl::desc("Turn all knobs to 11"));
+static cl::opt<bool> Stress("stress-machine-ccmp", cl::Hidden,
+ cl::desc("Turn all knobs to 11"), cl::init(false));
STATISTIC(NumConsidered, "Number of ccmps considered");
STATISTIC(NumPhiRejs, "Number of ccmps rejected (PHI)");
@@ -57,16 +66,8 @@ STATISTIC(NumPhysRejs, "Number of ccmps rejected (Physregs)");
STATISTIC(NumPhi2Rejs, "Number of ccmps rejected (PHI2)");
STATISTIC(NumHeadBranchRejs, "Number of ccmps rejected (Head branch)");
STATISTIC(NumCmpBranchRejs, "Number of ccmps rejected (CmpBB branch)");
-STATISTIC(NumCmpTermRejs, "Number of ccmps rejected (CmpBB is cbz...)");
-STATISTIC(NumImmRangeRejs, "Number of ccmps rejected (Imm out of range)");
-STATISTIC(NumLiveDstRejs, "Number of ccmps rejected (Cmp dest live)");
-STATISTIC(NumMultNZCVUses, "Number of ccmps rejected (NZCV used)");
-STATISTIC(NumUnknNZCVDefs, "Number of ccmps rejected (NZCV def unknown)");
-
STATISTIC(NumSpeculateRejs, "Number of ccmps rejected (Can't speculate)");
-
STATISTIC(NumConverted, "Number of ccmp instructions created");
-STATISTIC(NumCompBranches, "Number of cbz/cbnz branches converted");
//===----------------------------------------------------------------------===//
// SSACCmpConv
@@ -132,14 +133,17 @@ STATISTIC(NumCompBranches, "Number of cbz/cbnz branches converted");
// between Head and Tail, just like if-converting a diamond.
//
// FIXME: Handle PHIs in Tail by turning them into selects (if-conversion).
-
+//
namespace {
class SSACCmpConv {
- MachineFunction *MF;
const TargetInstrInfo *TII;
const TargetRegisterInfo *TRI;
MachineRegisterInfo *MRI;
const MachineBranchProbabilityInfo *MBPI;
+ MachineOptimizationRemarkEmitter *ORE;
+
+ /// The physical flag/status register clobbered by ccmp candidates.
+ MCRegister FlagReg;
public:
/// The first block containing a conditional branch, dominating everything
@@ -156,17 +160,16 @@ class SSACCmpConv {
MachineInstr *CmpMI;
private:
- /// The branch condition in Head as determined by analyzeBranch.
+ /// The branch condition in Head as determined by analyzeBranch. Stored
+ /// opaquely; only round-tripped through the target hooks.
SmallVector<MachineOperand, 4> HeadCond;
- /// The condition code that makes Head branch to CmpBB.
- AArch64CC::CondCode HeadCmpBBCC;
-
- /// The branch condition in CmpBB.
+ /// The branch condition in CmpBB as determined by analyzeBranch. Stored
+ /// opaquely; only round-tripped through the target hooks.
SmallVector<MachineOperand, 4> CmpBBCond;
- /// The condition code that makes CmpBB branch to Tail.
- AArch64CC::CondCode CmpBBTailCC;
+ /// Target-owned recognition/emission state produced by canConvertToCCMP().
+ TargetInstrInfo::CCmpConvInfo Info;
/// Check if the Tail PHIs are trivially convertible.
bool trivialTailPHIs();
@@ -174,42 +177,40 @@ class SSACCmpConv {
/// Remove CmpBB from the Tail PHIs.
void updateTailPHIs();
- /// Check if an operand defining DstReg is dead.
- bool isDeadDef(unsigned DstReg);
-
- /// Find the compare instruction in MBB that controls the conditional branch.
- /// Return NULL if a convertible instruction can't be found.
- MachineInstr *findConvertibleCompare(MachineBasicBlock *MBB);
-
/// Return true if all non-terminator instructions in MBB can be safely
/// speculated.
bool canSpeculateInstrs(MachineBasicBlock *MBB, const MachineInstr *CmpMI);
public:
- /// runOnMachineFunction - Initialize per-function data structures.
- void runOnMachineFunction(MachineFunction &MF,
- const MachineBranchProbabilityInfo *MBPI) {
- this->MF = &MF;
+ /// Initialize per-function data structures.
+ void init(MachineFunction &MF, const MachineBranchProbabilityInfo *MBPI,
+ MachineOptimizationRemarkEmitter *ORE) {
this->MBPI = MBPI;
+ this->ORE = ORE;
TII = MF.getSubtarget().getInstrInfo();
TRI = MF.getSubtarget().getRegisterInfo();
MRI = &MF.getRegInfo();
+ FlagReg = TII->getConditionalCompareFlagReg();
}
- /// If the sub-CFG headed by MBB can be cmp-converted, initialize the
- /// internal state, and return true.
+ /// If the sub-CFG headed by MBB can be cmp-converted, initialize the internal
+ /// state, and return true.
bool canConvert(MachineBasicBlock *MBB);
- /// Cmo-convert the last block passed to canConvertCmp(), assuming
- /// it is possible. Add any erased blocks to RemovedBlocks.
+ /// Cmp-convert the last block passed to canConvert(), assuming it is
+ /// possible. Add any erased blocks to RemovedBlocks.
void convert(SmallVectorImpl<MachineBasicBlock *> &RemovedBlocks);
- /// Return the expected code size delta if the conversion into a
- /// conditional compare is performed.
- int expectedCodeSizeDelta() const;
+ /// Return the expected code size delta if the conversion into a conditional
+ /// compare is performed.
+ int expectedCodeSizeDelta() const {
+ return TII->getCCMPCodeSizeDelta(Info, HeadCond);
+ }
};
} // end anonymous namespace
+// Detect a chain of vreg-to-vreg copies feeding Reg, returning the original
+// value. This lets trivialTailPHIs() see copy-equivalent PHI operands as equal.
static Register lookThroughCopies(Register Reg, MachineRegisterInfo *MRI) {
MachineInstr *MI;
while ((MI = MRI->getUniqueVRegDef(Reg)) &&
@@ -224,14 +225,12 @@ static Register lookThroughCopies(Register Reg, MachineRegisterInfo *MRI) {
// Check that all PHIs in Tail are selecting the same value from Head and CmpBB.
// This means that no if-conversion is required when merging CmpBB into Head.
bool SSACCmpConv::trivialTailPHIs() {
- for (auto &I : *Tail) {
- if (!I.isPHI())
- break;
+ for (auto &I : Tail->phis()) {
unsigned HeadReg = 0, CmpBBReg = 0;
// PHI operands come in (VReg, MBB) pairs.
- for (unsigned oi = 1, oe = I.getNumOperands(); oi != oe; oi += 2) {
- MachineBasicBlock *MBB = I.getOperand(oi + 1).getMBB();
- Register Reg = lookThroughCopies(I.getOperand(oi).getReg(), MRI);
+ for (unsigned Idx = 1, End = I.getNumOperands(); Idx != End; Idx += 2) {
+ MachineBasicBlock *MBB = I.getOperand(Idx + 1).getMBB();
+ Register Reg = lookThroughCopies(I.getOperand(Idx).getReg(), MRI);
if (MBB == Head) {
assert((!HeadReg || HeadReg...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/219359
More information about the llvm-commits
mailing list