diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Target/Sparc/SparcISelLowering.cpp | 60 | ||||
| -rw-r--r-- | llvm/lib/Target/Sparc/SparcISelLowering.h | 7 | ||||
| -rw-r--r-- | llvm/test/CodeGen/SPARC/inlineasm.ll | 35 | 
3 files changed, 102 insertions, 0 deletions
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 3abccdef6ef..6dae29c45c0 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -2923,12 +2923,72 @@ SparcTargetLowering::getConstraintType(const std::string &Constraint) const {      switch (Constraint[0]) {      default:  break;      case 'r': return C_RegisterClass; +    case 'I': // SIMM13 +      return C_Other;      }    }    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 { diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h index 2659fc89501..36d569e3b69 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.h +++ b/llvm/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; diff --git a/llvm/test/CodeGen/SPARC/inlineasm.ll b/llvm/test/CodeGen/SPARC/inlineasm.ll new file mode 100644 index 00000000000..7ecdd670666 --- /dev/null +++ b/llvm/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 +}  | 

