ir_eval.c (3864B)
1 /* The single definition of the width-aware integer constant-fold semantics. 2 * See cg/ir_eval.h for the contract and rationale. Plain (op, width, i64) 3 * arithmetic only — no Compiler, no IR types — so cg/ and opt/ share it. */ 4 5 #include "cg/ir_eval.h" 6 7 u64 kit_ir_width_mask(u32 width) { 8 if (width >= 64u) return UINT64_MAX; 9 return (1ull << width) - 1ull; 10 } 11 12 u64 kit_ir_mask_width(u64 v, u32 width) { return v & kit_ir_width_mask(width); } 13 14 i64 kit_ir_sign_extend_width(u64 v, u32 width) { 15 v = kit_ir_mask_width(v, width); 16 if (!width || width >= 64u) return (i64)v; 17 u64 sign = 1ull << (width - 1u); 18 return (i64)((v ^ sign) - sign); 19 } 20 21 int kit_ir_eval_binop(BinOp op, u32 width, i64 a, i64 b, i64* out) { 22 u64 ua = kit_ir_mask_width((u64)a, width); 23 u64 ub = kit_ir_mask_width((u64)b, width); 24 u64 r = 0; 25 if (!out) return 0; 26 switch (op) { 27 case BO_IADD: 28 r = ua + ub; 29 break; 30 case BO_ISUB: 31 r = ua - ub; 32 break; 33 case BO_IMUL: 34 r = ua * ub; 35 break; 36 case BO_AND: 37 r = ua & ub; 38 break; 39 case BO_OR: 40 r = ua | ub; 41 break; 42 case BO_XOR: 43 r = ua ^ ub; 44 break; 45 case BO_SHL: { 46 u32 sh = (u32)(ub & (u64)(width - 1u)); 47 r = ua << sh; 48 break; 49 } 50 case BO_SHR_U: { 51 u32 sh = (u32)(ub & (u64)(width - 1u)); 52 r = ua >> sh; 53 break; 54 } 55 case BO_SHR_S: { 56 u32 sh = (u32)(ub & (u64)(width - 1u)); 57 if (!sh) { 58 r = ua; 59 } else { 60 u64 sign = 1ull << (width - 1u); 61 r = ua >> sh; 62 if (ua & sign) r |= kit_ir_width_mask(width) << (width - sh); 63 } 64 break; 65 } 66 default: 67 return 0; 68 } 69 *out = (i64)kit_ir_mask_width(r, width); 70 return 1; 71 } 72 73 int kit_ir_eval_unop(UnOp op, u32 width, i64 a, i64* out) { 74 u64 ua = kit_ir_mask_width((u64)a, width); 75 u64 r; 76 if (!out) return 0; 77 switch (op) { 78 case UO_NEG: 79 r = 0u - ua; 80 break; 81 case UO_NOT: 82 r = ua == 0; 83 break; 84 case UO_BNOT: 85 r = ~ua; 86 break; 87 default: 88 return 0; 89 } 90 *out = (i64)kit_ir_mask_width(r, width); 91 return 1; 92 } 93 94 int kit_ir_eval_cmp(CmpOp op, u32 width, i64 a, i64 b, i64* out) { 95 u64 ua = kit_ir_mask_width((u64)a, width); 96 u64 ub = kit_ir_mask_width((u64)b, width); 97 i64 sa = kit_ir_sign_extend_width(ua, width); 98 i64 sb = kit_ir_sign_extend_width(ub, width); 99 int r; 100 if (!out) return 0; 101 switch (op) { 102 case CMP_EQ: 103 r = ua == ub; 104 break; 105 case CMP_NE: 106 r = ua != ub; 107 break; 108 case CMP_LT_S: 109 r = sa < sb; 110 break; 111 case CMP_LE_S: 112 r = sa <= sb; 113 break; 114 case CMP_GT_S: 115 r = sa > sb; 116 break; 117 case CMP_GE_S: 118 r = sa >= sb; 119 break; 120 case CMP_LT_U: 121 r = ua < ub; 122 break; 123 case CMP_LE_U: 124 r = ua <= ub; 125 break; 126 case CMP_GT_U: 127 r = ua > ub; 128 break; 129 case CMP_GE_U: 130 r = ua >= ub; 131 break; 132 default: 133 return 0; 134 } 135 *out = r ? 1 : 0; 136 return 1; 137 } 138 139 int kit_ir_eval_convert(ConvKind k, u32 src_width, u32 dst_width, i64 src, 140 i64* out) { 141 u64 v; 142 if (!out) return 0; 143 switch (k) { 144 case CV_TRUNC: 145 case CV_ZEXT: 146 v = kit_ir_mask_width((u64)src, src_width); 147 break; 148 case CV_SEXT: 149 v = (u64)kit_ir_sign_extend_width((u64)src, src_width); 150 break; 151 case CV_BITCAST: 152 if (src_width != dst_width) return 0; 153 v = kit_ir_mask_width((u64)src, src_width); 154 break; 155 default: 156 return 0; 157 } 158 *out = (i64)kit_ir_mask_width(v, dst_width); 159 return 1; 160 } 161 162 int kit_ir_binop_is_commutative_int(BinOp op) { 163 switch (op) { 164 case BO_IADD: 165 case BO_IMUL: 166 case BO_AND: 167 case BO_OR: 168 case BO_XOR: 169 return 1; 170 default: 171 return 0; 172 } 173 } 174 175 int kit_ir_cmp_is_commutative_int(CmpOp op) { 176 return op == CMP_EQ || op == CMP_NE; 177 }