@@ -7644,13 +7644,6 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
7644
7644
AsmNodeOperands.push_back (DAG.getTargetConstant (
7645
7645
ExtraInfo.get (), getCurSDLoc (), TLI.getPointerTy (DAG.getDataLayout ())));
7646
7646
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
-
7654
7647
for (SDISelAsmOperandInfo &OpInfo : ConstraintOperands) {
7655
7648
switch (OpInfo.Type ) {
7656
7649
case InlineAsm::isOutput:
@@ -7671,38 +7664,26 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
7671
7664
MVT::i32 ));
7672
7665
AsmNodeOperands.push_back (OpInfo.CallOperand );
7673
7666
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
+ }
7686
7679
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);
7697
7686
}
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);
7706
7687
break ;
7707
7688
7708
7689
case InlineAsm::isInput: {
@@ -7860,94 +7841,102 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
7860
7841
DAG.getVTList (MVT::Other, MVT::Glue), AsmNodeOperands);
7861
7842
Flag = Chain.getValue (1 );
7862
7843
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.
7912
7845
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;
7925
7849
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
+ };
7927
7891
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
+ }
7936
7918
}
7937
7919
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);
7945
7930
}
7946
7931
7932
+ // Collect store chains.
7947
7933
if (!OutChains.empty ())
7948
7934
Chain = DAG.getNode (ISD::TokenFactor, getCurSDLoc (), MVT::Other, OutChains);
7949
7935
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);
7951
7940
}
7952
7941
7953
7942
void SelectionDAGBuilder::emitInlineAsmError (ImmutableCallSite CS,
0 commit comments