<div dir="ltr"><div>Mike,</div><div><br></div>This was fixed in r265488. The bot is now failing on other testing cases<div><a href="http://lab.llvm.org:8011/builders/clang-cmake-thumbv7-a15-full-sh/builds/3367">http://lab.llvm.org:8011/builders/clang-cmake-thumbv7-a15-full-sh/builds/3367</a></div><div><br></div><div>Manman<br><div><br></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Apr 6, 2016 at 11:26 AM, Mike Aizatsky <span dir="ltr"><<a href="mailto:aizatsky@google.com" target="_blank">aizatsky@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Manman,<div><br></div><div>It looks like this change breaks the arm bot:</div><div><br></div><div><a href="http://lab.llvm.org:8011/builders/clang-cmake-thumbv7-a15-full-sh/builds/3366" target="_blank">http://lab.llvm.org:8011/builders/clang-cmake-thumbv7-a15-full-sh/builds/3366</a><br></div><div><br></div><div><div>Failing Tests (2):</div><div>    Clang :: CodeGen/arm-swiftcall.c</div><div>    Clang :: CodeGenCXX/arm-swiftcall.cpp</div><div><br></div></div><div>Can you take a look?</div><div><div class="h5"><br><div class="gmail_quote"><div dir="ltr">On Tue, Apr 5, 2016 at 11:18 AM Manman Ren via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: mren<br>
Date: Tue Apr  5 13:13:16 2016<br>
New Revision: 265433<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=265433&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=265433&view=rev</a><br>
Log:<br>
Swift Calling Convention: swifterror target-independent change.<br>
<br>
At IR level, the swifterror argument is an input argument with type<br>
ErrorObject**. For targets that support swifterror, we want to optimize it<br>
to behave as an inout value with type ErrorObject*; it will be passed in a<br>
fixed physical register.<br>
<br>
The main idea is to track the virtual registers for each swifterror value. We<br>
define swifterror values as AllocaInsts with swifterror attribute or a function<br>
argument with swifterror attribute.<br>
<br>
In SelectionDAGISel.cpp, we set up swifterror values (SwiftErrorVals) before<br>
handling the basic blocks.<br>
<br>
When iterating over all basic blocks in RPO, before actually visiting the basic<br>
block, we call mergeIncomingSwiftErrors to merge incoming swifterror values when<br>
there are multiple predecessors or to simply propagate them. There, we create a<br>
virtual register for each swifterror value in the entry block. For predecessors<br>
that are not yet visited, we create virtual registers to hold the swifterror<br>
values at the end of the predecessor. The assignments are saved in<br>
SwiftErrorWorklist and will be materialized at the end of visiting the basic<br>
block.<br>
<br>
When visiting a load from a swifterror value, we copy from the current virtual<br>
register assignment. When visiting a store to a swifterror value, we create a<br>
virtual register to hold the swifterror value and update SwiftErrorMap to<br>
track the current virtual register assignment.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D18108" rel="noreferrer" target="_blank">http://reviews.llvm.org/D18108</a><br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h<br>
    llvm/trunk/include/llvm/Target/TargetLowering.h<br>
    llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp<br>
    llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp<br>
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h<br>
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h?rev=265433&r1=265432&r2=265433&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h?rev=265433&r1=265432&r2=265433&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h (original)<br>
+++ llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h Tue Apr  5 13:13:16 2016<br>
@@ -72,6 +72,37 @@ public:<br>
   /// MBBMap - A mapping from LLVM basic blocks to their machine code entry.<br>
   DenseMap<const BasicBlock*, MachineBasicBlock *> MBBMap;<br>
<br>
+  typedef SmallVector<unsigned, 1> SwiftErrorVRegs;<br>
+  typedef SmallVector<const Value*, 1> SwiftErrorValues;<br>
+  /// A function can only have a single swifterror argument. And if it does<br>
+  /// have a swifterror argument, it must be the first entry in<br>
+  /// SwiftErrorVals.<br>
+  SwiftErrorValues SwiftErrorVals;<br>
+<br>
+  /// Track the virtual register for each swifterror value in a given basic<br>
+  /// block. Entries in SwiftErrorVRegs have the same ordering as entries<br>
+  /// in SwiftErrorVals.<br>
+  /// Note that another choice that is more straight-forward is to use<br>
+  /// Map<const MachineBasicBlock*, Map<Value*, unsigned/*VReg*/>>. It<br>
+  /// maintains a map from swifterror values to virtual registers for each<br>
+  /// machine basic block. This choice does not require a one-to-one<br>
+  /// correspondence between SwiftErrorValues and SwiftErrorVRegs. But because<br>
+  /// of efficiency concern, we do not choose it.<br>
+  llvm::DenseMap<const MachineBasicBlock*, SwiftErrorVRegs> SwiftErrorMap;<br>
+<br>
+  /// Track the virtual register for each swifterror value at the end of a basic<br>
+  /// block when we need the assignment of a virtual register before the basic<br>
+  /// block is visited. When we actually visit the basic block, we will make<br>
+  /// sure the swifterror value is in the correct virtual register.<br>
+  llvm::DenseMap<const MachineBasicBlock*, SwiftErrorVRegs><br>
+      SwiftErrorWorklist;<br>
+<br>
+  /// Find the swifterror virtual register in SwiftErrorMap. We will assert<br>
+  /// failure when the value does not exist in swifterror map.<br>
+  unsigned findSwiftErrorVReg(const MachineBasicBlock*, const Value*) const;<br>
+  /// Set the swifterror virtual register in SwiftErrorMap.<br>
+  void setSwiftErrorVReg(const MachineBasicBlock *MBB, const Value*, unsigned);<br>
+<br>
   /// ValueMap - Since we emit code for the function a basic block at a time,<br>
   /// we must remember which virtual registers hold the values for<br>
   /// cross-basic-block values.<br>
<br>
Modified: llvm/trunk/include/llvm/Target/TargetLowering.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=265433&r1=265432&r2=265433&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=265433&r1=265432&r2=265433&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Target/TargetLowering.h (original)<br>
+++ llvm/trunk/include/llvm/Target/TargetLowering.h Tue Apr  5 13:13:16 2016<br>
@@ -2275,6 +2275,12 @@ public:<br>
     return false;<br>
   }<br>
<br>
+  /// Return true if the target supports swifterror attribute. It optimizes<br>
+  /// loads and stores to reading and writing a specific register.<br>
+  virtual bool supportSwiftError() const {<br>
+    return false;<br>
+  }<br>
+<br>
   /// Return true if the target supports that a subset of CSRs for the given<br>
   /// machine function is handled explicitly via copies.<br>
   virtual bool supportSplitCSR(MachineFunction *MF) const {<br>
@@ -2377,6 +2383,7 @@ public:<br>
     SmallVector<ISD::OutputArg, 32> Outs;<br>
     SmallVector<SDValue, 32> OutVals;<br>
     SmallVector<ISD::InputArg, 32> Ins;<br>
+    SmallVector<SDValue, 4> InVals;<br>
<br>
     CallLoweringInfo(SelectionDAG &DAG)<br>
         : RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false),<br>
<br>
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp?rev=265433&r1=265432&r2=265433&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp?rev=265433&r1=265432&r2=265433&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp Tue Apr  5 13:13:16 2016<br>
@@ -1324,6 +1324,15 @@ bool FastISel::selectBitCast(const User<br>
   return true;<br>
 }<br>
<br>
+// Return true if we should copy from swift error to the final vreg as specified<br>
+// by SwiftErrorWorklist.<br>
+static bool shouldCopySwiftErrorsToFinalVRegs(const TargetLowering &TLI,<br>
+                                              FunctionLoweringInfo &FuncInfo) {<br>
+  if (!TLI.supportSwiftError())<br>
+    return false;<br>
+  return FuncInfo.SwiftErrorWorklist.count(FuncInfo.MBB);<br>
+}<br>
+<br>
 // Remove local value instructions starting from the instruction after<br>
 // SavedLastLocalValue to the current function insert point.<br>
 void FastISel::removeDeadLocalValueCode(MachineInstr *SavedLastLocalValue)<br>
@@ -1347,7 +1356,11 @@ bool FastISel::selectInstruction(const I<br>
   MachineInstr *SavedLastLocalValue = getLastLocalValue();<br>
   // Just before the terminator instruction, insert instructions to<br>
   // feed PHI nodes in successor blocks.<br>
-  if (isa<TerminatorInst>(I))<br>
+  if (isa<TerminatorInst>(I)) {<br>
+    // If we need to materialize any vreg from worklist, we bail out of<br>
+    // FastISel.<br>
+    if (shouldCopySwiftErrorsToFinalVRegs(TLI, FuncInfo))<br>
+      return false;<br>
     if (!handlePHINodesInSuccessorBlocks(I->getParent())) {<br>
       // PHI node handling may have generated local value instructions,<br>
       // even though it failed to handle all PHI nodes.<br>
@@ -1356,6 +1369,7 @@ bool FastISel::selectInstruction(const I<br>
       removeDeadLocalValueCode(SavedLastLocalValue);<br>
       return false;<br>
     }<br>
+  }<br>
<br>
   // FastISel does not handle any operand bundles except OB_funclet.<br>
   if (ImmutableCallSite CS = ImmutableCallSite(I))<br>
<br>
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp?rev=265433&r1=265432&r2=265433&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp?rev=265433&r1=265432&r2=265433&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp Tue Apr  5 13:13:16 2016<br>
@@ -595,3 +595,21 @@ void llvm::AddLandingPadInfo(const Landi<br>
     }<br>
   }<br>
 }<br>
+<br>
+unsigned FunctionLoweringInfo::findSwiftErrorVReg(const MachineBasicBlock *MBB,<br>
+                                                  const Value* Val) const {<br>
+  // Find the index in SwiftErrorVals.<br>
+  SwiftErrorValues::const_iterator I =<br>
+      std::find(SwiftErrorVals.begin(), SwiftErrorVals.end(), Val);<br>
+  assert(I != SwiftErrorVals.end() && "Can't find value in SwiftErrorVals");<br>
+  return SwiftErrorMap.lookup(MBB)[I - SwiftErrorVals.begin()];<br>
+}<br>
+<br>
+void FunctionLoweringInfo::setSwiftErrorVReg(const MachineBasicBlock *MBB,<br>
+                                             const Value* Val, unsigned VReg) {<br>
+  // Find the index in SwiftErrorVals.<br>
+  SwiftErrorValues::iterator I =<br>
+      std::find(SwiftErrorVals.begin(), SwiftErrorVals.end(), Val);<br>
+  assert(I != SwiftErrorVals.end() && "Can't find value in SwiftErrorVals");<br>
+  SwiftErrorMap[MBB][I - SwiftErrorVals.begin()] = VReg;<br>
+}<br>
<br>
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=265433&r1=265432&r2=265433&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=265433&r1=265432&r2=265433&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Tue Apr  5 13:13:16 2016<br>
@@ -929,10 +929,48 @@ SDValue SelectionDAGBuilder::getControlR<br>
   return Root;<br>
 }<br>
<br>
+/// Copy swift error to the final virtual register at end of a basic block, as<br>
+/// specified by SwiftErrorWorklist, if necessary.<br>
+static void copySwiftErrorsToFinalVRegs(SelectionDAGBuilder &SDB) {<br>
+  const TargetLowering &TLI = SDB.DAG.getTargetLoweringInfo();<br>
+  if (!TLI.supportSwiftError())<br>
+    return;<br>
+<br>
+  if (!SDB.FuncInfo.SwiftErrorWorklist.count(SDB.FuncInfo.MBB))<br>
+    return;<br>
+<br>
+  // Go through entries in SwiftErrorWorklist, and create copy as necessary.<br>
+  FunctionLoweringInfo::SwiftErrorVRegs &WorklistEntry =<br>
+      SDB.FuncInfo.SwiftErrorWorklist[SDB.FuncInfo.MBB];<br>
+  FunctionLoweringInfo::SwiftErrorVRegs &MapEntry =<br>
+      SDB.FuncInfo.SwiftErrorMap[SDB.FuncInfo.MBB];<br>
+  for (unsigned I = 0, E = WorklistEntry.size(); I < E; I++) {<br>
+    unsigned WorkReg = WorklistEntry[I];<br>
+<br>
+    // Find the swifterror virtual register for the value in SwiftErrorMap.<br>
+    unsigned MapReg = MapEntry[I];<br>
+    assert(TargetRegisterInfo::isVirtualRegister(MapReg) &&<br>
+           "Entries in SwiftErrorMap should be virtual registers");<br>
+<br>
+    if (WorkReg == MapReg)<br>
+      continue;<br>
+<br>
+    // Create copy from SwiftErrorMap to SwiftWorklist.<br>
+    auto &DL = SDB.DAG.getDataLayout();<br>
+    SDValue CopyNode = SDB.DAG.getCopyToReg(<br>
+        SDB.getRoot(), SDB.getCurSDLoc(), WorkReg,<br>
+        SDB.DAG.getRegister(MapReg, EVT(TLI.getPointerTy(DL))));<br>
+    MapEntry[I] = WorkReg;<br>
+    SDB.DAG.setRoot(CopyNode);<br>
+  }<br>
+}<br>
+<br>
 void SelectionDAGBuilder::visit(const Instruction &I) {<br>
   // Set up outgoing PHI node register values before emitting the terminator.<br>
-  if (isa<TerminatorInst>(&I))<br>
+  if (isa<TerminatorInst>(&I)) {<br>
+    copySwiftErrorsToFinalVRegs(*this);<br>
     HandlePHINodesInSuccessorBlocks(I.getParent());<br>
+  }<br>
<br>
   ++SDNodeOrder;<br>
<br>
@@ -1434,6 +1472,23 @@ void SelectionDAGBuilder::visitRet(const<br>
     }<br>
   }<br>
<br>
+  // Push in swifterror virtual register as the last element of Outs. This makes<br>
+  // sure swifterror virtual register will be returned in the swifterror<br>
+  // physical register.<br>
+  const Function *F = I.getParent()->getParent();<br>
+  if (TLI.supportSwiftError() &&<br>
+      F->getAttributes().hasAttrSomewhere(Attribute::SwiftError)) {<br>
+    ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy();<br>
+    Flags.setSwiftError();<br>
+    Outs.push_back(ISD::OutputArg(Flags, EVT(TLI.getPointerTy(DL)) /*vt*/,<br>
+                                  EVT(TLI.getPointerTy(DL)) /*argvt*/,<br>
+                                  true /*isfixed*/, 1 /*origidx*/,<br>
+                                  0 /*partOffs*/));<br>
+    // Create SDNode for the swifterror virtual register.<br>
+    OutVals.push_back(DAG.getRegister(FuncInfo.SwiftErrorMap[FuncInfo.MBB][0],<br>
+                                      EVT(TLI.getPointerTy(DL))));<br>
+  }<br>
+<br>
   bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();<br>
   CallingConv::ID CallConv =<br>
     DAG.getMachineFunction().getFunction()->getCallingConv();<br>
@@ -3308,7 +3363,22 @@ void SelectionDAGBuilder::visitLoad(cons<br>
   if (I.isAtomic())<br>
     return visitAtomicLoad(I);<br>
<br>
+  const TargetLowering &TLI = DAG.getTargetLoweringInfo();<br>
   const Value *SV = I.getOperand(0);<br>
+  if (TLI.supportSwiftError()) {<br>
+    // Swifterror values can come from either a function parameter with<br>
+    // swifterror attribute or an alloca with swifterror attribute.<br>
+    if (const Argument *Arg = dyn_cast<Argument>(SV)) {<br>
+      if (Arg->hasSwiftErrorAttr())<br>
+        return visitLoadFromSwiftError(I);<br>
+    }<br>
+<br>
+    if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(SV)) {<br>
+      if (Alloca->isSwiftError())<br>
+        return visitLoadFromSwiftError(I);<br>
+    }<br>
+  }<br>
+<br>
   SDValue Ptr = getValue(SV);<br>
<br>
   Type *Ty = I.getType();<br>
@@ -3332,7 +3402,6 @@ void SelectionDAGBuilder::visitLoad(cons<br>
   I.getAAMetadata(AAInfo);<br>
   const MDNode *Ranges = I.getMetadata(LLVMContext::MD_range);<br>
<br>
-  const TargetLowering &TLI = DAG.getTargetLoweringInfo();<br>
   SmallVector<EVT, 4> ValueVTs;<br>
   SmallVector<uint64_t, 4> Offsets;<br>
   ComputeValueVTs(TLI, DAG.getDataLayout(), Ty, ValueVTs, &Offsets);<br>
@@ -3409,6 +3478,64 @@ void SelectionDAGBuilder::visitLoad(cons<br>
                            DAG.getVTList(ValueVTs), Values));<br>
 }<br>
<br>
+void SelectionDAGBuilder::visitStoreToSwiftError(const StoreInst &I) {<br>
+  const TargetLowering &TLI = DAG.getTargetLoweringInfo();<br>
+  assert(TLI.supportSwiftError() &&<br>
+         "call visitStoreToSwiftError when backend supports swifterror");<br>
+<br>
+  SmallVector<EVT, 4> ValueVTs;<br>
+  SmallVector<uint64_t, 4> Offsets;<br>
+  const Value *SrcV = I.getOperand(0);<br>
+  ComputeValueVTs(DAG.getTargetLoweringInfo(), DAG.getDataLayout(),<br>
+                  SrcV->getType(), ValueVTs, &Offsets);<br>
+  assert(ValueVTs.size() == 1 && Offsets[0] == 0 &&<br>
+         "expect a single EVT for swifterror");<br>
+<br>
+  SDValue Src = getValue(SrcV);<br>
+  // Create a virtual register, then update the virtual register.<br>
+  auto &DL = DAG.getDataLayout();<br>
+  const TargetRegisterClass *RC = TLI.getRegClassFor(TLI.getPointerTy(DL));<br>
+  unsigned VReg = FuncInfo.MF->getRegInfo().createVirtualRegister(RC);<br>
+  // Chain, DL, Reg, N or Chain, DL, Reg, N, Glue<br>
+  // Chain can be getRoot or getControlRoot.<br>
+  SDValue CopyNode = DAG.getCopyToReg(getRoot(), getCurSDLoc(), VReg,<br>
+                                      SDValue(Src.getNode(), Src.getResNo()));<br>
+  DAG.setRoot(CopyNode);<br>
+  FuncInfo.setSwiftErrorVReg(FuncInfo.MBB, I.getOperand(1), VReg);<br>
+}<br>
+<br>
+void SelectionDAGBuilder::visitLoadFromSwiftError(const LoadInst &I) {<br>
+  assert(DAG.getTargetLoweringInfo().supportSwiftError() &&<br>
+         "call visitLoadFromSwiftError when backend supports swifterror");<br>
+<br>
+  assert(!I.isVolatile() &&<br>
+         I.getMetadata(LLVMContext::MD_nontemporal) == nullptr &&<br>
+         I.getMetadata(LLVMContext::MD_invariant_load) == nullptr &&<br>
+         "Support volatile, non temporal, invariant for load_from_swift_error");<br>
+<br>
+  const Value *SV = I.getOperand(0);<br>
+  Type *Ty = I.getType();<br>
+  AAMDNodes AAInfo;<br>
+  I.getAAMetadata(AAInfo);<br>
+  assert(!AA->pointsToConstantMemory(MemoryLocation(<br>
+             SV, DAG.getDataLayout().getTypeStoreSize(Ty), AAInfo)) &&<br>
+         "load_from_swift_error should not be constant memory");<br>
+<br>
+  SmallVector<EVT, 4> ValueVTs;<br>
+  SmallVector<uint64_t, 4> Offsets;<br>
+  ComputeValueVTs(DAG.getTargetLoweringInfo(), DAG.getDataLayout(), Ty,<br>
+                  ValueVTs, &Offsets);<br>
+  assert(ValueVTs.size() == 1 && Offsets[0] == 0 &&<br>
+         "expect a single EVT for swifterror");<br>
+<br>
+  // Chain, DL, Reg, VT, Glue or Chain, DL, Reg, VT<br>
+  SDValue L = DAG.getCopyFromReg(getRoot(), getCurSDLoc(),<br>
+                                 FuncInfo.findSwiftErrorVReg(FuncInfo.MBB, SV),<br>
+                                 ValueVTs[0]);<br>
+<br>
+  setValue(&I, L);<br>
+}<br>
+<br>
 void SelectionDAGBuilder::visitStore(const StoreInst &I) {<br>
   if (I.isAtomic())<br>
     return visitAtomicStore(I);<br>
@@ -3416,6 +3543,21 @@ void SelectionDAGBuilder::visitStore(con<br>
   const Value *SrcV = I.getOperand(0);<br>
   const Value *PtrV = I.getOperand(1);<br>
<br>
+  const TargetLowering &TLI = DAG.getTargetLoweringInfo();<br>
+  if (TLI.supportSwiftError()) {<br>
+    // Swifterror values can come from either a function parameter with<br>
+    // swifterror attribute or an alloca with swifterror attribute.<br>
+    if (const Argument *Arg = dyn_cast<Argument>(PtrV)) {<br>
+      if (Arg->hasSwiftErrorAttr())<br>
+        return visitStoreToSwiftError(I);<br>
+    }<br>
+<br>
+    if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(PtrV)) {<br>
+      if (Alloca->isSwiftError())<br>
+        return visitStoreToSwiftError(I);<br>
+    }<br>
+  }<br>
+<br>
   SmallVector<EVT, 4> ValueVTs;<br>
   SmallVector<uint64_t, 4> Offsets;<br>
   ComputeValueVTs(DAG.getTargetLoweringInfo(), DAG.getDataLayout(),<br>
@@ -5552,6 +5694,7 @@ SelectionDAGBuilder::lowerInvokable(Targ<br>
 void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee,<br>
                                       bool isTailCall,<br>
                                       const BasicBlock *EHPadBB) {<br>
+  auto &DL = DAG.getDataLayout();<br>
   FunctionType *FTy = CS.getFunctionType();<br>
   Type *RetTy = CS.getType();<br>
<br>
@@ -5559,6 +5702,8 @@ void SelectionDAGBuilder::LowerCallTo(Im<br>
   TargetLowering::ArgListEntry Entry;<br>
   Args.reserve(CS.arg_size());<br>
<br>
+  const Value *SwiftErrorVal = nullptr;<br>
+  const TargetLowering &TLI = DAG.getTargetLoweringInfo();<br>
   for (ImmutableCallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end();<br>
        i != e; ++i) {<br>
     const Value *V = *i;<br>
@@ -5572,6 +5717,17 @@ void SelectionDAGBuilder::LowerCallTo(Im<br>
<br>
     // Skip the first return-type Attribute to get to params.<br>
     Entry.setAttributes(&CS, i - CS.arg_begin() + 1);<br>
+<br>
+    // Use swifterror virtual register as input to the call.<br>
+    if (Entry.isSwiftError && TLI.supportSwiftError()) {<br>
+      SwiftErrorVal = V;<br>
+      // We find the virtual register for the actual swifterror argument.<br>
+      // Instead of using the Value, we use the virtual register instead.<br>
+      Entry.Node = DAG.getRegister(<br>
+          FuncInfo.findSwiftErrorVReg(FuncInfo.MBB, V),<br>
+          EVT(TLI.getPointerTy(DL)));<br>
+    }<br>
+<br>
     Args.push_back(Entry);<br>
<br>
     // If we have an explicit sret argument that is an Instruction, (i.e., it<br>
@@ -5598,6 +5754,20 @@ void SelectionDAGBuilder::LowerCallTo(Im<br>
     Result.first = lowerRangeToAssertZExt(DAG, *Inst, Result.first);<br>
     setValue(Inst, Result.first);<br>
   }<br>
+<br>
+  // The last element of CLI.InVals has the SDValue for swifterror return.<br>
+  // Here we copy it to a virtual register and update SwiftErrorMap for<br>
+  // book-keeping.<br>
+  if (SwiftErrorVal && TLI.supportSwiftError()) {<br>
+    // Get the last element of InVals.<br>
+    SDValue Src = CLI.InVals.back();<br>
+    const TargetRegisterClass *RC = TLI.getRegClassFor(TLI.getPointerTy(DL));<br>
+    unsigned VReg = FuncInfo.MF->getRegInfo().createVirtualRegister(RC);<br>
+    SDValue CopyNode = CLI.DAG.getCopyToReg(Result.second, CLI.DL, VReg, Src);<br>
+    // We update the virtual register for the actual swifterror argument.<br>
+    FuncInfo.setSwiftErrorVReg(FuncInfo.MBB, SwiftErrorVal, VReg);<br>
+    DAG.setRoot(CopyNode);<br>
+  }<br>
 }<br>
<br>
 /// IsOnlyUsedInZeroEqualityComparison - Return true if it only matters that the<br>
@@ -7311,10 +7481,23 @@ TargetLowering::LowerCallTo(TargetLoweri<br>
     }<br>
   }<br>
<br>
+  // We push in swifterror return as the last element of CLI.Ins.<br>
+  ArgListTy &Args = CLI.getArgs();<br>
+  if (supportSwiftError()) {<br>
+    for (unsigned i = 0, e = Args.size(); i != e; ++i) {<br>
+      if (Args[i].isSwiftError) {<br>
+        ISD::InputArg MyFlags;<br>
+        MyFlags.VT = getPointerTy(DL);<br>
+        MyFlags.ArgVT = EVT(getPointerTy(DL));<br>
+        MyFlags.Flags.setSwiftError();<br>
+        CLI.Ins.push_back(MyFlags);<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
   // Handle all of the outgoing arguments.<br>
   CLI.Outs.clear();<br>
   CLI.OutVals.clear();<br>
-  ArgListTy &Args = CLI.getArgs();<br>
   for (unsigned i = 0, e = Args.size(); i != e; ++i) {<br>
     SmallVector<EVT, 4> ValueVTs;<br>
     ComputeValueVTs(*this, DL, Args[i].Ty, ValueVTs);<br>
@@ -7432,6 +7615,9 @@ TargetLowering::LowerCallTo(TargetLoweri<br>
   SmallVector<SDValue, 4> InVals;<br>
   CLI.Chain = LowerCall(CLI, InVals);<br>
<br>
+  // Update CLI.InVals to use outside of this function.<br>
+  CLI.InVals = InVals;<br>
+<br>
   // Verify that the target's LowerCall behaved as expected.<br>
   assert(CLI.Chain.getNode() && CLI.Chain.getValueType() == MVT::Other &&<br>
          "LowerCall didn't return a valid chain!");<br>
@@ -7793,6 +7979,14 @@ void SelectionDAGISel::LowerArguments(co<br>
         FuncInfo->setArgumentFrameIndex(&*I, FI->getIndex());<br>
     }<br>
<br>
+    // Update SwiftErrorMap.<br>
+    if (Res.getOpcode() == ISD::CopyFromReg && TLI->supportSwiftError() &&<br>
+        F.getAttributes().hasAttribute(Idx, Attribute::SwiftError)) {<br>
+      unsigned Reg = cast<RegisterSDNode>(Res.getOperand(1))->getReg();<br>
+      if (TargetRegisterInfo::isVirtualRegister(Reg))<br>
+        FuncInfo->SwiftErrorMap[FuncInfo->MBB][0] = Reg;<br>
+    }<br>
+<br>
     // If this argument is live outside of the entry block, insert a copy from<br>
     // wherever we got it to the vreg that other BB's will reference it as.<br>
     if (!TM.Options.EnableFastISel && Res.getOpcode() == ISD::CopyFromReg) {<br>
<br>
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h?rev=265433&r1=265432&r2=265433&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h?rev=265433&r1=265432&r2=265433&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h (original)<br>
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h Tue Apr  5 13:13:16 2016<br>
@@ -895,6 +895,8 @@ private:<br>
   bool visitBinaryFloatCall(const CallInst &I, unsigned Opcode);<br>
   void visitAtomicLoad(const LoadInst &I);<br>
   void visitAtomicStore(const StoreInst &I);<br>
+  void visitLoadFromSwiftError(const LoadInst &I);<br>
+  void visitStoreToSwiftError(const StoreInst &I);<br>
<br>
   void visitInlineAsm(ImmutableCallSite CS);<br>
   const char *visitIntrinsicCall(const CallInst &I, unsigned Intrinsic);<br>
<br>
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=265433&r1=265432&r2=265433&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=265433&r1=265432&r2=265433&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Tue Apr  5 13:13:16 2016<br>
@@ -1159,12 +1159,132 @@ static void collectFailStats(const Instr<br>
 }<br>
 #endif // NDEBUG<br>
<br>
+/// Set up SwiftErrorVals by going through the function. If the function has<br>
+/// swifterror argument, it will be the first entry.<br>
+static void setupSwiftErrorVals(const Function &Fn, const TargetLowering *TLI,<br>
+                                FunctionLoweringInfo *FuncInfo) {<br>
+  if (!TLI->supportSwiftError())<br>
+    return;<br>
+<br>
+  FuncInfo->SwiftErrorVals.clear();<br>
+  FuncInfo->SwiftErrorMap.clear();<br>
+  FuncInfo->SwiftErrorWorklist.clear();<br>
+<br>
+  // Check if function has a swifterror argument.<br>
+  for (Function::const_arg_iterator AI = Fn.arg_begin(), AE = Fn.arg_end();<br>
+       AI != AE; ++AI)<br>
+    if (AI->hasSwiftErrorAttr())<br>
+      FuncInfo->SwiftErrorVals.push_back(&*AI);<br>
+<br>
+  for (const auto &LLVMBB : Fn)<br>
+    for (const auto &Inst : LLVMBB) {<br>
+      if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(&Inst))<br>
+        if (Alloca->isSwiftError())<br>
+          FuncInfo->SwiftErrorVals.push_back(Alloca);<br>
+    }<br>
+}<br>
+<br>
+/// For each basic block, merge incoming swifterror values or simply propagate<br>
+/// them. The merged results will be saved in SwiftErrorMap. For predecessors<br>
+/// that are not yet visited, we create virtual registers to hold the swifterror<br>
+/// values and save them in SwiftErrorWorklist.<br>
+static void mergeIncomingSwiftErrors(FunctionLoweringInfo *FuncInfo,<br>
+                            const TargetLowering *TLI,<br>
+                            const TargetInstrInfo *TII,<br>
+                            const BasicBlock *LLVMBB,<br>
+                            SelectionDAGBuilder *SDB) {<br>
+  if (!TLI->supportSwiftError())<br>
+    return;<br>
+<br>
+  // We should only do this when we have swifterror parameter or swifterror<br>
+  // alloc.<br>
+  if (FuncInfo->SwiftErrorVals.empty())<br>
+    return;<br>
+<br>
+  // At beginning of a basic block, insert PHI nodes or get the virtual<br>
+  // register from the only predecessor, and update SwiftErrorMap; if one<br>
+  // of the predecessors is not visited, update SwiftErrorWorklist.<br>
+  // At end of a basic block, if a block is in SwiftErrorWorklist, insert copy<br>
+  // to sync up the virtual register assignment.<br>
+<br>
+  // Always create a virtual register for each swifterror value in entry block.<br>
+  auto &DL = SDB->DAG.getDataLayout();<br>
+  const TargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));<br>
+  if (pred_begin(LLVMBB) == pred_end(LLVMBB)) {<br>
+    for (unsigned I = 0, E = FuncInfo->SwiftErrorVals.size(); I < E; I++) {<br>
+      unsigned VReg = FuncInfo->MF->getRegInfo().createVirtualRegister(RC);<br>
+      // Assign Undef to Vreg. We construct MI directly to make sure it works<br>
+      // with FastISel.<br>
+      BuildMI(*FuncInfo->MBB, FuncInfo->InsertPt, SDB->getCurDebugLoc(),<br>
+          TII->get(TargetOpcode::IMPLICIT_DEF), VReg);<br>
+      FuncInfo->SwiftErrorMap[FuncInfo->MBB].push_back(VReg);<br>
+    }<br>
+    return;<br>
+  }<br>
+<br>
+  if (auto *UniquePred = LLVMBB->getUniquePredecessor()) {<br>
+    auto *UniquePredMBB = FuncInfo->MBBMap[UniquePred];<br>
+    if (!FuncInfo->SwiftErrorMap.count(UniquePredMBB)) {<br>
+      // Update SwiftErrorWorklist with a new virtual register.<br>
+      for (unsigned I = 0, E = FuncInfo->SwiftErrorVals.size(); I < E; I++) {<br>
+        unsigned VReg = FuncInfo->MF->getRegInfo().createVirtualRegister(RC);<br>
+        FuncInfo->SwiftErrorWorklist[UniquePredMBB].push_back(VReg);<br>
+        // Propagate the information from the single predecessor.<br>
+        FuncInfo->SwiftErrorMap[FuncInfo->MBB].push_back(VReg);<br>
+      }<br>
+      return;<br>
+    }<br>
+    // Propagate the information from the single predecessor.<br>
+    FuncInfo->SwiftErrorMap[FuncInfo->MBB] =<br>
+      FuncInfo->SwiftErrorMap[UniquePredMBB];<br>
+    return;<br>
+  }<br>
+<br>
+  // For the case of multiple predecessors, update SwiftErrorWorklist.<br>
+  // Handle the case where we have two or more predecessors being the same.<br>
+  for (const_pred_iterator PI = pred_begin(LLVMBB), PE = pred_end(LLVMBB);<br>
+       PI != PE; ++PI) {<br>
+    auto *PredMBB = FuncInfo->MBBMap[*PI];<br>
+    if (!FuncInfo->SwiftErrorMap.count(PredMBB) &&<br>
+        !FuncInfo->SwiftErrorWorklist.count(PredMBB)) {<br>
+      for (unsigned I = 0, E = FuncInfo->SwiftErrorVals.size(); I < E; I++) {<br>
+        unsigned VReg = FuncInfo->MF->getRegInfo().createVirtualRegister(RC);<br>
+        // When we actually visit the basic block PredMBB, we will materialize<br>
+        // the virtual register assignment in copySwiftErrorsToFinalVRegs.<br>
+        FuncInfo->SwiftErrorWorklist[PredMBB].push_back(VReg);<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
+  // For the case of multiple predecessors, create a virtual register for<br>
+  // each swifterror value and generate Phi node.<br>
+  for (unsigned I = 0, E = FuncInfo->SwiftErrorVals.size(); I < E; I++) {<br>
+    unsigned VReg = FuncInfo->MF->getRegInfo().createVirtualRegister(RC);<br>
+    FuncInfo->SwiftErrorMap[FuncInfo->MBB].push_back(VReg);<br>
+<br>
+    MachineInstrBuilder SwiftErrorPHI = BuildMI(*FuncInfo->MBB,<br>
+        FuncInfo->MBB->begin(), SDB->getCurDebugLoc(),<br>
+        TII->get(TargetOpcode::PHI), VReg);<br>
+    for (const_pred_iterator PI = pred_begin(LLVMBB), PE = pred_end(LLVMBB);<br>
+         PI != PE; ++PI) {<br>
+      auto *PredMBB = FuncInfo->MBBMap[*PI];<br>
+      unsigned SwiftErrorReg = FuncInfo->SwiftErrorMap.count(PredMBB) ?<br>
+        FuncInfo->SwiftErrorMap[PredMBB][I] :<br>
+        FuncInfo->SwiftErrorWorklist[PredMBB][I];<br>
+      SwiftErrorPHI.addReg(SwiftErrorReg)<br>
+                   .addMBB(PredMBB);<br>
+    }<br>
+  }<br>
+}<br>
+<br>
 void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {<br>
   // Initialize the Fast-ISel state, if needed.<br>
   FastISel *FastIS = nullptr;<br>
   if (TM.Options.EnableFastISel)<br>
     FastIS = TLI->createFastISel(*FuncInfo, LibInfo);<br>
<br>
+  setupSwiftErrorVals(Fn, TLI, FuncInfo);<br>
+<br>
   // Iterate over all basic blocks in the function.<br>
   ReversePostOrderTraversal<const Function*> RPOT(&Fn);<br>
   for (ReversePostOrderTraversal<const Function*>::rpo_iterator<br>
@@ -1203,6 +1323,7 @@ void SelectionDAGISel::SelectAllBasicBlo<br>
     if (!FuncInfo->MBB)<br>
       continue; // Some blocks like catchpads have no code or MBB.<br>
     FuncInfo->InsertPt = FuncInfo->MBB->getFirstNonPHI();<br>
+    mergeIncomingSwiftErrors(FuncInfo, TLI, TII, LLVMBB, SDB);<br>
<br>
     // Setup an EH landing-pad block.<br>
     FuncInfo->ExceptionPointerVirtReg = 0;<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div></div></div><span class="HOEnZb"><font color="#888888"><div dir="ltr">-- <br></div>Mike<br>Sent from phone
</font></span></blockquote></div><br></div>