]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/patches/patch-r262261-llvm-r199781-sparc.diff
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / patches / patch-r262261-llvm-r199781-sparc.diff
1 Pull in r199781 from upstream llvm trunk (by Venkatraman Govindaraju):
2
3   [Sparc] Add support for inline assembly constraint 'I'.
4
5 Introduced here: http://svnweb.freebsd.org/changeset/base/262261
6
7 Index: 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 +}
47 Index: 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  
65 Index: 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 {