Regression test from seed 421

mlir-stage-06-v1 · regression test PR · draft · ← all drafts

Add a regression test for mlir-stage-06-v1

This adds one LIT test covering 51 lines and 38 branch outcomes that the existing suite does not reach, across 5 source files, at 48615bc5925ef4b9db8b4550b5d4322933cf4b7b.

Coverage this test adds

Source file Newly covered lines Newly covered branch outcomes
lib/Dataflow/IR/DataflowGraphCausality.cpp — 27:12–27:34 false
lib/Dataflow/IR/DataflowGraphValidation.cpp 1128–1130, 1132 1123:14–1123:20 false; 1130:11–1130:26 false
lib/Dataflow/IR/OperationSchema.cpp — 730:7–730:27 true; 738:7–739:56 true
lib/Frontend/Lowering/GraphParallelLowering.cpp 427, 479, 483, 582–589, 591, 594, 597–601, 603–605, 608–612, 615–621, 623–624, 626–630, 634, 638–639, 1320, 1322–1324 1314:17–1314:50 false; 1314:54–1314:76 false; 1315:17–1315:30 false; 1320:17–1320:50 false; 426:41–426:61 true; 478:14–478:17 true; 482:14–482:17 true; 583:23–583:31 false; 585:30–585:57 false; 585:30–585:57 true; 586:29–586:37 false; 589:44–589:45 false; 591:42–591:43 false; 600:18–600:24 false; 600:28–600:53 false; 600:9–600:14 false; 601:9–601:35 false; 611:18–611:24 false; 611:28–611:53 false; 611:9–611:14 false; 612:9–612:35 false; 616:14–616:40 true; 616:44–616:78 true; 617:14–619:16 false; 617:14–619:16 true; 621:31–621:50 false; 621:9–621:27 true; 623:9–623:27 true; 628:37–628:38 false; 628:37–628:38 true; 630:38–630:39 false; 634:36–634:37 false
lib/Frontend/Lowering/LowerGraphConstantsPass.cpp — 70:16–70:32 false

lib/Dataflow/IR/DataflowGraphValidation.cpp

 1121      }; 1122  +1123      if (auto stream = childPhase.getDefiningOp<dataflow::StreamOp>()) {    [false branch at 1123:14] 1124        if (childPhase != stream.getPhase() || !assumeExact(stream.getInit()) || 1125            !assumeExact(stream.getLimit()) || !assumeExact(stream.getStep())) 1126          return false; 1127      } else {+1128        llvm::SmallVector<dataflow::CarryOp, 4> carries;+1129        graphIndex->collectCarries(childPhase, carries);+1130        if (carries.empty())    [false branch at 1130:11] 1131          return false;+1132      } 1133   1134      llvm::SmallVector<mlir::Value, 4> inputs;

lib/Frontend/Lowering/GraphParallelLowering.cpp

  424    425    std::optional<LinearExpression> build(::mlir::Value value) {+ 426      if (auto found = cache.find(value); found != cache.end())    [true branch at 426:41]+ 427        return found->second;  428      if (failed.contains(value) || !active.insert(value).second)  429        return std::nullopt;@@  476      }  477  + 478      if (auto add = ::llvm::dyn_cast<::mlir::arith::AddIOp>(def))    [true branch at 478:14]+ 479        return finish(combine(add.getLhs(), add.getRhs(), /*subtract=*/false));  480      if (auto sub = ::llvm::dyn_cast<::mlir::arith::SubIOp>(def))  481        return finish(combine(sub.getLhs(), sub.getRhs(), /*subtract=*/true));+ 482      if (auto mul = ::llvm::dyn_cast<::mlir::arith::MulIOp>(def))    [true branch at 482:14]+ 483        return finish(multiply(mul.getLhs(), mul.getRhs()));  484      if (auto cast = ::llvm::dyn_cast<::mlir::arith::IndexCastOp>(def))  485        return finish(projectIndexCast(cast.getIn(), cast.getType(), false));@@  580    581    void add(LinearExpression &target, const LinearExpression &source,+ 582             bool subtract) {+ 583      target.constant = subtract ? target.constant - source.constant    [false branch at 583:23]+ 584                                 : target.constant + source.constant;+ 585      for (unsigned index = 0; index < target.lanes.size(); ++index)    [false branch at 585:30, true branch at 585:30]+ 586        target.lanes[index] = subtract    [false branch at 586:29]+ 587                                  ? target.lanes[index] - source.lanes[index]+ 588                                  : target.lanes[index] + source.lanes[index];+ 589      for (const auto &[symbol, coefficient] : source.symbols)    [false branch at 589:44]  590        addSymbol(target, symbol, subtract ? -coefficient : coefficient);+ 591      for (const auto &[lane, coefficient] : source.descendantLanes)    [false branch at 591:42]  592        addCoefficient(target.descendantLanes, lane,  593                       subtract ? -coefficient : coefficient);+ 594    }  595    596    std::optional<LinearExpression> combine(::mlir::Value lhs, ::mlir::Value rhs,+ 597                                            bool subtract) {+ 598      auto left = build(lhs);+ 599      auto right = build(rhs);+ 600      if (!left || !right || !left->transforms.empty() ||    [false branch at 600:18, false branch at 600:28, false branch at 600:9]+ 601          !right->transforms.empty())    [false branch at 601:9]  602        return std::nullopt;+ 603      add(*left, *right, subtract);+ 604      return left;+ 605    }  606    607    std::optional<LinearExpression> multiply(::mlir::Value lhs,+ 608                                             ::mlir::Value rhs) {+ 609      auto left = build(lhs);+ 610      auto right = build(rhs);+ 611      if (!left || !right || !left->transforms.empty() ||    [false branch at 611:18, false branch at 611:28, false branch at 611:9]+ 612          !right->transforms.empty())    [false branch at 612:9]  613        return std::nullopt;  614  + 615      auto isConstant = [](const LinearExpression &expression) {+ 616        return expression.symbols.empty() && expression.descendantLanes.empty() &&    [true branch at 616:14, true branch at 616:44]+ 617               ::llvm::all_of(expression.lanes, [](const ::llvm::APInt &value) {    [false branch at 617:14, true branch at 617:14]+ 618                 return value.isZero();+ 619               });+ 620      };+ 621      if (!isConstant(*left) && !isConstant(*right))    [false branch at 621:31, true branch at 621:9]  622        return std::nullopt;+ 623      if (!isConstant(*left))    [true branch at 623:9]+ 624        std::swap(left, right);  625  + 626      ::llvm::APInt scale = left->constant;+ 627      right->constant *= scale;+ 628      for (::llvm::APInt &coefficient : right->lanes)    [false branch at 628:37, true branch at 628:37]+ 629        coefficient *= scale;+ 630      for (auto &[symbol, coefficient] : right->symbols) {    [false branch at 630:38]  631        (void)symbol;  632        coefficient *= scale;  633      }+ 634      for (auto &[lane, coefficient] : right->descendantLanes) {    [false branch at 634:36]  635        (void)lane;  636        coefficient *= scale;  637      }+ 638      return right;+ 639    }  640    641    bool dependsOnLane(::mlir::Value value) {@@ 1312              SeenAddress &previous = found->second; 1313              bool differentLane =+1314                  previous.firstLane != currentLane || previous.multipleLanes;    [false branch at 1314:17, false branch at 1314:54]+1315              if (differentLane && (previous.writes || access.access->writes) &&    [false branch at 1315:17] 1316                  (!previous.allAtomic || !access.access->atomic)) { 1317                overlap = true; 1318                return false; 1319              }+1320              if (previous.firstLane != currentLane)    [false branch at 1320:17] 1321                previous.multipleLanes = true;+1322              previous.writes |= access.access->writes;+1323              previous.allAtomic &= access.access->atomic;+1324            } 1325            return true; 1326          });

The test

The input is 90 lines; reduction found nothing further to remove that kept the coverage above and a compiler that still accepted it. The CHECK lines are the compiler's exact output on this input at 48615bc5925ef4b9db8b4550b5d4322933cf4b7b.

// RUN: loom-raise-opt --loom-lower-scf-to-dfg --mlir-print-op-generic %s | FileCheck %s

llvm.func @imported_callable(i64) -> i64
func.func private @native_callable(%arg_a: i32) -> i32 {
  return %arg_a : i32
}
dataflow.thread private @thread_0 domain(#dataflow.thread_domain<dense>)(
    %limit: index, %memory: memref<?xindex>) ctrl (%ctrl: none) {
  "loom.spatial_region"(%limit, %memory)
      <{operandSegmentSizes = array<i32: 1, 0, 1, 0>,
        resultSegmentSizes = array<i32: 0, 0>}> ({
    ^bb0(%lim: index, %target: memref<?xindex>):
      %zero = arith.constant 0 : index
      %one = arith.constant 1 : index
      %two = arith.constant 2 : index
      %flag = arith.cmpi ult, %zero, %two : index
      scf.parallel (%iv0) = (%zero) to (%two) step (%one) {
        %mx0 = arith.muli %zero, %two : index
        %ix0 = arith.addi %mx0, %iv0 : index
      scf.parallel (%iv1) = (%zero) to (%two) step (%one) {
        %mx1 = arith.muli %ix0, %two : index
        %ix1 = arith.addi %mx1, %iv1 : index
      %ld2 = memref.load %target[%ix1] : memref<?xindex>
      %ad2 = arith.addi %ld2, %one : index
      memref.store %ad2, %target[%ix1] : memref<?xindex>
        scf.reduce
      }
        scf.reduce
      }
      "loom.spatial_yield"()
          <{operandSegmentSizes = array<i32: 0, 0>}> : () -> ()
  }) {graph_name = "g_thread_0", source_maps = []} :
      (index, memref<?xindex>) -> ()
  dataflow.thread.yield
}
dataflow.thread private @thread_1 domain(#dataflow.thread_domain<dense>)(
    %limit: index, %memory: memref<?xindex>) ctrl (%ctrl: none) {
  "loom.spatial_region"(%limit, %memory)
      <{operandSegmentSizes = array<i32: 1, 0, 1, 0>,
        resultSegmentSizes = array<i32: 0, 0>}> ({
    ^bb0(%lim: index, %target: memref<?xindex>):
      %zero = arith.constant 0 : index
      %one = arith.constant 1 : index
      %two = arith.constant 2 : index
      %flag = arith.cmpi ult, %zero, %two : index
      %wr3 = scf.while (%wa3 = %zero) : (index) -> index {
        %wc3 = arith.cmpi ult, %wa3, %two : index
        scf.condition(%wc3) %wa3 : index
      } do {
      ^bb0(%wb3: index):
      %wr4 = scf.while (%wa4 = %zero) : (index) -> index {
        %wc4 = arith.cmpi ult, %wa4, %two : index
        scf.condition(%wc4) %wa4 : index
      } do {
      ^bb0(%wb4: index):
      memref.store %one, %target[%zero] : memref<?xindex>
      %ld6 = memref.load %target[%zero] : memref<?xindex>
      %ad6 = arith.addi %ld6, %one : index
      memref.store %ad6, %target[%zero] : memref<?xindex>
        %wn4 = arith.addi %wb4, %one : index
        scf.yield %wn4 : index
      }
      memref.store %one, %target[%zero] : memref<?xindex>
        %wn3 = arith.addi %wb3, %one : index
        scf.yield %wn3 : index
      }
      %wr8 = scf.while (%wa8 = %zero) : (index) -> index {
        %wc8 = arith.cmpi ult, %wa8, %two : index
        scf.condition(%wc8) %wa8 : index
      } do {
      ^bb0(%wb8: index):
      %wr9 = scf.while (%wa9 = %zero) : (index) -> index {
        %wc9 = arith.cmpi ult, %wa9, %two : index
        scf.condition(%wc9) %wa9 : index
      } do {
      ^bb0(%wb9: index):
      memref.store %one, %target[%zero] : memref<?xindex>
        %wn9 = arith.addi %wb9, %one : index
        scf.yield %wn9 : index
      }
      %ld11 = memref.load %target[%zero] : memref<?xindex>
      %ad11 = arith.addi %ld11, %one : index
      memref.store %ad11, %target[%zero] : memref<?xindex>
        %wn8 = arith.addi %wb8, %one : index
        scf.yield %wn8 : index
      }
      "loom.spatial_yield"()
          <{operandSegmentSizes = array<i32: 0, 0>}> : () -> ()
  }) {graph_name = "g_thread_1", source_maps = []} :
      (index, memref<?xindex>) -> ()
  dataflow.thread.yield
}

// CHECK: "builtin.module"() ({
// CHECK-NEXT:   "llvm.func"() <{CConv = #llvm.cconv<ccc>, function_type = !llvm.func<i64 (i64)>, linkage = #llvm.linkage<external>, sym_name = "imported_callable", unnamed_addr = 0 : i64, visibility_ = 0 : i64}> ({
// CHECK-NEXT:   }) : () -> ()
// CHECK-NEXT:   "func.func"() <{function_type = (i32) -> i32, sym_name = "native_callable", sym_visibility = "private"}> ({
// CHECK-NEXT:   ^bb0(%arg12: i32):
// CHECK-NEXT:     "func.return"(%arg12) : (i32) -> ()
// CHECK-NEXT:   }) : () -> ()
// CHECK-NEXT:   "dataflow.thread"() <{domain = #dataflow.thread_domain<dense>, function_type = (index, memref<?xindex>) -> (), sym_name = "thread_0", sym_visibility = "private"}> ({
// CHECK-NEXT:   ^bb0(%arg9: index, %arg10: memref<?xindex>, %arg11: none):
// CHECK-NEXT:     %152 = "dataflow.graph.launch"(%arg11, %arg9, %arg10) <{callee = @g_thread_0, operandSegmentSizes = array<i32: 1, 1, 0, 1, 0>, resultSegmentSizes = array<i32: 0, 0, 1>, source_maps = []}> : (none, index, memref<?xindex>) -> none
// CHECK-NEXT:     "dataflow.thread.yield"(%152) : (none) -> ()
// CHECK-NEXT:   }) : () -> ()
// CHECK-NEXT:   "dataflow.thread"() <{domain = #dataflow.thread_domain<dense>, function_type = (index, memref<?xindex>) -> (), sym_name = "thread_1", sym_visibility = "private"}> ({
// CHECK-NEXT:   ^bb0(%arg6: index, %arg7: memref<?xindex>, %arg8: none):
// CHECK-NEXT:     %151 = "dataflow.graph.launch"(%arg8, %arg6, %arg7) <{callee = @g_thread_1, operandSegmentSizes = array<i32: 1, 1, 0, 1, 0>, resultSegmentSizes = array<i32: 0, 0, 1>, source_maps = []}> : (none, index, memref<?xindex>) -> none
// CHECK-NEXT:     "dataflow.thread.yield"(%151) : (none) -> ()
// CHECK-NEXT:   }) : () -> ()
// CHECK-NEXT:   "dataflow.graph"() <{arg_attrs = [{}, {llvm.noalias}], function_type = (index, memref<?xindex>) -> (), input_segments = array<i32: 1, 0, 1>, result_segments = array<i32: 0, 0, 0>, sym_name = "g_thread_0", sym_visibility = "private"}> ({
// CHECK-NEXT:   ^bb0(%arg3: none, %arg4: index, %arg5: memref<?xindex>):
// CHECK-NEXT:     %127 = "dataflow.constant"(%arg3) <{const_value = 1 : index}> : (none) -> index
// CHECK-NEXT:     %128 = "dataflow.constant"(%arg3) <{const_value = 2 : index}> : (none) -> index
// CHECK-NEXT:     %129 = "dataflow.constant"(%arg3) <{const_value = 0 : index}> : (none) -> index
// CHECK-NEXT:     %130 = "arith.muli"(%129, %128) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %131 = "arith.addi"(%130, %129) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %132 = "arith.addi"(%142#0, %127) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %133 = "arith.muli"(%129, %128) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %134 = "arith.addi"(%133, %127) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %135 = "arith.addi"(%144#0, %127) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %136 = "arith.muli"(%127, %128) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %137 = "arith.addi"(%136, %129) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %138 = "arith.addi"(%146#0, %127) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %139 = "arith.muli"(%127, %128) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %140 = "arith.addi"(%139, %127) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %141 = "arith.addi"(%148#0, %127) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %142:2 = "dataflow.load"(%arg5, %131, %arg3) : (memref<?xindex>, index, none) -> (index, none)
// CHECK-NEXT:     %143 = "dataflow.store"(%arg5, %131, %132, %142#1) : (memref<?xindex>, index, index, none) -> none
// CHECK-NEXT:     %144:2 = "dataflow.load"(%arg5, %134, %arg3) : (memref<?xindex>, index, none) -> (index, none)
// CHECK-NEXT:     %145 = "dataflow.store"(%arg5, %134, %135, %144#1) : (memref<?xindex>, index, index, none) -> none
// CHECK-NEXT:     %146:2 = "dataflow.load"(%arg5, %137, %arg3) : (memref<?xindex>, index, none) -> (index, none)
// CHECK-NEXT:     %147 = "dataflow.store"(%arg5, %137, %138, %146#1) : (memref<?xindex>, index, index, none) -> none
// CHECK-NEXT:     %148:2 = "dataflow.load"(%arg5, %140, %arg3) : (memref<?xindex>, index, none) -> (index, none)
// CHECK-NEXT:     %149 = "dataflow.store"(%arg5, %140, %141, %148#1) : (memref<?xindex>, index, index, none) -> none
// CHECK-NEXT:     %150:4 = "dataflow.sync"(%143, %145, %147, %149) : (none, none, none, none) -> (none, none, none, none)
// CHECK-NEXT:     "dataflow.graph.return"(%150#0) <{operandSegmentSizes = array<i32: 0, 0, 0, 1>}> : (none) -> ()
// CHECK-NEXT:   }) : () -> ()
// CHECK-NEXT:   "dataflow.graph"() <{arg_attrs = [{}, {llvm.noalias}], function_type = (index, memref<?xindex>) -> (), input_segments = array<i32: 1, 0, 1>, result_segments = array<i32: 0, 0, 0>, sym_name = "g_thread_1", sym_visibility = "private"}> ({
// CHECK-NEXT:   ^bb0(%arg0: none, %arg1: index, %arg2: memref<?xindex>):
// CHECK-NEXT:     %0 = "dataflow.constant"(%arg0) <{const_value = 0 : index}> : (none) -> index
// CHECK-NEXT:     %1 = "dataflow.constant"(%arg0) <{const_value = 1 : index}> : (none) -> index
// CHECK-NEXT:     %2 = "dataflow.constant"(%arg0) <{const_value = 2 : index}> : (none) -> index
// CHECK-NEXT:     %3 = "dataflow.carry"(%8, %arg0, %51#0) : (i1, none, none) -> none
// CHECK-NEXT:     %4 = "dataflow.carry"(%8, %0, %54) : (i1, index, index) -> index
// CHECK-NEXT:     %5 = "dataflow.invariant"(%8, %2) : (i1, index) -> index
// CHECK-NEXT:     %6 = "dataflow.carry"(%8, %arg0, %53) : (i1, none, none) -> none
// CHECK-NEXT:     %7 = "dataflow.carry"(%8, %arg0, %53) : (i1, none, none) -> none
// CHECK-NEXT:     %8 = "arith.cmpi"(%4, %5) <{predicate = 6 : i64}> : (index, index) -> i1
// CHECK-NEXT:     %9:2 = "dataflow.demux"(%8, %3) : (i1, none) -> (none, none)
// CHECK-NEXT:     %10:2 = "dataflow.gate"(%8, %3) : (i1, none) -> (i1, none)
// CHECK-NEXT:     %11:2 = "dataflow.demux"(%10#0, %10#1) : (i1, none) -> (none, none)
// CHECK-NEXT:     %12:2 = "dataflow.demux"(%8, %6) : (i1, none) -> (none, none)
// CHECK-NEXT:     %13:2 = "dataflow.demux"(%8, %7) : (i1, none) -> (none, none)
// CHECK-NEXT:     %14:2 = "dataflow.demux"(%8, %4) : (i1, index) -> (index, index)
// CHECK-NEXT:     %15 = "dataflow.invariant"(%8, %2) : (i1, index) -> index
// CHECK-NEXT:     %16:2 = "dataflow.gate"(%8, %15) : (i1, index) -> (i1, index)
// CHECK-NEXT:     %17:2 = "dataflow.demux"(%16#0, %16#1) : (i1, index) -> (index, index)
// CHECK-NEXT:     %18 = "dataflow.invariant"(%8, %1) : (i1, index) -> index
// CHECK-NEXT:     %19:2 = "dataflow.gate"(%8, %18) : (i1, index) -> (i1, index)
// CHECK-NEXT:     %20:2 = "dataflow.demux"(%19#0, %19#1) : (i1, index) -> (index, index)
// CHECK-NEXT:     %21 = "dataflow.invariant"(%8, %0) : (i1, index) -> index
// CHECK-NEXT:     %22:2 = "dataflow.gate"(%8, %21) : (i1, index) -> (i1, index)
// CHECK-NEXT:     %23:2 = "dataflow.demux"(%22#0, %22#1) : (i1, index) -> (index, index)
// CHECK-NEXT:     %24 = "dataflow.carry"(%28, %10#1, %30#1) : (i1, none, none) -> none
// CHECK-NEXT:     %25 = "dataflow.carry"(%28, %22#1, %45) : (i1, index, index) -> index
// CHECK-NEXT:     %26 = "dataflow.invariant"(%28, %16#1) : (i1, index) -> index
// CHECK-NEXT:     %27 = "dataflow.carry"(%28, %13#1, %44) : (i1, none, none) -> none
// CHECK-NEXT:     %28 = "arith.cmpi"(%25, %26) <{predicate = 6 : i64}> : (index, index) -> i1
// CHECK-NEXT:     %29:2 = "dataflow.demux"(%28, %24) : (i1, none) -> (none, none)
// CHECK-NEXT:     %30:2 = "dataflow.gate"(%28, %24) : (i1, none) -> (i1, none)
// CHECK-NEXT:     %31:2 = "dataflow.demux"(%30#0, %30#1) : (i1, none) -> (none, none)
// CHECK-NEXT:     %32:2 = "dataflow.demux"(%28, %27) : (i1, none) -> (none, none)
// CHECK-NEXT:     %33:2 = "dataflow.demux"(%28, %25) : (i1, index) -> (index, index)
// CHECK-NEXT:     %34 = "dataflow.invariant"(%28, %19#1) : (i1, index) -> index
// CHECK-NEXT:     %35:2 = "dataflow.gate"(%28, %34) : (i1, index) -> (i1, index)
// CHECK-NEXT:     %36:2 = "dataflow.demux"(%35#0, %35#1) : (i1, index) -> (index, index)
// CHECK-NEXT:     %37 = "dataflow.invariant"(%28, %22#1) : (i1, index) -> index
// CHECK-NEXT:     %38:2 = "dataflow.gate"(%28, %37) : (i1, index) -> (i1, index)
// CHECK-NEXT:     %39:2 = "dataflow.demux"(%38#0, %38#1) : (i1, index) -> (index, index)
// CHECK-NEXT:     %40:2 = "dataflow.sync"(%30#1, %32#1) : (none, none) -> (none, none)
// CHECK-NEXT:     %41 = "dataflow.store"(%arg2, %38#1, %35#1, %40#0) : (memref<?xindex>, index, index, none) -> none
// CHECK-NEXT:     %42:2 = "dataflow.load"(%arg2, %38#1, %41) : (memref<?xindex>, index, none) -> (index, none)
// CHECK-NEXT:     %43 = "arith.addi"(%42#0, %35#1) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %44 = "dataflow.store"(%arg2, %38#1, %43, %42#1) : (memref<?xindex>, index, index, none) -> none
// CHECK-NEXT:     %45 = "arith.addi"(%33#1, %35#1) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %46:2 = "dataflow.demux"(%30#0, %30#1) : (i1, none) -> (none, none)
// CHECK-NEXT:     %47:4 = "dataflow.sync"(%46#0, %31#0, %36#0, %39#0) : (none, none, index, index) -> (none, none, index, index)
// CHECK-NEXT:     %48 = "dataflow.mux"(%30#0, %47#0, %46#1) : (i1, none, none) -> none
// CHECK-NEXT:     %49 = "dataflow.carry"(%28, %10#1, %48) : (i1, none, none) -> none
// CHECK-NEXT:     %50:2 = "dataflow.demux"(%28, %49) : (i1, none) -> (none, none)
// CHECK-NEXT:     %51:2 = "dataflow.sync"(%29#0, %50#0) : (none, none) -> (none, none)
// CHECK-NEXT:     %52:2 = "dataflow.sync"(%51#0, %32#0) : (none, none) -> (none, none)
// CHECK-NEXT:     %53 = "dataflow.store"(%arg2, %22#1, %19#1, %52#0) : (memref<?xindex>, index, index, none) -> none
// CHECK-NEXT:     %54 = "arith.addi"(%14#1, %19#1) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %55:2 = "dataflow.demux"(%10#0, %51#0) : (i1, none) -> (none, none)
// CHECK-NEXT:     %56:2 = "dataflow.sync"(%55#0, %11#0) : (none, none) -> (none, none)
// CHECK-NEXT:     %57:2 = "dataflow.sync"(%56#0, %17#0) : (none, index) -> (none, index)
// CHECK-NEXT:     %58:2 = "dataflow.sync"(%20#0, %23#0) : (index, index) -> (index, index)
// CHECK-NEXT:     %59:2 = "dataflow.sync"(%57#0, %58#0) : (none, index) -> (none, index)
// CHECK-NEXT:     %60 = "dataflow.mux"(%10#0, %59#0, %55#1) : (i1, none, none) -> none
// CHECK-NEXT:     %61 = "dataflow.carry"(%8, %arg0, %60) : (i1, none, none) -> none
// CHECK-NEXT:     %62:2 = "dataflow.demux"(%8, %61) : (i1, none) -> (none, none)
// CHECK-NEXT:     %63:2 = "dataflow.sync"(%9#0, %62#0) : (none, none) -> (none, none)
// CHECK-NEXT:     %64 = "dataflow.carry"(%69, %63#0, %111#0) : (i1, none, none) -> none
// CHECK-NEXT:     %65 = "dataflow.carry"(%69, %0, %117) : (i1, index, index) -> index
// CHECK-NEXT:     %66 = "dataflow.invariant"(%69, %2) : (i1, index) -> index
// CHECK-NEXT:     %67 = "dataflow.carry"(%69, %12#0, %116) : (i1, none, none) -> none
// CHECK-NEXT:     %68 = "dataflow.carry"(%69, %13#0, %116) : (i1, none, none) -> none
// CHECK-NEXT:     %69 = "arith.cmpi"(%65, %66) <{predicate = 6 : i64}> : (index, index) -> i1
// CHECK-NEXT:     %70:2 = "dataflow.demux"(%69, %64) : (i1, none) -> (none, none)
// CHECK-NEXT:     %71:2 = "dataflow.gate"(%69, %64) : (i1, none) -> (i1, none)
// CHECK-NEXT:     %72:2 = "dataflow.demux"(%71#0, %71#1) : (i1, none) -> (none, none)
// CHECK-NEXT:     %73:2 = "dataflow.demux"(%69, %67) : (i1, none) -> (none, none)
// CHECK-NEXT:     %74:2 = "dataflow.demux"(%69, %68) : (i1, none) -> (none, none)
// CHECK-NEXT:     %75:2 = "dataflow.demux"(%69, %65) : (i1, index) -> (index, index)
// CHECK-NEXT:     %76 = "dataflow.invariant"(%69, %2) : (i1, index) -> index
// CHECK-NEXT:     %77:2 = "dataflow.gate"(%69, %76) : (i1, index) -> (i1, index)
// CHECK-NEXT:     %78:2 = "dataflow.demux"(%77#0, %77#1) : (i1, index) -> (index, index)
// CHECK-NEXT:     %79 = "dataflow.invariant"(%69, %1) : (i1, index) -> index
// CHECK-NEXT:     %80:2 = "dataflow.gate"(%69, %79) : (i1, index) -> (i1, index)
// CHECK-NEXT:     %81:2 = "dataflow.demux"(%80#0, %80#1) : (i1, index) -> (index, index)
// CHECK-NEXT:     %82 = "dataflow.invariant"(%69, %0) : (i1, index) -> index
// CHECK-NEXT:     %83:2 = "dataflow.gate"(%69, %82) : (i1, index) -> (i1, index)
// CHECK-NEXT:     %84:2 = "dataflow.demux"(%83#0, %83#1) : (i1, index) -> (index, index)
// CHECK-NEXT:     %85 = "dataflow.carry"(%90, %71#1, %92#1) : (i1, none, none) -> none
// CHECK-NEXT:     %86 = "dataflow.carry"(%90, %83#1, %105) : (i1, index, index) -> index
// CHECK-NEXT:     %87 = "dataflow.invariant"(%90, %77#1) : (i1, index) -> index
// CHECK-NEXT:     %88 = "dataflow.carry"(%90, %73#1, %104) : (i1, none, none) -> none
// CHECK-NEXT:     %89 = "dataflow.carry"(%90, %74#1, %104) : (i1, none, none) -> none
// CHECK-NEXT:     %90 = "arith.cmpi"(%86, %87) <{predicate = 6 : i64}> : (index, index) -> i1
// CHECK-NEXT:     %91:2 = "dataflow.demux"(%90, %85) : (i1, none) -> (none, none)
// CHECK-NEXT:     %92:2 = "dataflow.gate"(%90, %85) : (i1, none) -> (i1, none)
// CHECK-NEXT:     %93:2 = "dataflow.demux"(%92#0, %92#1) : (i1, none) -> (none, none)
// CHECK-NEXT:     %94:2 = "dataflow.demux"(%90, %88) : (i1, none) -> (none, none)
// CHECK-NEXT:     %95:2 = "dataflow.demux"(%90, %89) : (i1, none) -> (none, none)
// CHECK-NEXT:     %96:2 = "dataflow.demux"(%90, %86) : (i1, index) -> (index, index)
// CHECK-NEXT:     %97 = "dataflow.invariant"(%90, %80#1) : (i1, index) -> index
// CHECK-NEXT:     %98:2 = "dataflow.gate"(%90, %97) : (i1, index) -> (i1, index)
// CHECK-NEXT:     %99:2 = "dataflow.demux"(%98#0, %98#1) : (i1, index) -> (index, index)
// CHECK-NEXT:     %100 = "dataflow.invariant"(%90, %83#1) : (i1, index) -> index
// CHECK-NEXT:     %101:2 = "dataflow.gate"(%90, %100) : (i1, index) -> (i1, index)
// CHECK-NEXT:     %102:2 = "dataflow.demux"(%101#0, %101#1) : (i1, index) -> (index, index)
// CHECK-NEXT:     %103:2 = "dataflow.sync"(%92#1, %95#1) : (none, none) -> (none, none)
// CHECK-NEXT:     %104 = "dataflow.store"(%arg2, %101#1, %98#1, %103#0) : (memref<?xindex>, index, index, none) -> none
// CHECK-NEXT:     %105 = "arith.addi"(%96#1, %98#1) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %106:2 = "dataflow.demux"(%92#0, %92#1) : (i1, none) -> (none, none)
// CHECK-NEXT:     %107:4 = "dataflow.sync"(%106#0, %93#0, %99#0, %102#0) : (none, none, index, index) -> (none, none, index, index)
// CHECK-NEXT:     %108 = "dataflow.mux"(%92#0, %107#0, %106#1) : (i1, none, none) -> none
// CHECK-NEXT:     %109 = "dataflow.carry"(%90, %71#1, %108) : (i1, none, none) -> none
// CHECK-NEXT:     %110:2 = "dataflow.demux"(%90, %109) : (i1, none) -> (none, none)
// CHECK-NEXT:     %111:2 = "dataflow.sync"(%91#0, %110#0) : (none, none) -> (none, none)
// CHECK-NEXT:     %112:2 = "dataflow.sync"(%111#0, %94#0) : (none, none) -> (none, none)
// CHECK-NEXT:     %113:2 = "dataflow.load"(%arg2, %83#1, %112#0) : (memref<?xindex>, index, none) -> (index, none)
// CHECK-NEXT:     %114:2 = "dataflow.sync"(%95#0, %113#1) : (none, none) -> (none, none)
// CHECK-NEXT:     %115 = "arith.addi"(%113#0, %80#1) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %116 = "dataflow.store"(%arg2, %83#1, %115, %114#0) : (memref<?xindex>, index, index, none) -> none
// CHECK-NEXT:     %117 = "arith.addi"(%75#1, %80#1) <{overflowFlags = #arith.overflow<none>}> : (index, index) -> index
// CHECK-NEXT:     %118:2 = "dataflow.demux"(%71#0, %111#0) : (i1, none) -> (none, none)
// CHECK-NEXT:     %119:2 = "dataflow.sync"(%118#0, %72#0) : (none, none) -> (none, none)
// CHECK-NEXT:     %120:2 = "dataflow.sync"(%119#0, %78#0) : (none, index) -> (none, index)
// CHECK-NEXT:     %121:2 = "dataflow.sync"(%81#0, %84#0) : (index, index) -> (index, index)
// CHECK-NEXT:     %122:2 = "dataflow.sync"(%120#0, %121#0) : (none, index) -> (none, index)
// CHECK-NEXT:     %123 = "dataflow.mux"(%71#0, %122#0, %118#1) : (i1, none, none) -> none
// CHECK-NEXT:     %124 = "dataflow.carry"(%69, %63#0, %123) : (i1, none, none) -> none
// CHECK-NEXT:     %125:2 = "dataflow.demux"(%69, %124) : (i1, none) -> (none, none)
// CHECK-NEXT:     %126:2 = "dataflow.sync"(%70#0, %125#0) : (none, none) -> (none, none)
// CHECK-NEXT:     "dataflow.graph.return"(%126#0, %74#0) <{operandSegmentSizes = array<i32: 0, 0, 0, 2>}> : (none, none) -> ()
// CHECK-NEXT:   }) : () -> ()
// CHECK-NEXT: }) : () -> ()
// CHECK-EMPTY:

Validation

  • Native compiler and FileCheck replay: passed at 48615bc5925ef4b9db8b4550b5d4322933cf4b7b.
  • Property checker verdict on the reduced pair: PASS (postcondition.spct, SHA-256 1b36ea6d4e36596888d4e5081bae7a2edc8494a8b4713cc2852e0b4c08951bdd).
  • Reduction criterion: accepted checker PASS and every original line/branch increment over the suite baseline.

Where this test came from

PBT mlir-stage-06-v1, run 20260911-081718, seed 421.

The property under test is anchored on documentation:

  • selected output: docs/spec-compiler-part-3-dfg.md lines 102–109 (output side)
  • linked input 69: docs/spec-compiler-part-3-dfg.md lines 110–117 (input side)
  • linked input 76: docs/spec-compiler-part-3-dfg.md lines 92–100 (input side)
  • linked input 83: docs/spec-compiler-part-3-dfg.md lines 1454–1461 (input side)
  • linked input 92: docs/spec-compiler-part-3-dfg.md lines 117–120 (input side)
  • linked input 176: docs/spec-compiler-part-3-dfg.md lines 127–132 (input side)
  • linked input 203: docs/spec-compiler-part-3-dfg.md lines 87–90 (input side)

Coverage is measured against the recorded baseline suite at this revision, and counts unique mapped file locations including generated code. Reduction retains every added line or branch outcome and a passing property check; it is not a claim of global minimality, nor of a defect.

Originating PBT run · Seed 421

LIT test · PR patch · Native verification