1263320SdimPull in r199781 from upstream llvm trunk (by Venkatraman Govindaraju):
2263320Sdim
3263320Sdim  [Sparc] Add support for inline assembly constraint 'I'.
4263320Sdim
5263320SdimIntroduced here: http://svn.freebsd.org/changeset/base/262261
6263320Sdim
7263320SdimIndex: test/CodeGen/SPARC/inlineasm.ll
8263320Sdim===================================================================
9263320Sdim--- test/CodeGen/SPARC/inlineasm.ll
10263320Sdim+++ test/CodeGen/SPARC/inlineasm.ll
11263320Sdim@@ -0,0 +1,35 @@
12263320Sdim+; RUN: llc -march=sparc <%s | FileCheck %s
13263320Sdim+
14263320Sdim+; CHECK-LABEL: test_constraint_r
15263320Sdim+; CHECK:       add %o1, %o0, %o0
16263320Sdim+define i32 @test_constraint_r(i32 %a, i32 %b) {
17263320Sdim+entry:
18263320Sdim+  %0 = tail call i32 asm sideeffect "add $2, $1, $0", "=r,r,r"(i32 %a, i32 %b)
19263320Sdim+  ret i32 %0
20263320Sdim+}
21263320Sdim+
22263320Sdim+; CHECK-LABEL: test_constraint_I
23263320Sdim+; CHECK:       add %o0, 1023, %o0
24263320Sdim+define i32 @test_constraint_I(i32 %a) {
25263320Sdim+entry:
26263320Sdim+  %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 1023)
27263320Sdim+  ret i32 %0
28263320Sdim+}
29263320Sdim+
30263320Sdim+; CHECK-LABEL: test_constraint_I_neg
31263320Sdim+; CHECK:       add %o0, -4096, %o0
32263320Sdim+define i32 @test_constraint_I_neg(i32 %a) {
33263320Sdim+entry:
34263320Sdim+  %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 -4096)
35263320Sdim+  ret i32 %0
36263320Sdim+}
37263320Sdim+
38263320Sdim+; CHECK-LABEL: test_constraint_I_largeimm
39263320Sdim+; CHECK:       sethi 9, [[R0:%[gilo][0-7]]]
40263320Sdim+; CHECK:       or [[R0]], 784, [[R1:%[gilo][0-7]]]
41263320Sdim+; CHECK:       add %o0, [[R1]], %o0
42263320Sdim+define i32 @test_constraint_I_largeimm(i32 %a) {
43263320Sdim+entry:
44263320Sdim+  %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 10000)
45263320Sdim+  ret i32 %0
46263320Sdim+}
47263320SdimIndex: lib/Target/Sparc/SparcISelLowering.h
48263320Sdim===================================================================
49263320Sdim--- lib/Target/Sparc/SparcISelLowering.h
50263320Sdim+++ lib/Target/Sparc/SparcISelLowering.h
51263320Sdim@@ -73,6 +73,13 @@ namespace llvm {
52263320Sdim     virtual const char *getTargetNodeName(unsigned Opcode) const;
53263320Sdim 
54263320Sdim     ConstraintType getConstraintType(const std::string &Constraint) const;
55263320Sdim+    ConstraintWeight
56263320Sdim+    getSingleConstraintMatchWeight(AsmOperandInfo &info,
57263320Sdim+                                   const char *constraint) const;
58263320Sdim+    void LowerAsmOperandForConstraint(SDValue Op,
59263320Sdim+                                      std::string &Constraint,
60263320Sdim+                                      std::vector<SDValue> &Ops,
61263320Sdim+                                      SelectionDAG &DAG) const;
62263320Sdim     std::pair<unsigned, const TargetRegisterClass*>
63263320Sdim     getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const;
64263320Sdim 
65263320SdimIndex: lib/Target/Sparc/SparcISelLowering.cpp
66263320Sdim===================================================================
67263320Sdim--- lib/Target/Sparc/SparcISelLowering.cpp
68263320Sdim+++ lib/Target/Sparc/SparcISelLowering.cpp
69263320Sdim@@ -2918,6 +2918,8 @@ SparcTargetLowering::getConstraintType(const std::
70263320Sdim     switch (Constraint[0]) {
71263320Sdim     default:  break;
72263320Sdim     case 'r': return C_RegisterClass;
73263320Sdim+    case 'I': // SIMM13
74263320Sdim+      return C_Other;
75263320Sdim     }
76263320Sdim   }
77263320Sdim 
78263320Sdim@@ -2924,6 +2926,64 @@ SparcTargetLowering::getConstraintType(const std::
79263320Sdim   return TargetLowering::getConstraintType(Constraint);
80263320Sdim }
81263320Sdim 
82263320Sdim+TargetLowering::ConstraintWeight SparcTargetLowering::
83263320Sdim+getSingleConstraintMatchWeight(AsmOperandInfo &info,
84263320Sdim+                               const char *constraint) const {
85263320Sdim+  ConstraintWeight weight = CW_Invalid;
86263320Sdim+  Value *CallOperandVal = info.CallOperandVal;
87263320Sdim+  // If we don't have a value, we can't do a match,
88263320Sdim+  // but allow it at the lowest weight.
89263320Sdim+  if (CallOperandVal == NULL)
90263320Sdim+    return CW_Default;
91263320Sdim+
92263320Sdim+  // Look at the constraint type.
93263320Sdim+  switch (*constraint) {
94263320Sdim+  default:
95263320Sdim+    weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
96263320Sdim+    break;
97263320Sdim+  case 'I': // SIMM13
98263320Sdim+    if (ConstantInt *C = dyn_cast<ConstantInt>(info.CallOperandVal)) {
99263320Sdim+      if (isInt<13>(C->getSExtValue()))
100263320Sdim+        weight = CW_Constant;
101263320Sdim+    }
102263320Sdim+    break;
103263320Sdim+  }
104263320Sdim+  return weight;
105263320Sdim+}
106263320Sdim+
107263320Sdim+/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
108263320Sdim+/// vector.  If it is invalid, don't add anything to Ops.
109263320Sdim+void SparcTargetLowering::
110263320Sdim+LowerAsmOperandForConstraint(SDValue Op,
111263320Sdim+                             std::string &Constraint,
112263320Sdim+                             std::vector<SDValue> &Ops,
113263320Sdim+                             SelectionDAG &DAG) const {
114263320Sdim+  SDValue Result(0, 0);
115263320Sdim+
116263320Sdim+  // Only support length 1 constraints for now.
117263320Sdim+  if (Constraint.length() > 1)
118263320Sdim+    return;
119263320Sdim+
120263320Sdim+  char ConstraintLetter = Constraint[0];
121263320Sdim+  switch (ConstraintLetter) {
122263320Sdim+  default: break;
123263320Sdim+  case 'I':
124263320Sdim+    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
125263320Sdim+      if (isInt<13>(C->getSExtValue())) {
126263320Sdim+        Result = DAG.getTargetConstant(C->getSExtValue(), Op.getValueType());
127263320Sdim+        break;
128263320Sdim+      }
129263320Sdim+      return;
130263320Sdim+    }
131263320Sdim+  }
132263320Sdim+
133263320Sdim+  if (Result.getNode()) {
134263320Sdim+    Ops.push_back(Result);
135263320Sdim+    return;
136263320Sdim+  }
137263320Sdim+  TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
138263320Sdim+}
139263320Sdim+
140263320Sdim std::pair<unsigned, const TargetRegisterClass*>
141263320Sdim SparcTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
142263320Sdim                                                   MVT VT) const {
143