Browse Source

Remove need for `simd.splat`

gingerBill 3 years ago
parent
commit
f308f37ba1
4 changed files with 76 additions and 39 deletions
  1. 2 7
      core/simd/simd.odin
  2. 8 0
      src/check_expr.cpp
  3. 21 5
      src/llvm_backend_const.cpp
  4. 45 27
      src/llvm_backend_expr.cpp

+ 2 - 7
core/simd/simd.odin

@@ -103,10 +103,6 @@ reverse :: intrinsics.simd_reverse
 rotate_left  :: intrinsics.simd_rotate_left
 rotate_left  :: intrinsics.simd_rotate_left
 rotate_right :: intrinsics.simd_rotate_right
 rotate_right :: intrinsics.simd_rotate_right
 
 
-splat :: #force_inline proc "contextless" ($T: typeid/#simd[$LANES]$E, value: E) -> T {
-	return T{0..<LANES = value}
-}
-
 to_array_ptr :: #force_inline proc "contextless" (v: ^#simd[$LANES]$E) -> ^[LANES]E {
 to_array_ptr :: #force_inline proc "contextless" (v: ^#simd[$LANES]$E) -> ^[LANES]E {
 	return (^[LANES]E)(v)
 	return (^[LANES]E)(v)
 }
 }
@@ -127,12 +123,11 @@ from_slice :: proc($T: typeid/#simd[$LANES]$E, slice: []E) -> T {
 }
 }
 
 
 bit_not :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_integer(E) {
 bit_not :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_integer(E) {
-	ones := splat(type_of(v), ~E(0))
-	return xor(v, ones)
+	return xor(v, T(~E(0)))
 }
 }
 
 
 copysign :: #force_inline proc "contextless" (v, sign: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_float(E) {
 copysign :: #force_inline proc "contextless" (v, sign: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_float(E) {
-	neg_zero := to_bits(splat(T, E(-0.0)))
+	neg_zero := to_bits(T(-0.0))
 	sign_bit := and(to_bits(sign), neg_zero)
 	sign_bit := and(to_bits(sign), neg_zero)
 	magnitude := and(to_bits(v), bit_not(neg_zero))
 	magnitude := and(to_bits(v), bit_not(neg_zero))
 	return transmute(T)or(sign_bit, magnitude)
 	return transmute(T)or(sign_bit, magnitude)

+ 8 - 0
src/check_expr.cpp

@@ -2713,6 +2713,14 @@ bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) {
 		return check_is_castable_to(c, &x, elem_dst);
 		return check_is_castable_to(c, &x, elem_dst);
 	}
 	}
 
 
+	if (is_type_simd_vector(dst)) {
+		Type *elem = base_array_type(dst);
+		if (check_is_castable_to(c, operand, elem)) {
+			return true;
+		}
+	}
+
+
 	return false;
 	return false;
 }
 }
 
 

+ 21 - 5
src/llvm_backend_const.cpp

@@ -495,9 +495,9 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
 		res.value = data;
 		res.value = data;
 		return res;
 		return res;
 	} else if (is_type_array(type) &&
 	} else if (is_type_array(type) &&
-	    value.kind != ExactValue_Invalid &&
-	    value.kind != ExactValue_String &&
-	    value.kind != ExactValue_Compound) {
+		value.kind != ExactValue_Invalid &&
+		value.kind != ExactValue_String &&
+		value.kind != ExactValue_Compound) {
 
 
 		i64 count  = type->Array.count;
 		i64 count  = type->Array.count;
 		Type *elem = type->Array.elem;
 		Type *elem = type->Array.elem;
@@ -513,8 +513,8 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
 		res.value = llvm_const_array(lb_type(m, elem), elems, cast(unsigned)count);
 		res.value = llvm_const_array(lb_type(m, elem), elems, cast(unsigned)count);
 		return res;
 		return res;
 	} else if (is_type_matrix(type) &&
 	} else if (is_type_matrix(type) &&
-	    value.kind != ExactValue_Invalid &&
-	    value.kind != ExactValue_Compound) {
+		value.kind != ExactValue_Invalid &&
+		value.kind != ExactValue_Compound) {
 		i64 row = type->Matrix.row_count;
 		i64 row = type->Matrix.row_count;
 		i64 column = type->Matrix.column_count;
 		i64 column = type->Matrix.column_count;
 		GB_ASSERT(row == column);
 		GB_ASSERT(row == column);
@@ -537,6 +537,22 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
 		
 		
 		res.value = LLVMConstArray(lb_type(m, elem), elems, cast(unsigned)total_elem_count);
 		res.value = LLVMConstArray(lb_type(m, elem), elems, cast(unsigned)total_elem_count);
 		return res;
 		return res;
+	} else if (is_type_simd_vector(type) &&
+		value.kind != ExactValue_Invalid &&
+		value.kind != ExactValue_Compound) {
+		i64 count = type->SimdVector.count;
+		Type *elem = type->SimdVector.elem;
+
+		lbValue single_elem = lb_const_value(m, elem, value, allow_local);
+		single_elem.value = llvm_const_cast(single_elem.value, lb_type(m, elem));
+
+		LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, count);
+		for (i64 i = 0; i < count; i++) {
+			elems[i] = single_elem.value;
+		}
+
+		res.value = LLVMConstVector(elems, cast(unsigned)count);
+		return res;
 	}
 	}
 
 
 	switch (value.kind) {
 	switch (value.kind) {

+ 45 - 27
src/llvm_backend_expr.cpp

@@ -1820,41 +1820,59 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 		return res;
 		return res;
 	}
 	}
 
 
-	if (is_type_simd_vector(src) && is_type_simd_vector(dst)) {
-		Type *src_elem = core_array_type(src);
-		Type *dst_elem = core_array_type(dst);
+	if (is_type_simd_vector(dst)) {
+		Type *et = base_array_type(dst);
+		if (is_type_simd_vector(src)) {
+			Type *src_elem = core_array_type(src);
+			Type *dst_elem = core_array_type(dst);
 
 
-		GB_ASSERT(src->SimdVector.count == dst->SimdVector.count);
+			GB_ASSERT(src->SimdVector.count == dst->SimdVector.count);
 
 
-		lbValue res = {};
-		res.type = t;
-		if (are_types_identical(src_elem, dst_elem)) {
-			res.value = value.value;
-		} else if (is_type_float(src_elem) && is_type_integer(dst_elem)) {
-			if (is_type_unsigned(dst_elem)) {
-				res.value = LLVMBuildFPToUI(p->builder, value.value, lb_type(m, t), "");
-			} else {
-				res.value = LLVMBuildFPToSI(p->builder, value.value, lb_type(m, t), "");
-			}
-		} else if (is_type_integer(src_elem) && is_type_float(dst_elem)) {
-			if (is_type_unsigned(src_elem)) {
-				res.value = LLVMBuildUIToFP(p->builder, value.value, lb_type(m, t), "");
+			lbValue res = {};
+			res.type = t;
+			if (are_types_identical(src_elem, dst_elem)) {
+				res.value = value.value;
+			} else if (is_type_float(src_elem) && is_type_integer(dst_elem)) {
+				if (is_type_unsigned(dst_elem)) {
+					res.value = LLVMBuildFPToUI(p->builder, value.value, lb_type(m, t), "");
+				} else {
+					res.value = LLVMBuildFPToSI(p->builder, value.value, lb_type(m, t), "");
+				}
+			} else if (is_type_integer(src_elem) && is_type_float(dst_elem)) {
+				if (is_type_unsigned(src_elem)) {
+					res.value = LLVMBuildUIToFP(p->builder, value.value, lb_type(m, t), "");
+				} else {
+					res.value = LLVMBuildSIToFP(p->builder, value.value, lb_type(m, t), "");
+				}
+			} else if ((is_type_integer(src_elem) || is_type_boolean(src_elem)) && is_type_integer(dst_elem)) {
+				res.value = LLVMBuildIntCast2(p->builder, value.value, lb_type(m, t), !is_type_unsigned(src_elem), "");
+			} else if (is_type_float(src_elem) && is_type_float(dst_elem)) {
+				res.value = LLVMBuildFPCast(p->builder, value.value, lb_type(m, t), "");
+			} else if (is_type_integer(src_elem) && is_type_boolean(dst_elem)) {
+				LLVMValueRef i1vector = LLVMBuildICmp(p->builder, LLVMIntNE, value.value, LLVMConstNull(LLVMTypeOf(value.value)), "");
+				res.value = LLVMBuildIntCast2(p->builder, i1vector, lb_type(m, t), !is_type_unsigned(src_elem), "");
 			} else {
 			} else {
-				res.value = LLVMBuildSIToFP(p->builder, value.value, lb_type(m, t), "");
+				GB_PANIC("Unhandled simd vector conversion: %s -> %s", type_to_string(src), type_to_string(dst));
 			}
 			}
-		} else if ((is_type_integer(src_elem) || is_type_boolean(src_elem)) && is_type_integer(dst_elem)) {
-			res.value = LLVMBuildIntCast2(p->builder, value.value, lb_type(m, t), !is_type_unsigned(src_elem), "");
-		} else if (is_type_float(src_elem) && is_type_float(dst_elem)) {
-			res.value = LLVMBuildFPCast(p->builder, value.value, lb_type(m, t), "");
-		} else if (is_type_integer(src_elem) && is_type_boolean(dst_elem)) {
-			LLVMValueRef i1vector = LLVMBuildICmp(p->builder, LLVMIntNE, value.value, LLVMConstNull(LLVMTypeOf(value.value)), "");
-			res.value = LLVMBuildIntCast2(p->builder, i1vector, lb_type(m, t), !is_type_unsigned(src_elem), "");
+			return res;
 		} else {
 		} else {
-			GB_PANIC("Unhandled simd vector conversion: %s -> %s", type_to_string(src), type_to_string(dst));
+			i64 count = get_array_type_count(dst);
+			LLVMTypeRef vt = lb_type(m, t);
+			LLVMTypeRef llvm_u32 = lb_type(m, t_u32);
+			LLVMValueRef elem = lb_emit_conv(p, value, et).value;
+			LLVMValueRef vector = LLVMConstNull(vt);
+			for (i64 i = 0; i < count; i++) {
+				LLVMValueRef idx = LLVMConstInt(llvm_u32, i, false);
+				vector = LLVMBuildInsertElement(p->builder, vector, elem, idx, "");
+			}
+			lbValue res = {};
+			res.type = t;
+			res.value = vector;
+			return res;
 		}
 		}
-		return res;
 	}
 	}
 
 
+
 	// Pointer <-> uintptr
 	// Pointer <-> uintptr
 	if (is_type_pointer(src) && is_type_uintptr(dst)) {
 	if (is_type_pointer(src) && is_type_uintptr(dst)) {
 		lbValue res = {};
 		lbValue res = {};