Mercurial > vec
comparison utils/gengcc.c @ 41:c6e0df09b86f
*: performance improvements with old GCC, reimplement altivec
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 28 Apr 2025 16:31:59 -0400 |
| parents | 55cadb1fac4b |
| children |
comparison
equal
deleted
inserted
replaced
| 40:55cadb1fac4b | 41:c6e0df09b86f |
|---|---|
| 117 #define LOSIGN(x) ((x) ? "" : "u") | 117 #define LOSIGN(x) ((x) ? "" : "u") |
| 118 | 118 |
| 119 static void print_gcc_op(enum op op, int is_signed, int bits, int size) | 119 static void print_gcc_op(enum op op, int is_signed, int bits, int size) |
| 120 { | 120 { |
| 121 int i; | 121 int i; |
| 122 | 122 int gccprereq = 0; |
| 123 | |
| 124 switch (op) { | |
| 125 case OP_CMPEQ: | |
| 126 case OP_CMPLE: | |
| 127 case OP_CMPLT: | |
| 128 case OP_CMPGT: | |
| 129 case OP_CMPGE: | |
| 130 case OP_MIN: | |
| 131 case OP_MAX: | |
| 132 case OP_LSHIFT: | |
| 133 case OP_RSHIFT: | |
| 134 case OP_LRSHIFT: | |
| 135 case OP_AVG: | |
| 136 puts("#if VEC_GNUC_ATLEAST(4, 3, 0)"); | |
| 137 gccprereq = 1; | |
| 138 break; | |
| 139 default: | |
| 140 break; | |
| 141 } | |
| 142 | |
| 123 printf("#ifndef V%sINT%dx%d_%s_DEFINED\n", UPSIGN(is_signed), bits, size, op_names[op].u); | 143 printf("#ifndef V%sINT%dx%d_%s_DEFINED\n", UPSIGN(is_signed), bits, size, op_names[op].u); |
| 124 | 144 |
| 125 printf("VEC_FUNC_IMPL "); | 145 printf("VEC_FUNC_IMPL "); |
| 126 | 146 |
| 127 /* first; the return value */ | 147 /* first; the return value */ |
| 269 printf("\tvec1.gcc = (vec1.gcc & mask.gcc) | (vec2.gcc & ~mask.gcc);\n"); | 289 printf("\tvec1.gcc = (vec1.gcc & mask.gcc) | (vec2.gcc & ~mask.gcc);\n"); |
| 270 printf("\treturn vec1;\n"); | 290 printf("\treturn vec1;\n"); |
| 271 break; | 291 break; |
| 272 } | 292 } |
| 273 case OP_AVG: | 293 case OP_AVG: |
| 294 printf("\tvint%dx%d ones = vint%dx%d_splat(1);\n", bits, size, bits, size); | |
| 295 | |
| 274 if (is_signed) { | 296 if (is_signed) { |
| 275 printf("\tvint%dx%d ones = vint%dx%d_splat(1);\n", bits, size, bits, size); | 297 puts("\t__typeof__(vec1.gcc) x_d_rem = (vec1.gcc % 2);"); |
| 276 printf("\t__typeof__(vec1.gcc) x_d_rem = (vec1.gcc % 2);\n"); | 298 puts("\t__typeof__(vec1.gcc) y_d_rem = (vec2.gcc % 2);"); |
| 277 printf("\t__typeof__(vec1.gcc) y_d_rem = (vec2.gcc % 2);\n"); | 299 puts("\t__typeof__(vec1.gcc) rem_d_quot = ((x_d_rem + y_d_rem) / 2);"); |
| 278 printf("\t__typeof__(vec1.gcc) rem_d_quot = ((x_d_rem + y_d_rem) / 2);\n"); | 300 puts("\t__typeof__(vec1.gcc) rem_d_rem = ((x_d_rem + y_d_rem) % 2);"); |
| 279 printf("\t__typeof__(vec1.gcc) rem_d_rem = ((x_d_rem + y_d_rem) % 2);\n"); | |
| 280 puts(""); | 301 puts(""); |
| 281 printf("\tvec1.gcc = ((vec1.gcc / 2) + (vec2.gcc / 2)) + (rem_d_quot) + ((rem_d_rem == 1) & ones.gcc);\n"); | 302 printf("\tvec1.gcc = ((vec1.gcc / 2) + (vec2.gcc / 2)) + (rem_d_quot) + ((rem_d_rem == 1) & ones.gcc);\n"); |
| 282 } else { | 303 } else { |
| 283 printf("\tvec1.gcc = (vec1.gcc >> 1) + (vec2.gcc >> 1) + ((vec1.gcc | vec2.gcc) & 1);\n"); | 304 printf("\tvec1.gcc = (vec1.gcc >> 1) + (vec2.gcc >> 1) + ((vec1.gcc | vec2.gcc) & ones.gcc);\n"); |
| 284 } | 305 } |
| 285 | 306 |
| 286 printf("\treturn vec1;\n"); | 307 printf("\treturn vec1;\n"); |
| 287 break; | 308 break; |
| 288 case OP_NOT: | 309 case OP_NOT: |
| 297 /* end function definition */ | 318 /* end function definition */ |
| 298 puts("}"); | 319 puts("}"); |
| 299 | 320 |
| 300 printf("# define V%sINT%dx%d_%s_DEFINED\n", UPSIGN(is_signed), bits, size, op_names[op].u); | 321 printf("# define V%sINT%dx%d_%s_DEFINED\n", UPSIGN(is_signed), bits, size, op_names[op].u); |
| 301 puts("#endif"); | 322 puts("#endif"); |
| 323 | |
| 324 if (gccprereq) | |
| 325 puts("#endif"); | |
| 302 } | 326 } |
| 303 | 327 |
| 304 static inline void print_ops(int is_signed, int bits, int size) | 328 static inline void print_ops(int is_signed, int bits, int size) |
| 305 { | 329 { |
| 306 int i; | 330 int i; |
