ir_eval.h (3211B)
1 #ifndef KIT_CG_IR_EVAL_H 2 #define KIT_CG_IR_EVAL_H 3 4 /* Width-aware integer constant-fold core: the single definition of the 5 * arithmetic semantics that several layers used to transcribe in lockstep 6 * (cg/fold.c's api_try_fold_int_*, opt/pass_o2.c's gvn_fold_*, and the 7 * width/convert helpers in opt/pass_combine.c + pass_simplify.c). 8 * 9 * Dependency-light by design: it pulls in only cg/cgtarget.h (for the BinOp / 10 * UnOp / CmpOp / ConvKind op tags and the integer typedefs) and operates on 11 * plain (op tag, width-in-bits, i64 bit-patterns). It knows NOTHING about 12 * Compiler, cg/internal.h, or the optimizer's IR types, so BOTH the semantic 13 * codegen (cg/) and the optimizer (opt/) can include it. 14 * 15 * Each caller keeps its own TYPE-SELECTION policy (which types are foldable, 16 * how a width is derived from a type, where div/rem faults live): this header 17 * shares only the value arithmetic once a width has been chosen. `width` is the 18 * scalar bit width (1..64); the eval entry points return 0 for op tags they do 19 * not evaluate, leaving *out untouched. */ 20 21 #include "cg/cgtarget.h" 22 23 /* Low `width` bits set (width>=64 -> all ones). */ 24 u64 kit_ir_width_mask(u32 width); 25 26 /* `v` masked to its low `width` bits. */ 27 u64 kit_ir_mask_width(u64 v, u32 width); 28 29 /* `v` interpreted as a `width`-bit value, sign-extended to a full i64. */ 30 i64 kit_ir_sign_extend_width(u64 v, u32 width); 31 32 /* Fold an integer binop at the given width. Operands are masked to `width` 33 * first; the wrapping result is masked back to `width`. Shifts mask the count 34 * to (width-1). Returns 1 and stores the masked result for the wrapping 35 * arithmetic/bitwise/shift ops; returns 0 (and leaves *out untouched) for 36 * div/rem/float/anything else — those stay with their owning caller. */ 37 int kit_ir_eval_binop(BinOp op, u32 width, i64 a, i64 b, i64* out); 38 39 /* Fold an integer unop at the given width (NEG/NOT/BNOT). Returns 1 and stores 40 * the masked result, or 0 for unhandled tags. */ 41 int kit_ir_eval_unop(UnOp op, u32 width, i64 a, i64* out); 42 43 /* Fold an integer compare at the given width. Operands are masked to `width`; 44 * signed predicates compare the sign-extended values. Returns 1 and stores the 45 * 0/1 boolean for the 10 integer predicates, or 0 for the FP predicates. */ 46 int kit_ir_eval_cmp(CmpOp op, u32 width, i64 a, i64 b, i64* out); 47 48 /* Fold a bit-preserving integer/pointer convert from `src_width` to `dst_width` 49 * bits (TRUNC / ZEXT / SEXT / BITCAST). BITCAST requires equal widths. Returns 50 * 1 and stores the converted constant (masked to `dst_width`); returns 0 for 51 * the float-domain conversions, which reinterpret the bits and must not fold 52 * this way. */ 53 int kit_ir_eval_convert(ConvKind k, u32 src_width, u32 dst_width, i64 src, 54 i64* out); 55 56 /* Integer commutativity: the binops/compares whose operands may be swapped 57 * without changing the integer result. (FP commutativity is intentionally NOT 58 * unified here: callers that fold FP keep their own predicate, since NaN 59 * payloads and ordered/unordered routing can make operand order observable.) */ 60 int kit_ir_binop_is_commutative_int(BinOp op); 61 int kit_ir_cmp_is_commutative_int(CmpOp op); 62 63 #endif /* KIT_CG_IR_EVAL_H */