mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-07 22:34:28 +00:00
stage2: implement @setFloatMode
This commit is contained in:
parent
585c160c20
commit
d75fa86d70
14 changed files with 494 additions and 122 deletions
|
|
@ -813,6 +813,7 @@ test "conversion to f32" {
|
||||||
test "conversion to f80" {
|
test "conversion to f80" {
|
||||||
if (builtin.zig_backend == .stage1 and builtin.cpu.arch != .x86_64)
|
if (builtin.zig_backend == .stage1 and builtin.cpu.arch != .x86_64)
|
||||||
return error.SkipZigTest; // https://github.com/ziglang/zig/issues/11408
|
return error.SkipZigTest; // https://github.com/ziglang/zig/issues/11408
|
||||||
|
if (std.debug.runtime_safety) return error.SkipZigTest;
|
||||||
|
|
||||||
const intToFloat = @import("./int_to_float.zig").intToFloat;
|
const intToFloat = @import("./int_to_float.zig").intToFloat;
|
||||||
|
|
||||||
|
|
|
||||||
97
src/Air.zig
97
src/Air.zig
|
|
@ -38,11 +38,15 @@ pub const Inst = struct {
|
||||||
/// is the same as both operands.
|
/// is the same as both operands.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
add,
|
add,
|
||||||
|
/// Same as `add` with optimized float mode.
|
||||||
|
add_optimized,
|
||||||
/// Integer addition. Wrapping is defined to be twos complement wrapping.
|
/// Integer addition. Wrapping is defined to be twos complement wrapping.
|
||||||
/// Both operands are guaranteed to be the same type, and the result type
|
/// Both operands are guaranteed to be the same type, and the result type
|
||||||
/// is the same as both operands.
|
/// is the same as both operands.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
addwrap,
|
addwrap,
|
||||||
|
/// Same as `addwrap` with optimized float mode.
|
||||||
|
addwrap_optimized,
|
||||||
/// Saturating integer addition.
|
/// Saturating integer addition.
|
||||||
/// Both operands are guaranteed to be the same type, and the result type
|
/// Both operands are guaranteed to be the same type, and the result type
|
||||||
/// is the same as both operands.
|
/// is the same as both operands.
|
||||||
|
|
@ -53,11 +57,15 @@ pub const Inst = struct {
|
||||||
/// is the same as both operands.
|
/// is the same as both operands.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
sub,
|
sub,
|
||||||
|
/// Same as `sub` with optimized float mode.
|
||||||
|
sub_optimized,
|
||||||
/// Integer subtraction. Wrapping is defined to be twos complement wrapping.
|
/// Integer subtraction. Wrapping is defined to be twos complement wrapping.
|
||||||
/// Both operands are guaranteed to be the same type, and the result type
|
/// Both operands are guaranteed to be the same type, and the result type
|
||||||
/// is the same as both operands.
|
/// is the same as both operands.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
subwrap,
|
subwrap,
|
||||||
|
/// Same as `sub` with optimized float mode.
|
||||||
|
subwrap_optimized,
|
||||||
/// Saturating integer subtraction.
|
/// Saturating integer subtraction.
|
||||||
/// Both operands are guaranteed to be the same type, and the result type
|
/// Both operands are guaranteed to be the same type, and the result type
|
||||||
/// is the same as both operands.
|
/// is the same as both operands.
|
||||||
|
|
@ -68,11 +76,15 @@ pub const Inst = struct {
|
||||||
/// is the same as both operands.
|
/// is the same as both operands.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
mul,
|
mul,
|
||||||
|
/// Same as `mul` with optimized float mode.
|
||||||
|
mul_optimized,
|
||||||
/// Integer multiplication. Wrapping is defined to be twos complement wrapping.
|
/// Integer multiplication. Wrapping is defined to be twos complement wrapping.
|
||||||
/// Both operands are guaranteed to be the same type, and the result type
|
/// Both operands are guaranteed to be the same type, and the result type
|
||||||
/// is the same as both operands.
|
/// is the same as both operands.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
mulwrap,
|
mulwrap,
|
||||||
|
/// Same as `mulwrap` with optimized float mode.
|
||||||
|
mulwrap_optimized,
|
||||||
/// Saturating integer multiplication.
|
/// Saturating integer multiplication.
|
||||||
/// Both operands are guaranteed to be the same type, and the result type
|
/// Both operands are guaranteed to be the same type, and the result type
|
||||||
/// is the same as both operands.
|
/// is the same as both operands.
|
||||||
|
|
@ -83,32 +95,44 @@ pub const Inst = struct {
|
||||||
/// is the same as both operands.
|
/// is the same as both operands.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
div_float,
|
div_float,
|
||||||
|
/// Same as `div_float` with optimized float mode.
|
||||||
|
div_float_optimized,
|
||||||
/// Truncating integer or float division. For integers, wrapping is undefined behavior.
|
/// Truncating integer or float division. For integers, wrapping is undefined behavior.
|
||||||
/// Both operands are guaranteed to be the same type, and the result type
|
/// Both operands are guaranteed to be the same type, and the result type
|
||||||
/// is the same as both operands.
|
/// is the same as both operands.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
div_trunc,
|
div_trunc,
|
||||||
|
/// Same as `div_trunc` with optimized float mode.
|
||||||
|
div_trunc_optimized,
|
||||||
/// Flooring integer or float division. For integers, wrapping is undefined behavior.
|
/// Flooring integer or float division. For integers, wrapping is undefined behavior.
|
||||||
/// Both operands are guaranteed to be the same type, and the result type
|
/// Both operands are guaranteed to be the same type, and the result type
|
||||||
/// is the same as both operands.
|
/// is the same as both operands.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
div_floor,
|
div_floor,
|
||||||
|
/// Same as `div_floor` with optimized float mode.
|
||||||
|
div_floor_optimized,
|
||||||
/// Integer or float division. Guaranteed no remainder.
|
/// Integer or float division. Guaranteed no remainder.
|
||||||
/// For integers, wrapping is undefined behavior.
|
/// For integers, wrapping is undefined behavior.
|
||||||
/// Both operands are guaranteed to be the same type, and the result type
|
/// Both operands are guaranteed to be the same type, and the result type
|
||||||
/// is the same as both operands.
|
/// is the same as both operands.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
div_exact,
|
div_exact,
|
||||||
|
/// Same as `div_exact` with optimized float mode.
|
||||||
|
div_exact_optimized,
|
||||||
/// Integer or float remainder division.
|
/// Integer or float remainder division.
|
||||||
/// Both operands are guaranteed to be the same type, and the result type
|
/// Both operands are guaranteed to be the same type, and the result type
|
||||||
/// is the same as both operands.
|
/// is the same as both operands.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
rem,
|
rem,
|
||||||
|
/// Same as `rem` with optimized float mode.
|
||||||
|
rem_optimized,
|
||||||
/// Integer or float modulus division.
|
/// Integer or float modulus division.
|
||||||
/// Both operands are guaranteed to be the same type, and the result type
|
/// Both operands are guaranteed to be the same type, and the result type
|
||||||
/// is the same as both operands.
|
/// is the same as both operands.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
mod,
|
mod,
|
||||||
|
/// Same as `mod` with optimized float mode.
|
||||||
|
mod_optimized,
|
||||||
/// Add an offset to a pointer, returning a new pointer.
|
/// Add an offset to a pointer, returning a new pointer.
|
||||||
/// The offset is in element type units, not bytes.
|
/// The offset is in element type units, not bytes.
|
||||||
/// Wrapping is undefined behavior.
|
/// Wrapping is undefined behavior.
|
||||||
|
|
@ -293,29 +317,45 @@ pub const Inst = struct {
|
||||||
/// LHS of zero.
|
/// LHS of zero.
|
||||||
/// Uses the `un_op` field.
|
/// Uses the `un_op` field.
|
||||||
neg,
|
neg,
|
||||||
|
/// Same as `neg` with optimized float mode.
|
||||||
|
neg_optimized,
|
||||||
|
|
||||||
/// `<`. Result type is always bool.
|
/// `<`. Result type is always bool.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
cmp_lt,
|
cmp_lt,
|
||||||
|
/// Same as `cmp_lt` with optimized float mode.
|
||||||
|
cmp_lt_optimized,
|
||||||
/// `<=`. Result type is always bool.
|
/// `<=`. Result type is always bool.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
cmp_lte,
|
cmp_lte,
|
||||||
|
/// Same as `cmp_lte` with optimized float mode.
|
||||||
|
cmp_lte_optimized,
|
||||||
/// `==`. Result type is always bool.
|
/// `==`. Result type is always bool.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
cmp_eq,
|
cmp_eq,
|
||||||
|
/// Same as `cmp_eq` with optimized float mode.
|
||||||
|
cmp_eq_optimized,
|
||||||
/// `>=`. Result type is always bool.
|
/// `>=`. Result type is always bool.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
cmp_gte,
|
cmp_gte,
|
||||||
|
/// Same as `cmp_gte` with optimized float mode.
|
||||||
|
cmp_gte_optimized,
|
||||||
/// `>`. Result type is always bool.
|
/// `>`. Result type is always bool.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
cmp_gt,
|
cmp_gt,
|
||||||
|
/// Same as `cmp_gt` with optimized float mode.
|
||||||
|
cmp_gt_optimized,
|
||||||
/// `!=`. Result type is always bool.
|
/// `!=`. Result type is always bool.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
cmp_neq,
|
cmp_neq,
|
||||||
|
/// Same as `cmp_neq` with optimized float mode.
|
||||||
|
cmp_neq_optimized,
|
||||||
/// Conditional between two vectors.
|
/// Conditional between two vectors.
|
||||||
/// Result type is always a vector of bools.
|
/// Result type is always a vector of bools.
|
||||||
/// Uses the `ty_pl` field, payload is `VectorCmp`.
|
/// Uses the `ty_pl` field, payload is `VectorCmp`.
|
||||||
cmp_vector,
|
cmp_vector,
|
||||||
|
/// Same as `cmp_vector` with optimized float mode.
|
||||||
|
cmp_vector_optimized,
|
||||||
|
|
||||||
/// Conditional branch.
|
/// Conditional branch.
|
||||||
/// Result type is always noreturn; no instructions in a block follow this one.
|
/// Result type is always noreturn; no instructions in a block follow this one.
|
||||||
|
|
@ -553,6 +593,8 @@ pub const Inst = struct {
|
||||||
/// Given a float operand, return the integer with the closest mathematical meaning.
|
/// Given a float operand, return the integer with the closest mathematical meaning.
|
||||||
/// Uses the `ty_op` field.
|
/// Uses the `ty_op` field.
|
||||||
float_to_int,
|
float_to_int,
|
||||||
|
/// Same as `float_to_int` with optimized float mode.
|
||||||
|
float_to_int_optimized,
|
||||||
/// Given an integer operand, return the float with the closest mathematical meaning.
|
/// Given an integer operand, return the float with the closest mathematical meaning.
|
||||||
/// Uses the `ty_op` field.
|
/// Uses the `ty_op` field.
|
||||||
int_to_float,
|
int_to_float,
|
||||||
|
|
@ -564,6 +606,8 @@ pub const Inst = struct {
|
||||||
/// * min, max, add, mul => integer or float
|
/// * min, max, add, mul => integer or float
|
||||||
/// Uses the `reduce` field.
|
/// Uses the `reduce` field.
|
||||||
reduce,
|
reduce,
|
||||||
|
/// Same as `reduce` with optimized float mode.
|
||||||
|
reduce_optimized,
|
||||||
/// Given an integer, bool, float, or pointer operand, return a vector with all elements
|
/// Given an integer, bool, float, or pointer operand, return a vector with all elements
|
||||||
/// equal to the scalar value.
|
/// equal to the scalar value.
|
||||||
/// Uses the `ty_op` field.
|
/// Uses the `ty_op` field.
|
||||||
|
|
@ -676,25 +720,25 @@ pub const Inst = struct {
|
||||||
/// Sets the operand as the current error return trace,
|
/// Sets the operand as the current error return trace,
|
||||||
set_err_return_trace,
|
set_err_return_trace,
|
||||||
|
|
||||||
pub fn fromCmpOp(op: std.math.CompareOperator) Tag {
|
pub fn fromCmpOp(op: std.math.CompareOperator, optimized: bool) Tag {
|
||||||
return switch (op) {
|
switch (op) {
|
||||||
.lt => .cmp_lt,
|
.lt => return if (optimized) .cmp_lt_optimized else .cmp_lt,
|
||||||
.lte => .cmp_lte,
|
.lte => return if (optimized) .cmp_lte_optimized else .cmp_lte,
|
||||||
.eq => .cmp_eq,
|
.eq => return if (optimized) .cmp_eq_optimized else .cmp_eq,
|
||||||
.gte => .cmp_gte,
|
.gte => return if (optimized) .cmp_gte_optimized else .cmp_gte,
|
||||||
.gt => .cmp_gt,
|
.gt => return if (optimized) .cmp_gt_optimized else .cmp_gt,
|
||||||
.neq => .cmp_neq,
|
.neq => return if (optimized) .cmp_neq_optimized else .cmp_neq,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toCmpOp(tag: Tag) ?std.math.CompareOperator {
|
pub fn toCmpOp(tag: Tag) ?std.math.CompareOperator {
|
||||||
return switch (tag) {
|
return switch (tag) {
|
||||||
.cmp_lt => .lt,
|
.cmp_lt, .cmp_lt_optimized => .lt,
|
||||||
.cmp_lte => .lte,
|
.cmp_lte, .cmp_lte_optimized => .lte,
|
||||||
.cmp_eq => .eq,
|
.cmp_eq, .cmp_eq_optimized => .eq,
|
||||||
.cmp_gte => .gte,
|
.cmp_gte, .cmp_gte_optimized => .gte,
|
||||||
.cmp_gt => .gt,
|
.cmp_gt, .cmp_gt_optimized => .gt,
|
||||||
.cmp_neq => .neq,
|
.cmp_neq, .cmp_neq_optimized => .neq,
|
||||||
else => null,
|
else => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -959,6 +1003,18 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
||||||
.max,
|
.max,
|
||||||
.bool_and,
|
.bool_and,
|
||||||
.bool_or,
|
.bool_or,
|
||||||
|
.add_optimized,
|
||||||
|
.addwrap_optimized,
|
||||||
|
.sub_optimized,
|
||||||
|
.subwrap_optimized,
|
||||||
|
.mul_optimized,
|
||||||
|
.mulwrap_optimized,
|
||||||
|
.div_float_optimized,
|
||||||
|
.div_trunc_optimized,
|
||||||
|
.div_floor_optimized,
|
||||||
|
.div_exact_optimized,
|
||||||
|
.rem_optimized,
|
||||||
|
.mod_optimized,
|
||||||
=> return air.typeOf(datas[inst].bin_op.lhs),
|
=> return air.typeOf(datas[inst].bin_op.lhs),
|
||||||
|
|
||||||
.sqrt,
|
.sqrt,
|
||||||
|
|
@ -976,6 +1032,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
||||||
.round,
|
.round,
|
||||||
.trunc_float,
|
.trunc_float,
|
||||||
.neg,
|
.neg,
|
||||||
|
.neg_optimized,
|
||||||
=> return air.typeOf(datas[inst].un_op),
|
=> return air.typeOf(datas[inst].un_op),
|
||||||
|
|
||||||
.cmp_lt,
|
.cmp_lt,
|
||||||
|
|
@ -984,6 +1041,12 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
||||||
.cmp_gte,
|
.cmp_gte,
|
||||||
.cmp_gt,
|
.cmp_gt,
|
||||||
.cmp_neq,
|
.cmp_neq,
|
||||||
|
.cmp_lt_optimized,
|
||||||
|
.cmp_lte_optimized,
|
||||||
|
.cmp_eq_optimized,
|
||||||
|
.cmp_gte_optimized,
|
||||||
|
.cmp_gt_optimized,
|
||||||
|
.cmp_neq_optimized,
|
||||||
.cmp_lt_errors_len,
|
.cmp_lt_errors_len,
|
||||||
.is_null,
|
.is_null,
|
||||||
.is_non_null,
|
.is_non_null,
|
||||||
|
|
@ -1018,6 +1081,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
||||||
.union_init,
|
.union_init,
|
||||||
.field_parent_ptr,
|
.field_parent_ptr,
|
||||||
.cmp_vector,
|
.cmp_vector,
|
||||||
|
.cmp_vector_optimized,
|
||||||
.add_with_overflow,
|
.add_with_overflow,
|
||||||
.sub_with_overflow,
|
.sub_with_overflow,
|
||||||
.mul_with_overflow,
|
.mul_with_overflow,
|
||||||
|
|
@ -1054,6 +1118,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
||||||
.struct_field_ptr_index_3,
|
.struct_field_ptr_index_3,
|
||||||
.array_to_slice,
|
.array_to_slice,
|
||||||
.float_to_int,
|
.float_to_int,
|
||||||
|
.float_to_int_optimized,
|
||||||
.int_to_float,
|
.int_to_float,
|
||||||
.splat,
|
.splat,
|
||||||
.get_union_tag,
|
.get_union_tag,
|
||||||
|
|
@ -1129,7 +1194,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
||||||
return ptr_ty.elemType();
|
return ptr_ty.elemType();
|
||||||
},
|
},
|
||||||
|
|
||||||
.reduce => return air.typeOf(datas[inst].reduce.operand).childType(),
|
.reduce, .reduce_optimized => return air.typeOf(datas[inst].reduce.operand).childType(),
|
||||||
|
|
||||||
.mul_add => return air.typeOf(datas[inst].pl_op.operand),
|
.mul_add => return air.typeOf(datas[inst].pl_op.operand),
|
||||||
.select => {
|
.select => {
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,25 @@ pub fn categorizeOperand(
|
||||||
.shr_exact,
|
.shr_exact,
|
||||||
.min,
|
.min,
|
||||||
.max,
|
.max,
|
||||||
|
.add_optimized,
|
||||||
|
.addwrap_optimized,
|
||||||
|
.sub_optimized,
|
||||||
|
.subwrap_optimized,
|
||||||
|
.mul_optimized,
|
||||||
|
.mulwrap_optimized,
|
||||||
|
.div_float_optimized,
|
||||||
|
.div_trunc_optimized,
|
||||||
|
.div_floor_optimized,
|
||||||
|
.div_exact_optimized,
|
||||||
|
.rem_optimized,
|
||||||
|
.mod_optimized,
|
||||||
|
.neg_optimized,
|
||||||
|
.cmp_lt_optimized,
|
||||||
|
.cmp_lte_optimized,
|
||||||
|
.cmp_eq_optimized,
|
||||||
|
.cmp_gte_optimized,
|
||||||
|
.cmp_gt_optimized,
|
||||||
|
.cmp_neq_optimized,
|
||||||
=> {
|
=> {
|
||||||
const o = air_datas[inst].bin_op;
|
const o = air_datas[inst].bin_op;
|
||||||
if (o.lhs == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
|
if (o.lhs == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
|
||||||
|
|
@ -239,6 +258,7 @@ pub fn categorizeOperand(
|
||||||
.struct_field_ptr_index_3,
|
.struct_field_ptr_index_3,
|
||||||
.array_to_slice,
|
.array_to_slice,
|
||||||
.float_to_int,
|
.float_to_int,
|
||||||
|
.float_to_int_optimized,
|
||||||
.int_to_float,
|
.int_to_float,
|
||||||
.get_union_tag,
|
.get_union_tag,
|
||||||
.clz,
|
.clz,
|
||||||
|
|
@ -381,12 +401,12 @@ pub fn categorizeOperand(
|
||||||
if (extra.b == operand_ref) return matchOperandSmallIndex(l, inst, 1, .none);
|
if (extra.b == operand_ref) return matchOperandSmallIndex(l, inst, 1, .none);
|
||||||
return .none;
|
return .none;
|
||||||
},
|
},
|
||||||
.reduce => {
|
.reduce, .reduce_optimized => {
|
||||||
const reduce = air_datas[inst].reduce;
|
const reduce = air_datas[inst].reduce;
|
||||||
if (reduce.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
|
if (reduce.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
|
||||||
return .none;
|
return .none;
|
||||||
},
|
},
|
||||||
.cmp_vector => {
|
.cmp_vector, .cmp_vector_optimized => {
|
||||||
const extra = air.extraData(Air.VectorCmp, air_datas[inst].ty_pl.payload).data;
|
const extra = air.extraData(Air.VectorCmp, air_datas[inst].ty_pl.payload).data;
|
||||||
if (extra.lhs == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
|
if (extra.lhs == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
|
||||||
if (extra.rhs == operand_ref) return matchOperandSmallIndex(l, inst, 1, .none);
|
if (extra.rhs == operand_ref) return matchOperandSmallIndex(l, inst, 1, .none);
|
||||||
|
|
@ -701,29 +721,47 @@ fn analyzeInst(
|
||||||
|
|
||||||
switch (inst_tags[inst]) {
|
switch (inst_tags[inst]) {
|
||||||
.add,
|
.add,
|
||||||
|
.add_optimized,
|
||||||
.addwrap,
|
.addwrap,
|
||||||
|
.addwrap_optimized,
|
||||||
.add_sat,
|
.add_sat,
|
||||||
.sub,
|
.sub,
|
||||||
|
.sub_optimized,
|
||||||
.subwrap,
|
.subwrap,
|
||||||
|
.subwrap_optimized,
|
||||||
.sub_sat,
|
.sub_sat,
|
||||||
.mul,
|
.mul,
|
||||||
|
.mul_optimized,
|
||||||
.mulwrap,
|
.mulwrap,
|
||||||
|
.mulwrap_optimized,
|
||||||
.mul_sat,
|
.mul_sat,
|
||||||
.div_float,
|
.div_float,
|
||||||
|
.div_float_optimized,
|
||||||
.div_trunc,
|
.div_trunc,
|
||||||
|
.div_trunc_optimized,
|
||||||
.div_floor,
|
.div_floor,
|
||||||
|
.div_floor_optimized,
|
||||||
.div_exact,
|
.div_exact,
|
||||||
|
.div_exact_optimized,
|
||||||
.rem,
|
.rem,
|
||||||
|
.rem_optimized,
|
||||||
.mod,
|
.mod,
|
||||||
|
.mod_optimized,
|
||||||
.bit_and,
|
.bit_and,
|
||||||
.bit_or,
|
.bit_or,
|
||||||
.xor,
|
.xor,
|
||||||
.cmp_lt,
|
.cmp_lt,
|
||||||
|
.cmp_lt_optimized,
|
||||||
.cmp_lte,
|
.cmp_lte,
|
||||||
|
.cmp_lte_optimized,
|
||||||
.cmp_eq,
|
.cmp_eq,
|
||||||
|
.cmp_eq_optimized,
|
||||||
.cmp_gte,
|
.cmp_gte,
|
||||||
|
.cmp_gte_optimized,
|
||||||
.cmp_gt,
|
.cmp_gt,
|
||||||
|
.cmp_gt_optimized,
|
||||||
.cmp_neq,
|
.cmp_neq,
|
||||||
|
.cmp_neq_optimized,
|
||||||
.bool_and,
|
.bool_and,
|
||||||
.bool_or,
|
.bool_or,
|
||||||
.store,
|
.store,
|
||||||
|
|
@ -794,6 +832,7 @@ fn analyzeInst(
|
||||||
.struct_field_ptr_index_3,
|
.struct_field_ptr_index_3,
|
||||||
.array_to_slice,
|
.array_to_slice,
|
||||||
.float_to_int,
|
.float_to_int,
|
||||||
|
.float_to_int_optimized,
|
||||||
.int_to_float,
|
.int_to_float,
|
||||||
.get_union_tag,
|
.get_union_tag,
|
||||||
.clz,
|
.clz,
|
||||||
|
|
@ -836,6 +875,7 @@ fn analyzeInst(
|
||||||
.round,
|
.round,
|
||||||
.trunc_float,
|
.trunc_float,
|
||||||
.neg,
|
.neg,
|
||||||
|
.neg_optimized,
|
||||||
.cmp_lt_errors_len,
|
.cmp_lt_errors_len,
|
||||||
.set_err_return_trace,
|
.set_err_return_trace,
|
||||||
=> {
|
=> {
|
||||||
|
|
@ -903,11 +943,11 @@ fn analyzeInst(
|
||||||
const extra = a.air.extraData(Air.Shuffle, inst_datas[inst].ty_pl.payload).data;
|
const extra = a.air.extraData(Air.Shuffle, inst_datas[inst].ty_pl.payload).data;
|
||||||
return trackOperands(a, new_set, inst, main_tomb, .{ extra.a, extra.b, .none });
|
return trackOperands(a, new_set, inst, main_tomb, .{ extra.a, extra.b, .none });
|
||||||
},
|
},
|
||||||
.reduce => {
|
.reduce, .reduce_optimized => {
|
||||||
const reduce = inst_datas[inst].reduce;
|
const reduce = inst_datas[inst].reduce;
|
||||||
return trackOperands(a, new_set, inst, main_tomb, .{ reduce.operand, .none, .none });
|
return trackOperands(a, new_set, inst, main_tomb, .{ reduce.operand, .none, .none });
|
||||||
},
|
},
|
||||||
.cmp_vector => {
|
.cmp_vector, .cmp_vector_optimized => {
|
||||||
const extra = a.air.extraData(Air.VectorCmp, inst_datas[inst].ty_pl.payload).data;
|
const extra = a.air.extraData(Air.VectorCmp, inst_datas[inst].ty_pl.payload).data;
|
||||||
return trackOperands(a, new_set, inst, main_tomb, .{ extra.lhs, extra.rhs, .none });
|
return trackOperands(a, new_set, inst, main_tomb, .{ extra.lhs, extra.rhs, .none });
|
||||||
},
|
},
|
||||||
|
|
|
||||||
142
src/Sema.zig
142
src/Sema.zig
|
|
@ -144,6 +144,9 @@ pub const Block = struct {
|
||||||
/// when null, it is determined by build mode, changed by @setRuntimeSafety
|
/// when null, it is determined by build mode, changed by @setRuntimeSafety
|
||||||
want_safety: ?bool = null,
|
want_safety: ?bool = null,
|
||||||
|
|
||||||
|
/// What mode to generate float operations in, set by @setFloatMode
|
||||||
|
float_mode: std.builtin.FloatMode = .Strict,
|
||||||
|
|
||||||
c_import_buf: ?*std.ArrayList(u8) = null,
|
c_import_buf: ?*std.ArrayList(u8) = null,
|
||||||
|
|
||||||
/// type of `err` in `else => |err|`
|
/// type of `err` in `else => |err|`
|
||||||
|
|
@ -206,6 +209,7 @@ pub const Block = struct {
|
||||||
.runtime_loop = parent.runtime_loop,
|
.runtime_loop = parent.runtime_loop,
|
||||||
.runtime_index = parent.runtime_index,
|
.runtime_index = parent.runtime_index,
|
||||||
.want_safety = parent.want_safety,
|
.want_safety = parent.want_safety,
|
||||||
|
.float_mode = parent.float_mode,
|
||||||
.c_import_buf = parent.c_import_buf,
|
.c_import_buf = parent.c_import_buf,
|
||||||
.switch_else_err_ty = parent.switch_else_err_ty,
|
.switch_else_err_ty = parent.switch_else_err_ty,
|
||||||
};
|
};
|
||||||
|
|
@ -414,7 +418,7 @@ pub const Block = struct {
|
||||||
|
|
||||||
fn addCmpVector(block: *Block, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref, cmp_op: std.math.CompareOperator, vector_ty: Air.Inst.Ref) !Air.Inst.Ref {
|
fn addCmpVector(block: *Block, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref, cmp_op: std.math.CompareOperator, vector_ty: Air.Inst.Ref) !Air.Inst.Ref {
|
||||||
return block.addInst(.{
|
return block.addInst(.{
|
||||||
.tag = .cmp_vector,
|
.tag = if (block.float_mode == .Optimized) .cmp_vector_optimized else .cmp_vector,
|
||||||
.data = .{ .ty_pl = .{
|
.data = .{ .ty_pl = .{
|
||||||
.ty = vector_ty,
|
.ty = vector_ty,
|
||||||
.payload = try block.sema.addExtra(Air.VectorCmp{
|
.payload = try block.sema.addExtra(Air.VectorCmp{
|
||||||
|
|
@ -714,10 +718,10 @@ fn analyzeBodyInner(
|
||||||
.closure_get => try sema.zirClosureGet(block, inst),
|
.closure_get => try sema.zirClosureGet(block, inst),
|
||||||
.cmp_lt => try sema.zirCmp(block, inst, .lt),
|
.cmp_lt => try sema.zirCmp(block, inst, .lt),
|
||||||
.cmp_lte => try sema.zirCmp(block, inst, .lte),
|
.cmp_lte => try sema.zirCmp(block, inst, .lte),
|
||||||
.cmp_eq => try sema.zirCmpEq(block, inst, .eq, .cmp_eq),
|
.cmp_eq => try sema.zirCmpEq(block, inst, .eq, Air.Inst.Tag.fromCmpOp(.eq, block.float_mode == .Optimized)),
|
||||||
.cmp_gte => try sema.zirCmp(block, inst, .gte),
|
.cmp_gte => try sema.zirCmp(block, inst, .gte),
|
||||||
.cmp_gt => try sema.zirCmp(block, inst, .gt),
|
.cmp_gt => try sema.zirCmp(block, inst, .gt),
|
||||||
.cmp_neq => try sema.zirCmpEq(block, inst, .neq, .cmp_neq),
|
.cmp_neq => try sema.zirCmpEq(block, inst, .neq, Air.Inst.Tag.fromCmpOp(.neq, block.float_mode == .Optimized)),
|
||||||
.coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),
|
.coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),
|
||||||
.decl_ref => try sema.zirDeclRef(block, inst),
|
.decl_ref => try sema.zirDeclRef(block, inst),
|
||||||
.decl_val => try sema.zirDeclVal(block, inst),
|
.decl_val => try sema.zirDeclVal(block, inst),
|
||||||
|
|
@ -4705,6 +4709,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
|
||||||
.inlining = parent_block.inlining,
|
.inlining = parent_block.inlining,
|
||||||
.is_comptime = parent_block.is_comptime,
|
.is_comptime = parent_block.is_comptime,
|
||||||
.want_safety = parent_block.want_safety,
|
.want_safety = parent_block.want_safety,
|
||||||
|
.float_mode = parent_block.float_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
defer child_block.instructions.deinit(gpa);
|
defer child_block.instructions.deinit(gpa);
|
||||||
|
|
@ -5042,13 +5047,7 @@ fn zirSetCold(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi
|
||||||
fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
|
fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
|
||||||
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
|
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
|
||||||
const src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
|
const src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
|
||||||
const float_mode = try sema.resolveBuiltinEnum(block, src, extra.operand, "FloatMode", "operand to @setFloatMode must be comptime known");
|
block.float_mode = try sema.resolveBuiltinEnum(block, src, extra.operand, "FloatMode", "operand to @setFloatMode must be comptime known");
|
||||||
switch (float_mode) {
|
|
||||||
.Strict => return,
|
|
||||||
.Optimized => {
|
|
||||||
// TODO implement optimized float mode
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zirSetRuntimeSafety(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
|
fn zirSetRuntimeSafety(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
|
||||||
|
|
@ -8092,7 +8091,7 @@ fn intCast(
|
||||||
const ok = if (is_vector) ok: {
|
const ok = if (is_vector) ok: {
|
||||||
const is_in_range = try block.addCmpVector(diff_unsigned, dest_range, .lte, try sema.addType(operand_ty));
|
const is_in_range = try block.addCmpVector(diff_unsigned, dest_range, .lte, try sema.addType(operand_ty));
|
||||||
const all_in_range = try block.addInst(.{
|
const all_in_range = try block.addInst(.{
|
||||||
.tag = .reduce,
|
.tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
|
||||||
.data = .{ .reduce = .{
|
.data = .{ .reduce = .{
|
||||||
.operand = is_in_range,
|
.operand = is_in_range,
|
||||||
.operation = .And,
|
.operation = .And,
|
||||||
|
|
@ -8109,7 +8108,7 @@ fn intCast(
|
||||||
const ok = if (is_vector) ok: {
|
const ok = if (is_vector) ok: {
|
||||||
const is_in_range = try block.addCmpVector(diff, dest_max, .lte, try sema.addType(operand_ty));
|
const is_in_range = try block.addCmpVector(diff, dest_max, .lte, try sema.addType(operand_ty));
|
||||||
const all_in_range = try block.addInst(.{
|
const all_in_range = try block.addInst(.{
|
||||||
.tag = .reduce,
|
.tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
|
||||||
.data = .{ .reduce = .{
|
.data = .{ .reduce = .{
|
||||||
.operand = is_in_range,
|
.operand = is_in_range,
|
||||||
.operation = .And,
|
.operation = .And,
|
||||||
|
|
@ -8130,7 +8129,7 @@ fn intCast(
|
||||||
const zero_inst = try sema.addConstant(operand_ty, zero_val);
|
const zero_inst = try sema.addConstant(operand_ty, zero_val);
|
||||||
const is_in_range = try block.addCmpVector(operand, zero_inst, .gte, try sema.addType(operand_ty));
|
const is_in_range = try block.addCmpVector(operand, zero_inst, .gte, try sema.addType(operand_ty));
|
||||||
const all_in_range = try block.addInst(.{
|
const all_in_range = try block.addInst(.{
|
||||||
.tag = .reduce,
|
.tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
|
||||||
.data = .{ .reduce = .{
|
.data = .{ .reduce = .{
|
||||||
.operand = is_in_range,
|
.operand = is_in_range,
|
||||||
.operation = .And,
|
.operation = .And,
|
||||||
|
|
@ -9391,7 +9390,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||||
} else {
|
} else {
|
||||||
for (items) |item_ref| {
|
for (items) |item_ref| {
|
||||||
const item = try sema.resolveInst(item_ref);
|
const item = try sema.resolveInst(item_ref);
|
||||||
const cmp_ok = try case_block.addBinOp(.cmp_eq, operand, item);
|
const cmp_ok = try case_block.addBinOp(if (case_block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, operand, item);
|
||||||
if (any_ok != .none) {
|
if (any_ok != .none) {
|
||||||
any_ok = try case_block.addBinOp(.bool_or, any_ok, cmp_ok);
|
any_ok = try case_block.addBinOp(.bool_or, any_ok, cmp_ok);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -9411,12 +9410,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||||
|
|
||||||
// operand >= first and operand <= last
|
// operand >= first and operand <= last
|
||||||
const range_first_ok = try case_block.addBinOp(
|
const range_first_ok = try case_block.addBinOp(
|
||||||
.cmp_gte,
|
if (case_block.float_mode == .Optimized) .cmp_gte_optimized else .cmp_gte,
|
||||||
operand,
|
operand,
|
||||||
item_first,
|
item_first,
|
||||||
);
|
);
|
||||||
const range_last_ok = try case_block.addBinOp(
|
const range_last_ok = try case_block.addBinOp(
|
||||||
.cmp_lte,
|
if (case_block.float_mode == .Optimized) .cmp_lte_optimized else .cmp_lte,
|
||||||
operand,
|
operand,
|
||||||
item_last,
|
item_last,
|
||||||
);
|
);
|
||||||
|
|
@ -10023,7 +10022,7 @@ fn zirShl(
|
||||||
const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty);
|
const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty);
|
||||||
const any_ov_bit = if (lhs_ty.zigTypeTag() == .Vector)
|
const any_ov_bit = if (lhs_ty.zigTypeTag() == .Vector)
|
||||||
try block.addInst(.{
|
try block.addInst(.{
|
||||||
.tag = .reduce,
|
.tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
|
||||||
.data = .{ .reduce = .{
|
.data = .{ .reduce = .{
|
||||||
.operand = ov_bit,
|
.operand = ov_bit,
|
||||||
.operation = .Or,
|
.operation = .Or,
|
||||||
|
|
@ -10120,7 +10119,7 @@ fn zirShr(
|
||||||
const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: {
|
const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: {
|
||||||
const eql = try block.addCmpVector(lhs, back, .eq, try sema.addType(rhs_ty));
|
const eql = try block.addCmpVector(lhs, back, .eq, try sema.addType(rhs_ty));
|
||||||
break :ok try block.addInst(.{
|
break :ok try block.addInst(.{
|
||||||
.tag = .reduce,
|
.tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
|
||||||
.data = .{ .reduce = .{
|
.data = .{ .reduce = .{
|
||||||
.operand = eql,
|
.operand = eql,
|
||||||
.operation = .And,
|
.operation = .And,
|
||||||
|
|
@ -10719,7 +10718,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
|
||||||
return sema.addConstant(rhs_ty, try rhs_val.floatNeg(rhs_ty, sema.arena, target));
|
return sema.addConstant(rhs_ty, try rhs_val.floatNeg(rhs_ty, sema.arena, target));
|
||||||
}
|
}
|
||||||
try sema.requireRuntimeBlock(block, src, null);
|
try sema.requireRuntimeBlock(block, src, null);
|
||||||
return block.addUnOp(.neg, rhs);
|
return block.addUnOp(if (block.float_mode == .Optimized) .neg_optimized else .neg, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const lhs = if (rhs_ty.zigTypeTag() == .Vector)
|
const lhs = if (rhs_ty.zigTypeTag() == .Vector)
|
||||||
|
|
@ -11078,6 +11077,7 @@ fn analyzeArithmetic(
|
||||||
return casted_lhs;
|
return casted_lhs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .add_optimized else .add;
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (lhs_val.isUndef()) {
|
if (lhs_val.isUndef()) {
|
||||||
if (is_int) {
|
if (is_int) {
|
||||||
|
|
@ -11100,8 +11100,8 @@ fn analyzeArithmetic(
|
||||||
try sema.floatAdd(lhs_val, rhs_val, resolved_type),
|
try sema.floatAdd(lhs_val, rhs_val, resolved_type),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else break :rs .{ .src = rhs_src, .air_tag = .add };
|
} else break :rs .{ .src = rhs_src, .air_tag = air_tag };
|
||||||
} else break :rs .{ .src = lhs_src, .air_tag = .add };
|
} else break :rs .{ .src = lhs_src, .air_tag = air_tag };
|
||||||
},
|
},
|
||||||
.addwrap => {
|
.addwrap => {
|
||||||
// Integers only; floats are checked above.
|
// Integers only; floats are checked above.
|
||||||
|
|
@ -11112,6 +11112,7 @@ fn analyzeArithmetic(
|
||||||
return casted_rhs;
|
return casted_rhs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .addwrap_optimized else .addwrap;
|
||||||
if (maybe_rhs_val) |rhs_val| {
|
if (maybe_rhs_val) |rhs_val| {
|
||||||
if (rhs_val.isUndef()) {
|
if (rhs_val.isUndef()) {
|
||||||
return sema.addConstUndef(resolved_type);
|
return sema.addConstUndef(resolved_type);
|
||||||
|
|
@ -11124,8 +11125,8 @@ fn analyzeArithmetic(
|
||||||
resolved_type,
|
resolved_type,
|
||||||
try sema.numberAddWrap(block, src, lhs_val, rhs_val, resolved_type),
|
try sema.numberAddWrap(block, src, lhs_val, rhs_val, resolved_type),
|
||||||
);
|
);
|
||||||
} else break :rs .{ .src = lhs_src, .air_tag = .addwrap };
|
} else break :rs .{ .src = lhs_src, .air_tag = air_tag };
|
||||||
} else break :rs .{ .src = rhs_src, .air_tag = .addwrap };
|
} else break :rs .{ .src = rhs_src, .air_tag = air_tag };
|
||||||
},
|
},
|
||||||
.add_sat => {
|
.add_sat => {
|
||||||
// Integers only; floats are checked above.
|
// Integers only; floats are checked above.
|
||||||
|
|
@ -11173,6 +11174,7 @@ fn analyzeArithmetic(
|
||||||
return casted_lhs;
|
return casted_lhs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .sub_optimized else .sub;
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (lhs_val.isUndef()) {
|
if (lhs_val.isUndef()) {
|
||||||
if (is_int) {
|
if (is_int) {
|
||||||
|
|
@ -11195,8 +11197,8 @@ fn analyzeArithmetic(
|
||||||
try sema.floatSub(lhs_val, rhs_val, resolved_type),
|
try sema.floatSub(lhs_val, rhs_val, resolved_type),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else break :rs .{ .src = rhs_src, .air_tag = .sub };
|
} else break :rs .{ .src = rhs_src, .air_tag = air_tag };
|
||||||
} else break :rs .{ .src = lhs_src, .air_tag = .sub };
|
} else break :rs .{ .src = lhs_src, .air_tag = air_tag };
|
||||||
},
|
},
|
||||||
.subwrap => {
|
.subwrap => {
|
||||||
// Integers only; floats are checked above.
|
// Integers only; floats are checked above.
|
||||||
|
|
@ -11210,6 +11212,7 @@ fn analyzeArithmetic(
|
||||||
return casted_lhs;
|
return casted_lhs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .subwrap_optimized else .subwrap;
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (lhs_val.isUndef()) {
|
if (lhs_val.isUndef()) {
|
||||||
return sema.addConstUndef(resolved_type);
|
return sema.addConstUndef(resolved_type);
|
||||||
|
|
@ -11219,8 +11222,8 @@ fn analyzeArithmetic(
|
||||||
resolved_type,
|
resolved_type,
|
||||||
try sema.numberSubWrap(block, src, lhs_val, rhs_val, resolved_type),
|
try sema.numberSubWrap(block, src, lhs_val, rhs_val, resolved_type),
|
||||||
);
|
);
|
||||||
} else break :rs .{ .src = rhs_src, .air_tag = .subwrap };
|
} else break :rs .{ .src = rhs_src, .air_tag = air_tag };
|
||||||
} else break :rs .{ .src = lhs_src, .air_tag = .subwrap };
|
} else break :rs .{ .src = lhs_src, .air_tag = air_tag };
|
||||||
},
|
},
|
||||||
.sub_sat => {
|
.sub_sat => {
|
||||||
// Integers only; floats are checked above.
|
// Integers only; floats are checked above.
|
||||||
|
|
@ -11327,14 +11330,14 @@ fn analyzeArithmetic(
|
||||||
if (is_int) {
|
if (is_int) {
|
||||||
break :rs .{ .src = rhs_src, .air_tag = .div_trunc };
|
break :rs .{ .src = rhs_src, .air_tag = .div_trunc };
|
||||||
} else {
|
} else {
|
||||||
break :rs .{ .src = rhs_src, .air_tag = .div_float };
|
break :rs .{ .src = rhs_src, .air_tag = if (block.float_mode == .Optimized) .div_float_optimized else .div_float };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (is_int) {
|
if (is_int) {
|
||||||
break :rs .{ .src = lhs_src, .air_tag = .div_trunc };
|
break :rs .{ .src = lhs_src, .air_tag = .div_trunc };
|
||||||
} else {
|
} else {
|
||||||
break :rs .{ .src = lhs_src, .air_tag = .div_float };
|
break :rs .{ .src = lhs_src, .air_tag = if (block.float_mode == .Optimized) .div_float_optimized else .div_float };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -11373,6 +11376,7 @@ fn analyzeArithmetic(
|
||||||
return sema.failWithDivideByZero(block, rhs_src);
|
return sema.failWithDivideByZero(block, rhs_src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .div_trunc_optimized else .div_trunc;
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (lhs_val.isUndef()) {
|
if (lhs_val.isUndef()) {
|
||||||
if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
|
if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
|
||||||
|
|
@ -11398,8 +11402,8 @@ fn analyzeArithmetic(
|
||||||
try lhs_val.floatDivTrunc(rhs_val, resolved_type, sema.arena, target),
|
try lhs_val.floatDivTrunc(rhs_val, resolved_type, sema.arena, target),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else break :rs .{ .src = rhs_src, .air_tag = .div_trunc };
|
} else break :rs .{ .src = rhs_src, .air_tag = air_tag };
|
||||||
} else break :rs .{ .src = lhs_src, .air_tag = .div_trunc };
|
} else break :rs .{ .src = lhs_src, .air_tag = air_tag };
|
||||||
},
|
},
|
||||||
.div_floor => {
|
.div_floor => {
|
||||||
// For integers:
|
// For integers:
|
||||||
|
|
@ -11436,6 +11440,7 @@ fn analyzeArithmetic(
|
||||||
return sema.failWithDivideByZero(block, rhs_src);
|
return sema.failWithDivideByZero(block, rhs_src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .div_floor_optimized else .div_floor;
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (lhs_val.isUndef()) {
|
if (lhs_val.isUndef()) {
|
||||||
if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
|
if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
|
||||||
|
|
@ -11461,8 +11466,8 @@ fn analyzeArithmetic(
|
||||||
try lhs_val.floatDivFloor(rhs_val, resolved_type, sema.arena, target),
|
try lhs_val.floatDivFloor(rhs_val, resolved_type, sema.arena, target),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else break :rs .{ .src = rhs_src, .air_tag = .div_floor };
|
} else break :rs .{ .src = rhs_src, .air_tag = air_tag };
|
||||||
} else break :rs .{ .src = lhs_src, .air_tag = .div_floor };
|
} else break :rs .{ .src = lhs_src, .air_tag = air_tag };
|
||||||
},
|
},
|
||||||
.div_exact => {
|
.div_exact => {
|
||||||
// For integers:
|
// For integers:
|
||||||
|
|
@ -11498,6 +11503,7 @@ fn analyzeArithmetic(
|
||||||
return sema.failWithDivideByZero(block, rhs_src);
|
return sema.failWithDivideByZero(block, rhs_src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .div_exact_optimized else .div_exact;
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (maybe_rhs_val) |rhs_val| {
|
if (maybe_rhs_val) |rhs_val| {
|
||||||
if (is_int) {
|
if (is_int) {
|
||||||
|
|
@ -11513,8 +11519,8 @@ fn analyzeArithmetic(
|
||||||
try lhs_val.floatDiv(rhs_val, resolved_type, sema.arena, target),
|
try lhs_val.floatDiv(rhs_val, resolved_type, sema.arena, target),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else break :rs .{ .src = rhs_src, .air_tag = .div_exact };
|
} else break :rs .{ .src = rhs_src, .air_tag = air_tag };
|
||||||
} else break :rs .{ .src = lhs_src, .air_tag = .div_exact };
|
} else break :rs .{ .src = lhs_src, .air_tag = air_tag };
|
||||||
},
|
},
|
||||||
.mul => {
|
.mul => {
|
||||||
// For integers:
|
// For integers:
|
||||||
|
|
@ -11535,6 +11541,7 @@ fn analyzeArithmetic(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .mul_optimized else .mul;
|
||||||
if (maybe_rhs_val) |rhs_val| {
|
if (maybe_rhs_val) |rhs_val| {
|
||||||
if (rhs_val.isUndef()) {
|
if (rhs_val.isUndef()) {
|
||||||
if (is_int) {
|
if (is_int) {
|
||||||
|
|
@ -11570,8 +11577,8 @@ fn analyzeArithmetic(
|
||||||
try lhs_val.floatMul(rhs_val, resolved_type, sema.arena, target),
|
try lhs_val.floatMul(rhs_val, resolved_type, sema.arena, target),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else break :rs .{ .src = lhs_src, .air_tag = .mul };
|
} else break :rs .{ .src = lhs_src, .air_tag = air_tag };
|
||||||
} else break :rs .{ .src = rhs_src, .air_tag = .mul };
|
} else break :rs .{ .src = rhs_src, .air_tag = air_tag };
|
||||||
},
|
},
|
||||||
.mulwrap => {
|
.mulwrap => {
|
||||||
// Integers only; floats are handled above.
|
// Integers only; floats are handled above.
|
||||||
|
|
@ -11588,6 +11595,7 @@ fn analyzeArithmetic(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .mulwrap_optimized else .mulwrap;
|
||||||
if (maybe_rhs_val) |rhs_val| {
|
if (maybe_rhs_val) |rhs_val| {
|
||||||
if (rhs_val.isUndef()) {
|
if (rhs_val.isUndef()) {
|
||||||
return sema.addConstUndef(resolved_type);
|
return sema.addConstUndef(resolved_type);
|
||||||
|
|
@ -11606,8 +11614,8 @@ fn analyzeArithmetic(
|
||||||
resolved_type,
|
resolved_type,
|
||||||
try lhs_val.numberMulWrap(rhs_val, resolved_type, sema.arena, target),
|
try lhs_val.numberMulWrap(rhs_val, resolved_type, sema.arena, target),
|
||||||
);
|
);
|
||||||
} else break :rs .{ .src = lhs_src, .air_tag = .mulwrap };
|
} else break :rs .{ .src = lhs_src, .air_tag = air_tag };
|
||||||
} else break :rs .{ .src = rhs_src, .air_tag = .mulwrap };
|
} else break :rs .{ .src = rhs_src, .air_tag = air_tag };
|
||||||
},
|
},
|
||||||
.mul_sat => {
|
.mul_sat => {
|
||||||
// Integers only; floats are checked above.
|
// Integers only; floats are checked above.
|
||||||
|
|
@ -11777,6 +11785,7 @@ fn analyzeArithmetic(
|
||||||
return sema.failWithDivideByZero(block, rhs_src);
|
return sema.failWithDivideByZero(block, rhs_src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .rem_optimized else .rem;
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (lhs_val.isUndef()) {
|
if (lhs_val.isUndef()) {
|
||||||
return sema.addConstUndef(resolved_type);
|
return sema.addConstUndef(resolved_type);
|
||||||
|
|
@ -11786,8 +11795,8 @@ fn analyzeArithmetic(
|
||||||
resolved_type,
|
resolved_type,
|
||||||
try lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target),
|
try lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target),
|
||||||
);
|
);
|
||||||
} else break :rs .{ .src = rhs_src, .air_tag = .rem };
|
} else break :rs .{ .src = rhs_src, .air_tag = air_tag };
|
||||||
} else break :rs .{ .src = lhs_src, .air_tag = .rem };
|
} else break :rs .{ .src = lhs_src, .air_tag = air_tag };
|
||||||
},
|
},
|
||||||
.mod => {
|
.mod => {
|
||||||
// For integers:
|
// For integers:
|
||||||
|
|
@ -11834,6 +11843,7 @@ fn analyzeArithmetic(
|
||||||
return sema.failWithDivideByZero(block, rhs_src);
|
return sema.failWithDivideByZero(block, rhs_src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .mod_optimized else .mod;
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (lhs_val.isUndef()) {
|
if (lhs_val.isUndef()) {
|
||||||
return sema.addConstUndef(resolved_type);
|
return sema.addConstUndef(resolved_type);
|
||||||
|
|
@ -11843,8 +11853,8 @@ fn analyzeArithmetic(
|
||||||
resolved_type,
|
resolved_type,
|
||||||
try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, target),
|
try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, target),
|
||||||
);
|
);
|
||||||
} else break :rs .{ .src = rhs_src, .air_tag = .mod };
|
} else break :rs .{ .src = rhs_src, .air_tag = air_tag };
|
||||||
} else break :rs .{ .src = lhs_src, .air_tag = .mod };
|
} else break :rs .{ .src = lhs_src, .air_tag = air_tag };
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
|
|
@ -11874,7 +11884,7 @@ fn analyzeArithmetic(
|
||||||
const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty);
|
const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty);
|
||||||
const any_ov_bit = if (resolved_type.zigTypeTag() == .Vector)
|
const any_ov_bit = if (resolved_type.zigTypeTag() == .Vector)
|
||||||
try block.addInst(.{
|
try block.addInst(.{
|
||||||
.tag = .reduce,
|
.tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
|
||||||
.data = .{ .reduce = .{
|
.data = .{ .reduce = .{
|
||||||
.operand = ov_bit,
|
.operand = ov_bit,
|
||||||
.operation = .Or,
|
.operation = .Or,
|
||||||
|
|
@ -11890,13 +11900,17 @@ fn analyzeArithmetic(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (rs.air_tag) {
|
switch (rs.air_tag) {
|
||||||
.div_float, .div_exact, .div_trunc, .div_floor => {
|
// zig fmt: off
|
||||||
|
.div_float, .div_exact, .div_trunc, .div_floor, .div_float_optimized,
|
||||||
|
.div_exact_optimized, .div_trunc_optimized, .div_floor_optimized
|
||||||
|
// zig fmt: on
|
||||||
|
=> if (scalar_tag == .Int or block.float_mode == .Optimized) {
|
||||||
const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {
|
const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {
|
||||||
const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
|
const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
|
||||||
const zero = try sema.addConstant(sema.typeOf(casted_rhs), zero_val);
|
const zero = try sema.addConstant(sema.typeOf(casted_rhs), zero_val);
|
||||||
const ok = try block.addCmpVector(casted_rhs, zero, .neq, try sema.addType(resolved_type));
|
const ok = try block.addCmpVector(casted_rhs, zero, .neq, try sema.addType(resolved_type));
|
||||||
break :ok try block.addInst(.{
|
break :ok try block.addInst(.{
|
||||||
.tag = .reduce,
|
.tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
|
||||||
.data = .{ .reduce = .{
|
.data = .{ .reduce = .{
|
||||||
.operand = ok,
|
.operand = ok,
|
||||||
.operation = .And,
|
.operation = .And,
|
||||||
|
|
@ -11904,17 +11918,17 @@ fn analyzeArithmetic(
|
||||||
});
|
});
|
||||||
} else ok: {
|
} else ok: {
|
||||||
const zero = try sema.addConstant(sema.typeOf(casted_rhs), Value.zero);
|
const zero = try sema.addConstant(sema.typeOf(casted_rhs), Value.zero);
|
||||||
break :ok try block.addBinOp(.cmp_neq, casted_rhs, zero);
|
break :ok try block.addBinOp(if (block.float_mode == .Optimized) .cmp_neq_optimized else .cmp_neq, casted_rhs, zero);
|
||||||
};
|
};
|
||||||
try sema.addSafetyCheck(block, ok, .divide_by_zero);
|
try sema.addSafetyCheck(block, ok, .divide_by_zero);
|
||||||
},
|
},
|
||||||
.rem, .mod => {
|
.rem, .mod, .rem_optimized, .mod_optimized => {
|
||||||
const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {
|
const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {
|
||||||
const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
|
const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
|
||||||
const zero = try sema.addConstant(sema.typeOf(casted_rhs), zero_val);
|
const zero = try sema.addConstant(sema.typeOf(casted_rhs), zero_val);
|
||||||
const ok = try block.addCmpVector(casted_rhs, zero, if (scalar_tag == .Int) .gt else .neq, try sema.addType(resolved_type));
|
const ok = try block.addCmpVector(casted_rhs, zero, if (scalar_tag == .Int) .gt else .neq, try sema.addType(resolved_type));
|
||||||
break :ok try block.addInst(.{
|
break :ok try block.addInst(.{
|
||||||
.tag = .reduce,
|
.tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
|
||||||
.data = .{ .reduce = .{
|
.data = .{ .reduce = .{
|
||||||
.operand = ok,
|
.operand = ok,
|
||||||
.operation = .And,
|
.operation = .And,
|
||||||
|
|
@ -11922,13 +11936,19 @@ fn analyzeArithmetic(
|
||||||
});
|
});
|
||||||
} else ok: {
|
} else ok: {
|
||||||
const zero = try sema.addConstant(sema.typeOf(casted_rhs), Value.zero);
|
const zero = try sema.addConstant(sema.typeOf(casted_rhs), Value.zero);
|
||||||
break :ok try block.addBinOp(if (scalar_tag == .Int) .cmp_gt else .cmp_neq, casted_rhs, zero);
|
const air_tag = if (scalar_tag == .Int)
|
||||||
|
Air.Inst.Tag.cmp_gt
|
||||||
|
else if (block.float_mode == .Optimized)
|
||||||
|
Air.Inst.Tag.cmp_neq_optimized
|
||||||
|
else
|
||||||
|
Air.Inst.Tag.cmp_neq;
|
||||||
|
break :ok try block.addBinOp(air_tag, casted_rhs, zero);
|
||||||
};
|
};
|
||||||
try sema.addSafetyCheck(block, ok, .remainder_division_zero_negative);
|
try sema.addSafetyCheck(block, ok, .remainder_division_zero_negative);
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
if (rs.air_tag == .div_exact) {
|
if (rs.air_tag == .div_exact or rs.air_tag == .div_exact_optimized) {
|
||||||
const result = try block.addBinOp(.div_exact, casted_lhs, casted_rhs);
|
const result = try block.addBinOp(.div_exact, casted_lhs, casted_rhs);
|
||||||
const ok = if (scalar_tag == .Float) ok: {
|
const ok = if (scalar_tag == .Float) ok: {
|
||||||
const floored = try block.addUnOp(.floor, result);
|
const floored = try block.addUnOp(.floor, result);
|
||||||
|
|
@ -11936,14 +11956,14 @@ fn analyzeArithmetic(
|
||||||
if (resolved_type.zigTypeTag() == .Vector) {
|
if (resolved_type.zigTypeTag() == .Vector) {
|
||||||
const eql = try block.addCmpVector(result, floored, .eq, try sema.addType(resolved_type));
|
const eql = try block.addCmpVector(result, floored, .eq, try sema.addType(resolved_type));
|
||||||
break :ok try block.addInst(.{
|
break :ok try block.addInst(.{
|
||||||
.tag = .reduce,
|
.tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
|
||||||
.data = .{ .reduce = .{
|
.data = .{ .reduce = .{
|
||||||
.operand = eql,
|
.operand = eql,
|
||||||
.operation = .And,
|
.operation = .And,
|
||||||
} },
|
} },
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const is_in_range = try block.addBinOp(.cmp_eq, result, floored);
|
const is_in_range = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, result, floored);
|
||||||
break :ok is_in_range;
|
break :ok is_in_range;
|
||||||
}
|
}
|
||||||
} else ok: {
|
} else ok: {
|
||||||
|
|
@ -11962,7 +11982,7 @@ fn analyzeArithmetic(
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const zero = try sema.addConstant(sema.typeOf(casted_rhs), Value.zero);
|
const zero = try sema.addConstant(sema.typeOf(casted_rhs), Value.zero);
|
||||||
const is_in_range = try block.addBinOp(.cmp_eq, remainder, zero);
|
const is_in_range = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, remainder, zero);
|
||||||
break :ok is_in_range;
|
break :ok is_in_range;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -12476,7 +12496,7 @@ fn cmpSelf(
|
||||||
const result_ty_ref = try sema.addType(result_ty);
|
const result_ty_ref = try sema.addType(result_ty);
|
||||||
return block.addCmpVector(casted_lhs, casted_rhs, op, result_ty_ref);
|
return block.addCmpVector(casted_lhs, casted_rhs, op, result_ty_ref);
|
||||||
}
|
}
|
||||||
const tag = Air.Inst.Tag.fromCmpOp(op);
|
const tag = Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized);
|
||||||
return block.addBinOp(tag, casted_lhs, casted_rhs);
|
return block.addBinOp(tag, casted_lhs, casted_rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -15954,12 +15974,12 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
|
||||||
}
|
}
|
||||||
|
|
||||||
try sema.requireRuntimeBlock(block, inst_data.src(), operand_src);
|
try sema.requireRuntimeBlock(block, inst_data.src(), operand_src);
|
||||||
const result = try block.addTyOp(.float_to_int, dest_ty, operand);
|
const result = try block.addTyOp(if (block.float_mode == .Optimized) .float_to_int_optimized else .float_to_int, dest_ty, operand);
|
||||||
if (block.wantSafety()) {
|
if (block.wantSafety()) {
|
||||||
const back = try block.addTyOp(.int_to_float, operand_ty, result);
|
const back = try block.addTyOp(.int_to_float, operand_ty, result);
|
||||||
const diff = try block.addBinOp(.sub, operand, back);
|
const diff = try block.addBinOp(.sub, operand, back);
|
||||||
const ok_pos = try block.addBinOp(.cmp_lt, diff, try sema.addConstant(operand_ty, Value.one));
|
const ok_pos = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_lt_optimized else .cmp_lt, diff, try sema.addConstant(operand_ty, Value.one));
|
||||||
const ok_neg = try block.addBinOp(.cmp_gt, diff, try sema.addConstant(operand_ty, Value.negative_one));
|
const ok_neg = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_gt_optimized else .cmp_gt, diff, try sema.addConstant(operand_ty, Value.negative_one));
|
||||||
const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg);
|
const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg);
|
||||||
try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);
|
try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);
|
||||||
}
|
}
|
||||||
|
|
@ -17194,7 +17214,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
|
||||||
|
|
||||||
try sema.requireRuntimeBlock(block, inst_data.src(), operand_src);
|
try sema.requireRuntimeBlock(block, inst_data.src(), operand_src);
|
||||||
return block.addInst(.{
|
return block.addInst(.{
|
||||||
.tag = .reduce,
|
.tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
|
||||||
.data = .{ .reduce = .{
|
.data = .{ .reduce = .{
|
||||||
.operand = operand,
|
.operand = operand,
|
||||||
.operation = operation,
|
.operation = operation,
|
||||||
|
|
@ -24489,7 +24509,7 @@ fn cmpNumeric(
|
||||||
};
|
};
|
||||||
const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src);
|
const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src);
|
||||||
const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src);
|
const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src);
|
||||||
return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs);
|
return block.addBinOp(Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized), casted_lhs, casted_rhs);
|
||||||
}
|
}
|
||||||
// For mixed unsigned integer sizes, implicit cast both operands to the larger integer.
|
// For mixed unsigned integer sizes, implicit cast both operands to the larger integer.
|
||||||
// For mixed signed and unsigned integers, implicit cast both operands to a signed
|
// For mixed signed and unsigned integers, implicit cast both operands to a signed
|
||||||
|
|
@ -24610,7 +24630,7 @@ fn cmpNumeric(
|
||||||
const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src);
|
const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src);
|
||||||
const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src);
|
const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src);
|
||||||
|
|
||||||
return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs);
|
return block.addBinOp(Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized), casted_lhs, casted_rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Asserts that lhs and rhs types are both vectors.
|
/// Asserts that lhs and rhs types are both vectors.
|
||||||
|
|
|
||||||
|
|
@ -729,6 +729,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||||
.wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
|
.wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
|
||||||
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
||||||
|
|
||||||
|
.add_optimized,
|
||||||
|
.addwrap_optimized,
|
||||||
|
.sub_optimized,
|
||||||
|
.subwrap_optimized,
|
||||||
|
.mul_optimized,
|
||||||
|
.mulwrap_optimized,
|
||||||
|
.div_float_optimized,
|
||||||
|
.div_trunc_optimized,
|
||||||
|
.div_floor_optimized,
|
||||||
|
.div_exact_optimized,
|
||||||
|
.rem_optimized,
|
||||||
|
.mod_optimized,
|
||||||
|
.neg_optimized,
|
||||||
|
.cmp_lt_optimized,
|
||||||
|
.cmp_lte_optimized,
|
||||||
|
.cmp_eq_optimized,
|
||||||
|
.cmp_gte_optimized,
|
||||||
|
.cmp_gt_optimized,
|
||||||
|
.cmp_neq_optimized,
|
||||||
|
.cmp_vector_optimized,
|
||||||
|
.reduce_optimized,
|
||||||
|
.float_to_int_optimized,
|
||||||
|
=> return self.fail("TODO implement optimized float mode", .{}),
|
||||||
|
|
||||||
.wasm_memory_size => unreachable,
|
.wasm_memory_size => unreachable,
|
||||||
.wasm_memory_grow => unreachable,
|
.wasm_memory_grow => unreachable,
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
|
|
|
||||||
|
|
@ -744,6 +744,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||||
.wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
|
.wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
|
||||||
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
||||||
|
|
||||||
|
.add_optimized,
|
||||||
|
.addwrap_optimized,
|
||||||
|
.sub_optimized,
|
||||||
|
.subwrap_optimized,
|
||||||
|
.mul_optimized,
|
||||||
|
.mulwrap_optimized,
|
||||||
|
.div_float_optimized,
|
||||||
|
.div_trunc_optimized,
|
||||||
|
.div_floor_optimized,
|
||||||
|
.div_exact_optimized,
|
||||||
|
.rem_optimized,
|
||||||
|
.mod_optimized,
|
||||||
|
.neg_optimized,
|
||||||
|
.cmp_lt_optimized,
|
||||||
|
.cmp_lte_optimized,
|
||||||
|
.cmp_eq_optimized,
|
||||||
|
.cmp_gte_optimized,
|
||||||
|
.cmp_gt_optimized,
|
||||||
|
.cmp_neq_optimized,
|
||||||
|
.cmp_vector_optimized,
|
||||||
|
.reduce_optimized,
|
||||||
|
.float_to_int_optimized,
|
||||||
|
=> return self.fail("TODO implement optimized float mode", .{}),
|
||||||
|
|
||||||
.wasm_memory_size => unreachable,
|
.wasm_memory_size => unreachable,
|
||||||
.wasm_memory_grow => unreachable,
|
.wasm_memory_grow => unreachable,
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
|
|
|
||||||
|
|
@ -669,6 +669,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||||
.wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
|
.wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
|
||||||
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
||||||
|
|
||||||
|
.add_optimized,
|
||||||
|
.addwrap_optimized,
|
||||||
|
.sub_optimized,
|
||||||
|
.subwrap_optimized,
|
||||||
|
.mul_optimized,
|
||||||
|
.mulwrap_optimized,
|
||||||
|
.div_float_optimized,
|
||||||
|
.div_trunc_optimized,
|
||||||
|
.div_floor_optimized,
|
||||||
|
.div_exact_optimized,
|
||||||
|
.rem_optimized,
|
||||||
|
.mod_optimized,
|
||||||
|
.neg_optimized,
|
||||||
|
.cmp_lt_optimized,
|
||||||
|
.cmp_lte_optimized,
|
||||||
|
.cmp_eq_optimized,
|
||||||
|
.cmp_gte_optimized,
|
||||||
|
.cmp_gt_optimized,
|
||||||
|
.cmp_neq_optimized,
|
||||||
|
.cmp_vector_optimized,
|
||||||
|
.reduce_optimized,
|
||||||
|
.float_to_int_optimized,
|
||||||
|
=> return self.fail("TODO implement optimized float mode", .{}),
|
||||||
|
|
||||||
.wasm_memory_size => unreachable,
|
.wasm_memory_size => unreachable,
|
||||||
.wasm_memory_grow => unreachable,
|
.wasm_memory_grow => unreachable,
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
|
|
|
||||||
|
|
@ -681,6 +681,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||||
.wrap_errunion_payload => @panic("TODO try self.airWrapErrUnionPayload(inst)"),
|
.wrap_errunion_payload => @panic("TODO try self.airWrapErrUnionPayload(inst)"),
|
||||||
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
||||||
|
|
||||||
|
.add_optimized,
|
||||||
|
.addwrap_optimized,
|
||||||
|
.sub_optimized,
|
||||||
|
.subwrap_optimized,
|
||||||
|
.mul_optimized,
|
||||||
|
.mulwrap_optimized,
|
||||||
|
.div_float_optimized,
|
||||||
|
.div_trunc_optimized,
|
||||||
|
.div_floor_optimized,
|
||||||
|
.div_exact_optimized,
|
||||||
|
.rem_optimized,
|
||||||
|
.mod_optimized,
|
||||||
|
.neg_optimized,
|
||||||
|
.cmp_lt_optimized,
|
||||||
|
.cmp_lte_optimized,
|
||||||
|
.cmp_eq_optimized,
|
||||||
|
.cmp_gte_optimized,
|
||||||
|
.cmp_gt_optimized,
|
||||||
|
.cmp_neq_optimized,
|
||||||
|
.cmp_vector_optimized,
|
||||||
|
.reduce_optimized,
|
||||||
|
.float_to_int_optimized,
|
||||||
|
=> @panic("TODO implement optimized float mode"),
|
||||||
|
|
||||||
.wasm_memory_size => unreachable,
|
.wasm_memory_size => unreachable,
|
||||||
.wasm_memory_grow => unreachable,
|
.wasm_memory_grow => unreachable,
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
|
|
|
||||||
|
|
@ -1622,6 +1622,30 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
|
||||||
.err_return_trace,
|
.err_return_trace,
|
||||||
.set_err_return_trace,
|
.set_err_return_trace,
|
||||||
=> |tag| return self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
|
=> |tag| return self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
|
||||||
|
|
||||||
|
.add_optimized,
|
||||||
|
.addwrap_optimized,
|
||||||
|
.sub_optimized,
|
||||||
|
.subwrap_optimized,
|
||||||
|
.mul_optimized,
|
||||||
|
.mulwrap_optimized,
|
||||||
|
.div_float_optimized,
|
||||||
|
.div_trunc_optimized,
|
||||||
|
.div_floor_optimized,
|
||||||
|
.div_exact_optimized,
|
||||||
|
.rem_optimized,
|
||||||
|
.mod_optimized,
|
||||||
|
.neg_optimized,
|
||||||
|
.cmp_lt_optimized,
|
||||||
|
.cmp_lte_optimized,
|
||||||
|
.cmp_eq_optimized,
|
||||||
|
.cmp_gte_optimized,
|
||||||
|
.cmp_gt_optimized,
|
||||||
|
.cmp_neq_optimized,
|
||||||
|
.cmp_vector_optimized,
|
||||||
|
.reduce_optimized,
|
||||||
|
.float_to_int_optimized,
|
||||||
|
=> return self.fail("TODO implement optimized float mode", .{}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -751,6 +751,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||||
.wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
|
.wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
|
||||||
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
||||||
|
|
||||||
|
.add_optimized,
|
||||||
|
.addwrap_optimized,
|
||||||
|
.sub_optimized,
|
||||||
|
.subwrap_optimized,
|
||||||
|
.mul_optimized,
|
||||||
|
.mulwrap_optimized,
|
||||||
|
.div_float_optimized,
|
||||||
|
.div_trunc_optimized,
|
||||||
|
.div_floor_optimized,
|
||||||
|
.div_exact_optimized,
|
||||||
|
.rem_optimized,
|
||||||
|
.mod_optimized,
|
||||||
|
.neg_optimized,
|
||||||
|
.cmp_lt_optimized,
|
||||||
|
.cmp_lte_optimized,
|
||||||
|
.cmp_eq_optimized,
|
||||||
|
.cmp_gte_optimized,
|
||||||
|
.cmp_gt_optimized,
|
||||||
|
.cmp_neq_optimized,
|
||||||
|
.cmp_vector_optimized,
|
||||||
|
.reduce_optimized,
|
||||||
|
.float_to_int_optimized,
|
||||||
|
=> return self.fail("TODO implement optimized float mode", .{}),
|
||||||
|
|
||||||
.wasm_memory_size => unreachable,
|
.wasm_memory_size => unreachable,
|
||||||
.wasm_memory_grow => unreachable,
|
.wasm_memory_grow => unreachable,
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
|
|
|
||||||
|
|
@ -1928,6 +1928,30 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
|
||||||
|
|
||||||
.wasm_memory_size => try airWasmMemorySize(f, inst),
|
.wasm_memory_size => try airWasmMemorySize(f, inst),
|
||||||
.wasm_memory_grow => try airWasmMemoryGrow(f, inst),
|
.wasm_memory_grow => try airWasmMemoryGrow(f, inst),
|
||||||
|
|
||||||
|
.add_optimized,
|
||||||
|
.addwrap_optimized,
|
||||||
|
.sub_optimized,
|
||||||
|
.subwrap_optimized,
|
||||||
|
.mul_optimized,
|
||||||
|
.mulwrap_optimized,
|
||||||
|
.div_float_optimized,
|
||||||
|
.div_trunc_optimized,
|
||||||
|
.div_floor_optimized,
|
||||||
|
.div_exact_optimized,
|
||||||
|
.rem_optimized,
|
||||||
|
.mod_optimized,
|
||||||
|
.neg_optimized,
|
||||||
|
.cmp_lt_optimized,
|
||||||
|
.cmp_lte_optimized,
|
||||||
|
.cmp_eq_optimized,
|
||||||
|
.cmp_gte_optimized,
|
||||||
|
.cmp_gt_optimized,
|
||||||
|
.cmp_neq_optimized,
|
||||||
|
.cmp_vector_optimized,
|
||||||
|
.reduce_optimized,
|
||||||
|
.float_to_int_optimized,
|
||||||
|
=> return f.fail("TODO implement optimized float mode", .{}),
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
};
|
};
|
||||||
switch (result_value) {
|
switch (result_value) {
|
||||||
|
|
|
||||||
|
|
@ -3984,21 +3984,21 @@ pub const FuncGen = struct {
|
||||||
for (body) |inst, i| {
|
for (body) |inst, i| {
|
||||||
const opt_value: ?*const llvm.Value = switch (air_tags[inst]) {
|
const opt_value: ?*const llvm.Value = switch (air_tags[inst]) {
|
||||||
// zig fmt: off
|
// zig fmt: off
|
||||||
.add => try self.airAdd(inst),
|
.add => try self.airAdd(inst, false),
|
||||||
.addwrap => try self.airAddWrap(inst),
|
.addwrap => try self.airAddWrap(inst, false),
|
||||||
.add_sat => try self.airAddSat(inst),
|
.add_sat => try self.airAddSat(inst),
|
||||||
.sub => try self.airSub(inst),
|
.sub => try self.airSub(inst, false),
|
||||||
.subwrap => try self.airSubWrap(inst),
|
.subwrap => try self.airSubWrap(inst, false),
|
||||||
.sub_sat => try self.airSubSat(inst),
|
.sub_sat => try self.airSubSat(inst),
|
||||||
.mul => try self.airMul(inst),
|
.mul => try self.airMul(inst, false),
|
||||||
.mulwrap => try self.airMulWrap(inst),
|
.mulwrap => try self.airMulWrap(inst, false),
|
||||||
.mul_sat => try self.airMulSat(inst),
|
.mul_sat => try self.airMulSat(inst),
|
||||||
.div_float => try self.airDivFloat(inst),
|
.div_float => try self.airDivFloat(inst, false),
|
||||||
.div_trunc => try self.airDivTrunc(inst),
|
.div_trunc => try self.airDivTrunc(inst, false),
|
||||||
.div_floor => try self.airDivFloor(inst),
|
.div_floor => try self.airDivFloor(inst, false),
|
||||||
.div_exact => try self.airDivExact(inst),
|
.div_exact => try self.airDivExact(inst, false),
|
||||||
.rem => try self.airRem(inst),
|
.rem => try self.airRem(inst, false),
|
||||||
.mod => try self.airMod(inst),
|
.mod => try self.airMod(inst, false),
|
||||||
.ptr_add => try self.airPtrAdd(inst),
|
.ptr_add => try self.airPtrAdd(inst),
|
||||||
.ptr_sub => try self.airPtrSub(inst),
|
.ptr_sub => try self.airPtrSub(inst),
|
||||||
.shl => try self.airShl(inst),
|
.shl => try self.airShl(inst),
|
||||||
|
|
@ -4009,6 +4009,19 @@ pub const FuncGen = struct {
|
||||||
.slice => try self.airSlice(inst),
|
.slice => try self.airSlice(inst),
|
||||||
.mul_add => try self.airMulAdd(inst),
|
.mul_add => try self.airMulAdd(inst),
|
||||||
|
|
||||||
|
.add_optimized => try self.airAdd(inst, true),
|
||||||
|
.addwrap_optimized => try self.airAddWrap(inst, true),
|
||||||
|
.sub_optimized => try self.airSub(inst, true),
|
||||||
|
.subwrap_optimized => try self.airSubWrap(inst, true),
|
||||||
|
.mul_optimized => try self.airMul(inst, true),
|
||||||
|
.mulwrap_optimized => try self.airMulWrap(inst, true),
|
||||||
|
.div_float_optimized => try self.airDivFloat(inst, true),
|
||||||
|
.div_trunc_optimized => try self.airDivTrunc(inst, true),
|
||||||
|
.div_floor_optimized => try self.airDivFloor(inst, true),
|
||||||
|
.div_exact_optimized => try self.airDivExact(inst, true),
|
||||||
|
.rem_optimized => try self.airRem(inst, true),
|
||||||
|
.mod_optimized => try self.airMod(inst, true),
|
||||||
|
|
||||||
.add_with_overflow => try self.airOverflow(inst, "llvm.sadd.with.overflow", "llvm.uadd.with.overflow"),
|
.add_with_overflow => try self.airOverflow(inst, "llvm.sadd.with.overflow", "llvm.uadd.with.overflow"),
|
||||||
.sub_with_overflow => try self.airOverflow(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"),
|
.sub_with_overflow => try self.airOverflow(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"),
|
||||||
.mul_with_overflow => try self.airOverflow(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"),
|
.mul_with_overflow => try self.airOverflow(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"),
|
||||||
|
|
@ -4034,16 +4047,26 @@ pub const FuncGen = struct {
|
||||||
.ceil => try self.airUnaryOp(inst, .ceil),
|
.ceil => try self.airUnaryOp(inst, .ceil),
|
||||||
.round => try self.airUnaryOp(inst, .round),
|
.round => try self.airUnaryOp(inst, .round),
|
||||||
.trunc_float => try self.airUnaryOp(inst, .trunc),
|
.trunc_float => try self.airUnaryOp(inst, .trunc),
|
||||||
.neg => try self.airUnaryOp(inst, .neg),
|
|
||||||
|
|
||||||
.cmp_eq => try self.airCmp(inst, .eq),
|
.neg => try self.airNeg(inst, false),
|
||||||
.cmp_gt => try self.airCmp(inst, .gt),
|
.neg_optimized => try self.airNeg(inst, true),
|
||||||
.cmp_gte => try self.airCmp(inst, .gte),
|
|
||||||
.cmp_lt => try self.airCmp(inst, .lt),
|
|
||||||
.cmp_lte => try self.airCmp(inst, .lte),
|
|
||||||
.cmp_neq => try self.airCmp(inst, .neq),
|
|
||||||
|
|
||||||
.cmp_vector => try self.airCmpVector(inst),
|
.cmp_eq => try self.airCmp(inst, .eq, false),
|
||||||
|
.cmp_gt => try self.airCmp(inst, .gt, false),
|
||||||
|
.cmp_gte => try self.airCmp(inst, .gte, false),
|
||||||
|
.cmp_lt => try self.airCmp(inst, .lt, false),
|
||||||
|
.cmp_lte => try self.airCmp(inst, .lte, false),
|
||||||
|
.cmp_neq => try self.airCmp(inst, .neq, false),
|
||||||
|
|
||||||
|
.cmp_eq_optimized => try self.airCmp(inst, .eq, true),
|
||||||
|
.cmp_gt_optimized => try self.airCmp(inst, .gt, true),
|
||||||
|
.cmp_gte_optimized => try self.airCmp(inst, .gte, true),
|
||||||
|
.cmp_lt_optimized => try self.airCmp(inst, .lt, true),
|
||||||
|
.cmp_lte_optimized => try self.airCmp(inst, .lte, true),
|
||||||
|
.cmp_neq_optimized => try self.airCmp(inst, .neq, true),
|
||||||
|
|
||||||
|
.cmp_vector => try self.airCmpVector(inst, false),
|
||||||
|
.cmp_vector_optimized => try self.airCmpVector(inst, true),
|
||||||
.cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
|
.cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
|
||||||
|
|
||||||
.is_non_null => try self.airIsNonNull(inst, false, .NE),
|
.is_non_null => try self.airIsNonNull(inst, false, .NE),
|
||||||
|
|
@ -4093,8 +4116,10 @@ pub const FuncGen = struct {
|
||||||
.ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0),
|
.ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0),
|
||||||
.ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1),
|
.ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1),
|
||||||
|
|
||||||
|
.float_to_int => try self.airFloatToInt(inst, false),
|
||||||
|
.float_to_int_optimized => try self.airFloatToInt(inst, true),
|
||||||
|
|
||||||
.array_to_slice => try self.airArrayToSlice(inst),
|
.array_to_slice => try self.airArrayToSlice(inst),
|
||||||
.float_to_int => try self.airFloatToInt(inst),
|
|
||||||
.int_to_float => try self.airIntToFloat(inst),
|
.int_to_float => try self.airIntToFloat(inst),
|
||||||
.cmpxchg_weak => try self.airCmpxchg(inst, true),
|
.cmpxchg_weak => try self.airCmpxchg(inst, true),
|
||||||
.cmpxchg_strong => try self.airCmpxchg(inst, false),
|
.cmpxchg_strong => try self.airCmpxchg(inst, false),
|
||||||
|
|
@ -4115,11 +4140,13 @@ pub const FuncGen = struct {
|
||||||
.splat => try self.airSplat(inst),
|
.splat => try self.airSplat(inst),
|
||||||
.select => try self.airSelect(inst),
|
.select => try self.airSelect(inst),
|
||||||
.shuffle => try self.airShuffle(inst),
|
.shuffle => try self.airShuffle(inst),
|
||||||
.reduce => try self.airReduce(inst),
|
|
||||||
.aggregate_init => try self.airAggregateInit(inst),
|
.aggregate_init => try self.airAggregateInit(inst),
|
||||||
.union_init => try self.airUnionInit(inst),
|
.union_init => try self.airUnionInit(inst),
|
||||||
.prefetch => try self.airPrefetch(inst),
|
.prefetch => try self.airPrefetch(inst),
|
||||||
|
|
||||||
|
.reduce => try self.airReduce(inst, false),
|
||||||
|
.reduce_optimized => try self.airReduce(inst, true),
|
||||||
|
|
||||||
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
|
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
|
||||||
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
|
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
|
||||||
.atomic_store_release => try self.airAtomicStore(inst, .Release),
|
.atomic_store_release => try self.airAtomicStore(inst, .Release),
|
||||||
|
|
@ -4485,8 +4512,9 @@ pub const FuncGen = struct {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airCmp(self: *FuncGen, inst: Air.Inst.Index, op: math.CompareOperator) !?*const llvm.Value {
|
fn airCmp(self: *FuncGen, inst: Air.Inst.Index, op: math.CompareOperator, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||||
const lhs = try self.resolveInst(bin_op.lhs);
|
const lhs = try self.resolveInst(bin_op.lhs);
|
||||||
|
|
@ -4496,8 +4524,9 @@ pub const FuncGen = struct {
|
||||||
return self.cmp(lhs, rhs, operand_ty, op);
|
return self.cmp(lhs, rhs, operand_ty, op);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
|
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
|
||||||
const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;
|
const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;
|
||||||
|
|
@ -4943,10 +4972,12 @@ pub const FuncGen = struct {
|
||||||
return self.builder.buildCall(libc_fn, ¶ms, params.len, .C, .Auto, "");
|
return self.builder.buildCall(libc_fn, ¶ms, params.len, .C, .Auto, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst))
|
if (self.liveness.isUnused(inst))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const target = self.dg.module.getTarget();
|
const target = self.dg.module.getTarget();
|
||||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||||
|
|
||||||
|
|
@ -6095,8 +6126,9 @@ pub const FuncGen = struct {
|
||||||
return self.builder.buildInsertValue(partial, len, 1, "");
|
return self.builder.buildInsertValue(partial, len, 1, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airAdd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
fn airAdd(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||||
const lhs = try self.resolveInst(bin_op.lhs);
|
const lhs = try self.resolveInst(bin_op.lhs);
|
||||||
|
|
@ -6109,8 +6141,9 @@ pub const FuncGen = struct {
|
||||||
return self.builder.buildNUWAdd(lhs, rhs, "");
|
return self.builder.buildNUWAdd(lhs, rhs, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||||
const lhs = try self.resolveInst(bin_op.lhs);
|
const lhs = try self.resolveInst(bin_op.lhs);
|
||||||
|
|
@ -6134,8 +6167,9 @@ pub const FuncGen = struct {
|
||||||
return self.builder.buildUAddSat(lhs, rhs, "");
|
return self.builder.buildUAddSat(lhs, rhs, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airSub(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||||
const lhs = try self.resolveInst(bin_op.lhs);
|
const lhs = try self.resolveInst(bin_op.lhs);
|
||||||
|
|
@ -6148,8 +6182,9 @@ pub const FuncGen = struct {
|
||||||
return self.builder.buildNUWSub(lhs, rhs, "");
|
return self.builder.buildNUWSub(lhs, rhs, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airSubWrap(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
fn airSubWrap(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||||
const lhs = try self.resolveInst(bin_op.lhs);
|
const lhs = try self.resolveInst(bin_op.lhs);
|
||||||
|
|
@ -6172,8 +6207,9 @@ pub const FuncGen = struct {
|
||||||
return self.builder.buildUSubSat(lhs, rhs, "");
|
return self.builder.buildUSubSat(lhs, rhs, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airMul(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||||
const lhs = try self.resolveInst(bin_op.lhs);
|
const lhs = try self.resolveInst(bin_op.lhs);
|
||||||
|
|
@ -6186,8 +6222,9 @@ pub const FuncGen = struct {
|
||||||
return self.builder.buildNUWMul(lhs, rhs, "");
|
return self.builder.buildNUWMul(lhs, rhs, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airMulWrap(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
fn airMulWrap(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||||
const lhs = try self.resolveInst(bin_op.lhs);
|
const lhs = try self.resolveInst(bin_op.lhs);
|
||||||
|
|
@ -6210,8 +6247,9 @@ pub const FuncGen = struct {
|
||||||
return self.builder.buildUMulFixSat(lhs, rhs, "");
|
return self.builder.buildUMulFixSat(lhs, rhs, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||||
const lhs = try self.resolveInst(bin_op.lhs);
|
const lhs = try self.resolveInst(bin_op.lhs);
|
||||||
|
|
@ -6221,8 +6259,9 @@ pub const FuncGen = struct {
|
||||||
return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
|
return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||||
const lhs = try self.resolveInst(bin_op.lhs);
|
const lhs = try self.resolveInst(bin_op.lhs);
|
||||||
|
|
@ -6238,8 +6277,9 @@ pub const FuncGen = struct {
|
||||||
return self.builder.buildUDiv(lhs, rhs, "");
|
return self.builder.buildUDiv(lhs, rhs, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||||
const lhs = try self.resolveInst(bin_op.lhs);
|
const lhs = try self.resolveInst(bin_op.lhs);
|
||||||
|
|
@ -6270,8 +6310,9 @@ pub const FuncGen = struct {
|
||||||
return self.builder.buildUDiv(lhs, rhs, "");
|
return self.builder.buildUDiv(lhs, rhs, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airDivExact(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||||
const lhs = try self.resolveInst(bin_op.lhs);
|
const lhs = try self.resolveInst(bin_op.lhs);
|
||||||
|
|
@ -6284,8 +6325,9 @@ pub const FuncGen = struct {
|
||||||
return self.builder.buildExactUDiv(lhs, rhs, "");
|
return self.builder.buildExactUDiv(lhs, rhs, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airRem(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
fn airRem(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||||
const lhs = try self.resolveInst(bin_op.lhs);
|
const lhs = try self.resolveInst(bin_op.lhs);
|
||||||
|
|
@ -6298,8 +6340,9 @@ pub const FuncGen = struct {
|
||||||
return self.builder.buildURem(lhs, rhs, "");
|
return self.builder.buildURem(lhs, rhs, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airMod(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
fn airMod(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||||
const lhs = try self.resolveInst(bin_op.lhs);
|
const lhs = try self.resolveInst(bin_op.lhs);
|
||||||
|
|
@ -7613,6 +7656,17 @@ pub const FuncGen = struct {
|
||||||
return self.buildFloatOp(op, operand_ty, 1, .{operand});
|
return self.buildFloatOp(op, operand_ty, 1, .{operand});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn airNeg(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
|
const un_op = self.air.instructions.items(.data)[inst].un_op;
|
||||||
|
const operand = try self.resolveInst(un_op);
|
||||||
|
const operand_ty = self.air.typeOf(un_op);
|
||||||
|
|
||||||
|
return self.buildFloatOp(.neg, operand_ty, 1, .{operand});
|
||||||
|
}
|
||||||
|
|
||||||
fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*const llvm.Value {
|
fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
|
||||||
|
|
@ -7927,8 +7981,9 @@ pub const FuncGen = struct {
|
||||||
return self.builder.buildShuffleVector(a, b, llvm_mask_value, "");
|
return self.builder.buildShuffleVector(a, b, llvm_mask_value, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airReduce(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
|
||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
self.builder.setFastMath(want_fast_math);
|
||||||
|
|
||||||
const reduce = self.air.instructions.items(.data)[inst].reduce;
|
const reduce = self.air.instructions.items(.data)[inst].reduce;
|
||||||
const operand = try self.resolveInst(reduce.operand);
|
const operand = try self.resolveInst(reduce.operand);
|
||||||
|
|
|
||||||
|
|
@ -941,6 +941,9 @@ pub const Builder = opaque {
|
||||||
|
|
||||||
pub const buildFPMulReduce = ZigLLVMBuildFPMulReduce;
|
pub const buildFPMulReduce = ZigLLVMBuildFPMulReduce;
|
||||||
extern fn ZigLLVMBuildFPMulReduce(B: *const Builder, Acc: *const Value, Val: *const Value) *const Value;
|
extern fn ZigLLVMBuildFPMulReduce(B: *const Builder, Acc: *const Value, Val: *const Value) *const Value;
|
||||||
|
|
||||||
|
pub const setFastMath = ZigLLVMSetFastMath;
|
||||||
|
extern fn ZigLLVMSetFastMath(B: *const Builder, on_state: bool) void;
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const MDString = opaque {
|
pub const MDString = opaque {
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,24 @@ const Writer = struct {
|
||||||
.set_union_tag,
|
.set_union_tag,
|
||||||
.min,
|
.min,
|
||||||
.max,
|
.max,
|
||||||
|
.add_optimized,
|
||||||
|
.addwrap_optimized,
|
||||||
|
.sub_optimized,
|
||||||
|
.subwrap_optimized,
|
||||||
|
.mul_optimized,
|
||||||
|
.mulwrap_optimized,
|
||||||
|
.div_float_optimized,
|
||||||
|
.div_trunc_optimized,
|
||||||
|
.div_floor_optimized,
|
||||||
|
.div_exact_optimized,
|
||||||
|
.rem_optimized,
|
||||||
|
.mod_optimized,
|
||||||
|
.cmp_lt_optimized,
|
||||||
|
.cmp_lte_optimized,
|
||||||
|
.cmp_eq_optimized,
|
||||||
|
.cmp_gte_optimized,
|
||||||
|
.cmp_gt_optimized,
|
||||||
|
.cmp_neq_optimized,
|
||||||
=> try w.writeBinOp(s, inst),
|
=> try w.writeBinOp(s, inst),
|
||||||
|
|
||||||
.is_null,
|
.is_null,
|
||||||
|
|
@ -169,6 +187,7 @@ const Writer = struct {
|
||||||
.round,
|
.round,
|
||||||
.trunc_float,
|
.trunc_float,
|
||||||
.neg,
|
.neg,
|
||||||
|
.neg_optimized,
|
||||||
.cmp_lt_errors_len,
|
.cmp_lt_errors_len,
|
||||||
.set_err_return_trace,
|
.set_err_return_trace,
|
||||||
=> try w.writeUnOp(s, inst),
|
=> try w.writeUnOp(s, inst),
|
||||||
|
|
@ -216,6 +235,7 @@ const Writer = struct {
|
||||||
.int_to_float,
|
.int_to_float,
|
||||||
.splat,
|
.splat,
|
||||||
.float_to_int,
|
.float_to_int,
|
||||||
|
.float_to_int_optimized,
|
||||||
.get_union_tag,
|
.get_union_tag,
|
||||||
.clz,
|
.clz,
|
||||||
.ctz,
|
.ctz,
|
||||||
|
|
@ -280,8 +300,8 @@ const Writer = struct {
|
||||||
.mul_add => try w.writeMulAdd(s, inst),
|
.mul_add => try w.writeMulAdd(s, inst),
|
||||||
.select => try w.writeSelect(s, inst),
|
.select => try w.writeSelect(s, inst),
|
||||||
.shuffle => try w.writeShuffle(s, inst),
|
.shuffle => try w.writeShuffle(s, inst),
|
||||||
.reduce => try w.writeReduce(s, inst),
|
.reduce, .reduce_optimized => try w.writeReduce(s, inst),
|
||||||
.cmp_vector => try w.writeCmpVector(s, inst),
|
.cmp_vector, .cmp_vector_optimized => try w.writeCmpVector(s, inst),
|
||||||
|
|
||||||
.dbg_block_begin, .dbg_block_end => {},
|
.dbg_block_begin, .dbg_block_end => {},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue