Index: include/llvm/Target/TargetLowering.h =================================================================== --- include/llvm/Target/TargetLowering.h +++ include/llvm/Target/TargetLowering.h @@ -2621,9 +2621,10 @@ /// AsmOperandInfo, setting OpInfo.ConstraintCode and OpInfo.ConstraintType. /// If the actual operand being passed in is available, it can be passed in as /// Op, otherwise an empty SDValue can be passed. - virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, - SDValue Op, - SelectionDAG *DAG = nullptr) const; + /// When \param PreferReg is true prefer register over memory. + virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, SDValue Op, + SelectionDAG *DAG = nullptr, + bool PreferReg = false) const; /// Given a constraint, return the type of constraint it is for this target. virtual ConstraintType getConstraintType(const std::string &Constraint) const; Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5658,6 +5658,8 @@ unsigned ArgNo = 0; // ArgNo - The argument of the CallInst. unsigned ResNo = 0; // ResNo - The result number of the next output. + unsigned NumInputOperands = 0; // #Input operands. + unsigned InputInVreg = 0; for (unsigned i = 0, e = TargetConstraints.size(); i != e; ++i) { ConstraintOperands.push_back(SDISelAsmOperandInfo(TargetConstraints[i])); SDISelAsmOperandInfo &OpInfo = ConstraintOperands.back(); @@ -5684,9 +5686,15 @@ } ++ResNo; break; - case InlineAsm::isInput: + case InlineAsm::isInput: { OpInfo.CallOperandVal = const_cast(CS.getArgument(ArgNo++)); - break; + DenseMap::iterator VMI = + FuncInfo.ValueMap.find(OpInfo.CallOperandVal); + if (VMI != FuncInfo.ValueMap.end()) { + InputInVreg = 1; + } + ++NumInputOperands; + } break; case InlineAsm::isClobber: // Nothing to do. break; @@ -5763,7 +5771,9 @@ } // Compute the constraint code and ConstraintType to use. - TLI.ComputeConstraintToUse(OpInfo, OpInfo.CallOperand, &DAG); + TLI.ComputeConstraintToUse(OpInfo, OpInfo.CallOperand, &DAG, + OpInfo.Type == InlineAsm::isInput && + NumInputOperands == 1 && InputInVreg == 1); if (OpInfo.ConstraintType == TargetLowering::C_Memory && OpInfo.Type == InlineAsm::isClobber) Index: lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -2551,11 +2551,12 @@ /// that constraint, use it. This makes us take advantage of 'i' /// constraints when available. /// 2) Otherwise, pick the most general constraint present. This prefers -/// 'm' over 'r', for example. +/// 'm' over 'r', for example. But this can be overruled by \param +/// PreferReg. /// static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo, - const TargetLowering &TLI, - SDValue Op, SelectionDAG *DAG) { + const TargetLowering &TLI, SDValue Op, + SelectionDAG *DAG, bool PreferReg) { assert(OpInfo.Codes.size() > 1 && "Doesn't have multiple constraint options"); unsigned BestIdx = 0; TargetLowering::ConstraintType BestType = TargetLowering::C_Unknown; @@ -2591,6 +2592,9 @@ // This constraint letter is more general than the previous one, use it. int Generality = getConstraintGenerality(CType); if (Generality > BestGenerality) { + if (PreferReg && CType == TargetLowering::C_Memory && + BestType == TargetLowering::C_RegisterClass) + continue; BestType = CType; BestIdx = i; BestGenerality = Generality; @@ -2604,9 +2608,9 @@ /// ComputeConstraintToUse - Determines the constraint code and constraint /// type to use for the specific AsmOperandInfo, setting /// OpInfo.ConstraintCode and OpInfo.ConstraintType. -void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo, - SDValue Op, - SelectionDAG *DAG) const { +void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo, SDValue Op, + SelectionDAG *DAG, + bool PreferReg) const { assert(!OpInfo.Codes.empty() && "Must have at least one constraint"); // Single-letter constraints ('r') are very common. @@ -2614,7 +2618,7 @@ OpInfo.ConstraintCode = OpInfo.Codes[0]; OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode); } else { - ChooseConstraint(OpInfo, *this, Op, DAG); + ChooseConstraint(OpInfo, *this, Op, DAG, PreferReg); } // 'X' matches anything. Index: test/CodeGen/X86/inline-asm-rm-constraint.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/inline-asm-rm-constraint.ll @@ -0,0 +1,21 @@ +; RUN: llc -march=x86-64 < %s | FileCheck %s +; Check that register is preferred vs memory when there is +; only one input operand. +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-apple-darwin10.0" + +declare i32 @bar(i32) + +define void @foo(i32* %codeLength, i32 %nextSeveralBits, i32 %order) { +entry: +; CHECK-LABEL:foo +; CHECK: bsrl %esi, %ebp + %0 = tail call i32 asm "bsrl $1, $0", "=r,rm,~{dirflag},~{fpsr},~{flags}"(i32 %nextSeveralBits) #2 + %call = tail call i32 @bar(i32 %nextSeveralBits) + %xor = shl i32 %0, 1 + %mul = xor i32 %xor, 62 + %add = add i32 %call, %order + %add1 = add i32 %add, %mul + store i32 %add1, i32* %codeLength, align 4 + ret void +}