| ... | ... | @@ -12932,7 +12932,52 @@ static bool optional_value_is_null(ConstExprValue *val) { |
| 12932 | 12932 | } |
| 12933 | 12933 | } |
| 12934 | 12934 | |
| 12935 | // Returns ErrorNotLazy when the value cannot be determined |
| 12936 | static Error lazy_cmp_zero(AstNode *source_node, ConstExprValue *val, Cmp *result) { |
| 12937 | Error err; |
| 12938 | |
| 12939 | switch (val->special) { |
| 12940 | case ConstValSpecialRuntime: |
| 12941 | case ConstValSpecialUndef: |
| 12942 | return ErrorNotLazy; |
| 12943 | case ConstValSpecialStatic: |
| 12944 | switch (val->type->id) { |
| 12945 | case ZigTypeIdComptimeInt: |
| 12946 | case ZigTypeIdInt: |
| 12947 | *result = bigint_cmp_zero(&val->data.x_bigint); |
| 12948 | return ErrorNone; |
| 12949 | default: |
| 12950 | return ErrorNotLazy; |
| 12951 | } |
| 12952 | case ConstValSpecialLazy: |
| 12953 | switch (val->data.x_lazy->id) { |
| 12954 | case LazyValueIdInvalid: |
| 12955 | zig_unreachable(); |
| 12956 | case LazyValueIdAlignOf: |
| 12957 | *result = CmpGT; |
| 12958 | return ErrorNone; |
| 12959 | case LazyValueIdSizeOf: { |
| 12960 | LazyValueSizeOf *lazy_size_of = reinterpret_cast<LazyValueSizeOf *>(val->data.x_lazy); |
| 12961 | IrAnalyze *ira = lazy_size_of->ira; |
| 12962 | bool is_zero_bits; |
| 12963 | if ((err = type_val_resolve_zero_bits(ira->codegen, &lazy_size_of->target_type->value, |
| 12964 | nullptr, nullptr, &is_zero_bits))) |
| 12965 | { |
| 12966 | return err; |
| 12967 | } |
| 12968 | *result = is_zero_bits ? CmpEQ : CmpGT; |
| 12969 | return ErrorNone; |
| 12970 | } |
| 12971 | default: |
| 12972 | return ErrorNotLazy; |
| 12973 | } |
| 12974 | } |
| 12975 | zig_unreachable(); |
| 12976 | } |
| 12977 | |
| 12935 | 12978 | static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| 12979 | Error err; |
| 12980 | |
| 12936 | 12981 | IrInstruction *op1 = bin_op_instruction->op1->child; |
| 12937 | 12982 | if (type_is_invalid(op1->value.type)) |
| 12938 | 12983 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -13182,6 +13227,50 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 13182 | 13227 | } |
| 13183 | 13228 | |
| 13184 | 13229 | if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) { |
| 13230 | { |
| 13231 | // Before resolving the values, we special case comparisons against zero. These can often be done |
| 13232 | // without resolving lazy values, preventing potential dependency loops. |
| 13233 | Cmp op1_cmp_zero; |
| 13234 | if ((err = lazy_cmp_zero(bin_op_instruction->base.source_node, &casted_op1->value, &op1_cmp_zero))) { |
| 13235 | if (err == ErrorNotLazy) goto never_mind_just_calculate_it_normally; |
| 13236 | return ira->codegen->invalid_instruction; |
| 13237 | } |
| 13238 | Cmp op2_cmp_zero; |
| 13239 | if ((err = lazy_cmp_zero(bin_op_instruction->base.source_node, &casted_op2->value, &op2_cmp_zero))) { |
| 13240 | if (err == ErrorNotLazy) goto never_mind_just_calculate_it_normally; |
| 13241 | return ira->codegen->invalid_instruction; |
| 13242 | } |
| 13243 | bool can_cmp_zero = false; |
| 13244 | Cmp cmp_result; |
| 13245 | if (op1_cmp_zero == CmpEQ && op2_cmp_zero == CmpEQ) { |
| 13246 | can_cmp_zero = true; |
| 13247 | cmp_result = CmpEQ; |
| 13248 | } else if (op1_cmp_zero == CmpGT && op2_cmp_zero == CmpEQ) { |
| 13249 | can_cmp_zero = true; |
| 13250 | cmp_result = CmpGT; |
| 13251 | } else if (op1_cmp_zero == CmpEQ && op2_cmp_zero == CmpGT) { |
| 13252 | can_cmp_zero = true; |
| 13253 | cmp_result = CmpLT; |
| 13254 | } else if (op1_cmp_zero == CmpLT && op2_cmp_zero == CmpEQ) { |
| 13255 | can_cmp_zero = true; |
| 13256 | cmp_result = CmpLT; |
| 13257 | } else if (op1_cmp_zero == CmpEQ && op2_cmp_zero == CmpLT) { |
| 13258 | can_cmp_zero = true; |
| 13259 | cmp_result = CmpGT; |
| 13260 | } else if (op1_cmp_zero == CmpLT && op2_cmp_zero == CmpGT) { |
| 13261 | can_cmp_zero = true; |
| 13262 | cmp_result = CmpLT; |
| 13263 | } else if (op1_cmp_zero == CmpGT && op2_cmp_zero == CmpLT) { |
| 13264 | can_cmp_zero = true; |
| 13265 | cmp_result = CmpGT; |
| 13266 | } |
| 13267 | if (can_cmp_zero) { |
| 13268 | bool answer = resolve_cmp_op_id(op_id, cmp_result); |
| 13269 | return ir_const_bool(ira, &bin_op_instruction->base, answer); |
| 13270 | } |
| 13271 | } |
| 13272 | never_mind_just_calculate_it_normally: |
| 13273 | |
| 13185 | 13274 | ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad); |
| 13186 | 13275 | if (op1_val == nullptr) |
| 13187 | 13276 | return ira->codegen->invalid_instruction; |