Skip to content

Commit 8cd6b4c

Browse files
authored
Merge pull request #630 from OpenVADL/feature/determine-intrinsic-attributes
lcb: Setup intrinsic attributes
2 parents 2295014 + f806854 commit 8cd6b4c

File tree

4 files changed

+236
-0
lines changed

4 files changed

+236
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// SPDX-FileCopyrightText : © 2025 TU Wien <vadl@tuwien.ac.at>
2+
// SPDX-License-Identifier: GPL-3.0-or-later
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
package vadl.gcb.passes;
18+
19+
import java.io.IOException;
20+
import java.util.ArrayList;
21+
import java.util.IdentityHashMap;
22+
import java.util.List;
23+
import java.util.Map;
24+
import java.util.Objects;
25+
import javax.annotation.Nullable;
26+
import vadl.configuration.GcbConfiguration;
27+
import vadl.pass.Pass;
28+
import vadl.pass.PassName;
29+
import vadl.pass.PassResults;
30+
import vadl.viam.Instruction;
31+
import vadl.viam.Specification;
32+
import vadl.viam.graph.Graph;
33+
import vadl.viam.graph.WritesRegisterTensor;
34+
import vadl.viam.graph.dependency.ProcCallNode;
35+
import vadl.viam.graph.dependency.ReadMemNode;
36+
import vadl.viam.graph.dependency.WriteMemNode;
37+
import vadl.viam.passes.SnapshotInstructionBehaviorPass;
38+
39+
/**
40+
* Compute the intrinsic attributes for a {@link Instruction}.
41+
*/
42+
public class DetermineIntrinsicAttributesPass extends Pass {
43+
public DetermineIntrinsicAttributesPass(GcbConfiguration gcbConfiguration) {
44+
super(gcbConfiguration);
45+
}
46+
47+
@Override
48+
public PassName getName() {
49+
return new PassName("DetermineIntrinsicAttributesPass");
50+
}
51+
52+
@Nullable
53+
@Override
54+
public Object execute(PassResults passResults, Specification viam) throws IOException {
55+
var snapshots =
56+
(Map<Instruction, Graph>) passResults.lastResultOf(SnapshotInstructionBehaviorPass.class);
57+
IdentityHashMap<Instruction, List<InstructionIntrinsicAttributesCtx.Attribute>> map =
58+
new IdentityHashMap<>();
59+
60+
for (var instruction : viam.isa().orElseThrow().ownInstructions()) {
61+
var snapshot = Objects.requireNonNull(snapshots.get(instruction));
62+
var isNoMem = isNoMem(snapshot);
63+
var willReturn = willReturn(snapshot);
64+
var speculatable = speculatable(snapshot);
65+
66+
var attributes = new ArrayList<InstructionIntrinsicAttributesCtx.Attribute>();
67+
if (isNoMem) {
68+
attributes.add(InstructionIntrinsicAttributesCtx.Attribute.NoMem);
69+
}
70+
if (willReturn) {
71+
attributes.add(InstructionIntrinsicAttributesCtx.Attribute.WillReturn);
72+
} else {
73+
attributes.add(InstructionIntrinsicAttributesCtx.Attribute.NoReturn);
74+
}
75+
if (speculatable) {
76+
attributes.add(InstructionIntrinsicAttributesCtx.Attribute.Speculatable);
77+
}
78+
79+
map.put(instruction, attributes);
80+
instruction.attachExtension(new InstructionIntrinsicAttributesCtx(attributes));
81+
}
82+
83+
return map;
84+
}
85+
86+
private boolean isMem(Graph snapshot) {
87+
return !snapshot.getNodes(WriteMemNode.class).toList().isEmpty()
88+
|| !snapshot.getNodes(ReadMemNode.class).toList().isEmpty();
89+
}
90+
91+
private boolean isNoMem(Graph snapshot) {
92+
return !isMem(snapshot);
93+
}
94+
95+
private boolean willReturn(Graph snapshot) {
96+
return !snapshot.getNodes(WritesRegisterTensor.class).toList().isEmpty();
97+
}
98+
99+
/**
100+
* Compute a special attribute for LLVM.
101+
* The following conditions must hold:
102+
* x) No side effects
103+
* x) Does not write memory
104+
* x) Does not perform I/O
105+
* x) Does not change global state
106+
* x) Cannot trap or fault
107+
* x) No division-by-zero traps
108+
*/
109+
private boolean speculatable(Graph snapshot) {
110+
return isNoMem(snapshot) && snapshot.getNodes(ProcCallNode.class).toList().isEmpty();
111+
}
112+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// SPDX-FileCopyrightText : © 2025 TU Wien <vadl@tuwien.ac.at>
2+
// SPDX-License-Identifier: GPL-3.0-or-later
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
package vadl.gcb.passes;
18+
19+
import java.util.List;
20+
import vadl.viam.Definition;
21+
import vadl.viam.DefinitionExtension;
22+
import vadl.viam.Instruction;
23+
24+
/**
25+
* An extension for the {@link Instruction}. It will be used to indicate what the attributes for the
26+
* intrinsic of the {@link Instruction} are.
27+
*/
28+
public class InstructionIntrinsicAttributesCtx extends DefinitionExtension<Instruction> {
29+
/**
30+
* Attributes for the intrinsic.
31+
*/
32+
public enum Attribute {
33+
NoMem,
34+
WillReturn,
35+
NoReturn,
36+
Speculatable
37+
}
38+
39+
private final List<Attribute> attributes;
40+
41+
public InstructionIntrinsicAttributesCtx(List<Attribute> attributes) {
42+
this.attributes = attributes;
43+
}
44+
45+
public List<Attribute> getAttributes() {
46+
return attributes;
47+
}
48+
49+
@Override
50+
public Class<? extends Definition> extendsDefClass() {
51+
return Definition.class;
52+
}
53+
}

vadl/main/vadl/pass/PassOrders.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import vadl.configuration.RtlConfiguration;
3333
import vadl.dump.CollectBehaviorDotGraphPass;
3434
import vadl.dump.HtmlDumpPass;
35+
import vadl.gcb.passes.DetermineIntrinsicAttributesPass;
3536
import vadl.gcb.passes.DetermineRegisterUsesAndDefsPass;
3637
import vadl.gcb.passes.DetermineRelocationTypeForFieldPass;
3738
import vadl.gcb.passes.GenerateCompilerRegistersPass;
@@ -259,6 +260,7 @@ public static PassOrder gcbAndCppCodeGen(GcbConfiguration gcbConfiguration) thro
259260
order.add(new DetermineRegisterUsesAndDefsPass(gcbConfiguration));
260261
order.add(new GenerateInstructionOperandsPass(gcbConfiguration));
261262
order.add(new InstructionPatternPruningPass(gcbConfiguration));
263+
order.add(new DetermineIntrinsicAttributesPass(gcbConfiguration));
262264

263265
addHtmlDump(order, gcbConfiguration, "gcbProcessing",
264266
"Now the gcb produced all necessary encoding function for field accesses "
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// SPDX-FileCopyrightText : © 2025 TU Wien <vadl@tuwien.ac.at>
2+
// SPDX-License-Identifier: GPL-3.0-or-later
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
package vadl.gcb.riscv.riscv64.passes;
18+
19+
import static vadl.gcb.passes.InstructionIntrinsicAttributesCtx.Attribute.NoMem;
20+
import static vadl.gcb.passes.InstructionIntrinsicAttributesCtx.Attribute.Speculatable;
21+
import static vadl.gcb.passes.InstructionIntrinsicAttributesCtx.Attribute.WillReturn;
22+
23+
import java.io.IOException;
24+
import java.util.List;
25+
import java.util.Map;
26+
import java.util.stream.Collectors;
27+
import java.util.stream.Stream;
28+
import org.junit.jupiter.api.Assertions;
29+
import org.junit.jupiter.params.ParameterizedTest;
30+
import org.junit.jupiter.params.provider.Arguments;
31+
import org.junit.jupiter.params.provider.MethodSource;
32+
import vadl.gcb.AbstractGcbTest;
33+
import vadl.gcb.passes.DetermineIntrinsicAttributesPass;
34+
import vadl.gcb.passes.InstructionIntrinsicAttributesCtx;
35+
import vadl.pass.PassKey;
36+
import vadl.pass.exception.DuplicatedPassKeyException;
37+
import vadl.viam.Instruction;
38+
39+
public class DetermineIntrinsicAttributesPassTest extends AbstractGcbTest {
40+
public static Stream<Arguments> expected() {
41+
return Stream.of(
42+
Arguments.of("ADD", List.of(NoMem, WillReturn, Speculatable)),
43+
Arguments.of("SUB", List.of(NoMem, WillReturn, Speculatable)),
44+
Arguments.of("MUL", List.of(NoMem, WillReturn, Speculatable))
45+
);
46+
}
47+
48+
@MethodSource(value = "expected")
49+
@ParameterizedTest
50+
void shouldDetect(String instructionName,
51+
List<InstructionIntrinsicAttributesCtx.Attribute> attrs)
52+
throws DuplicatedPassKeyException, IOException {
53+
// Given
54+
var setup = runGcb(getConfiguration(false), "sys/risc-v/rv64im.vadl",
55+
new PassKey(DetermineIntrinsicAttributesPassTest.class.getName()));
56+
var passManager = setup.passManager();
57+
58+
// When
59+
var result =
60+
((Map<Instruction, List<InstructionIntrinsicAttributesCtx.Attribute>>) passManager.getPassResults()
61+
.lastResultOf(DetermineIntrinsicAttributesPass.class)).entrySet().stream().collect(
62+
Collectors.toMap(x -> x.getKey().simpleName(), Map.Entry::getValue));
63+
64+
// Then
65+
Assertions.assertNotNull(result);
66+
Assertions.assertNotNull(result.get(instructionName));
67+
Assertions.assertEquals(result.get(instructionName), attrs);
68+
}
69+
}

0 commit comments

Comments
 (0)