LCOV - code coverage report
Current view: top level - gfx/angle/src/compiler/translator - BreakVariableAliasingInInnerLoops.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 27 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
       3             : // Use of this source code is governed by a BSD-style license that can be
       4             : // found in the LICENSE file.
       5             : //
       6             : 
       7             : // BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend
       8             : //      may record a variable as aliasing another. Sometimes the alias information gets garbled
       9             : //      so we work around this issue by breaking the aliasing chain in inner loops.
      10             : 
      11             : #include "BreakVariableAliasingInInnerLoops.h"
      12             : 
      13             : #include "compiler/translator/IntermNode.h"
      14             : 
      15             : // A HLSL compiler developer gave us more details on the root cause and the workaround needed:
      16             : //     The root problem is that if the HLSL compiler is applying aliasing information even on
      17             : //     incomplete simulations (in this case, a single pass). The bug is triggered by an assignment
      18             : //     that comes from a series of assignments, possibly with swizzled or ternary operators with
      19             : //     known conditionals, where the source is before the loop.
      20             : //     So, a workaround is to add a +0 term to variables the first time they are assigned to in
      21             : //     an inner loop (if they are declared in an outside scope, otherwise there is no need).
      22             : //     This will break the aliasing chain.
      23             : 
      24             : // For simplicity here we add a +0 to any assignment that is in at least two nested loops. Because
      25             : // the bug only shows up with swizzles, and ternary assignment, whole array or whole structure
      26             : // assignment don't need a workaround.
      27             : 
      28             : namespace sh
      29             : {
      30             : 
      31             : namespace
      32             : {
      33             : 
      34           0 : class AliasingBreaker : public TIntermTraverser
      35             : {
      36             :   public:
      37           0 :     AliasingBreaker() : TIntermTraverser(true, false, true) {}
      38             : 
      39             :   protected:
      40           0 :     bool visitBinary(Visit visit, TIntermBinary *binary)
      41             :     {
      42           0 :         if (visit != PreVisit)
      43             :         {
      44           0 :             return false;
      45             :         }
      46             : 
      47           0 :         if (mLoopLevel < 2 || !binary->isAssignment())
      48             :         {
      49           0 :             return true;
      50             :         }
      51             : 
      52           0 :         TIntermTyped *B = binary->getRight();
      53           0 :         TType type      = B->getType();
      54             : 
      55           0 :         if (!type.isScalar() && !type.isVector() && !type.isMatrix())
      56             :         {
      57           0 :             return true;
      58             :         }
      59             : 
      60           0 :         if (type.isArray() || IsSampler(type.getBasicType()))
      61             :         {
      62           0 :             return true;
      63             :         }
      64             : 
      65             :         // We have a scalar / vector / matrix assignment with loop depth 2.
      66             :         // Transform it from
      67             :         //    A = B
      68             :         // to
      69             :         //    A = (B + typeof<B>(0));
      70             : 
      71           0 :         TIntermBinary *bPlusZero = new TIntermBinary(EOpAdd, B, TIntermTyped::CreateZero(type));
      72           0 :         bPlusZero->setLine(B->getLine());
      73             : 
      74           0 :         binary->replaceChildNode(B, bPlusZero);
      75             : 
      76           0 :         return true;
      77             :     }
      78             : 
      79           0 :     bool visitLoop(Visit visit, TIntermLoop *loop)
      80             :     {
      81           0 :         if (visit == PreVisit)
      82             :         {
      83           0 :             mLoopLevel++;
      84             :         }
      85             :         else
      86             :         {
      87           0 :             ASSERT(mLoopLevel > 0);
      88           0 :             mLoopLevel--;
      89             :         }
      90             : 
      91           0 :         return true;
      92             :     }
      93             : 
      94             :   private:
      95             :     int mLoopLevel = 0;
      96             : };
      97             : 
      98             : }  // anonymous namespace
      99             : 
     100           0 : void BreakVariableAliasingInInnerLoops(TIntermNode *root)
     101             : {
     102           0 :     AliasingBreaker breaker;
     103           0 :     root->traverse(&breaker);
     104           0 : }
     105             : 
     106             : }  // namespace sh

Generated by: LCOV version 1.13