Make a re-useable template for generating ASM index functions with different tests

This commit is contained in:
Kovid Goyal
2024-01-31 19:59:09 +05:30
parent fa9a2b1e2e
commit 82b7b4fcce

View File

@@ -1079,46 +1079,20 @@ func (isa *ISA) LEA() string {
return "LEAQ" return "LEAQ"
} }
func (s *State) indexbyte2() { func (s *State) index_func(f *Function, test_bytes_impl func(pos, test_ans Register, aligned bool, byte_found_label string)) {
f := s.NewFunction("index_byte2_asm", "Find the index of either of two bytes", []FunctionParam{{"data", ByteSlice}, {"b1", types.Byte}, {"b2", types.Byte}}, []FunctionParam{{"ans", types.Int}})
if s.ISA.HasSIMD {
s.indexbyte2_body(f)
}
f = s.NewFunction("index_byte2_string_asm", "Find the index of either of two bytes", []FunctionParam{{"data", types.String}, {"b1", types.Byte}, {"b2", types.Byte}}, []FunctionParam{{"ans", types.Int}})
if s.ISA.HasSIMD {
s.indexbyte2_body(f)
}
}
func (s *State) indexbyte2_body(f *Function) {
b1 := f.Vec()
b2 := f.Vec()
test_ans := f.Vec()
f.Set1Epi8FromParam("b1", b1)
f.Set1Epi8FromParam("b2", b2)
pos := f.Reg() pos := f.Reg()
test_ans := f.Vec()
data_start := f.LoadParam(`data`) data_start := f.LoadParam(`data`)
limit := f.LoadParamLen(`data`) limit := f.LoadParamLen(`data`)
f.AddToSelf(limit, data_start) f.AddToSelf(limit, data_start)
test_bytes := func(aligned bool) {
bytes_to_test := f.Vec()
defer f.ReleaseReg(bytes_to_test)
if aligned {
f.LoadPointerAligned(pos, bytes_to_test)
} else {
f.LoadPointerUnaligned(pos, bytes_to_test)
}
f.CmpEqEpi8(bytes_to_test, b1, test_ans)
f.CmpEqEpi8(bytes_to_test, b2, bytes_to_test)
f.Or(test_ans, bytes_to_test, test_ans)
f.JumpIfNonZero(test_ans, "byte_found")
}
vecsz := f.ISA.Bits / 8 vecsz := f.ISA.Bits / 8
f.CopyRegister(data_start, pos) f.CopyRegister(data_start, pos)
test_bytes := func(aligned bool) {
test_bytes_impl(pos, test_ans, aligned, "byte_found")
}
f.Comment("Load next vector of possibly unaligned bytes and check if either of the bytes are present in it") f.Comment("Load next vector of possibly unaligned bytes and check if either of the bytes are present in it")
test_bytes(false) test_bytes(false)
@@ -1164,6 +1138,39 @@ func (s *State) indexbyte2_body(f *Function) {
} }
func (s *State) indexbyte2_body(f *Function) {
b1 := f.Vec()
b2 := f.Vec()
f.Set1Epi8FromParam("b1", b1)
f.Set1Epi8FromParam("b2", b2)
test_bytes := func(pos, test_ans Register, aligned bool, byte_found_label string) {
bytes_to_test := f.Vec()
defer f.ReleaseReg(bytes_to_test)
if aligned {
f.LoadPointerAligned(pos, bytes_to_test)
} else {
f.LoadPointerUnaligned(pos, bytes_to_test)
}
f.CmpEqEpi8(bytes_to_test, b1, test_ans)
f.CmpEqEpi8(bytes_to_test, b2, bytes_to_test)
f.Or(test_ans, bytes_to_test, test_ans)
f.JumpIfNonZero(test_ans, byte_found_label)
}
s.index_func(f, test_bytes)
}
func (s *State) indexbyte2() {
f := s.NewFunction("index_byte2_asm", "Find the index of either of two bytes", []FunctionParam{{"data", ByteSlice}, {"b1", types.Byte}, {"b2", types.Byte}}, []FunctionParam{{"ans", types.Int}})
if s.ISA.HasSIMD {
s.indexbyte2_body(f)
}
f = s.NewFunction("index_byte2_string_asm", "Find the index of either of two bytes", []FunctionParam{{"data", types.String}, {"b1", types.Byte}, {"b2", types.Byte}}, []FunctionParam{{"ans", types.Int}})
if s.ISA.HasSIMD {
s.indexbyte2_body(f)
}
}
func (s *State) Generate() { func (s *State) Generate() {
s.test_load() s.test_load()
s.test_set1_epi8() s.test_set1_epi8()