[llvm] [CodeGen] [EarlyIfConversion] Prioritize conversion of hard to predict branches (PR #174457)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 26 03:58:02 PST 2026


================
@@ -896,6 +915,101 @@ void EarlyIfConverter::invalidateTraces() {
   Traces->verifyAnalysis();
 }
 
+static bool isConstantPoolLoad(const MachineInstr *MI) {
+  // Check if this instruction is a load.
+  if (MI->mayLoad()) {
+    for (const auto &MOp : MI->memoperands()) {
+      if (const PseudoSourceValue *PSV = MOp->getPseudoValue())
+        if (PSV->isConstantPool())
+          return true;
+    }
+  }
+
+  return false;
+}
+
+/// Check if a register's value comes from a memory load by walking the
+/// def-use chain. We want to prioritize converting branches which
+/// depend on values loaded from memory (unless they are loop invariant,
+/// or come from a constant pool).
+/// Results are cached for virtual registers only.
+bool EarlyIfConverter::doOperandsComeFromMemory(Register Reg) {
+  if (!Reg.isVirtual())
+    return false;
+
+  // Walk the def-use chain.
+  SmallPtrSet<const MachineInstr *, 8> Visited;
+  SmallVector<const MachineInstr *> Worklist;
+  SmallVector<Register, 16> VisitedRegs;
+
+  MachineInstr *DefMI = MRI->getVRegDef(Reg);
+  // The operand is defined outside of the function - it does not
+  // come from memory access.
+  if (!DefMI)
+    return false;
+
+  Worklist.push_back(DefMI);
+  VisitedRegs.push_back(Reg);
+  unsigned int NumSteps = 0;
+
+  while (!Worklist.empty() && ++NumSteps < MaxNumSteps) {
+    const MachineInstr *MI = Worklist.pop_back_val();
+    if (!Visited.insert(MI).second)
+      continue;
+
+    // Check if this instruction is a load.
+    if (MI->mayLoad() && !isConstantPoolLoad(MI) &&
+        !MI->isDereferenceableInvariantLoad())
+      return true;
+
+    // Walk through all register use operands and find their definitions.
+    for (const MachineOperand &MO : MI->operands()) {
+      if (!MO.isReg() || !MO.isUse())
+        continue;
+      Register UseReg = MO.getReg();
+      if (!UseReg.isVirtual())
+        continue;
+
+      if (MachineInstr *UseDef = MRI->getVRegDef(UseReg)) {
+        if (!Visited.count(UseDef)) {
+          Worklist.push_back(UseDef);
+          VisitedRegs.push_back(UseReg);
+        }
+      }
+    }
+  }
+
+  return false;
+}
+
+/// Check if the branch condition is data-dependent (comes from memory loads).
+bool EarlyIfConverter::isConditionDataDependent() {
+  TargetInstrInfo::MachineBranchPredicate MBP;
+  if (TII->analyzeBranchPredicate(*IfConv.Head, MBP, /*AllowModify=*/false))
+    return false;
+
+  if (!MBP.ConditionDef)
+    return false;
+
+  // If the branch is biased (not 50/50), don't consider it data dependent.
+  // This is to prevent converting unprofitable checks such as
+  // `x[i] != 0;`
+  auto TBBProb = MBPI->getEdgeProbability(IfConv.Head, IfConv.TBB);
+  auto FBBProb = MBPI->getEdgeProbability(IfConv.Head, IfConv.FBB);
+  if (TBBProb != FBBProb) {
+    ++NumLikelyBiased;
+    return false;
+  }
+
+  // Check if ConditionDef itself is a load (e.g., CBZ with loaded value).
----------------
fhahn wrote:

comment needs updating now I htink

https://github.com/llvm/llvm-project/pull/174457


More information about the llvm-commits mailing list