mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-15 06:29:05 +00:00
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:
@@ -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);
|
||||||
|
11
test/CodeGen/PowerPC/2008-10-17-AsmMatchingOperands.ll
Normal file
11
test/CodeGen/PowerPC/2008-10-17-AsmMatchingOperands.ll
Normal 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
|
||||||
|
}
|
Reference in New Issue
Block a user