Skip to content

cmd/compile: intel APX meta issue #80257

Description

@Jorropo

I semi regularly get asked, what even is there to do in the toolchain ?
Thus this issue track all the ideas that probably help performance of programs in the new Intel APX instruction set, so I can point at a list of stuff to do:

  • add an intel APX builder
  • decide on intel APX syntax for GOAMD64
  • eGPR, change the number of GP registers from 16 to 32
    • encoding is backward compatible, very entropically inneficient
    • more registers means less memory operations in complex code
    • more space for fixed registers (we currently only have g in GP) ?
  • NDD (new data destination), allows some general purpose int instruction who currently output in the first argument operand to have a proper 3 operand encoding where the sources are untouched and it writes the data into a new destination register
    • IMO NDD ADD (and others in the same situation) shouldn't be it's own Op different than legacy ADD to avoid duplication in rules, we can handle this by removing resultInArg0 for all of theses if GOAMD64 allows for APX and using the assembler or obj to use "legacy" ADD if the destination is equal to one of the argument, and NDD ADD otherwise
      • maybe this would mean add a new generator flag like apx3operands or resultInArg0IfNotUsingAPX ?
  • ZU flag, replace the partial result merging behavior, with a zeroing of all the bits the legacy instruction would have left unset (/ result merged).
    • available for IMUL with opcodes 0x69 and 0x6B in map 0 and SETcc instructions
    • all SETcc should be replaced with SETcc.zu as it removes result merging costs (altho I can't measure them on my AMD CPU so maybe it's just an intel skill issue ?) and zero extension cost
      (I have a CL for implementing this without APX and results were underwhelming: https://go-review.googlesource.com/c/go/+/731620)
  • NF flag, allows instructions that traditionally set flags regardless of it being useful, to not set flags
    • available on: INC, DEC, NEG, ADD, SUB, AND, OR, XOR, SAL, SAR, SHL, SHR, ROL, ROR, SHLD, SHRD, IMUL, IDIV, MUL, DIV, LZCNT, TZCNT, POPCNT
    • we currently act like most of theses instructions do not set flags (only clobber them for flagalloc purposes) so no hard interactions here
    • I have an idea of a late pass that would remove some CMP and TEST instructions by finding previous instructions that already set the required flags in the dependency chain, this would interact with that but not much.
    • It's not clear what are the gains from NF, on current non APX CPUs there is no measurable cost to setting flags with let's say an ADD and never using them.
      • Is it just that it would allow flagalloc to do a better job since it could turn-off useless flags clobbers ? But if yes is that worth the APX encoding overhead ?
  • new CCMPcc instruction
    • looks very interesting for complex && and || chains (where the arguments do not have side effects).
    • it takes in a condition (like CMOV does)
      • if the condition is true it execute the CMP and store the results in the flags
      • if the condition is false it sets the OSZC flags from an immediate
  • new CTESTcc instruction
    • identical to CCMPcc but execute TEST when the condition is true rather than CMP
  • new CFCMOVcc instruction, allows to conditionally read and or and/or write to a memory location without branches nor sideeffects if the condition is false
    • identical to CMOVcc except when a memory operand is used.
      for example sake let's compare CMOVcc m64, r64 with CFCMOVcc m64, r64
      CMOVcc is basically equal to that pseudo-code if value := *ptr; cc(flags) { result = value }
      CFCMOVcc is basically equal to that pseudo-code if cc(flags) { result = *ptr }
      Looks promising for removing even more branches.
    • along of conditional loads this allows for conditional stores
    • looks architecturally tricky to integrate into the branchelim pass and generic op, it's not a simple thing that wont touch anything outside of the amd64 code.
  • new atomic instructions, I havn't looked into the details
  • POP2, PUSH2, mirrors the pair pops and pair push instructions in arm64
  • new JMPABS instruction, jump with a 64bits immediate, remove the need for trampolines if jumping more than +-2GiB away
    • Tbh I don't know if anyone even has a text segment big enough, it looks to me like it's more useful for dynamic linking purposes and most go binaries are statically linked so I don't know what use this could be.

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.Thinkingcompiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    Todo

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions