[RFC] Add std.switch and scf.switch

Thanks to reviews from Uday and River, this is now landed. It diverges from llvm.switch in a couple other ways now, allowing any signless int to switch on and placing the default case within the list of cases with an explicit keyword:

  switch %flag : i32, [
    default: ^bb1(%a : i32),
    42: ^bb1(%b : i32),
    43: ^bb3(%c : i32)
  ]

For scf.switch, I propose we make it more general, adopting Mehdi and Uday’s suggestions above.

%x, %y = scf.switch %flag : !mydialect.string -> (f32, f32) [
  default: {
    %x_default = ...
    %y_default = ...
    %scf.yield %x_default, %y_default
  },
  "foo": {
    %x_0 = ...
    %y_0 = ...
    %scf.yield %x_0, %y_0
  }
  "bar", "baz": {
    %x_m1 = ...
    %y_m1 = ...
    %scf.yield %x_m1, %y_m1
  }
]

which would be a definition like:

def IfOp : SCF_Op<"switch",
      [DeclareOpInterfaceMethods<RegionBranchOpInterface>,
       SingleBlockImplicitTerminator<"scf::YieldOp">, RecursiveSideEffects,
       NoRegionArguments]> {

  let arguments = (ins AnyType:$flag
                       OptionalAttr<ArrayAttr>:$case_values,
                       OptionalAttr<I32ElementsAttr>:$case_value_offsets);
  let results = (outs Variadic<AnyType>:$results);
  let regions = (region SizedRegion<1>:$defaultRegion,
                        Variadic<SizedRegion<1>>:$caseRegions);
  // ...
}

Some particular points:

  • the default keyword will always be on its own. I don’t think there’s any reason we should allow a declared case value to share a region with the default case. It would never make sense to construct such an op statically and if identifying matching regions in a canonicalization, we would just delete them.
  • We can use offsets to group the case values (as with operands in the llvm and std switch). We could also make this an array of arrays def 2DArrayAttr : TypedArrayAttrBase<ArrayAttr, "array of arrays">. Not sure which will end up being more ergonomic.

PS: discourse syntax highlighting of the basic block args there is weird. I don’t suppose we can fix that?