applied to our copy of llvm/clang. These can be applied in alphabetical order to a pristine llvm/clang 3.4 release source tree, to result in the same version used in FreeBSD. This is intended to clearly document all the changes until now, which mostly consist of cherry pickings from the respective upstream trunks, plus a number of hand-written FreeBSD-specific ones. Hopefully those can eventually be cleaned up and sent upstream too. MFC after: 1 week X-MFC-With: r263313
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://svn.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 {
|