Skip to content

Commit 61cd679

Browse files
authored
lcb: Created custom lowerings to emit a pair CMP + B.cond (#487)
* lcb: Fixed matching for status registers * lcb: Setup ISelLowering to lower cmp + branch * lcb: Refactored code * lcb: Implemented more status register matchings * temp * lcb: Use underlying field name to avoid generation of duplicated fields * lcb: Added additional branch instructions * lcb: Added matching for SUBS * lcb: Set branches in lowerBR_CC * lcb: Set SUBS automatically based on architecture * lcb: Added branch instructions for BR_CC * lcb: Expand LlvmSMulSD into smul_lohi * lcb: Disabled test * chore: Fixed build * chore: Fixed build * chore: Make CheckStyle happy * lcb: Updated test * lcb: Updated tests * lcb: Updated test * ci: Enable logging * Revert "ci: Enable logging" This reverts commit b22652c. * ci: Enabled logging * Revert "ci: Enabled logging" This reverts commit 6fd5e9d. * lcb: Set `mergedCmpAndBranch` * lcb: Updated test
1 parent f0a6dc0 commit 61cd679

File tree

15 files changed

+710
-259
lines changed

15 files changed

+710
-259
lines changed

vadl/main/resources/templates/lcb/llvm/lib/Target/ISelLowering.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ void [(${namespace})]TargetLowering::anchor() {}
6464
setLoadExtAction(N, MVT::[(${stackPointerType})], MVT::i1, Promote);
6565
}
6666

67+
[#th:block th:if="${mergedCmpAndBranch}"]
68+
setOperationAction(ISD::BRCOND, MVT::Other, Expand);
69+
setOperationAction(ISD::BR_CC, MVT::[(${stackPointerType})], Custom);
70+
[/th:block]
71+
6772
setBooleanContents(ZeroOrOneBooleanContent);
6873

6974
// Compute derived properties from the register classes
@@ -87,6 +92,44 @@ const char *[(${namespace})]TargetLowering::getTargetNodeName(unsigned Opcode) c
8792
}
8893
}
8994

95+
[#th:block th:if="${mergedCmpAndBranch}"]
96+
static SDValue lowerBR_CC(SDValue Op, SelectionDAG &DAG) {
97+
SDValue Chain = Op.getOperand(0);
98+
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
99+
SDValue LHS = Op.getOperand(2);
100+
SDValue RHS = Op.getOperand(3);
101+
SDValue Dest = Op.getOperand(4);
102+
SDLoc dl(Op);
103+
104+
auto Sub = DAG.getMachineNode([(${namespace})]::[(${SUBS})], dl, { MVT::i64, MVT::Other }, {LHS, RHS, Chain});
105+
SDValue ConditionFlag = SDValue(Sub, 1);
106+
107+
switch(CC) {
108+
case ISD::CondCode::SETEQ:
109+
return SDValue(DAG.getMachineNode([(${namespace})]::[(${B_EQ})], dl, MVT::Other, Dest, ConditionFlag), 0);
110+
break;
111+
case ISD::CondCode::SETNE:
112+
return SDValue(DAG.getMachineNode([(${namespace})]::[(${B_NEQ})], dl, MVT::Other, Dest, ConditionFlag), 0);
113+
break;
114+
case ISD::CondCode::SETLT:
115+
return SDValue(DAG.getMachineNode([(${namespace})]::[(${B_LT})], dl, MVT::Other, Dest, ConditionFlag), 0);
116+
break;
117+
case ISD::CondCode::SETLE:
118+
return SDValue(DAG.getMachineNode([(${namespace})]::[(${B_LE})], dl, MVT::Other, Dest, ConditionFlag), 0);
119+
break;
120+
case ISD::CondCode::SETGT:
121+
return SDValue(DAG.getMachineNode([(${namespace})]::[(${B_GT})], dl, MVT::Other, Dest, ConditionFlag), 0);
122+
break;
123+
case ISD::CondCode::SETGE:
124+
return SDValue(DAG.getMachineNode([(${namespace})]::[(${B_GE})], dl, MVT::Other, Dest, ConditionFlag), 0);
125+
break;
126+
default:
127+
llvm_unreachable("unimplemented operand");
128+
}
129+
}
130+
131+
[/th:block]
132+
90133
SDValue [(${namespace})]TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const
91134
{
92135
switch (Op.getOpcode())
@@ -109,6 +152,10 @@ SDValue [(${namespace})]TargetLowering::LowerOperation(SDValue Op, SelectionDAG
109152
case ISD::SELECT:
110153
return lowerSelect(Op, DAG);
111154
[/th:block]
155+
[#th:block th:if="${mergedCmpAndBranch}"]
156+
case ISD::BR_CC:
157+
return lowerBR_CC(Op, DAG);
158+
[/th:block]
112159
default : llvm_unreachable("unimplemented operand");
113160
}
114161
}

vadl/main/vadl/gcb/passes/IsaMatchingUtils.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,26 @@
2525
import java.util.Set;
2626
import java.util.stream.Collectors;
2727
import java.util.stream.Stream;
28+
import vadl.gcb.annotations.StatusRegisterAnnotation;
2829
import vadl.gcb.valuetypes.RelocationCtx;
2930
import vadl.gcb.valuetypes.RelocationFunctionLabel;
3031
import vadl.lcb.passes.isaMatching.IsaMachineInstructionMatchingPass;
3132
import vadl.lcb.passes.isaMatching.IsaPseudoInstructionMatchingPass;
33+
import vadl.types.BitsType;
3234
import vadl.types.BuiltInTable;
35+
import vadl.types.TupleType;
3336
import vadl.types.Type;
3437
import vadl.viam.Instruction;
3538
import vadl.viam.PseudoInstruction;
3639
import vadl.viam.Relocation;
3740
import vadl.viam.Specification;
41+
import vadl.viam.graph.Graph;
42+
import vadl.viam.graph.WritesRegisterTensor;
43+
import vadl.viam.graph.control.IfNode;
3844
import vadl.viam.graph.dependency.BuiltInCall;
3945
import vadl.viam.graph.dependency.ReadMemNode;
4046
import vadl.viam.graph.dependency.ReadRegTensorNode;
47+
import vadl.viam.graph.dependency.SliceNode;
4148
import vadl.viam.graph.dependency.WriteMemNode;
4249
import vadl.viam.graph.dependency.WriteRegTensorNode;
4350
import vadl.viam.matching.Matcher;
@@ -137,6 +144,55 @@ default boolean findRegisterImmediateOrImmediateRegister(UninlinedGraph behavior
137144
return !matched.isEmpty() && writesExactlyOneRegisterClass(behavior) && noPcAccess(behavior);
138145
}
139146

147+
/**
148+
* Find an instruction which acts as subtraction but also sets the flags.
149+
*
150+
* @param behavior is a modified but uninlined graph.
151+
* @param original is the original VIAM.
152+
* @param ty is the type of the result.
153+
*/
154+
default boolean findSubS(UninlinedGraph behavior, Graph original, BitsType ty) {
155+
var writes =
156+
original.getNodes(WritesRegisterTensor.class).toList();
157+
158+
var hasNegative = false;
159+
var hasOverflow = false;
160+
var hasZero = false;
161+
var hasCarry = false;
162+
163+
for (var write : writes) {
164+
var tensor = write.registerTensor();
165+
if (tensor.hasAnnotation(StatusRegisterAnnotation.NegativeStatusRegisterAnnotation.class)) {
166+
hasNegative = true;
167+
} else if (tensor.hasAnnotation(
168+
StatusRegisterAnnotation.ZeroStatusRegisterAnnotation.class)) {
169+
hasZero = true;
170+
} else if (tensor.hasAnnotation(
171+
StatusRegisterAnnotation.CarryStatusRegisterAnnotation.class)) {
172+
hasCarry = true;
173+
} else if (tensor.hasAnnotation(
174+
StatusRegisterAnnotation.OverflowStatusRegisterAnnotation.class)) {
175+
hasOverflow = true;
176+
}
177+
}
178+
179+
var matched = TreeMatcher.matches(behavior.getNodes(BuiltInCall.class).map(x -> x),
180+
new BuiltInMatcher(List.of(BuiltInTable.SUBSC), List.of(
181+
new AnyChildMatcher(new AnyReadRegisterFileMatcher()),
182+
new AnyChildMatcher(new AnyReadRegisterFileMatcher())
183+
)));
184+
185+
return !matched.isEmpty()
186+
&& ((TupleType) ((BuiltInCall) matched.getFirst()).type()).first().equals(ty)
187+
&& behavior.getNodes(Set.of(IfNode.class, SliceNode.class)).toList().isEmpty()
188+
&& behavior.getNodes(BuiltInCall.class).toList().size() == 1
189+
&& noPcAccess(behavior)
190+
&& hasNegative
191+
&& hasOverflow
192+
&& hasZero
193+
&& hasCarry;
194+
}
195+
140196
/**
141197
* Return {@code true} if there is only one side effect which writes a register file.
142198
*/

vadl/main/vadl/gcb/passes/MachineInstructionLabel.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public enum MachineInstructionLabel {
4040
OR,
4141
ORI,
4242
SUB,
43+
SUB_RR_WITH_STATUS_REGISTER_64, // subtraction (register register) and sets status flags
44+
SUB_RR_WITH_STATUS_REGISTER_32, // subtraction (register register) and sets status flags
4345
MUL,
4446
SUBB,
4547
SUBC,
@@ -82,6 +84,12 @@ public enum MachineInstructionLabel {
8284
BULEQ,
8385
BULTH,
8486
BUGTH,
87+
BEQ_BY_STATUS_REGISTER,
88+
BNEQ_BY_STATUS_REGISTER,
89+
BSGEQ_BY_STATUS_REGISTER,
90+
BSLEQ_BY_STATUS_REGISTER,
91+
BSLTH_BY_STATUS_REGISTER,
92+
BSGTH_BY_STATUS_REGISTER,
8593
/*
8694
UNCONDITIONAL JUMPS
8795
*/

vadl/main/vadl/lcb/codegen/expansion/CompilerInstructionExpansionCodeGenerator.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static vadl.error.DiagUtils.throwNotAllowed;
2121
import static vadl.lcb.codegen.expansion.CompilerInstructionExpansionCodeGenerator.COMPILER_INSTRUCTION;
2222
import static vadl.lcb.codegen.expansion.CompilerInstructionExpansionCodeGenerator.INSTRUCTION_SYMBOL;
23+
import static vadl.lcb.codegen.expansion.CompilerInstructionExpansionCodeGenerator.canonicalizeField;
2324
import static vadl.viam.ViamError.ensure;
2425
import static vadl.viam.ViamError.ensureNonNull;
2526
import static vadl.viam.ViamError.ensurePresent;
@@ -381,7 +382,7 @@ private List<Pair<Either<Format.Field, Format.FieldAccess>, ExpressionNode>> reo
381382
* We need to map them back from {@link RenamedField} to {@link Format.Field}, so the lookup
382383
* works.
383384
*/
384-
private Format.Field canonicalizeField(Format.Field field) {
385+
static Format.Field canonicalizeField(Format.Field field) {
385386
if (field instanceof RenamedField renamedField) {
386387
// rd_0 drops to rd
387388
return renamedField.inner();
@@ -695,7 +696,8 @@ public void fieldUsedAsRegisterAndExpressionFuncParamNode(CNodeWithBaggageContex
695696
var pseudoInstructionIndex =
696697
getOperandIndexFromCompilerInstruction(compilerInstruction, field, funcParamNode,
697698
funcParamNode.parameter().identifier);
698-
ctx.ln("%s = instruction.getOperand(%d).getReg();", field.identifier.simpleName(),
699+
ctx.ln("%s = instruction.getOperand(%d).getReg();",
700+
canonicalizeField(field).identifier.simpleName(),
699701
pseudoInstructionIndex);
700702
}
701703

@@ -712,7 +714,10 @@ public void fieldUsedAsImmediateAndFieldAssignmentAndExpressionConstant(
712714
CNodeWithBaggageContext ctx, InstrCallNode instrCallNode, Format.Field field,
713715
ConstantNode cn) {
714716
var value = cn.constant().asVal().intValue();
715-
ctx.ln("%s = %s;", field.identifier.simpleName(), value);
717+
ctx.ln("%s = %s; // %s",
718+
canonicalizeField(field).identifier.simpleName(),
719+
value,
720+
field.identifier.simpleName());
716721
}
717722

718723
@Override
@@ -724,8 +729,10 @@ public void fieldUsedAsImmediateAndFieldAssignmentAndExpressionFuncParamNode(
724729
funcParamNode.parameter().identifier);
725730
ctx.ln("if(instruction.getOperand(%d).isImm()) {", pseudoInstructionIndex)
726731
.spacedIn()
727-
.ln("%s = instruction.getOperand(%d).getImm();", field.identifier.simpleName(),
728-
pseudoInstructionIndex)
732+
.ln("%s = instruction.getOperand(%d).getImm(); // %s",
733+
canonicalizeField(field).identifier.simpleName(),
734+
pseudoInstructionIndex,
735+
field.identifier.simpleName())
729736
.spaceOut()
730737
.ln("}");
731738
}
@@ -742,8 +749,10 @@ public void fieldUsedAsImmediateAndFieldAssignmentAndExpressionFuncCallNode(
742749

743750
ctx.ln("if(instruction.getOperand(%d).isImm()) {", pseudoInstructionIndex)
744751
.spacedIn()
745-
.ln("%s = instruction.getOperand(%d).getImm();", field.identifier.simpleName(),
746-
pseudoInstructionIndex)
752+
.ln("%s = instruction.getOperand(%d).getImm(); // %s",
753+
canonicalizeField(field).identifier.simpleName(),
754+
pseudoInstructionIndex,
755+
field.identifier.simpleName())
747756
.spaceOut()
748757
.ln("}");
749758
}
@@ -762,7 +771,8 @@ public void fieldUsedAsImmediateAndFieldAssignmentAndArbitraryExpression(
762771
getOperandIndexFromCompilerInstruction(compilerInstruction, field,
763772
funcParamNode,
764773
funcParamNode.parameter().identifier);
765-
ctx.ln("%s = instruction.getOperand(%d).getImm();", field.identifier.simpleName(),
774+
ctx.ln("%s = instruction.getOperand(%d).getImm();",
775+
canonicalizeField(field).identifier.simpleName(),
766776
pseudoInstructionIndex);
767777
}
768778

0 commit comments

Comments
 (0)