On 8/8/2026 4:57 PM, wangjue wrote:
Hi Jeff

Yea, that could well be the one I was looking at fairly recently. At
the point where you're considering if-conversion, what values are you
selecting across?
Thanks for the explanation and the commit reference.
I reduced the MCF case to a small testcase. At the point where RTL
if-conversion is considered, it is not selecting across 1 and -1.
Instead, the same condition controls three pairs of pointer values:
extern void consume (void *, void *, void *);

__attribute__ ((noinline, noclone))
void
select_three_pointers (long x, long y,
                        void *a0, void *a1,
                        void *b0, void *b1,
                        void *c0, void *c1)
{
   if (x > y)
     {
       a0 = a1;
       b0 = b1;
       c0 = c1;
     }

   consume (a0, b0, c0);
}

In other words, the three selections are:
a0 = condition ? a1 : a0;
b0 = condition ? b1 : b0;
c0 = condition ? c1 : c0;

The original comparator in MCF returns 1 or -1, but after med3 and the
comparator are inlined into spec_qsort, that intermediate result is
eliminated. The ID comparison directly controls the three pointer
selections.
Ah.  It's a series of two-way selects.  Essentially 3 generalized conditional moves.  It only seems to if-convert at an absurdly high branch cost value (-mbranch-cost=9).

The if-converted sequence looks like:

(insn 59 0 60 (set (reg:DI 160)
        (gt:DI (reg/v:DI 134 [ x ])
            (reg/v:DI 135 [ y ]))) -1
     (nil))

(insn 60 59 61 (set (reg:DI 162)
        (if_then_else:DI (eq:DI (reg:DI 160)
                (const_int 0 [0]))
            (const_int 0 [0])
            (reg/v/f:DI 141 [ c1 ]))) -1
     (nil))

(insn 61 60 62 (set (reg:DI 161)
        (if_then_else:DI (ne:DI (reg:DI 160)
                (const_int 0 [0]))
            (const_int 0 [0])
            (reg/v/f:DI 140 [ c0 ]))) -1
     (nil))

(insn 62 61 69 (set (reg/v/f:DI 141 [ c1 ])
        (plus:DI (reg:DI 161)
            (reg:DI 162))) -1
     (nil))

Which gets repeated 2 more times for the other values.  The sgt insn is repeated and the only obvious redundancy.  Avoiding the redundancy would help, but likely would only bring the required cost down to 7 to trigger if-conversion (which still seems quite high). However, it may still be worth eliminating that redundancy as doing so would likely result if-converting cases where we need two generalized conditional moves at just a branch cost of 4.  I'll probably file that as a PR momentarily.

For the 3+ case I think we are going to need to do something with the cost model, possibly along the lines of what you did.  I think I've got enough info now to dive into what you did and draw some conclusions.

Thanks, this has been really helpful in understanding why you tackled this problem in the way you did!

jeff






Reply via email to