Bug 101442

Summary: Piglit shaders@ssa@fs-if-def-else-break fails with sb but passes with R600_DEBUG=nosb
Product: Mesa Reporter: Gert Wollny <gw.fossdev>
Component: Drivers/Gallium/r600Assignee: Default DRI bug account <dri-devel>
Status: RESOLVED FIXED QA Contact: Default DRI bug account <dri-devel>
Severity: normal    
Priority: medium    
Version: git   
Hardware: Other   
OS: All   
Whiteboard:
i915 platform: i915 features:
Attachments: Test that fails with r600/sb
Test that doesn't fail

Description Gert Wollny 2017-06-15 09:07:31 UTC
The  piglit test 

  shaders@ssa@fs-if-def-else-break

fails with only with sb enabled but passes without it.

The relevant parts of the failing shader before and after optimization look like this: 

===== SHADER #12 ====================================== PS/BARTS/EVERGREEN =====
===== 90 dw ===== 9 gprs ===== 2 stack ==================================
[...]
0060  801f00fe 0100229c     6 MP   x: PRED_SETNE_INT     R8.x,  PV.x, 0
0018  0000000b 82800000 JUMP @22
0020  0000001f a00c0000 ALU 4 @62
 0062  000000f8 00200c90     7      x: MOV                R1.x,  0      <----
 0064  000004f9 20200c90            y: MOV                R1.y,  1.0    <----
 0066  000000f8 40200c90            z: MOV                R1.z,  0
 0068  800004f9 60200c90            w: MOV                R1.w,  1.0
0022  0000000d 83400001 ELSE @26 POP:1
0024  00000023 a80c0000 ALU_POP_AFTER 4 @70
 0070  000004f9 00200c90     8      x: MOV                R1.x,  1.0    <----
 0072  000000f8 20200c90            y: MOV                R1.y,  0      <----
 0074  000000f8 40200c90            z: MOV                R1.z,  0
 0076  800004f9 60200c90            w: MOV                R1.w,  1.0
0026  40000027 a4040000 ALU_PUSH_BEFORE 2 @78 KC0[CB0:0-15]
 0078  80000081 00801990     9      x: NOT_INT            R4.x,  KC0[1].x

 0080  801f00fe 0100229c    10 MP   x: PRED_SETNE_INT     R8.x,  PV.x, 0
0028  00000011 82800001 JUMP @34 POP:1
0030  00000011 82400000 LOOP_BREAK @34
0032  00000011 83800001 POP @34 POP:1
0034  00000002 81400000 LOOP_END @4
0036  00000029 a00c0000 ALU 4 @82
 0082  00000001 00000c90    11      x: MOV                R0.x,  R1.x
 0084  00000401 20000c90            y: MOV                R0.y,  R1.y
 0086  00000801 40000c90            z: MOV                R0.z,  R1.z
 0088  80000c01 60000c90            w: MOV                R0.w,  R1.w
0038  c0000000 95200688 EXPORT_DONE        PIXEL 0     R0.xyzw  EOP
===== SHADER_END ===============================================================



===== SHADER #12 OPT ================================== PS/BARTS/EVERGREEN =====
===== 50 dw ===== 1 gprs ===== 2 stack =========================================
[...]

 0040  801f0800 00002284     3 M    x: PRED_SETNE_INT     __.x,  R0.z, 0
0018  0000000d 82800001 JUMP @26 POP:1
0020  00000015 a0040000 ALU 2 @42
 0042  000000f9 00000c90     4      x: MOV                R0.x,  1.0   <-----
 0044  800000f8 20000c90            y: MOV                R0.y,  0     <-----
0022  0000000e 82400000 LOOP_BREAK @28
0024  0000000d 83800001 POP @26 POP:1
0026  00000017 a0040000 ALU 2 @46
 0046  000000f9 00000c90     5      x: MOV                R0.x,  1.0   <-----
 0048  800000f8 20000c90            y: MOV                R0.y,  0     <-----
0028  00000002 81400000 LOOP_END @4
0030  c0000000 95200a44 EXPORT_DONE        PIXEL 0     R0.0xy1  EOP
===== SHADER_END ===============================================================

In short after the optimization R0.xy get the same values assigned in both decision paths. 

Best, 
Gert
Comment 1 Gert Wollny 2017-06-15 09:19:53 UTC
Also shaders@ssa@fs-while-loop-rotate-value fails with sb enabled, but passes with nosb.
Comment 2 Gert Wollny 2017-08-18 14:05:56 UTC
spec@glsl-1.10@execution@variable-indexing@
   vs-output-array-float-index-wr
   vs-output-array-vec3-index-wr
   vs-output-array-vec4-index-wr 

also fail with sb enabled but pass without it.
Comment 3 romain.naour 2017-11-26 22:58:08 UTC
Hello,

I'm using an HD6310 graphic card and when I'm running piglit with mesa-17.3-rc5, I have the same error.

What's the status of this bug ?

Best regards,
Romain Naour
Comment 4 Gert Wollny 2018-01-27 10:49:19 UTC
After reviewing the byte code of fs-if-def-else-break  I found that the problem is a bit different: 

In the original code BREAK is called in the loop when (KC0[0].x != 0) just like implemented in the glsl code: 

0002  LOOP_START_DX10 @36
0004   ALU_PUSH_BEFORE 2 @48 KC0[CB0:0-15]
 0048      2      x: MOV                R2.x,  1
 0050      3 MP   x: PRED_SETNE_INT     R6.x,  KC0[0].x, 0
0006   JUMP @10                       << JUMP is called if condition fails 
0008   ALU 2 @52
 0052      4      x: MOV                R2.x,  [0x00000002 2.8026e-45].x
 0054  00000002 
0010   ELSE @16 POP:1
0012   LOOP_BREAK @34
0014   POP @16 POP:1

however, in the optimized code the assignment and its branch is optimized away, and BREAK is called when (KC0[0].x == 0), i.e. exactly the opposite of the 

 0002 LOOP_START_DX10 @30
0004   PUSH @6
0006   ALU 1 @38 KC0[CB0:0-15]
 0038       2 M    x: PRED_SETNE_INT     __.x,  KC0[0].x, 0
0008   JUMP @14 POP:1          << JUMP is called if condition fails 
0010   LOOP_BREAK @28
0012   POP @14 POP:1

i.e. the optimizer removed the if branch, keeps the else branch but acts as if it were the if branch, hence the failure.
Comment 5 Gert Wollny 2018-01-27 21:00:57 UTC
With a bit more digging I found out that the sb optimizer simply drops the ELSE if no ALU instructions are found in the else branch, i.e. 

   while(cond1)
      if (cond2) {
          a = b + c; 
      } else {
          break; 
      }
   }

becomes 

   while(cond1)
      if (cond2) {
         a = b + c; 
         break; 
   }
}

after the first sb/dce_cleanup pass, and this is obviously wrong. With the break in the if path this is not a problem. I'll attach two piglits that illustrate the behaviour.
Comment 6 Gert Wollny 2018-01-27 21:03:46 UTC
Created attachment 136995 [details]
Test that fails with r600/sb

Other then in the fs-if-def-else-break piglit here the if path doesn't get completely optimized away.
Comment 7 Gert Wollny 2018-01-27 21:05:23 UTC
Created attachment 136996 [details]
Test that doesn't fail

Here the break is in the if path and other then ELSE the JUMP instruction doesn't get optimized away. Since the ELSE clause contains an ALU clause it also doesn't get optimized away.
Comment 8 Emil Velikov 2018-03-28 16:55:28 UTC
Should be resolved with

commit 8d633f067b8a3d74e3f39faea0773a229d4b93b3
Author: Dave Airlie <airlied@redhat.com>
Date:   Tue Jan 30 16:38:51 2018 +1000

    r600/sb: insert the else clause when we might depart from a loop

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.