[llvm] a880c10 - [CodeGen][NFC] Refactor inline asm constraint determination (#195104)

via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 30 11:52:48 PDT 2026


Author: Bill Wendling
Date: 2026-04-30T11:52:42-07:00
New Revision: a880c10074b7d9d57cd5f2b1616025d7de0a736d

URL: https://github.com/llvm/llvm-project/commit/a880c10074b7d9d57cd5f2b1616025d7de0a736d
DIFF: https://github.com/llvm/llvm-project/commit/a880c10074b7d9d57cd5f2b1616025d7de0a736d.diff

LOG: [CodeGen][NFC] Refactor inline asm constraint determination (#195104)

The original function was very large and unwieldy. This also sets the
function up for future improvements.

Added: 
    

Modified: 
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index fb454afd141e2..3deb8b4f2cf22 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -10193,32 +10193,38 @@ static bool isFunction(SDValue Op) {
   return false;
 }
 
-/// visitInlineAsm - Handle a call to an InlineAsm object.
-void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
-                                         const BasicBlock *EHPadBB) {
-  const InlineAsm *IA = cast<InlineAsm>(Call.getCalledOperand());
+namespace {
 
-  /// ConstraintOperands - Information about all of the constraints.
+struct ConstraintDecisionInfo {
   SmallVector<SDISelAsmOperandInfo, 16> ConstraintOperands;
+  std::vector<SDValue> AsmNodeOperands;
+  SDValue Glue, Chain;
+  bool HasSideEffect = false;
+  MCSymbol *BeginLabel = nullptr;
 
-  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
-  TargetLowering::AsmOperandInfoVector TargetConstraints = TLI.ParseConstraints(
-      DAG.getDataLayout(), DAG.getSubtarget().getRegisterInfo(), Call);
+  SmallVector<char> Buffer;
+  raw_svector_ostream ErrorMsg;
 
-  // First Pass: Calculate HasSideEffects and ExtraFlags (AlignStack,
-  // AsmDialect, MayLoad, MayStore).
-  bool HasSideEffect = IA->hasSideEffects();
-  ExtraFlags ExtraInfo(Call);
+  ConstraintDecisionInfo() : ErrorMsg(Buffer) {}
+};
 
+} // end anonymous namespace
+
+/// Construct operand info objects.
+static bool
+constructOperandInfo(ConstraintDecisionInfo &Info,
+                     TargetLowering::AsmOperandInfoVector &TargetConstraints,
+                     SelectionDAGBuilder &Builder, const TargetLowering &TLI,
+                     ExtraFlags &ExtraInfo) {
   for (auto &T : TargetConstraints) {
-    ConstraintOperands.push_back(SDISelAsmOperandInfo(T));
-    SDISelAsmOperandInfo &OpInfo = ConstraintOperands.back();
+    Info.ConstraintOperands.push_back(SDISelAsmOperandInfo(T));
+    SDISelAsmOperandInfo &OpInfo = Info.ConstraintOperands.back();
 
     if (OpInfo.CallOperandVal)
-      OpInfo.CallOperand = getValue(OpInfo.CallOperandVal);
+      OpInfo.CallOperand = Builder.getValue(OpInfo.CallOperandVal);
 
-    if (!HasSideEffect)
-      HasSideEffect = OpInfo.hasMemory(TLI);
+    if (!Info.HasSideEffect)
+      Info.HasSideEffect = OpInfo.hasMemory(TLI);
 
     // Determine if this InlineAsm MayLoad or MayStore based on the constraints.
     // FIXME: Could we compute this on OpInfo rather than T?
@@ -10226,45 +10232,33 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
     // Compute the constraint code and ConstraintType to use.
     TLI.ComputeConstraintToUse(T, SDValue());
 
-    if (T.ConstraintType == TargetLowering::C_Immediate &&
-        OpInfo.CallOperand && !isa<ConstantSDNode>(OpInfo.CallOperand))
+    if (T.ConstraintType == TargetLowering::C_Immediate && OpInfo.CallOperand &&
+        !isa<ConstantSDNode>(OpInfo.CallOperand)) {
       // We've delayed emitting a diagnostic like the "n" constraint because
       // inlining could cause an integer showing up.
-      return emitInlineAsmError(Call, "constraint '" + Twine(T.ConstraintCode) +
-                                          "' expects an integer constant "
-                                          "expression");
+      Info.ErrorMsg << "constraint '" << T.ConstraintCode
+                    << "' expects an integer constant expression";
+      return true;
+    }
 
     ExtraInfo.update(T);
   }
 
-  // We won't need to flush pending loads if this asm doesn't touch
-  // memory and is nonvolatile.
-  SDValue Glue, Chain = (HasSideEffect) ? getRoot() : DAG.getRoot();
-
-  bool EmitEHLabels = isa<InvokeInst>(Call);
-  if (EmitEHLabels) {
-    assert(EHPadBB && "InvokeInst must have an EHPadBB");
-  }
-  bool IsCallBr = isa<CallBrInst>(Call);
-
-  if (IsCallBr || EmitEHLabels) {
-    // If this is a callbr or invoke we need to flush pending exports since
-    // inlineasm_br and invoke are terminators.
-    // We need to do this before nodes are glued to the inlineasm_br node.
-    Chain = getControlRoot();
-  }
-
-  MCSymbol *BeginLabel = nullptr;
-  if (EmitEHLabels) {
-    Chain = lowerStartEH(Chain, EHPadBB, BeginLabel);
-  }
+  return false;
+}
 
-  int OpNo = -1;
-  SmallVector<StringRef> AsmStrs;
+/// Compute which constraint option to use for each operand.
+static void
+computeConstraintToUse(ConstraintDecisionInfo &Info, const CallBase &Call,
+                       TargetLowering::AsmOperandInfoVector &TargetConstraints,
+                       SelectionDAGBuilder &Builder, const TargetLowering &TLI,
+                       const TargetMachine &TM, SelectionDAG &DAG) {
+  const auto *IA = cast<InlineAsm>(Call.getCalledOperand());
+  SmallVector<StringRef, 4> AsmStrs;
   IA->collectAsmStrs(AsmStrs);
 
-  // Second pass over the constraints: compute which constraint option to use.
-  for (SDISelAsmOperandInfo &OpInfo : ConstraintOperands) {
+  int OpNo = -1;
+  for (SDISelAsmOperandInfo &OpInfo : Info.ConstraintOperands) {
     if (OpInfo.hasArg() || OpInfo.Type == InlineAsm::isOutput)
       OpNo++;
 
@@ -10273,7 +10267,8 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
     // other is floating point, or their sizes are 
diff erent, flag it as an
     // error.
     if (OpInfo.hasMatchingInput()) {
-      SDISelAsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput];
+      SDISelAsmOperandInfo &Input =
+          Info.ConstraintOperands[OpInfo.MatchingInput];
       patchMatchingInput(OpInfo, Input, DAG);
     }
 
@@ -10320,7 +10315,8 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
              "Can only indirectify direct input operands!");
 
       // Memory operands really want the address of the value.
-      Chain = getAddressForMemoryInput(Chain, getCurSDLoc(), OpInfo, DAG);
+      Info.Chain = getAddressForMemoryInput(Info.Chain, Builder.getCurSDLoc(),
+                                            OpInfo, DAG);
 
       // There is no longer a Value* corresponding to this operand.
       OpInfo.CallOperandVal = nullptr;
@@ -10328,58 +10324,46 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
       // It is now an indirect operand.
       OpInfo.isIndirect = true;
     }
-
   }
+}
 
-  // AsmNodeOperands - The operands for the ISD::INLINEASM node.
-  std::vector<SDValue> AsmNodeOperands;
-  AsmNodeOperands.push_back(SDValue());  // reserve space for input chain
-  AsmNodeOperands.push_back(DAG.getTargetExternalSymbol(
-      IA->getAsmString().data(), TLI.getProgramPointerTy(DAG.getDataLayout())));
-
-  // If we have a !srcloc metadata node associated with it, we want to attach
-  // this to the ultimately generated inline asm machineinstr.  To do this, we
-  // pass in the third operand as this (potentially null) inline asm MDNode.
-  const MDNode *SrcLoc = Call.getMetadata("srcloc");
-  AsmNodeOperands.push_back(DAG.getMDNode(SrcLoc));
-
-  // Remember the HasSideEffect, AlignStack, AsmDialect, MayLoad and MayStore
-  // bits as operand 3.
-  AsmNodeOperands.push_back(DAG.getTargetConstant(
-      ExtraInfo.get(), getCurSDLoc(), TLI.getPointerTy(DAG.getDataLayout())));
-
-  // Third pass: Loop over operands to prepare DAG-level operands.. As part of
-  // this, assign virtual and physical registers for inputs and otput.
-  for (SDISelAsmOperandInfo &OpInfo : ConstraintOperands) {
+/// Prepare DAG-level operands. As part of this, assign virtual and physical
+/// registers for inputs and output.
+static bool prepareDAGLevelOperands(ConstraintDecisionInfo &Info,
+                                    const CallBase &Call,
+                                    SelectionDAGBuilder &Builder,
+                                    const TargetLowering &TLI,
+                                    SelectionDAG &DAG) {
+  SDLoc DL = Builder.getCurSDLoc();
+  for (SDISelAsmOperandInfo &OpInfo : Info.ConstraintOperands) {
     // Assign Registers.
     SDISelAsmOperandInfo &RefOpInfo =
         OpInfo.isMatchingInputConstraint()
-            ? ConstraintOperands[OpInfo.getMatchedOperand()]
+            ? Info.ConstraintOperands[OpInfo.getMatchedOperand()]
             : OpInfo;
-    const auto RegError =
-        getRegistersForValue(DAG, getCurSDLoc(), OpInfo, RefOpInfo);
+    const auto RegError = getRegistersForValue(DAG, DL, OpInfo, RefOpInfo);
     if (RegError) {
       const MachineFunction &MF = DAG.getMachineFunction();
       const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
       const char *RegName = TRI.getName(*RegError);
-      emitInlineAsmError(Call, "register '" + Twine(RegName) +
-                                   "' allocated for constraint '" +
-                                   Twine(OpInfo.ConstraintCode) +
-                                   "' does not match required type");
-      return;
+      Info.ErrorMsg << "register '" << RegName << "' allocated for constraint '"
+                    << OpInfo.ConstraintCode
+                    << "' does not match required type";
+      return true;
     }
 
     auto DetectWriteToReservedRegister = [&]() {
       const MachineFunction &MF = DAG.getMachineFunction();
       const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
+
       for (Register Reg : OpInfo.AssignedRegs.Regs) {
         if (Reg.isPhysical() && TRI.isInlineAsmReadOnlyReg(MF, Reg)) {
-          const char *RegName = TRI.getName(Reg);
-          emitInlineAsmError(Call, "write to reserved register '" +
-                                       Twine(RegName) + "'");
+          Info.ErrorMsg << "write to reserved register '"
+                        << TRI.getRegAsmName(Reg) << "'";
           return true;
         }
       }
+
       return false;
     };
     assert((OpInfo.ConstraintType != TargetLowering::C_Address ||
@@ -10398,29 +10382,28 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
         // Add information to the INLINEASM node to know about this output.
         InlineAsm::Flag OpFlags(InlineAsm::Kind::Mem, 1);
         OpFlags.setMemConstraint(ConstraintID);
-        AsmNodeOperands.push_back(DAG.getTargetConstant(OpFlags, getCurSDLoc(),
-                                                        MVT::i32));
-        AsmNodeOperands.push_back(OpInfo.CallOperand);
+        Info.AsmNodeOperands.push_back(
+            DAG.getTargetConstant(OpFlags, DL, MVT::i32));
+        Info.AsmNodeOperands.push_back(OpInfo.CallOperand);
       } else {
         // Otherwise, this outputs to a register (directly for C_Register /
         // C_RegisterClass, and a target-defined fashion for
         // C_Immediate/C_Other). Find a register that we can use.
         if (OpInfo.AssignedRegs.Regs.empty()) {
-          emitInlineAsmError(
-              Call, "couldn't allocate output register for constraint '" +
-                        Twine(OpInfo.ConstraintCode) + "'");
-          return;
+          Info.ErrorMsg << "couldn't allocate output register for "
+                        << "constraint '" << OpInfo.ConstraintCode << "'";
+          return true;
         }
 
         if (DetectWriteToReservedRegister())
-          return;
+          return true;
 
         // Add information to the INLINEASM node to know that this register is
         // set.
         OpInfo.AssignedRegs.AddInlineAsmOperands(
             OpInfo.isEarlyClobber ? InlineAsm::Kind::RegDefEarlyClobber
                                   : InlineAsm::Kind::RegDef,
-            false, 0, getCurSDLoc(), DAG, AsmNodeOperands);
+            false, 0, DL, DAG, Info.AsmNodeOperands);
       }
       break;
 
@@ -10432,52 +10415,52 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
         // If this is required to match an output register we have already set,
         // just use its register.
         auto CurOp = findMatchingInlineAsmOperand(OpInfo.getMatchedOperand(),
-                                                  AsmNodeOperands);
-        InlineAsm::Flag Flag(AsmNodeOperands[CurOp]->getAsZExtVal());
+                                                  Info.AsmNodeOperands);
+        InlineAsm::Flag Flag(Info.AsmNodeOperands[CurOp]->getAsZExtVal());
         if (Flag.isRegDefKind() || Flag.isRegDefEarlyClobberKind()) {
           if (OpInfo.isIndirect) {
             // This happens on gcc/testsuite/gcc.dg/pr8788-1.c
-            emitInlineAsmError(Call, "inline asm not supported yet: "
-                                     "don't know how to handle tied "
-                                     "indirect register inputs");
-            return;
+            Info.ErrorMsg << "inline asm not supported yet: don't know how "
+                          << "to handle tied indirect register inputs";
+            return true;
           }
 
           SmallVector<Register, 4> Regs;
           MachineFunction &MF = DAG.getMachineFunction();
           MachineRegisterInfo &MRI = MF.getRegInfo();
           const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
-          auto *R = cast<RegisterSDNode>(AsmNodeOperands[CurOp+1]);
+          auto *R = cast<RegisterSDNode>(Info.AsmNodeOperands[CurOp + 1]);
           Register TiedReg = R->getReg();
           MVT RegVT = R->getSimpleValueType(0);
           const TargetRegisterClass *RC =
               TiedReg.isVirtual()     ? MRI.getRegClass(TiedReg)
               : RegVT != MVT::Untyped ? TLI.getRegClassFor(RegVT)
                                       : TRI.getMinimalPhysRegClass(TiedReg);
-          for (unsigned i = 0, e = Flag.getNumOperandRegisters(); i != e; ++i)
+          for (unsigned I = 0, E = Flag.getNumOperandRegisters(); I != E; ++I)
             Regs.push_back(MRI.createVirtualRegister(RC));
 
           RegsForValue MatchedRegs(Regs, RegVT, InOperandVal.getValueType());
 
-          SDLoc dl = getCurSDLoc();
           // Use the produced MatchedRegs object to
-          MatchedRegs.getCopyToRegs(InOperandVal, DAG, dl, Chain, &Glue, &Call);
+          MatchedRegs.getCopyToRegs(InOperandVal, DAG, DL, Info.Chain,
+                                    &Info.Glue, &Call);
           MatchedRegs.AddInlineAsmOperands(InlineAsm::Kind::RegUse, true,
-                                           OpInfo.getMatchedOperand(), dl, DAG,
-                                           AsmNodeOperands);
+                                           OpInfo.getMatchedOperand(), DL, DAG,
+                                           Info.AsmNodeOperands);
           break;
         }
 
         assert(Flag.isMemKind() && "Unknown matching constraint!");
         assert(Flag.getNumOperandRegisters() == 1 &&
                "Unexpected number of operands");
+
         // Add information to the INLINEASM node to know about this input.
         // See InlineAsm.h isUseOperandTiedToDef.
         Flag.clearMemConstraint();
         Flag.setMatchingOp(OpInfo.getMatchedOperand());
-        AsmNodeOperands.push_back(DAG.getTargetConstant(
-            Flag, getCurSDLoc(), TLI.getPointerTy(DAG.getDataLayout())));
-        AsmNodeOperands.push_back(AsmNodeOperands[CurOp+1]);
+        Info.AsmNodeOperands.push_back(DAG.getTargetConstant(
+            Flag, DL, TLI.getPointerTy(DAG.getDataLayout())));
+        Info.AsmNodeOperands.push_back(Info.AsmNodeOperands[CurOp + 1]);
         break;
       }
 
@@ -10494,22 +10477,21 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
         if (Ops.empty()) {
           if (OpInfo.ConstraintType == TargetLowering::C_Immediate)
             if (isa<ConstantSDNode>(InOperandVal)) {
-              emitInlineAsmError(Call, "value out of range for constraint '" +
-                                           Twine(OpInfo.ConstraintCode) + "'");
-              return;
+              Info.ErrorMsg << "value out of range for constraint '"
+                            << OpInfo.ConstraintCode << "'";
+              return true;
             }
 
-          emitInlineAsmError(Call,
-                             "invalid operand for inline asm constraint '" +
-                                 Twine(OpInfo.ConstraintCode) + "'");
-          return;
+          Info.ErrorMsg << "invalid operand for inline asm constraint '"
+                        << OpInfo.ConstraintCode << "'";
+          return true;
         }
 
         // Add information to the INLINEASM node to know about this input.
         InlineAsm::Flag ResOpType(InlineAsm::Kind::Imm, Ops.size());
-        AsmNodeOperands.push_back(DAG.getTargetConstant(
-            ResOpType, getCurSDLoc(), TLI.getPointerTy(DAG.getDataLayout())));
-        llvm::append_range(AsmNodeOperands, Ops);
+        Info.AsmNodeOperands.push_back(DAG.getTargetConstant(
+            ResOpType, DL, TLI.getPointerTy(DAG.getDataLayout())));
+        llvm::append_range(Info.AsmNodeOperands, Ops);
         break;
       }
 
@@ -10529,10 +10511,9 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
         // Add information to the INLINEASM node to know about this input.
         InlineAsm::Flag ResOpType(InlineAsm::Kind::Mem, 1);
         ResOpType.setMemConstraint(ConstraintID);
-        AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType,
-                                                        getCurSDLoc(),
-                                                        MVT::i32));
-        AsmNodeOperands.push_back(InOperandVal);
+        Info.AsmNodeOperands.push_back(
+            DAG.getTargetConstant(ResOpType, DL, MVT::i32));
+        Info.AsmNodeOperands.push_back(InOperandVal);
         break;
       }
 
@@ -10548,7 +10529,7 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
         if (isFunction(InOperandVal)) {
           auto *GA = cast<GlobalAddressSDNode>(InOperandVal);
           ResOpType = InlineAsm::Flag(InlineAsm::Kind::Func, 1);
-          AsmOp = DAG.getTargetGlobalAddress(GA->getGlobal(), getCurSDLoc(),
+          AsmOp = DAG.getTargetGlobalAddress(GA->getGlobal(), DL,
                                              InOperandVal.getValueType(),
                                              GA->getOffset());
         }
@@ -10556,67 +10537,138 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
         // Add information to the INLINEASM node to know about this input.
         ResOpType.setMemConstraint(ConstraintID);
 
-        AsmNodeOperands.push_back(
-            DAG.getTargetConstant(ResOpType, getCurSDLoc(), MVT::i32));
-
-        AsmNodeOperands.push_back(AsmOp);
+        Info.AsmNodeOperands.push_back(
+            DAG.getTargetConstant(ResOpType, DL, MVT::i32));
+        Info.AsmNodeOperands.push_back(AsmOp);
         break;
       }
 
       if (OpInfo.ConstraintType != TargetLowering::C_RegisterClass &&
           OpInfo.ConstraintType != TargetLowering::C_Register) {
-        emitInlineAsmError(Call, "unknown asm constraint '" +
-                                     Twine(OpInfo.ConstraintCode) + "'");
-        return;
+        Info.ErrorMsg << "unknown asm constraint '" << OpInfo.ConstraintCode
+                      << "'";
+        return true;
       }
 
       // TODO: Support this.
       if (OpInfo.isIndirect) {
-        emitInlineAsmError(
-            Call, "Don't know how to handle indirect register inputs yet "
-                  "for constraint '" +
-                      Twine(OpInfo.ConstraintCode) + "'");
-        return;
+        Info.ErrorMsg << "Don't know how to handle indirect register inputs "
+                      << "yet for constraint '" << OpInfo.ConstraintCode << "'";
+        return true;
       }
 
       // Copy the input into the appropriate registers.
       if (OpInfo.AssignedRegs.Regs.empty()) {
-        emitInlineAsmError(Call,
-                           "couldn't allocate input reg for constraint '" +
-                               Twine(OpInfo.ConstraintCode) + "'");
-        return;
+        Info.ErrorMsg << "couldn't allocate input reg for constraint '"
+                      << OpInfo.ConstraintCode << "'";
+        return true;
       }
 
       if (DetectWriteToReservedRegister())
-        return;
-
-      SDLoc dl = getCurSDLoc();
-
-      OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, dl, Chain, &Glue,
-                                        &Call);
+        return true;
 
-      OpInfo.AssignedRegs.AddInlineAsmOperands(InlineAsm::Kind::RegUse, false,
-                                               0, dl, DAG, AsmNodeOperands);
+      OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, DL, Info.Chain,
+                                        &Info.Glue, &Call);
+      OpInfo.AssignedRegs.AddInlineAsmOperands(
+          InlineAsm::Kind::RegUse, false, 0, DL, DAG, Info.AsmNodeOperands);
       break;
     }
+
     case InlineAsm::isClobber:
       // Add the clobbered value to the operand list, so that the register
       // allocator is aware that the physreg got clobbered.
       if (!OpInfo.AssignedRegs.Regs.empty())
-        OpInfo.AssignedRegs.AddInlineAsmOperands(InlineAsm::Kind::Clobber,
-                                                 false, 0, getCurSDLoc(), DAG,
-                                                 AsmNodeOperands);
+        OpInfo.AssignedRegs.AddInlineAsmOperands(
+            InlineAsm::Kind::Clobber, false, 0, DL, DAG, Info.AsmNodeOperands);
       break;
     }
   }
 
+  return false;
+}
+
+/// DetermineConstraints - Find the constraints to use for inline asm operands.
+static bool
+determineConstraints(ConstraintDecisionInfo &Info,
+                     TargetLowering::AsmOperandInfoVector &TargetConstraints,
+                     const CallBase &Call, SelectionDAGBuilder &Builder,
+                     const TargetLowering &TLI, const TargetMachine &TM,
+                     SelectionDAG &DAG, const BasicBlock *EHPadBB) {
+  const auto *IA = cast<InlineAsm>(Call.getCalledOperand());
+  ExtraFlags ExtraInfo(Call);
+
+  // First pass: Construct operand info objects.
+  Info.HasSideEffect = IA->hasSideEffects();
+  if (constructOperandInfo(Info, TargetConstraints, Builder, TLI, ExtraInfo))
+    return true;
+
+  // We won't need to flush pending loads if this asm doesn't touch
+  // memory and is nonvolatile.
+  Info.Chain = Info.HasSideEffect ? Builder.getRoot() : DAG.getRoot();
+
+  bool IsCallBr = isa<CallBrInst>(Call);
+  bool EmitEHLabels = isa<InvokeInst>(Call);
+  if (IsCallBr || EmitEHLabels)
+    // If this is a callbr or invoke we need to flush pending exports since
+    // inlineasm_br and invoke are terminators.
+    // We need to do this before nodes are glued to the inlineasm_br node.
+    Info.Chain = Builder.getControlRoot();
+
+  if (EmitEHLabels)
+    Info.Chain = Builder.lowerStartEH(Info.Chain, EHPadBB, Info.BeginLabel);
+
+  // Second pass: Compute which constraint option to use.
+  computeConstraintToUse(Info, Call, TargetConstraints, Builder, TLI, TM, DAG);
+
+  // AsmNodeOperands - The operands for the ISD::INLINEASM node.
+  Info.AsmNodeOperands.push_back(SDValue()); // reserve space for input chain
+  Info.AsmNodeOperands.push_back(DAG.getTargetExternalSymbol(
+      IA->getAsmString().data(), TLI.getProgramPointerTy(DAG.getDataLayout())));
+
+  // If we have a !srcloc metadata node associated with it, we want to attach
+  // this to the ultimately generated inline asm machineinstr.  To do this, we
+  // pass in the third operand as this (potentially null) inline asm MDNode.
+  const MDNode *SrcLoc = Call.getMetadata("srcloc");
+  Info.AsmNodeOperands.push_back(DAG.getMDNode(SrcLoc));
+
+  // Remember the HasSideEffect, AlignStack, AsmDialect, MayLoad and MayStore
+  // bits as operand 3.
+  Info.AsmNodeOperands.push_back(
+      DAG.getTargetConstant(ExtraInfo.get(), Builder.getCurSDLoc(),
+                            TLI.getPointerTy(DAG.getDataLayout())));
+
+  // Third pass: Prepare DAG-level operands
+  return prepareDAGLevelOperands(Info, Call, Builder, TLI, DAG);
+}
+
+/// visitInlineAsm - Handle a call to an InlineAsm object.
+void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
+                                         const BasicBlock *EHPadBB) {
+  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+  TargetLowering::AsmOperandInfoVector TargetConstraints = TLI.ParseConstraints(
+      DAG.getDataLayout(), DAG.getSubtarget().getRegisterInfo(), Call);
+
+  assert((!isa<InvokeInst>(Call) || EHPadBB) &&
+         "InvokeInst must have an EHPadBB");
+
+  ConstraintDecisionInfo Info;
+  if (determineConstraints(Info, TargetConstraints, Call, *this, TLI, TM, DAG,
+                           EHPadBB))
+    return emitInlineAsmError(Call, Info.ErrorMsg.str());
+
+  SDValue Glue = Info.Glue;
+  SDValue Chain = Info.Chain;
+
   // Finish up input operands.  Set the input chain and add the flag last.
-  AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
-  if (Glue.getNode()) AsmNodeOperands.push_back(Glue);
+  Info.AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
+  if (Glue.getNode())
+    Info.AsmNodeOperands.push_back(Glue);
 
+  bool IsCallBr = isa<CallBrInst>(Call);
   unsigned ISDOpc = IsCallBr ? ISD::INLINEASM_BR : ISD::INLINEASM;
-  Chain = DAG.getNode(ISDOpc, getCurSDLoc(),
-                      DAG.getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
+  Chain =
+      DAG.getNode(ISDOpc, getCurSDLoc(), DAG.getVTList(MVT::Other, MVT::Glue),
+                  Info.AsmNodeOperands);
   Glue = Chain.getValue(1);
 
   // Do additional work to generate outputs.
@@ -10664,7 +10716,7 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
   };
 
   // Deal with output operands.
-  for (SDISelAsmOperandInfo &OpInfo : ConstraintOperands) {
+  for (SDISelAsmOperandInfo &OpInfo : Info.ConstraintOperands) {
     if (OpInfo.Type == InlineAsm::isOutput) {
       SDValue Val;
       // Skip trivial output operands.
@@ -10725,13 +10777,12 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
   if (!OutChains.empty())
     Chain = DAG.getNode(ISD::TokenFactor, getCurSDLoc(), MVT::Other, OutChains);
 
-  if (EmitEHLabels) {
-    Chain = lowerEndEH(Chain, cast<InvokeInst>(&Call), EHPadBB, BeginLabel);
-  }
+  if (const auto *II = dyn_cast<InvokeInst>(&Call))
+    Chain = lowerEndEH(Chain, II, EHPadBB, Info.BeginLabel);
 
   // Only Update Root if inline assembly has a memory effect.
-  if (ResultValues.empty() || HasSideEffect || !OutChains.empty() || IsCallBr ||
-      EmitEHLabels)
+  if (ResultValues.empty() || Info.HasSideEffect || !OutChains.empty() ||
+      IsCallBr || isa<InvokeInst>(Call))
     DAG.setRoot(Chain);
 }
 

diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index bab0509dd138f..21aac333a73cd 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -733,8 +733,11 @@ class SelectionDAGBuilder {
                           DIExpression *Expr, const DebugLoc &dl,
                           unsigned DbgSDNodeOrder);
 
+public:
   SDValue lowerStartEH(SDValue Chain, const BasicBlock *EHPadBB,
                        MCSymbol *&BeginLabel);
+
+private:
   SDValue lowerEndEH(SDValue Chain, const InvokeInst *II,
                      const BasicBlock *EHPadBB, MCSymbol *BeginLabel);
 


        


More information about the llvm-commits mailing list