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