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
This commit is contained in:
Chris Lattner
2008-10-17 17:52:49 +00:00
parent 0f046c3c99
commit 0c52644cd8
2 changed files with 54 additions and 15 deletions

View File

@@ -4721,6 +4721,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
OpInfo.CallOperandVal = CS.getArgument(ArgNo++); OpInfo.CallOperandVal = CS.getArgument(ArgNo++);
break; break;
} }
// The return value of the call is this value. As such, there is no // The return value of the call is this value. As such, there is no
// corresponding argument. // corresponding argument.
assert(CS.getType() != Type::VoidTy && "Bad inline asm!"); assert(CS.getType() != Type::VoidTy && "Bad inline asm!");
@@ -4753,6 +4754,30 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
} }
OpInfo.ConstraintVT = OpVT; 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. // Compute the constraint code and ConstraintType to use.
TLI.ComputeConstraintToUse(OpInfo, OpInfo.CallOperand, hasMemory, &DAG); 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. // and set it as the value of the call.
if (!RetValRegs.Regs.empty()) { if (!RetValRegs.Regs.empty()) {
SDValue Val = RetValRegs.getCopyFromRegs(DAG, Chain, &Flag); 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 // 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 // wrong width/num elts. This can happen for register classes that can
// contain multiple different value types. The preg or vreg allocated may // 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 // not have the same VT as was expected. Convert it to the right type
// bit_convert. // with bit_convert.
if (const StructType *ResSTy = dyn_cast<StructType>(CS.getType())) { // FIXME: Is this sufficient for inline asms with MRVs?
for (unsigned i = 0, e = ResSTy->getNumElements(); i != e; ++i) { if (ResultType != Val.getValueType() && Val.getValueType().isVector()) {
if (Val.getNode()->getValueType(i).isVector()) Val = DAG.getNode(ISD::BIT_CONVERT, ResultType, Val);
Val = DAG.getNode(ISD::BIT_CONVERT,
TLI.getValueType(ResSTy->getElementType(i)), Val); } else if (ResultType != Val.getValueType() &&
} ResultType.isInteger() && Val.getValueType().isInteger()) {
} else { // If a result value was tied to an input value, the computed result may
if (Val.getValueType().isVector()) // have a wider width than the expected result. Extract the relevant
Val = DAG.getNode(ISD::BIT_CONVERT, TLI.getValueType(CS.getType()), // portion.
Val); Val = DAG.getNode(ISD::TRUNCATE, ResultType, Val);
} }
assert(ResultType == Val.getValueType() && "Asm result value mismatch!");
setValue(CS.getInstruction(), Val); setValue(CS.getInstruction(), Val);
} }
@@ -5273,7 +5300,8 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy,
Value != NumValues; ++Value) { Value != NumValues; ++Value) {
MVT VT = ValueVTs[Value]; MVT VT = ValueVTs[Value];
const Type *ArgTy = VT.getTypeForMVT(); 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; ISD::ArgFlagsTy Flags;
unsigned OriginalAlignment = unsigned OriginalAlignment =
getTargetData()->getABITypeAlignment(ArgTy); getTargetData()->getABITypeAlignment(ArgTy);

View File

@@ -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 ; <i32> [#uses=0]
%y = add i32 %asmtmp, 1
ret i32 %y
}