patch-r262261-llvm-r199781-sparc.diff revision 269012
1Pull in r199781 from upstream llvm trunk (by Venkatraman Govindaraju):
2
3  [Sparc] Add support for inline assembly constraint 'I'.
4
5Introduced here: http://svnweb.freebsd.org/changeset/base/262261
6
7Index: test/CodeGen/SPARC/inlineasm.ll
8===================================================================
9--- test/CodeGen/SPARC/inlineasm.ll
10+++ test/CodeGen/SPARC/inlineasm.ll
11@@ -0,0 +1,35 @@
12+; RUN: llc -march=sparc <%s | FileCheck %s
13+
14+; CHECK-LABEL: test_constraint_r
15+; CHECK:       add %o1, %o0, %o0
16+define i32 @test_constraint_r(i32 %a, i32 %b) {
17+entry:
18+  %0 = tail call i32 asm sideeffect "add $2, $1, $0", "=r,r,r"(i32 %a, i32 %b)
19+  ret i32 %0
20+}
21+
22+; CHECK-LABEL: test_constraint_I
23+; CHECK:       add %o0, 1023, %o0
24+define i32 @test_constraint_I(i32 %a) {
25+entry:
26+  %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 1023)
27+  ret i32 %0
28+}
29+
30+; CHECK-LABEL: test_constraint_I_neg
31+; CHECK:       add %o0, -4096, %o0
32+define i32 @test_constraint_I_neg(i32 %a) {
33+entry:
34+  %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 -4096)
35+  ret i32 %0
36+}
37+
38+; CHECK-LABEL: test_constraint_I_largeimm
39+; CHECK:       sethi 9, [[R0:%[gilo][0-7]]]
40+; CHECK:       or [[R0]], 784, [[R1:%[gilo][0-7]]]
41+; CHECK:       add %o0, [[R1]], %o0
42+define i32 @test_constraint_I_largeimm(i32 %a) {
43+entry:
44+  %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 10000)
45+  ret i32 %0
46+}
47Index: lib/Target/Sparc/SparcISelLowering.h
48===================================================================
49--- lib/Target/Sparc/SparcISelLowering.h
50+++ lib/Target/Sparc/SparcISelLowering.h
51@@ -73,6 +73,13 @@ namespace llvm {
52     virtual const char *getTargetNodeName(unsigned Opcode) const;
53 
54     ConstraintType getConstraintType(const std::string &Constraint) const;
55+    ConstraintWeight
56+    getSingleConstraintMatchWeight(AsmOperandInfo &info,
57+                                   const char *constraint) const;
58+    void LowerAsmOperandForConstraint(SDValue Op,
59+                                      std::string &Constraint,
60+                                      std::vector<SDValue> &Ops,
61+                                      SelectionDAG &DAG) const;
62     std::pair<unsigned, const TargetRegisterClass*>
63     getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const;
64 
65Index: lib/Target/Sparc/SparcISelLowering.cpp
66===================================================================
67--- lib/Target/Sparc/SparcISelLowering.cpp
68+++ lib/Target/Sparc/SparcISelLowering.cpp
69@@ -2918,6 +2918,8 @@ SparcTargetLowering::getConstraintType(const std::
70     switch (Constraint[0]) {
71     default:  break;
72     case 'r': return C_RegisterClass;
73+    case 'I': // SIMM13
74+      return C_Other;
75     }
76   }
77 
78@@ -2924,6 +2926,64 @@ SparcTargetLowering::getConstraintType(const std::
79   return TargetLowering::getConstraintType(Constraint);
80 }
81 
82+TargetLowering::ConstraintWeight SparcTargetLowering::
83+getSingleConstraintMatchWeight(AsmOperandInfo &info,
84+                               const char *constraint) const {
85+  ConstraintWeight weight = CW_Invalid;
86+  Value *CallOperandVal = info.CallOperandVal;
87+  // If we don't have a value, we can't do a match,
88+  // but allow it at the lowest weight.
89+  if (CallOperandVal == NULL)
90+    return CW_Default;
91+
92+  // Look at the constraint type.
93+  switch (*constraint) {
94+  default:
95+    weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
96+    break;
97+  case 'I': // SIMM13
98+    if (ConstantInt *C = dyn_cast<ConstantInt>(info.CallOperandVal)) {
99+      if (isInt<13>(C->getSExtValue()))
100+        weight = CW_Constant;
101+    }
102+    break;
103+  }
104+  return weight;
105+}
106+
107+/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
108+/// vector.  If it is invalid, don't add anything to Ops.
109+void SparcTargetLowering::
110+LowerAsmOperandForConstraint(SDValue Op,
111+                             std::string &Constraint,
112+                             std::vector<SDValue> &Ops,
113+                             SelectionDAG &DAG) const {
114+  SDValue Result(0, 0);
115+
116+  // Only support length 1 constraints for now.
117+  if (Constraint.length() > 1)
118+    return;
119+
120+  char ConstraintLetter = Constraint[0];
121+  switch (ConstraintLetter) {
122+  default: break;
123+  case 'I':
124+    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
125+      if (isInt<13>(C->getSExtValue())) {
126+        Result = DAG.getTargetConstant(C->getSExtValue(), Op.getValueType());
127+        break;
128+      }
129+      return;
130+    }
131+  }
132+
133+  if (Result.getNode()) {
134+    Ops.push_back(Result);
135+    return;
136+  }
137+  TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
138+}
139+
140 std::pair<unsigned, const TargetRegisterClass*>
141 SparcTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
142                                                   MVT VT) const {
143