From: Chris Lattner Date: Fri, 17 Oct 2008 17:52:49 +0000 (+0000) Subject: Fix PR2356 on PowerPC: if we have an input and output that are tied together X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=0c52644cd8e46ca4c9caa6c51d43f97a2de8c5f5;p=oota-llvm.git Fix PR2356 on PowerPC: if we have an input and output that are tied together that have different sizes (e.g. i32 and i64) make sure to reserve registers for the bigger operand. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@57699 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index 51275f8f3ed..0052a3028a6 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -4721,6 +4721,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { OpInfo.CallOperandVal = CS.getArgument(ArgNo++); break; } + // The return value of the call is this value. As such, there is no // corresponding argument. assert(CS.getType() != Type::VoidTy && "Bad inline asm!"); @@ -4753,6 +4754,30 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { } OpInfo.ConstraintVT = OpVT; + } + + // Second pass over the constraints: compute which constraint option to use + // and assign registers to constraints that want a specific physreg. + for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) { + SDISelAsmOperandInfo &OpInfo = ConstraintOperands[i]; + + // If this is an output operand with a matching input operand, look up the + // matching input. It might have a different type (e.g. the output might be + // i32 and the input i64) and we need to pick the larger width to ensure we + // reserve the right number of registers. + if (OpInfo.hasMatchingInput()) { + SDISelAsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput]; + if (OpInfo.ConstraintVT != Input.ConstraintVT) { + assert(OpInfo.ConstraintVT.isInteger() && + Input.ConstraintVT.isInteger() && + "Asm constraints must be the same or different sized integers"); + if (OpInfo.ConstraintVT.getSizeInBits() < + Input.ConstraintVT.getSizeInBits()) + OpInfo.ConstraintVT = Input.ConstraintVT; + else + Input.ConstraintVT = OpInfo.ConstraintVT; + } + } // Compute the constraint code and ConstraintType to use. TLI.ComputeConstraintToUse(OpInfo, OpInfo.CallOperand, hasMemory, &DAG); @@ -5002,24 +5027,26 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { // and set it as the value of the call. if (!RetValRegs.Regs.empty()) { SDValue Val = RetValRegs.getCopyFromRegs(DAG, Chain, &Flag); - + MVT ResultType = TLI.getValueType(CS.getType()); + // If any of the results of the inline asm is a vector, it may have the // wrong width/num elts. This can happen for register classes that can // contain multiple different value types. The preg or vreg allocated may - // not have the same VT as was expected. Convert it to the right type with - // bit_convert. - if (const StructType *ResSTy = dyn_cast(CS.getType())) { - for (unsigned i = 0, e = ResSTy->getNumElements(); i != e; ++i) { - if (Val.getNode()->getValueType(i).isVector()) - Val = DAG.getNode(ISD::BIT_CONVERT, - TLI.getValueType(ResSTy->getElementType(i)), Val); - } - } else { - if (Val.getValueType().isVector()) - Val = DAG.getNode(ISD::BIT_CONVERT, TLI.getValueType(CS.getType()), - Val); + // not have the same VT as was expected. Convert it to the right type + // with bit_convert. + // FIXME: Is this sufficient for inline asms with MRVs? + if (ResultType != Val.getValueType() && Val.getValueType().isVector()) { + Val = DAG.getNode(ISD::BIT_CONVERT, ResultType, Val); + + } else if (ResultType != Val.getValueType() && + ResultType.isInteger() && Val.getValueType().isInteger()) { + // If a result value was tied to an input value, the computed result may + // have a wider width than the expected result. Extract the relevant + // portion. + Val = DAG.getNode(ISD::TRUNCATE, ResultType, Val); } - + + assert(ResultType == Val.getValueType() && "Asm result value mismatch!"); setValue(CS.getInstruction(), Val); } @@ -5273,7 +5300,8 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, Value != NumValues; ++Value) { MVT VT = ValueVTs[Value]; const Type *ArgTy = VT.getTypeForMVT(); - SDValue Op = SDValue(Args[i].Node.getNode(), Args[i].Node.getResNo() + Value); + SDValue Op = SDValue(Args[i].Node.getNode(), + Args[i].Node.getResNo() + Value); ISD::ArgFlagsTy Flags; unsigned OriginalAlignment = getTargetData()->getABITypeAlignment(ArgTy); diff --git a/test/CodeGen/PowerPC/2008-10-17-AsmMatchingOperands.ll b/test/CodeGen/PowerPC/2008-10-17-AsmMatchingOperands.ll new file mode 100644 index 00000000000..7f475e3e9d7 --- /dev/null +++ b/test/CodeGen/PowerPC/2008-10-17-AsmMatchingOperands.ll @@ -0,0 +1,11 @@ +; RUN: llvm-as < %s | llc +; PR2356 +target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f128:64:128" +target triple = "powerpc-apple-darwin9" + +define i32 @test(i64 %x, i32* %p) nounwind { +entry: + %asmtmp = call i32 asm "", "=r,0"(i64 0) nounwind ; [#uses=0] + %y = add i32 %asmtmp, 1 + ret i32 %y +}