Skip to content

Slow pattern matching elaboration #21802

@ErrWare

Description

@ErrWare

Description of the problem

Rocq takes 17-35 seconds to accept the Nify_fn definition below, and 8 seconds to accept the same definition minus one match case. First reported on a zulip thread), the workaround was to use an equality decision procedure instead of a match. Pierre-Marie Pédrot profiled the example and suggests there is "algorithmic slowdown due to unification constraints [from] a huge list of Evd.unification_pb".

Require Import NArith ZArith.
Open Scope N.
From MetaRocq.Template Require Export All Checker Reduction.
Export MonadNotation.
From MetaRocq.Utils Require Export bytestring.
Export String.
Open Scope bs.
Open Scope list.

Definition zxbits z i j := ((Z.shiftr z i) mod (Z.shiftl 1%Z (Z.max 0 (j - i))))%Z.
Definition xbits n i j :=  (N.shiftr n i) mod (N.shiftl 1 (j - i)).

Notation "'_zxbits_'" := (tConst (MPfile ["mvp"; "Project"], "zxbits") []).
Notation "'_xbits_'" := (tConst (MPfile ["mvp"; "Project"], "xbits") []).
Notation "'_Z.of_N_'" := (tConst (MPdot (MPfile ["IntDef"; "BinNums"; "Corelib"]) "Z", "of_N") []).
Notation "'_N.eqb_'" := (tConst (MPdot (MPfile ["BinNatDef"; "NArith"; "Stdlib"]) "N", "eqb") []).
Notation "'_Z.eqb_'" := (tConst (MPdot (MPfile ["IntDef"; "BinNums"; "Corelib"]) "Z", "eqb") []).

Fixpoint monadmap {A B:Type} (f:A->TemplateMonad B) (l:list A) : TemplateMonad (list B) :=
  match l with
  | h::t => fh <- f h;; ft <- monadmap f t;; tmReturn (fh::ft)
  | nil => tmReturn nil
  end.

(* Takes 17s in mvp, 35s in project. *)
Time Definition Nify_fn (Nify:term -> TemplateMonad term) (fn:term) (ts:list term): TemplateMonad term :=
  Nts <- monadmap Nify ts ;;
  match fn with
  | _zxbits_ => tmReturn (tApp _xbits_ Nts)
  | _Z.of_N_ => match ts with h::nil => Nify h | _ => tmFail "Z.of_N had more than one argument." end
  | _Z.eqb_ => tmReturn (tApp _N.eqb_ Nts)
  | _ => tmReturn (tApp fn Nts)
  end.

(* Takes 8s in mvp and project. *)
Time Definition Nify_fn' (Nify:term -> TemplateMonad term) (fn:term) (ts:list term): TemplateMonad term :=
  Nts <- monadmap Nify ts ;;
  match fn with
  (* removed zxbits case *)
  | _Z.of_N_ => match ts with h::nil => Nify h | _ => tmFail "Z.of_N had more than one argument." end
  | _Z.eqb_ => tmReturn (tApp _N.eqb_ Nts)
  | _ => tmReturn (tApp fn Nts)
  end.

Version of Rocq / Coq where this bug occurs

9.1.1

Interface of Rocq / Coq where this bug occurs

No response

Last version of Rocq / Coq where the bug did not occur

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind: bugAn error, flaw, fault or unintended behaviour.needs: triageThe validity of this issue needs to be checked, or the issue itself updated.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions