diff --git a/src/alloy/backend/x64/x64_sequences.cc b/src/alloy/backend/x64/x64_sequences.cc index a3b207425..8a1467a43 100644 --- a/src/alloy/backend/x64/x64_sequences.cc +++ b/src/alloy/backend/x64/x64_sequences.cc @@ -4782,16 +4782,22 @@ EMITTER_OPCODE_TABLE( // ============================================================================ // OPCODE_INSERT // ============================================================================ -EMITTER(INSERT_I8, MATCH(I, V128<>, I64<>, I8<>>)) { +EMITTER(INSERT_I8, MATCH(I, V128<>, I8<>, I8<>>)) { static void Emit(X64Emitter& e, const EmitArgType& i) { + assert_true(i.src2.is_constant); + e.vpinsrb(i.dest, i.src3.reg().cvt32(), i.src2.constant() ^ 0x3); } }; -EMITTER(INSERT_I16, MATCH(I, V128<>, I64<>, I16<>>)) { +EMITTER(INSERT_I16, MATCH(I, V128<>, I8<>, I16<>>)) { static void Emit(X64Emitter& e, const EmitArgType& i) { + assert_true(i.src2.is_constant); + e.vpinsrw(i.dest, i.src3.reg().cvt32(), i.src2.constant() ^ 0x1); } }; -EMITTER(INSERT_I32, MATCH(I, V128<>, I64<>, I32<>>)) { +EMITTER(INSERT_I32, MATCH(I, V128<>, I8<>, I32<>>)) { static void Emit(X64Emitter& e, const EmitArgType& i) { + assert_true(i.src2.is_constant); + e.vpinsrd(i.dest, i.src3, i.src2.constant()); } }; EMITTER_OPCODE_TABLE( diff --git a/src/alloy/hir/hir_builder.cc b/src/alloy/hir/hir_builder.cc index f1d3f7883..62dbe16cf 100644 --- a/src/alloy/hir/hir_builder.cc +++ b/src/alloy/hir/hir_builder.cc @@ -1809,9 +1809,12 @@ Value* HIRBuilder::CountLeadingZeros(Value* value) { Value* HIRBuilder::Insert(Value* value, Value* index, Value* part) { // TODO(benvanik): could do some of this as constants. + Value* trunc_index = + index->type != INT8_TYPE ? Truncate(index, INT8_TYPE) : index; + Instr* i = AppendInstr(OPCODE_INSERT_info, 0, AllocValue(value->type)); i->set_src1(value); - i->set_src2(ZeroExtend(index, INT64_TYPE)); + i->set_src2(trunc_index); i->set_src3(part); return i->dest; } diff --git a/src/alloy/test/test_insert.cc b/src/alloy/test/test_insert.cc index a23d07896..5bd9a756b 100644 --- a/src/alloy/test/test_insert.cc +++ b/src/alloy/test/test_insert.cc @@ -18,66 +18,69 @@ using namespace alloy::test; using alloy::frontend::ppc::PPCContext; TEST_CASE("INSERT_INT8", "[instr]") { - TestFunction test([](hir::HIRBuilder& b) { - StoreVR(b, 3, b.Insert(LoadVR(b, 4), LoadGPR(b, 4), - b.Truncate(LoadGPR(b, 5), INT8_TYPE))); - b.Return(); - }); for (int i = 0; i < 16; ++i) { - test.Run([i](PPCContext* ctx) { - ctx->v[4] = vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15); - ctx->r[4] = i; - ctx->r[5] = 100 + i; - }, - [i](PPCContext* ctx) { - auto result = ctx->v[3]; - auto expected = vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15); - expected.i8[i ^ 0x3] = 100 + i; - REQUIRE(result == expected); - }); + TestFunction test([i](hir::HIRBuilder& b) { + StoreVR(b, 3, b.Insert(LoadVR(b, 4), b.LoadConstant(i), + b.Truncate(LoadGPR(b, 5), INT8_TYPE))); + b.Return(); + }); + test.Run( + [i](PPCContext* ctx) { + ctx->v[4] = + vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + ctx->r[4] = i; + ctx->r[5] = 100 + i; + }, + [i](PPCContext* ctx) { + auto result = ctx->v[3]; + auto expected = + vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + expected.i8[i ^ 0x3] = 100 + i; + REQUIRE(result == expected); + }); } } TEST_CASE("INSERT_INT16", "[instr]") { - TestFunction test([](hir::HIRBuilder& b) { - StoreVR(b, 3, b.Insert(LoadVR(b, 4), LoadGPR(b, 4), - b.Truncate(LoadGPR(b, 5), INT16_TYPE))); - b.Return(); - }); for (int i = 0; i < 8; ++i) { - test.Run([i](PPCContext* ctx) { - ctx->v[4] = vec128s(0, 1, 2, 3, 4, 5, 6, 7); - ctx->r[4] = i; - ctx->r[5] = 100 + i; - }, - [i](PPCContext* ctx) { - auto result = ctx->v[3]; - auto expected = vec128s(0, 1, 2, 3, 4, 5, 6, 7); - expected.i16[i ^ 0x1] = 100 + i; - REQUIRE(result == expected); - }); + TestFunction test([i](hir::HIRBuilder& b) { + StoreVR(b, 3, b.Insert(LoadVR(b, 4), b.LoadConstant(i), + b.Truncate(LoadGPR(b, 5), INT16_TYPE))); + b.Return(); + }); + test.Run( + [i](PPCContext* ctx) { + ctx->v[4] = vec128s(0, 1, 2, 3, 4, 5, 6, 7); + ctx->r[4] = i; + ctx->r[5] = 100 + i; + }, + [i](PPCContext* ctx) { + auto result = ctx->v[3]; + auto expected = vec128s(0, 1, 2, 3, 4, 5, 6, 7); + expected.i16[i ^ 0x1] = 100 + i; + REQUIRE(result == expected); + }); } } TEST_CASE("INSERT_INT32", "[instr]") { - TestFunction test([](hir::HIRBuilder& b) { - StoreVR(b, 3, b.Insert(LoadVR(b, 4), LoadGPR(b, 4), - b.Truncate(LoadGPR(b, 5), INT32_TYPE))); - b.Return(); - }); for (int i = 0; i < 4; ++i) { - test.Run([i](PPCContext* ctx) { - ctx->v[4] = vec128i(0, 1, 2, 3); - ctx->r[4] = i; - ctx->r[5] = 100 + i; - }, - [i](PPCContext* ctx) { - auto result = ctx->v[3]; - auto expected = vec128i(0, 1, 2, 3); - expected.i32[i] = 100 + i; - REQUIRE(result == expected); - }); + TestFunction test([i](hir::HIRBuilder& b) { + StoreVR(b, 3, b.Insert(LoadVR(b, 4), b.LoadConstant(i), + b.Truncate(LoadGPR(b, 5), INT32_TYPE))); + b.Return(); + }); + test.Run( + [i](PPCContext* ctx) { + ctx->v[4] = vec128i(0, 1, 2, 3); + ctx->r[4] = i; + ctx->r[5] = 100 + i; + }, + [i](PPCContext* ctx) { + auto result = ctx->v[3]; + auto expected = vec128i(0, 1, 2, 3); + expected.i32[i] = 100 + i; + REQUIRE(result == expected); + }); } }