On 5/27/2026 9:20 PM, Wang Yaduo wrote:
Hi Jeff,

Thanks for the overview :)
My primary focus is on improving benchmark performance,
particularly on SPEC CPU2017. So I'm most interested in areas that
have a direct impact on benchmark scores.

Are there any known issues or ongoing efforts — on either the scalar
or vector side — that are currently limiting SPEC performance?
I'd love to pick up something in that space if there's work that could use attention.
Ha!  There's where Robin and I have lived the last 3 years ;-)

Robin has several ideas in the vector space.  I won't try to prioritize them or even enumerate them all.

On the scalar side, improving the zicond behavior is definitely useful.  We have this tendency to use paired ziconds to implement a generic conditional move but often there's better sequences.  THe way to attack this (IMHO) is to use a QEMU plugin to dump hot blocks (I can pass along our plug in if you want it).  Then in the output files it generates look for paired czeros then look for alternate sequences.

Daniel and I were working on a class of these in deepsjeng.  Just looking at a datafile I have lying around:

  0x000000000001cfec   19052519606  1.1575% _Z5fevalP7state_tiP12t_eval_comps.constprop.0
      ld                      a4,48(sp)
      ld                      a5,128(sp)
      ld                      t3,32(sp)
      ld                      t5,136(sp)
      or                      a1,a5,a4
      ld                      a5,64(sp)
      or                      a1,a1,a5
      sh3add                  a5,t0,s1
      ld                      t1,1856(a5)
      ld                      a5,104(sp)
      or                      a1,a1,t2
      and                     a4,t1,t3
      snez                    a4,a4
      sh3add                  a5,t0,a5
      ld                      a0,-1728(a5)
      addiw                   a2,a4,1
      and                     a5,t1,a3
      czero.eqz               a2,a2,a5
      czero.nez               a5,a4,a5
      add                     a4,a5,a2
[ ... ]

That says that 1.15% of all the dynamic instructions are in that code fragment.  We use that as a signal to gauge hotness when deciding if a code generation inefficiency is likely worth chasing. Let's assume for the sake of argument we want to look more deeply at this case.

Note the czeros with opposite polarity (eqz/nez, both using a5 as the condition) where the outputs of the czero are consumed in a subsequent add instruction.  That's a conditional move idiom.   If we look at the inputs to the two czero instructions, they're in a2 and a4 respectively and working backwards we see that a2 and a4 are related (a2 = a4 + 1).

So we've effectively got

a4 = (a5 == 0) ? a4 : a4 + 1

Which we can more efficiently implement as:

a4 = a4 + (a5 != 0)

There was a patch recently posted which may fix this specific instance (I strongly suspect the sign extend in the add is spoiling the conditional zero paths through ifcvt.cc).  But that's the basic process.

I also suspect there's stuff lying around in leela as I've spent the least amount of time studying it, though I did just squash out roughly 1% of its instruction stream (see pr 124955).  I haven't tested that on any design yet.

The same procedure was used to find the perlbench case in pr124766.

Anyway, we're happy for any efforts you can do in this space.

jeff

Reply via email to