6 ms·
Sounds like there should be an option when you write assembly code to tell the compiler "please save/restore any register that I'm modifying in this asm code ac
by 323 4y ago
Sounds like there should be an option when you write assembly code to tell the compiler "please save/restore any register that I'm modifying in this asm code according to the target you are compiling for"
- pjc50 4y agoThat kind of feature is very .. un-assembler. You certainly could, but the assembler doesn't keep track of any of the relevant information, so it would be a larger feature than you expect. It doesn't know the calling convention. It doesn't have a map of registers dirtied by which instructions. It doesn't do reachability analysis, so it doesn't even necessarily know what's "in the function".
- Joker_vD 4y agoDoesn't GCC inline assembly actually track that info, with the "clobber" section?
- masklinn 4y agoYes, but it's not a property of the assembly (or assembler), it's a necessity for the compiler to correctly codegen around the inline assembly. Historically, assemblers have been really dumb, so ABI is not a thing they'd track, especially as... I don't think they know what functions are? So while they can notice call/ret, they have no knowledge of a label being a jump or call target per-se, do they? So you'd need an assembly-like language to encode this sort of information.
- ElevenLathe 4y agoI mean if you have a macro assembler you should be able to write a macro that generates "save registers" instructions before a section of code and "restore registers" instructions after it. The assembler doesn't need to know our care that this section of code is a function. It's interesting how blurry the line is between a good, full-featured assembler and a crappy compiler!
- masklinn 4y ago> I mean if you have a macro assembler you should be able to write a macro that generates "save registers" instructions before a section of code and "restore registers" instructions after it. Except you want a "macro" which: - saves only the registers you touched - which are callee-saved - according to the ABI you're targeting And you really only want that for functions, because... that's where ABIs come into play.
- denton-scratch 4y ago> I don't think they know what functions are? It's a long time since I tangled with x86 assembler; but as I recall, ENTER and LEAVE were specifically for functions, and I'm not aware of any other use for them.
- tremon 4y agoENTER and LEAVE were specific x86 instructions though, not some kind of assembler special sauce. The assembler just translated your ENTER instruction into the corresponding machine opcode; no ABI knowledge required whatsoever.
- brucedawson 4y agoI think most assemblers know what functions are. There are usually directives to indicate this. They help with emitting symbols (you need the function name to be emitted or no-one can call it), stack unwind information, and other information (some of which may also be required by the ABI). Here's some relevant documentation for MASM https://learn.microsoft.com/en-us/cpp/assembler/masm/proc?view=msvc-170 https://learn.microsoft.com/en-us/cpp/assembler/masm/proc?vi... The short version of it is that assemblers these days are rarely - if ever - just a zero-context stream of machine instructions. There is far more, some of it actually required.
- dfox 4y agoTHat is essentially how inline assembly in GCC works. You have to declare which registers you are changing and in which registers you expect input and which contain results from your inline assembly block. This for obvious reasons does not work if you have separate compilation unit written in assembly, then you have to follow the ABI.
- flanfly 4y agoI not sure whether that satire. In case its not, most languages that allow inline assembly (like C) have an optional "clobber list" argument that tells the dataflow analysis of the compiler that your assembly snippet overwrites certain registers [1]. Inline assembly doesn't have target specific clobber lists because it's assumed that the code only works on one target and the programmer has to take care of making it work. 1: https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.3 https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO....
- tom_ 4y agoThe System V x64 ABI is different from the Windows x64 ABI.
- matthews2 4y agoMaybe we need some kind of higher level language that gets boiled down into assembly.
- pencilguin 4y agoAnd, a compiler that knows custom SIMD optimizations for every algorithm anyone might ever need, and can recognize when you have coded one of them so it can substitute its SIMD version.
- astrange 4y agoC does have official intrinsics for SIMD on Intel platforms, but the people who are good at writing video codecs don't like to use them because Wintel culture has such bad taste at naming functions (thanks to Hungarian notation) that using them is near-unreadable and it's easier to write everything in asm.
- deleted 4y ago[deleted]
- Iwan-Zotow 4y agoYou're wrong. Intrinsics for SIMD are not named by Windows people. They were named by Intel engineers and supported now by all other compilers. Naming is actually in the C/C++ style - __simd_do_something_here() and such
- astrange 4y agoI am not wrong and I'm not talking about those. The Intel platform intrinsics have names like `_mm512_4dpwssd_epi32()`. The standardized SIMD intrinsics with `simd` in the name are much newer than any of the code I'm talking about in ffmpeg/x264/dav1d. These are okay, but not being platform-specific of course means you don't get platform-specific features, which you might want when you're doing this level of optimization. The other problem is compilers (esp. gcc) were traditionally very bad at code generation for them, although these days they're okay at it.
- wyldfire 4y agoWhen you use inline assembly, in fact the compiler does preserve the semantics of the surrounding program considering the target's ABI -- if you tell it correctly what impacts the inline asm has. Lots of rules must be followed in order to get this behavior just right. One of the most subtle ones is "early clobbers" [1]. In many cases, you can get all the benefits of inline assembly from compiler intrinsics while letting the compiler handle all the details of register allocation and scheduling. Note that in OP's case IIUC this was assembly code and not inline assembly. If you write functions in assembly you are solely responsible for calling conventions and ABI conformance. [1] https://stackoverflow.com/a/15819941/489590 https://stackoverflow.com/a/15819941/489590
- mrkeen 4y agoYou could totally design a better convention in your own high-level language which compiled down to assembly, as long as you stayed inside it. But once you need to interface with external code you need to use a shared convention. Your scheme sounds like it would make your code well-behaved as the callee (with perhaps some performance penalty?). But as a caller, you couldn't trust the external code not to clobber registers.
- brucedawson 4y agoIn fact the fix to the WebRTC bug was to adjust the clobber list, thus telling the compiler to save the registers. Why the compiler didn't notice that registers were being used that weren't on the clobber list is unclear to me. Your suggestion seems totally reasonable. https://chromium-review.googlesource.com/c/libyuv/libyuv/+/3972137/3/source/scale_gcc.cc https://chromium-review.googlesource.com/c/libyuv/libyuv/+/3...