authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-05 00:01:15-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-05 02:59:02-05:00
logc478c7609e4529267d1ce030577777e836ffc10b
treee7973c148c363ba3957015597b585e7610e2aeb1
parentb2e9c0d0ff1dc6799fe3b5fdbecd53af176f37b7

CBE: implement vector operations

Also, bigint add and sub which is all I was actually trying to do.

11 files changed, 809 insertions(+), 479 deletions(-)

lib/zig.h+440-220
......@@ -612,12 +612,6 @@ static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8
612612#endif
613613}
614614
615static inline void zig_vaddo_u32(uint8_t *ov, uint32_t *res, int n,
616 const uint32_t *lhs, const uint32_t *rhs, uint8_t bits)
617{
618 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u32(&res[i], lhs[i], rhs[i], bits);
619}
620
621615zig_extern int32_t __addosi4(int32_t lhs, int32_t rhs, int *overflow);
622616static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
623617#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
......@@ -632,12 +626,6 @@ static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
632626 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
633627}
634628
635static inline void zig_vaddo_i32(uint8_t *ov, int32_t *res, int n,
636 const int32_t *lhs, const int32_t *rhs, uint8_t bits)
637{
638 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i32(&res[i], lhs[i], rhs[i], bits);
639}
640
641629static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
642630#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
643631 uint64_t full_res;
......@@ -650,12 +638,6 @@ static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
650638#endif
651639}
652640
653static inline void zig_vaddo_u64(uint8_t *ov, uint64_t *res, int n,
654 const uint64_t *lhs, const uint64_t *rhs, uint8_t bits)
655{
656 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u64(&res[i], lhs[i], rhs[i], bits);
657}
658
659641zig_extern int64_t __addodi4(int64_t lhs, int64_t rhs, int *overflow);
660642static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
661643#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
......@@ -670,12 +652,6 @@ static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
670652 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
671653}
672654
673static inline void zig_vaddo_i64(uint8_t *ov, int64_t *res, int n,
674 const int64_t *lhs, const int64_t *rhs, uint8_t bits)
675{
676 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i64(&res[i], lhs[i], rhs[i], bits);
677}
678
679655static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
680656#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
681657 uint8_t full_res;
......@@ -690,12 +666,6 @@ static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b
690666#endif
691667}
692668
693static inline void zig_vaddo_u8(uint8_t *ov, uint8_t *res, int n,
694 const uint8_t *lhs, const uint8_t *rhs, uint8_t bits)
695{
696 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u8(&res[i], lhs[i], rhs[i], bits);
697}
698
699669static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) {
700670#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
701671 int8_t full_res;
......@@ -710,12 +680,6 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
710680#endif
711681}
712682
713static inline void zig_vaddo_i8(uint8_t *ov, int8_t *res, int n,
714 const int8_t *lhs, const int8_t *rhs, uint8_t bits)
715{
716 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i8(&res[i], lhs[i], rhs[i], bits);
717}
718
719683static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) {
720684#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
721685 uint16_t full_res;
......@@ -730,12 +694,6 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
730694#endif
731695}
732696
733static inline void zig_vaddo_u16(uint8_t *ov, uint16_t *res, int n,
734 const uint16_t *lhs, const uint16_t *rhs, uint8_t bits)
735{
736 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u16(&res[i], lhs[i], rhs[i], bits);
737}
738
739697static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) {
740698#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
741699 int16_t full_res;
......@@ -750,12 +708,6 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
750708#endif
751709}
752710
753static inline void zig_vaddo_i16(uint8_t *ov, int16_t *res, int n,
754 const int16_t *lhs, const int16_t *rhs, uint8_t bits)
755{
756 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i16(&res[i], lhs[i], rhs[i], bits);
757}
758
759711static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
760712#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
761713 uint32_t full_res;
......@@ -768,12 +720,6 @@ static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8
768720#endif
769721}
770722
771static inline void zig_vsubo_u32(uint8_t *ov, uint32_t *res, int n,
772 const uint32_t *lhs, const uint32_t *rhs, uint8_t bits)
773{
774 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u32(&res[i], lhs[i], rhs[i], bits);
775}
776
777723zig_extern int32_t __subosi4(int32_t lhs, int32_t rhs, int *overflow);
778724static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
779725#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
......@@ -788,12 +734,6 @@ static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
788734 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
789735}
790736
791static inline void zig_vsubo_i32(uint8_t *ov, int32_t *res, int n,
792 const int32_t *lhs, const int32_t *rhs, uint8_t bits)
793{
794 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i32(&res[i], lhs[i], rhs[i], bits);
795}
796
797737static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
798738#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
799739 uint64_t full_res;
......@@ -806,12 +746,6 @@ static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
806746#endif
807747}
808748
809static inline void zig_vsubo_u64(uint8_t *ov, uint64_t *res, int n,
810 const uint64_t *lhs, const uint64_t *rhs, uint8_t bits)
811{
812 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u64(&res[i], lhs[i], rhs[i], bits);
813}
814
815749zig_extern int64_t __subodi4(int64_t lhs, int64_t rhs, int *overflow);
816750static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
817751#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
......@@ -826,12 +760,6 @@ static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
826760 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
827761}
828762
829static inline void zig_vsubo_i64(uint8_t *ov, int64_t *res, int n,
830 const int64_t *lhs, const int64_t *rhs, uint8_t bits)
831{
832 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i64(&res[i], lhs[i], rhs[i], bits);
833}
834
835763static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
836764#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
837765 uint8_t full_res;
......@@ -846,12 +774,6 @@ static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b
846774#endif
847775}
848776
849static inline void zig_vsubo_u8(uint8_t *ov, uint8_t *res, int n,
850 const uint8_t *lhs, const uint8_t *rhs, uint8_t bits)
851{
852 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u8(&res[i], lhs[i], rhs[i], bits);
853}
854
855777static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) {
856778#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
857779 int8_t full_res;
......@@ -866,13 +788,6 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
866788#endif
867789}
868790
869static inline void zig_vsubo_i8(uint8_t *ov, int8_t *res, int n,
870 const int8_t *lhs, const int8_t *rhs, uint8_t bits)
871{
872 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i8(&res[i], lhs[i], rhs[i], bits);
873}
874
875
876791static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) {
877792#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
878793 uint16_t full_res;
......@@ -887,13 +802,6 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
887802#endif
888803}
889804
890static inline void zig_vsubo_u16(uint8_t *ov, uint16_t *res, int n,
891 const uint16_t *lhs, const uint16_t *rhs, uint8_t bits)
892{
893 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u16(&res[i], lhs[i], rhs[i], bits);
894}
895
896
897805static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) {
898806#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
899807 int16_t full_res;
......@@ -908,12 +816,6 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
908816#endif
909817}
910818
911static inline void zig_vsubo_i16(uint8_t *ov, int16_t *res, int n,
912 const int16_t *lhs, const int16_t *rhs, uint8_t bits)
913{
914 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i16(&res[i], lhs[i], rhs[i], bits);
915}
916
917819static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
918820#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
919821 uint32_t full_res;
......@@ -926,12 +828,6 @@ static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8
926828#endif
927829}
928830
929static inline void zig_vmulo_u32(uint8_t *ov, uint32_t *res, int n,
930 const uint32_t *lhs, const uint32_t *rhs, uint8_t bits)
931{
932 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u32(&res[i], lhs[i], rhs[i], bits);
933}
934
935831zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow);
936832static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
937833#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
......@@ -946,12 +842,6 @@ static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
946842 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
947843}
948844
949static inline void zig_vmulo_i32(uint8_t *ov, int32_t *res, int n,
950 const int32_t *lhs, const int32_t *rhs, uint8_t bits)
951{
952 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i32(&res[i], lhs[i], rhs[i], bits);
953}
954
955845static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
956846#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
957847 uint64_t full_res;
......@@ -964,12 +854,6 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
964854#endif
965855}
966856
967static inline void zig_vmulo_u64(uint8_t *ov, uint64_t *res, int n,
968 const uint64_t *lhs, const uint64_t *rhs, uint8_t bits)
969{
970 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u64(&res[i], lhs[i], rhs[i], bits);
971}
972
973857zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
974858static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
975859#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
......@@ -984,12 +868,6 @@ static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
984868 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
985869}
986870
987static inline void zig_vmulo_i64(uint8_t *ov, int64_t *res, int n,
988 const int64_t *lhs, const int64_t *rhs, uint8_t bits)
989{
990 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i64(&res[i], lhs[i], rhs[i], bits);
991}
992
993871static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
994872#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
995873 uint8_t full_res;
......@@ -1004,12 +882,6 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b
1004882#endif
1005883}
1006884
1007static inline void zig_vmulo_u8(uint8_t *ov, uint8_t *res, int n,
1008 const uint8_t *lhs, const uint8_t *rhs, uint8_t bits)
1009{
1010 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u8(&res[i], lhs[i], rhs[i], bits);
1011}
1012
1013885static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) {
1014886#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
1015887 int8_t full_res;
......@@ -1024,12 +896,6 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
1024896#endif
1025897}
1026898
1027static inline void zig_vmulo_i8(uint8_t *ov, int8_t *res, int n,
1028 const int8_t *lhs, const int8_t *rhs, uint8_t bits)
1029{
1030 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i8(&res[i], lhs[i], rhs[i], bits);
1031}
1032
1033899static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) {
1034900#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
1035901 uint16_t full_res;
......@@ -1044,12 +910,6 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
1044910#endif
1045911}
1046912
1047static inline void zig_vmulo_u16(uint8_t *ov, uint16_t *res, int n,
1048 const uint16_t *lhs, const uint16_t *rhs, uint8_t bits)
1049{
1050 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u16(&res[i], lhs[i], rhs[i], bits);
1051}
1052
1053913static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) {
1054914#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
1055915 int16_t full_res;
......@@ -1064,12 +924,6 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
1064924#endif
1065925}
1066926
1067static inline void zig_vmulo_i16(uint8_t *ov, int16_t *res, int n,
1068 const int16_t *lhs, const int16_t *rhs, uint8_t bits)
1069{
1070 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i16(&res[i], lhs[i], rhs[i], bits);
1071}
1072
1073927#define zig_int_builtins(w) \
1074928 static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
1075929 *res = zig_shlw_u##w(lhs, rhs, bits); \
......@@ -2090,6 +1944,446 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
20901944 return 0;
20911945}
20921946
1947static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
1948 uint8_t *res_bytes = res;
1949 const uint8_t *lhs_bytes = lhs;
1950 const uint8_t *rhs_bytes = rhs;
1951 uint16_t byte_offset = 0;
1952 uint16_t remaining_bytes = zig_int_bytes(bits);
1953 uint16_t top_bits = remaining_bytes * 8 - bits;
1954 bool overflow = false;
1955
1956#if zig_big_endian
1957 byte_offset = remaining_bytes;
1958#endif
1959
1960 while (remaining_bytes >= 128 / CHAR_BIT) {
1961 uint16_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
1962
1963#if zig_big_endian
1964 byte_offset -= 128 / CHAR_BIT;
1965#endif
1966
1967 if (remaining_bytes == 128 / CHAR_BIT && is_signed) {
1968 zig_i128 res_limb;
1969 zig_i128 tmp_limb;
1970 zig_i128 lhs_limb;
1971 zig_i128 rhs_limb;
1972 bool limb_overflow;
1973
1974 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
1975 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
1976 limb_overflow = zig_addo_i128(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
1977 overflow = limb_overflow ^ zig_addo_i128(&res_limb, tmp_limb, zig_make_i128(INT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits);
1978 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
1979 } else {
1980 zig_u128 res_limb;
1981 zig_u128 tmp_limb;
1982 zig_u128 lhs_limb;
1983 zig_u128 rhs_limb;
1984 bool limb_overflow;
1985
1986 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
1987 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
1988 limb_overflow = zig_addo_u128(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
1989 overflow = limb_overflow ^ zig_addo_u128(&res_limb, tmp_limb, zig_make_u128(UINT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits);
1990 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
1991 }
1992
1993 remaining_bytes -= 128 / CHAR_BIT;
1994
1995#if zig_little_endian
1996 byte_offset += 128 / CHAR_BIT;
1997#endif
1998 }
1999
2000 while (remaining_bytes >= 64 / CHAR_BIT) {
2001 uint16_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
2002
2003#if zig_big_endian
2004 byte_offset -= 64 / CHAR_BIT;
2005#endif
2006
2007 if (remaining_bytes == 64 / CHAR_BIT && is_signed) {
2008 int64_t res_limb;
2009 int64_t tmp_limb;
2010 int64_t lhs_limb;
2011 int64_t rhs_limb;
2012 bool limb_overflow;
2013
2014 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2015 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2016 limb_overflow = zig_addo_i64(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2017 overflow = limb_overflow ^ zig_addo_i64(&res_limb, tmp_limb, overflow ? INT64_C(1) : INT64_C(0), limb_bits);
2018 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2019 } else {
2020 uint64_t res_limb;
2021 uint64_t tmp_limb;
2022 uint64_t lhs_limb;
2023 uint64_t rhs_limb;
2024 bool limb_overflow;
2025
2026 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2027 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2028 limb_overflow = zig_addo_u64(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2029 overflow = limb_overflow ^ zig_addo_u64(&res_limb, tmp_limb, overflow ? UINT64_C(1) : UINT64_C(0), limb_bits);
2030 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2031 }
2032
2033 remaining_bytes -= 64 / CHAR_BIT;
2034
2035#if zig_little_endian
2036 byte_offset += 64 / CHAR_BIT;
2037#endif
2038 }
2039
2040 while (remaining_bytes >= 32 / CHAR_BIT) {
2041 uint16_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
2042
2043#if zig_big_endian
2044 byte_offset -= 32 / CHAR_BIT;
2045#endif
2046
2047 if (remaining_bytes == 32 / CHAR_BIT && is_signed) {
2048 int32_t res_limb;
2049 int32_t tmp_limb;
2050 int32_t lhs_limb;
2051 int32_t rhs_limb;
2052 bool limb_overflow;
2053
2054 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2055 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2056 limb_overflow = zig_addo_i32(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2057 overflow = limb_overflow ^ zig_addo_i32(&res_limb, tmp_limb, overflow ? INT32_C(1) : INT32_C(0), limb_bits);
2058 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2059 } else {
2060 uint32_t res_limb;
2061 uint32_t tmp_limb;
2062 uint32_t lhs_limb;
2063 uint32_t rhs_limb;
2064 bool limb_overflow;
2065
2066 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2067 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2068 limb_overflow = zig_addo_u32(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2069 overflow = limb_overflow ^ zig_addo_u32(&res_limb, tmp_limb, overflow ? UINT32_C(1) : UINT32_C(0), limb_bits);
2070 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2071 }
2072
2073 remaining_bytes -= 32 / CHAR_BIT;
2074
2075#if zig_little_endian
2076 byte_offset += 32 / CHAR_BIT;
2077#endif
2078 }
2079
2080 while (remaining_bytes >= 16 / CHAR_BIT) {
2081 uint16_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
2082
2083#if zig_big_endian
2084 byte_offset -= 16 / CHAR_BIT;
2085#endif
2086
2087 if (remaining_bytes == 16 / CHAR_BIT && is_signed) {
2088 int16_t res_limb;
2089 int16_t tmp_limb;
2090 int16_t lhs_limb;
2091 int16_t rhs_limb;
2092 bool limb_overflow;
2093
2094 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2095 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2096 limb_overflow = zig_addo_i16(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2097 overflow = limb_overflow ^ zig_addo_i16(&res_limb, tmp_limb, overflow ? INT16_C(1) : INT16_C(0), limb_bits);
2098 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2099 } else {
2100 uint16_t res_limb;
2101 uint16_t tmp_limb;
2102 uint16_t lhs_limb;
2103 uint16_t rhs_limb;
2104 bool limb_overflow;
2105
2106 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2107 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2108 limb_overflow = zig_addo_u16(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2109 overflow = limb_overflow ^ zig_addo_u16(&res_limb, tmp_limb, overflow ? UINT16_C(1) : UINT16_C(0), limb_bits);
2110 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2111 }
2112
2113 remaining_bytes -= 16 / CHAR_BIT;
2114
2115#if zig_little_endian
2116 byte_offset += 16 / CHAR_BIT;
2117#endif
2118 }
2119
2120 while (remaining_bytes >= 8 / CHAR_BIT) {
2121 uint16_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
2122
2123#if zig_big_endian
2124 byte_offset -= 8 / CHAR_BIT;
2125#endif
2126
2127 if (remaining_bytes == 8 / CHAR_BIT && is_signed) {
2128 int8_t res_limb;
2129 int8_t tmp_limb;
2130 int8_t lhs_limb;
2131 int8_t rhs_limb;
2132 bool limb_overflow;
2133
2134 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2135 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2136 limb_overflow = zig_addo_i8(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2137 overflow = limb_overflow ^ zig_addo_i8(&res_limb, tmp_limb, overflow ? INT8_C(1) : INT8_C(0), limb_bits);
2138 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2139 } else {
2140 uint8_t res_limb;
2141 uint8_t tmp_limb;
2142 uint8_t lhs_limb;
2143 uint8_t rhs_limb;
2144 bool limb_overflow;
2145
2146 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2147 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2148 limb_overflow = zig_addo_u8(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2149 overflow = limb_overflow ^ zig_addo_u8(&res_limb, tmp_limb, overflow ? UINT8_C(1) : UINT8_C(0), limb_bits);
2150 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2151 }
2152
2153 remaining_bytes -= 8 / CHAR_BIT;
2154
2155#if zig_little_endian
2156 byte_offset += 8 / CHAR_BIT;
2157#endif
2158 }
2159
2160 return overflow;
2161}
2162
2163static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2164 uint8_t *res_bytes = res;
2165 const uint8_t *lhs_bytes = lhs;
2166 const uint8_t *rhs_bytes = rhs;
2167 uint16_t byte_offset = 0;
2168 uint16_t remaining_bytes = zig_int_bytes(bits);
2169 uint16_t top_bits = remaining_bytes * 8 - bits;
2170 bool overflow = false;
2171
2172#if zig_big_endian
2173 byte_offset = remaining_bytes;
2174#endif
2175
2176 while (remaining_bytes >= 128 / CHAR_BIT) {
2177 uint16_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
2178
2179#if zig_big_endian
2180 byte_offset -= 128 / CHAR_BIT;
2181#endif
2182
2183 if (remaining_bytes == 128 / CHAR_BIT && is_signed) {
2184 zig_i128 res_limb;
2185 zig_i128 tmp_limb;
2186 zig_i128 lhs_limb;
2187 zig_i128 rhs_limb;
2188 bool limb_overflow;
2189
2190 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2191 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2192 limb_overflow = zig_subo_i128(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2193 overflow = limb_overflow ^ zig_subo_i128(&res_limb, tmp_limb, zig_make_i128(INT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits);
2194 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2195 } else {
2196 zig_u128 res_limb;
2197 zig_u128 tmp_limb;
2198 zig_u128 lhs_limb;
2199 zig_u128 rhs_limb;
2200 bool limb_overflow;
2201
2202 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2203 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2204 limb_overflow = zig_subo_u128(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2205 overflow = limb_overflow ^ zig_subo_u128(&res_limb, tmp_limb, zig_make_u128(UINT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits);
2206 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2207 }
2208
2209 remaining_bytes -= 128 / CHAR_BIT;
2210
2211#if zig_little_endian
2212 byte_offset += 128 / CHAR_BIT;
2213#endif
2214 }
2215
2216 while (remaining_bytes >= 64 / CHAR_BIT) {
2217 uint16_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
2218
2219#if zig_big_endian
2220 byte_offset -= 64 / CHAR_BIT;
2221#endif
2222
2223 if (remaining_bytes == 64 / CHAR_BIT && is_signed) {
2224 int64_t res_limb;
2225 int64_t tmp_limb;
2226 int64_t lhs_limb;
2227 int64_t rhs_limb;
2228 bool limb_overflow;
2229
2230 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2231 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2232 limb_overflow = zig_subo_i64(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2233 overflow = limb_overflow ^ zig_subo_i64(&res_limb, tmp_limb, overflow ? INT64_C(1) : INT64_C(0), limb_bits);
2234 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2235 } else {
2236 uint64_t res_limb;
2237 uint64_t tmp_limb;
2238 uint64_t lhs_limb;
2239 uint64_t rhs_limb;
2240 bool limb_overflow;
2241
2242 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2243 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2244 limb_overflow = zig_subo_u64(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2245 overflow = limb_overflow ^ zig_subo_u64(&res_limb, tmp_limb, overflow ? UINT64_C(1) : UINT64_C(0), limb_bits);
2246 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2247 }
2248
2249 remaining_bytes -= 64 / CHAR_BIT;
2250
2251#if zig_little_endian
2252 byte_offset += 64 / CHAR_BIT;
2253#endif
2254 }
2255
2256 while (remaining_bytes >= 32 / CHAR_BIT) {
2257 uint16_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
2258
2259#if zig_big_endian
2260 byte_offset -= 32 / CHAR_BIT;
2261#endif
2262
2263 if (remaining_bytes == 32 / CHAR_BIT && is_signed) {
2264 int32_t res_limb;
2265 int32_t tmp_limb;
2266 int32_t lhs_limb;
2267 int32_t rhs_limb;
2268 bool limb_overflow;
2269
2270 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2271 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2272 limb_overflow = zig_subo_i32(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2273 overflow = limb_overflow ^ zig_subo_i32(&res_limb, tmp_limb, overflow ? INT32_C(1) : INT32_C(0), limb_bits);
2274 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2275 } else {
2276 uint32_t res_limb;
2277 uint32_t tmp_limb;
2278 uint32_t lhs_limb;
2279 uint32_t rhs_limb;
2280 bool limb_overflow;
2281
2282 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2283 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2284 limb_overflow = zig_subo_u32(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2285 overflow = limb_overflow ^ zig_subo_u32(&res_limb, tmp_limb, overflow ? UINT32_C(1) : UINT32_C(0), limb_bits);
2286 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2287 }
2288
2289 remaining_bytes -= 32 / CHAR_BIT;
2290
2291#if zig_little_endian
2292 byte_offset += 32 / CHAR_BIT;
2293#endif
2294 }
2295
2296 while (remaining_bytes >= 16 / CHAR_BIT) {
2297 uint16_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
2298
2299#if zig_big_endian
2300 byte_offset -= 16 / CHAR_BIT;
2301#endif
2302
2303 if (remaining_bytes == 16 / CHAR_BIT && is_signed) {
2304 int16_t res_limb;
2305 int16_t tmp_limb;
2306 int16_t lhs_limb;
2307 int16_t rhs_limb;
2308 bool limb_overflow;
2309
2310 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2311 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2312 limb_overflow = zig_subo_i16(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2313 overflow = limb_overflow ^ zig_subo_i16(&res_limb, tmp_limb, overflow ? INT16_C(1) : INT16_C(0), limb_bits);
2314 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2315 } else {
2316 uint16_t res_limb;
2317 uint16_t tmp_limb;
2318 uint16_t lhs_limb;
2319 uint16_t rhs_limb;
2320 bool limb_overflow;
2321
2322 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2323 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2324 limb_overflow = zig_subo_u16(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2325 overflow = limb_overflow ^ zig_subo_u16(&res_limb, tmp_limb, overflow ? UINT16_C(1) : UINT16_C(0), limb_bits);
2326 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2327 }
2328
2329 remaining_bytes -= 16 / CHAR_BIT;
2330
2331#if zig_little_endian
2332 byte_offset += 16 / CHAR_BIT;
2333#endif
2334 }
2335
2336 while (remaining_bytes >= 8 / CHAR_BIT) {
2337 uint16_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
2338
2339#if zig_big_endian
2340 byte_offset -= 8 / CHAR_BIT;
2341#endif
2342
2343 if (remaining_bytes == 8 / CHAR_BIT && is_signed) {
2344 int8_t res_limb;
2345 int8_t tmp_limb;
2346 int8_t lhs_limb;
2347 int8_t rhs_limb;
2348 bool limb_overflow;
2349
2350 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2351 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2352 limb_overflow = zig_subo_i8(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2353 overflow = limb_overflow ^ zig_subo_i8(&res_limb, tmp_limb, overflow ? INT8_C(1) : INT8_C(0), limb_bits);
2354 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2355 } else {
2356 uint8_t res_limb;
2357 uint8_t tmp_limb;
2358 uint8_t lhs_limb;
2359 uint8_t rhs_limb;
2360 bool limb_overflow;
2361
2362 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2363 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2364 limb_overflow = zig_subo_u8(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2365 overflow = limb_overflow ^ zig_subo_u8(&res_limb, tmp_limb, overflow ? UINT8_C(1) : UINT8_C(0), limb_bits);
2366 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2367 }
2368
2369 remaining_bytes -= 8 / CHAR_BIT;
2370
2371#if zig_little_endian
2372 byte_offset += 8 / CHAR_BIT;
2373#endif
2374 }
2375
2376 return overflow;
2377}
2378
2379static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2380 (void)zig_addo_big(res, lhs, rhs, is_signed, bits);
2381}
2382
2383static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2384 (void)zig_subo_big(res, lhs, rhs, is_signed, bits);
2385}
2386
20932387static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) {
20942388 const uint8_t *val_bytes = val;
20952389 uint16_t byte_offset = 0;
......@@ -3092,80 +3386,6 @@ zig_msvc_atomics_128op(u128, max)
30923386
30933387#endif /* _MSC_VER && (_M_IX86 || _M_X64) */
30943388
3095/* ============================= Vector Support ============================= */
3096
3097#define zig_cmp_vec(operation, operator) \
3098 static inline void zig_##operation##_vec(bool *result, const void *lhs, const void *rhs, uint32_t len, bool is_signed, uint16_t elem_bits) { \
3099 uint32_t index = 0; \
3100 const uint8_t *lhs_ptr = lhs; \
3101 const uint8_t *rhs_ptr = rhs; \
3102 uint16_t elem_bytes = zig_int_bytes(elem_bits); \
3103 \
3104 while (index < len) { \
3105 result[index] = zig_cmp_big(lhs_ptr, rhs_ptr, is_signed, elem_bits) operator 0; \
3106 lhs_ptr += elem_bytes; \
3107 rhs_ptr += elem_bytes; \
3108 index += 1; \
3109 } \
3110 }
3111zig_cmp_vec(eq, ==)
3112zig_cmp_vec(ne, !=)
3113zig_cmp_vec(lt, < )
3114zig_cmp_vec(le, <=)
3115zig_cmp_vec(gt, > )
3116zig_cmp_vec(ge, >=)
3117
3118static inline void zig_clz_vec(void *result, const void *val, uint32_t len, bool is_signed, uint16_t elem_bits) {
3119 uint32_t index = 0;
3120 const uint8_t *val_ptr = val;
3121 uint16_t elem_bytes = zig_int_bytes(elem_bits);
3122
3123 while (index < len) {
3124 uint16_t lz = zig_clz_big(val_ptr, is_signed, elem_bits);
3125 if (elem_bits <= 128) {
3126 ((uint8_t *)result)[index] = (uint8_t)lz;
3127 } else {
3128 ((uint16_t *)result)[index] = lz;
3129 }
3130 val_ptr += elem_bytes;
3131 index += 1;
3132 }
3133}
3134
3135static inline void zig_ctz_vec(void *result, const void *val, uint32_t len, bool is_signed, uint16_t elem_bits) {
3136 uint32_t index = 0;
3137 const uint8_t *val_ptr = val;
3138 uint16_t elem_bytes = zig_int_bytes(elem_bits);
3139
3140 while (index < len) {
3141 uint16_t tz = zig_ctz_big(val_ptr, is_signed, elem_bits);
3142 if (elem_bits <= 128) {
3143 ((uint8_t *)result)[index] = (uint8_t)tz;
3144 } else {
3145 ((uint16_t *)result)[index] = tz;
3146 }
3147 val_ptr += elem_bytes;
3148 index += 1;
3149 }
3150}
3151
3152static inline void zig_popcount_vec(void *result, const void *val, uint32_t len, bool is_signed, uint16_t elem_bits) {
3153 uint32_t index = 0;
3154 const uint8_t *val_ptr = val;
3155 uint16_t elem_bytes = zig_int_bytes(elem_bits);
3156
3157 while (index < len) {
3158 uint16_t pc = zig_popcount_big(val_ptr, is_signed, elem_bits);
3159 if (elem_bits <= 128) {
3160 ((uint8_t *)result)[index] = (uint8_t)pc;
3161 } else {
3162 ((uint16_t *)result)[index] = pc;
3163 }
3164 val_ptr += elem_bytes;
3165 index += 1;
3166 }
3167}
3168
31693389/* ======================== Special Case Intrinsics ========================= */
31703390
31713391#if (_MSC_VER && _M_X64) || defined(__x86_64__)
src/codegen/c.zig+357-209
......@@ -444,8 +444,8 @@ pub const Function = struct {
444444 return f.object.dg.renderType(w, t);
445445 }
446446
447 fn renderIntCast(f: *Function, w: anytype, dest_ty: Type, src: CValue, src_ty: Type, location: ValueRenderLocation) !void {
448 return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src } }, src_ty, location);
447 fn renderIntCast(f: *Function, w: anytype, dest_ty: Type, src: CValue, v: Vectorizer, src_ty: Type, location: ValueRenderLocation) !void {
448 return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location);
449449 }
450450
451451 fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) {
......@@ -1593,6 +1593,7 @@ pub const DeclGen = struct {
15931593 c_value: struct {
15941594 f: *Function,
15951595 value: CValue,
1596 v: Vectorizer,
15961597 },
15971598 value: struct {
15981599 value: Value,
......@@ -1602,6 +1603,7 @@ pub const DeclGen = struct {
16021603 switch (self.*) {
16031604 .c_value => |v| {
16041605 try v.f.writeCValue(w, v.value, location);
1606 try v.v.elem(v.f, w);
16051607 },
16061608 .value => |v| {
16071609 try dg.renderValue(w, value_ty, v.value, location);
......@@ -1887,7 +1889,6 @@ pub const DeclGen = struct {
18871889 if (cty.isFloat()) cty.floatActiveBits(dg.module.getTarget()) else dg.byteSize(cty) * 8,
18881890 }),
18891891 .array => try writer.writeAll("big"),
1890 .vector => try writer.writeAll("vec"),
18911892 }
18921893 }
18931894
......@@ -1895,34 +1896,19 @@ pub const DeclGen = struct {
18951896 switch (info) {
18961897 .none => {},
18971898 .bits => {
1898 const cty = try dg.typeToCType(ty, .complete);
1899 if (cty.castTag(.vector)) |pl| {
1900 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = pl.data.len };
1901 try writer.print(", {}", .{try dg.fmtIntLiteral(
1902 Type.u32,
1903 Value.initPayload(&len_pl.base),
1904 .FunctionArgument,
1905 )});
1906 }
1907
19081899 const target = dg.module.getTarget();
1909 const elem_ty = ty.shallowElemType();
1910 const elem_info = if (elem_ty.isAbiInt())
1911 elem_ty.intInfo(target)
1912 else
1913 std.builtin.Type.Int{
1914 .signedness = .unsigned,
1915 .bits = @intCast(u16, elem_ty.bitSize(target)),
1916 };
1917 switch (cty.tag()) {
1918 else => {},
1919 .array, .vector => try writer.print(", {}", .{elem_info.signedness == .signed}),
1920 }
1900 const int_info = if (ty.isAbiInt()) ty.intInfo(target) else std.builtin.Type.Int{
1901 .signedness = .unsigned,
1902 .bits = @intCast(u16, ty.bitSize(target)),
1903 };
1904
1905 const cty = try dg.typeToCType(ty, .complete);
1906 if (cty.tag() == .array) try writer.print(", {}", .{int_info.signedness == .signed});
19211907
1922 var bits_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = elem_info.bits };
1908 var bits_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = int_info.bits };
19231909 try writer.print(", {}", .{try dg.fmtIntLiteral(switch (cty.tag()) {
19241910 else => Type.u8,
1925 .array, .vector => Type.u16,
1911 .array => Type.u16,
19261912 }, Value.initPayload(&bits_pl.base), .FunctionArgument)});
19271913 },
19281914 }
......@@ -2786,10 +2772,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
27862772 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none),
27872773 .rem => blk: {
27882774 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2789 const lhs_ty = f.air.typeOf(bin_op.lhs);
2775 const lhs_scalar_ty = f.air.typeOf(bin_op.lhs).scalarType();
27902776 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
27912777 // so we only check one.
2792 break :blk if (lhs_ty.isInt())
2778 break :blk if (lhs_scalar_ty.isInt())
27932779 try airBinOp(f, inst, "%", "rem", .none)
27942780 else
27952781 try airBinFloatOp(f, inst, "fmod");
......@@ -2833,10 +2819,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
28332819
28342820 .slice => try airSlice(f, inst),
28352821
2836 .cmp_gt => try airCmpOp(f, inst, .gt),
2837 .cmp_gte => try airCmpOp(f, inst, .gte),
2838 .cmp_lt => try airCmpOp(f, inst, .lt),
2839 .cmp_lte => try airCmpOp(f, inst, .lte),
2822 .cmp_gt => try airCmpOp(f, inst, f.air.instructions.items(.data)[inst].bin_op, .gt),
2823 .cmp_gte => try airCmpOp(f, inst, f.air.instructions.items(.data)[inst].bin_op, .gte),
2824 .cmp_lt => try airCmpOp(f, inst, f.air.instructions.items(.data)[inst].bin_op, .lt),
2825 .cmp_lte => try airCmpOp(f, inst, f.air.instructions.items(.data)[inst].bin_op, .lte),
28402826
28412827 .cmp_eq => try airEquality(f, inst, .eq),
28422828 .cmp_neq => try airEquality(f, inst, .neq),
......@@ -2844,7 +2830,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
28442830 .cmp_vector => blk: {
28452831 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
28462832 const extra = f.air.extraData(Air.VectorCmp, ty_pl.payload).data;
2847 break :blk try airCmpBuiltinCall(f, inst, extra, extra.compareOperator(), .operator, .bits,);
2833 break :blk try airCmpOp(f, inst, extra, extra.compareOperator());
28482834 },
28492835 .cmp_lt_errors_len => try airCmpLtErrorsLen(f, inst),
28502836
......@@ -3294,7 +3280,10 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {
32943280
32953281fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
32963282 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
3297 const ptr_info = f.air.typeOf(ty_op.operand).ptrInfo().data;
3283
3284 const ptr_ty = f.air.typeOf(ty_op.operand);
3285 const ptr_scalar_ty = ptr_ty.scalarType();
3286 const ptr_info = ptr_scalar_ty.ptrInfo().data;
32983287 const src_ty = ptr_info.pointee_type;
32993288
33003289 if (!src_ty.hasRuntimeBitsIgnoreComptime() or
......@@ -3312,16 +3301,19 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
33123301 const is_aligned = ptr_info.@"align" == 0 or ptr_info.@"align" >= src_ty.abiAlignment(target);
33133302 const is_array = lowersToArray(src_ty, target);
33143303 const need_memcpy = !is_aligned or is_array;
3315 const writer = f.object.writer();
33163304
3305 const writer = f.object.writer();
33173306 const local = try f.allocLocal(inst, src_ty);
3307 const v = try Vectorizer.start(f, inst, writer, ptr_ty);
33183308
33193309 if (need_memcpy) {
33203310 try writer.writeAll("memcpy(");
33213311 if (!is_array) try writer.writeByte('&');
3322 try f.writeCValue(writer, local, .FunctionArgument);
3312 try f.writeCValue(writer, local, .Other);
3313 try v.elem(f, writer);
33233314 try writer.writeAll(", (const char *)");
33243315 try f.writeCValue(writer, operand, .Other);
3316 try v.elem(f, writer);
33253317 try writer.writeAll(", sizeof(");
33263318 try f.renderType(writer, src_ty);
33273319 try writer.writeAll("))");
......@@ -3351,6 +3343,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
33513343 const field_ty = Type.initPayload(&field_pl.base);
33523344
33533345 try f.writeCValue(writer, local, .Other);
3346 try v.elem(f, writer);
33543347 try writer.writeAll(" = (");
33553348 try f.renderType(writer, src_ty);
33563349 try writer.writeAll(")zig_wrap_");
......@@ -3369,16 +3362,21 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
33693362 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
33703363 try writer.writeByte('(');
33713364 try f.writeCValueDeref(writer, operand);
3365 try v.elem(f, writer);
33723366 try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)});
33733367 if (cant_cast) try writer.writeByte(')');
33743368 try f.object.dg.renderBuiltinInfo(writer, field_ty, .bits);
33753369 try writer.writeByte(')');
33763370 } else {
33773371 try f.writeCValue(writer, local, .Other);
3372 try v.elem(f, writer);
33783373 try writer.writeAll(" = ");
33793374 try f.writeCValueDeref(writer, operand);
3375 try v.elem(f, writer);
33803376 }
33813377 try writer.writeAll(";\n");
3378 try v.end(f, inst, writer);
3379
33823380 return local;
33833381}
33843382
......@@ -3444,15 +3442,22 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
34443442
34453443 const operand = try f.resolveInst(ty_op.operand);
34463444 try reap(f, inst, &.{ty_op.operand});
3447 const writer = f.object.writer();
3445
34483446 const inst_ty = f.air.typeOfIndex(inst);
3449 const local = try f.allocLocal(inst, inst_ty);
3447 const inst_scalar_ty = inst_ty.scalarType();
34503448 const operand_ty = f.air.typeOf(ty_op.operand);
3449 const scalar_ty = operand_ty.scalarType();
34513450
3451 const writer = f.object.writer();
3452 const local = try f.allocLocal(inst, inst_ty);
3453 const v = try Vectorizer.start(f, inst, writer, operand_ty);
34523454 try f.writeCValue(writer, local, .Other);
3455 try v.elem(f, writer);
34533456 try writer.writeAll(" = ");
3454 try f.renderIntCast(writer, inst_ty, operand, operand_ty, .Other);
3457 try f.renderIntCast(writer, inst_scalar_ty, operand, v, scalar_ty, .Other);
34553458 try writer.writeAll(";\n");
3459 try v.end(f, inst, writer);
3460
34563461 return local;
34573462}
34583463
......@@ -3578,7 +3583,10 @@ fn storeUndefined(f: *Function, lhs_child_ty: Type, dest_ptr: CValue) !CValue {
35783583fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
35793584 // *a = b;
35803585 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3581 const ptr_info = f.air.typeOf(bin_op.lhs).ptrInfo().data;
3586
3587 const ptr_ty = f.air.typeOf(bin_op.lhs);
3588 const ptr_scalar_ty = ptr_ty.scalarType();
3589 const ptr_info = ptr_scalar_ty.ptrInfo().data;
35823590 if (!ptr_info.pointee_type.hasRuntimeBitsIgnoreComptime()) {
35833591 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
35843592 return .none;
......@@ -3601,11 +3609,13 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
36013609 ptr_info.@"align" >= ptr_info.pointee_type.abiAlignment(target);
36023610 const is_array = lowersToArray(ptr_info.pointee_type, target);
36033611 const need_memcpy = !is_aligned or is_array;
3604 const writer = f.object.writer();
36053612
36063613 const src_val = try f.resolveInst(bin_op.rhs);
36073614 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
36083615
3616 const writer = f.object.writer();
3617 const v = try Vectorizer.start(f, inst, writer, ptr_ty);
3618
36093619 if (need_memcpy) {
36103620 // For this memcpy to safely work we need the rhs to have the same
36113621 // underlying type as the lhs (i.e. they must both be arrays of the same underlying type).
......@@ -3626,9 +3636,11 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
36263636
36273637 try writer.writeAll("memcpy((char *)");
36283638 try f.writeCValue(writer, ptr_val, .FunctionArgument);
3639 try v.elem(f, writer);
36293640 try writer.writeAll(", ");
36303641 if (!is_array) try writer.writeByte('&');
36313642 try f.writeCValue(writer, array_src, .FunctionArgument);
3643 try v.elem(f, writer);
36323644 try writer.writeAll(", sizeof(");
36333645 try f.renderType(writer, src_ty);
36343646 try writer.writeAll("))");
......@@ -3672,12 +3684,14 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
36723684 const mask_val = Value.initPayload(&mask_pl.base);
36733685
36743686 try f.writeCValueDeref(writer, ptr_val);
3687 try v.elem(f, writer);
36753688 try writer.writeAll(" = zig_or_");
36763689 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
36773690 try writer.writeAll("(zig_and_");
36783691 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
36793692 try writer.writeByte('(');
36803693 try f.writeCValueDeref(writer, ptr_val);
3694 try v.elem(f, writer);
36813695 try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(host_ty, mask_val)});
36823696 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
36833697 try writer.writeByte('(');
......@@ -3699,14 +3713,19 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
36993713 try writer.writeByte(')');
37003714 }
37013715 try f.writeCValue(writer, src_val, .Other);
3716 try v.elem(f, writer);
37023717 if (cant_cast) try writer.writeByte(')');
37033718 try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)});
37043719 } else {
37053720 try f.writeCValueDeref(writer, ptr_val);
3721 try v.elem(f, writer);
37063722 try writer.writeAll(" = ");
37073723 try f.writeCValue(writer, src_val, .Other);
3724 try v.elem(f, writer);
37083725 }
37093726 try writer.writeAll(";\n");
3727 try v.end(f, inst, writer);
3728
37103729 return .none;
37113730}
37123731
......@@ -3724,51 +3743,39 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
37243743 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
37253744
37263745 const inst_ty = f.air.typeOfIndex(inst);
3727 const vector_ty = f.air.typeOf(bin_op.lhs);
3728 const scalar_ty = vector_ty.scalarType();
3729 const w = f.object.writer();
3746 const operand_ty = f.air.typeOf(bin_op.lhs);
3747 const scalar_ty = operand_ty.scalarType();
37303748
3749 const w = f.object.writer();
37313750 const local = try f.allocLocal(inst, inst_ty);
3732
3733 switch (vector_ty.zigTypeTag()) {
3734 .Vector => {
3735 try w.writeAll("zig_v");
3736 try w.writeAll(operation);
3737 try w.writeAll("o_");
3738 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3739 try w.writeAll("(");
3740 try f.writeCValueMember(w, local, .{ .field = 1 });
3741 try w.writeAll(", ");
3742 try f.writeCValueMember(w, local, .{ .field = 0 });
3743 try w.print(", {d}, ", .{vector_ty.vectorLen()});
3744 },
3745 else => {
3746 try f.writeCValueMember(w, local, .{ .field = 1 });
3747 try w.writeAll(" = zig_");
3748 try w.writeAll(operation);
3749 try w.writeAll("o_");
3750 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3751 try w.writeAll("(&");
3752 try f.writeCValueMember(w, local, .{ .field = 0 });
3753 try w.writeAll(", ");
3754 },
3755 }
3756
3751 const v = try Vectorizer.start(f, inst, w, operand_ty);
3752 try f.writeCValueMember(w, local, .{ .field = 1 });
3753 try v.elem(f, w);
3754 try w.writeAll(" = zig_");
3755 try w.writeAll(operation);
3756 try w.writeAll("o_");
3757 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3758 try w.writeAll("(&");
3759 try f.writeCValueMember(w, local, .{ .field = 0 });
3760 try v.elem(f, w);
3761 try w.writeAll(", ");
37573762 try f.writeCValue(w, lhs, .FunctionArgument);
3763 try v.elem(f, w);
37583764 try w.writeAll(", ");
37593765 try f.writeCValue(w, rhs, .FunctionArgument);
3766 try v.elem(f, w);
37603767 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
37613768 try w.writeAll(");\n");
3769 try v.end(f, inst, w);
37623770
37633771 return local;
37643772}
37653773
37663774fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
3767 const inst_ty = f.air.typeOfIndex(inst);
3768 if (inst_ty.tag() != .bool)
3769 return try airUnBuiltinCall(f, inst, "not", .bits);
3770
37713775 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
3776 const operand_ty = f.air.typeOf(ty_op.operand);
3777 const scalar_ty = operand_ty.scalarType();
3778 if (scalar_ty.tag() != .bool) return try airUnBuiltinCall(f, inst, "not", .bits);
37723779
37733780 if (f.liveness.isUnused(inst)) {
37743781 try reap(f, inst, &.{ty_op.operand});
......@@ -3778,14 +3785,20 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
37783785 const op = try f.resolveInst(ty_op.operand);
37793786 try reap(f, inst, &.{ty_op.operand});
37803787
3788 const inst_ty = f.air.typeOfIndex(inst);
3789
37813790 const writer = f.object.writer();
37823791 const local = try f.allocLocal(inst, inst_ty);
3783
3792 const v = try Vectorizer.start(f, inst, writer, operand_ty);
37843793 try f.writeCValue(writer, local, .Other);
3794 try v.elem(f, writer);
37853795 try writer.writeAll(" = ");
37863796 try writer.writeByte('!');
37873797 try f.writeCValue(writer, op, .Other);
3798 try v.elem(f, writer);
37883799 try writer.writeAll(";\n");
3800 try v.end(f, inst, writer);
3801
37893802 return local;
37903803}
37913804
......@@ -3798,71 +3811,89 @@ fn airBinOp(
37983811) !CValue {
37993812 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
38003813 const operand_ty = f.air.typeOf(bin_op.lhs);
3814 const scalar_ty = operand_ty.scalarType();
38013815 const target = f.object.dg.module.getTarget();
3802 if ((operand_ty.isInt() and operand_ty.bitSize(target) > 64) or operand_ty.isRuntimeFloat())
3816 if ((scalar_ty.isInt() and scalar_ty.bitSize(target) > 64) or scalar_ty.isRuntimeFloat())
38033817 return try airBinBuiltinCall(f, inst, operation, info);
38043818
3819 if (f.liveness.isUnused(inst)) {
3820 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3821 return .none;
3822 }
3823
38053824 const lhs = try f.resolveInst(bin_op.lhs);
38063825 const rhs = try f.resolveInst(bin_op.rhs);
3807
38083826 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
38093827
3810 if (f.liveness.isUnused(inst)) return .none;
3811
38123828 const inst_ty = f.air.typeOfIndex(inst);
38133829
38143830 const writer = f.object.writer();
38153831 const local = try f.allocLocal(inst, inst_ty);
3832 const v = try Vectorizer.start(f, inst, writer, operand_ty);
38163833 try f.writeCValue(writer, local, .Other);
3834 try v.elem(f, writer);
38173835 try writer.writeAll(" = ");
38183836 try f.writeCValue(writer, lhs, .Other);
3837 try v.elem(f, writer);
38193838 try writer.writeByte(' ');
38203839 try writer.writeAll(operator);
38213840 try writer.writeByte(' ');
38223841 try f.writeCValue(writer, rhs, .Other);
3842 try v.elem(f, writer);
38233843 try writer.writeAll(";\n");
3844 try v.end(f, inst, writer);
38243845
38253846 return local;
38263847}
38273848
3828fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: std.math.CompareOperator) !CValue {
3829 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3830
3849fn airCmpOp(
3850 f: *Function,
3851 inst: Air.Inst.Index,
3852 data: anytype,
3853 operator: std.math.CompareOperator,
3854) !CValue {
38313855 if (f.liveness.isUnused(inst)) {
3832 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3856 try reap(f, inst, &.{ data.lhs, data.rhs });
38333857 return .none;
38343858 }
38353859
3836 const operand_ty = f.air.typeOf(bin_op.lhs);
3860 const operand_ty = f.air.typeOf(data.lhs);
3861 const scalar_ty = operand_ty.scalarType();
3862
38373863 const target = f.object.dg.module.getTarget();
3838 const operand_bits = operand_ty.bitSize(target);
3839 if (operand_ty.isInt() and operand_bits > 64)
3864 const scalar_bits = scalar_ty.bitSize(target);
3865 if (scalar_ty.isInt() and scalar_bits > 64)
38403866 return airCmpBuiltinCall(
38413867 f,
38423868 inst,
3843 bin_op,
3869 data,
38443870 operator,
38453871 .cmp,
3846 if (operand_bits > 128) .bits else .none,
3872 if (scalar_bits > 128) .bits else .none,
38473873 );
3848 if (operand_ty.isRuntimeFloat())
3849 return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none);
3874 if (scalar_ty.isRuntimeFloat())
3875 return airCmpBuiltinCall(f, inst, data, operator, .operator, .none);
38503876
38513877 const inst_ty = f.air.typeOfIndex(inst);
3852 const lhs = try f.resolveInst(bin_op.lhs);
3853 const rhs = try f.resolveInst(bin_op.rhs);
3854 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3878 const lhs = try f.resolveInst(data.lhs);
3879 const rhs = try f.resolveInst(data.rhs);
3880 try reap(f, inst, &.{ data.lhs, data.rhs });
38553881
38563882 const writer = f.object.writer();
38573883 const local = try f.allocLocal(inst, inst_ty);
3884 const v = try Vectorizer.start(f, inst, writer, operand_ty);
38583885 try f.writeCValue(writer, local, .Other);
3886 try v.elem(f, writer);
38593887 try writer.writeAll(" = ");
38603888 try f.writeCValue(writer, lhs, .Other);
3889 try v.elem(f, writer);
38613890 try writer.writeByte(' ');
38623891 try writer.writeAll(compareOperatorC(operator));
38633892 try writer.writeByte(' ');
38643893 try f.writeCValue(writer, rhs, .Other);
3894 try v.elem(f, writer);
38653895 try writer.writeAll(";\n");
3896 try v.end(f, inst, writer);
38663897
38673898 return local;
38683899}
......@@ -3974,11 +4005,14 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
39744005 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
39754006
39764007 const inst_ty = f.air.typeOfIndex(inst);
3977 const elem_ty = inst_ty.elemType2();
4008 const inst_scalar_ty = inst_ty.scalarType();
4009 const elem_ty = inst_scalar_ty.elemType2();
39784010
39794011 const local = try f.allocLocal(inst, inst_ty);
39804012 const writer = f.object.writer();
4013 const v = try Vectorizer.start(f, inst, writer, inst_ty);
39814014 try f.writeCValue(writer, local, .Other);
4015 try v.elem(f, writer);
39824016 try writer.writeAll(" = ");
39834017
39844018 if (elem_ty.hasRuntimeBitsIgnoreComptime()) {
......@@ -3986,19 +4020,26 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
39864020 // results in a NULL pointer, or if LHS is NULL. The operation is only UB
39874021 // if the result is NULL and then dereferenced.
39884022 try writer.writeByte('(');
3989 try f.renderType(writer, inst_ty);
4023 try f.renderType(writer, inst_scalar_ty);
39904024 try writer.writeAll(")(((uintptr_t)");
39914025 try f.writeCValue(writer, lhs, .Other);
4026 try v.elem(f, writer);
39924027 try writer.writeAll(") ");
39934028 try writer.writeByte(operator);
39944029 try writer.writeAll(" (");
39954030 try f.writeCValue(writer, rhs, .Other);
4031 try v.elem(f, writer);
39964032 try writer.writeAll("*sizeof(");
39974033 try f.renderType(writer, elem_ty);
39984034 try writer.writeAll(")))");
3999 } else try f.writeCValue(writer, lhs, .Initializer);
4035 } else {
4036 try f.writeCValue(writer, lhs, .Other);
4037 try v.elem(f, writer);
4038 }
40004039
40014040 try writer.writeAll(";\n");
4041 try v.end(f, inst, writer);
4042
40024043 return local;
40034044}
40044045
......@@ -4011,10 +4052,12 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
40114052 }
40124053
40134054 const inst_ty = f.air.typeOfIndex(inst);
4055 const inst_scalar_ty = inst_ty.scalarType();
4056
40144057 const target = f.object.dg.module.getTarget();
4015 if (inst_ty.isInt() and inst_ty.bitSize(target) > 64)
4058 if (inst_scalar_ty.isInt() and inst_scalar_ty.bitSize(target) > 64)
40164059 return try airBinBuiltinCall(f, inst, operation[1..], .none);
4017 if (inst_ty.isRuntimeFloat())
4060 if (inst_scalar_ty.isRuntimeFloat())
40184061 return try airBinFloatOp(f, inst, operation);
40194062
40204063 const lhs = try f.resolveInst(bin_op.lhs);
......@@ -4023,19 +4066,26 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
40234066
40244067 const writer = f.object.writer();
40254068 const local = try f.allocLocal(inst, inst_ty);
4069 const v = try Vectorizer.start(f, inst, writer, inst_ty);
40264070 try f.writeCValue(writer, local, .Other);
4071 try v.elem(f, writer);
40274072 // (lhs <> rhs) ? lhs : rhs
40284073 try writer.writeAll(" = (");
40294074 try f.writeCValue(writer, lhs, .Other);
4075 try v.elem(f, writer);
40304076 try writer.writeByte(' ');
40314077 try writer.writeByte(operator);
40324078 try writer.writeByte(' ');
40334079 try f.writeCValue(writer, rhs, .Other);
4080 try v.elem(f, writer);
40344081 try writer.writeAll(") ? ");
40354082 try f.writeCValue(writer, lhs, .Other);
4083 try v.elem(f, writer);
40364084 try writer.writeAll(" : ");
40374085 try f.writeCValue(writer, rhs, .Other);
4086 try v.elem(f, writer);
40384087 try writer.writeAll(";\n");
4088 try v.end(f, inst, writer);
40394089
40404090 return local;
40414091}
......@@ -6002,30 +6052,35 @@ fn airUnBuiltinCall(
60026052 const operand = try f.resolveInst(ty_op.operand);
60036053 try reap(f, inst, &.{ty_op.operand});
60046054 const inst_ty = f.air.typeOfIndex(inst);
6055 const inst_scalar_ty = inst_ty.scalarType();
60056056 const operand_ty = f.air.typeOf(ty_op.operand);
6057 const scalar_ty = operand_ty.scalarType();
60066058
6007 const inst_cty = try f.typeToCType(inst_ty, .complete);
6008 const ref_ret = switch (inst_cty.tag()) {
6009 else => false,
6010 .array, .vector => true,
6011 };
6059 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
6060 const ref_ret = inst_scalar_cty.tag() == .array;
60126061
60136062 const writer = f.object.writer();
60146063 const local = try f.allocLocal(inst, inst_ty);
6064 const v = try Vectorizer.start(f, inst, writer, operand_ty);
60156065 if (!ref_ret) {
60166066 try f.writeCValue(writer, local, .Other);
6067 try v.elem(f, writer);
60176068 try writer.writeAll(" = ");
60186069 }
60196070 try writer.print("zig_{s}_", .{operation});
6020 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
6071 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
60216072 try writer.writeByte('(');
60226073 if (ref_ret) {
60236074 try f.writeCValue(writer, local, .FunctionArgument);
6075 try v.elem(f, writer);
60246076 try writer.writeAll(", ");
60256077 }
60266078 try f.writeCValue(writer, operand, .FunctionArgument);
6027 try f.object.dg.renderBuiltinInfo(writer, operand_ty, info);
6079 try v.elem(f, writer);
6080 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);
60286081 try writer.writeAll(");\n");
6082 try v.end(f, inst, writer);
6083
60296084 return local;
60306085}
60316086
......@@ -6047,21 +6102,38 @@ fn airBinBuiltinCall(
60476102 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
60486103
60496104 const inst_ty = f.air.typeOfIndex(inst);
6105 const inst_scalar_ty = inst_ty.scalarType();
60506106 const operand_ty = f.air.typeOf(bin_op.lhs);
6107 const scalar_ty = operand_ty.scalarType();
6108
6109 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
6110 const ref_ret = inst_scalar_cty.tag() == .array;
60516111
60526112 const writer = f.object.writer();
60536113 const local = try f.allocLocal(inst, inst_ty);
6054 try f.writeCValue(writer, local, .Other);
6055 try writer.writeAll(" = zig_");
6056 try writer.writeAll(operation);
6057 try writer.writeByte('_');
6058 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
6114 const v = try Vectorizer.start(f, inst, writer, operand_ty);
6115 if (!ref_ret) {
6116 try f.writeCValue(writer, local, .Other);
6117 try v.elem(f, writer);
6118 try writer.writeAll(" = ");
6119 }
6120 try writer.print("zig_{s}_", .{operation});
6121 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
60596122 try writer.writeByte('(');
6123 if (ref_ret) {
6124 try f.writeCValue(writer, local, .FunctionArgument);
6125 try v.elem(f, writer);
6126 try writer.writeAll(", ");
6127 }
60606128 try f.writeCValue(writer, lhs, .FunctionArgument);
6129 try v.elem(f, writer);
60616130 try writer.writeAll(", ");
60626131 try f.writeCValue(writer, rhs, .FunctionArgument);
6063 try f.object.dg.renderBuiltinInfo(writer, operand_ty, info);
6132 try v.elem(f, writer);
6133 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);
60646134 try writer.writeAll(");\n");
6135 try v.end(f, inst, writer);
6136
60656137 return local;
60666138}
60676139
......@@ -6073,45 +6145,56 @@ fn airCmpBuiltinCall(
60736145 operation: enum { cmp, operator },
60746146 info: BuiltinInfo,
60756147) !CValue {
6076 const inst_ty = f.air.typeOfIndex(inst);
6077 const operand_ty = f.air.typeOf(data.lhs);
6148 if (f.liveness.isUnused(inst)) {
6149 try reap(f, inst, &.{ data.lhs, data.rhs });
6150 return .none;
6151 }
60786152
60796153 const lhs = try f.resolveInst(data.lhs);
60806154 const rhs = try f.resolveInst(data.rhs);
60816155 try reap(f, inst, &.{ data.lhs, data.rhs });
60826156
6083 const inst_cty = try f.typeToCType(inst_ty, .complete);
6084 const ref_ret = switch (inst_cty.tag()) {
6085 else => false,
6086 .array, .vector => true,
6087 };
6157 const inst_ty = f.air.typeOfIndex(inst);
6158 const inst_scalar_ty = inst_ty.scalarType();
6159 const operand_ty = f.air.typeOf(data.lhs);
6160 const scalar_ty = operand_ty.scalarType();
6161
6162 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
6163 const ref_ret = inst_scalar_cty.tag() == .array;
60886164
60896165 const writer = f.object.writer();
60906166 const local = try f.allocLocal(inst, inst_ty);
6167 const v = try Vectorizer.start(f, inst, writer, operand_ty);
60916168 if (!ref_ret) {
60926169 try f.writeCValue(writer, local, .Other);
6170 try v.elem(f, writer);
60936171 try writer.writeAll(" = ");
60946172 }
60956173 try writer.print("zig_{s}_", .{switch (operation) {
60966174 else => @tagName(operation),
60976175 .operator => compareOperatorAbbrev(operator),
60986176 }});
6099 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
6177 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
61006178 try writer.writeByte('(');
61016179 if (ref_ret) {
61026180 try f.writeCValue(writer, local, .FunctionArgument);
6181 try v.elem(f, writer);
61036182 try writer.writeAll(", ");
61046183 }
61056184 try f.writeCValue(writer, lhs, .FunctionArgument);
6185 try v.elem(f, writer);
61066186 try writer.writeAll(", ");
61076187 try f.writeCValue(writer, rhs, .FunctionArgument);
6108 try f.object.dg.renderBuiltinInfo(writer, operand_ty, info);
6188 try v.elem(f, writer);
6189 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);
61096190 try writer.writeByte(')');
61106191 if (!ref_ret) try writer.print(" {s} {}", .{
61116192 compareOperatorC(operator),
61126193 try f.fmtIntLiteral(Type.initTag(.i32), Value.zero),
61136194 });
61146195 try writer.writeAll(";\n");
6196 try v.end(f, inst, writer);
6197
61156198 return local;
61166199}
61176200
......@@ -6498,65 +6581,35 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
64986581 const operand = try f.resolveInst(reduce.operand);
64996582 try reap(f, inst, &.{reduce.operand});
65006583 const operand_ty = f.air.typeOf(reduce.operand);
6501 const vector_len = operand_ty.vectorLen();
65026584 const writer = f.object.writer();
65036585
6504 const Op = union(enum) {
6505 call_fn: []const u8,
6586 const op: union(enum) {
6587 float_op: []const u8,
6588 builtin: []const u8,
65066589 infix: []const u8,
65076590 ternary: []const u8,
6508 };
6509 var fn_name_buf: [64]u8 = undefined;
6510 const op: Op = switch (reduce.operation) {
6591 } = switch (reduce.operation) {
65116592 .And => .{ .infix = " &= " },
65126593 .Or => .{ .infix = " |= " },
65136594 .Xor => .{ .infix = " ^= " },
65146595 .Min => switch (scalar_ty.zigTypeTag()) {
6515 .Int => Op{ .ternary = " < " },
6516 .Float => op: {
6517 const float_bits = scalar_ty.floatBits(target);
6518 break :op Op{
6519 .call_fn = std.fmt.bufPrintZ(&fn_name_buf, "{s}fmin{s}", .{
6520 libcFloatPrefix(float_bits), libcFloatSuffix(float_bits),
6521 }) catch unreachable,
6522 };
6523 },
6596 .Int => .{ .ternary = " < " },
6597 .Float => .{ .float_op = "fmin" },
65246598 else => unreachable,
65256599 },
65266600 .Max => switch (scalar_ty.zigTypeTag()) {
6527 .Int => Op{ .ternary = " > " },
6528 .Float => op: {
6529 const float_bits = scalar_ty.floatBits(target);
6530 break :op Op{
6531 .call_fn = std.fmt.bufPrintZ(&fn_name_buf, "{s}fmax{s}", .{
6532 libcFloatPrefix(float_bits), libcFloatSuffix(float_bits),
6533 }) catch unreachable,
6534 };
6535 },
6601 .Int => .{ .ternary = " > " },
6602 .Float => .{ .float_op = "fmax" },
65366603 else => unreachable,
65376604 },
65386605 .Add => switch (scalar_ty.zigTypeTag()) {
6539 .Int => Op{ .infix = " += " },
6540 .Float => op: {
6541 const float_bits = scalar_ty.floatBits(target);
6542 break :op Op{
6543 .call_fn = std.fmt.bufPrintZ(&fn_name_buf, "__add{s}f3", .{
6544 compilerRtFloatAbbrev(float_bits),
6545 }) catch unreachable,
6546 };
6547 },
6606 .Int => .{ .infix = " += " },
6607 .Float => .{ .builtin = "add" },
65486608 else => unreachable,
65496609 },
65506610 .Mul => switch (scalar_ty.zigTypeTag()) {
6551 .Int => Op{ .infix = " *= " },
6552 .Float => op: {
6553 const float_bits = scalar_ty.floatBits(target);
6554 break :op Op{
6555 .call_fn = std.fmt.bufPrintZ(&fn_name_buf, "__mul{s}f3", .{
6556 compilerRtFloatAbbrev(float_bits),
6557 }) catch unreachable,
6558 };
6559 },
6611 .Int => .{ .infix = " *= " },
6612 .Float => .{ .builtin = "mul" },
65606613 else => unreachable,
65616614 },
65626615 };
......@@ -6572,75 +6625,94 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
65726625 // }
65736626 // break :reduce accum;
65746627 // }
6575 const it = try f.allocLocal(inst, Type.usize);
6576 try f.writeCValue(writer, it, .Other);
6577 try writer.writeAll(" = 0;\n");
65786628
65796629 const accum = try f.allocLocal(inst, scalar_ty);
65806630 try f.writeCValue(writer, accum, .Other);
65816631 try writer.writeAll(" = ");
65826632
6583 const init_val = switch (reduce.operation) {
6584 .And, .Or, .Xor, .Add => "0",
6633 var arena = std.heap.ArenaAllocator.init(f.object.dg.gpa);
6634 defer arena.deinit();
6635
6636 const ExpectedContents = union {
6637 u: Value.Payload.U64,
6638 i: Value.Payload.I64,
6639 f16: Value.Payload.Float_16,
6640 f32: Value.Payload.Float_32,
6641 f64: Value.Payload.Float_64,
6642 f80: Value.Payload.Float_80,
6643 f128: Value.Payload.Float_128,
6644 };
6645 var stack align(@alignOf(ExpectedContents)) =
6646 std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator());
6647
6648 try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) {
6649 .Or, .Xor, .Add => Value.zero,
6650 .And => switch (scalar_ty.zigTypeTag()) {
6651 .Bool => Value.one,
6652 else => switch (scalar_ty.intInfo(target).signedness) {
6653 .unsigned => try scalar_ty.maxInt(stack.get(), target),
6654 .signed => Value.negative_one,
6655 },
6656 },
65856657 .Min => switch (scalar_ty.zigTypeTag()) {
6586 .Int => "TODO_intmax",
6587 .Float => "TODO_nan",
6658 .Bool => Value.one,
6659 .Int => try scalar_ty.maxInt(stack.get(), target),
6660 .Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target),
65886661 else => unreachable,
65896662 },
65906663 .Max => switch (scalar_ty.zigTypeTag()) {
6591 .Int => "TODO_intmin",
6592 .Float => "TODO_nan",
6664 .Bool => Value.zero,
6665 .Int => try scalar_ty.minInt(stack.get(), target),
6666 .Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target),
65936667 else => unreachable,
65946668 },
6595 .Mul => "1",
6596 };
6597 try writer.writeAll(init_val);
6598 try writer.writeAll(";");
6599 try f.object.indent_writer.insertNewline();
6600 try writer.writeAll("for (;");
6601 try f.writeCValue(writer, it, .Other);
6602 try writer.print("<{d};++", .{vector_len});
6603 try f.writeCValue(writer, it, .Other);
6604 try writer.writeAll(") ");
6605 try f.writeCValue(writer, accum, .Other);
6669 .Mul => Value.one,
6670 }, .Initializer);
6671 try writer.writeAll(";\n");
66066672
6673 const v = try Vectorizer.start(f, inst, writer, operand_ty);
6674 try f.writeCValue(writer, accum, .Other);
66076675 switch (op) {
6608 .call_fn => |fn_name| {
6609 try writer.print(" = {s}(", .{fn_name});
6676 .float_op => |operation| {
6677 try writer.writeAll(" = zig_libc_name_");
6678 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
6679 try writer.print("({s})(", .{operation});
6680 try f.writeCValue(writer, accum, .FunctionArgument);
6681 try writer.writeAll(", ");
6682 try f.writeCValue(writer, operand, .Other);
6683 try v.elem(f, writer);
6684 try writer.writeByte(')');
6685 },
6686 .builtin => |operation| {
6687 try writer.print(" = zig_{s}_", .{operation});
6688 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
6689 try writer.writeByte('(');
66106690 try f.writeCValue(writer, accum, .FunctionArgument);
66116691 try writer.writeAll(", ");
66126692 try f.writeCValue(writer, operand, .Other);
6613 try writer.writeAll("[");
6614 try f.writeCValue(writer, it, .Other);
6615 try writer.writeAll("])");
6693 try v.elem(f, writer);
6694 try writer.writeByte(')');
66166695 },
66176696 .infix => |ass| {
66186697 try writer.writeAll(ass);
66196698 try f.writeCValue(writer, operand, .Other);
6620 try writer.writeAll("[");
6621 try f.writeCValue(writer, it, .Other);
6622 try writer.writeAll("]");
6699 try v.elem(f, writer);
66236700 },
66246701 .ternary => |cmp| {
66256702 try writer.writeAll(" = ");
66266703 try f.writeCValue(writer, accum, .Other);
66276704 try writer.writeAll(cmp);
66286705 try f.writeCValue(writer, operand, .Other);
6629 try writer.writeAll("[");
6630 try f.writeCValue(writer, it, .Other);
6631 try writer.writeAll("] ? ");
6706 try v.elem(f, writer);
6707 try writer.writeAll(" ? ");
66326708 try f.writeCValue(writer, accum, .Other);
66336709 try writer.writeAll(" : ");
66346710 try f.writeCValue(writer, operand, .Other);
6635 try writer.writeAll("[");
6636 try f.writeCValue(writer, it, .Other);
6637 try writer.writeAll("]");
6711 try v.elem(f, writer);
66386712 },
66396713 }
6640
66416714 try writer.writeAll(";\n");
6642
6643 try freeLocal(f, inst, it.new_local, 0);
6715 try v.end(f, inst, writer);
66446716
66456717 return accum;
66466718}
......@@ -6774,7 +6846,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
67746846 try writer.writeByte('(');
67756847
67766848 if (inst_ty.isAbiInt() and (field_ty.isAbiInt() or field_ty.isPtrAtRuntime())) {
6777 try f.renderIntCast(writer, inst_ty, element, field_ty, .FunctionArgument);
6849 try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument);
67786850 } else {
67796851 try writer.writeByte('(');
67806852 try f.renderType(writer, inst_ty);
......@@ -6916,7 +6988,6 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
69166988}
69176989
69186990fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
6919 const inst_ty = f.air.typeOfIndex(inst);
69206991 const un_op = f.air.instructions.items(.data)[inst].un_op;
69216992 if (f.liveness.isUnused(inst)) {
69226993 try reap(f, inst, &.{un_op});
......@@ -6925,16 +6996,23 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
69256996
69266997 const operand = try f.resolveInst(un_op);
69276998 try reap(f, inst, &.{un_op});
6999
69287000 const operand_ty = f.air.typeOf(un_op);
7001 const scalar_ty = operand_ty.scalarType();
69297002
69307003 const writer = f.object.writer();
6931 const local = try f.allocLocal(inst, inst_ty);
7004 const local = try f.allocLocal(inst, operand_ty);
7005 const v = try Vectorizer.start(f, inst, writer, operand_ty);
69327006 try f.writeCValue(writer, local, .Other);
7007 try v.elem(f, writer);
69337008 try writer.writeAll(" = zig_neg_");
6934 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
7009 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
69357010 try writer.writeByte('(');
69367011 try f.writeCValue(writer, operand, .FunctionArgument);
7012 try v.elem(f, writer);
69377013 try writer.writeAll(");\n");
7014 try v.end(f, inst, writer);
7015
69387016 return local;
69397017}
69407018
......@@ -6944,19 +7022,28 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal
69447022 try reap(f, inst, &.{un_op});
69457023 return .none;
69467024 }
7025
69477026 const operand = try f.resolveInst(un_op);
69487027 try reap(f, inst, &.{un_op});
6949 const writer = f.object.writer();
7028
69507029 const inst_ty = f.air.typeOfIndex(inst);
7030 const inst_scalar_ty = inst_ty.scalarType();
7031
7032 const writer = f.object.writer();
69517033 const local = try f.allocLocal(inst, inst_ty);
7034 const v = try Vectorizer.start(f, inst, writer, inst_ty);
69527035 try f.writeCValue(writer, local, .Other);
7036 try v.elem(f, writer);
69537037 try writer.writeAll(" = zig_libc_name_");
6954 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
7038 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);
69557039 try writer.writeByte('(');
69567040 try writer.writeAll(operation);
69577041 try writer.writeAll(")(");
69587042 try f.writeCValue(writer, operand, .FunctionArgument);
7043 try v.elem(f, writer);
69597044 try writer.writeAll(");\n");
7045 try v.end(f, inst, writer);
7046
69607047 return local;
69617048}
69627049
......@@ -6966,23 +7053,32 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa
69667053 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
69677054 return .none;
69687055 }
7056
69697057 const lhs = try f.resolveInst(bin_op.lhs);
69707058 const rhs = try f.resolveInst(bin_op.rhs);
69717059 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
69727060
6973 const writer = f.object.writer();
69747061 const inst_ty = f.air.typeOfIndex(inst);
7062 const inst_scalar_ty = inst_ty.scalarType();
7063
7064 const writer = f.object.writer();
69757065 const local = try f.allocLocal(inst, inst_ty);
7066 const v = try Vectorizer.start(f, inst, writer, inst_ty);
69767067 try f.writeCValue(writer, local, .Other);
7068 try v.elem(f, writer);
69777069 try writer.writeAll(" = zig_libc_name_");
6978 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
7070 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);
69797071 try writer.writeByte('(');
69807072 try writer.writeAll(operation);
69817073 try writer.writeAll(")(");
69827074 try f.writeCValue(writer, lhs, .FunctionArgument);
7075 try v.elem(f, writer);
69837076 try writer.writeAll(", ");
69847077 try f.writeCValue(writer, rhs, .FunctionArgument);
7078 try v.elem(f, writer);
69857079 try writer.writeAll(");\n");
7080 try v.end(f, inst, writer);
7081
69867082 return local;
69877083}
69887084
......@@ -6993,23 +7089,34 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
69937089 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand });
69947090 return .none;
69957091 }
6996 const inst_ty = f.air.typeOfIndex(inst);
7092
69977093 const mulend1 = try f.resolveInst(bin_op.lhs);
69987094 const mulend2 = try f.resolveInst(bin_op.rhs);
69997095 const addend = try f.resolveInst(pl_op.operand);
70007096 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand });
7097
7098 const inst_ty = f.air.typeOfIndex(inst);
7099 const inst_scalar_ty = inst_ty.scalarType();
7100
70017101 const writer = f.object.writer();
70027102 const local = try f.allocLocal(inst, inst_ty);
7103 const v = try Vectorizer.start(f, inst, writer, inst_ty);
70037104 try f.writeCValue(writer, local, .Other);
7105 try v.elem(f, writer);
70047106 try writer.writeAll(" = zig_libc_name_");
7005 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
7107 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);
70067108 try writer.writeAll("(fma)(");
70077109 try f.writeCValue(writer, mulend1, .FunctionArgument);
7110 try v.elem(f, writer);
70087111 try writer.writeAll(", ");
70097112 try f.writeCValue(writer, mulend2, .FunctionArgument);
7113 try v.elem(f, writer);
70107114 try writer.writeAll(", ");
70117115 try f.writeCValue(writer, addend, .FunctionArgument);
7116 try v.elem(f, writer);
70127117 try writer.writeAll(");\n");
7118 try v.end(f, inst, writer);
7119
70137120 return local;
70147121}
70157122
......@@ -7510,6 +7617,47 @@ fn formatIntLiteral(
75107617 try data.cty.renderLiteralSuffix(writer);
75117618}
75127619
7620const Vectorizer = struct {
7621 index: CValue = .none,
7622
7623 pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorizer {
7624 return if (ty.zigTypeTag() == .Vector) index: {
7625 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = ty.vectorLen() };
7626
7627 const local = try f.allocLocal(inst, Type.usize);
7628
7629 try writer.writeAll("for (");
7630 try f.writeCValue(writer, local, .Other);
7631 try writer.print(" = {d}; ", .{try f.fmtIntLiteral(Type.usize, Value.zero)});
7632 try f.writeCValue(writer, local, .Other);
7633 try writer.print(" < {d}; ", .{
7634 try f.fmtIntLiteral(Type.usize, Value.initPayload(&len_pl.base)),
7635 });
7636 try f.writeCValue(writer, local, .Other);
7637 try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(Type.usize, Value.one)});
7638 f.object.indent_writer.pushIndent();
7639
7640 break :index .{ .index = local };
7641 } else .{};
7642 }
7643
7644 pub fn elem(self: Vectorizer, f: *Function, writer: anytype) !void {
7645 if (self.index != .none) {
7646 try writer.writeByte('[');
7647 try f.writeCValue(writer, self.index, .Other);
7648 try writer.writeByte(']');
7649 }
7650 }
7651
7652 pub fn end(self: Vectorizer, f: *Function, inst: Air.Inst.Index, writer: anytype) !void {
7653 if (self.index != .none) {
7654 f.object.indent_writer.popIndent();
7655 try writer.writeAll("}\n");
7656 try freeLocal(f, inst, self.index.new_local, 0);
7657 }
7658 }
7659};
7660
75137661fn isByRef(ty: Type) bool {
75147662 _ = ty;
75157663 return false;
src/type.zig+1-1
......@@ -4213,7 +4213,7 @@ pub const Type = extern union {
42134213 };
42144214 }
42154215
4216 pub fn shallowElemType(child_ty: Type) Type {
4216 fn shallowElemType(child_ty: Type) Type {
42174217 return switch (child_ty.zigTypeTag()) {
42184218 .Array, .Vector => child_ty.childType(),
42194219 else => child_ty,
src/value.zig+1-1
......@@ -3319,7 +3319,7 @@ pub const Value = extern union {
33193319 }
33203320 }
33213321
3322 fn floatToValue(float: f128, arena: Allocator, dest_ty: Type, target: Target) !Value {
3322 pub fn floatToValue(float: f128, arena: Allocator, dest_ty: Type, target: Target) !Value {
33233323 switch (dest_ty.floatBits(target)) {
33243324 16 => return Value.Tag.float_16.create(arena, @floatCast(f16, float)),
33253325 32 => return Value.Tag.float_32.create(arena, @floatCast(f32, float)),
test/behavior/bitreverse.zig-3
......@@ -96,7 +96,6 @@ fn vector8() !void {
9696
9797test "bitReverse vectors u8" {
9898 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
99 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
10099 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
101100 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
102101 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -115,7 +114,6 @@ fn vector16() !void {
115114
116115test "bitReverse vectors u16" {
117116 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
118 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
119117 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
120118 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
121119 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -134,7 +132,6 @@ fn vector24() !void {
134132
135133test "bitReverse vectors u24" {
136134 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
137 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
138135 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
139136 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
140137 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
test/behavior/byteswap.zig-3
......@@ -62,7 +62,6 @@ fn vector8() !void {
6262
6363test "@byteSwap vectors u8" {
6464 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
65 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
6665 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
6766 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
6867 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -81,7 +80,6 @@ fn vector16() !void {
8180
8281test "@byteSwap vectors u16" {
8382 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
84 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
8583 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
8684 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
8785 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -100,7 +98,6 @@ fn vector24() !void {
10098
10199test "@byteSwap vectors u24" {
102100 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
103 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
104101 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
105102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
106103 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
test/behavior/cast.zig-1
......@@ -598,7 +598,6 @@ test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
598598
599599test "vector casts" {
600600 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
601 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
602601 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
603602 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
604603 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/floatop.zig-12
......@@ -141,7 +141,6 @@ fn testSqrt() !void {
141141
142142test "@sqrt with vectors" {
143143 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
144 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
145144 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
146145 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
147146 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -234,7 +233,6 @@ fn testSin() !void {
234233
235234test "@sin with vectors" {
236235 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
237 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
238236 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
239237 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
240238 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -275,7 +273,6 @@ fn testCos() !void {
275273
276274test "@cos with vectors" {
277275 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
278 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
279276 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
280277 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
281278 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -315,7 +312,6 @@ fn testExp() !void {
315312
316313test "@exp with vectors" {
317314 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
318 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
319315 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
320316 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
321317 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -355,7 +351,6 @@ fn testExp2() !void {
355351
356352test "@exp2" {
357353 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
358 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
359354 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
360355 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
361356 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -409,7 +404,6 @@ test "@log with @vectors" {
409404 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
410405 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
411406 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
412 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
413407 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
414408
415409 {
......@@ -447,7 +441,6 @@ test "@log2 with vectors" {
447441 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
448442 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
449443 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
450 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
451444 // https://github.com/ziglang/zig/issues/13681
452445 if (builtin.zig_backend == .stage2_llvm and
453446 builtin.cpu.arch == .aarch64 and
......@@ -491,7 +484,6 @@ test "@log10 with vectors" {
491484 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
492485 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
493486 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
494 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
495487
496488 comptime try testLog10WithVectors();
497489 try testLog10WithVectors();
......@@ -537,7 +529,6 @@ fn testFabs() !void {
537529
538530test "@fabs with vectors" {
539531 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
540 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
541532 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
542533 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
543534 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -660,7 +651,6 @@ fn testFloor() !void {
660651
661652test "@floor with vectors" {
662653 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
663 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
664654 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
665655 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
666656 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -754,7 +744,6 @@ fn testCeil() !void {
754744
755745test "@ceil with vectors" {
756746 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
757 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
758747 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
759748 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
760749 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -848,7 +837,6 @@ fn testTrunc() !void {
848837
849838test "@trunc with vectors" {
850839 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
851 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
852840 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
853841 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
854842 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/maximum_minimum.zig-2
......@@ -25,7 +25,6 @@ test "@max" {
2525test "@max on vectors" {
2626 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2727 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
28 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2928 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
3029 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
3130 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -75,7 +74,6 @@ test "@min for vectors" {
7574 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
7675 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7776 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
7977 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8078
8179 const S = struct {
test/behavior/muladd.zig-5
......@@ -100,7 +100,6 @@ fn vector16() !void {
100100}
101101
102102test "vector f16" {
103 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
104103 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
105104 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
106105 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -124,7 +123,6 @@ fn vector32() !void {
124123}
125124
126125test "vector f32" {
127 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
128126 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
129127 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
130128 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -148,7 +146,6 @@ fn vector64() !void {
148146}
149147
150148test "vector f64" {
151 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
152149 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
153150 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
154151 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -171,7 +168,6 @@ fn vector80() !void {
171168}
172169
173170test "vector f80" {
174 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
175171 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
176172 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
177173 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -195,7 +191,6 @@ fn vector128() !void {
195191}
196192
197193test "vector f128" {
198 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
199194 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
200195 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
201196 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/vector.zig+10-22
......@@ -25,7 +25,6 @@ test "implicit cast vector to array - bool" {
2525
2626test "vector wrap operators" {
2727 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
28 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2928 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
3029 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
3130 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -116,7 +115,6 @@ test "vector float operators" {
116115
117116test "vector bit operators" {
118117 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
119 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
120118 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
121119 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
122120 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -442,7 +440,6 @@ test "vector comparison operators" {
442440
443441test "vector division operators" {
444442 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
445 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
446443 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
447444 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
448445 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -525,7 +522,6 @@ test "vector division operators" {
525522
526523test "vector bitwise not operator" {
527524 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
528 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
529525 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
530526 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
531527 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -557,7 +553,6 @@ test "vector bitwise not operator" {
557553
558554test "vector shift operators" {
559555 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
560 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
561556 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
562557 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
563558 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -651,7 +646,6 @@ test "vector shift operators" {
651646
652647test "vector reduce operation" {
653648 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
654 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
655649 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
656650 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
657651 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -707,7 +701,7 @@ test "vector reduce operation" {
707701
708702 // LLVM 11 ERROR: Cannot select type
709703 // https://github.com/ziglang/zig/issues/7138
710 if (builtin.target.cpu.arch != .aarch64) {
704 if (builtin.zig_backend != .stage2_llvm or builtin.target.cpu.arch != .aarch64) {
711705 try testReduce(.Min, [4]i64{ 1234567, -386, 0, 3 }, @as(i64, -386));
712706 try testReduce(.Min, [4]u64{ 99, 9999, 9, 99999 }, @as(u64, 9));
713707 }
......@@ -725,7 +719,7 @@ test "vector reduce operation" {
725719
726720 // LLVM 11 ERROR: Cannot select type
727721 // https://github.com/ziglang/zig/issues/7138
728 if (builtin.target.cpu.arch != .aarch64) {
722 if (builtin.zig_backend != .stage2_llvm or builtin.target.cpu.arch != .aarch64) {
729723 try testReduce(.Max, [4]i64{ 1234567, -386, 0, 3 }, @as(i64, 1234567));
730724 try testReduce(.Max, [4]u64{ 99, 9999, 9, 99999 }, @as(u64, 99999));
731725 }
......@@ -773,14 +767,14 @@ test "vector reduce operation" {
773767
774768 // LLVM 11 ERROR: Cannot select type
775769 // https://github.com/ziglang/zig/issues/7138
776 if (false) {
777 try testReduce(.Min, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
778 try testReduce(.Min, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
779 try testReduce(.Min, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
780
781 try testReduce(.Max, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
782 try testReduce(.Max, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
783 try testReduce(.Max, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
770 if (builtin.zig_backend != .stage2_llvm) {
771 try testReduce(.Min, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, -1.9));
772 try testReduce(.Min, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, -1.9));
773 try testReduce(.Min, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, -1.9));
774
775 try testReduce(.Max, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, 100.0));
776 try testReduce(.Max, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, 100.0));
777 try testReduce(.Max, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, 100.0));
784778 }
785779
786780 try testReduce(.Mul, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
......@@ -831,7 +825,6 @@ test "mask parameter of @shuffle is comptime scope" {
831825
832826test "saturating add" {
833827 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
834 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
835828 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
836829 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
837830 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -863,7 +856,6 @@ test "saturating add" {
863856
864857test "saturating subtraction" {
865858 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
866 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
867859 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
868860 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
869861 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -886,7 +878,6 @@ test "saturating subtraction" {
886878
887879test "saturating multiplication" {
888880 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
889 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
890881 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
891882 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
892883 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -913,7 +904,6 @@ test "saturating multiplication" {
913904
914905test "saturating shift-left" {
915906 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
916 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
917907 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
918908 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
919909 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1047,7 +1037,6 @@ test "@mulWithOverflow" {
10471037}
10481038
10491039test "@shlWithOverflow" {
1050 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10511040 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
10521041 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10531042 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -1202,7 +1191,6 @@ test "zero multiplicand" {
12021191
12031192test "@intCast to u0" {
12041193 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1205 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12061194 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12071195 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12081196 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO