Pull in r199781 from upstream llvm trunk (by Venkatraman Govindaraju): [Sparc] Add support for inline assembly constraint 'I'. Introduced here: http://svnweb.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 &Ops, + SelectionDAG &DAG) const; std::pair 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(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 &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(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 SparcTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const {