mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-02 00:37:09 +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:
parent
0f046c3c99
commit
0c52644cd8
@ -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<StructType>(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);
|
||||
|
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
|
||||
}
|
Loading…
Reference in New Issue
Block a user