a426b286c8
patch for r263619, and unify all the URLs to point to svnweb.
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 {
|