freebsd-dev/contrib/llvm/patches/patch-r262261-llvm-r199781-sparc.diff
Dimitry Andric a1f8ad145e Add separate patch files for all the customizations we have currently
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
2014-03-18 22:07:45 +00:00

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 {