On Fri, 2020-06-26 at 14:27 -0600, Jeff Law wrote:
> On Thu, 2020-06-04 at 02:37 +0200, Ilya Leoshkevich via Gcc-patches
> wrote:
> > Bootstrapped and regtested on x86_64-redhat-linux, ppc64le-redhat-
> > linux
> > and s390x-redhat-linux.
> > 
> > 
> > Linux Kernel (specifically, drivers/leds/trigger/ledtrig-cpu.c)
> > build
> > with GCC 10 fails on s390 with "impossible constraint".
> > 
> > The problem is that jump threading makes __builtin_constant_p lie
> > when
> > an expression in question appears to be a constant on a threading
> > path.
> What do you mean by this?
> 
> What should happen is the path where the queried object is constant,
> builtin_constant_p will return true.  On the other path where it is
> not,
> builtin_constant_p will return false.

But what if a path ends before we use the `builtin_constant_p` result?
In the testcase from the patch we have `i = is_active ? 1 : -1`, which 
produces two paths.  On each path `builtin_constant_p (i)` returns 
true, however, the asm statement which depends on this being true is
not on either path and comes only later.

Here are the relevant tree dumps (sorry, a bit verbose, I couldn't make
them smaller):

gcc/cc1 ../gcc/testsuite/gcc.target/s390/builtin-constant-p-threading.c 
-O2 -march=z196 -mzarch -fdump-tree-all-all

Before 106t.thread1:

;;   basic block 2
  if (is_active_2(D) != 0)
    goto <bb 3>; [50.00%]
  else
    goto <bb 4>; [50.00%]

;;   basic block 3
  # iftmp.0_6 = PHI <1(2)>
  _7 = __builtin_constant_pD.1098 (iftmp.0_6);
  if (_7 != 0)
    goto <bb 6>; [50.00%]
  else
    goto <bb 8>; [50.00%]

;;   basic block 4
  # iftmp.0_4 = PHI <-1(2)>
  _12 = __builtin_constant_pD.1098 (iftmp.0_4);
  if (_12 != 0)
    goto <bb 5>; [50.00%]
  else
    goto <bb 8>; [50.00%]

;;   basic block 5
  if (iftmp.0_4 >= -128)
    goto <bb 7>; [20.00%]
  else
    goto <bb 8>; [80.00%]

;;   basic block 6
  if (iftmp.0_6 <= 127)
    goto <bb 7>; [12.00%]
  else
    goto <bb 8>; [88.00%]

;;   basic block 7
  # iftmp.0_13 = PHI <iftmp.0_6(6), iftmp.0_4(5)>
  # .MEM_10 = VDEF <.MEM_3(D)>
  __asm__ __volatile__("asi %0,%1
" : "ptr" "=Q" MEM[(intD.6 *)&num_active_cpusD.2277] : "val" "i"
iftmp.0_13, "Q" MEM[(intD.6 *)&num_active_cpusD.2277] : "memory",
"cc");
  goto <bb 9>; [100.00%]
;;    succ:       9 [always]  count:91268056 (estimated locally)
(FALLTHRU,EXECUTABLE)

;;   basic block 8
  # iftmp.0_14 = PHI <iftmp.0_4(5), iftmp.0_4(4), iftmp.0_6(6),
iftmp.0_6(3)>
  # .MEM_11 = VDEF <.MEM_3(D)>
  __asm__ __volatile__("laa %0,%2,%1
" : "old" "=d" old_8, "ptr" "=Q" MEM[(intD.6 *)&num_active_cpusD.2277]
: "val" "d" iftmp.0_14, "Q" MEM[(intD.6 *)&num_active_cpusD.2277] :
"memory", "cc");

`asi` instruction (bb 7) can be used only with constants, and that's 
what `__builtin_constant_p` ensures here.  For other values `laa`
instruction (block 8) must be used.

106t.thread1 says:

about to thread: path: 2 -> 4, 4 -> 5, 5 -> 6
about to thread: path: 3 -> 4, 4 -> 5, 5 -> 6, 6 -> 7

and as a result produces this:

;;   basic block 2
  if (is_active_2(D) != 0)
    goto <bb 3>; [50.00%]
  else
    goto <bb 4>; [50.00%]

;;   basic block 3

;;   basic block 4
  # iftmp.0_13 = PHI <-1(2), 1(3)>
  # .MEM_10 = VDEF <.MEM_3(D)>
  __asm__ __volatile__("asi %0,%1
" : "ptr" "=Q" MEM[(intD.6 *)&num_active_cpusD.2277] : "val" "i"
iftmp.0_13, "Q" MEM[(intD.6 *)&num_active_cpusD.2277] : "memory",
"cc");

This code won't compile - `iftmp.0_13` is not a constant.  My idea was
that the root cause is that `i` is constant on each threading path,
but is not constant anymore when they merge.  But maybe there is a
deeper issue?  What would be a better way to fix this?

> > Fix by disallowing __builtin_constant_p on threading paths.
> > 
> > gcc/ChangeLog:
> > 
> > 2020-06-03  Ilya Leoshkevich  <i...@linux.ibm.com>
> > 
> >     * tree-ssa-threadbackward.c
> > (thread_jumps::profitable_jump_thread_path):
> >     Do not allow __builtin_constant_p on a threading path.
> Sorry, this is wrong.
> 
> jeff
> 
> 

Reply via email to