Fixed subtle issue that causes tests to fail in VS2013 in some configs.
authorAndrew Woloszyn <awoloszyn@google.com>
Fri, 18 Sep 2015 20:12:03 +0000 (16:12 -0400)
committerAndrew Woloszyn <awoloszyn@google.com>
Fri, 18 Sep 2015 20:12:03 +0000 (16:12 -0400)
Depending on specific optimization settings VS2013 will sometimes
execute the operands to

new Instruction(builder.getUniqueId(), builder.makeBoolType(), OpPhi)

left-to-right, and sometimes right-to-left. Since makeBoolType can
also call getUniqueId(), the IDs to the OpPhi can sometimes be swapped.

This guarantees an explicit ordering of the Ids so that tests work
reliably.

SPIRV/SpvBuilder.cpp
SPIRV/SpvBuilder.h

index 3e2768b..9d8288a 100755 (executable)
@@ -2304,9 +2304,18 @@ Builder::Loop::Loop(Builder& builder, bool testFirstArg)
     merge(new Block(builder.getUniqueId(), *function)),
     body(new Block(builder.getUniqueId(), *function)),
     testFirst(testFirstArg),
-    isFirstIteration(testFirst
-                     ? nullptr
-                     : new Instruction(builder.getUniqueId(), builder.makeBoolType(), OpPhi))
-  {}
+    isFirstIteration(nullptr)
+{
+    if (!testFirst)
+    {
+// You may be tempted to rewrite this as
+// new Instruction(builder.getUniqueId(), builder.makeBoolType(), OpPhi);
+// This will cause subtle test failures because builder.getUniqueId(),
+// and builder.makeBoolType() can then get run in a compiler-specific
+// order making tests fail for certain configurations.
+        Id instructionId = builder.getUniqueId();
+        isFirstIteration = new Instruction(instructionId, builder.makeBoolType(), OpPhi);
+    }
+}
 
 }; // end spv namespace
index c5637f0..23b9bc2 100755 (executable)
@@ -564,8 +564,9 @@ protected:
         const bool testFirst;
         // When the test executes after the body, this is defined as the phi
         // instruction that tells us whether we are on the first iteration of
-        // the loop.  Otherwise this is null.
-        Instruction* const isFirstIteration;
+        // the loop.  Otherwise this is null. This is non-const because
+        // it has to be initialized outside of the initializer-list.
+        Instruction* isFirstIteration;
     };
 
     // Our loop stack.