[llvm] [BOLT][AArch64] Tweak heuristics for epilogue recognition (PR #169584)

Paschalis Mpeis via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 5 04:03:26 PST 2025


================
@@ -170,46 +170,48 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
     return isLoadFromStack(Inst);
   }
 
-  // We look for instructions that load from stack or make stack pointer
-  // adjustment, and assume the basic block is an epilogue if and only if
-  // such instructions are present and also immediately precede the branch
-  // instruction that ends the basic block.
+  // We look for instruction that saves LR to or restores LR from stack.
+  //
+  // If we ever see an LR save to stack, we assume this block is not an
+  // epilogue.
+  //
+  // If there is no LR save in the block and we see an LR restore from
+  // stack, we assume it is an epilogue.
+  //
+  // If neither is seen, we assume it is not an epilogue.
+  //
+  // This is not meant to accurately recognize epilogue in all possible
+  // cases, but to have BOLT be conservative on treating basic block as
+  // epilogue and then turning indirect branch with unknown control flow
+  // to tail call.
   bool isEpilogue(const BinaryBasicBlock &BB) const override {
     if (BB.succ_size())
       return false;
 
-    bool SeenLoadFromStack = false;
-    bool SeenStackPointerAdjustment = false;
-    for (const MCInst &Instr : BB) {
+    bool SeenLRRestoreFromStack = false;
+    for (auto It = BB.rbegin(); It != BB.rend(); ++It) {
+      const MCInst &Instr = *It;
       // Skip CFI pseudo instruction.
       if (isCFI(Instr))
         continue;
-
-      bool IsPop = isPop(Instr);
-      // A load from stack instruction could do SP adjustment in pre-index or
-      // post-index form, which we can skip to check for epilogue recognition
-      // purpose.
-      bool IsSPAdj = (isADD(Instr) || isMOVW(Instr)) &&
-                     Instr.getOperand(0).isReg() &&
-                     Instr.getOperand(0).getReg() == AArch64::SP;
-      SeenLoadFromStack |= IsPop;
-      SeenStackPointerAdjustment |= IsSPAdj;
-
-      if (!SeenLoadFromStack && !SeenStackPointerAdjustment)
-        continue;
-      if (IsPop || IsSPAdj || isPAuthOnLR(Instr))
-        continue;
       if (isReturn(Instr))
         return true;
-      if (isBranch(Instr))
-        break;
 
-      // Any previously seen load from stack or stack adjustment instruction
-      // is definitely not part of epilogue code sequence, so reset these two.
-      SeenLoadFromStack = false;
-      SeenStackPointerAdjustment = false;
+      if (isStoreToStack(Instr)) {
+        for (const MCOperand &Operand : useOperands(Instr)) {
+          if (Operand.isReg() && Operand.getReg() == AArch64::LR) {
+            return false;
+          }
+        }
+      } else if (isLoadFromStack(Instr)) {
+        for (const MCOperand &Operand : defOperands(Instr)) {
+          if (Operand.isReg() && Operand.getReg() == AArch64::LR) {
+            SeenLRRestoreFromStack = true;
----------------
paschalis-mpeis wrote:

We could return `true` directly here?

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


More information about the llvm-commits mailing list