The application I'm trying to optimise makes intensive use of shift cl operations to pack bits together. Such as:
packed_bits = (packed_bits << n) | new_bits;
(where n is a variable specifying the size of new_bits)
The target platform is Sandy Bridge. Vtune reports a high number of Flags Merge Stalls. All is consistent with the description made in this page http://software.intel.com/sites/products/documentation/doclib/iss/2013/amplifier/lin/ug_docs/GUID-02...
Not use any shift cl operation sounds a quite big limitation. I was wondering if anyone could suggest a way to workaround this issue, considering that such flags are not really used for packing bits (i.e. the bits that slide out are not relevant).
SAR instruction moves LSB to CF and compiler decided to use sar cl followed by test instr. which also updates flag register hence I suppose so called Flag Merge Stalls .By checking Agner Fog instruction tables it can be seen that sar instruction latency is 2 cycles and test latency is 1 cycle.
According to optimization user manual:
Flags Merge micro-op ratio:
100 * PARTIAL_RAT_STALLS.FLAGS_MERGE_UOP_CYCLES /
Get event count in GE report (set "Show data as" to number), know how it impacts on performance data overall.
Try Intel C/C++ Composer XE 13.0 to build, with advanced option "-xHost -O3". Use VTune to test it again. It's my opinion.
Another consideration to split your statement :
packed_bits = (packed_bits << n) | new_bits; To two statements avoid RAT stall, I hope.
Yes iliyapolak. That was why I hope that Intel C++ compiler can help, and we may change code to:
packed_bit = (packed_bits << n);
packed_bit |= new_bits;
In loop to reduce RAT resource pressure, improve performance.
I remember that Intel C++ composer has "intrinsic" function to implement shift function, you may ask to Composer forum.
It seems that GCC was used to compile that code.It could be interesting to run that code(responsible for generating Flags Merge) not in the loop to see if Flags Merge stalls are generated due to loop Sar cl and Test beign executed inside the loop.