Regression test from seed 2

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

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

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

Coverage this test adds

Source file Newly covered lines Newly covered branch outcomes
lib/Dataflow/IR/DataflowFunctionLikeOps.cpp 104–106, 109, 117–118, 121–122, 124–128, 130–131, 173–174, 180–182, 191, 194–197, 224–226, 230, 235–237, 239–245, 474, 542 105:7–105:27 true; 118:35–118:62 false; 118:7–118:31 false; 121:7–121:33 true; 122:38–122:62 false; 122:9–122:34 false; 127:63–127:69 false; 127:9–127:59 false; 127:9–128:38 false; 128:9–128:38 false; 172:12–172:26 true; 174:11–174:42 false; 182:14–182:62 false; 191:11–191:20 false; 219:9–219:16 false; 226:9–226:44 false; 230:9–230:37 false; 240:9–240:41 true; 331:15–331:23 true; 331:27–331:59 false; 473:12–473:50 true; 474:11–474:21 false; 541:13–541:22 true
lib/Frontend/Lowering/LowerForallToThreadPass.cpp 40 39:11–39:59 true; 47:9–47:17 false

lib/Dataflow/IR/DataflowFunctionLikeOps.cpp

 102  enum class ExtentExprKind { Unsupported, Constant, AddI, IndexCast }; 103  +104  static bool isScalarNonzeroSignlessIntegerOrIndex(Type type) {+105    if (isa<IndexType>(type))    [true branch at 105:7]+106      return true; 107    auto integerType = dyn_cast<IntegerType>(type); 108    return integerType && integerType.isSignless() && integerType.getWidth() != 0;+109  } 110   111  static unsigned getScalarIntegerBitWidth(Type type) {@@ 115  } 116  +117  static ExtentExprKind classifyExtentExpr(Operation *op) {+118    if (op->getNumRegions() != 0 || op->getNumSuccessors() != 0)    [false branch at 118:35, false branch at 118:7] 119      return ExtentExprKind::Unsupported; 120  +121    if (isa<arith::ConstantOp>(op)) {    [true branch at 121:7]+122      if (op->getNumOperands() != 0 || op->getNumResults() != 1)    [false branch at 122:38, false branch at 122:9] 123        return ExtentExprKind::Unsupported;+124      Type resultType = op->getResult(0).getType();+125      auto value = dyn_cast_or_null<IntegerAttr>(+126          cast<arith::ConstantOp>(op).getProperties().value);+127      if (!isScalarNonzeroSignlessIntegerOrIndex(resultType) || !value ||    [false branch at 127:63, false branch at 127:9, false branch at 127:9]+128          value.getType() != resultType)    [false branch at 128:9] 129        return ExtentExprKind::Unsupported;+130      return ExtentExprKind::Constant;+131    } 132   133    if (isa<arith::AddIOp>(op)) {@@ 170      SmallVector<Frame> stack; 171      schedule(value, stack);+172      while (!stack.empty()) {    [true branch at 172:12]+173        Frame &frame = stack.back();+174        if (constants.contains(frame.value)) {    [false branch at 174:11] 175          active.erase(frame.value); 176          stack.pop_back();@@ 178        } 179  +180        Operation *definingOp = cast<OpResult>(frame.value).getOwner();+181        bool descended = false;+182        while (frame.nextOperand < definingOp->getNumOperands()) {    [false branch at 182:14] 183          Value operand = definingOp->getOperand(frame.nextOperand++); 184          if (constants.contains(operand))@@ 189          } 190        }+191        if (descended)    [false branch at 191:11] 192          continue; 193  +194        evaluateOperation(definingOp, frame.kind);+195        active.erase(frame.value);+196        stack.pop_back();+197      } 198   199      return constants.lookup(value);@@ 217   218      auto result = dyn_cast<OpResult>(value);+219      if (!result) {    [false branch at 219:9] 220        constants.try_emplace(value, Attribute{}); 221        return false; 222      } 223  +224      Operation *definingOp = result.getOwner();+225      ExtentExprKind kind = classifyExtentExpr(definingOp);+226      if (kind == ExtentExprKind::Unsupported) {    [false branch at 226:9] 227        cacheUnknown(definingOp); 228        return false; 229      }+230      if (!active.insert(value).second) {    [false branch at 230:9] 231        cacheUnknown(definingOp); 232        return false; 233      } 234  +235      stack.push_back({value, 0, kind});+236      return true;+237    } 238  +239    void evaluateOperation(Operation *op, ExtentExprKind kind) {+240      if (kind == ExtentExprKind::Constant) {    [true branch at 240:9]+241        constants.try_emplace(+242            op->getResult(0),+243            cast<IntegerAttr>(cast<arith::ConstantOp>(op).getProperties().value));+244        return;+245      } 246   247      auto operandConstant = [&](unsigned index) {@@ 329            auto constant = 330                dyn_cast_or_null<IntegerAttr>(evaluator.evaluate(extent));+331            if (constant && constant.getValue().isNegative()) {    [true branch at 331:15, false branch at 331:27] 332              launch.emitOpError("grid upper bound #") 333                  << index << " must be nonnegative";@@ 471      if (parseOne()) 472        return failure();+473      while (succeeded(parser.parseOptionalComma()))    [true branch at 473:12]+474        if (parseOne())    [false branch at 474:11] 475          return failure(); 476      return parser.parseRParen();@@ 539        p << " iv ("; 540        for (size_t i = N + 1, e = entry->getNumArguments(); i < e; ++i) {+541          if (i > N + 1)    [true branch at 541:13]+542            p << ", "; 543          p.printRegionArgument(entry->getArgument(i)); 544        }

lib/Frontend/Lowering/LowerForallToThreadPass.cpp

 37      bool rejected = false; 38      getOperation().walk([&](::mlir::scf::ForallOp forall) {+39        if (!forall->getParentOfType<::mlir::func::FuncOp>())    [true branch at 39:11]+40          return; 41        forall.emitError( 42            "loom-lower-forall-to-thread: raw scf.forall has no recognized "@@ 45        rejected = true; 46      });+47      if (rejected)    [false branch at 47:9] 48        signalPassFailure(); 49    }

The test

The input was reduced from 14 to 12 lines while keeping every covered line and branch outcome above, and while the compiler still accepted it. The CHECK lines are the compiler's exact output on this input at 48615bc5925ef4b9db8b4550b5d4322933cf4b7b.

// RUN: loom-raise-opt --loom-lower-forall-to-thread %s | FileCheck %s

dataflow.thread private @thread_0 domain(#dataflow.thread_domain<dense>)(%buf: memref<8xi32>) ctrl (%thread_ctrl: none) iv (%coord_0: index, %coord_1: index) {
  scf.forall (%lane) in (8) {
  }
  dataflow.thread.yield %thread_ctrl : none
}
func.func @host_0() {
  %buf = memref.alloc() : memref<8xi32>
  %g0 = arith.constant 4 : index
  %g1 = arith.constant 4 : index
  %token = dataflow.thread.launch @thread_0(%buf) grid(%g0, %g1) : (memref<8xi32>) -> !dataflow.thread_token
  return
}

// CHECK: module {
// CHECK-NEXT:   dataflow.thread private @thread_0 domain(#dataflow.thread_domain<dense>)(%arg0: memref<8xi32>) ctrl (%arg1: none) iv (%arg2: index, %arg3: index) {
// CHECK-NEXT:     scf.forall (%arg4) in (8) {
// CHECK-NEXT:     }
// CHECK-NEXT:     dataflow.thread.yield %arg1 : none
// CHECK-NEXT:   }
// CHECK-NEXT:   func.func @host_0() {
// CHECK-NEXT:     %alloc = memref.alloc() : memref<8xi32>
// CHECK-NEXT:     %c4 = arith.constant 4 : index
// CHECK-NEXT:     %c4_0 = arith.constant 4 : index
// CHECK-NEXT:     %0 = dataflow.thread.launch @thread_0(%alloc) grid(%c4, %c4_0) : (memref<8xi32>) -> !dataflow.thread_token
// CHECK-NEXT:     return
// 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 7335de40554c2959553a5de0c02886882a4779d2dd1eacf94f13877cc1ba64e5).
  • Reduction criterion: accepted checker PASS and every original line/branch increment over the suite baseline; the original postcondition BDD decision path is unchanged; every original fast edge increment over its suite baseline.

Where this test came from

PBT mlir-stage-19-v1, run 20260911-085053, seed 2.

The property under test is anchored on documentation:

  • selected output: docs/spec-compiler-part-3-dfg.md lines 1008–1013 (output side)
  • linked input 4: docs/spec-compiler-part-3-dfg.md lines 2052–2055 (input side)
  • linked input 40: docs/spec-compiler-part-2-scf.md lines 934–937 (input side)
  • linked input 44: docs/spec-compiler-part-3-dfg.md lines 2096–2100 (input side)
  • linked input 49: docs/spec-compiler-part-3-dfg.md lines 2057–2061 (input side)
  • linked input 51: docs/spec-compiler-part-2-scf.md lines 940–942 (input side)
  • linked input 79: docs/spec-compiler-part-3-dfg.md lines 2008–2010 (input side)
  • linked input 139: docs/spec-compiler-part-3-dfg.md lines 2017–2020 (input side)
  • linked input 199: docs/spec-compiler-part-3-dfg.md lines 2022–2023 (input side)
  • linked input 208: docs/spec-compiler-part-3-dfg.md lines 2012–2013 (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 2

LIT test · PR patch · Native verification