}
END_TEST
+static void vop3p_constant(unsigned *idx, aco_opcode op, const char *swizzle, uint32_t val)
+{
+ uint32_t halves[2] = {val & 0xffff, val >> 16};
+ uint32_t expected = halves[swizzle[0] - 'x'] | (halves[swizzle[1] - 'x'] << 16);
+ fprintf(output, "Expected for %u: 0x%.8x / %u\n", *idx, expected, expected);
+
+ unsigned opsel_lo = swizzle[0] == 'x' ? 0x0 : 0x1;
+ unsigned opsel_hi = swizzle[1] == 'x' ? 0x2 : 0x3;
+ writeout((*idx)++, bld.vop3p(op, bld.def(v1), bld.copy(bld.def(v1), Operand::c32(val)),
+ inputs[0], opsel_lo, opsel_hi));
+}
+
+BEGIN_TEST(optimize.vop3p_constants)
+ for (aco_opcode op : {aco_opcode::v_pk_add_f16, aco_opcode::v_pk_add_u16}) {
+ for (const char *swizzle : {"xx", "yy", "xy", "yx"}) {
+ char variant[16];
+ strcpy(variant, op == aco_opcode::v_pk_add_f16 ? "_f16" : "_u16");
+ strcat(variant, "_");
+ strcat(variant, swizzle);
+
+ //; for i in range(36):
+ //; insert_pattern('Expected for %u: $_ / #expected%u' % (i, i))
+
+ //>> v1: %a = p_startpgm
+ if (!setup_cs("v1", GFX10_3, CHIP_UNKNOWN, variant))
+ continue;
+
+ //; opcode = 'v_pk_add_u16' if 'u16' in variant else 'v_pk_add_f16'
+ //; for i in range(36):
+ //; insert_pattern('v1: %%res%u = %s $got%u %%a' % (i, opcode, i))
+ //; insert_pattern('p_unit_test %u, %%res%u' % (i, i))
+ //! s_endpgm
+
+ //; def parse_op(op):
+ //; is_int = opcode == 'v_pk_add_u16'
+ //; op = op.rstrip(',')
+ //;
+ //; mods = lambda v: v
+ //; if op.endswith('*[1,-1]'):
+ //; mods = lambda v: v ^ 0x80000000
+ //; assert(not is_int)
+ //; elif op.endswith('*[-1,1]'):
+ //; mods = lambda v: v ^ 0x00008000
+ //; assert(not is_int)
+ //; op = op.split('*')[0]
+ //;
+ //; swizzle = lambda v: v
+ //; if op.endswith('.xx'):
+ //; swizzle = lambda v: ((v & 0xffff) | (v << 16)) & 0xffffffff;
+ //; elif op.endswith('.yy'):
+ //; swizzle = lambda v: (v >> 16) | (v & 0xffff0000);
+ //; elif op.endswith('.yx'):
+ //; swizzle = lambda v: ((v >> 16) | (v << 16)) & 0xffffffff;
+ //; op = op.rstrip('xy.')
+ //;
+ //; val = None
+ //; if op.startswith('0x'):
+ //; val = int(op[2:], 16)
+ //; elif op == '-1.0':
+ //; val = 0xbf800000 if is_int else 0xbC00
+ //; elif op == '1.0':
+ //; val = 0x3f800000 if is_int else 0x3c00
+ //; else:
+ //; val = int(op) & 0xffffffff
+ //;
+ //; return mods(swizzle(val))
+
+ //; # Check correctness
+ //; for i in range(36):
+ //; expected = globals()['expected%u' % i]
+ //; got = globals()['got%u' % i]
+ //; got_parsed = parse_op(got)
+ //; if got_parsed != expected:
+ //; raise Exception('Check %u failed: expected 0x%.8x, got 0x%.8x ("%s")' % (i, expected, got_parsed, got))
+
+ //; # Check that all literals are ones that cannot be encoded as inline constants
+ //; allowed_literals = [0x00004242, 0x0000fffe, 0x00308030, 0x0030ffff, 0x3c00ffff,
+ //; 0x42420000, 0x42424242, 0x4242c242, 0x4242ffff, 0x7ffefffe,
+ //; 0x80300030, 0xbeefdead, 0xc2424242, 0xdeadbeef, 0xfffe0000,
+ //; 0xfffe7ffe, 0xffff0030, 0xffff3c00, 0xffff4242]
+ //; if opcode == 'v_pk_add_u16':
+ //; allowed_literals.extend([0x00003c00, 0x3c000000, 0x3c003c00, 0x3c00bc00, 0xbc003c00])
+ //; else:
+ //; allowed_literals.extend([0x00003f80, 0x3f800000])
+ //;
+ //; for i in range(36):
+ //; got = globals()['got%u' % i]
+ //; if not got.startswith('0x'):
+ //; continue;
+ //; got = int(got[2:].rstrip(',').split('*')[0].split('.')[0], 16)
+ //; if got not in allowed_literals:
+ //; raise Exception('Literal check %u failed: 0x%.8x not in allowed literals' % (i, got))
+
+ unsigned idx = 0;
+ for (uint32_t constant : {0x3C00, 0x0030, 0xfffe, 0x4242}) {
+ vop3p_constant(&idx, op, swizzle, constant);
+ vop3p_constant(&idx, op, swizzle, constant | 0xffff0000);
+ vop3p_constant(&idx, op, swizzle, constant | (constant << 16));
+ vop3p_constant(&idx, op, swizzle, constant << 16);
+ vop3p_constant(&idx, op, swizzle, (constant << 16) | 0x0000ffff);
+ vop3p_constant(&idx, op, swizzle, constant | ((constant ^ 0x8000) << 16));
+ vop3p_constant(&idx, op, swizzle, (constant ^ 0x8000) | (constant << 16));
+ }
+
+ for (uint32_t constant : {0x3f800000u, 0xfffffffeu, 0x00000030u, 0xdeadbeefu}) {
+ uint32_t lo = constant & 0xffff;
+ uint32_t hi = constant >> 16;
+ vop3p_constant(&idx, op, swizzle, constant);
+ vop3p_constant(&idx, op, swizzle, hi | (lo << 16));
+ }
+
+ finish_opt_test();
+ }
+ }
+END_TEST