@@ -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
79537942void SelectionDAGBuilder::emitInlineAsmError (ImmutableCallSite CS,
0 commit comments