Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 33cddcf

Browse files
committed
[SelectionDAGBuilder] Cleanup InlineAsm Output generation. NFCI.
Defer inline asm's output fixup work until after we've generated the inline asm node itself. Remove StoresToEmit, IndirectStoresToEmit, and RetValRegs in favor of using ConstraintOperands. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351558 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent de8551c commit 33cddcf

File tree

1 file changed

+104
-115
lines changed

1 file changed

+104
-115
lines changed

lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 104 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -7644,13 +7644,6 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
76447644
AsmNodeOperands.push_back(DAG.getTargetConstant(
76457645
ExtraInfo.get(), getCurSDLoc(), TLI.getPointerTy(DAG.getDataLayout())));
76467646

7647-
// Loop over all of the inputs, copying the operand values into the
7648-
// appropriate registers and processing the output regs.
7649-
RegsForValue RetValRegs;
7650-
7651-
// IndirectStoresToEmit - The set of stores to emit after the inline asm node.
7652-
std::vector<std::pair<RegsForValue, Value *>> IndirectStoresToEmit;
7653-
76547647
for (SDISelAsmOperandInfo &OpInfo : ConstraintOperands) {
76557648
switch (OpInfo.Type) {
76567649
case InlineAsm::isOutput:
@@ -7671,38 +7664,26 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
76717664
MVT::i32));
76727665
AsmNodeOperands.push_back(OpInfo.CallOperand);
76737666
break;
7674-
}
7675-
7676-
// Otherwise, this is a register or register class output.
7677-
7678-
// Copy the output from the appropriate register. Find a register that
7679-
// we can use.
7680-
if (OpInfo.AssignedRegs.Regs.empty()) {
7681-
emitInlineAsmError(
7682-
CS, "couldn't allocate output register for constraint '" +
7683-
Twine(OpInfo.ConstraintCode) + "'");
7684-
return;
7685-
}
7667+
} else if (OpInfo.ConstraintType == TargetLowering::C_Register ||
7668+
OpInfo.ConstraintType == TargetLowering::C_RegisterClass) {
7669+
// Otherwise, this is a register or register class output.
7670+
7671+
// Copy the output from the appropriate register. Find a register that
7672+
// we can use.
7673+
if (OpInfo.AssignedRegs.Regs.empty()) {
7674+
emitInlineAsmError(
7675+
CS, "couldn't allocate output register for constraint '" +
7676+
Twine(OpInfo.ConstraintCode) + "'");
7677+
return;
7678+
}
76867679

7687-
// If this is an indirect operand, store through the pointer after the
7688-
// asm.
7689-
if (OpInfo.isIndirect) {
7690-
IndirectStoresToEmit.push_back(std::make_pair(OpInfo.AssignedRegs,
7691-
OpInfo.CallOperandVal));
7692-
} else {
7693-
// This is the result value of the call.
7694-
assert(!CS.getType()->isVoidTy() && "Bad inline asm!");
7695-
// Concatenate this output onto the outputs list.
7696-
RetValRegs.append(OpInfo.AssignedRegs);
7680+
// Add information to the INLINEASM node to know that this register is
7681+
// set.
7682+
OpInfo.AssignedRegs.AddInlineAsmOperands(
7683+
OpInfo.isEarlyClobber ? InlineAsm::Kind_RegDefEarlyClobber
7684+
: InlineAsm::Kind_RegDef,
7685+
false, 0, getCurSDLoc(), DAG, AsmNodeOperands);
76977686
}
7698-
7699-
// Add information to the INLINEASM node to know that this register is
7700-
// set.
7701-
OpInfo.AssignedRegs
7702-
.AddInlineAsmOperands(OpInfo.isEarlyClobber
7703-
? InlineAsm::Kind_RegDefEarlyClobber
7704-
: InlineAsm::Kind_RegDef,
7705-
false, 0, getCurSDLoc(), DAG, AsmNodeOperands);
77067687
break;
77077688

77087689
case InlineAsm::isInput: {
@@ -7860,94 +7841,102 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
78607841
DAG.getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
78617842
Flag = Chain.getValue(1);
78627843

7863-
// If this asm returns a register value, copy the result from that register
7864-
// and set it as the value of the call.
7865-
if (!RetValRegs.Regs.empty()) {
7866-
SDValue Val = RetValRegs.getCopyFromRegs(DAG, FuncInfo, getCurSDLoc(),
7867-
Chain, &Flag, CS.getInstruction());
7868-
7869-
llvm::Type *CSResultType = CS.getType();
7870-
unsigned numRet;
7871-
ArrayRef<Type *> ResultTypes;
7872-
SmallVector<SDValue, 1> ResultValues(1);
7873-
if (StructType *StructResult = dyn_cast<StructType>(CSResultType)) {
7874-
numRet = StructResult->getNumElements();
7875-
assert(Val->getNumOperands() == numRet &&
7876-
"Mismatch in number of output operands in asm result");
7877-
ResultTypes = StructResult->elements();
7878-
ArrayRef<SDUse> ValueUses = Val->ops();
7879-
ResultValues.resize(numRet);
7880-
std::transform(ValueUses.begin(), ValueUses.end(), ResultValues.begin(),
7881-
[](const SDUse &u) -> SDValue { return u.get(); });
7882-
} else {
7883-
numRet = 1;
7884-
ResultValues[0] = Val;
7885-
ResultTypes = makeArrayRef(CSResultType);
7886-
}
7887-
SmallVector<EVT, 1> ResultVTs(numRet);
7888-
for (unsigned i = 0; i < numRet; i++) {
7889-
EVT ResultVT = TLI.getValueType(DAG.getDataLayout(), ResultTypes[i]);
7890-
SDValue Val = ResultValues[i];
7891-
assert(ResultTypes[i]->isSized() && "Unexpected unsized type");
7892-
// If the type of the inline asm call site return value is different but
7893-
// has same size as the type of the asm output bitcast it. One example
7894-
// of this is for vectors with different width / number of elements.
7895-
// This can happen for register classes that can contain multiple
7896-
// different value types. The preg or vreg allocated may not have the
7897-
// same VT as was expected.
7898-
//
7899-
// This can also happen for a return value that disagrees with the
7900-
// register class it is put in, eg. a double in a general-purpose
7901-
// register on a 32-bit machine.
7902-
if (ResultVT != Val.getValueType() &&
7903-
ResultVT.getSizeInBits() == Val.getValueSizeInBits())
7904-
Val = DAG.getNode(ISD::BITCAST, getCurSDLoc(), ResultVT, Val);
7905-
else if (ResultVT != Val.getValueType() && ResultVT.isInteger() &&
7906-
Val.getValueType().isInteger()) {
7907-
// If a result value was tied to an input value, the computed result
7908-
// may have a wider width than the expected result. Extract the
7909-
// relevant portion.
7910-
Val = DAG.getNode(ISD::TRUNCATE, getCurSDLoc(), ResultVT, Val);
7911-
}
7844+
// Do additional work to generate outputs.
79127845

7913-
assert(ResultVT == Val.getValueType() && "Asm result value mismatch!");
7914-
ResultVTs[i] = ResultVT;
7915-
ResultValues[i] = Val;
7916-
}
7917-
7918-
Val = DAG.getNode(ISD::MERGE_VALUES, getCurSDLoc(),
7919-
DAG.getVTList(ResultVTs), ResultValues);
7920-
setValue(CS.getInstruction(), Val);
7921-
// Don't need to use this as a chain in this case.
7922-
if (!IA->hasSideEffects() && !hasMemory && IndirectStoresToEmit.empty())
7923-
return;
7924-
}
7846+
SmallVector<EVT, 1> ResultVTs;
7847+
SmallVector<SDValue, 1> ResultValues;
7848+
SmallVector<SDValue, 8> OutChains;
79257849

7926-
std::vector<std::pair<SDValue, const Value *>> StoresToEmit;
7850+
llvm::Type *CSResultType = CS.getType();
7851+
unsigned NumReturns = 0;
7852+
ArrayRef<Type *> ResultTypes;
7853+
if (StructType *StructResult = dyn_cast<StructType>(CSResultType)) {
7854+
NumReturns = StructResult->getNumElements();
7855+
ResultTypes = StructResult->elements();
7856+
} else if (!CSResultType->isVoidTy()) {
7857+
NumReturns = 1;
7858+
ResultTypes = makeArrayRef(CSResultType);
7859+
}
7860+
7861+
auto CurResultType = ResultTypes.begin();
7862+
auto handleRegAssign = [&](SDValue V) {
7863+
assert(CurResultType != ResultTypes.end() && "Unexpected value");
7864+
assert((*CurResultType)->isSized() && "Unexpected unsized type");
7865+
EVT ResultVT = TLI.getValueType(DAG.getDataLayout(), *CurResultType);
7866+
++CurResultType;
7867+
// If the type of the inline asm call site return value is different but has
7868+
// same size as the type of the asm output bitcast it. One example of this
7869+
// is for vectors with different width / number of elements. This can
7870+
// happen for register classes that can contain multiple different value
7871+
// types. The preg or vreg allocated may not have the same VT as was
7872+
// expected.
7873+
//
7874+
// This can also happen for a return value that disagrees with the register
7875+
// class it is put in, eg. a double in a general-purpose register on a
7876+
// 32-bit machine.
7877+
if (ResultVT != V.getValueType() &&
7878+
ResultVT.getSizeInBits() == V.getValueSizeInBits())
7879+
V = DAG.getNode(ISD::BITCAST, getCurSDLoc(), ResultVT, V);
7880+
else if (ResultVT != V.getValueType() && ResultVT.isInteger() &&
7881+
V.getValueType().isInteger()) {
7882+
// If a result value was tied to an input value, the computed result
7883+
// may have a wider width than the expected result. Extract the
7884+
// relevant portion.
7885+
V = DAG.getNode(ISD::TRUNCATE, getCurSDLoc(), ResultVT, V);
7886+
}
7887+
assert(ResultVT == V.getValueType() && "Asm result value mismatch!");
7888+
ResultVTs.push_back(ResultVT);
7889+
ResultValues.push_back(V);
7890+
};
79277891

7928-
// Process indirect outputs, first output all of the flagged copies out of
7929-
// physregs.
7930-
for (unsigned i = 0, e = IndirectStoresToEmit.size(); i != e; ++i) {
7931-
RegsForValue &OutRegs = IndirectStoresToEmit[i].first;
7932-
const Value *Ptr = IndirectStoresToEmit[i].second;
7933-
SDValue OutVal = OutRegs.getCopyFromRegs(DAG, FuncInfo, getCurSDLoc(),
7934-
Chain, &Flag, IA);
7935-
StoresToEmit.push_back(std::make_pair(OutVal, Ptr));
7892+
// Deal with assembly output fixups.
7893+
for (SDISelAsmOperandInfo &OpInfo : ConstraintOperands) {
7894+
if (OpInfo.Type == InlineAsm::isOutput &&
7895+
(OpInfo.ConstraintType == TargetLowering::C_Register ||
7896+
OpInfo.ConstraintType == TargetLowering::C_RegisterClass)) {
7897+
if (OpInfo.isIndirect) {
7898+
// Register indirect are manifest as stores.
7899+
const RegsForValue &OutRegs = OpInfo.AssignedRegs;
7900+
const Value *Ptr = OpInfo.CallOperandVal;
7901+
SDValue OutVal = OutRegs.getCopyFromRegs(DAG, FuncInfo, getCurSDLoc(),
7902+
Chain, &Flag, IA);
7903+
SDValue Val = DAG.getStore(Chain, getCurSDLoc(), OutVal, getValue(Ptr),
7904+
MachinePointerInfo(Ptr));
7905+
OutChains.push_back(Val);
7906+
} else {
7907+
// generate CopyFromRegs to associated registers.
7908+
assert(!CS.getType()->isVoidTy() && "Bad inline asm!");
7909+
SDValue Val = OpInfo.AssignedRegs.getCopyFromRegs(
7910+
DAG, FuncInfo, getCurSDLoc(), Chain, &Flag, CS.getInstruction());
7911+
if (Val.getOpcode() == ISD::MERGE_VALUES) {
7912+
for (const SDValue &V : Val->op_values())
7913+
handleRegAssign(V);
7914+
} else
7915+
handleRegAssign(Val);
7916+
}
7917+
}
79367918
}
79377919

7938-
// Emit the non-flagged stores from the physregs.
7939-
SmallVector<SDValue, 8> OutChains;
7940-
for (unsigned i = 0, e = StoresToEmit.size(); i != e; ++i) {
7941-
SDValue Val = DAG.getStore(Chain, getCurSDLoc(), StoresToEmit[i].first,
7942-
getValue(StoresToEmit[i].second),
7943-
MachinePointerInfo(StoresToEmit[i].second));
7944-
OutChains.push_back(Val);
7920+
// Set results.
7921+
if (!ResultValues.empty()) {
7922+
assert(CurResultType == ResultTypes.end() &&
7923+
"Mismatch in number of ResultTypes");
7924+
assert(ResultValues.size() == NumReturns &&
7925+
"Mismatch in number of output operands in asm result");
7926+
7927+
SDValue V = DAG.getNode(ISD::MERGE_VALUES, getCurSDLoc(),
7928+
DAG.getVTList(ResultVTs), ResultValues);
7929+
setValue(CS.getInstruction(), V);
79457930
}
79467931

7932+
// Collect store chains.
79477933
if (!OutChains.empty())
79487934
Chain = DAG.getNode(ISD::TokenFactor, getCurSDLoc(), MVT::Other, OutChains);
79497935

7950-
DAG.setRoot(Chain);
7936+
// Only Update Root if inline assembly has a memory effect.
7937+
if (ResultValues.empty() || IA->hasSideEffects() || hasMemory ||
7938+
!OutChains.empty())
7939+
DAG.setRoot(Chain);
79517940
}
79527941

79537942
void SelectionDAGBuilder::emitInlineAsmError(ImmutableCallSite CS,

0 commit comments

Comments
 (0)