summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp53
1 files changed, 37 insertions, 16 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 80d665a64df..62ad0ec71ee 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7776,10 +7776,29 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
SDValue Val = RetValRegs.getCopyFromRegs(DAG, FuncInfo, getCurSDLoc(),
Chain, &Flag, CS.getInstruction());
- // FIXME: Why don't we do this for inline asms with MRVs?
- if (CS.getType()->isSingleValueType() && CS.getType()->isSized()) {
- EVT ResultType = TLI.getValueType(DAG.getDataLayout(), CS.getType());
-
+ llvm::Type *CSResultType = CS.getType();
+ unsigned numRet;
+ ArrayRef<Type *> ResultTypes;
+ SmallVector<SDValue, 1> ResultValues(1);
+ if (CSResultType->isSingleValueType()) {
+ numRet = 1;
+ ResultValues[0] = Val;
+ ResultTypes = makeArrayRef(CSResultType);
+ } else {
+ numRet = CSResultType->getNumContainedTypes();
+ assert(Val->getNumOperands() == numRet &&
+ "Mismatch in number of output operands in asm result");
+ ResultTypes = CSResultType->subtypes();
+ ArrayRef<SDUse> ValueUses = Val->ops();
+ ResultValues.resize(numRet);
+ std::transform(ValueUses.begin(), ValueUses.end(), ResultValues.begin(),
+ [](const SDUse &u) -> SDValue { return u.get(); });
+ }
+ SmallVector<EVT, 1> ResultVTs(numRet);
+ for (unsigned i = 0; i < numRet; i++) {
+ EVT ResultVT = TLI.getValueType(DAG.getDataLayout(), ResultTypes[i]);
+ SDValue Val = ResultValues[i];
+ assert(ResultTypes[i]->isSized() && "Unexpected unsized type");
// If the type of the inline asm call site return value is different but
// has same size as the type of the asm output bitcast it. One example
// of this is for vectors with different width / number of elements.
@@ -7790,22 +7809,24 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
// This can also happen for a return value that disagrees with the
// register class it is put in, eg. a double in a general-purpose
// register on a 32-bit machine.
- if (ResultType != Val.getValueType() &&
- ResultType.getSizeInBits() == Val.getValueSizeInBits()) {
- Val = DAG.getNode(ISD::BITCAST, getCurSDLoc(),
- 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, getCurSDLoc(), ResultType, Val);
+ if (ResultVT != Val.getValueType() &&
+ ResultVT.getSizeInBits() == Val.getValueSizeInBits())
+ Val = DAG.getNode(ISD::BITCAST, getCurSDLoc(), ResultVT, Val);
+ else if (ResultVT != Val.getValueType() && ResultVT.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, getCurSDLoc(), ResultVT, Val);
}
- assert(ResultType == Val.getValueType() && "Asm result value mismatch!");
+ assert(ResultVT == Val.getValueType() && "Asm result value mismatch!");
+ ResultVTs[i] = ResultVT;
+ ResultValues[i] = Val;
}
+ Val = DAG.getNode(ISD::MERGE_VALUES, getCurSDLoc(),
+ DAG.getVTList(ResultVTs), ResultValues);
setValue(CS.getInstruction(), Val);
// Don't need to use this as a chain in this case.
if (!IA->hasSideEffects() && !hasMemory && IndirectStoresToEmit.empty())
OpenPOWER on IntegriCloud