From 2d83ab2f57013e9b0281fb6859a74c8bd3b006d4 Mon Sep 17 00:00:00 2001 From: Andrew Woloszyn <awoloszyn@google.com> Date: Fri, 18 Sep 2015 16:12:03 -0400 Subject: [PATCH] Fixed subtle issue that causes tests to fail in VS2013 in some configs. 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 | 17 +++++++++++++---- SPIRV/SpvBuilder.h | 5 +++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 3e2768b66..9d8288a2c 100755 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -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 diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h index c5637f042..23b9bc2c0 100755 --- a/SPIRV/SpvBuilder.h +++ b/SPIRV/SpvBuilder.h @@ -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. -- GitLab