1263320SdimPull in r199781 from upstream llvm trunk (by Venkatraman Govindaraju): 2263320Sdim 3263320Sdim [Sparc] Add support for inline assembly constraint 'I'. 4263320Sdim 5269012SemasteIntroduced here: http://svnweb.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