kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

fold.h (5229B)


      1 #ifndef KIT_CG_FOLD_H
      2 #define KIT_CG_FOLD_H
      3 
      4 /* The semantic-layer peephole optimizer (Track 6).
      5  *
      6  * The value stack is not just a lowering buffer — it is also a small, named
      7  * `-O0` peephole optimizer (a kept feature: free unoptimized-build quality).
      8  * This header is its contract; the implementation is src/cg/fold.c. Op families
      9  * (arith.c, value.c, memory.c, control.c) call *into* these helpers rather than
     10  * reaching into the peephole's internals.
     11  *
     12  * This header is part of cg/internal.h's surface: cg/internal.h includes it
     13  * after the core operand/value types are defined, so anything that includes
     14  * cg/internal.h sees these declarations. Do not include fold.h on its own.
     15  *
     16  * Three responsibilities live here:
     17  *
     18  *   1. Integer constant folding. Pure width-aware integer arithmetic on
     19  *      immediates: a binop/unop/cmp of two constants becomes one constant.
     20  *      The width/mask/sign helpers and the foldable-type predicates back this.
     21  *
     22  *   2. Delayed-form lifecycle. Two stack entries are held un-emitted so a
     23  *      consumer can fuse:
     24  *        - SV_CMP   — a compare held so a following branch fuses cmp_branch
     25  *                     instead of materializing a 0/1 then testing it. The
     26  *                     consumer is api_branch_if (control.c); api_ensure_local
     27  *                     materializes it to a 0/1 when used as a value. LIVE.
     28  *        - SV_ARITH — a small immediate/local arith held so it can flow into a
     29  *                     following binop or collapse via identities. LIVE:
     30  * admitted by api_can_delay_int_arith for an unflagged foldable int op. It was
     31  * gated off while the load/store EA rider existed; Track 7 removed the rider
     32  * and Track 6.3 re-enabled it. Each delayed form has make / release /
     33  * materialize-to-dst entry points, plus the fold-chain and identity-collapse
     34  * helpers for SV_ARITH.
     35  *
     36  *   3. Const-local store-to-load forwarding. A scalar auto local with a known
     37  *      constant value is tracked so a later load reads the immediate directly.
     38  *      The invalidation boundaries are explicit:
     39  * api_local_const_memory_boundary (a possibly-aliasing store/call),
     40  * api_local_const_control_boundary (a label/branch/jump — no CFG, so values
     41  * cannot cross edges), and api_local_const_address_taken (the local escaped).
     42  */
     43 
     44 /* ---- 1. integer constant folding ---- */
     45 
     46 u32 api_int_like_width(Compiler* c, KitCgTypeId id);
     47 int api_type_is_bool(Compiler* c, KitCgTypeId id);
     48 u64 api_width_mask(u32 width);
     49 u64 api_mask_width(u64 v, u32 width);
     50 i64 api_sign_extend_width(u64 v, u32 width);
     51 int api_foldable_int_like_type(Compiler* c, KitCgTypeId ty, u32* width_out);
     52 int api_foldable_int_type(Compiler* c, KitCgTypeId ty, u32* width_out);
     53 i64 api_fold_result(Compiler* c, KitCgTypeId ty, u64 v, u32 width);
     54 int api_try_fold_int_binop(KitCg* g, BinOp op, KitCgTypeId ty, i64 a, i64 b,
     55                            i64* out);
     56 int api_try_fold_int_unop(KitCg* g, UnOp op, KitCgTypeId ty, i64 a, i64* out);
     57 int api_try_fold_int_cmp(KitCg* g, CmpOp op, KitCgTypeId ty, i64 a, i64 b,
     58                          i64* out);
     59 
     60 /* ---- 2a. delayed compare (SV_CMP) lifecycle ---- */
     61 
     62 ApiSValue api_make_cmp(CmpOp op, Operand a, Operand b, KitCgTypeId result_ty,
     63                        int a_owned, int b_owned);
     64 void api_release_cmp(KitCg* g, ApiSValue* sv);
     65 void api_materialize_cmp_to(KitCg* g, ApiSValue* sv, Operand dst);
     66 CmpOp api_invert_cmp(CmpOp op);
     67 
     68 /* ---- 2b. delayed arith (SV_ARITH) lifecycle — live (Track 6.3) ---- */
     69 
     70 ApiSValue api_make_arith_unop(UnOp op, Operand a, KitCgTypeId ty, int a_owned);
     71 ApiSValue api_make_arith_binop(BinOp op, Operand a, Operand b, KitCgTypeId ty,
     72                                int a_owned, int b_owned);
     73 void api_release_arith(KitCg* g, ApiSValue* sv);
     74 void api_materialize_arith_to(KitCg* g, ApiSValue* sv, Operand dst);
     75 int api_arith_rhs_reusable(const ApiSValue* sv);
     76 int api_can_delay_int_arith(KitCg* g, KitCgTypeId ty, u32 flags);
     77 int api_try_strength_reduce(KitCg* g, BinOp* op, KitCgTypeId ty, ApiSValue* a,
     78                             ApiSValue* b);
     79 int api_op_is_int_identity(KitCg* g, BinOp op, KitCgTypeId ty, i64 imm);
     80 int api_try_collapse_binop_identity(KitCg* g, BinOp op, KitCgTypeId ty,
     81                                     ApiSValue* a, ApiSValue* b, ApiSValue* out);
     82 int api_try_fold_arith_chain(KitCg* g, BinOp op, KitCgTypeId ty, ApiSValue* a,
     83                              ApiSValue* b, ApiSValue* out);
     84 int api_try_fold_unary_chain(ApiSValue* a, UnOp op, KitCgTypeId ty,
     85                              ApiSValue* out);
     86 
     87 /* ---- 3. const-local store-to-load forwarding ---- */
     88 
     89 void api_local_const_clear(ApiSourceLocal* rec);
     90 void api_local_const_clear_all(KitCg* g);
     91 void api_local_const_memory_boundary(KitCg* g);
     92 void api_local_const_control_boundary(KitCg* g);
     93 void api_local_const_address_taken(KitCg* g, KitCgLocal local);
     94 int api_local_const_can_track(KitCg* g, const ApiSourceLocal* rec,
     95                               KitCgMemAccess access);
     96 void api_local_const_store(KitCg* g, KitCgLocal local, KitCgMemAccess access,
     97                            i64 value);
     98 int api_local_const_load(KitCg* g, KitCgLocal local, KitCgMemAccess access,
     99                          Operand* out);
    100 
    101 #endif