diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/VisitorOpsControlFlow.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/VisitorOpsControlFlow.java index f1bae7323e..a27bb9d598 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/VisitorOpsControlFlow.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/VisitorOpsControlFlow.java @@ -155,22 +155,6 @@ private Event visitLoopBranch(String labelId) { return visitGoto(labelId); } - private Event visitIfBranch(Expression guard, String trueLabelId, String falseLabelId) { - for (String labelId : List.of(trueLabelId, falseLabelId)) { - if (cfBuilder.isBlockStarted(labelId)) { - throw new ParsingException("Illegal backward jump to '%s' from a structured branch", labelId); - } - } - mergeLabelId = null; - nextLabelId = trueLabelId; - builder.setNextOps(Set.of("OpLabel")); - Label falseLabel = cfBuilder.getOrCreateLabel(falseLabelId); - Label mergeLabel = cfBuilder.createMergeLabel(falseLabelId); - Event event = EventFactory.newIfJumpUnless(guard, falseLabel, mergeLabel); - builder.addEvent(event); - return cfBuilder.endBlock(event); - } - private Event visitConditionalJump(Expression guard, String trueLabelId, String falseLabelId) { if (cfBuilder.isBlockStarted(trueLabelId)) { if (cfBuilder.isBlockStarted(falseLabelId)) { @@ -189,16 +173,32 @@ private Event visitConditionalJump(Expression guard, String trueLabelId, String return cfBuilder.endBlock(trueJump); } + private Event visitIfBranch(Expression guard, String trueLabelId, String falseLabelId) { + for (String labelId : List.of(trueLabelId, falseLabelId)) { + if (cfBuilder.isBlockStarted(labelId)) { + throw new ParsingException("Illegal backward jump to '%s' from a structured branch", labelId); + } + } + mergeLabelId = null; + builder.setNextOps(Set.of("OpLabel")); + + // TODO: Currently, we treat structured branches as unstructured control flow. + // We need a new event type to represent SPIR-V structured control flow. + // For now, we can treat a structured branch as unstructured jumps, + // because Vulkan memory model has no control dependency. + + return visitConditionalJump(guard, trueLabelId, falseLabelId); + } + private Event visitLoopBranchConditional(Expression guard, String trueLabelId, String falseLabelId) { mergeLabelId = null; continueLabelId = null; nextLabelId = trueLabelId; builder.setNextOps(Set.of("OpLabel")); - // TODO: For a structured while loop, a control dependency - // should be generated in the same way as for a structured if branch. + // TODO: Currently, we treat structured loops as unstructured control flow. // We need to add a new event type for this. - // For now, we can treat while loop as unstructured jumps, + // For now, we can treat a structured branch as unstructured jumps, // because Vulkan memory model has no control dependency. return visitConditionalJump(guard, trueLabelId, falseLabelId); diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/builders/ControlFlowBuilder.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/builders/ControlFlowBuilder.java index 7e10dee763..bb24422f86 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/builders/ControlFlowBuilder.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/builders/ControlFlowBuilder.java @@ -15,7 +15,6 @@ public class ControlFlowBuilder { protected final Map blockLabels = new HashMap<>(); protected final Map lastBlockEvents = new HashMap<>(); - protected final Map mergeLabelIds = new HashMap<>(); protected final Deque blockStack = new ArrayDeque<>(); protected final Map> phiDefinitions = new HashMap<>(); protected final Map phiDefinitionLocations = new HashMap<>(); @@ -44,8 +43,6 @@ public void build() { if (loc != null) { event.setMetadata(loc); } lastBlockEvents.get(blockId).getPredecessor().insertAfter(event); })); - mergeLabelIds.forEach((jumpLabelId, endLabelId) -> - lastBlockEvents.get(jumpLabelId).getPredecessor().insertAfter(blockLabels.get(endLabelId))); } public void startBlock(String id) { @@ -68,12 +65,6 @@ public Label getOrCreateLabel(String id) { return blockLabels.computeIfAbsent(id, EventFactory::newLabel); } - public Label createMergeLabel(String id) { - String mergeId = id + "_end"; - mergeLabelIds.put(id, mergeId); - return createLabel(mergeId); - } - public void addPhiDefinition(String blockId, Register register, String expressionId) { phiDefinitions.computeIfAbsent(blockId, k -> new HashMap<>()).put(register, expressionId); } @@ -121,11 +112,6 @@ private void validateBeforeBuild() { throw new ParsingException("Phi operation(s) refer to undefined block(s) %s", String.join(", ", missingPhiBlocks)); } - Set missingMergeBlocks = Sets.difference(mergeLabelIds.keySet(), blockLabels.keySet()); - if (!missingMergeBlocks.isEmpty()) { - throw new ParsingException("Branch merge label(s) refer to undefined block(s) %s", - String.join(", ", missingMergeBlocks)); - } Map reverse = new HashMap<>(); lastBlockEvents.forEach((k, v) -> { if (reverse.containsKey(v)) { @@ -135,13 +121,6 @@ private void validateBeforeBuild() { }); } - private Label createLabel(String id) { - if (blockLabels.containsKey(id)) { - throw new ParsingException("Attempt to redefine label '%s'", id); - } - return getOrCreateLabel(id); - } - private SourceLocation getPhiLocation(String blockId, Register register) { String id = phiDefinitionIds.get(blockId).get(register); if (id != null) { diff --git a/dartagnan/src/test/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/VisitorOpsControlFlowTest.java b/dartagnan/src/test/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/VisitorOpsControlFlowTest.java index 39f9212d2e..066e8b7be2 100644 --- a/dartagnan/src/test/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/VisitorOpsControlFlowTest.java +++ b/dartagnan/src/test/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/VisitorOpsControlFlowTest.java @@ -10,7 +10,6 @@ import com.dat3m.dartagnan.program.Register; import com.dat3m.dartagnan.program.event.Event; import com.dat3m.dartagnan.program.event.core.CondJump; -import com.dat3m.dartagnan.program.event.core.IfAsJump; import com.dat3m.dartagnan.program.event.core.Label; import com.dat3m.dartagnan.program.event.core.Skip; import com.dat3m.dartagnan.program.event.functions.Return; @@ -153,22 +152,64 @@ public void testStructuredBranch() { List events = builder.getCurrentFunction().getEvents(); Label label0 = (Label) events.get(0); - IfAsJump ifJump = (IfAsJump) events.get(1); - Label label1 = (Label) events.get(2); - CondJump jump = (CondJump) events.get(3); - Label label2 = (Label) events.get(4); - Return ret = (Return) events.get(5); + CondJump trueJump = (CondJump) events.get(1); + CondJump falseJump = (CondJump) events.get(2); + Label label1 = (Label) events.get(3); + CondJump jump = (CondJump) events.get(4); + Label label2 = (Label) events.get(5); + Return ret = (Return) events.get(6); assertEquals("%label0", label0.getName()); - assertEquals("%label2", ifJump.getLabel().getName()); - assertEquals("%label2_end", ifJump.getEndIf().getName()); + assertEquals("%label1", trueJump.getLabel().getName()); + assertEquals("%label2", falseJump.getLabel().getName()); assertEquals("%label1", label1.getName()); assertEquals("%label2", jump.getLabel().getName()); assertEquals("%label2", label2.getName()); assertTrue(jump.isGoto()); - assertEquals(Map.of("%label2", "%label2_end"), cfBuilder.getMergeLabelIds()); - assertEquals(Map.of("%label0", ifJump, "%label1", jump, "%label2", ret), + assertEquals(Map.of("%label0", trueJump, "%label1", jump, "%label2", ret), + cfBuilder.getLastBlockEvents()); + } + + @Test + public void testStructuredBranchInverseLabeOrder() { + String input = """ + %label0 = OpLabel + OpSelectionMerge %label2 None + OpBranchConditional %value %label2 %label1 + %label1 = OpLabel + OpBranch %label2 + %label2 = OpLabel + OpReturn + """; + + builder.mockBoolType("%bool"); + builder.mockUndefinedValue("%value", "%bool"); + builder.mockFunctionStart(false); + + // when + visit(input); + + // then + List events = builder.getCurrentFunction().getEvents(); + + Label label0 = (Label) events.get(0); + CondJump trueJump = (CondJump) events.get(1); + CondJump falseJump = (CondJump) events.get(2); + Label label1 = (Label) events.get(3); + CondJump jump = (CondJump) events.get(4); + Label label2 = (Label) events.get(5); + Return ret = (Return) events.get(6); + + assertEquals("%label0", label0.getName()); + assertEquals("%label2", trueJump.getLabel().getName()); + assertEquals("%label1", falseJump.getLabel().getName()); + assertEquals("%label1", label1.getName()); + assertEquals("%label2", jump.getLabel().getName()); + assertEquals("%label2", label2.getName()); + + assertTrue(jump.isGoto()); + assertEquals(Map.of("%label0", trueJump, "%label1", jump, "%label2", ret), cfBuilder.getLastBlockEvents()); } @@ -201,22 +242,24 @@ public void testStructuredBranchNestedTrue() { List events = builder.getCurrentFunction().getEvents(); Label label0 = (Label) events.get(0); - IfAsJump ifJump = (IfAsJump) events.get(1); - Label label1 = (Label) events.get(2); - IfAsJump ifJumpInner = (IfAsJump) events.get(3); - Label label1Inner = (Label) events.get(4); - CondJump jumpInner = (CondJump) events.get(5); - Label label2Inner = (Label) events.get(6); - CondJump jump = (CondJump) events.get(7); - Label label2 = (Label) events.get(8); - Return ret = (Return) events.get(9); + CondJump trueJump = (CondJump) events.get(1); + CondJump falseJump = (CondJump) events.get(2); + Label label1 = (Label) events.get(3); + CondJump trueJumpInner = (CondJump) events.get(4); + CondJump falseJumpInner = (CondJump) events.get(5); + Label label1Inner = (Label) events.get(6); + CondJump jumpInner = (CondJump) events.get(7); + Label label2Inner = (Label) events.get(8); + CondJump jump = (CondJump) events.get(9); + Label label2 = (Label) events.get(10); + Return ret = (Return) events.get(11); assertEquals("%label0", label0.getName()); - assertEquals("%label2", ifJump.getLabel().getName()); - assertEquals("%label2_end", ifJump.getEndIf().getName()); + assertEquals("%label1", trueJump.getLabel().getName()); + assertEquals("%label2", falseJump.getLabel().getName()); assertEquals("%label1", label1.getName()); - assertEquals("%label2_inner", ifJumpInner.getLabel().getName()); - assertEquals("%label2_inner_end", ifJumpInner.getEndIf().getName()); + assertEquals("%label1_inner", trueJumpInner.getLabel().getName()); + assertEquals("%label2_inner", falseJumpInner.getLabel().getName()); assertEquals("%label1_inner", label1Inner.getName()); assertEquals("%label2_inner", jumpInner.getLabel().getName()); assertEquals("%label2_inner", label2Inner.getName()); @@ -228,8 +271,8 @@ public void testStructuredBranchNestedTrue() { assertTrue(jumpInner.isGoto()); assertEquals(Map.of( - "%label0", ifJump, - "%label1", ifJumpInner, + "%label0", trueJump, + "%label1", trueJumpInner, "%label1_inner", jumpInner, "%label2_inner", jump, "%label2", ret @@ -267,26 +310,28 @@ public void testStructuredBranchNestedFalse() { List events = builder.getCurrentFunction().getEvents(); Label label0 = (Label) events.get(0); - IfAsJump ifJump = (IfAsJump) events.get(1); - Label label1 = (Label) events.get(2); - CondJump jump1 = (CondJump) events.get(3); - Label label2 = (Label) events.get(4); - IfAsJump ifJumpInner = (IfAsJump) events.get(5); - Label label1Inner = (Label) events.get(6); - CondJump jumpInner = (CondJump) events.get(7); - Label label2Inner = (Label) events.get(8); - CondJump jump2 = (CondJump) events.get(9); - Label label3 = (Label) events.get(10); - Return ret = (Return) events.get(11); + CondJump trueJump = (CondJump) events.get(1); + CondJump falseJump = (CondJump) events.get(2); + Label label1 = (Label) events.get(3); + CondJump jump1 = (CondJump) events.get(4); + Label label2 = (Label) events.get(5); + CondJump trueJumpInner = (CondJump) events.get(6); + CondJump falseJumpInner = (CondJump) events.get(7); + Label label1Inner = (Label) events.get(8); + CondJump jumpInner = (CondJump) events.get(9); + Label label2Inner = (Label) events.get(10); + CondJump jump2 = (CondJump) events.get(11); + Label label3 = (Label) events.get(12); + Return ret = (Return) events.get(13); assertEquals("%label0", label0.getName()); - assertEquals("%label3", ifJump.getLabel().getName()); - assertEquals("%label3_end", ifJump.getEndIf().getName()); + assertEquals("%label1", trueJump.getLabel().getName()); + assertEquals("%label3", falseJump.getLabel().getName()); assertEquals("%label2", jump1.getLabel().getName()); assertEquals("%label1", label1.getName()); assertEquals("%label2", label2.getName()); - assertEquals("%label2_inner", ifJumpInner.getLabel().getName()); - assertEquals("%label2_inner_end", ifJumpInner.getEndIf().getName()); + assertEquals("%label1_inner", trueJumpInner.getLabel().getName()); + assertEquals("%label2_inner", falseJumpInner.getLabel().getName()); assertEquals("%label1_inner", label1Inner.getName()); assertEquals("%label2_inner", jumpInner.getLabel().getName()); assertEquals("%label2_inner", label2Inner.getName()); @@ -298,9 +343,9 @@ public void testStructuredBranchNestedFalse() { assertTrue(jumpInner.isGoto()); assertEquals(Map.of( - "%label0", ifJump, + "%label0", trueJump, "%label1", jump1, - "%label2", ifJumpInner, + "%label2", trueJumpInner, "%label1_inner", jumpInner, "%label2_inner", jump2, "%label3", ret @@ -308,16 +353,13 @@ public void testStructuredBranchNestedFalse() { } @Test - public void testStructuredBranchNestedSameLabel() { + public void testLoopWithForwardLabels() { // given String input = """ %label0 = OpLabel - OpSelectionMerge %label2 None + OpLoopMerge %label1 %label2 None OpBranchConditional %value %label1 %label2 %label1 = OpLabel - OpSelectionMerge %label2 None - OpBranchConditional %value %label1_inner %label2 - %label1_inner = OpLabel OpBranch %label2 %label2 = OpLabel OpReturn @@ -327,33 +369,6 @@ public void testStructuredBranchNestedSameLabel() { builder.mockBoolType("%bool"); builder.mockUndefinedValue("%value", "%bool"); - try { - // when - visit(input); - fail("Should throw exception"); - } catch (ParsingException e) { - // then - assertEquals("Attempt to redefine label '%label2_end'", e.getMessage()); - } - } - - @Test - public void testLoopWithForwardLabels() { - // given - String input = """ - %label0 = OpLabel - OpLoopMerge %label1 %label2 None - OpBranchConditional %value %label1 %label2 - %label1 = OpLabel - OpBranch %label2 - %label2 = OpLabel - OpReturn - """; - - builder.mockFunctionStart(false); - builder.mockBoolType("%bool"); - builder.mockUndefinedValue("%value", "%bool"); - // when visit(input); @@ -379,8 +394,6 @@ public void testLoopWithForwardLabels() { assertTrue(jump2.isGoto()); assertTrue(jump3.isGoto()); - assertTrue(cfBuilder.getMergeLabelIds().isEmpty()); - assertEquals(Map.of("%label0", jump1, "%label1", jump3, "%label2", ret), cfBuilder.getLastBlockEvents()); } @@ -420,8 +433,6 @@ public void testLoopWithBackwardLabel() { assertFalse(jump1.isGoto()); assertTrue(jump2.isGoto()); - assertTrue(cfBuilder.getMergeLabelIds().isEmpty()); - assertEquals(Map.of("%label0", jump1, "%label1", ret), cfBuilder.getLastBlockEvents()); } @@ -452,20 +463,6 @@ public void testStructuredBranchBackwardFalse() { "from a structured branch"); } - @Test - public void testStructuredBranchLabelsIllegalOrder() { - doTestIllegalStructuredBranch(""" - %label0 = OpLabel - OpSelectionMerge %label1 None - OpBranchConditional %value1 %label2 %label1 - %label1 = OpLabel - OpBranch %label2 - %label2 = OpLabel - OpReturn - """, - "Illegal label, expected '%label2' but received '%label1'"); - } - @Test public void testLoopMergeWithTwoBackwardLabels() { doTestIllegalStructuredBranch(""" diff --git a/dartagnan/src/test/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/mocks/MockControlFlowBuilder.java b/dartagnan/src/test/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/mocks/MockControlFlowBuilder.java index 02506234f3..f404985793 100644 --- a/dartagnan/src/test/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/mocks/MockControlFlowBuilder.java +++ b/dartagnan/src/test/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/mocks/MockControlFlowBuilder.java @@ -18,10 +18,6 @@ public List getBlockStack() { return blockStack.stream().toList(); } - public Map getMergeLabelIds() { - return Map.copyOf(mergeLabelIds); - } - public Map getLastBlockEvents() { return Map.copyOf(lastBlockEvents); } diff --git a/dartagnan/src/test/java/com/dat3m/dartagnan/spirv/basic/SpirvAssertionsTest.java b/dartagnan/src/test/java/com/dat3m/dartagnan/spirv/basic/SpirvAssertionsTest.java index 5b0a72da2a..23a19e890d 100644 --- a/dartagnan/src/test/java/com/dat3m/dartagnan/spirv/basic/SpirvAssertionsTest.java +++ b/dartagnan/src/test/java/com/dat3m/dartagnan/spirv/basic/SpirvAssertionsTest.java @@ -86,11 +86,13 @@ public static Iterable data() throws IOException { {"branch-cond-bf.spv.dis", 2, PASS}, {"branch-cond-fb.spv.dis", 1, UNKNOWN}, {"branch-cond-fb.spv.dis", 2, PASS}, - {"branch-cond-struct.spv.dis", 1, PASS}, - {"branch-cond-struct-read-write.spv.dis", 1, PASS}, {"branch-race.spv.dis", 1, PASS}, {"branch-loop.spv.dis", 2, UNKNOWN}, {"branch-loop.spv.dis", 3, PASS}, + {"branch-struct-if.spv.dis", 1, PASS}, + {"branch-struct-if-inverted.spv.dis", 1, PASS}, + {"branch-struct-if-else.spv.dis", 1, PASS}, + {"branch-struct-if-else-inverted.spv.dis", 1, PASS}, {"loop-struct-cond.spv.dis", 1, UNKNOWN}, {"loop-struct-cond.spv.dis", 2, PASS}, {"loop-struct-cond-suffix.spv.dis", 1, UNKNOWN}, diff --git a/dartagnan/src/test/java/com/dat3m/dartagnan/spirv/basic/SpirvChecksTest.java b/dartagnan/src/test/java/com/dat3m/dartagnan/spirv/basic/SpirvChecksTest.java index 5ff198b1ab..50070f70e6 100644 --- a/dartagnan/src/test/java/com/dat3m/dartagnan/spirv/basic/SpirvChecksTest.java +++ b/dartagnan/src/test/java/com/dat3m/dartagnan/spirv/basic/SpirvChecksTest.java @@ -87,11 +87,13 @@ public static Iterable data() throws IOException { {"branch-cond-bf.spv.dis", 2, PASS}, {"branch-cond-fb.spv.dis", 1, UNKNOWN}, {"branch-cond-fb.spv.dis", 2, PASS}, - {"branch-cond-struct.spv.dis", 1, PASS}, - {"branch-cond-struct-read-write.spv.dis", 1, PASS}, {"branch-race.spv.dis", 1, PASS}, {"branch-loop.spv.dis", 2, UNKNOWN}, {"branch-loop.spv.dis", 3, PASS}, + {"branch-struct-if.spv.dis", 1, PASS}, + {"branch-struct-if-inverted.spv.dis", 1, PASS}, + {"branch-struct-if-else.spv.dis", 1, PASS}, + {"branch-struct-if-else-inverted.spv.dis", 1, PASS}, {"loop-struct-cond.spv.dis", 1, UNKNOWN}, {"loop-struct-cond.spv.dis", 2, PASS}, {"loop-struct-cond-suffix.spv.dis", 1, UNKNOWN}, diff --git a/dartagnan/src/test/resources/spirv/basic/branch-cond-struct-read-write.spv.dis b/dartagnan/src/test/resources/spirv/basic/branch-cond-struct-read-write.spv.dis deleted file mode 100644 index 4d1a3ac892..0000000000 --- a/dartagnan/src/test/resources/spirv/basic/branch-cond-struct-read-write.spv.dis +++ /dev/null @@ -1,46 +0,0 @@ -; @Input: %out = {0, 0} -; @Output: forall (%out[0]==11 and %out[1]==22) -; @Config: 2, 1, 1 -; SPIR-V -; Version: 1.0 -; Schema: 0 - OpCapability Shader - OpCapability VulkanMemoryModel - OpMemoryModel Logical Vulkan - OpEntryPoint GLCompute %main "main" %ids - OpSource GLSL 450 - OpDecorate %ids BuiltIn GlobalInvocationId - %void = OpTypeVoid - %bool = OpTypeBool - %func = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %v3uint = OpTypeVector %uint 3 - %v2uint = OpTypeVector %uint 2 - %ptr_uint = OpTypePointer Private %uint - %ptr_v3uint = OpTypePointer Input %v3uint - %ptr_v2uint = OpTypePointer Output %v2uint - %c0 = OpConstant %uint 0 - %c11 = OpConstant %uint 11 - %c22 = OpConstant %uint 22 - %ids = OpVariable %ptr_v3uint Input - %out = OpVariable %ptr_v2uint Output - %main = OpFunction %void None %func - %label_1 = OpLabel - %id_ptr = OpAccessChain %ptr_uint %ids %c0 - %id = OpLoad %uint %id_ptr - %local = OpVariable %ptr_uint Private %c0 - %cond = OpUGreaterThan %bool %id %c0 - OpSelectionMerge %label_3 None - OpBranchConditional %cond %label_2 %label_3 - %label_2 = OpLabel - OpStore %local %c22 - OpBranch %label_4 - %label_3 = OpLabel - OpStore %local %c11 - OpBranch %label_4 - %label_4 = OpLabel - %value = OpLoad %uint %local - %ptr_out = OpAccessChain %ptr_uint %out %id - OpStore %ptr_out %value - OpReturn - OpFunctionEnd diff --git a/dartagnan/src/test/resources/spirv/basic/branch-cond-struct.spv.dis b/dartagnan/src/test/resources/spirv/basic/branch-cond-struct.spv.dis deleted file mode 100644 index 2b9f7cc11e..0000000000 --- a/dartagnan/src/test/resources/spirv/basic/branch-cond-struct.spv.dis +++ /dev/null @@ -1,41 +0,0 @@ -; @Input: %out = {0, 0} -; @Output: forall (%out[0]==11 and %out[1]==22) -; @Config: 2, 1, 1 -; SPIR-V -; Version: 1.0 -; Schema: 0 - OpCapability Shader - OpCapability VulkanMemoryModel - OpMemoryModel Logical Vulkan - OpEntryPoint GLCompute %main "main" %ids - OpSource GLSL 450 - OpDecorate %ids BuiltIn GlobalInvocationId - %void = OpTypeVoid - %bool = OpTypeBool - %func = OpTypeFunction %void - %uint = OpTypeInt 32 0 - %v3uint = OpTypeVector %uint 3 - %v2uint = OpTypeVector %uint 2 - %ptr_uint = OpTypePointer Private %uint - %ptr_v3uint = OpTypePointer Input %v3uint - %ptr_v2uint = OpTypePointer Output %v2uint - %c0 = OpConstant %uint 0 - %c11 = OpConstant %uint 11 - %c22 = OpConstant %uint 22 - %ids = OpVariable %ptr_v3uint Input - %out = OpVariable %ptr_v2uint Output - %main = OpFunction %void None %func - %label = OpLabel - %id_ptr = OpAccessChain %ptr_uint %ids %c0 - %id = OpLoad %uint %id_ptr - %ptr_out = OpAccessChain %ptr_uint %out %id - %cond = OpUGreaterThan %bool %id %c0 - OpSelectionMerge %l_false None - OpBranchConditional %cond %l_true %l_false - %l_true = OpLabel - OpStore %ptr_out %c22 - OpReturn - %l_false = OpLabel - OpStore %ptr_out %c11 - OpReturn - OpFunctionEnd diff --git a/dartagnan/src/test/resources/spirv/basic/branch-struct-if-else-inverted.spv.dis b/dartagnan/src/test/resources/spirv/basic/branch-struct-if-else-inverted.spv.dis new file mode 100644 index 0000000000..c5dc64619b --- /dev/null +++ b/dartagnan/src/test/resources/spirv/basic/branch-struct-if-else-inverted.spv.dis @@ -0,0 +1,68 @@ +; @Input: %out = {{0, 0}} +; @Output: forall (%out[0][0]==2 and %out[0][1]==1) +; @Config: 2, 1, 1 +; SPIR-V +; Version: 1.6 +; Generator: Google Clspv; 0 +; Bound: 51 +; Schema: 0 + OpCapability Shader + %43 = OpExtInstImport "NonSemantic.ClspvReflection.5" + OpMemoryModel Logical Vulkan + OpEntryPoint GLCompute %17 "test" %gl_LocalInvocationID %10 %out + OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId + OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize + OpDecorate %_runtimearr_uint ArrayStride 4 + OpMemberDecorate %_struct_12 0 Offset 0 + OpDecorate %_struct_12 Block + OpDecorate %out DescriptorSet 0 + OpDecorate %out Binding 0 + OpDecorate %5 SpecId 0 + OpDecorate %6 SpecId 1 + OpDecorate %7 SpecId 2 + %uint = OpTypeInt 32 0 + %v3uint = OpTypeVector %uint 3 +%_ptr_Input_v3uint = OpTypePointer Input %v3uint + %5 = OpSpecConstant %uint 1 + %6 = OpSpecConstant %uint 1 + %7 = OpSpecConstant %uint 1 +%gl_WorkGroupSize = OpSpecConstantComposite %v3uint %5 %6 %7 +%_ptr_Private_v3uint = OpTypePointer Private %v3uint +%_runtimearr_uint = OpTypeRuntimeArray %uint + %_struct_12 = OpTypeStruct %_runtimearr_uint +%_ptr_StorageBuffer__struct_12 = OpTypePointer StorageBuffer %_struct_12 + %void = OpTypeVoid + %16 = OpTypeFunction %void +%_ptr_Input_uint = OpTypePointer Input %uint + %uint_0 = OpConstant %uint 0 + %bool = OpTypeBool +%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint + %uint_2 = OpConstant %uint 2 + %uint_1 = OpConstant %uint 1 + %false = OpConstantFalse %bool + %true = OpConstantTrue %bool +%gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input + %10 = OpVariable %_ptr_Private_v3uint Private %gl_WorkGroupSize + %out = OpVariable %_ptr_StorageBuffer__struct_12 StorageBuffer + %17 = OpFunction %void None %16 + %18 = OpLabel + %21 = OpAccessChain %_ptr_Input_uint %gl_LocalInvocationID %uint_0 + %22 = OpLoad %uint %21 + %24 = OpINotEqual %bool %22 %uint_0 + OpSelectionMerge %32 None + OpBranchConditional %24 %32 %27 + %27 = OpLabel + %29 = OpAccessChain %_ptr_StorageBuffer_uint %out %uint_0 %22 + OpStore %29 %uint_2 + OpBranch %32 + %32 = OpLabel + %33 = OpPhi %bool %false %27 %true %18 + OpSelectionMerge %40 None + OpBranchConditional %33 %36 %40 + %36 = OpLabel + %37 = OpAccessChain %_ptr_StorageBuffer_uint %out %uint_0 %22 + OpStore %37 %uint_1 + OpBranch %40 + %40 = OpLabel + OpReturn + OpFunctionEnd diff --git a/dartagnan/src/test/resources/spirv/basic/branch-struct-if-else.spv.dis b/dartagnan/src/test/resources/spirv/basic/branch-struct-if-else.spv.dis new file mode 100644 index 0000000000..a6e2b68f56 --- /dev/null +++ b/dartagnan/src/test/resources/spirv/basic/branch-struct-if-else.spv.dis @@ -0,0 +1,68 @@ +; @Input: %out = {{0, 0}} +; @Output: forall (%out[0][0]==1 and %out[0][1]==2) +; @Config: 2, 1, 1 +; SPIR-V +; Version: 1.6 +; Generator: Google Clspv; 0 +; Bound: 51 +; Schema: 0 + OpCapability Shader + %43 = OpExtInstImport "NonSemantic.ClspvReflection.5" + OpMemoryModel Logical Vulkan + OpEntryPoint GLCompute %17 "test" %gl_LocalInvocationID %10 %out + OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId + OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize + OpDecorate %_runtimearr_uint ArrayStride 4 + OpMemberDecorate %_struct_12 0 Offset 0 + OpDecorate %_struct_12 Block + OpDecorate %out DescriptorSet 0 + OpDecorate %out Binding 0 + OpDecorate %5 SpecId 0 + OpDecorate %6 SpecId 1 + OpDecorate %7 SpecId 2 + %uint = OpTypeInt 32 0 + %v3uint = OpTypeVector %uint 3 +%_ptr_Input_v3uint = OpTypePointer Input %v3uint + %5 = OpSpecConstant %uint 1 + %6 = OpSpecConstant %uint 1 + %7 = OpSpecConstant %uint 1 +%gl_WorkGroupSize = OpSpecConstantComposite %v3uint %5 %6 %7 +%_ptr_Private_v3uint = OpTypePointer Private %v3uint +%_runtimearr_uint = OpTypeRuntimeArray %uint + %_struct_12 = OpTypeStruct %_runtimearr_uint +%_ptr_StorageBuffer__struct_12 = OpTypePointer StorageBuffer %_struct_12 + %void = OpTypeVoid + %16 = OpTypeFunction %void +%_ptr_Input_uint = OpTypePointer Input %uint + %uint_0 = OpConstant %uint 0 + %bool = OpTypeBool +%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint + %uint_2 = OpConstant %uint 2 + %uint_1 = OpConstant %uint 1 + %false = OpConstantFalse %bool + %true = OpConstantTrue %bool +%gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input + %10 = OpVariable %_ptr_Private_v3uint Private %gl_WorkGroupSize + %out = OpVariable %_ptr_StorageBuffer__struct_12 StorageBuffer + %17 = OpFunction %void None %16 + %18 = OpLabel + %21 = OpAccessChain %_ptr_Input_uint %gl_LocalInvocationID %uint_0 + %22 = OpLoad %uint %21 + %24 = OpINotEqual %bool %22 %uint_0 + OpSelectionMerge %32 None + OpBranchConditional %24 %27 %32 + %27 = OpLabel + %29 = OpAccessChain %_ptr_StorageBuffer_uint %out %uint_0 %22 + OpStore %29 %uint_2 + OpBranch %32 + %32 = OpLabel + %33 = OpPhi %bool %false %27 %true %18 + OpSelectionMerge %40 None + OpBranchConditional %33 %36 %40 + %36 = OpLabel + %37 = OpAccessChain %_ptr_StorageBuffer_uint %out %uint_0 %22 + OpStore %37 %uint_1 + OpBranch %40 + %40 = OpLabel + OpReturn + OpFunctionEnd diff --git a/dartagnan/src/test/resources/spirv/basic/branch-struct-if-inverted.spv.dis b/dartagnan/src/test/resources/spirv/basic/branch-struct-if-inverted.spv.dis new file mode 100644 index 0000000000..a81a46ecff --- /dev/null +++ b/dartagnan/src/test/resources/spirv/basic/branch-struct-if-inverted.spv.dis @@ -0,0 +1,58 @@ +; @Input: %out = {{0, 0}} +; @Output: forall (%out[0][0]==0 and %out[0][1]==1) +; @Config: 2, 1, 1 +; SPIR-V +; Version: 1.6 +; Generator: Google Clspv; 0 +; Bound: 42 +; Schema: 0 + OpCapability Shader + %33 = OpExtInstImport "NonSemantic.ClspvReflection.5" + OpMemoryModel Logical Vulkan + OpEntryPoint GLCompute %17 "test" %gl_LocalInvocationID %10 %out + OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId + OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize + OpDecorate %_runtimearr_uint ArrayStride 4 + OpMemberDecorate %_struct_12 0 Offset 0 + OpDecorate %_struct_12 Block + OpDecorate %out DescriptorSet 0 + OpDecorate %out Binding 0 + OpDecorate %5 SpecId 0 + OpDecorate %6 SpecId 1 + OpDecorate %7 SpecId 2 + %uint = OpTypeInt 32 0 + %v3uint = OpTypeVector %uint 3 +%_ptr_Input_v3uint = OpTypePointer Input %v3uint + %5 = OpSpecConstant %uint 1 + %6 = OpSpecConstant %uint 1 + %7 = OpSpecConstant %uint 1 +%gl_WorkGroupSize = OpSpecConstantComposite %v3uint %5 %6 %7 +%_ptr_Private_v3uint = OpTypePointer Private %v3uint +%_runtimearr_uint = OpTypeRuntimeArray %uint + %_struct_12 = OpTypeStruct %_runtimearr_uint +%_ptr_StorageBuffer__struct_12 = OpTypePointer StorageBuffer %_struct_12 + %void = OpTypeVoid + %16 = OpTypeFunction %void +%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint + %uint_0 = OpConstant %uint 0 +%_ptr_Input_uint = OpTypePointer Input %uint + %bool = OpTypeBool + %uint_1 = OpConstant %uint 1 + %uint_2 = OpConstant %uint 2 +%gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input + %10 = OpVariable %_ptr_Private_v3uint Private %gl_WorkGroupSize + %out = OpVariable %_ptr_StorageBuffer__struct_12 StorageBuffer + %17 = OpFunction %void None %16 + %18 = OpLabel + %23 = OpAccessChain %_ptr_Input_uint %gl_LocalInvocationID %uint_0 + %24 = OpLoad %uint %23 + %21 = OpAccessChain %_ptr_StorageBuffer_uint %out %uint_0 %24 + %26 = OpIEqual %bool %24 %uint_0 + OpSelectionMerge %32 None + OpBranchConditional %26 %32 %29 + %29 = OpLabel + OpStore %21 %uint_1 + OpBranch %32 + %32 = OpLabel + OpReturn + OpFunctionEnd diff --git a/dartagnan/src/test/resources/spirv/basic/branch-struct-if.spv.dis b/dartagnan/src/test/resources/spirv/basic/branch-struct-if.spv.dis new file mode 100644 index 0000000000..f6b9dc3295 --- /dev/null +++ b/dartagnan/src/test/resources/spirv/basic/branch-struct-if.spv.dis @@ -0,0 +1,58 @@ +; @Input: %out = {{0, 0}} +; @Output: forall (%out[0][0]==1 and %out[0][1]==0) +; @Config: 2, 1, 1 +; SPIR-V +; Version: 1.6 +; Generator: Google Clspv; 0 +; Bound: 42 +; Schema: 0 + OpCapability Shader + %33 = OpExtInstImport "NonSemantic.ClspvReflection.5" + OpMemoryModel Logical Vulkan + OpEntryPoint GLCompute %17 "test" %gl_LocalInvocationID %10 %out + OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId + OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize + OpDecorate %_runtimearr_uint ArrayStride 4 + OpMemberDecorate %_struct_12 0 Offset 0 + OpDecorate %_struct_12 Block + OpDecorate %out DescriptorSet 0 + OpDecorate %out Binding 0 + OpDecorate %5 SpecId 0 + OpDecorate %6 SpecId 1 + OpDecorate %7 SpecId 2 + %uint = OpTypeInt 32 0 + %v3uint = OpTypeVector %uint 3 +%_ptr_Input_v3uint = OpTypePointer Input %v3uint + %5 = OpSpecConstant %uint 1 + %6 = OpSpecConstant %uint 1 + %7 = OpSpecConstant %uint 1 +%gl_WorkGroupSize = OpSpecConstantComposite %v3uint %5 %6 %7 +%_ptr_Private_v3uint = OpTypePointer Private %v3uint +%_runtimearr_uint = OpTypeRuntimeArray %uint + %_struct_12 = OpTypeStruct %_runtimearr_uint +%_ptr_StorageBuffer__struct_12 = OpTypePointer StorageBuffer %_struct_12 + %void = OpTypeVoid + %16 = OpTypeFunction %void +%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint + %uint_0 = OpConstant %uint 0 +%_ptr_Input_uint = OpTypePointer Input %uint + %bool = OpTypeBool + %uint_1 = OpConstant %uint 1 + %uint_2 = OpConstant %uint 2 +%gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input + %10 = OpVariable %_ptr_Private_v3uint Private %gl_WorkGroupSize + %out = OpVariable %_ptr_StorageBuffer__struct_12 StorageBuffer + %17 = OpFunction %void None %16 + %18 = OpLabel + %23 = OpAccessChain %_ptr_Input_uint %gl_LocalInvocationID %uint_0 + %24 = OpLoad %uint %23 + %21 = OpAccessChain %_ptr_StorageBuffer_uint %out %uint_0 %24 + %26 = OpIEqual %bool %24 %uint_0 + OpSelectionMerge %32 None + OpBranchConditional %26 %29 %32 + %29 = OpLabel + OpStore %21 %uint_1 + OpBranch %32 + %32 = OpLabel + OpReturn + OpFunctionEnd