diffsl 0.11.9

A compiler for a domain-specific language for ordinary differential equations (ODE).
Documentation
// RUN: %eopt --enzyme %s | FileCheck %s

module {
  func.func @square(%x : f64, %c : i32) -> f64 {
    %c2 = arith.constant 2.000000e+00 : f64
    %c10 = arith.constant 10.000000e+00 : f64
    %r:2 = scf.execute_region -> (f64, f64) {
      cf.switch %c : i32, [
      default: ^bb5,
      104: ^bb3,
      113: ^bb4(%c10 : f64)
    ]
  ^bb4(%z : f64):  // pred: ^bb2
    %x2 = arith.mulf %x, %x : f64
    scf.yield %x2, %z : f64, f64
  ^bb3:
    %x3 = arith.addf %x, %x : f64
    scf.yield %x3, %c2 : f64, f64
  ^bb5:
    cf.br ^bb4(%x : f64)
    }
    %res = arith.mulf %r#0, %r#1 : f64
    return %res : f64
  }
  func.func @dsq(%x : f64, %dx : f64, %c : i32) -> f64 {
    %r = enzyme.fwddiff @square(%x, %dx, %c) { activity=[#enzyme<activity enzyme_dup>, #enzyme<activity enzyme_const>], ret_activity=[#enzyme<activity enzyme_dupnoneed>] } : (f64, f64, i32) -> (f64)
    return %r : f64
  }
}

// CHECK:   func.func private @fwddiffesquare(%[[x:.+]]: f64, %[[dx:.+]]: f64, %[[c:.+]]: i32) -> f64 {
// CHECK-DAG:     %[[cst2:.+]] = arith.constant 2.000000e+00 : f64
// CHECK-DAG:     %[[cst10:.+]] = arith.constant 1.000000e+01 : f64
// CHECK-DAG:     %[[cst0:.+]] = arith.constant 0.000000e+00 : f64
// CHECK-NEXT:     %[[r0:.+]]:4 = scf.execute_region -> (f64, f64, f64, f64) {
// CHECK-NEXT:     %[[cst02:.+]] = arith.constant 0.000000e+00 : f64
// CHECK-NEXT:       cf.switch %[[c]] : i32, [
// CHECK-NEXT:         default: ^bb3,
// CHECK-NEXT:         104: ^bb2,
// CHECK-NEXT:         113: ^bb1(%[[cst10]], %[[cst02]] : f64, f64)
// CHECK-NEXT:       ]
// CHECK-NEXT:     ^bb1(%[[a3:.+]]: f64, %[[da3:.+]]: f64):  // 2 preds: ^bb0, ^bb3
// CHECK-NEXT:       %[[a4:.+]] = arith.mulf %[[dx]], %[[x]] : f64
// CHECK-NEXT:       %[[a5:.+]] = arith.mulf %[[dx]], %[[x]] : f64
// CHECK-NEXT:       %[[a6:.+]] = arith.addf %[[a4]], %[[a5]] : f64
// CHECK-NEXT:       %[[a7:.+]] = arith.mulf %[[x]], %[[x]] : f64
// CHECK-NEXT:       scf.yield %[[a7]], %[[a6]], %[[a3]], %[[da3]] : f64, f64, f64, f64
// CHECK-NEXT:     ^bb2:  // pred: ^bb0
// CHECK-NEXT:       %[[b8:.+]] = arith.addf %[[dx]], %[[dx]] : f64
// CHECK-NEXT:       %[[b9:.+]] = arith.addf %[[x]], %[[x]] : f64
// CHECK-NEXT:       scf.yield %[[b9]], %[[b8]], %[[cst2]], %[[cst0]] : f64, f64, f64, f64
// CHECK-NEXT:     ^bb3:  // pred: ^bb0
// CHECK-NEXT:       cf.br ^bb1(%[[x]], %[[dx]] : f64, f64)
// CHECK-NEXT:     }
// CHECK-NEXT:     %[[r1:.+]] = arith.mulf %[[r0]]#1, %[[r0]]#2 : f64
// CHECK-NEXT:     %[[r2:.+]] = arith.mulf %[[r0]]#3, %[[r0]]#0 : f64
// CHECK-NEXT:     %[[r3:.+]] = arith.addf %[[r1]], %[[r2]] : f64
// CHECK-NEXT:     %[[r4:.+]] = arith.mulf %[[r0]]#0, %[[r0]]#2 : f64
// CHECK-NEXT:     return %[[r3]] : f64
// CHECK-NEXT:   }