<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/136120>136120</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Custom unroll pass results in "opt: CommandLine Error: Option 'max-deopt-or-unreachable-succ-check-depth' registered more than once!"
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          mahmoodn
      </td>
    </tr>
</table>

<pre>
    I have written the following code, `loop.c`:
```
#include <stdio.h>
int main() {
    volatile int sum = 0;
 
    for (int i = 0; i < 4; i++) {
        ++sum;
    }
 printf("Sum is %d\n", sum);
    return 0;
}
```
with a custom and basic loop unrolling pass, `MyUnroll.cpp`:
```
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Constants.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

namespace {
 struct SimpleLoopUnroll : public LoopPass {
    static char ID;
 SimpleLoopUnroll() : LoopPass(ID) {}

    bool runOnLoop(Loop *L, LPPassManager &LPM) override {
      // Ensure loop is in simplified form and has a single basic block
      if (!L->isLoopSimplifyForm() || L->getNumBlocks() != 1)
        return false;

      // Get loop components
      BasicBlock *Header = L->getHeader();
      BasicBlock *Preheader = L->getLoopPreheader();
      BasicBlock *Latch = L->getLoopLatch();
      BasicBlock *Exit = L->getExitBlock();
      if (!Preheader || !Latch || !Exit)
        return false;

      // Check for constant trip count of exactly 4
      if (!hasTripCountFour(L))
 return false;

      // Unroll the loop fully (4 times)
 unrollLoopFully(L, LPM);
      return true;
    }

    // Check if the loop has a trip count of exactly 4
    bool hasTripCountFour(Loop *L) {
 BasicBlock *Header = L->getHeader();
      BasicBlock *Latch = L->getLoopLatch();

      // Find the induction variable and its step
 PHINode *IndVar = nullptr;
      for (PHINode &PN : Header->phis()) {
 IndVar = &PN;
        break; // Assume first PHI is the induction variable
      }
      if (!IndVar)
        return false;

      // Get the step value from the latch
      Value *LatchValue = IndVar->getIncomingValueForBlock(Latch);
      Instruction *StepInst = dyn_cast<Instruction>(LatchValue);
      if (!StepInst || StepInst->getOpcode() != Instruction::Add)
        return false;

 ConstantInt *Step = dyn_cast<ConstantInt>(StepInst->getOperand(1));
      if (!Step || Step->getSExtValue() != 1)
        return false;

      // Get the initial and final values
      Value *InitValue = IndVar->getIncomingValueForBlock(L->getLoopPreheader());
      ConstantInt *Init = dyn_cast<ConstantInt>(InitValue);
      if (!Init)
        return false;

      // Find the comparison in the latch
      BranchInst *LatchBr = dyn_cast<BranchInst>(Latch->getTerminator());
      if (!LatchBr || !LatchBr->isConditional())
        return false;

      ICmpInst *Cmp = dyn_cast<ICmpInst>(LatchBr->getCondition());
      if (!Cmp || Cmp->getPredicate() != ICmpInst::ICMP_SLT)
        return false;

 ConstantInt *Limit = dyn_cast<ConstantInt>(Cmp->getOperand(1));
      if (!Limit)
        return false;

      // Calculate trip count: (Limit - Init) / Step
      int64_t TripCount = Limit->getSExtValue() - Init->getSExtValue();
      return TripCount == 4;
    }

    void unrollLoopFully(Loop *L, LPPassManager &LPM) {
      BasicBlock *Header = L->getHeader();
      BasicBlock *Preheader = L->getLoopPreheader();
 BasicBlock *Latch = L->getLoopLatch();
      BasicBlock *Exit = L->getExitBlock();
      Function *F = Header->getParent();

      // Clone the loop body 4 times
      SmallVector<BasicBlock *, 4> NewBlocks;
 ValueToValueMapTy VMap;
      for (unsigned i = 0; i < 4; ++i) {
 BasicBlock *NewBB = CloneBasicBlock(Header, VMap, ".unroll" + Twine(i), F);
        NewBlocks.push_back(NewBB);
        for (Instruction &I : *NewBB) {
          RemapInstruction(&I, VMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
        }
      }

      // Redirect preheader to the first unrolled block
 Preheader->getTerminator()->replaceSuccessorWith(Header, NewBlocks[0]);

 // Chain the unrolled blocks
      for (unsigned i = 0; i < 3; ++i) {
 NewBlocks[i]->getTerminator()->replaceSuccessorWith(Header, NewBlocks[i + 1]);
      }

      // Redirect the last block to the exit
 NewBlocks[3]->getTerminator()->replaceSuccessorWith(Header, Exit);

 // Remove the original loop
      DeleteDeadBlock(Header);
 DeleteDeadBlock(Latch);

      // Remove the loop from LoopInfo
 LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
 LI->erase(L);
    }

    void getAnalysisUsage(AnalysisUsage &AU) const override {
      AU.addRequired<LoopInfoWrapperPass>();
    }
 };
}

char SimpleLoopUnroll::ID = 0;
static RegisterPass<SimpleLoopUnroll> X("simple-loop-unroll", "Simple Loop Unrolling Pass for Loops with 4 Iterations", false, false);
```

I then ran these commands to build the pass and deploy it:
```
$ FILE=loop
$ clang -O0 -emit-llvm -S -Xclang -disable-O0-optnone -emit-llvm $FILE.c -o $FILE.ll
$ opt -load ./MyUnroll.so -simple-loop-unroll -S $FILE.ll -o $FILE-MyUnroll.ll
opt: CommandLine Error: Option 'max-deopt-or-unreachable-succ-check-depth' registered more than once!
LLVM ERROR: inconsistency in registered CommandLine options
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: opt -load ./MyUnroll.so -simple-loop-unroll -S loop.ll -o loop-MyUnroll.ll
 #0 0x00000000032b68db llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/scratch/mahmood/llvm-project/build/bin/opt+0x32b68db)
 #1 0x00000000032b40ec SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #2 0x0000155555116990 __restore_rt (/lib64/libpthread.so.0+0x12990)
 #3 0x0000155553f1852f raise (/lib64/libc.so.6+0x4e52f)
 #4 0x0000155553eebe65 abort (/lib64/libc.so.6+0x21e65)
 #5 0x0000000000757bf4 llvm::GlobPattern::create(llvm::StringRef, std::optional<unsigned long>) (.cold) GlobPattern.cpp:0:0
 #6 0x00000000031f40b8 (/scratch/mahmood/llvm-project/build/bin/opt+0x31f40b8)
 #7 0x00000000031deb1e (/scratch/mahmood/llvm-project/build/bin/opt+0x31deb1e)
 #8 0x00000000031df02d llvm::cl::Option::addArgument() (/scratch/mahmood/llvm-project/build/bin/opt+0x31df02d)
 #9 0x0000155553486a33 _GLOBAL__sub_I_BasicBlockUtils.cpp BasicBlockUtils.cpp:0:0
#10 0x000015555532d11a call_init.part.0 /usr/src/debug/glibc-2.28-251.el8_10.13.x86_64/elf/dl-init.c:71:19
#11 0x000015555532d21a _dl_init /usr/src/debug/glibc-2.28-251.el8_10.13.x86_64/elf/dl-init.c:118:9
#12 0x000015555404309c _dl_catch_exception (/lib64/libc.so.6+0x17909c)
#13 0x000015555533492e dl_open_worker /usr/src/debug/glibc-2.28-251.el8_10.13.x86_64/elf/dl-open.c:792:6
#14 0x000015555533492e dl_open_worker /usr/src/debug/glibc-2.28-251.el8_10.13.x86_64/elf/dl-open.c:751:1
#15 0x0000155554043044 _dl_catch_exception (/lib64/libc.so.6+0x179044)
#16 0x0000155555334b81 _dl_open /usr/src/debug/glibc-2.28-251.el8_10.13.x86_64/elf/dl-open.c:870:17
#17 0x0000155554cf8f8a dlopen_doit (/lib64/libdl.so.2+0xf8a)
#18 0x0000155554043044 _dl_catch_exception (/lib64/libc.so.6+0x179044)
#19 0x0000155554043103 _dl_catch_error (/lib64/libc.so.6+0x179103)
#20 0x0000155554cf952e _dlerror_run (/lib64/libdl.so.2+0x152e)
#21 0x0000155554cf902a dlopen@@GLIBC_2.2.5 (/lib64/libdl.so.2+0x102a)
#22 0x000000000329f3fc llvm::sys::DynamicLibrary::getPermanentLibrary(char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*) (/scratch/mahmood/llvm-project/build/bin/opt+0x329f3fc)
#23 0x000000000321e124 llvm::PluginLoader::operator=(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&) (/scratch/mahmood/llvm-project/build/bin/opt+0x321e124)
#24 0x0000000000824e07 llvm::cl::opt<llvm::PluginLoader, false, llvm::cl::parser<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>::handleOccurrence(unsigned int, llvm::StringRef, llvm::StringRef) (/scratch/mahmood/llvm-project/build/bin/opt+0x824e07)
#25 0x00000000031e25d6 llvm::cl::ParseCommandLineOptions(int, char const* const*, llvm::StringRef, llvm::raw_ostream*, char const*, bool) (/scratch/mahmood/llvm-project/build/bin/opt+0x31e25d6)
#26 0x00000000008284d8 optMain (/scratch/mahmood/llvm-project/build/bin/opt+0x8284d8)
#27 0x0000155553f047e5 __libc_start_main (/lib64/libc.so.6+0x3a7e5)
#28 0x00000000008225fe _start (/scratch/mahmood/llvm-project/build/bin/opt+0x8225fe)
Aborted (core dumped)
```

As you can see using the pass resulted in a crash. I don't know how that option has come to my pass, but according to the crash output and following grep, it is related to basic blocks.
```
$ grep -r "max-deopt-or-unreachable-succ-check-depth" ./llvm
./llvm/lib/Transforms/Utils/BasicBlockUtils.cpp: "max-deopt-or-unreachable-succ-check-depth", cl::init(8), cl::Hidden,

```
I wonder how can I fix this conflict?
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzEOltz4jizv0Z5UUHZsrk95MEhYZcqskklM_N9b5SQBeiMLPlIci7__lRLNraBTJLNnN2pTGEk9f2i7sbUWrFTnF-i0RUaXV_Qyu21uSzovtA6Vxcbnb9eLvGePnH8bIRzXGG353irpdTPQu0w0zlHZI7ROJJal0OGxhFKMhRl8BD-ogyRRCgmq5xjlMyty4Ue7lFyg6JMKIcLKhQiU0RmGE2uUJRhjPGTltQJyTGcsFWBUXKNI5T4_frMVhuMyBROiMO-f5zj1D8icuX_upjhX1i3VVEjhKXJNTyVRii39eyQx6rAwmJERjkazRUiBGQFKDJrAQ13lVENbwFNV_pn4faYYlZZpwtMVY431AqGQWG4UkZLCaosqbW1Km9fv_vlISvLdxVKiJRPBSKLe2rtcA9MvnFg-YDIYlEp5oRW759cKutM5Q9_AO9cK-uocr8-mikqX62wiCxWWpdLtdWfOf-uiN8MVXarTQEQ352Q8DmXWgm1-zzgFdjpSmr206_8EsFjVZbaOEQWhj6vtXWG0-IAEWWVBSMrWnBbUsaxBwseE2Xtcu2mQfP4URSl5CB5cAiMkgyX1UYKhht9dDzbOuoEw2xPDV5e1x56jKOJtCQ7oEBkurxugiT4b0C40VpiU6k7BUcRmcIHRiRbgaeu7gH4liq64xCI49X9LWDRT9wYkfNezCGyQGSBb5StDA--LywWClvgT2wFzyGeQ4DsqcUUg8Ykr6NlA2Y4YBNb7OWIVwOU3AgLfD0GRK8LbYpDOpmjyRz7Qzvu_qoKb03bbJMYskYM4dzmhjqet1RafrBQT4g_uAsSMF2UWnHl7OFI6zOgpz85zUE3yfWBibAUOGiTyDHgveH7U1hvsGbnPRQr6tj-BNyvvgd68yJcDxIW_O4p5MEUHZaD2sE8gYfDd8DzWW3P95z99Lme1TkGOyNA-ZVyWG8xf6HMyVecnvK0p_abEeUcji50BTpbAf3Awvu067CDS88bfFtJ-Qq4U-xEwW2NKGRxUO8CDgQqECC3R8qqKTpT8eObp_nSFVpsW9IhJn4tuY_XczK3YXu4CX-To37Qy44VuxAq97IJlYc7Bj9RI-hGcp8BhLPYOl4C3P2fy7-0T7bZUuU_aGBTVVKWznQ5q-uB9vz4_i-f6IIowF-5F3X0d1TRwephujgx3hhOf0I1UbOeWVsVHG-FsQ54gzx2XpJW6FBb9H0zUP07uQeogXLwE5UVx1uji-AnXusNwA-_2Zio_pZc19LWxloqpguhdn57oU0T5LUBe4bvFASA9tHxEpY80vxVrRm1DiXzzjGo8WpcnsBbqaNFFTJF871m8q4MdWY3afeoZCjJsjz_iC6bOmWpXCPEsQCdI0GAE3a4oSpHZBrXueQtmbry1MCPNy-u1sWX76DgdcIJKn3QbIWiMjiFPXWDpRLus17wi3unL_aRWoHWu2o9MPSWCuHAZ_VySCxwN1MjrFZQZZyGx5Whiu2D19UxcmWOeW4PdVy5Vso3bgqhqNPnNdKWKA3q_q14ZULpMtcqF-DGVLZ4PiTxcl6UDf_z4sSNm-0O51eNwQ9Ef826xxrYnheNB98bngtG3XFAHshBNC7nt_frx9W3vxGSK1F8wHlafj4Wjh7rp0sPKlklqeOdexfuE9Cn53KAax8FCB_mLWXlxuna4cNdHC5JAHsjFQRk5zfPFBE9xIA7faOkeNIiP1eifKSW75bw_1Jp-69UtU2bDHALD9TWEBAD1HDlflXgQNPJ2-pto_NX3BSNzdHHgkr5gzNIIcm8zywYJUXJDf6LP9dNS2DPO8U37T9uafntFf-4peWZMqhSfrqTvzEbCSMQ8WZFCHSvPKQXpd1EZNoYeh5oE8hqZFjV_SUB3Pjbs1DgvMIH5RwvjjSMW8mGZWX36w31uD3dk7O1TP0SZLzEIRqzBuhozIPxAy9o2a0VwGTjZZf1h8X6L32r80ryFX_icr6nasehr_Z7y53Sht8KC-3oSjMq7Ql33fquF3oHd3jguTCcOVwevN_pMEzzdWTQHc_bPvcQDG9cN7BseCkp448VY9xabf4j3L5nntZ5RlcRGl333PXQatD6guwzYT_uUMl5h-pSF2h0_bskEd7B4q48H9J9KAKsC_I1BuDQkx5xm3yR26bPPdb1Ay_0U0gL2oidr9cgPxxYvuaSO37NaX4ca42gpyf6tfqp9AeSoYWFbqEZvsHh5tln12XTBe24Owzfknlz5j-GliU3fmjkr2FEZsM6B3t83US6WoKuuKGWN333Ly6oDsHvlu4ApPcdmMq-g3f5McD5KVP2fUjz_IH_byUMz99h_GT2Cx_dIW6U-VHayQQtVDjX3ZF0PXp74DthXUNnfgp5g_8bZst-7MUHYJLBIXHWmTSAecPUEwihdtgP-yAUYd1iP1ZO8dJxQ_2MtoYP5Uz70LhFd3wcZUtwCIUN9ZFvfblcUJVbiIpNJWQookugCa1FzkupX7Fw54bRKV4sVzcoua5dGVaYpGqHB3cRHnAoeaR8KvDgEQ_-W-_kwkKPPLiLBrp0Cm7LzklEUsA5ZHigD1-krJHr0uGB1DTHQ0QWh3G51Xhwqleg2mLo4BscAD1iXfrabh4UsRKK4xtj4GrO8F1ZXzmTgr4Mcq5LN9AGCHDK9l4OWzE2YHvOfg5yXkI-mGBTuwPPcaENBCFVWCvGoWaOstXqxy2-eXi4ewAaQoFjw3nFXqFn6UB3mdJlMHeU3a9usscbbKsN1KIUb6odNrzUxoEV986VFszl88BOuH21GTJdILKoZ9bwMSiN_h_OHCILYS00jmQRJjD1iNv3UobaPYYL2hnK-BBF2aOj7CfOq6IMHhENQwTeG70ztMDU7KrCT0aT7PP28j8mBWP5nb6lMCJJhKOXqPmXkM14mm_qoTpEp3214eHeCOU8s9-AdUSm7aHOpB6RMcSMUHUxP0VkYZkJmXVR_yJ2qjIfKfApFCIL8CByFb3U7NTdBiJJfMRsGnGGH8VOUfknVbn0Fa-nPccWroWtXru6CITk6B9nNYT1PwslWeT_BwKkJhCP4F8cj2ezCK_XhlunDV8bV4skxWachs_S7Q2n-dDqYeS5jslsFrU8J12UyTaejsgWGyosP8XFAMvYY0n5iGxbLGkPC-cbPh5hutHnOOpgITEfj1oso67-oslostmmHWP_IfXmnjrHTT0LYoaH_rQ98-iMULsHvvU6dnlYDbFEJUrmh-pGarXzd4T3gyHTYOEZ7hA5Y4Bxz8LxNo020y-7UUDTqmHSJ5LzTcy_TsSjaYlMj4hsI5J3dM3q6y9kxPBM8zyrw_0wE_gqU0C2ZWrWc6N0OqZJgtd_rO6ustV6bavNerk-_rWOlSU-s9YxHERm1IuchORxTDGjUq6FEm5YUuOGEdRSlTUgkmGILHK-qXaQVMFrB2RIpgMyiodcTtdxNIyT4ct0vPZuzeUWzsuBx8ZQkk1ilGTxrCYfH5MnMcXrPFD_nWTjeIqSrCHbyxdplCbRjHmyDAy25i-MNzfe20EaT2bRjAUjAdKkL0uSzgjHuVzrkqv1szY__WThqxIBtqDIGUFJNq6Jp_8w8ZE3Y018dKLONP1b6kzTVp3jY4k209gjBSZ-pyzTCQREPKnpTnrCsO10O6U4l16RuRZnEncOV_mQeCm2U9qKMP3_0MvsGGkcJV2kULO9hzCOkgNCEh0JPBsRDgg9prWpzrDXlTgeEd4ii4-RRaTRHkojlEZ_rJZX8zUZkuHoHbwRaVVJSL-EmG2TLTtX71y_KloIthIbQ81rWNtxd89NQRVXrtkgU9_b-F6qrjQOt-J6zV5e4jh88T-_r62_PlEyB6jeYVhYO0MFlHphGy7PzgkqpWY0DLmafTiS_ZZSy2ui1VPS11PMY9ItFe5ltRNqpX1PXZcA0EABc9eITP9ZHTTqH_8WTXhZW02kvaJpSlIeTc5c5L7tmb-hoW4_eQpaUmNBjfN_2HPqPzix9-XzHWOVMdw3Vp0xVSio36gBzy5_2QpBza0RRv1qipNRPj6jyXvQZKfJu6t7vENX0AvWXtS-K16vy8lOkMHCRmv5W8o2L18r_fjIBadpPoVm8JYK9XVNA7aW1qTfr0TphI_weg2pf20dNW5dtFTPXwwJnfBRi3F6xD0ZbTkOuL7OPCALpDLohngOKJk23PfUvK59j6Y2mcWvusKMKmw5x-GdssOcxnBbSecdH9PQsw_xEudaITJx-KfSz3ivn7HbU1dPEfxbJUwXHDuNi9fDS4ibymHKmDa5p6A7UwBduRJ2Vd55D3RnuJ-lC4cFMCIp8OF09-UtOzwzOAJAPID7mnxiskL8HMG7eJQNOwMNsfnou3yhE_gsXR89dcwK_8vfdFr_vtEs_ynynCtE5sFkXYGX-FmrnBtvBTDiEm_FC3Z7AUZQWymYQ8niIr9M8lkyoxf8Mp6k6XQ6Smfpxf5yNklJPmM0mcRkEyWbySxKUkrGySyfbLZ0eyEuSURGURpP4oiko3SYjsgsiuIpT9g0SkmK0ogXVMghKGyoze7CD30u42Qck-hC0g2X1r8OTIjiz9jvgtyj6wtz6V17U-0sSiMprLMtGiec5Jfz8I5rPcfpOKV_0w8R8k_P2Ai5qIy8_PujsFoxT5fk_wIAAP__o51sDQ">