golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
122.91k stars 17.52k forks source link

cmd/asm: refactor the framework of the arm64 assembler #44734

Open erifan opened 3 years ago

erifan commented 3 years ago

I propose to refactor the framework of the arm64 assembler.

Why ? 1, The current framework is a bit complicated, not easy to understand, maintain and extend. Especially the handling of constants and the design of optab. 2, Adding a new arm64 instruction is taking more and more effort. For some complex instructions with many formats, a lot of modifications are needed. For example, https://go-review.googlesource.com/c/go/+/273668, https://go-review.googlesource.com/c/go/+/233277, etc. 3, At the moment, we are still missing ~1000 assembly instructions, including NEON and SVE. The potential cost for adding those instructions are high.

People is paying more and more attention to arm64 platform, and there are more and more requests to add new instructions, see https://github.com/golang/go/issues/40725, https://github.com/golang/go/issues/42326, https://github.com/golang/go/issues/41092 etc. Arm64 also has many new features, such as SVE. We hope to construct a better framework to solve the above problems and make future work easier.

Goals for the changes 1, More readable and easy to maintain. 2, Easy to add new instructions. 3, Friendly to testing, Can be cross checked with GNU tools. 4, Share instruction definition with disassembly to avoid mismatch between assembler and disassembler.

How to refactor ? First let's take a look of the current framework. image

We mainly focus on the span7function which encodes a function's Prog list. The main idea of this function is that for a specific Prog, first find its corresponding item in optab (by oplookfunction), and then encode it according to optab._type (in asmout function). In oplook, we need to handle the matching relationship between a Progand an optabitem, which is quite complex especially those constant types and constant offset types. In optab, each format of an instruction has an entry. In theory, we need to write an encoding function for each entry, fortunately we can reuse some similar cases. However sometimes we don't know whether there is a similar implementation, and as instructions increase, the code becomes more and more complex and difficult to maintain.

We propose to change this logic to: separate the preprocessing and encoding of a Prog. The specific method is to first unfold the Prog into a Progcorresponding to only one machine instruction (by hardcode), and then encode it according to the known bits and argument types. Namely: encoding_of_P = Known_bits | arg1 | arg2 | ... | argn

The control flow of span7 becomes: image

We basically have a complete argument type description list and arm64 instruction table, see argument types and instruction table When we know the known bits and parameter types of an instruction, it is easy to encode it.

With this change, we don't need to handle the matching relationship between the Progand the item of optabany more, and we won't encode a specific instruction but the instruction argument type. The number of the instruction argument type is much less than the instruction number, so theoretically the reusability will increase and complexity will decrease. In the future to add new instructions we only need to do this: 1, Set an index to the goal instruction in the arm64 instruction table. 2, Unfold a Progto one or multiple arm64 instructions. 3, Encode the parameters of the arm64 instruction if they have not been implemented.

I have a prototype patch for this proposal, including the complete framework and support for a few instructions such as ADD, SUB, MOV, LDR and STR. See https://go-review.googlesource.com/c/go/+/297776. The patch is incomplete, more work is required to make it work. If the proposal is accepted, we are committed to taking charge of the work.

TODO list: 1, Enable more instructions. 2, Add more tests. 3, Fix the assembly printing issue. 4, Cross check with GNU tools.

CC @cherrymui @randall77 @ianlancetaylor

erifan commented 1 year ago

Specifically I'll need operand actions (read, write, ...) so that I can do liveness analysis and register allocation.

I'm sorry that the arm instruction document does not mark whether an operand is a read or write operation.

If you only need to distinguish whether an operand is a read or write operation, and you don't care about how to read and write, then I think it's doable. Because usually the source operand is read and the destination operand is write. Take the most common three-operand arm instruction as an example, the first operand is the destination operand, and the last two are source operands. And there are some special cases, such as STR, CAS, we need to do some special handling.

If you also need to know how the operand is read and written, then this needs to be combined with encoding and decoding of operand rules.

erifan commented 1 year ago

@mmcloughlin I have uploaded the xml parser

gopherbot commented 1 year ago

Change https://go.dev/cl/506118 mentions this issue: cmd/asm: a new design for register encoding format on arm64

gopherbot commented 1 year ago

Change https://go.dev/cl/518117 mentions this issue: cmd/asm: allows shrinking of error messages reported in the assembler

gopherbot commented 1 year ago

Change https://go.dev/cl/424138 mentions this issue: cmd/asm: migrate some instruction implementations from optab to the new path

gopherbot commented 1 year ago

Change https://go.dev/cl/518118 mentions this issue: cmd/asm: encodes elements of general instructions on arm64

gopherbot commented 1 year ago

Change https://go.dev/cl/527256 mentions this issue: cmd/asm: add encoding of all SIMD&FP elements to new encoding path on arm64

gopherbot commented 1 year ago

Change https://go.dev/cl/527257 mentions this issue: cmd/asm: move support for arm64 SIMD&FP instructions from optab to the new encoding path

gopherbot commented 10 months ago

Change https://go.dev/cl/538136 mentions this issue: arm64: add arm64 XML ISA manual parser

gopherbot commented 10 months ago

Change https://go.dev/cl/538456 mentions this issue: cmd/internal/obj/arm64: refactor disassembler based on new instruction table

mmcloughlin commented 8 months ago

The last Go compiler and runtime meeting notes https://github.com/golang/go/issues/43930#issuecomment-1874498879 said:

rumor has it that ARM just laid off their whole Go team in China

I hope you're not affected @erifan?

erifan commented 8 months ago

The last Go compiler and runtime meeting notes https://github.com/golang/go/issues/43930#issuecomment-1874498879 said:

rumor has it that ARM just laid off their whole Go team in China

I hope you're not affected @erifan?

@mmcloughlin

Thank you for your greetings. Unfortunately, I was also affected. I don't know how to deal with this work now. If you care about the new assembler, maybe you can ask Arm. They may build a new Go team, may not, I don't know. Personally, I really want to finish this, but I'm not sure if I still have time and opportunity to do it. Sorry for this bad situation.

mmcloughlin commented 8 months ago

@erifan That's awful news, I'm so sorry. Thank you for all your work on this so far.

@cherrymui What's the plan for this work going forward? Sorry I haven't been keeping up with the details of the CLs, but it seemed like it might be close? Is it possible to get this over the finish line from here? Or is there another contact at ARM we can ask for support?

cherrymui commented 8 months ago

Thanks very much for your contribution, @erifan and others on ARM who have contributed!

@mmcloughlin I think @erifan 's CLs are in a good shape, and we can proceed along that direction. Unfortunately I'm a bit occupied and I won't be able to work on the CLs myself in the near future. If someone is interested, feel free to take a look at the CLs and go from there. Thanks.

mmcloughlin commented 8 months ago

@mmcloughlin I think @erifan 's CLs are in a good shape, and we can proceed along that direction. Unfortunately I'm a bit occupied and I won't be able to work on the CLs myself in the near future. If someone is interested, feel free to take a look at the CLs and go from there. Thanks.

Got it, thanks for the update. I'd be interested in doing the work but I suspect I won't have the time to devote to it any time soon.

I've emailed some contacts at ARM as recommended by @erifan and CC'd you. It would be great if they are able to sponsor the completion of the work. However I'm just a random Go developer, I think the request would have more weight if it came directly from the Go team. Would it be worth asking Russ Cox to reach out to them about this?

lizthegrey commented 8 months ago

@honeycombio as a reference arm customer is also very interested in this work as it blocks us using the latest vector processing instructions in our hot path. We'll be reaching out to our marketing/partnership contacts.

cherrymui commented 8 months ago

@lizthegrey What specific instructions do you need in the short term? Are they SVE instructions, or the "old" "advanced SIMD" instructions? For the latter, we support a number of such instructions. So if you name the missing instructions we might be able to add them in short term without finishing the refactoring. (Another possibility is to write WORD directives with binary encodings of the instructions. This is not pretty, but get the job done if you only need very few instructions.)

Thanks.

lizthegrey commented 8 months ago

@lizthegrey What specific instructions do you need in the short term? Are they SVE instructions, or the "old" "advanced SIMD" instructions? For the latter, we support a number of such instructions. So if you name the missing instructions we might be able to add them in short term without finishing the refactoring. (Another possibility is to write WORD directives with binary encodings of the instructions. This is not pretty, but get the job done if you only need very few instructions.)

We need two things to happen: (1) we need to have SVE1/2 support added (for Graviton 3/4 respectively), and then (2) we need Avo to support arm64. So it's a two step process with a longer time horizon, and Graviton4 isn't even GA yet. Don't worry about doing a short-term hack.

gopherbot commented 3 months ago

Change https://go.dev/cl/587315 mentions this issue: cmd/internal/obj/arm64: Enable arm64 assembler tests for cross-compiler

gopherbot commented 2 months ago

Change https://go.dev/cl/595755 mentions this issue: cmd/internal/obj/arm64: Add helpers for span7 passes

gopherbot commented 1 month ago

Change https://go.dev/cl/602355 mentions this issue: cmd/internal/obj/arm64: Support ARM64 Z and P type SVE registers

gopherbot commented 1 month ago

Change https://go.dev/cl/606195 mentions this issue: cmd/internal/obj/arm64: Implement ARM64 SVE assembler