aboutsummaryrefslogtreecommitdiff
path: root/src/value.zig
diff options
context:
space:
mode:
authorWilliam Sengir <william@sengir.com>2022-03-20 00:38:12 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-03-21 16:54:19 -0700
commitafdcfb005ea32849f30e2abd7361ce1f33d0ee74 (patch)
treeee60a029d0fd028bc17e65e84a0fe36877a7c1fb /src/value.zig
parent3f4676901a8c02d9d7069b284aa848d685c3975c (diff)
downloadzig-afdcfb005ea32849f30e2abd7361ce1f33d0ee74.tar.gz
zig-afdcfb005ea32849f30e2abd7361ce1f33d0ee74.zip
Sema: make most instructions vector-agnostic
Made most `Value` functions require a `Type`. If the provided type is a vector, then automatically vectorize the operation and return with another vector. The Sema side can then automatically become vectorized with minimal changes. There are already a few manually vectorized instructions, but we can simplify those later.
Diffstat (limited to 'src/value.zig')
-rw-r--r--src/value.zig771
1 files changed, 728 insertions, 43 deletions
diff --git a/src/value.zig b/src/value.zig
index c5e082485a..6f0f786072 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -1846,8 +1846,23 @@ pub const Value = extern union {
return order(lhs, rhs).compare(op);
}
- /// Asserts the value is comparable. Both operands have type `ty`.
+ /// Asserts the values are comparable. Both operands have type `ty`.
+ /// Vector results will be reduced with AND.
pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type) bool {
+ if (ty.zigTypeTag() == .Vector) {
+ var i: usize = 0;
+ while (i < ty.vectorLen()) : (i += 1) {
+ if (!compareScalar(lhs.indexVectorlike(i), op, rhs.indexVectorlike(i), ty.scalarType())) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return compareScalar(lhs, op, rhs, ty);
+ }
+
+ /// Asserts the values are comparable. Both operands have type `ty`.
+ pub fn compareScalar(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type) bool {
return switch (op) {
.eq => lhs.eql(rhs, ty),
.neq => !lhs.eql(rhs, ty),
@@ -1855,18 +1870,25 @@ pub const Value = extern union {
};
}
+ /// Asserts the values are comparable vectors of type `ty`.
+ pub fn compareVector(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, allocator: Allocator) !Value {
+ assert(ty.zigTypeTag() == .Vector);
+ const result_data = try allocator.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ const res_bool = compareScalar(lhs.indexVectorlike(i), op, rhs.indexVectorlike(i), ty.scalarType());
+ scalar.* = if (res_bool) Value.@"true" else Value.@"false";
+ }
+ return Value.Tag.aggregate.create(allocator, result_data);
+ }
+
/// Asserts the value is comparable.
- /// For vectors this is only valid with op == .eq.
+ /// Vector results will be reduced with AND.
pub fn compareWithZero(lhs: Value, op: std.math.CompareOperator) bool {
switch (lhs.tag()) {
- .repeated => {
- assert(op == .eq);
- return lhs.castTag(.repeated).?.data.compareWithZero(.eq);
- },
+ .repeated => return lhs.castTag(.repeated).?.data.compareWithZero(op),
.aggregate => {
- assert(op == .eq);
for (lhs.castTag(.aggregate).?.data) |elem_val| {
- if (!elem_val.compareWithZero(.eq)) return false;
+ if (!elem_val.compareWithZero(op)) return false;
}
return true;
},
@@ -2404,6 +2426,27 @@ pub const Value = extern union {
};
}
+ /// Index into a vector-like `Value`. Asserts `index` is a valid index for `val`.
+ /// Some scalar values are considered vector-like to avoid needing to allocate
+ /// a new `repeated` each time a constant is used.
+ pub fn indexVectorlike(val: Value, index: usize) Value {
+ return switch (val.tag()) {
+ .aggregate => val.castTag(.aggregate).?.data[index],
+
+ .repeated => val.castTag(.repeated).?.data,
+ // These values will implicitly be treated as `repeated`.
+ .zero,
+ .one,
+ .bool_false,
+ .bool_true,
+ .int_i64,
+ .int_u64,
+ => val,
+
+ else => unreachable,
+ };
+ }
+
/// Asserts the value is a single-item pointer to an array, or an array,
/// or an unknown-length pointer, and returns the element value at the index.
pub fn elemValue(val: Value, arena: Allocator, index: usize) !Value {
@@ -2646,25 +2689,38 @@ pub const Value = extern union {
};
}
- pub fn intToFloat(val: Value, arena: Allocator, dest_ty: Type, target: Target) !Value {
+ pub fn intToFloat(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, target: Target) !Value {
+ if (int_ty.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, int_ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try intToFloatScalar(val.indexVectorlike(i), arena, int_ty.scalarType(), float_ty.scalarType(), target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return intToFloatScalar(val, arena, int_ty, float_ty, target);
+ }
+
+ pub fn intToFloatScalar(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, target: Target) !Value {
+ assert(int_ty.isNumeric() and !int_ty.isAnyFloat());
+ assert(float_ty.isAnyFloat());
switch (val.tag()) {
.undef, .zero, .one => return val,
.the_only_possible_value => return Value.initTag(.zero), // for i0, u0
.int_u64 => {
- return intToFloatInner(val.castTag(.int_u64).?.data, arena, dest_ty, target);
+ return intToFloatInner(val.castTag(.int_u64).?.data, arena, float_ty, target);
},
.int_i64 => {
- return intToFloatInner(val.castTag(.int_i64).?.data, arena, dest_ty, target);
+ return intToFloatInner(val.castTag(.int_i64).?.data, arena, float_ty, target);
},
.int_big_positive => {
const limbs = val.castTag(.int_big_positive).?.data;
const float = bigIntToFloat(limbs, true);
- return floatToValue(float, arena, dest_ty, target);
+ return floatToValue(float, arena, float_ty, target);
},
.int_big_negative => {
const limbs = val.castTag(.int_big_negative).?.data;
const float = bigIntToFloat(limbs, false);
- return floatToValue(float, arena, dest_ty, target);
+ return floatToValue(float, arena, float_ty, target);
},
else => unreachable,
}
@@ -2694,7 +2750,20 @@ pub const Value = extern union {
}
}
- pub fn floatToInt(val: Value, arena: Allocator, dest_ty: Type, target: Target) error{ FloatCannotFit, OutOfMemory }!Value {
+ pub fn floatToInt(val: Value, arena: Allocator, float_ty: Type, int_ty: Type, target: Target) error{ FloatCannotFit, OutOfMemory }!Value {
+ if (float_ty.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try floatToIntScalar(val.indexVectorlike(i), arena, float_ty.scalarType(), int_ty.scalarType(), target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return floatToIntScalar(val, arena, float_ty, int_ty, target);
+ }
+
+ pub fn floatToIntScalar(val: Value, arena: Allocator, float_ty: Type, int_ty: Type, target: Target) error{ FloatCannotFit, OutOfMemory }!Value {
+ assert(float_ty.isAnyFloat());
+ assert(int_ty.isInt());
const Limb = std.math.big.Limb;
var value = val.toFloat(f64); // TODO: f128 ?
@@ -2724,7 +2793,7 @@ pub const Value = extern union {
else
try Value.Tag.int_big_positive.create(arena, result_limbs);
- if (result.intFitsInType(dest_ty, target)) {
+ if (result.intFitsInType(int_ty, target)) {
return result;
} else {
return error.FloatCannotFit;
@@ -2771,7 +2840,7 @@ pub const Value = extern union {
};
}
- /// Supports both floats and ints; handles undefined.
+ /// Supports both (vectors of) floats and ints; handles undefined scalars.
pub fn numberAddWrap(
lhs: Value,
rhs: Value,
@@ -2779,10 +2848,28 @@ pub const Value = extern union {
arena: Allocator,
target: Target,
) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try numberAddWrapScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return numberAddWrapScalar(lhs, rhs, ty, arena, target);
+ }
+
+ /// Supports both floats and ints; handles undefined.
+ pub fn numberAddWrapScalar(
+ lhs: Value,
+ rhs: Value,
+ ty: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
if (ty.zigTypeTag() == .ComptimeInt) {
- return intAdd(lhs, rhs, arena);
+ return intAdd(lhs, rhs, ty, arena);
}
if (ty.isAnyFloat()) {
@@ -2809,7 +2896,7 @@ pub const Value = extern union {
}
}
- /// Supports integers only; asserts neither operand is undefined.
+ /// Supports (vectors of) integers only; asserts neither operand is undefined.
pub fn intAddSat(
lhs: Value,
rhs: Value,
@@ -2817,6 +2904,24 @@ pub const Value = extern union {
arena: Allocator,
target: Target,
) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try intAddSatScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return intAddSatScalar(lhs, rhs, ty, arena, target);
+ }
+
+ /// Supports integers only; asserts neither operand is undefined.
+ pub fn intAddSatScalar(
+ lhs: Value,
+ rhs: Value,
+ ty: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
assert(!lhs.isUndef());
assert(!rhs.isUndef());
@@ -2861,7 +2966,7 @@ pub const Value = extern union {
};
}
- /// Supports both floats and ints; handles undefined.
+ /// Supports both (vectors of) floats and ints; handles undefined scalars.
pub fn numberSubWrap(
lhs: Value,
rhs: Value,
@@ -2869,10 +2974,28 @@ pub const Value = extern union {
arena: Allocator,
target: Target,
) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try numberSubWrapScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return numberSubWrapScalar(lhs, rhs, ty, arena, target);
+ }
+
+ /// Supports both floats and ints; handles undefined.
+ pub fn numberSubWrapScalar(
+ lhs: Value,
+ rhs: Value,
+ ty: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
if (ty.zigTypeTag() == .ComptimeInt) {
- return intSub(lhs, rhs, arena);
+ return intSub(lhs, rhs, ty, arena);
}
if (ty.isAnyFloat()) {
@@ -2883,7 +3006,7 @@ pub const Value = extern union {
return overflow_result.wrapped_result;
}
- /// Supports integers only; asserts neither operand is undefined.
+ /// Supports (vectors of) integers only; asserts neither operand is undefined.
pub fn intSubSat(
lhs: Value,
rhs: Value,
@@ -2891,6 +3014,24 @@ pub const Value = extern union {
arena: Allocator,
target: Target,
) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try intSubSatScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return intSubSatScalar(lhs, rhs, ty, arena, target);
+ }
+
+ /// Supports integers only; asserts neither operand is undefined.
+ pub fn intSubSatScalar(
+ lhs: Value,
+ rhs: Value,
+ ty: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
assert(!lhs.isUndef());
assert(!rhs.isUndef());
@@ -2944,7 +3085,7 @@ pub const Value = extern union {
};
}
- /// Supports both floats and ints; handles undefined.
+ /// Supports both (vectors of) floats and ints; handles undefined scalars.
pub fn numberMulWrap(
lhs: Value,
rhs: Value,
@@ -2952,10 +3093,28 @@ pub const Value = extern union {
arena: Allocator,
target: Target,
) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try numberMulWrapScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return numberMulWrapScalar(lhs, rhs, ty, arena, target);
+ }
+
+ /// Supports both floats and ints; handles undefined.
+ pub fn numberMulWrapScalar(
+ lhs: Value,
+ rhs: Value,
+ ty: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
if (ty.zigTypeTag() == .ComptimeInt) {
- return intMul(lhs, rhs, arena);
+ return intMul(lhs, rhs, ty, arena);
}
if (ty.isAnyFloat()) {
@@ -2966,7 +3125,7 @@ pub const Value = extern union {
return overflow_result.wrapped_result;
}
- /// Supports integers only; asserts neither operand is undefined.
+ /// Supports (vectors of) integers only; asserts neither operand is undefined.
pub fn intMulSat(
lhs: Value,
rhs: Value,
@@ -2974,6 +3133,24 @@ pub const Value = extern union {
arena: Allocator,
target: Target,
) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try intMulSatScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return intMulSatScalar(lhs, rhs, ty, arena, target);
+ }
+
+ /// Supports (vectors of) integers only; asserts neither operand is undefined.
+ pub fn intMulSatScalar(
+ lhs: Value,
+ rhs: Value,
+ ty: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
assert(!lhs.isUndef());
assert(!rhs.isUndef());
@@ -3025,8 +3202,20 @@ pub const Value = extern union {
};
}
- /// operands must be integers; handles undefined.
+ /// operands must be (vectors of) integers; handles undefined scalars.
pub fn bitwiseNot(val: Value, ty: Type, arena: Allocator, target: Target) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try bitwiseNotScalar(val.indexVectorlike(i), ty.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return bitwiseNotScalar(val, ty, arena, target);
+ }
+
+ /// operands must be integers; handles undefined.
+ pub fn bitwiseNotScalar(val: Value, ty: Type, arena: Allocator, target: Target) !Value {
if (val.isUndef()) return Value.initTag(.undef);
const info = ty.intInfo(target);
@@ -3050,8 +3239,20 @@ pub const Value = extern union {
return fromBigInt(arena, result_bigint.toConst());
}
+ /// operands must be (vectors of) integers; handles undefined scalars.
+ pub fn bitwiseAnd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try allocator.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try bitwiseAndScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
+ }
+ return Value.Tag.aggregate.create(allocator, result_data);
+ }
+ return bitwiseAndScalar(lhs, rhs, allocator);
+ }
+
/// operands must be integers; handles undefined.
- pub fn bitwiseAnd(lhs: Value, rhs: Value, arena: Allocator) !Value {
+ pub fn bitwiseAndScalar(lhs: Value, rhs: Value, arena: Allocator) !Value {
if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
// TODO is this a performance issue? maybe we should try the operation without
@@ -3070,22 +3271,46 @@ pub const Value = extern union {
return fromBigInt(arena, result_bigint.toConst());
}
- /// operands must be integers; handles undefined.
+ /// operands must be (vectors of) integers; handles undefined scalars.
pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: Allocator, target: Target) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try bitwiseNandScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return bitwiseNandScalar(lhs, rhs, ty, arena, target);
+ }
+
+ /// operands must be integers; handles undefined.
+ pub fn bitwiseNandScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, target: Target) !Value {
if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
- const anded = try bitwiseAnd(lhs, rhs, arena);
+ const anded = try bitwiseAnd(lhs, rhs, ty, arena);
const all_ones = if (ty.isSignedInt())
try Value.Tag.int_i64.create(arena, -1)
else
try ty.maxInt(arena, target);
- return bitwiseXor(anded, all_ones, arena);
+ return bitwiseXor(anded, all_ones, ty, arena);
+ }
+
+ /// operands must be (vectors of) integers; handles undefined scalars.
+ pub fn bitwiseOr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try allocator.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try bitwiseOrScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
+ }
+ return Value.Tag.aggregate.create(allocator, result_data);
+ }
+ return bitwiseOrScalar(lhs, rhs, allocator);
}
/// operands must be integers; handles undefined.
- pub fn bitwiseOr(lhs: Value, rhs: Value, arena: Allocator) !Value {
+ pub fn bitwiseOrScalar(lhs: Value, rhs: Value, arena: Allocator) !Value {
if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
// TODO is this a performance issue? maybe we should try the operation without
@@ -3103,8 +3328,20 @@ pub const Value = extern union {
return fromBigInt(arena, result_bigint.toConst());
}
+ /// operands must be (vectors of) integers; handles undefined scalars.
+ pub fn bitwiseXor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try allocator.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try bitwiseXorScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
+ }
+ return Value.Tag.aggregate.create(allocator, result_data);
+ }
+ return bitwiseXorScalar(lhs, rhs, allocator);
+ }
+
/// operands must be integers; handles undefined.
- pub fn bitwiseXor(lhs: Value, rhs: Value, arena: Allocator) !Value {
+ pub fn bitwiseXorScalar(lhs: Value, rhs: Value, arena: Allocator) !Value {
if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
// TODO is this a performance issue? maybe we should try the operation without
@@ -3123,7 +3360,18 @@ pub const Value = extern union {
return fromBigInt(arena, result_bigint.toConst());
}
- pub fn intAdd(lhs: Value, rhs: Value, allocator: Allocator) !Value {
+ pub fn intAdd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try allocator.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try intAddScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
+ }
+ return Value.Tag.aggregate.create(allocator, result_data);
+ }
+ return intAddScalar(lhs, rhs, allocator);
+ }
+
+ pub fn intAddScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
// TODO is this a performance issue? maybe we should try the operation without
// resorting to BigInt first.
var lhs_space: Value.BigIntSpace = undefined;
@@ -3139,7 +3387,18 @@ pub const Value = extern union {
return fromBigInt(allocator, result_bigint.toConst());
}
- pub fn intSub(lhs: Value, rhs: Value, allocator: Allocator) !Value {
+ pub fn intSub(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try allocator.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try intSubScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
+ }
+ return Value.Tag.aggregate.create(allocator, result_data);
+ }
+ return intSubScalar(lhs, rhs, allocator);
+ }
+
+ pub fn intSubScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
// TODO is this a performance issue? maybe we should try the operation without
// resorting to BigInt first.
var lhs_space: Value.BigIntSpace = undefined;
@@ -3155,7 +3414,18 @@ pub const Value = extern union {
return fromBigInt(allocator, result_bigint.toConst());
}
- pub fn intDiv(lhs: Value, rhs: Value, allocator: Allocator) !Value {
+ pub fn intDiv(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try allocator.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try intDivScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
+ }
+ return Value.Tag.aggregate.create(allocator, result_data);
+ }
+ return intDivScalar(lhs, rhs, allocator);
+ }
+
+ pub fn intDivScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
// TODO is this a performance issue? maybe we should try the operation without
// resorting to BigInt first.
var lhs_space: Value.BigIntSpace = undefined;
@@ -3180,7 +3450,18 @@ pub const Value = extern union {
return fromBigInt(allocator, result_q.toConst());
}
- pub fn intDivFloor(lhs: Value, rhs: Value, allocator: Allocator) !Value {
+ pub fn intDivFloor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try allocator.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try intDivFloorScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
+ }
+ return Value.Tag.aggregate.create(allocator, result_data);
+ }
+ return intDivFloorScalar(lhs, rhs, allocator);
+ }
+
+ pub fn intDivFloorScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
// TODO is this a performance issue? maybe we should try the operation without
// resorting to BigInt first.
var lhs_space: Value.BigIntSpace = undefined;
@@ -3205,7 +3486,18 @@ pub const Value = extern union {
return fromBigInt(allocator, result_q.toConst());
}
- pub fn intRem(lhs: Value, rhs: Value, allocator: Allocator) !Value {
+ pub fn intRem(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try allocator.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try intRemScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
+ }
+ return Value.Tag.aggregate.create(allocator, result_data);
+ }
+ return intRemScalar(lhs, rhs, allocator);
+ }
+
+ pub fn intRemScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
// TODO is this a performance issue? maybe we should try the operation without
// resorting to BigInt first.
var lhs_space: Value.BigIntSpace = undefined;
@@ -3232,7 +3524,18 @@ pub const Value = extern union {
return fromBigInt(allocator, result_r.toConst());
}
- pub fn intMod(lhs: Value, rhs: Value, allocator: Allocator) !Value {
+ pub fn intMod(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try allocator.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try intModScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
+ }
+ return Value.Tag.aggregate.create(allocator, result_data);
+ }
+ return intModScalar(lhs, rhs, allocator);
+ }
+
+ pub fn intModScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
// TODO is this a performance issue? maybe we should try the operation without
// resorting to BigInt first.
var lhs_space: Value.BigIntSpace = undefined;
@@ -3270,6 +3573,17 @@ pub const Value = extern union {
}
pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try floatRemScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return floatRemScalar(lhs, rhs, float_type, arena, target);
+ }
+
+ pub fn floatRemScalar(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
switch (float_type.floatBits(target)) {
16 => {
const lhs_val = lhs.toFloat(f16);
@@ -3304,6 +3618,17 @@ pub const Value = extern union {
}
pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try floatModScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return floatModScalar(lhs, rhs, float_type, arena, target);
+ }
+
+ pub fn floatModScalar(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
switch (float_type.floatBits(target)) {
16 => {
const lhs_val = lhs.toFloat(f16);
@@ -3337,7 +3662,18 @@ pub const Value = extern union {
}
}
- pub fn intMul(lhs: Value, rhs: Value, allocator: Allocator) !Value {
+ pub fn intMul(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try allocator.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try intMulScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
+ }
+ return Value.Tag.aggregate.create(allocator, result_data);
+ }
+ return intMulScalar(lhs, rhs, allocator);
+ }
+
+ pub fn intMulScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
// TODO is this a performance issue? maybe we should try the operation without
// resorting to BigInt first.
var lhs_space: Value.BigIntSpace = undefined;
@@ -3358,7 +3694,30 @@ pub const Value = extern union {
return fromBigInt(allocator, result_bigint.toConst());
}
- pub fn intTrunc(val: Value, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16) !Value {
+ pub fn intTrunc(val: Value, ty: Type, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try allocator.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try intTruncScalar(val.indexVectorlike(i), allocator, signedness, bits);
+ }
+ return Value.Tag.aggregate.create(allocator, result_data);
+ }
+ return intTruncScalar(val, allocator, signedness, bits);
+ }
+
+ /// This variant may vectorize on `bits`. Asserts that `bits` is a (vector of) `u16`.
+ pub fn intTruncBitsAsValue(val: Value, ty: Type, allocator: Allocator, signedness: std.builtin.Signedness, bits: Value) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try allocator.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try intTruncScalar(val.indexVectorlike(i), allocator, signedness, @intCast(u16, bits.indexVectorlike(i).toUnsignedInt()));
+ }
+ return Value.Tag.aggregate.create(allocator, result_data);
+ }
+ return intTruncScalar(val, allocator, signedness, @intCast(u16, bits.toUnsignedInt()));
+ }
+
+ pub fn intTruncScalar(val: Value, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16) !Value {
if (bits == 0) return Value.zero;
var val_space: Value.BigIntSpace = undefined;
@@ -3374,7 +3733,18 @@ pub const Value = extern union {
return fromBigInt(allocator, result_bigint.toConst());
}
- pub fn shl(lhs: Value, rhs: Value, allocator: Allocator) !Value {
+ pub fn shl(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try allocator.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try shlScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
+ }
+ return Value.Tag.aggregate.create(allocator, result_data);
+ }
+ return shlScalar(lhs, rhs, allocator);
+ }
+
+ pub fn shlScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
// TODO is this a performance issue? maybe we should try the operation without
// resorting to BigInt first.
var lhs_space: Value.BigIntSpace = undefined;
@@ -3431,6 +3801,23 @@ pub const Value = extern union {
arena: Allocator,
target: Target,
) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try shlSatScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return shlSatScalar(lhs, rhs, ty, arena, target);
+ }
+
+ pub fn shlSatScalar(
+ lhs: Value,
+ rhs: Value,
+ ty: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
// TODO is this a performance issue? maybe we should try the operation without
// resorting to BigInt first.
const info = ty.intInfo(target);
@@ -3458,13 +3845,41 @@ pub const Value = extern union {
arena: Allocator,
target: Target,
) !Value {
- const shifted = try lhs.shl(rhs, arena);
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try shlTruncScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return shlTruncScalar(lhs, rhs, ty, arena, target);
+ }
+
+ pub fn shlTruncScalar(
+ lhs: Value,
+ rhs: Value,
+ ty: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
+ const shifted = try lhs.shl(rhs, ty, arena);
const int_info = ty.intInfo(target);
- const truncated = try shifted.intTrunc(arena, int_info.signedness, int_info.bits);
+ const truncated = try shifted.intTrunc(ty, arena, int_info.signedness, int_info.bits);
return truncated;
}
- pub fn shr(lhs: Value, rhs: Value, allocator: Allocator) !Value {
+ pub fn shr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try allocator.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try shrScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator);
+ }
+ return Value.Tag.aggregate.create(allocator, result_data);
+ }
+ return shrScalar(lhs, rhs, allocator);
+ }
+
+ pub fn shrScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value {
// TODO is this a performance issue? maybe we should try the operation without
// resorting to BigInt first.
var lhs_space: Value.BigIntSpace = undefined;
@@ -3498,6 +3913,23 @@ pub const Value = extern union {
arena: Allocator,
target: Target,
) !Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try floatAddScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return floatAddScalar(lhs, rhs, float_type, arena, target);
+ }
+
+ pub fn floatAddScalar(
+ lhs: Value,
+ rhs: Value,
+ float_type: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
switch (float_type.floatBits(target)) {
16 => {
const lhs_val = lhs.toFloat(f16);
@@ -3535,6 +3967,23 @@ pub const Value = extern union {
arena: Allocator,
target: Target,
) !Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try floatSubScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return floatSubScalar(lhs, rhs, float_type, arena, target);
+ }
+
+ pub fn floatSubScalar(
+ lhs: Value,
+ rhs: Value,
+ float_type: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
switch (float_type.floatBits(target)) {
16 => {
const lhs_val = lhs.toFloat(f16);
@@ -3572,6 +4021,23 @@ pub const Value = extern union {
arena: Allocator,
target: Target,
) !Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try floatDivScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return floatDivScalar(lhs, rhs, float_type, arena, target);
+ }
+
+ pub fn floatDivScalar(
+ lhs: Value,
+ rhs: Value,
+ float_type: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
switch (float_type.floatBits(target)) {
16 => {
const lhs_val = lhs.toFloat(f16);
@@ -3612,6 +4078,23 @@ pub const Value = extern union {
arena: Allocator,
target: Target,
) !Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try floatDivFloorScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return floatDivFloorScalar(lhs, rhs, float_type, arena, target);
+ }
+
+ pub fn floatDivFloorScalar(
+ lhs: Value,
+ rhs: Value,
+ float_type: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
switch (float_type.floatBits(target)) {
16 => {
const lhs_val = lhs.toFloat(f16);
@@ -3652,6 +4135,23 @@ pub const Value = extern union {
arena: Allocator,
target: Target,
) !Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try floatDivTruncScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return floatDivTruncScalar(lhs, rhs, float_type, arena, target);
+ }
+
+ pub fn floatDivTruncScalar(
+ lhs: Value,
+ rhs: Value,
+ float_type: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
switch (float_type.floatBits(target)) {
16 => {
const lhs_val = lhs.toFloat(f16);
@@ -3692,6 +4192,23 @@ pub const Value = extern union {
arena: Allocator,
target: Target,
) !Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try floatMulScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return floatMulScalar(lhs, rhs, float_type, arena, target);
+ }
+
+ pub fn floatMulScalar(
+ lhs: Value,
+ rhs: Value,
+ float_type: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
switch (float_type.floatBits(target)) {
16 => {
const lhs_val = lhs.toFloat(f16);
@@ -3726,6 +4243,17 @@ pub const Value = extern union {
}
pub fn sqrt(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try sqrtScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return sqrtScalar(val, float_type, arena, target);
+ }
+
+ pub fn sqrtScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
switch (float_type.floatBits(target)) {
16 => {
const f = val.toFloat(f16);
@@ -3758,6 +4286,17 @@ pub const Value = extern union {
}
pub fn sin(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try sinScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return sinScalar(val, float_type, arena, target);
+ }
+
+ pub fn sinScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
switch (float_type.floatBits(target)) {
16 => {
const f = val.toFloat(f16);
@@ -3790,6 +4329,17 @@ pub const Value = extern union {
}
pub fn cos(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try cosScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return cosScalar(val, float_type, arena, target);
+ }
+
+ pub fn cosScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
switch (float_type.floatBits(target)) {
16 => {
const f = val.toFloat(f16);
@@ -3822,6 +4372,17 @@ pub const Value = extern union {
}
pub fn exp(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try expScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return expScalar(val, float_type, arena, target);
+ }
+
+ pub fn expScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
switch (float_type.floatBits(target)) {
16 => {
const f = val.toFloat(f16);
@@ -3854,6 +4415,17 @@ pub const Value = extern union {
}
pub fn exp2(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try exp2Scalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return exp2Scalar(val, float_type, arena, target);
+ }
+
+ pub fn exp2Scalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
switch (float_type.floatBits(target)) {
16 => {
const f = val.toFloat(f16);
@@ -3886,6 +4458,17 @@ pub const Value = extern union {
}
pub fn log(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try logScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return logScalar(val, float_type, arena, target);
+ }
+
+ pub fn logScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
switch (float_type.floatBits(target)) {
16 => {
const f = val.toFloat(f16);
@@ -3918,6 +4501,17 @@ pub const Value = extern union {
}
pub fn log2(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try log2Scalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return log2Scalar(val, float_type, arena, target);
+ }
+
+ pub fn log2Scalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
switch (float_type.floatBits(target)) {
16 => {
const f = val.toFloat(f16);
@@ -3950,6 +4544,17 @@ pub const Value = extern union {
}
pub fn log10(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try log10Scalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return log10Scalar(val, float_type, arena, target);
+ }
+
+ pub fn log10Scalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
switch (float_type.floatBits(target)) {
16 => {
const f = val.toFloat(f16);
@@ -3982,6 +4587,17 @@ pub const Value = extern union {
}
pub fn fabs(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try fabsScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return fabsScalar(val, float_type, arena, target);
+ }
+
+ pub fn fabsScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
switch (float_type.floatBits(target)) {
16 => {
const f = val.toFloat(f16);
@@ -4011,6 +4627,17 @@ pub const Value = extern union {
}
pub fn floor(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try floorScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return floorScalar(val, float_type, arena, target);
+ }
+
+ pub fn floorScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
switch (float_type.floatBits(target)) {
16 => {
const f = val.toFloat(f16);
@@ -4040,6 +4667,17 @@ pub const Value = extern union {
}
pub fn ceil(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try ceilScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return ceilScalar(val, float_type, arena, target);
+ }
+
+ pub fn ceilScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
switch (float_type.floatBits(target)) {
16 => {
const f = val.toFloat(f16);
@@ -4069,6 +4707,17 @@ pub const Value = extern union {
}
pub fn round(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try roundScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return roundScalar(val, float_type, arena, target);
+ }
+
+ pub fn roundScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
switch (float_type.floatBits(target)) {
16 => {
const f = val.toFloat(f16);
@@ -4098,6 +4747,17 @@ pub const Value = extern union {
}
pub fn trunc(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try truncScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target);
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return truncScalar(val, float_type, arena, target);
+ }
+
+ pub fn truncScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
switch (float_type.floatBits(target)) {
16 => {
const f = val.toFloat(f16);
@@ -4134,6 +4794,31 @@ pub const Value = extern union {
arena: Allocator,
target: Target,
) Allocator.Error!Value {
+ if (float_type.zigTypeTag() == .Vector) {
+ const result_data = try arena.alloc(Value, float_type.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try mulAddScalar(
+ float_type.scalarType(),
+ mulend1.indexVectorlike(i),
+ mulend2.indexVectorlike(i),
+ addend.indexVectorlike(i),
+ arena,
+ target,
+ );
+ }
+ return Value.Tag.aggregate.create(arena, result_data);
+ }
+ return mulAddScalar(float_type, mulend1, mulend2, addend, arena, target);
+ }
+
+ pub fn mulAddScalar(
+ float_type: Type,
+ mulend1: Value,
+ mulend2: Value,
+ addend: Value,
+ arena: Allocator,
+ target: Target,
+ ) Allocator.Error!Value {
switch (float_type.floatBits(target)) {
16 => {
const m1 = mulend1.toFloat(f16);