143 lines
4.8 KiB
Diff
143 lines
4.8 KiB
Diff
Pull in r199781 from upstream llvm trunk (by Venkatraman Govindaraju):
|
|
|
|
[Sparc] Add support for inline assembly constraint 'I'.
|
|
|
|
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
|
|
|
Index: test/CodeGen/SPARC/inlineasm.ll
|
|
===================================================================
|
|
--- test/CodeGen/SPARC/inlineasm.ll
|
|
+++ test/CodeGen/SPARC/inlineasm.ll
|
|
@@ -0,0 +1,35 @@
|
|
+; RUN: llc -march=sparc <%s | FileCheck %s
|
|
+
|
|
+; CHECK-LABEL: test_constraint_r
|
|
+; CHECK: add %o1, %o0, %o0
|
|
+define i32 @test_constraint_r(i32 %a, i32 %b) {
|
|
+entry:
|
|
+ %0 = tail call i32 asm sideeffect "add $2, $1, $0", "=r,r,r"(i32 %a, i32 %b)
|
|
+ ret i32 %0
|
|
+}
|
|
+
|
|
+; CHECK-LABEL: test_constraint_I
|
|
+; CHECK: add %o0, 1023, %o0
|
|
+define i32 @test_constraint_I(i32 %a) {
|
|
+entry:
|
|
+ %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 1023)
|
|
+ ret i32 %0
|
|
+}
|
|
+
|
|
+; CHECK-LABEL: test_constraint_I_neg
|
|
+; CHECK: add %o0, -4096, %o0
|
|
+define i32 @test_constraint_I_neg(i32 %a) {
|
|
+entry:
|
|
+ %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 -4096)
|
|
+ ret i32 %0
|
|
+}
|
|
+
|
|
+; CHECK-LABEL: test_constraint_I_largeimm
|
|
+; CHECK: sethi 9, [[R0:%[gilo][0-7]]]
|
|
+; CHECK: or [[R0]], 784, [[R1:%[gilo][0-7]]]
|
|
+; CHECK: add %o0, [[R1]], %o0
|
|
+define i32 @test_constraint_I_largeimm(i32 %a) {
|
|
+entry:
|
|
+ %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 10000)
|
|
+ ret i32 %0
|
|
+}
|
|
Index: lib/Target/Sparc/SparcISelLowering.h
|
|
===================================================================
|
|
--- lib/Target/Sparc/SparcISelLowering.h
|
|
+++ lib/Target/Sparc/SparcISelLowering.h
|
|
@@ -73,6 +73,13 @@ namespace llvm {
|
|
virtual const char *getTargetNodeName(unsigned Opcode) const;
|
|
|
|
ConstraintType getConstraintType(const std::string &Constraint) const;
|
|
+ ConstraintWeight
|
|
+ getSingleConstraintMatchWeight(AsmOperandInfo &info,
|
|
+ const char *constraint) const;
|
|
+ void LowerAsmOperandForConstraint(SDValue Op,
|
|
+ std::string &Constraint,
|
|
+ std::vector<SDValue> &Ops,
|
|
+ SelectionDAG &DAG) const;
|
|
std::pair<unsigned, const TargetRegisterClass*>
|
|
getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const;
|
|
|
|
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
|
===================================================================
|
|
--- lib/Target/Sparc/SparcISelLowering.cpp
|
|
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
|
@@ -2918,6 +2918,8 @@ SparcTargetLowering::getConstraintType(const std::
|
|
switch (Constraint[0]) {
|
|
default: break;
|
|
case 'r': return C_RegisterClass;
|
|
+ case 'I': // SIMM13
|
|
+ return C_Other;
|
|
}
|
|
}
|
|
|
|
@@ -2924,6 +2926,64 @@ SparcTargetLowering::getConstraintType(const std::
|
|
return TargetLowering::getConstraintType(Constraint);
|
|
}
|
|
|
|
+TargetLowering::ConstraintWeight SparcTargetLowering::
|
|
+getSingleConstraintMatchWeight(AsmOperandInfo &info,
|
|
+ const char *constraint) const {
|
|
+ ConstraintWeight weight = CW_Invalid;
|
|
+ Value *CallOperandVal = info.CallOperandVal;
|
|
+ // If we don't have a value, we can't do a match,
|
|
+ // but allow it at the lowest weight.
|
|
+ if (CallOperandVal == NULL)
|
|
+ return CW_Default;
|
|
+
|
|
+ // Look at the constraint type.
|
|
+ switch (*constraint) {
|
|
+ default:
|
|
+ weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
|
|
+ break;
|
|
+ case 'I': // SIMM13
|
|
+ if (ConstantInt *C = dyn_cast<ConstantInt>(info.CallOperandVal)) {
|
|
+ if (isInt<13>(C->getSExtValue()))
|
|
+ weight = CW_Constant;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ return weight;
|
|
+}
|
|
+
|
|
+/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
|
|
+/// vector. If it is invalid, don't add anything to Ops.
|
|
+void SparcTargetLowering::
|
|
+LowerAsmOperandForConstraint(SDValue Op,
|
|
+ std::string &Constraint,
|
|
+ std::vector<SDValue> &Ops,
|
|
+ SelectionDAG &DAG) const {
|
|
+ SDValue Result(0, 0);
|
|
+
|
|
+ // Only support length 1 constraints for now.
|
|
+ if (Constraint.length() > 1)
|
|
+ return;
|
|
+
|
|
+ char ConstraintLetter = Constraint[0];
|
|
+ switch (ConstraintLetter) {
|
|
+ default: break;
|
|
+ case 'I':
|
|
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
|
|
+ if (isInt<13>(C->getSExtValue())) {
|
|
+ Result = DAG.getTargetConstant(C->getSExtValue(), Op.getValueType());
|
|
+ break;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (Result.getNode()) {
|
|
+ Ops.push_back(Result);
|
|
+ return;
|
|
+ }
|
|
+ TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
|
|
+}
|
|
+
|
|
std::pair<unsigned, const TargetRegisterClass*>
|
|
SparcTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
|
|
MVT VT) const {
|