SPIR-V dialect serialization issue

For this code:

        spv.mlir.loop {
          spv.Branch ^bb1(%16 : i64)
        ^bb1(%27: i64):  // 2 preds: ^bb0, ^bb2
          %28 = spv.SGreaterThan %27, %cst0_i64 : i64
          %29 = spv.Variable : !spv.ptr<i1, Function>
          spv.mlir.selection {
            spv.BranchConditional %28, ^bb1, ^bb2
          ^bb1:  // pred: ^bb0
            %44 = spv.ISub %27, %cst1_i64 : i64
            %45 = spv.IMul %44, %arg6 : i64
            %46 = spv.InBoundsPtrAccessChain %3[%45] : !spv.ptr<f64, CrossWorkgroup>, i64
            %47 = spv.Load "CrossWorkgroup" %46 ["Aligned", 8] : f64
            %48 = spv.FOrdLessThan %20, %47 : f64
            spv.Store "Function" %29, %48 : i1
            spv.Branch ^bb3
          ^bb2:  // pred: ^bb0
            spv.Store "Function" %29, %false : i1
            spv.Branch ^bb3
          ^bb3:  // 2 preds: ^bb1, ^bb2
            spv.mlir.merge
          }
          %30 = spv.Load "Function" %29 : i1
          %31 = spv.LogicalAnd %28, %30 : i1
          spv.Store "Function" %24, %27 : i64
          spv.BranchConditional %31, ^bb2(%27 : i64), ^bb3
        ^bb2(%32: i64):  // pred: ^bb1
          %33 = spv.ISub %32, %cst1_i64 : i64
          %34 = spv.IMul %33, %arg6 : i64
          %35 = spv.InBoundsPtrAccessChain %3[%34] : !spv.ptr<f64, CrossWorkgroup>, i64
          %36 = spv.Load "CrossWorkgroup" %35 ["Aligned", 8] : f64
          %37 = spv.IMul %32, %arg6 : i64
          %38 = spv.InBoundsPtrAccessChain %3[%37] : !spv.ptr<f64, CrossWorkgroup>, i64
          spv.Store "CrossWorkgroup" %38, %36 ["Aligned", 8] : f64
          %39 = spv.IAdd %34, %cst1_i64 : i64
          %40 = spv.InBoundsPtrAccessChain %3[%39] : !spv.ptr<f64, CrossWorkgroup>, i64
          %41 = spv.Load "CrossWorkgroup" %40 ["Aligned", 8] : f64
          %42 = spv.IAdd %37, %cst1_i64 : i64
          %43 = spv.InBoundsPtrAccessChain %3[%42] : !spv.ptr<f64, CrossWorkgroup>, i64
          spv.Store "CrossWorkgroup" %43, %41 ["Aligned", 8] : f64
          spv.Store "CrossWorkgroup" %35, %20 ["Aligned", 8] : f64
          spv.Store "CrossWorkgroup" %40, %23 ["Aligned", 8] : f64
          spv.Branch ^bb1(%33 : i64)
        ^bb3:  // pred: ^bb1
          spv.mlir.merge
        }

I’m hitting this assert llvm-project/Serializer.cpp at main · llvm/llvm-project · GitHub

It calls emitPhiForBlockArguments for block ^bb2(%32: i64): // pred: ^bb1, block->getPredecessors() returns block ^bb1(%27: i64): // 2 preds: ^bb0, ^bb2 and getPhiIncomingBlock returns ^bb3: // 2 preds: ^bb1, ^bb2 block from nested spv.mlir.selection.
And then } else if (auto branchCondOp = branch fails to populate blockOperands

ping @antiagainst

Thanks for reporting! I’ll take a look and fix it soon.

Sorry about the delay. Two issues are actually revealed by this: 1) missing support for structured control flow ops in header blocks and 2) block argument querying from the wrong predecessor. I’ve uploaded ⚙ D115560 [mlir][spirv] Fix nested control flow serialization that should fix the issue.