1/* 2 * Copyright © 2016 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include <gtest/gtest.h> 25#include "brw_eu.h" 26#include "brw_eu_defines.h" 27#include "util/bitset.h" 28#include "util/ralloc.h" 29 30static const struct intel_gfx_info { 31 const char *name; 32} gfx_names[] = { 33 { "brw", }, 34 { "g4x", }, 35 { "ilk", }, 36 { "snb", }, 37 { "ivb", }, 38 { "byt", }, 39 { "hsw", }, 40 { "bdw", }, 41 { "chv", }, 42 { "skl", }, 43 { "bxt", }, 44 { "kbl", }, 45 { "aml", }, 46 { "glk", }, 47 { "cfl", }, 48 { "whl", }, 49 { "icl", }, 50 { "tgl", }, 51}; 52 53class validation_test: public ::testing::TestWithParam<struct intel_gfx_info> { 54 virtual void SetUp(); 55 56public: 57 validation_test(); 58 virtual ~validation_test(); 59 60 struct brw_codegen *p; 61 struct intel_device_info devinfo; 62}; 63 64validation_test::validation_test() 65{ 66 p = rzalloc(NULL, struct brw_codegen); 67 memset(&devinfo, 0, sizeof(devinfo)); 68} 69 70validation_test::~validation_test() 71{ 72 ralloc_free(p); 73} 74 75void validation_test::SetUp() 76{ 77 struct intel_gfx_info info = GetParam(); 78 int devid = intel_device_name_to_pci_device_id(info.name); 79 80 intel_get_device_info_from_pci_id(devid, &devinfo); 81 82 brw_init_codegen(&devinfo, p, p); 83} 84 85struct gfx_name { 86 template <class ParamType> 87 std::string 88 operator()(const ::testing::TestParamInfo<ParamType>& info) const { 89 return info.param.name; 90 } 91}; 92 93INSTANTIATE_TEST_CASE_P(eu_assembly, validation_test, 94 ::testing::ValuesIn(gfx_names), 95 gfx_name()); 96 97static bool 98validate(struct brw_codegen *p) 99{ 100 const bool print = getenv("TEST_DEBUG"); 101 struct disasm_info *disasm = disasm_initialize(p->devinfo, NULL); 102 103 if (print) { 104 disasm_new_inst_group(disasm, 0); 105 disasm_new_inst_group(disasm, p->next_insn_offset); 106 } 107 108 bool ret = brw_validate_instructions(p->devinfo, p->store, 0, 109 p->next_insn_offset, disasm); 110 111 if (print) { 112 dump_assembly(p->store, 0, p->next_insn_offset, disasm, NULL); 113 } 114 ralloc_free(disasm); 115 116 return ret; 117} 118 119#define last_inst (&p->store[p->nr_insn - 1]) 120#define g0 brw_vec8_grf(0, 0) 121#define acc0 brw_acc_reg(8) 122#define null brw_null_reg() 123#define zero brw_imm_f(0.0f) 124 125static void 126clear_instructions(struct brw_codegen *p) 127{ 128 p->next_insn_offset = 0; 129 p->nr_insn = 0; 130} 131 132TEST_P(validation_test, sanity) 133{ 134 brw_ADD(p, g0, g0, g0); 135 136 EXPECT_TRUE(validate(p)); 137} 138 139TEST_P(validation_test, src0_null_reg) 140{ 141 brw_MOV(p, g0, null); 142 143 EXPECT_FALSE(validate(p)); 144} 145 146TEST_P(validation_test, src1_null_reg) 147{ 148 brw_ADD(p, g0, g0, null); 149 150 EXPECT_FALSE(validate(p)); 151} 152 153TEST_P(validation_test, math_src0_null_reg) 154{ 155 if (devinfo.ver >= 6) { 156 gfx6_math(p, g0, BRW_MATH_FUNCTION_SIN, null, null); 157 } else { 158 gfx4_math(p, g0, BRW_MATH_FUNCTION_SIN, 0, null, BRW_MATH_PRECISION_FULL); 159 } 160 161 EXPECT_FALSE(validate(p)); 162} 163 164TEST_P(validation_test, math_src1_null_reg) 165{ 166 if (devinfo.ver >= 6) { 167 gfx6_math(p, g0, BRW_MATH_FUNCTION_POW, g0, null); 168 EXPECT_FALSE(validate(p)); 169 } else { 170 /* Math instructions on Gfx4/5 are actually SEND messages with payloads. 171 * src1 is an immediate message descriptor set by gfx4_math. 172 */ 173 } 174} 175 176TEST_P(validation_test, opcode46) 177{ 178 /* opcode 46 is "push" on Gen 4 and 5 179 * "fork" on Gen 6 180 * reserved on Gen 7 181 * "goto" on Gfx8+ 182 */ 183 brw_next_insn(p, brw_opcode_decode(&devinfo, 46)); 184 185 if (devinfo.ver == 7) { 186 EXPECT_FALSE(validate(p)); 187 } else { 188 EXPECT_TRUE(validate(p)); 189 } 190} 191 192TEST_P(validation_test, invalid_exec_size_encoding) 193{ 194 const struct { 195 enum brw_execution_size exec_size; 196 bool expected_result; 197 } test_case[] = { 198 { BRW_EXECUTE_1, true }, 199 { BRW_EXECUTE_2, true }, 200 { BRW_EXECUTE_4, true }, 201 { BRW_EXECUTE_8, true }, 202 { BRW_EXECUTE_16, true }, 203 { BRW_EXECUTE_32, true }, 204 205 { (enum brw_execution_size)((int)BRW_EXECUTE_32 + 1), false }, 206 { (enum brw_execution_size)((int)BRW_EXECUTE_32 + 2), false }, 207 }; 208 209 for (unsigned i = 0; i < ARRAY_SIZE(test_case); i++) { 210 brw_MOV(p, g0, g0); 211 212 brw_inst_set_exec_size(&devinfo, last_inst, test_case[i].exec_size); 213 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 214 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 215 216 if (test_case[i].exec_size == BRW_EXECUTE_1) { 217 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_0); 218 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_1); 219 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0); 220 } else { 221 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_2); 222 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_2); 223 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 224 } 225 226 EXPECT_EQ(test_case[i].expected_result, validate(p)); 227 228 clear_instructions(p); 229 } 230} 231 232TEST_P(validation_test, invalid_file_encoding) 233{ 234 /* Register file on Gfx12 is only one bit */ 235 if (devinfo.ver >= 12) 236 return; 237 238 brw_MOV(p, g0, g0); 239 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_MESSAGE_REGISTER_FILE, BRW_REGISTER_TYPE_F); 240 241 if (devinfo.ver > 6) { 242 EXPECT_FALSE(validate(p)); 243 } else { 244 EXPECT_TRUE(validate(p)); 245 } 246 247 clear_instructions(p); 248 249 if (devinfo.ver < 6) { 250 gfx4_math(p, g0, BRW_MATH_FUNCTION_SIN, 0, g0, BRW_MATH_PRECISION_FULL); 251 } else { 252 gfx6_math(p, g0, BRW_MATH_FUNCTION_SIN, g0, null); 253 } 254 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_MESSAGE_REGISTER_FILE, BRW_REGISTER_TYPE_F); 255 256 if (devinfo.ver > 6) { 257 EXPECT_FALSE(validate(p)); 258 } else { 259 EXPECT_TRUE(validate(p)); 260 } 261} 262 263TEST_P(validation_test, invalid_type_encoding) 264{ 265 enum brw_reg_file files[2] = { 266 BRW_GENERAL_REGISTER_FILE, 267 BRW_IMMEDIATE_VALUE, 268 }; 269 270 for (unsigned i = 0; i < ARRAY_SIZE(files); i++) { 271 const enum brw_reg_file file = files[i]; 272 const int num_bits = devinfo.ver >= 8 ? 4 : 3; 273 const int num_encodings = 1 << num_bits; 274 275 /* The data types are encoded into <num_bits> bits to be used in hardware 276 * instructions, so keep a record in a bitset the invalid patterns so 277 * they can be verified to be invalid when used. 278 */ 279 BITSET_DECLARE(invalid_encodings, num_encodings); 280 281 const struct { 282 enum brw_reg_type type; 283 bool expected_result; 284 } test_case[] = { 285 { BRW_REGISTER_TYPE_NF, devinfo.ver == 11 && file != IMM }, 286 { BRW_REGISTER_TYPE_DF, devinfo.has_64bit_float && (devinfo.ver >= 8 || file != IMM) }, 287 { BRW_REGISTER_TYPE_F, true }, 288 { BRW_REGISTER_TYPE_HF, devinfo.ver >= 8 }, 289 { BRW_REGISTER_TYPE_VF, file == IMM }, 290 { BRW_REGISTER_TYPE_Q, devinfo.has_64bit_int }, 291 { BRW_REGISTER_TYPE_UQ, devinfo.has_64bit_int }, 292 { BRW_REGISTER_TYPE_D, true }, 293 { BRW_REGISTER_TYPE_UD, true }, 294 { BRW_REGISTER_TYPE_W, true }, 295 { BRW_REGISTER_TYPE_UW, true }, 296 { BRW_REGISTER_TYPE_B, file == FIXED_GRF }, 297 { BRW_REGISTER_TYPE_UB, file == FIXED_GRF }, 298 { BRW_REGISTER_TYPE_V, file == IMM }, 299 { BRW_REGISTER_TYPE_UV, devinfo.ver >= 6 && file == IMM }, 300 }; 301 302 /* Initially assume all hardware encodings are invalid */ 303 BITSET_ONES(invalid_encodings); 304 305 brw_set_default_exec_size(p, BRW_EXECUTE_4); 306 307 for (unsigned i = 0; i < ARRAY_SIZE(test_case); i++) { 308 if (test_case[i].expected_result) { 309 unsigned hw_type = brw_reg_type_to_hw_type(&devinfo, file, test_case[i].type); 310 if (hw_type != INVALID_REG_TYPE) { 311 /* ... and remove valid encodings from the set */ 312 assert(BITSET_TEST(invalid_encodings, hw_type)); 313 BITSET_CLEAR(invalid_encodings, hw_type); 314 } 315 316 if (file == FIXED_GRF) { 317 struct brw_reg g = retype(g0, test_case[i].type); 318 brw_MOV(p, g, g); 319 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 320 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4); 321 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 322 } else { 323 enum brw_reg_type t; 324 325 switch (test_case[i].type) { 326 case BRW_REGISTER_TYPE_V: 327 t = BRW_REGISTER_TYPE_W; 328 break; 329 case BRW_REGISTER_TYPE_UV: 330 t = BRW_REGISTER_TYPE_UW; 331 break; 332 case BRW_REGISTER_TYPE_VF: 333 t = BRW_REGISTER_TYPE_F; 334 break; 335 default: 336 t = test_case[i].type; 337 break; 338 } 339 340 struct brw_reg g = retype(g0, t); 341 brw_MOV(p, g, retype(brw_imm_w(0), test_case[i].type)); 342 } 343 344 EXPECT_TRUE(validate(p)); 345 346 clear_instructions(p); 347 } 348 } 349 350 /* The remaining encodings in invalid_encodings do not have a mapping 351 * from BRW_REGISTER_TYPE_* and must be invalid. Verify that invalid 352 * encodings are rejected by the validator. 353 */ 354 int e; 355 BITSET_FOREACH_SET(e, invalid_encodings, num_encodings) { 356 if (file == FIXED_GRF) { 357 brw_MOV(p, g0, g0); 358 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 359 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4); 360 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 361 } else { 362 brw_MOV(p, g0, brw_imm_w(0)); 363 } 364 brw_inst_set_dst_reg_hw_type(&devinfo, last_inst, e); 365 brw_inst_set_src0_reg_hw_type(&devinfo, last_inst, e); 366 367 EXPECT_FALSE(validate(p)); 368 369 clear_instructions(p); 370 } 371 } 372} 373 374TEST_P(validation_test, invalid_type_encoding_3src_a16) 375{ 376 /* 3-src instructions in align16 mode only supported on Gfx6-10 */ 377 if (devinfo.ver < 6 || devinfo.ver > 10) 378 return; 379 380 const int num_bits = devinfo.ver >= 8 ? 3 : 2; 381 const int num_encodings = 1 << num_bits; 382 383 /* The data types are encoded into <num_bits> bits to be used in hardware 384 * instructions, so keep a record in a bitset the invalid patterns so 385 * they can be verified to be invalid when used. 386 */ 387 BITSET_DECLARE(invalid_encodings, num_encodings); 388 389 const struct { 390 enum brw_reg_type type; 391 bool expected_result; 392 } test_case[] = { 393 { BRW_REGISTER_TYPE_DF, devinfo.ver >= 7 }, 394 { BRW_REGISTER_TYPE_F, true }, 395 { BRW_REGISTER_TYPE_HF, devinfo.ver >= 8 }, 396 { BRW_REGISTER_TYPE_D, devinfo.ver >= 7 }, 397 { BRW_REGISTER_TYPE_UD, devinfo.ver >= 7 }, 398 }; 399 400 /* Initially assume all hardware encodings are invalid */ 401 BITSET_ONES(invalid_encodings); 402 403 brw_set_default_access_mode(p, BRW_ALIGN_16); 404 brw_set_default_exec_size(p, BRW_EXECUTE_4); 405 406 for (unsigned i = 0; i < ARRAY_SIZE(test_case); i++) { 407 if (test_case[i].expected_result) { 408 unsigned hw_type = brw_reg_type_to_a16_hw_3src_type(&devinfo, test_case[i].type); 409 if (hw_type != INVALID_HW_REG_TYPE) { 410 /* ... and remove valid encodings from the set */ 411 assert(BITSET_TEST(invalid_encodings, hw_type)); 412 BITSET_CLEAR(invalid_encodings, hw_type); 413 } 414 415 struct brw_reg g = retype(g0, test_case[i].type); 416 if (!brw_reg_type_is_integer(test_case[i].type)) { 417 brw_MAD(p, g, g, g, g); 418 } else { 419 brw_BFE(p, g, g, g, g); 420 } 421 422 EXPECT_TRUE(validate(p)); 423 424 clear_instructions(p); 425 } 426 } 427 428 /* The remaining encodings in invalid_encodings do not have a mapping 429 * from BRW_REGISTER_TYPE_* and must be invalid. Verify that invalid 430 * encodings are rejected by the validator. 431 */ 432 int e; 433 BITSET_FOREACH_SET(e, invalid_encodings, num_encodings) { 434 for (unsigned i = 0; i < 2; i++) { 435 if (i == 0) { 436 brw_MAD(p, g0, g0, g0, g0); 437 } else { 438 brw_BFE(p, g0, g0, g0, g0); 439 } 440 441 brw_inst_set_3src_a16_dst_hw_type(&devinfo, last_inst, e); 442 brw_inst_set_3src_a16_src_hw_type(&devinfo, last_inst, e); 443 444 EXPECT_FALSE(validate(p)); 445 446 clear_instructions(p); 447 448 if (devinfo.ver == 6) 449 break; 450 } 451 } 452} 453 454TEST_P(validation_test, invalid_type_encoding_3src_a1) 455{ 456 /* 3-src instructions in align1 mode only supported on Gfx10+ */ 457 if (devinfo.ver < 10) 458 return; 459 460 const int num_bits = 3 + 1 /* for exec_type */; 461 const int num_encodings = 1 << num_bits; 462 463 /* The data types are encoded into <num_bits> bits to be used in hardware 464 * instructions, so keep a record in a bitset the invalid patterns so 465 * they can be verified to be invalid when used. 466 */ 467 BITSET_DECLARE(invalid_encodings, num_encodings); 468 469 const struct { 470 enum brw_reg_type type; 471 unsigned exec_type; 472 bool expected_result; 473 } test_case[] = { 474#define E(x) ((unsigned)BRW_ALIGN1_3SRC_EXEC_TYPE_##x) 475 { BRW_REGISTER_TYPE_NF, E(FLOAT), devinfo.ver == 11 }, 476 { BRW_REGISTER_TYPE_DF, E(FLOAT), devinfo.has_64bit_float }, 477 { BRW_REGISTER_TYPE_F, E(FLOAT), true }, 478 { BRW_REGISTER_TYPE_HF, E(FLOAT), true }, 479 { BRW_REGISTER_TYPE_D, E(INT), true }, 480 { BRW_REGISTER_TYPE_UD, E(INT), true }, 481 { BRW_REGISTER_TYPE_W, E(INT), true }, 482 { BRW_REGISTER_TYPE_UW, E(INT), true }, 483 484 /* There are no ternary instructions that can operate on B-type sources 485 * on Gfx11-12. Src1/Src2 cannot be B-typed either. 486 */ 487 { BRW_REGISTER_TYPE_B, E(INT), false }, 488 { BRW_REGISTER_TYPE_UB, E(INT), false }, 489 }; 490 491 /* Initially assume all hardware encodings are invalid */ 492 BITSET_ONES(invalid_encodings); 493 494 brw_set_default_access_mode(p, BRW_ALIGN_1); 495 brw_set_default_exec_size(p, BRW_EXECUTE_4); 496 497 for (unsigned i = 0; i < ARRAY_SIZE(test_case); i++) { 498 if (test_case[i].expected_result) { 499 unsigned hw_type = brw_reg_type_to_a1_hw_3src_type(&devinfo, test_case[i].type); 500 unsigned hw_exec_type = hw_type | (test_case[i].exec_type << 3); 501 if (hw_type != INVALID_HW_REG_TYPE) { 502 /* ... and remove valid encodings from the set */ 503 assert(BITSET_TEST(invalid_encodings, hw_exec_type)); 504 BITSET_CLEAR(invalid_encodings, hw_exec_type); 505 } 506 507 struct brw_reg g = retype(g0, test_case[i].type); 508 if (!brw_reg_type_is_integer(test_case[i].type)) { 509 brw_MAD(p, g, g, g, g); 510 } else { 511 brw_BFE(p, g, g, g, g); 512 } 513 514 EXPECT_TRUE(validate(p)); 515 516 clear_instructions(p); 517 } 518 } 519 520 /* The remaining encodings in invalid_encodings do not have a mapping 521 * from BRW_REGISTER_TYPE_* and must be invalid. Verify that invalid 522 * encodings are rejected by the validator. 523 */ 524 int e; 525 BITSET_FOREACH_SET(e, invalid_encodings, num_encodings) { 526 const unsigned hw_type = e & 0x7; 527 const unsigned exec_type = e >> 3; 528 529 for (unsigned i = 0; i < 2; i++) { 530 if (i == 0) { 531 brw_MAD(p, g0, g0, g0, g0); 532 brw_inst_set_3src_a1_exec_type(&devinfo, last_inst, BRW_ALIGN1_3SRC_EXEC_TYPE_FLOAT); 533 } else { 534 brw_CSEL(p, g0, g0, g0, g0); 535 brw_inst_set_3src_cond_modifier(&devinfo, last_inst, BRW_CONDITIONAL_NZ); 536 brw_inst_set_3src_a1_exec_type(&devinfo, last_inst, BRW_ALIGN1_3SRC_EXEC_TYPE_INT); 537 } 538 539 brw_inst_set_3src_a1_exec_type(&devinfo, last_inst, exec_type); 540 brw_inst_set_3src_a1_dst_hw_type (&devinfo, last_inst, hw_type); 541 brw_inst_set_3src_a1_src0_hw_type(&devinfo, last_inst, hw_type); 542 brw_inst_set_3src_a1_src1_hw_type(&devinfo, last_inst, hw_type); 543 brw_inst_set_3src_a1_src2_hw_type(&devinfo, last_inst, hw_type); 544 545 EXPECT_FALSE(validate(p)); 546 547 clear_instructions(p); 548 } 549 } 550} 551 552TEST_P(validation_test, 3src_inst_access_mode) 553{ 554 /* 3-src instructions only supported on Gfx6+ */ 555 if (devinfo.ver < 6) 556 return; 557 558 /* No access mode bit on Gfx12+ */ 559 if (devinfo.ver >= 12) 560 return; 561 562 const struct { 563 unsigned mode; 564 bool expected_result; 565 } test_case[] = { 566 { BRW_ALIGN_1, devinfo.ver >= 10 }, 567 { BRW_ALIGN_16, devinfo.ver <= 10 }, 568 }; 569 570 for (unsigned i = 0; i < ARRAY_SIZE(test_case); i++) { 571 if (devinfo.ver < 10) 572 brw_set_default_access_mode(p, BRW_ALIGN_16); 573 574 brw_MAD(p, g0, g0, g0, g0); 575 brw_inst_set_access_mode(&devinfo, last_inst, test_case[i].mode); 576 577 EXPECT_EQ(test_case[i].expected_result, validate(p)); 578 579 clear_instructions(p); 580 } 581} 582 583/* When the Execution Data Type is wider than the destination data type, the 584 * destination must [...] specify a HorzStride equal to the ratio in sizes of 585 * the two data types. 586 */ 587TEST_P(validation_test, dest_stride_must_be_equal_to_the_ratio_of_exec_size_to_dest_size) 588{ 589 brw_ADD(p, g0, g0, g0); 590 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 591 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D); 592 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D); 593 594 EXPECT_FALSE(validate(p)); 595 596 clear_instructions(p); 597 598 brw_ADD(p, g0, g0, g0); 599 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 600 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 601 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D); 602 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D); 603 604 EXPECT_TRUE(validate(p)); 605} 606 607/* When the Execution Data Type is wider than the destination data type, the 608 * destination must be aligned as required by the wider execution data type 609 * [...] 610 */ 611TEST_P(validation_test, dst_subreg_must_be_aligned_to_exec_type_size) 612{ 613 brw_ADD(p, g0, g0, g0); 614 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 2); 615 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 616 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 617 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D); 618 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D); 619 620 EXPECT_FALSE(validate(p)); 621 622 clear_instructions(p); 623 624 brw_ADD(p, g0, g0, g0); 625 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_4); 626 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 8); 627 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 628 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 629 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D); 630 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 631 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4); 632 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 633 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D); 634 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 635 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4); 636 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 637 638 EXPECT_TRUE(validate(p)); 639} 640 641/* ExecSize must be greater than or equal to Width. */ 642TEST_P(validation_test, exec_size_less_than_width) 643{ 644 brw_ADD(p, g0, g0, g0); 645 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_16); 646 647 EXPECT_FALSE(validate(p)); 648 649 clear_instructions(p); 650 651 brw_ADD(p, g0, g0, g0); 652 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_16); 653 654 EXPECT_FALSE(validate(p)); 655} 656 657/* If ExecSize = Width and HorzStride ≠ 0, 658 * VertStride must be set to Width * HorzStride. 659 */ 660TEST_P(validation_test, vertical_stride_is_width_by_horizontal_stride) 661{ 662 brw_ADD(p, g0, g0, g0); 663 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 664 665 EXPECT_FALSE(validate(p)); 666 667 clear_instructions(p); 668 669 brw_ADD(p, g0, g0, g0); 670 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 671 672 EXPECT_FALSE(validate(p)); 673} 674 675/* If Width = 1, HorzStride must be 0 regardless of the values 676 * of ExecSize and VertStride. 677 */ 678TEST_P(validation_test, horizontal_stride_must_be_0_if_width_is_1) 679{ 680 brw_ADD(p, g0, g0, g0); 681 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_0); 682 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_1); 683 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 684 685 EXPECT_FALSE(validate(p)); 686 687 clear_instructions(p); 688 689 brw_ADD(p, g0, g0, g0); 690 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_0); 691 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_1); 692 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 693 694 EXPECT_FALSE(validate(p)); 695} 696 697/* If ExecSize = Width = 1, both VertStride and HorzStride must be 0. */ 698TEST_P(validation_test, scalar_region_must_be_0_1_0) 699{ 700 struct brw_reg g0_0 = brw_vec1_grf(0, 0); 701 702 brw_ADD(p, g0, g0, g0_0); 703 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_1); 704 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_1); 705 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_1); 706 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0); 707 708 EXPECT_FALSE(validate(p)); 709 710 clear_instructions(p); 711 712 brw_ADD(p, g0, g0_0, g0); 713 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_1); 714 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_1); 715 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_1); 716 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0); 717 718 EXPECT_FALSE(validate(p)); 719} 720 721/* If VertStride = HorzStride = 0, Width must be 1 regardless of the value 722 * of ExecSize. 723 */ 724TEST_P(validation_test, zero_stride_implies_0_1_0) 725{ 726 brw_ADD(p, g0, g0, g0); 727 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_0); 728 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_2); 729 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0); 730 731 EXPECT_FALSE(validate(p)); 732 733 clear_instructions(p); 734 735 brw_ADD(p, g0, g0, g0); 736 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_0); 737 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_2); 738 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0); 739 740 EXPECT_FALSE(validate(p)); 741} 742 743/* Dst.HorzStride must not be 0. */ 744TEST_P(validation_test, dst_horizontal_stride_0) 745{ 746 brw_ADD(p, g0, g0, g0); 747 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0); 748 749 EXPECT_FALSE(validate(p)); 750 751 clear_instructions(p); 752 753 /* Align16 does not exist on Gfx11+ */ 754 if (devinfo.ver >= 11) 755 return; 756 757 brw_set_default_access_mode(p, BRW_ALIGN_16); 758 759 brw_ADD(p, g0, g0, g0); 760 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0); 761 762 EXPECT_FALSE(validate(p)); 763} 764 765/* VertStride must be used to cross BRW_GENERAL_REGISTER_FILE register boundaries. This rule implies 766 * that elements within a 'Width' cannot cross BRW_GENERAL_REGISTER_FILE boundaries. 767 */ 768TEST_P(validation_test, must_not_cross_grf_boundary_in_a_width) 769{ 770 brw_ADD(p, g0, g0, g0); 771 brw_inst_set_src0_da1_subreg_nr(&devinfo, last_inst, 4); 772 773 EXPECT_FALSE(validate(p)); 774 775 clear_instructions(p); 776 777 brw_ADD(p, g0, g0, g0); 778 brw_inst_set_src1_da1_subreg_nr(&devinfo, last_inst, 4); 779 780 EXPECT_FALSE(validate(p)); 781 782 clear_instructions(p); 783 784 brw_ADD(p, g0, g0, g0); 785 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 786 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4); 787 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 788 789 EXPECT_FALSE(validate(p)); 790 791 clear_instructions(p); 792 793 brw_ADD(p, g0, g0, g0); 794 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 795 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4); 796 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 797 798 EXPECT_FALSE(validate(p)); 799} 800 801/* Destination Horizontal must be 1 in Align16 */ 802TEST_P(validation_test, dst_hstride_on_align16_must_be_1) 803{ 804 /* Align16 does not exist on Gfx11+ */ 805 if (devinfo.ver >= 11) 806 return; 807 808 brw_set_default_access_mode(p, BRW_ALIGN_16); 809 810 brw_ADD(p, g0, g0, g0); 811 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 812 813 EXPECT_FALSE(validate(p)); 814 815 clear_instructions(p); 816 817 brw_ADD(p, g0, g0, g0); 818 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 819 820 EXPECT_TRUE(validate(p)); 821} 822 823/* VertStride must be 0 or 4 in Align16 */ 824TEST_P(validation_test, vstride_on_align16_must_be_0_or_4) 825{ 826 /* Align16 does not exist on Gfx11+ */ 827 if (devinfo.ver >= 11) 828 return; 829 830 const struct { 831 enum brw_vertical_stride vstride; 832 bool expected_result; 833 } vstride[] = { 834 { BRW_VERTICAL_STRIDE_0, true }, 835 { BRW_VERTICAL_STRIDE_1, false }, 836 { BRW_VERTICAL_STRIDE_2, devinfo.verx10 >= 75 }, 837 { BRW_VERTICAL_STRIDE_4, true }, 838 { BRW_VERTICAL_STRIDE_8, false }, 839 { BRW_VERTICAL_STRIDE_16, false }, 840 { BRW_VERTICAL_STRIDE_32, false }, 841 { BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL, false }, 842 }; 843 844 brw_set_default_access_mode(p, BRW_ALIGN_16); 845 846 for (unsigned i = 0; i < ARRAY_SIZE(vstride); i++) { 847 brw_ADD(p, g0, g0, g0); 848 brw_inst_set_src0_vstride(&devinfo, last_inst, vstride[i].vstride); 849 850 EXPECT_EQ(vstride[i].expected_result, validate(p)); 851 852 clear_instructions(p); 853 } 854 855 for (unsigned i = 0; i < ARRAY_SIZE(vstride); i++) { 856 brw_ADD(p, g0, g0, g0); 857 brw_inst_set_src1_vstride(&devinfo, last_inst, vstride[i].vstride); 858 859 EXPECT_EQ(vstride[i].expected_result, validate(p)); 860 861 clear_instructions(p); 862 } 863} 864 865/* In Direct Addressing mode, a source cannot span more than 2 adjacent BRW_GENERAL_REGISTER_FILE 866 * registers. 867 */ 868TEST_P(validation_test, source_cannot_span_more_than_2_registers) 869{ 870 brw_ADD(p, g0, g0, g0); 871 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_32); 872 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 873 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 874 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 875 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16); 876 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_8); 877 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 878 879 EXPECT_FALSE(validate(p)); 880 881 clear_instructions(p); 882 883 brw_ADD(p, g0, g0, g0); 884 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16); 885 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 886 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 887 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 888 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16); 889 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_8); 890 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 891 brw_inst_set_src1_da1_subreg_nr(&devinfo, last_inst, 2); 892 893 EXPECT_TRUE(validate(p)); 894 895 clear_instructions(p); 896 897 brw_ADD(p, g0, g0, g0); 898 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16); 899 900 EXPECT_TRUE(validate(p)); 901} 902 903/* A destination cannot span more than 2 adjacent BRW_GENERAL_REGISTER_FILE registers. */ 904TEST_P(validation_test, destination_cannot_span_more_than_2_registers) 905{ 906 brw_ADD(p, g0, g0, g0); 907 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_32); 908 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 909 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 910 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 911 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 912 913 EXPECT_FALSE(validate(p)); 914 915 clear_instructions(p); 916 917 brw_ADD(p, g0, g0, g0); 918 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_8); 919 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 6); 920 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_4); 921 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 922 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 923 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16); 924 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4); 925 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 926 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 927 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16); 928 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4); 929 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 930 931 EXPECT_TRUE(validate(p)); 932} 933 934TEST_P(validation_test, src_region_spans_two_regs_dst_region_spans_one) 935{ 936 /* Writes to dest are to the lower OWord */ 937 brw_ADD(p, g0, g0, g0); 938 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 939 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 940 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 941 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16); 942 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4); 943 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 944 945 EXPECT_TRUE(validate(p)); 946 947 clear_instructions(p); 948 949 /* Writes to dest are to the upper OWord */ 950 brw_ADD(p, g0, g0, g0); 951 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 16); 952 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 953 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 954 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 955 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16); 956 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4); 957 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 958 959 EXPECT_TRUE(validate(p)); 960 961 clear_instructions(p); 962 963 /* Writes to dest are evenly split between OWords */ 964 brw_ADD(p, g0, g0, g0); 965 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16); 966 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 967 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 968 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 969 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16); 970 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_8); 971 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 972 973 EXPECT_TRUE(validate(p)); 974 975 clear_instructions(p); 976 977 /* Writes to dest are uneven between OWords */ 978 brw_ADD(p, g0, g0, g0); 979 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_4); 980 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 10); 981 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 982 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 983 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 984 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4); 985 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 986 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 987 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16); 988 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_2); 989 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 990 991 if (devinfo.ver >= 9) { 992 EXPECT_TRUE(validate(p)); 993 } else { 994 EXPECT_FALSE(validate(p)); 995 } 996} 997 998TEST_P(validation_test, dst_elements_must_be_evenly_split_between_registers) 999{ 1000 brw_ADD(p, g0, g0, g0); 1001 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 4); 1002 1003 if (devinfo.ver >= 9) { 1004 EXPECT_TRUE(validate(p)); 1005 } else { 1006 EXPECT_FALSE(validate(p)); 1007 } 1008 1009 clear_instructions(p); 1010 1011 brw_ADD(p, g0, g0, g0); 1012 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16); 1013 1014 EXPECT_TRUE(validate(p)); 1015 1016 clear_instructions(p); 1017 1018 if (devinfo.ver >= 6) { 1019 gfx6_math(p, g0, BRW_MATH_FUNCTION_SIN, g0, null); 1020 1021 EXPECT_TRUE(validate(p)); 1022 1023 clear_instructions(p); 1024 1025 gfx6_math(p, g0, BRW_MATH_FUNCTION_SIN, g0, null); 1026 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 4); 1027 1028 EXPECT_FALSE(validate(p)); 1029 } 1030} 1031 1032TEST_P(validation_test, two_src_two_dst_source_offsets_must_be_same) 1033{ 1034 brw_ADD(p, g0, g0, g0); 1035 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_4); 1036 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_4); 1037 brw_inst_set_src0_da1_subreg_nr(&devinfo, last_inst, 16); 1038 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_2); 1039 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_1); 1040 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0); 1041 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 1042 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4); 1043 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 1044 1045 if (devinfo.ver <= 7) { 1046 EXPECT_FALSE(validate(p)); 1047 } else { 1048 EXPECT_TRUE(validate(p)); 1049 } 1050 1051 clear_instructions(p); 1052 1053 brw_ADD(p, g0, g0, g0); 1054 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_4); 1055 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_4); 1056 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 1057 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_1); 1058 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0); 1059 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_8); 1060 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_2); 1061 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 1062 1063 EXPECT_TRUE(validate(p)); 1064} 1065 1066TEST_P(validation_test, two_src_two_dst_each_dst_must_be_derived_from_one_src) 1067{ 1068 brw_MOV(p, g0, g0); 1069 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16); 1070 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 1071 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 1072 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 1073 brw_inst_set_src0_da1_subreg_nr(&devinfo, last_inst, 8); 1074 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 1075 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4); 1076 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 1077 1078 if (devinfo.ver <= 7) { 1079 EXPECT_FALSE(validate(p)); 1080 } else { 1081 EXPECT_TRUE(validate(p)); 1082 } 1083 1084 clear_instructions(p); 1085 1086 brw_MOV(p, g0, g0); 1087 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 16); 1088 brw_inst_set_src0_da1_subreg_nr(&devinfo, last_inst, 8); 1089 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_2); 1090 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_2); 1091 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 1092 1093 if (devinfo.ver <= 7) { 1094 EXPECT_FALSE(validate(p)); 1095 } else { 1096 EXPECT_TRUE(validate(p)); 1097 } 1098} 1099 1100TEST_P(validation_test, one_src_two_dst) 1101{ 1102 struct brw_reg g0_0 = brw_vec1_grf(0, 0); 1103 1104 brw_ADD(p, g0, g0_0, g0_0); 1105 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16); 1106 1107 EXPECT_TRUE(validate(p)); 1108 1109 clear_instructions(p); 1110 1111 brw_ADD(p, g0, g0, g0); 1112 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16); 1113 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D); 1114 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 1115 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 1116 1117 EXPECT_TRUE(validate(p)); 1118 1119 clear_instructions(p); 1120 1121 brw_ADD(p, g0, g0, g0); 1122 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16); 1123 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 1124 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 1125 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 1126 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 1127 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_0); 1128 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_1); 1129 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0); 1130 1131 if (devinfo.ver >= 8) { 1132 EXPECT_TRUE(validate(p)); 1133 } else { 1134 EXPECT_FALSE(validate(p)); 1135 } 1136 1137 clear_instructions(p); 1138 1139 brw_ADD(p, g0, g0, g0); 1140 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16); 1141 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 1142 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 1143 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 1144 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_0); 1145 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_1); 1146 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0); 1147 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W); 1148 1149 if (devinfo.ver >= 8) { 1150 EXPECT_TRUE(validate(p)); 1151 } else { 1152 EXPECT_FALSE(validate(p)); 1153 } 1154} 1155 1156TEST_P(validation_test, packed_byte_destination) 1157{ 1158 static const struct { 1159 enum brw_reg_type dst_type; 1160 enum brw_reg_type src_type; 1161 bool neg, abs, sat; 1162 bool expected_result; 1163 } move[] = { 1164 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UB, 0, 0, 0, true }, 1165 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_B , 0, 0, 0, true }, 1166 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_B , 0, 0, 0, true }, 1167 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_UB, 0, 0, 0, true }, 1168 1169 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UB, 1, 0, 0, false }, 1170 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_B , 1, 0, 0, false }, 1171 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_B , 1, 0, 0, false }, 1172 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_UB, 1, 0, 0, false }, 1173 1174 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UB, 0, 1, 0, false }, 1175 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_B , 0, 1, 0, false }, 1176 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_B , 0, 1, 0, false }, 1177 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_UB, 0, 1, 0, false }, 1178 1179 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UB, 0, 0, 1, false }, 1180 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_B , 0, 0, 1, false }, 1181 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_B , 0, 0, 1, false }, 1182 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_UB, 0, 0, 1, false }, 1183 1184 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UW, 0, 0, 0, false }, 1185 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_W , 0, 0, 0, false }, 1186 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UD, 0, 0, 0, false }, 1187 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_D , 0, 0, 0, false }, 1188 }; 1189 1190 for (unsigned i = 0; i < ARRAY_SIZE(move); i++) { 1191 brw_MOV(p, retype(g0, move[i].dst_type), retype(g0, move[i].src_type)); 1192 brw_inst_set_src0_negate(&devinfo, last_inst, move[i].neg); 1193 brw_inst_set_src0_abs(&devinfo, last_inst, move[i].abs); 1194 brw_inst_set_saturate(&devinfo, last_inst, move[i].sat); 1195 1196 EXPECT_EQ(move[i].expected_result, validate(p)); 1197 1198 clear_instructions(p); 1199 } 1200 1201 brw_SEL(p, retype(g0, BRW_REGISTER_TYPE_UB), 1202 retype(g0, BRW_REGISTER_TYPE_UB), 1203 retype(g0, BRW_REGISTER_TYPE_UB)); 1204 brw_inst_set_pred_control(&devinfo, last_inst, BRW_PREDICATE_NORMAL); 1205 1206 EXPECT_FALSE(validate(p)); 1207 1208 clear_instructions(p); 1209 1210 brw_SEL(p, retype(g0, BRW_REGISTER_TYPE_B), 1211 retype(g0, BRW_REGISTER_TYPE_B), 1212 retype(g0, BRW_REGISTER_TYPE_B)); 1213 brw_inst_set_pred_control(&devinfo, last_inst, BRW_PREDICATE_NORMAL); 1214 1215 EXPECT_FALSE(validate(p)); 1216} 1217 1218TEST_P(validation_test, byte_destination_relaxed_alignment) 1219{ 1220 brw_SEL(p, retype(g0, BRW_REGISTER_TYPE_B), 1221 retype(g0, BRW_REGISTER_TYPE_W), 1222 retype(g0, BRW_REGISTER_TYPE_W)); 1223 brw_inst_set_pred_control(&devinfo, last_inst, BRW_PREDICATE_NORMAL); 1224 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 1225 1226 EXPECT_TRUE(validate(p)); 1227 1228 clear_instructions(p); 1229 1230 brw_SEL(p, retype(g0, BRW_REGISTER_TYPE_B), 1231 retype(g0, BRW_REGISTER_TYPE_W), 1232 retype(g0, BRW_REGISTER_TYPE_W)); 1233 brw_inst_set_pred_control(&devinfo, last_inst, BRW_PREDICATE_NORMAL); 1234 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 1235 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 1); 1236 1237 if (devinfo.ver > 4 || devinfo.is_g4x) { 1238 EXPECT_TRUE(validate(p)); 1239 } else { 1240 EXPECT_FALSE(validate(p)); 1241 } 1242} 1243 1244TEST_P(validation_test, byte_64bit_conversion) 1245{ 1246 static const struct { 1247 enum brw_reg_type dst_type; 1248 enum brw_reg_type src_type; 1249 unsigned dst_stride; 1250 bool expected_result; 1251 } inst[] = { 1252#define INST(dst_type, src_type, dst_stride, expected_result) \ 1253 { \ 1254 BRW_REGISTER_TYPE_##dst_type, \ 1255 BRW_REGISTER_TYPE_##src_type, \ 1256 BRW_HORIZONTAL_STRIDE_##dst_stride, \ 1257 expected_result, \ 1258 } 1259 1260 INST(B, Q, 1, false), 1261 INST(B, UQ, 1, false), 1262 INST(B, DF, 1, false), 1263 INST(UB, Q, 1, false), 1264 INST(UB, UQ, 1, false), 1265 INST(UB, DF, 1, false), 1266 1267 INST(B, Q, 2, false), 1268 INST(B, UQ, 2, false), 1269 INST(B , DF, 2, false), 1270 INST(UB, Q, 2, false), 1271 INST(UB, UQ, 2, false), 1272 INST(UB, DF, 2, false), 1273 1274 INST(B, Q, 4, false), 1275 INST(B, UQ, 4, false), 1276 INST(B, DF, 4, false), 1277 INST(UB, Q, 4, false), 1278 INST(UB, UQ, 4, false), 1279 INST(UB, DF, 4, false), 1280 1281#undef INST 1282 }; 1283 1284 if (devinfo.ver < 8) 1285 return; 1286 1287 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 1288 if (!devinfo.has_64bit_float && 1289 inst[i].src_type == BRW_REGISTER_TYPE_DF) 1290 continue; 1291 1292 if (!devinfo.has_64bit_int && 1293 (inst[i].src_type == BRW_REGISTER_TYPE_Q || 1294 inst[i].src_type == BRW_REGISTER_TYPE_UQ)) 1295 continue; 1296 1297 brw_MOV(p, retype(g0, inst[i].dst_type), retype(g0, inst[i].src_type)); 1298 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride); 1299 EXPECT_EQ(inst[i].expected_result, validate(p)); 1300 1301 clear_instructions(p); 1302 } 1303} 1304 1305TEST_P(validation_test, half_float_conversion) 1306{ 1307 static const struct { 1308 enum brw_reg_type dst_type; 1309 enum brw_reg_type src_type; 1310 unsigned dst_stride; 1311 unsigned dst_subnr; 1312 bool expected_result_bdw; 1313 bool expected_result_chv_gfx9; 1314 } inst[] = { 1315#define INST_C(dst_type, src_type, dst_stride, dst_subnr, expected_result) \ 1316 { \ 1317 BRW_REGISTER_TYPE_##dst_type, \ 1318 BRW_REGISTER_TYPE_##src_type, \ 1319 BRW_HORIZONTAL_STRIDE_##dst_stride, \ 1320 dst_subnr, \ 1321 expected_result, \ 1322 expected_result, \ 1323 } 1324#define INST_S(dst_type, src_type, dst_stride, dst_subnr, \ 1325 expected_result_bdw, expected_result_chv_gfx9) \ 1326 { \ 1327 BRW_REGISTER_TYPE_##dst_type, \ 1328 BRW_REGISTER_TYPE_##src_type, \ 1329 BRW_HORIZONTAL_STRIDE_##dst_stride, \ 1330 dst_subnr, \ 1331 expected_result_bdw, \ 1332 expected_result_chv_gfx9, \ 1333 } 1334 1335 /* MOV to half-float destination */ 1336 INST_C(HF, B, 1, 0, false), 1337 INST_C(HF, W, 1, 0, false), 1338 INST_C(HF, HF, 1, 0, true), 1339 INST_C(HF, HF, 1, 2, true), 1340 INST_C(HF, D, 1, 0, false), 1341 INST_S(HF, F, 1, 0, false, true), 1342 INST_C(HF, Q, 1, 0, false), 1343 INST_C(HF, B, 2, 0, true), 1344 INST_C(HF, B, 2, 2, false), 1345 INST_C(HF, W, 2, 0, true), 1346 INST_C(HF, W, 2, 2, false), 1347 INST_C(HF, HF, 2, 0, true), 1348 INST_C(HF, HF, 2, 2, true), 1349 INST_C(HF, D, 2, 0, true), 1350 INST_C(HF, D, 2, 2, false), 1351 INST_C(HF, F, 2, 0, true), 1352 INST_S(HF, F, 2, 2, false, true), 1353 INST_C(HF, Q, 2, 0, false), 1354 INST_C(HF, DF, 2, 0, false), 1355 INST_C(HF, B, 4, 0, false), 1356 INST_C(HF, W, 4, 0, false), 1357 INST_C(HF, HF, 4, 0, true), 1358 INST_C(HF, HF, 4, 2, true), 1359 INST_C(HF, D, 4, 0, false), 1360 INST_C(HF, F, 4, 0, false), 1361 INST_C(HF, Q, 4, 0, false), 1362 INST_C(HF, DF, 4, 0, false), 1363 1364 /* MOV from half-float source */ 1365 INST_C( B, HF, 1, 0, false), 1366 INST_C( W, HF, 1, 0, false), 1367 INST_C( D, HF, 1, 0, true), 1368 INST_C( D, HF, 1, 4, true), 1369 INST_C( F, HF, 1, 0, true), 1370 INST_C( F, HF, 1, 4, true), 1371 INST_C( Q, HF, 1, 0, false), 1372 INST_C(DF, HF, 1, 0, false), 1373 INST_C( B, HF, 2, 0, false), 1374 INST_C( W, HF, 2, 0, true), 1375 INST_C( W, HF, 2, 2, false), 1376 INST_C( D, HF, 2, 0, false), 1377 INST_C( F, HF, 2, 0, true), 1378 INST_C( B, HF, 4, 0, true), 1379 INST_C( B, HF, 4, 1, false), 1380 INST_C( W, HF, 4, 0, false), 1381 1382#undef INST_C 1383#undef INST_S 1384 }; 1385 1386 if (devinfo.ver < 8) 1387 return; 1388 1389 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 1390 if (!devinfo.has_64bit_float && 1391 (inst[i].dst_type == BRW_REGISTER_TYPE_DF || 1392 inst[i].src_type == BRW_REGISTER_TYPE_DF)) 1393 continue; 1394 1395 if (!devinfo.has_64bit_int && 1396 (inst[i].dst_type == BRW_REGISTER_TYPE_Q || 1397 inst[i].dst_type == BRW_REGISTER_TYPE_UQ || 1398 inst[i].src_type == BRW_REGISTER_TYPE_Q || 1399 inst[i].src_type == BRW_REGISTER_TYPE_UQ)) 1400 continue; 1401 1402 brw_MOV(p, retype(g0, inst[i].dst_type), retype(g0, inst[i].src_type)); 1403 1404 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_4); 1405 1406 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride); 1407 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, inst[i].dst_subnr); 1408 1409 if (inst[i].src_type == BRW_REGISTER_TYPE_B) { 1410 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 1411 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_2); 1412 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2); 1413 } else { 1414 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 1415 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4); 1416 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 1417 } 1418 1419 if (devinfo.is_cherryview || devinfo.ver >= 9) 1420 EXPECT_EQ(inst[i].expected_result_chv_gfx9, validate(p)); 1421 else 1422 EXPECT_EQ(inst[i].expected_result_bdw, validate(p)); 1423 1424 clear_instructions(p); 1425 } 1426} 1427 1428TEST_P(validation_test, mixed_float_source_indirect_addressing) 1429{ 1430 static const struct { 1431 enum brw_reg_type dst_type; 1432 enum brw_reg_type src0_type; 1433 enum brw_reg_type src1_type; 1434 unsigned dst_stride; 1435 bool dst_indirect; 1436 bool src0_indirect; 1437 bool expected_result; 1438 } inst[] = { 1439#define INST(dst_type, src0_type, src1_type, \ 1440 dst_stride, dst_indirect, src0_indirect, expected_result) \ 1441 { \ 1442 BRW_REGISTER_TYPE_##dst_type, \ 1443 BRW_REGISTER_TYPE_##src0_type, \ 1444 BRW_REGISTER_TYPE_##src1_type, \ 1445 BRW_HORIZONTAL_STRIDE_##dst_stride, \ 1446 dst_indirect, \ 1447 src0_indirect, \ 1448 expected_result, \ 1449 } 1450 1451 /* Source and dest are mixed float: indirect src addressing not allowed */ 1452 INST(HF, F, F, 2, false, false, true), 1453 INST(HF, F, F, 2, true, false, true), 1454 INST(HF, F, F, 2, false, true, false), 1455 INST(HF, F, F, 2, true, true, false), 1456 INST( F, HF, F, 1, false, false, true), 1457 INST( F, HF, F, 1, true, false, true), 1458 INST( F, HF, F, 1, false, true, false), 1459 INST( F, HF, F, 1, true, true, false), 1460 1461 INST(HF, HF, F, 2, false, false, true), 1462 INST(HF, HF, F, 2, true, false, true), 1463 INST(HF, HF, F, 2, false, true, false), 1464 INST(HF, HF, F, 2, true, true, false), 1465 INST( F, F, HF, 1, false, false, true), 1466 INST( F, F, HF, 1, true, false, true), 1467 INST( F, F, HF, 1, false, true, false), 1468 INST( F, F, HF, 1, true, true, false), 1469 1470#undef INST 1471 }; 1472 1473 if (devinfo.ver < 8) 1474 return; 1475 1476 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 1477 brw_ADD(p, retype(g0, inst[i].dst_type), 1478 retype(g0, inst[i].src0_type), 1479 retype(g0, inst[i].src1_type)); 1480 1481 brw_inst_set_dst_address_mode(&devinfo, last_inst, inst[i].dst_indirect); 1482 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride); 1483 brw_inst_set_src0_address_mode(&devinfo, last_inst, inst[i].src0_indirect); 1484 1485 EXPECT_EQ(inst[i].expected_result, validate(p)); 1486 1487 clear_instructions(p); 1488 } 1489} 1490 1491TEST_P(validation_test, mixed_float_align1_simd16) 1492{ 1493 static const struct { 1494 unsigned exec_size; 1495 enum brw_reg_type dst_type; 1496 enum brw_reg_type src0_type; 1497 enum brw_reg_type src1_type; 1498 unsigned dst_stride; 1499 bool expected_result; 1500 } inst[] = { 1501#define INST(exec_size, dst_type, src0_type, src1_type, \ 1502 dst_stride, expected_result) \ 1503 { \ 1504 BRW_EXECUTE_##exec_size, \ 1505 BRW_REGISTER_TYPE_##dst_type, \ 1506 BRW_REGISTER_TYPE_##src0_type, \ 1507 BRW_REGISTER_TYPE_##src1_type, \ 1508 BRW_HORIZONTAL_STRIDE_##dst_stride, \ 1509 expected_result, \ 1510 } 1511 1512 /* No SIMD16 in mixed mode when destination is packed f16 */ 1513 INST( 8, HF, F, HF, 2, true), 1514 INST(16, HF, HF, F, 2, true), 1515 INST(16, HF, HF, F, 1, false), 1516 INST(16, HF, F, HF, 1, false), 1517 1518 /* No SIMD16 in mixed mode when destination is f32 */ 1519 INST( 8, F, HF, F, 1, true), 1520 INST( 8, F, F, HF, 1, true), 1521 INST(16, F, HF, F, 1, false), 1522 INST(16, F, F, HF, 1, false), 1523 1524#undef INST 1525 }; 1526 1527 if (devinfo.ver < 8) 1528 return; 1529 1530 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 1531 brw_ADD(p, retype(g0, inst[i].dst_type), 1532 retype(g0, inst[i].src0_type), 1533 retype(g0, inst[i].src1_type)); 1534 1535 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size); 1536 1537 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride); 1538 1539 EXPECT_EQ(inst[i].expected_result, validate(p)); 1540 1541 clear_instructions(p); 1542 } 1543} 1544 1545TEST_P(validation_test, mixed_float_align1_packed_fp16_dst_acc_read_offset_0) 1546{ 1547 static const struct { 1548 enum brw_reg_type dst_type; 1549 enum brw_reg_type src0_type; 1550 enum brw_reg_type src1_type; 1551 unsigned dst_stride; 1552 bool read_acc; 1553 unsigned subnr; 1554 bool expected_result_bdw; 1555 bool expected_result_chv_skl; 1556 } inst[] = { 1557#define INST(dst_type, src0_type, src1_type, dst_stride, read_acc, subnr, \ 1558 expected_result_bdw, expected_result_chv_skl) \ 1559 { \ 1560 BRW_REGISTER_TYPE_##dst_type, \ 1561 BRW_REGISTER_TYPE_##src0_type, \ 1562 BRW_REGISTER_TYPE_##src1_type, \ 1563 BRW_HORIZONTAL_STRIDE_##dst_stride, \ 1564 read_acc, \ 1565 subnr, \ 1566 expected_result_bdw, \ 1567 expected_result_chv_skl, \ 1568 } 1569 1570 /* Destination is not packed */ 1571 INST(HF, HF, F, 2, true, 0, true, true), 1572 INST(HF, HF, F, 2, true, 2, true, true), 1573 INST(HF, HF, F, 2, true, 4, true, true), 1574 INST(HF, HF, F, 2, true, 8, true, true), 1575 INST(HF, HF, F, 2, true, 16, true, true), 1576 1577 /* Destination is packed, we don't read acc */ 1578 INST(HF, HF, F, 1, false, 0, false, true), 1579 INST(HF, HF, F, 1, false, 2, false, true), 1580 INST(HF, HF, F, 1, false, 4, false, true), 1581 INST(HF, HF, F, 1, false, 8, false, true), 1582 INST(HF, HF, F, 1, false, 16, false, true), 1583 1584 /* Destination is packed, we read acc */ 1585 INST(HF, HF, F, 1, true, 0, false, false), 1586 INST(HF, HF, F, 1, true, 2, false, false), 1587 INST(HF, HF, F, 1, true, 4, false, false), 1588 INST(HF, HF, F, 1, true, 8, false, false), 1589 INST(HF, HF, F, 1, true, 16, false, false), 1590 1591#undef INST 1592 }; 1593 1594 if (devinfo.ver < 8) 1595 return; 1596 1597 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 1598 brw_ADD(p, retype(g0, inst[i].dst_type), 1599 retype(inst[i].read_acc ? acc0 : g0, inst[i].src0_type), 1600 retype(g0, inst[i].src1_type)); 1601 1602 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride); 1603 1604 brw_inst_set_src0_da1_subreg_nr(&devinfo, last_inst, inst[i].subnr); 1605 1606 if (devinfo.is_cherryview || devinfo.ver >= 9) 1607 EXPECT_EQ(inst[i].expected_result_chv_skl, validate(p)); 1608 else 1609 EXPECT_EQ(inst[i].expected_result_bdw, validate(p)); 1610 1611 clear_instructions(p); 1612 } 1613} 1614 1615TEST_P(validation_test, mixed_float_fp16_dest_with_acc) 1616{ 1617 static const struct { 1618 unsigned exec_size; 1619 unsigned opcode; 1620 enum brw_reg_type dst_type; 1621 enum brw_reg_type src0_type; 1622 enum brw_reg_type src1_type; 1623 unsigned dst_stride; 1624 bool read_acc; 1625 bool expected_result_bdw; 1626 bool expected_result_chv_skl; 1627 } inst[] = { 1628#define INST(exec_size, opcode, dst_type, src0_type, src1_type, \ 1629 dst_stride, read_acc,expected_result_bdw, \ 1630 expected_result_chv_skl) \ 1631 { \ 1632 BRW_EXECUTE_##exec_size, \ 1633 BRW_OPCODE_##opcode, \ 1634 BRW_REGISTER_TYPE_##dst_type, \ 1635 BRW_REGISTER_TYPE_##src0_type, \ 1636 BRW_REGISTER_TYPE_##src1_type, \ 1637 BRW_HORIZONTAL_STRIDE_##dst_stride, \ 1638 read_acc, \ 1639 expected_result_bdw, \ 1640 expected_result_chv_skl, \ 1641 } 1642 1643 /* Packed fp16 dest with implicit acc needs hstride=2 */ 1644 INST(8, MAC, HF, HF, F, 1, false, false, false), 1645 INST(8, MAC, HF, HF, F, 2, false, true, true), 1646 INST(8, MAC, HF, F, HF, 1, false, false, false), 1647 INST(8, MAC, HF, F, HF, 2, false, true, true), 1648 1649 /* Packed fp16 dest with explicit acc needs hstride=2 */ 1650 INST(8, ADD, HF, HF, F, 1, true, false, false), 1651 INST(8, ADD, HF, HF, F, 2, true, true, true), 1652 INST(8, ADD, HF, F, HF, 1, true, false, false), 1653 INST(8, ADD, HF, F, HF, 2, true, true, true), 1654 1655 /* If destination is not fp16, restriction doesn't apply */ 1656 INST(8, MAC, F, HF, F, 1, false, true, true), 1657 INST(8, MAC, F, HF, F, 2, false, true, true), 1658 1659 /* If there is no implicit/explicit acc, restriction doesn't apply */ 1660 INST(8, ADD, HF, HF, F, 1, false, false, true), 1661 INST(8, ADD, HF, HF, F, 2, false, true, true), 1662 INST(8, ADD, HF, F, HF, 1, false, false, true), 1663 INST(8, ADD, HF, F, HF, 2, false, true, true), 1664 INST(8, ADD, F, HF, F, 1, false, true, true), 1665 INST(8, ADD, F, HF, F, 2, false, true, true), 1666 1667#undef INST 1668 }; 1669 1670 if (devinfo.ver < 8) 1671 return; 1672 1673 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 1674 if (inst[i].opcode == BRW_OPCODE_MAC) { 1675 brw_MAC(p, retype(g0, inst[i].dst_type), 1676 retype(g0, inst[i].src0_type), 1677 retype(g0, inst[i].src1_type)); 1678 } else { 1679 assert(inst[i].opcode == BRW_OPCODE_ADD); 1680 brw_ADD(p, retype(g0, inst[i].dst_type), 1681 retype(inst[i].read_acc ? acc0: g0, inst[i].src0_type), 1682 retype(g0, inst[i].src1_type)); 1683 } 1684 1685 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size); 1686 1687 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride); 1688 1689 if (devinfo.is_cherryview || devinfo.ver >= 9) 1690 EXPECT_EQ(inst[i].expected_result_chv_skl, validate(p)); 1691 else 1692 EXPECT_EQ(inst[i].expected_result_bdw, validate(p)); 1693 1694 clear_instructions(p); 1695 } 1696} 1697 1698TEST_P(validation_test, mixed_float_align1_math_strided_fp16_inputs) 1699{ 1700 static const struct { 1701 enum brw_reg_type dst_type; 1702 enum brw_reg_type src0_type; 1703 enum brw_reg_type src1_type; 1704 unsigned dst_stride; 1705 unsigned src0_stride; 1706 unsigned src1_stride; 1707 bool expected_result; 1708 } inst[] = { 1709#define INST(dst_type, src0_type, src1_type, \ 1710 dst_stride, src0_stride, src1_stride, expected_result) \ 1711 { \ 1712 BRW_REGISTER_TYPE_##dst_type, \ 1713 BRW_REGISTER_TYPE_##src0_type, \ 1714 BRW_REGISTER_TYPE_##src1_type, \ 1715 BRW_HORIZONTAL_STRIDE_##dst_stride, \ 1716 BRW_HORIZONTAL_STRIDE_##src0_stride, \ 1717 BRW_HORIZONTAL_STRIDE_##src1_stride, \ 1718 expected_result, \ 1719 } 1720 1721 INST(HF, HF, F, 2, 2, 1, true), 1722 INST(HF, F, HF, 2, 1, 2, true), 1723 INST(HF, F, HF, 1, 1, 2, true), 1724 INST(HF, F, HF, 2, 1, 1, false), 1725 INST(HF, HF, F, 2, 1, 1, false), 1726 INST(HF, HF, F, 1, 1, 1, false), 1727 INST(HF, HF, F, 2, 1, 1, false), 1728 INST( F, HF, F, 1, 1, 1, false), 1729 INST( F, F, HF, 1, 1, 2, true), 1730 INST( F, HF, HF, 1, 2, 1, false), 1731 INST( F, HF, HF, 1, 2, 2, true), 1732 1733#undef INST 1734 }; 1735 1736 /* No half-float math in gfx8 */ 1737 if (devinfo.ver < 9) 1738 return; 1739 1740 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 1741 gfx6_math(p, retype(g0, inst[i].dst_type), 1742 BRW_MATH_FUNCTION_POW, 1743 retype(g0, inst[i].src0_type), 1744 retype(g0, inst[i].src1_type)); 1745 1746 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride); 1747 1748 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 1749 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4); 1750 brw_inst_set_src0_hstride(&devinfo, last_inst, inst[i].src0_stride); 1751 1752 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 1753 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4); 1754 brw_inst_set_src1_hstride(&devinfo, last_inst, inst[i].src1_stride); 1755 1756 EXPECT_EQ(inst[i].expected_result, validate(p)); 1757 1758 clear_instructions(p); 1759 } 1760} 1761 1762TEST_P(validation_test, mixed_float_align1_packed_fp16_dst) 1763{ 1764 static const struct { 1765 unsigned exec_size; 1766 enum brw_reg_type dst_type; 1767 enum brw_reg_type src0_type; 1768 enum brw_reg_type src1_type; 1769 unsigned dst_stride; 1770 unsigned dst_subnr; 1771 bool expected_result_bdw; 1772 bool expected_result_chv_skl; 1773 } inst[] = { 1774#define INST(exec_size, dst_type, src0_type, src1_type, dst_stride, dst_subnr, \ 1775 expected_result_bdw, expected_result_chv_skl) \ 1776 { \ 1777 BRW_EXECUTE_##exec_size, \ 1778 BRW_REGISTER_TYPE_##dst_type, \ 1779 BRW_REGISTER_TYPE_##src0_type, \ 1780 BRW_REGISTER_TYPE_##src1_type, \ 1781 BRW_HORIZONTAL_STRIDE_##dst_stride, \ 1782 dst_subnr, \ 1783 expected_result_bdw, \ 1784 expected_result_chv_skl \ 1785 } 1786 1787 /* SIMD8 packed fp16 dst won't cross oword boundaries if region is 1788 * oword-aligned 1789 */ 1790 INST( 8, HF, HF, F, 1, 0, false, true), 1791 INST( 8, HF, HF, F, 1, 2, false, false), 1792 INST( 8, HF, HF, F, 1, 4, false, false), 1793 INST( 8, HF, HF, F, 1, 8, false, false), 1794 INST( 8, HF, HF, F, 1, 16, false, true), 1795 1796 /* SIMD16 packed fp16 always crosses oword boundaries */ 1797 INST(16, HF, HF, F, 1, 0, false, false), 1798 INST(16, HF, HF, F, 1, 2, false, false), 1799 INST(16, HF, HF, F, 1, 4, false, false), 1800 INST(16, HF, HF, F, 1, 8, false, false), 1801 INST(16, HF, HF, F, 1, 16, false, false), 1802 1803 /* If destination is not packed (or not fp16) we can cross oword 1804 * boundaries 1805 */ 1806 INST( 8, HF, HF, F, 2, 0, true, true), 1807 INST( 8, F, HF, F, 1, 0, true, true), 1808 1809#undef INST 1810 }; 1811 1812 if (devinfo.ver < 8) 1813 return; 1814 1815 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 1816 brw_ADD(p, retype(g0, inst[i].dst_type), 1817 retype(g0, inst[i].src0_type), 1818 retype(g0, inst[i].src1_type)); 1819 1820 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride); 1821 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, inst[i].dst_subnr); 1822 1823 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 1824 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4); 1825 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 1826 1827 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 1828 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4); 1829 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 1830 1831 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size); 1832 1833 if (devinfo.is_cherryview || devinfo.ver >= 9) 1834 EXPECT_EQ(inst[i].expected_result_chv_skl, validate(p)); 1835 else 1836 EXPECT_EQ(inst[i].expected_result_bdw, validate(p)); 1837 1838 clear_instructions(p); 1839 } 1840} 1841 1842TEST_P(validation_test, mixed_float_align16_packed_data) 1843{ 1844 static const struct { 1845 enum brw_reg_type dst_type; 1846 enum brw_reg_type src0_type; 1847 enum brw_reg_type src1_type; 1848 unsigned src0_vstride; 1849 unsigned src1_vstride; 1850 bool expected_result; 1851 } inst[] = { 1852#define INST(dst_type, src0_type, src1_type, \ 1853 src0_vstride, src1_vstride, expected_result) \ 1854 { \ 1855 BRW_REGISTER_TYPE_##dst_type, \ 1856 BRW_REGISTER_TYPE_##src0_type, \ 1857 BRW_REGISTER_TYPE_##src1_type, \ 1858 BRW_VERTICAL_STRIDE_##src0_vstride, \ 1859 BRW_VERTICAL_STRIDE_##src1_vstride, \ 1860 expected_result, \ 1861 } 1862 1863 /* We only test with F destination because there is a restriction 1864 * by which F->HF conversions need to be DWord aligned but Align16 also 1865 * requires that destination horizontal stride is 1. 1866 */ 1867 INST(F, F, HF, 4, 4, true), 1868 INST(F, F, HF, 2, 4, false), 1869 INST(F, F, HF, 4, 2, false), 1870 INST(F, F, HF, 0, 4, false), 1871 INST(F, F, HF, 4, 0, false), 1872 INST(F, HF, F, 4, 4, true), 1873 INST(F, HF, F, 4, 2, false), 1874 INST(F, HF, F, 2, 4, false), 1875 INST(F, HF, F, 0, 4, false), 1876 INST(F, HF, F, 4, 0, false), 1877 1878#undef INST 1879 }; 1880 1881 if (devinfo.ver < 8 || devinfo.ver >= 11) 1882 return; 1883 1884 brw_set_default_access_mode(p, BRW_ALIGN_16); 1885 1886 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 1887 brw_ADD(p, retype(g0, inst[i].dst_type), 1888 retype(g0, inst[i].src0_type), 1889 retype(g0, inst[i].src1_type)); 1890 1891 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].src0_vstride); 1892 brw_inst_set_src1_vstride(&devinfo, last_inst, inst[i].src1_vstride); 1893 1894 EXPECT_EQ(inst[i].expected_result, validate(p)); 1895 1896 clear_instructions(p); 1897 } 1898} 1899 1900TEST_P(validation_test, mixed_float_align16_no_simd16) 1901{ 1902 static const struct { 1903 unsigned exec_size; 1904 enum brw_reg_type dst_type; 1905 enum brw_reg_type src0_type; 1906 enum brw_reg_type src1_type; 1907 bool expected_result; 1908 } inst[] = { 1909#define INST(exec_size, dst_type, src0_type, src1_type, expected_result) \ 1910 { \ 1911 BRW_EXECUTE_##exec_size, \ 1912 BRW_REGISTER_TYPE_##dst_type, \ 1913 BRW_REGISTER_TYPE_##src0_type, \ 1914 BRW_REGISTER_TYPE_##src1_type, \ 1915 expected_result, \ 1916 } 1917 1918 /* We only test with F destination because there is a restriction 1919 * by which F->HF conversions need to be DWord aligned but Align16 also 1920 * requires that destination horizontal stride is 1. 1921 */ 1922 INST( 8, F, F, HF, true), 1923 INST( 8, F, HF, F, true), 1924 INST( 8, F, F, HF, true), 1925 INST(16, F, F, HF, false), 1926 INST(16, F, HF, F, false), 1927 INST(16, F, F, HF, false), 1928 1929#undef INST 1930 }; 1931 1932 if (devinfo.ver < 8 || devinfo.ver >= 11) 1933 return; 1934 1935 brw_set_default_access_mode(p, BRW_ALIGN_16); 1936 1937 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 1938 brw_ADD(p, retype(g0, inst[i].dst_type), 1939 retype(g0, inst[i].src0_type), 1940 retype(g0, inst[i].src1_type)); 1941 1942 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size); 1943 1944 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 1945 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 1946 1947 EXPECT_EQ(inst[i].expected_result, validate(p)); 1948 1949 clear_instructions(p); 1950 } 1951} 1952 1953TEST_P(validation_test, mixed_float_align16_no_acc_read) 1954{ 1955 static const struct { 1956 enum brw_reg_type dst_type; 1957 enum brw_reg_type src0_type; 1958 enum brw_reg_type src1_type; 1959 bool read_acc; 1960 bool expected_result; 1961 } inst[] = { 1962#define INST(dst_type, src0_type, src1_type, read_acc, expected_result) \ 1963 { \ 1964 BRW_REGISTER_TYPE_##dst_type, \ 1965 BRW_REGISTER_TYPE_##src0_type, \ 1966 BRW_REGISTER_TYPE_##src1_type, \ 1967 read_acc, \ 1968 expected_result, \ 1969 } 1970 1971 /* We only test with F destination because there is a restriction 1972 * by which F->HF conversions need to be DWord aligned but Align16 also 1973 * requires that destination horizontal stride is 1. 1974 */ 1975 INST( F, F, HF, false, true), 1976 INST( F, F, HF, true, false), 1977 INST( F, HF, F, false, true), 1978 INST( F, HF, F, true, false), 1979 1980#undef INST 1981 }; 1982 1983 if (devinfo.ver < 8 || devinfo.ver >= 11) 1984 return; 1985 1986 brw_set_default_access_mode(p, BRW_ALIGN_16); 1987 1988 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 1989 brw_ADD(p, retype(g0, inst[i].dst_type), 1990 retype(inst[i].read_acc ? acc0 : g0, inst[i].src0_type), 1991 retype(g0, inst[i].src1_type)); 1992 1993 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 1994 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4); 1995 1996 EXPECT_EQ(inst[i].expected_result, validate(p)); 1997 1998 clear_instructions(p); 1999 } 2000} 2001 2002TEST_P(validation_test, mixed_float_align16_math_packed_format) 2003{ 2004 static const struct { 2005 enum brw_reg_type dst_type; 2006 enum brw_reg_type src0_type; 2007 enum brw_reg_type src1_type; 2008 unsigned src0_vstride; 2009 unsigned src1_vstride; 2010 bool expected_result; 2011 } inst[] = { 2012#define INST(dst_type, src0_type, src1_type, \ 2013 src0_vstride, src1_vstride, expected_result) \ 2014 { \ 2015 BRW_REGISTER_TYPE_##dst_type, \ 2016 BRW_REGISTER_TYPE_##src0_type, \ 2017 BRW_REGISTER_TYPE_##src1_type, \ 2018 BRW_VERTICAL_STRIDE_##src0_vstride, \ 2019 BRW_VERTICAL_STRIDE_##src1_vstride, \ 2020 expected_result, \ 2021 } 2022 2023 /* We only test with F destination because there is a restriction 2024 * by which F->HF conversions need to be DWord aligned but Align16 also 2025 * requires that destination horizontal stride is 1. 2026 */ 2027 INST( F, HF, F, 4, 0, false), 2028 INST( F, HF, HF, 4, 4, true), 2029 INST( F, F, HF, 4, 0, false), 2030 INST( F, F, HF, 2, 4, false), 2031 INST( F, F, HF, 4, 2, false), 2032 INST( F, HF, HF, 0, 4, false), 2033 2034#undef INST 2035 }; 2036 2037 /* Align16 Math for mixed float mode is not supported in gfx8 */ 2038 if (devinfo.ver < 9 || devinfo.ver >= 11) 2039 return; 2040 2041 brw_set_default_access_mode(p, BRW_ALIGN_16); 2042 2043 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 2044 gfx6_math(p, retype(g0, inst[i].dst_type), 2045 BRW_MATH_FUNCTION_POW, 2046 retype(g0, inst[i].src0_type), 2047 retype(g0, inst[i].src1_type)); 2048 2049 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].src0_vstride); 2050 brw_inst_set_src1_vstride(&devinfo, last_inst, inst[i].src1_vstride); 2051 2052 EXPECT_EQ(inst[i].expected_result, validate(p)); 2053 2054 clear_instructions(p); 2055 } 2056} 2057 2058TEST_P(validation_test, vector_immediate_destination_alignment) 2059{ 2060 static const struct { 2061 enum brw_reg_type dst_type; 2062 enum brw_reg_type src_type; 2063 unsigned subnr; 2064 unsigned exec_size; 2065 bool expected_result; 2066 } move[] = { 2067 { BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_VF, 0, BRW_EXECUTE_4, true }, 2068 { BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_VF, 16, BRW_EXECUTE_4, true }, 2069 { BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_VF, 1, BRW_EXECUTE_4, false }, 2070 2071 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, 0, BRW_EXECUTE_8, true }, 2072 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, 16, BRW_EXECUTE_8, true }, 2073 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, 1, BRW_EXECUTE_8, false }, 2074 2075 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, 0, BRW_EXECUTE_8, true }, 2076 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, 16, BRW_EXECUTE_8, true }, 2077 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, 1, BRW_EXECUTE_8, false }, 2078 }; 2079 2080 for (unsigned i = 0; i < ARRAY_SIZE(move); i++) { 2081 /* UV type is Gfx6+ */ 2082 if (devinfo.ver < 6 && 2083 move[i].src_type == BRW_REGISTER_TYPE_UV) 2084 continue; 2085 2086 brw_MOV(p, retype(g0, move[i].dst_type), retype(zero, move[i].src_type)); 2087 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, move[i].subnr); 2088 brw_inst_set_exec_size(&devinfo, last_inst, move[i].exec_size); 2089 2090 EXPECT_EQ(move[i].expected_result, validate(p)); 2091 2092 clear_instructions(p); 2093 } 2094} 2095 2096TEST_P(validation_test, vector_immediate_destination_stride) 2097{ 2098 static const struct { 2099 enum brw_reg_type dst_type; 2100 enum brw_reg_type src_type; 2101 unsigned stride; 2102 bool expected_result; 2103 } move[] = { 2104 { BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_1, true }, 2105 { BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_2, false }, 2106 { BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_1, true }, 2107 { BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_2, false }, 2108 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_2, true }, 2109 { BRW_REGISTER_TYPE_B, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_4, true }, 2110 2111 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, BRW_HORIZONTAL_STRIDE_1, true }, 2112 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, BRW_HORIZONTAL_STRIDE_2, false }, 2113 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, BRW_HORIZONTAL_STRIDE_4, false }, 2114 { BRW_REGISTER_TYPE_B, BRW_REGISTER_TYPE_V, BRW_HORIZONTAL_STRIDE_2, true }, 2115 2116 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, BRW_HORIZONTAL_STRIDE_1, true }, 2117 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, BRW_HORIZONTAL_STRIDE_2, false }, 2118 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, BRW_HORIZONTAL_STRIDE_4, false }, 2119 { BRW_REGISTER_TYPE_B, BRW_REGISTER_TYPE_UV, BRW_HORIZONTAL_STRIDE_2, true }, 2120 }; 2121 2122 for (unsigned i = 0; i < ARRAY_SIZE(move); i++) { 2123 /* UV type is Gfx6+ */ 2124 if (devinfo.ver < 6 && 2125 move[i].src_type == BRW_REGISTER_TYPE_UV) 2126 continue; 2127 2128 brw_MOV(p, retype(g0, move[i].dst_type), retype(zero, move[i].src_type)); 2129 brw_inst_set_dst_hstride(&devinfo, last_inst, move[i].stride); 2130 2131 EXPECT_EQ(move[i].expected_result, validate(p)); 2132 2133 clear_instructions(p); 2134 } 2135} 2136 2137TEST_P(validation_test, qword_low_power_align1_regioning_restrictions) 2138{ 2139 static const struct { 2140 enum opcode opcode; 2141 unsigned exec_size; 2142 2143 enum brw_reg_type dst_type; 2144 unsigned dst_subreg; 2145 unsigned dst_stride; 2146 2147 enum brw_reg_type src_type; 2148 unsigned src_subreg; 2149 unsigned src_vstride; 2150 unsigned src_width; 2151 unsigned src_hstride; 2152 2153 bool expected_result; 2154 } inst[] = { 2155#define INST(opcode, exec_size, dst_type, dst_subreg, dst_stride, src_type, \ 2156 src_subreg, src_vstride, src_width, src_hstride, expected_result) \ 2157 { \ 2158 BRW_OPCODE_##opcode, \ 2159 BRW_EXECUTE_##exec_size, \ 2160 BRW_REGISTER_TYPE_##dst_type, \ 2161 dst_subreg, \ 2162 BRW_HORIZONTAL_STRIDE_##dst_stride, \ 2163 BRW_REGISTER_TYPE_##src_type, \ 2164 src_subreg, \ 2165 BRW_VERTICAL_STRIDE_##src_vstride, \ 2166 BRW_WIDTH_##src_width, \ 2167 BRW_HORIZONTAL_STRIDE_##src_hstride, \ 2168 expected_result, \ 2169 } 2170 2171 /* Some instruction that violate no restrictions, as a control */ 2172 INST(MOV, 4, DF, 0, 1, DF, 0, 4, 4, 1, true ), 2173 INST(MOV, 4, Q, 0, 1, Q, 0, 4, 4, 1, true ), 2174 INST(MOV, 4, UQ, 0, 1, UQ, 0, 4, 4, 1, true ), 2175 2176 INST(MOV, 4, DF, 0, 1, F, 0, 8, 4, 2, true ), 2177 INST(MOV, 4, Q, 0, 1, D, 0, 8, 4, 2, true ), 2178 INST(MOV, 4, UQ, 0, 1, UD, 0, 8, 4, 2, true ), 2179 2180 INST(MOV, 4, F, 0, 2, DF, 0, 4, 4, 1, true ), 2181 INST(MOV, 4, D, 0, 2, Q, 0, 4, 4, 1, true ), 2182 INST(MOV, 4, UD, 0, 2, UQ, 0, 4, 4, 1, true ), 2183 2184 INST(MUL, 8, D, 0, 2, D, 0, 8, 4, 2, true ), 2185 INST(MUL, 8, UD, 0, 2, UD, 0, 8, 4, 2, true ), 2186 2187 /* Something with subreg nrs */ 2188 INST(MOV, 2, DF, 8, 1, DF, 8, 2, 2, 1, true ), 2189 INST(MOV, 2, Q, 8, 1, Q, 8, 2, 2, 1, true ), 2190 INST(MOV, 2, UQ, 8, 1, UQ, 8, 2, 2, 1, true ), 2191 2192 INST(MUL, 2, D, 4, 2, D, 4, 4, 2, 2, true ), 2193 INST(MUL, 2, UD, 4, 2, UD, 4, 4, 2, 2, true ), 2194 2195 /* The PRMs say that for CHV, BXT: 2196 * 2197 * When source or destination datatype is 64b or operation is integer 2198 * DWord multiply, regioning in Align1 must follow these rules: 2199 * 2200 * 1. Source and Destination horizontal stride must be aligned to the 2201 * same qword. 2202 */ 2203 INST(MOV, 4, DF, 0, 2, DF, 0, 4, 4, 1, false), 2204 INST(MOV, 4, Q, 0, 2, Q, 0, 4, 4, 1, false), 2205 INST(MOV, 4, UQ, 0, 2, UQ, 0, 4, 4, 1, false), 2206 2207 INST(MOV, 4, DF, 0, 2, F, 0, 8, 4, 2, false), 2208 INST(MOV, 4, Q, 0, 2, D, 0, 8, 4, 2, false), 2209 INST(MOV, 4, UQ, 0, 2, UD, 0, 8, 4, 2, false), 2210 2211 INST(MOV, 4, DF, 0, 2, F, 0, 4, 4, 1, false), 2212 INST(MOV, 4, Q, 0, 2, D, 0, 4, 4, 1, false), 2213 INST(MOV, 4, UQ, 0, 2, UD, 0, 4, 4, 1, false), 2214 2215 INST(MUL, 4, D, 0, 2, D, 0, 4, 4, 1, false), 2216 INST(MUL, 4, UD, 0, 2, UD, 0, 4, 4, 1, false), 2217 2218 INST(MUL, 4, D, 0, 1, D, 0, 8, 4, 2, false), 2219 INST(MUL, 4, UD, 0, 1, UD, 0, 8, 4, 2, false), 2220 2221 /* 2. Regioning must ensure Src.Vstride = Src.Width * Src.Hstride. */ 2222 INST(MOV, 4, DF, 0, 1, DF, 0, 0, 2, 1, false), 2223 INST(MOV, 4, Q, 0, 1, Q, 0, 0, 2, 1, false), 2224 INST(MOV, 4, UQ, 0, 1, UQ, 0, 0, 2, 1, false), 2225 2226 INST(MOV, 4, DF, 0, 1, F, 0, 0, 2, 2, false), 2227 INST(MOV, 4, Q, 0, 1, D, 0, 0, 2, 2, false), 2228 INST(MOV, 4, UQ, 0, 1, UD, 0, 0, 2, 2, false), 2229 2230 INST(MOV, 8, F, 0, 2, DF, 0, 0, 2, 1, false), 2231 INST(MOV, 8, D, 0, 2, Q, 0, 0, 2, 1, false), 2232 INST(MOV, 8, UD, 0, 2, UQ, 0, 0, 2, 1, false), 2233 2234 INST(MUL, 8, D, 0, 2, D, 0, 0, 4, 2, false), 2235 INST(MUL, 8, UD, 0, 2, UD, 0, 0, 4, 2, false), 2236 2237 INST(MUL, 8, D, 0, 2, D, 0, 0, 4, 2, false), 2238 INST(MUL, 8, UD, 0, 2, UD, 0, 0, 4, 2, false), 2239 2240 /* 3. Source and Destination offset must be the same, except the case 2241 * of scalar source. 2242 */ 2243 INST(MOV, 2, DF, 8, 1, DF, 0, 2, 2, 1, false), 2244 INST(MOV, 2, Q, 8, 1, Q, 0, 2, 2, 1, false), 2245 INST(MOV, 2, UQ, 8, 1, UQ, 0, 2, 2, 1, false), 2246 2247 INST(MOV, 2, DF, 0, 1, DF, 8, 2, 2, 1, false), 2248 INST(MOV, 2, Q, 0, 1, Q, 8, 2, 2, 1, false), 2249 INST(MOV, 2, UQ, 0, 1, UQ, 8, 2, 2, 1, false), 2250 2251 INST(MUL, 4, D, 4, 2, D, 0, 4, 2, 2, false), 2252 INST(MUL, 4, UD, 4, 2, UD, 0, 4, 2, 2, false), 2253 2254 INST(MUL, 4, D, 0, 2, D, 4, 4, 2, 2, false), 2255 INST(MUL, 4, UD, 0, 2, UD, 4, 4, 2, 2, false), 2256 2257 INST(MOV, 2, DF, 8, 1, DF, 0, 0, 1, 0, true ), 2258 INST(MOV, 2, Q, 8, 1, Q, 0, 0, 1, 0, true ), 2259 INST(MOV, 2, UQ, 8, 1, UQ, 0, 0, 1, 0, true ), 2260 2261 INST(MOV, 2, DF, 8, 1, F, 4, 0, 1, 0, true ), 2262 INST(MOV, 2, Q, 8, 1, D, 4, 0, 1, 0, true ), 2263 INST(MOV, 2, UQ, 8, 1, UD, 4, 0, 1, 0, true ), 2264 2265 INST(MUL, 4, D, 4, 1, D, 0, 0, 1, 0, true ), 2266 INST(MUL, 4, UD, 4, 1, UD, 0, 0, 1, 0, true ), 2267 2268 INST(MUL, 4, D, 0, 1, D, 4, 0, 1, 0, true ), 2269 INST(MUL, 4, UD, 0, 1, UD, 4, 0, 1, 0, true ), 2270 2271#undef INST 2272 }; 2273 2274 /* These restrictions only apply to Gfx8+ */ 2275 if (devinfo.ver < 8) 2276 return; 2277 2278 /* NoDDChk/NoDDClr does not exist on Gfx12+ */ 2279 if (devinfo.ver >= 12) 2280 return; 2281 2282 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 2283 if (!devinfo.has_64bit_float && 2284 (inst[i].dst_type == BRW_REGISTER_TYPE_DF || 2285 inst[i].src_type == BRW_REGISTER_TYPE_DF)) 2286 continue; 2287 2288 if (!devinfo.has_64bit_int && 2289 (inst[i].dst_type == BRW_REGISTER_TYPE_Q || 2290 inst[i].dst_type == BRW_REGISTER_TYPE_UQ || 2291 inst[i].src_type == BRW_REGISTER_TYPE_Q || 2292 inst[i].src_type == BRW_REGISTER_TYPE_UQ)) 2293 continue; 2294 2295 if (inst[i].opcode == BRW_OPCODE_MOV) { 2296 brw_MOV(p, retype(g0, inst[i].dst_type), 2297 retype(g0, inst[i].src_type)); 2298 } else { 2299 assert(inst[i].opcode == BRW_OPCODE_MUL); 2300 brw_MUL(p, retype(g0, inst[i].dst_type), 2301 retype(g0, inst[i].src_type), 2302 retype(zero, inst[i].src_type)); 2303 } 2304 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size); 2305 2306 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, inst[i].dst_subreg); 2307 brw_inst_set_src0_da1_subreg_nr(&devinfo, last_inst, inst[i].src_subreg); 2308 2309 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride); 2310 2311 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].src_vstride); 2312 brw_inst_set_src0_width(&devinfo, last_inst, inst[i].src_width); 2313 brw_inst_set_src0_hstride(&devinfo, last_inst, inst[i].src_hstride); 2314 2315 if (devinfo.is_cherryview || intel_device_info_is_9lp(&devinfo)) { 2316 EXPECT_EQ(inst[i].expected_result, validate(p)); 2317 } else { 2318 EXPECT_TRUE(validate(p)); 2319 } 2320 2321 clear_instructions(p); 2322 } 2323} 2324 2325TEST_P(validation_test, qword_low_power_no_indirect_addressing) 2326{ 2327 static const struct { 2328 enum opcode opcode; 2329 unsigned exec_size; 2330 2331 enum brw_reg_type dst_type; 2332 bool dst_is_indirect; 2333 unsigned dst_stride; 2334 2335 enum brw_reg_type src_type; 2336 bool src_is_indirect; 2337 unsigned src_vstride; 2338 unsigned src_width; 2339 unsigned src_hstride; 2340 2341 bool expected_result; 2342 } inst[] = { 2343#define INST(opcode, exec_size, dst_type, dst_is_indirect, dst_stride, \ 2344 src_type, src_is_indirect, src_vstride, src_width, src_hstride, \ 2345 expected_result) \ 2346 { \ 2347 BRW_OPCODE_##opcode, \ 2348 BRW_EXECUTE_##exec_size, \ 2349 BRW_REGISTER_TYPE_##dst_type, \ 2350 dst_is_indirect, \ 2351 BRW_HORIZONTAL_STRIDE_##dst_stride, \ 2352 BRW_REGISTER_TYPE_##src_type, \ 2353 src_is_indirect, \ 2354 BRW_VERTICAL_STRIDE_##src_vstride, \ 2355 BRW_WIDTH_##src_width, \ 2356 BRW_HORIZONTAL_STRIDE_##src_hstride, \ 2357 expected_result, \ 2358 } 2359 2360 /* Some instruction that violate no restrictions, as a control */ 2361 INST(MOV, 4, DF, 0, 1, DF, 0, 4, 4, 1, true ), 2362 INST(MOV, 4, Q, 0, 1, Q, 0, 4, 4, 1, true ), 2363 INST(MOV, 4, UQ, 0, 1, UQ, 0, 4, 4, 1, true ), 2364 2365 INST(MUL, 8, D, 0, 2, D, 0, 8, 4, 2, true ), 2366 INST(MUL, 8, UD, 0, 2, UD, 0, 8, 4, 2, true ), 2367 2368 INST(MOV, 4, F, 1, 1, F, 0, 4, 4, 1, true ), 2369 INST(MOV, 4, F, 0, 1, F, 1, 4, 4, 1, true ), 2370 INST(MOV, 4, F, 1, 1, F, 1, 4, 4, 1, true ), 2371 2372 /* The PRMs say that for CHV, BXT: 2373 * 2374 * When source or destination datatype is 64b or operation is integer 2375 * DWord multiply, indirect addressing must not be used. 2376 */ 2377 INST(MOV, 4, DF, 1, 1, DF, 0, 4, 4, 1, false), 2378 INST(MOV, 4, Q, 1, 1, Q, 0, 4, 4, 1, false), 2379 INST(MOV, 4, UQ, 1, 1, UQ, 0, 4, 4, 1, false), 2380 2381 INST(MOV, 4, DF, 0, 1, DF, 1, 4, 4, 1, false), 2382 INST(MOV, 4, Q, 0, 1, Q, 1, 4, 4, 1, false), 2383 INST(MOV, 4, UQ, 0, 1, UQ, 1, 4, 4, 1, false), 2384 2385 INST(MOV, 4, DF, 1, 1, F, 0, 8, 4, 2, false), 2386 INST(MOV, 4, Q, 1, 1, D, 0, 8, 4, 2, false), 2387 INST(MOV, 4, UQ, 1, 1, UD, 0, 8, 4, 2, false), 2388 2389 INST(MOV, 4, DF, 0, 1, F, 1, 8, 4, 2, false), 2390 INST(MOV, 4, Q, 0, 1, D, 1, 8, 4, 2, false), 2391 INST(MOV, 4, UQ, 0, 1, UD, 1, 8, 4, 2, false), 2392 2393 INST(MOV, 4, F, 1, 2, DF, 0, 4, 4, 1, false), 2394 INST(MOV, 4, D, 1, 2, Q, 0, 4, 4, 1, false), 2395 INST(MOV, 4, UD, 1, 2, UQ, 0, 4, 4, 1, false), 2396 2397 INST(MOV, 4, F, 0, 2, DF, 1, 4, 4, 1, false), 2398 INST(MOV, 4, D, 0, 2, Q, 1, 4, 4, 1, false), 2399 INST(MOV, 4, UD, 0, 2, UQ, 1, 4, 4, 1, false), 2400 2401 INST(MUL, 8, D, 1, 2, D, 0, 8, 4, 2, false), 2402 INST(MUL, 8, UD, 1, 2, UD, 0, 8, 4, 2, false), 2403 2404 INST(MUL, 8, D, 0, 2, D, 1, 8, 4, 2, false), 2405 INST(MUL, 8, UD, 0, 2, UD, 1, 8, 4, 2, false), 2406 2407#undef INST 2408 }; 2409 2410 /* These restrictions only apply to Gfx8+ */ 2411 if (devinfo.ver < 8) 2412 return; 2413 2414 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 2415 if (!devinfo.has_64bit_float && 2416 (inst[i].dst_type == BRW_REGISTER_TYPE_DF || 2417 inst[i].src_type == BRW_REGISTER_TYPE_DF)) 2418 continue; 2419 2420 if (!devinfo.has_64bit_int && 2421 (inst[i].dst_type == BRW_REGISTER_TYPE_Q || 2422 inst[i].dst_type == BRW_REGISTER_TYPE_UQ || 2423 inst[i].src_type == BRW_REGISTER_TYPE_Q || 2424 inst[i].src_type == BRW_REGISTER_TYPE_UQ)) 2425 continue; 2426 2427 if (inst[i].opcode == BRW_OPCODE_MOV) { 2428 brw_MOV(p, retype(g0, inst[i].dst_type), 2429 retype(g0, inst[i].src_type)); 2430 } else { 2431 assert(inst[i].opcode == BRW_OPCODE_MUL); 2432 brw_MUL(p, retype(g0, inst[i].dst_type), 2433 retype(g0, inst[i].src_type), 2434 retype(zero, inst[i].src_type)); 2435 } 2436 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size); 2437 2438 brw_inst_set_dst_address_mode(&devinfo, last_inst, inst[i].dst_is_indirect); 2439 brw_inst_set_src0_address_mode(&devinfo, last_inst, inst[i].src_is_indirect); 2440 2441 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride); 2442 2443 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].src_vstride); 2444 brw_inst_set_src0_width(&devinfo, last_inst, inst[i].src_width); 2445 brw_inst_set_src0_hstride(&devinfo, last_inst, inst[i].src_hstride); 2446 2447 if (devinfo.is_cherryview || intel_device_info_is_9lp(&devinfo)) { 2448 EXPECT_EQ(inst[i].expected_result, validate(p)); 2449 } else { 2450 EXPECT_TRUE(validate(p)); 2451 } 2452 2453 clear_instructions(p); 2454 } 2455} 2456 2457TEST_P(validation_test, qword_low_power_no_64bit_arf) 2458{ 2459 static const struct { 2460 enum opcode opcode; 2461 unsigned exec_size; 2462 2463 struct brw_reg dst; 2464 enum brw_reg_type dst_type; 2465 unsigned dst_stride; 2466 2467 struct brw_reg src; 2468 enum brw_reg_type src_type; 2469 unsigned src_vstride; 2470 unsigned src_width; 2471 unsigned src_hstride; 2472 2473 bool acc_wr; 2474 bool expected_result; 2475 } inst[] = { 2476#define INST(opcode, exec_size, dst, dst_type, dst_stride, \ 2477 src, src_type, src_vstride, src_width, src_hstride, \ 2478 acc_wr, expected_result) \ 2479 { \ 2480 BRW_OPCODE_##opcode, \ 2481 BRW_EXECUTE_##exec_size, \ 2482 dst, \ 2483 BRW_REGISTER_TYPE_##dst_type, \ 2484 BRW_HORIZONTAL_STRIDE_##dst_stride, \ 2485 src, \ 2486 BRW_REGISTER_TYPE_##src_type, \ 2487 BRW_VERTICAL_STRIDE_##src_vstride, \ 2488 BRW_WIDTH_##src_width, \ 2489 BRW_HORIZONTAL_STRIDE_##src_hstride, \ 2490 acc_wr, \ 2491 expected_result, \ 2492 } 2493 2494 /* Some instruction that violate no restrictions, as a control */ 2495 INST(MOV, 4, g0, DF, 1, g0, F, 4, 2, 2, 0, true ), 2496 INST(MOV, 4, g0, F, 2, g0, DF, 4, 4, 1, 0, true ), 2497 2498 INST(MOV, 4, g0, Q, 1, g0, D, 4, 2, 2, 0, true ), 2499 INST(MOV, 4, g0, D, 2, g0, Q, 4, 4, 1, 0, true ), 2500 2501 INST(MOV, 4, g0, UQ, 1, g0, UD, 4, 2, 2, 0, true ), 2502 INST(MOV, 4, g0, UD, 2, g0, UQ, 4, 4, 1, 0, true ), 2503 2504 INST(MOV, 4, null, F, 1, g0, F, 4, 4, 1, 0, true ), 2505 INST(MOV, 4, acc0, F, 1, g0, F, 4, 4, 1, 0, true ), 2506 INST(MOV, 4, g0, F, 1, acc0, F, 4, 4, 1, 0, true ), 2507 2508 INST(MOV, 4, null, D, 1, g0, D, 4, 4, 1, 0, true ), 2509 INST(MOV, 4, acc0, D, 1, g0, D, 4, 4, 1, 0, true ), 2510 INST(MOV, 4, g0, D, 1, acc0, D, 4, 4, 1, 0, true ), 2511 2512 INST(MOV, 4, null, UD, 1, g0, UD, 4, 4, 1, 0, true ), 2513 INST(MOV, 4, acc0, UD, 1, g0, UD, 4, 4, 1, 0, true ), 2514 INST(MOV, 4, g0, UD, 1, acc0, UD, 4, 4, 1, 0, true ), 2515 2516 INST(MUL, 4, g0, D, 2, g0, D, 4, 2, 2, 0, true ), 2517 INST(MUL, 4, g0, UD, 2, g0, UD, 4, 2, 2, 0, true ), 2518 2519 /* The PRMs say that for CHV, BXT: 2520 * 2521 * ARF registers must never be used with 64b datatype or when 2522 * operation is integer DWord multiply. 2523 */ 2524 INST(MOV, 4, acc0, DF, 1, g0, F, 4, 2, 2, 0, false), 2525 INST(MOV, 4, g0, DF, 1, acc0, F, 4, 2, 2, 0, false), 2526 2527 INST(MOV, 4, acc0, Q, 1, g0, D, 4, 2, 2, 0, false), 2528 INST(MOV, 4, g0, Q, 1, acc0, D, 4, 2, 2, 0, false), 2529 2530 INST(MOV, 4, acc0, UQ, 1, g0, UD, 4, 2, 2, 0, false), 2531 INST(MOV, 4, g0, UQ, 1, acc0, UD, 4, 2, 2, 0, false), 2532 2533 INST(MOV, 4, acc0, F, 2, g0, DF, 4, 4, 1, 0, false), 2534 INST(MOV, 4, g0, F, 2, acc0, DF, 4, 4, 1, 0, false), 2535 2536 INST(MOV, 4, acc0, D, 2, g0, Q, 4, 4, 1, 0, false), 2537 INST(MOV, 4, g0, D, 2, acc0, Q, 4, 4, 1, 0, false), 2538 2539 INST(MOV, 4, acc0, UD, 2, g0, UQ, 4, 4, 1, 0, false), 2540 INST(MOV, 4, g0, UD, 2, acc0, UQ, 4, 4, 1, 0, false), 2541 2542 INST(MUL, 4, acc0, D, 2, g0, D, 4, 2, 2, 0, false), 2543 INST(MUL, 4, acc0, UD, 2, g0, UD, 4, 2, 2, 0, false), 2544 /* MUL cannot have integer accumulator sources, so don't test that */ 2545 2546 /* We assume that the restriction does not apply to the null register */ 2547 INST(MOV, 4, null, DF, 1, g0, F, 4, 2, 2, 0, true ), 2548 INST(MOV, 4, null, Q, 1, g0, D, 4, 2, 2, 0, true ), 2549 INST(MOV, 4, null, UQ, 1, g0, UD, 4, 2, 2, 0, true ), 2550 2551 /* Check implicit accumulator write control */ 2552 INST(MOV, 4, null, DF, 1, g0, F, 4, 2, 2, 1, false), 2553 INST(MUL, 4, null, DF, 1, g0, F, 4, 2, 2, 1, false), 2554 2555#undef INST 2556 }; 2557 2558 /* These restrictions only apply to Gfx8+ */ 2559 if (devinfo.ver < 8) 2560 return; 2561 2562 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 2563 if (!devinfo.has_64bit_float && 2564 (inst[i].dst_type == BRW_REGISTER_TYPE_DF || 2565 inst[i].src_type == BRW_REGISTER_TYPE_DF)) 2566 continue; 2567 2568 if (!devinfo.has_64bit_int && 2569 (inst[i].dst_type == BRW_REGISTER_TYPE_Q || 2570 inst[i].dst_type == BRW_REGISTER_TYPE_UQ || 2571 inst[i].src_type == BRW_REGISTER_TYPE_Q || 2572 inst[i].src_type == BRW_REGISTER_TYPE_UQ)) 2573 continue; 2574 2575 if (inst[i].opcode == BRW_OPCODE_MOV) { 2576 brw_MOV(p, retype(inst[i].dst, inst[i].dst_type), 2577 retype(inst[i].src, inst[i].src_type)); 2578 } else { 2579 assert(inst[i].opcode == BRW_OPCODE_MUL); 2580 brw_MUL(p, retype(inst[i].dst, inst[i].dst_type), 2581 retype(inst[i].src, inst[i].src_type), 2582 retype(zero, inst[i].src_type)); 2583 brw_inst_set_opcode(&devinfo, last_inst, inst[i].opcode); 2584 } 2585 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size); 2586 brw_inst_set_acc_wr_control(&devinfo, last_inst, inst[i].acc_wr); 2587 2588 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride); 2589 2590 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].src_vstride); 2591 brw_inst_set_src0_width(&devinfo, last_inst, inst[i].src_width); 2592 brw_inst_set_src0_hstride(&devinfo, last_inst, inst[i].src_hstride); 2593 2594 if (devinfo.is_cherryview || intel_device_info_is_9lp(&devinfo)) { 2595 EXPECT_EQ(inst[i].expected_result, validate(p)); 2596 } else { 2597 EXPECT_TRUE(validate(p)); 2598 } 2599 2600 clear_instructions(p); 2601 } 2602 2603 if (!devinfo.has_64bit_float) 2604 return; 2605 2606 /* MAC implicitly reads the accumulator */ 2607 brw_MAC(p, retype(g0, BRW_REGISTER_TYPE_DF), 2608 retype(stride(g0, 4, 4, 1), BRW_REGISTER_TYPE_DF), 2609 retype(stride(g0, 4, 4, 1), BRW_REGISTER_TYPE_DF)); 2610 if (devinfo.is_cherryview || intel_device_info_is_9lp(&devinfo)) { 2611 EXPECT_FALSE(validate(p)); 2612 } else { 2613 EXPECT_TRUE(validate(p)); 2614 } 2615} 2616 2617TEST_P(validation_test, align16_64_bit_integer) 2618{ 2619 static const struct { 2620 enum opcode opcode; 2621 unsigned exec_size; 2622 2623 enum brw_reg_type dst_type; 2624 enum brw_reg_type src_type; 2625 2626 bool expected_result; 2627 } inst[] = { 2628#define INST(opcode, exec_size, dst_type, src_type, expected_result) \ 2629 { \ 2630 BRW_OPCODE_##opcode, \ 2631 BRW_EXECUTE_##exec_size, \ 2632 BRW_REGISTER_TYPE_##dst_type, \ 2633 BRW_REGISTER_TYPE_##src_type, \ 2634 expected_result, \ 2635 } 2636 2637 /* Some instruction that violate no restrictions, as a control */ 2638 INST(MOV, 2, Q, D, true ), 2639 INST(MOV, 2, UQ, UD, true ), 2640 INST(MOV, 2, DF, F, true ), 2641 2642 INST(ADD, 2, Q, D, true ), 2643 INST(ADD, 2, UQ, UD, true ), 2644 INST(ADD, 2, DF, F, true ), 2645 2646 /* The PRMs say that for BDW, SKL: 2647 * 2648 * If Align16 is required for an operation with QW destination and non-QW 2649 * source datatypes, the execution size cannot exceed 2. 2650 */ 2651 2652 INST(MOV, 4, Q, D, false), 2653 INST(MOV, 4, UQ, UD, false), 2654 INST(MOV, 4, DF, F, false), 2655 2656 INST(ADD, 4, Q, D, false), 2657 INST(ADD, 4, UQ, UD, false), 2658 INST(ADD, 4, DF, F, false), 2659 2660#undef INST 2661 }; 2662 2663 /* 64-bit integer types exist on Gfx8+ */ 2664 if (devinfo.ver < 8) 2665 return; 2666 2667 /* Align16 does not exist on Gfx11+ */ 2668 if (devinfo.ver >= 11) 2669 return; 2670 2671 brw_set_default_access_mode(p, BRW_ALIGN_16); 2672 2673 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 2674 if (inst[i].opcode == BRW_OPCODE_MOV) { 2675 brw_MOV(p, retype(g0, inst[i].dst_type), 2676 retype(g0, inst[i].src_type)); 2677 } else { 2678 assert(inst[i].opcode == BRW_OPCODE_ADD); 2679 brw_ADD(p, retype(g0, inst[i].dst_type), 2680 retype(g0, inst[i].src_type), 2681 retype(g0, inst[i].src_type)); 2682 } 2683 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size); 2684 2685 EXPECT_EQ(inst[i].expected_result, validate(p)); 2686 2687 clear_instructions(p); 2688 } 2689} 2690 2691TEST_P(validation_test, qword_low_power_no_depctrl) 2692{ 2693 static const struct { 2694 enum opcode opcode; 2695 unsigned exec_size; 2696 2697 enum brw_reg_type dst_type; 2698 unsigned dst_stride; 2699 2700 enum brw_reg_type src_type; 2701 unsigned src_vstride; 2702 unsigned src_width; 2703 unsigned src_hstride; 2704 2705 bool no_dd_check; 2706 bool no_dd_clear; 2707 2708 bool expected_result; 2709 } inst[] = { 2710#define INST(opcode, exec_size, dst_type, dst_stride, \ 2711 src_type, src_vstride, src_width, src_hstride, \ 2712 no_dd_check, no_dd_clear, expected_result) \ 2713 { \ 2714 BRW_OPCODE_##opcode, \ 2715 BRW_EXECUTE_##exec_size, \ 2716 BRW_REGISTER_TYPE_##dst_type, \ 2717 BRW_HORIZONTAL_STRIDE_##dst_stride, \ 2718 BRW_REGISTER_TYPE_##src_type, \ 2719 BRW_VERTICAL_STRIDE_##src_vstride, \ 2720 BRW_WIDTH_##src_width, \ 2721 BRW_HORIZONTAL_STRIDE_##src_hstride, \ 2722 no_dd_check, \ 2723 no_dd_clear, \ 2724 expected_result, \ 2725 } 2726 2727 /* Some instruction that violate no restrictions, as a control */ 2728 INST(MOV, 4, DF, 1, F, 8, 4, 2, 0, 0, true ), 2729 INST(MOV, 4, Q, 1, D, 8, 4, 2, 0, 0, true ), 2730 INST(MOV, 4, UQ, 1, UD, 8, 4, 2, 0, 0, true ), 2731 2732 INST(MOV, 4, F, 2, DF, 4, 4, 1, 0, 0, true ), 2733 INST(MOV, 4, D, 2, Q, 4, 4, 1, 0, 0, true ), 2734 INST(MOV, 4, UD, 2, UQ, 4, 4, 1, 0, 0, true ), 2735 2736 INST(MUL, 8, D, 2, D, 8, 4, 2, 0, 0, true ), 2737 INST(MUL, 8, UD, 2, UD, 8, 4, 2, 0, 0, true ), 2738 2739 INST(MOV, 4, F, 1, F, 4, 4, 1, 1, 1, true ), 2740 2741 /* The PRMs say that for CHV, BXT: 2742 * 2743 * When source or destination datatype is 64b or operation is integer 2744 * DWord multiply, DepCtrl must not be used. 2745 */ 2746 INST(MOV, 4, DF, 1, F, 8, 4, 2, 1, 0, false), 2747 INST(MOV, 4, Q, 1, D, 8, 4, 2, 1, 0, false), 2748 INST(MOV, 4, UQ, 1, UD, 8, 4, 2, 1, 0, false), 2749 2750 INST(MOV, 4, F, 2, DF, 4, 4, 1, 1, 0, false), 2751 INST(MOV, 4, D, 2, Q, 4, 4, 1, 1, 0, false), 2752 INST(MOV, 4, UD, 2, UQ, 4, 4, 1, 1, 0, false), 2753 2754 INST(MOV, 4, DF, 1, F, 8, 4, 2, 0, 1, false), 2755 INST(MOV, 4, Q, 1, D, 8, 4, 2, 0, 1, false), 2756 INST(MOV, 4, UQ, 1, UD, 8, 4, 2, 0, 1, false), 2757 2758 INST(MOV, 4, F, 2, DF, 4, 4, 1, 0, 1, false), 2759 INST(MOV, 4, D, 2, Q, 4, 4, 1, 0, 1, false), 2760 INST(MOV, 4, UD, 2, UQ, 4, 4, 1, 0, 1, false), 2761 2762 INST(MUL, 8, D, 2, D, 8, 4, 2, 1, 0, false), 2763 INST(MUL, 8, UD, 2, UD, 8, 4, 2, 1, 0, false), 2764 2765 INST(MUL, 8, D, 2, D, 8, 4, 2, 0, 1, false), 2766 INST(MUL, 8, UD, 2, UD, 8, 4, 2, 0, 1, false), 2767 2768#undef INST 2769 }; 2770 2771 /* These restrictions only apply to Gfx8+ */ 2772 if (devinfo.ver < 8) 2773 return; 2774 2775 /* NoDDChk/NoDDClr does not exist on Gfx12+ */ 2776 if (devinfo.ver >= 12) 2777 return; 2778 2779 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 2780 if (!devinfo.has_64bit_float && 2781 (inst[i].dst_type == BRW_REGISTER_TYPE_DF || 2782 inst[i].src_type == BRW_REGISTER_TYPE_DF)) 2783 continue; 2784 2785 if (!devinfo.has_64bit_int && 2786 (inst[i].dst_type == BRW_REGISTER_TYPE_Q || 2787 inst[i].dst_type == BRW_REGISTER_TYPE_UQ || 2788 inst[i].src_type == BRW_REGISTER_TYPE_Q || 2789 inst[i].src_type == BRW_REGISTER_TYPE_UQ)) 2790 continue; 2791 2792 if (inst[i].opcode == BRW_OPCODE_MOV) { 2793 brw_MOV(p, retype(g0, inst[i].dst_type), 2794 retype(g0, inst[i].src_type)); 2795 } else { 2796 assert(inst[i].opcode == BRW_OPCODE_MUL); 2797 brw_MUL(p, retype(g0, inst[i].dst_type), 2798 retype(g0, inst[i].src_type), 2799 retype(zero, inst[i].src_type)); 2800 } 2801 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size); 2802 2803 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride); 2804 2805 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].src_vstride); 2806 brw_inst_set_src0_width(&devinfo, last_inst, inst[i].src_width); 2807 brw_inst_set_src0_hstride(&devinfo, last_inst, inst[i].src_hstride); 2808 2809 brw_inst_set_no_dd_check(&devinfo, last_inst, inst[i].no_dd_check); 2810 brw_inst_set_no_dd_clear(&devinfo, last_inst, inst[i].no_dd_clear); 2811 2812 if (devinfo.is_cherryview || intel_device_info_is_9lp(&devinfo)) { 2813 EXPECT_EQ(inst[i].expected_result, validate(p)); 2814 } else { 2815 EXPECT_TRUE(validate(p)); 2816 } 2817 2818 clear_instructions(p); 2819 } 2820} 2821 2822TEST_P(validation_test, gfx11_no_byte_src_1_2) 2823{ 2824 static const struct { 2825 enum opcode opcode; 2826 unsigned access_mode; 2827 2828 enum brw_reg_type dst_type; 2829 struct { 2830 enum brw_reg_type type; 2831 unsigned vstride; 2832 unsigned width; 2833 unsigned hstride; 2834 } srcs[3]; 2835 2836 int gfx_ver; 2837 bool expected_result; 2838 } inst[] = { 2839#define INST(opcode, access_mode, dst_type, \ 2840 src0_type, src0_vstride, src0_width, src0_hstride, \ 2841 src1_type, src1_vstride, src1_width, src1_hstride, \ 2842 src2_type, \ 2843 gfx_ver, expected_result) \ 2844 { \ 2845 BRW_OPCODE_##opcode, \ 2846 BRW_ALIGN_##access_mode, \ 2847 BRW_REGISTER_TYPE_##dst_type, \ 2848 { \ 2849 { \ 2850 BRW_REGISTER_TYPE_##src0_type, \ 2851 BRW_VERTICAL_STRIDE_##src0_vstride, \ 2852 BRW_WIDTH_##src0_width, \ 2853 BRW_HORIZONTAL_STRIDE_##src0_hstride, \ 2854 }, \ 2855 { \ 2856 BRW_REGISTER_TYPE_##src1_type, \ 2857 BRW_VERTICAL_STRIDE_##src1_vstride, \ 2858 BRW_WIDTH_##src1_width, \ 2859 BRW_HORIZONTAL_STRIDE_##src1_hstride, \ 2860 }, \ 2861 { \ 2862 BRW_REGISTER_TYPE_##src2_type, \ 2863 }, \ 2864 }, \ 2865 gfx_ver, \ 2866 expected_result, \ 2867 } 2868 2869 /* Passes on < 11 */ 2870 INST(MOV, 16, F, B, 2, 4, 0, UD, 0, 4, 0, D, 8, true ), 2871 INST(ADD, 16, UD, F, 0, 4, 0, UB, 0, 1, 0, D, 7, true ), 2872 INST(MAD, 16, D, B, 0, 4, 0, UB, 0, 1, 0, B, 10, true ), 2873 2874 /* Fails on 11+ */ 2875 INST(MAD, 1, UB, W, 1, 1, 0, D, 0, 4, 0, B, 11, false ), 2876 INST(MAD, 1, UB, W, 1, 1, 1, UB, 1, 1, 0, W, 11, false ), 2877 INST(ADD, 1, W, W, 1, 4, 1, B, 1, 1, 0, D, 11, false ), 2878 2879 /* Passes on 11+ */ 2880 INST(MOV, 1, W, B, 8, 8, 1, D, 8, 8, 1, D, 11, true ), 2881 INST(ADD, 1, UD, B, 8, 8, 1, W, 8, 8, 1, D, 11, true ), 2882 INST(MAD, 1, B, B, 0, 1, 0, D, 0, 4, 0, W, 11, true ), 2883 2884#undef INST 2885 }; 2886 2887 2888 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) { 2889 /* Skip instruction not meant for this gfx_ver. */ 2890 if (devinfo.ver != inst[i].gfx_ver) 2891 continue; 2892 2893 brw_push_insn_state(p); 2894 2895 brw_set_default_exec_size(p, BRW_EXECUTE_8); 2896 brw_set_default_access_mode(p, inst[i].access_mode); 2897 2898 switch (inst[i].opcode) { 2899 case BRW_OPCODE_MOV: 2900 brw_MOV(p, retype(g0, inst[i].dst_type), 2901 retype(g0, inst[i].srcs[0].type)); 2902 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].srcs[0].vstride); 2903 brw_inst_set_src0_hstride(&devinfo, last_inst, inst[i].srcs[0].hstride); 2904 break; 2905 case BRW_OPCODE_ADD: 2906 brw_ADD(p, retype(g0, inst[i].dst_type), 2907 retype(g0, inst[i].srcs[0].type), 2908 retype(g0, inst[i].srcs[1].type)); 2909 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].srcs[0].vstride); 2910 brw_inst_set_src0_width(&devinfo, last_inst, inst[i].srcs[0].width); 2911 brw_inst_set_src0_hstride(&devinfo, last_inst, inst[i].srcs[0].hstride); 2912 brw_inst_set_src1_vstride(&devinfo, last_inst, inst[i].srcs[1].vstride); 2913 brw_inst_set_src1_width(&devinfo, last_inst, inst[i].srcs[1].width); 2914 brw_inst_set_src1_hstride(&devinfo, last_inst, inst[i].srcs[1].hstride); 2915 break; 2916 case BRW_OPCODE_MAD: 2917 brw_MAD(p, retype(g0, inst[i].dst_type), 2918 retype(g0, inst[i].srcs[0].type), 2919 retype(g0, inst[i].srcs[1].type), 2920 retype(g0, inst[i].srcs[2].type)); 2921 brw_inst_set_3src_a1_src0_vstride(&devinfo, last_inst, inst[i].srcs[0].vstride); 2922 brw_inst_set_3src_a1_src0_hstride(&devinfo, last_inst, inst[i].srcs[0].hstride); 2923 brw_inst_set_3src_a1_src1_vstride(&devinfo, last_inst, inst[i].srcs[0].vstride); 2924 brw_inst_set_3src_a1_src1_hstride(&devinfo, last_inst, inst[i].srcs[0].hstride); 2925 break; 2926 default: 2927 unreachable("invalid opcode"); 2928 } 2929 2930 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1); 2931 2932 brw_inst_set_src0_width(&devinfo, last_inst, inst[i].srcs[0].width); 2933 brw_inst_set_src1_width(&devinfo, last_inst, inst[i].srcs[1].width); 2934 2935 brw_pop_insn_state(p); 2936 2937 EXPECT_EQ(inst[i].expected_result, validate(p)); 2938 2939 clear_instructions(p); 2940 } 2941} 2942