summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/patches/patch-r262261-llvm-r199781-sparc.diff
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/patches/patch-r262261-llvm-r199781-sparc.diff')
-rw-r--r--contrib/llvm/patches/patch-r262261-llvm-r199781-sparc.diff142
1 files changed, 142 insertions, 0 deletions
diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199781-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199781-sparc.diff
new file mode 100644
index 0000000..0417410
--- /dev/null
+++ b/contrib/llvm/patches/patch-r262261-llvm-r199781-sparc.diff
@@ -0,0 +1,142 @@
+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 {
OpenPOWER on IntegriCloud