Skip to content

llzk-unused-declaration-elim can remove struct members that still have read/write #562

Description

@tim-hoffman

Run:

llzk-opt -llzk-unused-declaration-elim -debug-only=llzk-unused-declaration-elim <input>

Input:

module attributes {llzk.lang, llzk.main = !struct.type<@std::@C1>} {
  module @std attributes {llzk.lang = "zirgen"} {
    module @std attributes {llzk.lang = "zirgen"} {
      module @risc0 {
        struct.def @ValU32 {
          struct.member @low : !felt.type {llzk.pub}
          struct.member @high : !felt.type {llzk.pub}
          function.def @compute(%arg0: !felt.type, %arg1: !felt.type) -> !struct.type<@risc0::@ValU32> attributes {function.allow_witness} {
            %self = struct.new : <@risc0::@ValU32>
            struct.writem %self[@low] = %arg0 : <@risc0::@ValU32>, !felt.type
            struct.writem %self[@high] = %arg1 : <@risc0::@ValU32>, !felt.type
            function.return %self : !struct.type<@risc0::@ValU32>
          }
          function.def @constrain(%arg0: !struct.type<@risc0::@ValU32>, %arg1: !felt.type, %arg2: !felt.type) attributes {function.allow_constraint} {
            function.return
          }
        }
        struct.def @Reg {
          struct.member @reg : !felt.type {llzk.pub}
          function.def @compute(%arg0: !felt.type) -> !struct.type<@risc0::@Reg> attributes {function.allow_witness} {
            %self = struct.new : <@risc0::@Reg>
            struct.writem %self[@reg] = %arg0 : <@risc0::@Reg>, !felt.type
            function.return %self : !struct.type<@risc0::@Reg>
          }
          function.def @constrain(%arg0: !struct.type<@risc0::@Reg>, %arg1: !felt.type) attributes {function.allow_constraint} {
            %0 = struct.readm %arg0[@reg] : <@risc0::@Reg>, !felt.type
            constrain.eq %arg1, %0 : !felt.type, !felt.type
            function.return
          }
        }
      }
    }
    struct.def @C1 {
      struct.member @z : !struct.type<@std::@risc0::@Reg> {llzk.pub}
      function.def @compute(%arg0: !felt.type, %arg1: !felt.type) -> !struct.type<@C1> attributes {function.allow_witness} {
        %self = struct.new : <@C1>
        %0 = felt.add %arg0, %arg1 : !felt.type, !felt.type
        %1 = function.call @std::@risc0::@Reg::@compute(%0) : (!felt.type) -> !struct.type<@std::@risc0::@Reg>
        struct.writem %self[@z] = %1 : <@C1>, !struct.type<@std::@risc0::@Reg>
        function.return %self : !struct.type<@C1>
      }
      function.def @constrain(%arg0: !struct.type<@C1>, %arg1: !felt.type, %arg2: !felt.type) attributes {function.allow_constraint} {
        %0 = struct.readm %arg0[@z] : <@C1>, !struct.type<@std::@risc0::@Reg>
        %1 = felt.add %arg1, %arg2 : !felt.type, !felt.type
        function.call @std::@risc0::@Reg::@constrain(%0, %1) : (!struct.type<@std::@risc0::@Reg>, !felt.type) -> ()
        function.return
      }
    }
  }
}

Output:

Removing member struct.member @high : !felt.type {llzk.pub}
Removing member "struct.member"() <{sym_name = "low", type = !felt.type}> {llzk.pub} : () -> ()
Removing member struct.member @reg : !felt.type {llzk.pub}
Removing member struct.member @z : !struct.type<@std::@risc0::@Reg> {llzk.pub}
~/llzk-lib/test/Transforms/RedundantAndUnusedElim/redundant_op_pass_C.llzk:15:13: error: 'struct.writem' op references unknown symbol "@low"
            struct.writem %self[@low] = %arg0 : <@risc0::@ValU32>, !felt.type
            ^
~/llzk-lib/test/Transforms/RedundantAndUnusedElim/redundant_op_pass_C.llzk:15:13: note: see current operation: "struct.writem"(%0, %arg0) <{member_name = @low}> : (!struct.type<@risc0::@ValU32>, !felt.type) -> ()
~/llzk-lib/test/Transforms/RedundantAndUnusedElim/redundant_op_pass_C.llzk:15:13: error: could not find 'struct.member' named "@low" in "@risc0::@ValU32"
            struct.writem %self[@low] = %arg0 : <@risc0::@ValU32>, !felt.type
            ^
~/llzk-lib/test/Transforms/RedundantAndUnusedElim/redundant_op_pass_C.llzk:15:13: note: see current operation: "struct.writem"(%0, %arg0) <{member_name = @low}> : (!struct.type<@risc0::@ValU32>, !felt.type) -> ()
~/llzk-lib/test/Transforms/RedundantAndUnusedElim/redundant_op_pass_C.llzk:31:18: error: 'struct.readm' op references unknown symbol "@reg"
            %0 = struct.readm %arg0[@reg] : <@risc0::@Reg>, !felt.type
                 ^
~/llzk-lib/test/Transforms/RedundantAndUnusedElim/redundant_op_pass_C.llzk:31:18: note: see current operation: %0 = "struct.readm"(%arg0) <{mapOpGroupSizes = array<i32>, member_name = @reg, numDimsPerMap = array<i32>}> : (!struct.type<@risc0::@Reg>) -> !felt.type
~/llzk-lib/test/Transforms/RedundantAndUnusedElim/redundant_op_pass_C.llzk:31:18: error: could not find 'struct.member' named "@reg" in "@risc0::@Reg"
            %0 = struct.readm %arg0[@reg] : <@risc0::@Reg>, !felt.type
                 ^
~/llzk-lib/test/Transforms/RedundantAndUnusedElim/redundant_op_pass_C.llzk:31:18: note: see current operation: %0 = "struct.readm"(%arg0) <{mapOpGroupSizes = array<i32>, member_name = @reg, numDimsPerMap = array<i32>}> : (!struct.type<@risc0::@Reg>) -> !felt.type
~/llzk-lib/test/Transforms/RedundantAndUnusedElim/redundant_op_pass_C.llzk:48:14: error: 'struct.readm' op references unknown symbol "@z"
        %0 = struct.readm %arg0[@z] : <@C1>, !struct.type<@std::@risc0::@Reg>
             ^
~/llzk-lib/test/Transforms/RedundantAndUnusedElim/redundant_op_pass_C.llzk:48:14: note: see current operation: %0 = "struct.readm"(%arg0) <{mapOpGroupSizes = array<i32>, member_name = @z, numDimsPerMap = array<i32>}> : (!struct.type<@C1>) -> !struct.type<@std::@risc0::@Reg>
~/llzk-lib/test/Transforms/RedundantAndUnusedElim/redundant_op_pass_C.llzk:48:14: error: could not find 'struct.member' named "@z" in "@C1"
        %0 = struct.readm %arg0[@z] : <@C1>, !struct.type<@std::@risc0::@Reg>
             ^
~/llzk-lib/test/Transforms/RedundantAndUnusedElim/redundant_op_pass_C.llzk:48:14: note: see current operation: %0 = "struct.readm"(%arg0) <{mapOpGroupSizes = array<i32>, member_name = @z, numDimsPerMap = array<i32>}> : (!struct.type<@C1>) -> !struct.type<@std::@risc0::@Reg>

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions