[llvm-commits] [llvm] r50663 - in /llvm/trunk: include/llvm/ include/llvm/CodeGen/ include/llvm/Target/ lib/CodeGen/ lib/CodeGen/SelectionDAG/ lib/Target/ lib/Target/X86/ test/CodeGen/X86/

Andrew Lenharth andrewl at lenharth.org
Thu Jun 5 14:35:16 PDT 2008


The language reference needs to be updated with these intrinsics.

Andrew

On Mon, May 5, 2008 at 2:05 PM, Mon P Wang <wangmp at apple.com> wrote:
> Author: wangmp
> Date: Mon May  5 14:05:59 2008
> New Revision: 50663
>
> URL: http://llvm.org/viewvc/llvm-project?rev=50663&view=rev
> Log:
> Added addition atomic instrinsics and, or, xor, min, and max.
>
> Added:
>    llvm/trunk/test/CodeGen/X86/atomic_op.ll
> Modified:
>    llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h
>    llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
>    llvm/trunk/include/llvm/Intrinsics.td
>    llvm/trunk/include/llvm/Target/TargetLowering.h
>    llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp
>    llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
>    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
>    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
>    llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
>    llvm/trunk/lib/Target/TargetSelectionDAG.td
>    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
>    llvm/trunk/lib/Target/X86/X86ISelLowering.h
>    llvm/trunk/lib/Target/X86/X86InstrInfo.td
>    llvm/trunk/lib/Target/X86/X86Subtarget.cpp
>
> Modified: llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h?rev=50663&r1=50662&r2=50663&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h Mon May  5 14:05:59 2008
> @@ -236,6 +236,11 @@
>   ///
>   succ_iterator removeSuccessor(succ_iterator I);
>
> +  /// transferSuccessors - Transfers all the successors from MBB to this
> +  /// machine basic block (i.e., copies all the successors fromMBB and
> +  /// remove all the successors fromBB).
> +  void transferSuccessors(MachineBasicBlock *fromMBB);
> +
>   /// isSuccessor - Return true if the specified MBB is a successor of this
>   /// block.
>   bool isSuccessor(MachineBasicBlock *MBB) const;
>
> Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=50663&r1=50662&r2=50663&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Mon May  5 14:05:59 2008
> @@ -594,6 +594,24 @@
>     // the return is always the original value in *ptr
>     ATOMIC_SWAP,
>
> +    // Val, OUTCHAIN = ATOMIC_LSS(INCHAIN, ptr, amt)
> +    // this corresponds to the atomic.lss intrinsic.
> +    // *ptr - amt is stored to *ptr atomically.
> +    // the return is always the original value in *ptr
> +    ATOMIC_LSS,
> +
> +    // Val, OUTCHAIN = ATOMIC_L[OpName]S(INCHAIN, ptr, amt)
> +    // this corresponds to the atomic.[OpName] intrinsic.
> +    // op(*ptr, amt) is stored to *ptr atomically.
> +    // the return is always the original value in *ptr
> +    ATOMIC_LOAD_AND,
> +    ATOMIC_LOAD_OR,
> +    ATOMIC_LOAD_XOR,
> +    ATOMIC_LOAD_MIN,
> +    ATOMIC_LOAD_MAX,
> +    ATOMIC_LOAD_UMIN,
> +    ATOMIC_LOAD_UMAX,
> +
>     // BUILTIN_OP_END - This must be the last enum value in this list.
>     BUILTIN_OP_END
>   };
>
> Modified: llvm/trunk/include/llvm/Intrinsics.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Intrinsics.td?rev=50663&r1=50662&r2=50663&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Intrinsics.td (original)
> +++ llvm/trunk/include/llvm/Intrinsics.td Mon May  5 14:05:59 2008
> @@ -267,22 +267,62 @@
>  def int_memory_barrier : Intrinsic<[llvm_void_ty, llvm_i1_ty, llvm_i1_ty,
>                                     llvm_i1_ty, llvm_i1_ty, llvm_i1_ty], []>;
>
> -def int_atomic_lcs  : Intrinsic<[llvm_anyint_ty,
> -                                 LLVMPointerType<LLVMMatchType<0>>,
> -                                 LLVMMatchType<0>, LLVMMatchType<0>],
> +def int_atomic_lcs   : Intrinsic<[llvm_anyint_ty,
> +                                  LLVMPointerType<LLVMMatchType<0>>,
> +                                  LLVMMatchType<0>, LLVMMatchType<0>],
> +                                 [IntrWriteArgMem]>,
> +                       GCCBuiltin<"__sync_val_compare_and_swap">;
> +def int_atomic_las   : Intrinsic<[llvm_anyint_ty,
> +                                  LLVMPointerType<LLVMMatchType<0>>,
> +                                  LLVMMatchType<0>],
> +                                 [IntrWriteArgMem]>,
> +                       GCCBuiltin<"__sync_fetch_and_add">;
> +def int_atomic_swap   : Intrinsic<[llvm_anyint_ty,
> +                                  LLVMPointerType<LLVMMatchType<0>>,
> +                                  LLVMMatchType<0>],
>                                 [IntrWriteArgMem]>,
> -                      GCCBuiltin<"__sync_val_compare_and_swap">;
> -def int_atomic_las  : Intrinsic<[llvm_anyint_ty,
> -                                 LLVMPointerType<LLVMMatchType<0>>,
> -                                 LLVMMatchType<0>],
> -                                [IntrWriteArgMem]>,
> -                      GCCBuiltin<"__sync_fetch_and_add">;
> -def int_atomic_swap : Intrinsic<[llvm_anyint_ty,
> -                                 LLVMPointerType<LLVMMatchType<0>>,
> -                                 LLVMMatchType<0>],
> -                               [IntrWriteArgMem]>,
> -                      GCCBuiltin<"__sync_lock_test_and_set">;
> -
> +                       GCCBuiltin<"__sync_lock_test_and_set">;
> +def int_atomic_lss   : Intrinsic<[llvm_anyint_ty,
> +                                  LLVMPointerType<LLVMMatchType<0>>,
> +                                  LLVMMatchType<0>],
> +                                 [IntrWriteArgMem]>,
> +                       GCCBuiltin<"__sync_fetch_and_sub">;
> +def int_atomic_load_and : Intrinsic<[llvm_anyint_ty,
> +                                  LLVMPointerType<LLVMMatchType<0>>,
> +                                  LLVMMatchType<0>],
> +                                 [IntrWriteArgMem]>,
> +                           GCCBuiltin<"__sync_fetch_and_and">;
> +def int_atomic_load_or   : Intrinsic<[llvm_anyint_ty,
> +                                  LLVMPointerType<LLVMMatchType<0>>,
> +                                  LLVMMatchType<0>],
> +                                 [IntrWriteArgMem]>,
> +                           GCCBuiltin<"__sync_fetch_and_or">;
> +def int_atomic_load_xor  : Intrinsic<[llvm_anyint_ty,
> +                                  LLVMPointerType<LLVMMatchType<0>>,
> +                                  LLVMMatchType<0>],
> +                                 [IntrWriteArgMem]>,
> +                           GCCBuiltin<"__sync_fetch_and_xor">;
> +def int_atomic_load_min  : Intrinsic<[llvm_anyint_ty,
> +                                   LLVMPointerType<LLVMMatchType<0>>,
> +                                   LLVMMatchType<0>],
> +                                  [IntrWriteArgMem]>,
> +                           GCCBuiltin<"__sync_fetch_and_min">;
> +def int_atomic_load_max  : Intrinsic<[llvm_anyint_ty,
> +                                   LLVMPointerType<LLVMMatchType<0>>,
> +                                   LLVMMatchType<0>],
> +                                  [IntrWriteArgMem]>,
> +                           GCCBuiltin<"__sync_fetch_and_max">;
> +def int_atomic_load_umin : Intrinsic<[llvm_anyint_ty,
> +                                   LLVMPointerType<LLVMMatchType<0>>,
> +                                   LLVMMatchType<0>],
> +                                  [IntrWriteArgMem]>,
> +                           GCCBuiltin<"__sync_fetch_and_umin">;
> +def int_atomic_load_umax : Intrinsic<[llvm_anyint_ty,
> +                                   LLVMPointerType<LLVMMatchType<0>>,
> +                                   LLVMMatchType<0>],
> +                                  [IntrWriteArgMem]>,
> +                           GCCBuiltin<"__sync_fetch_and_umax">;
> +
>  //===-------------------------- Other Intrinsics --------------------------===//
>  //
>  def int_flt_rounds : Intrinsic<[llvm_i32_ty]>,
>
> Modified: llvm/trunk/include/llvm/Target/TargetLowering.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=50663&r1=50662&r2=50663&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Target/TargetLowering.h (original)
> +++ llvm/trunk/include/llvm/Target/TargetLowering.h Mon May  5 14:05:59 2008
> @@ -1340,12 +1340,15 @@
>   /// by the system, this holds the same type (e.g. i32 -> i32).
>   MVT::ValueType TransformToType[MVT::LAST_VALUETYPE];
>
> +  // Defines the capacity of the TargetLowering::OpActions table
> +  static const int OpActionsCapacity = 173;
> +
>   /// OpActions - For each operation and each value type, keep a LegalizeAction
>   /// that indicates how instruction selection should deal with the operation.
>   /// Most operations are Legal (aka, supported natively by the target), but
>   /// operations that are not should be described.  Note that operations on
>   /// non-legal value types are not described here.
> -  uint64_t OpActions[156];
> +  uint64_t OpActions[OpActionsCapacity];
>
>   /// LoadXActions - For each load of load extension type and each value type,
>   /// keep a LegalizeAction that indicates how instruction selection should deal
> @@ -1378,7 +1381,7 @@
>   /// TargetDAGCombineArray - Targets can specify ISD nodes that they would
>   /// like PerformDAGCombine callbacks for by calling setTargetDAGCombine(),
>   /// which sets a bit in this array.
> -  unsigned char TargetDAGCombineArray[160/(sizeof(unsigned char)*8)];
> +  unsigned char TargetDAGCombineArray[168/(sizeof(unsigned char)*8)];
>
>   /// PromoteToType - For operations that must be promoted to a specific type,
>   /// this holds the destination type.  This map should be sparse, so don't hold
>
> Modified: llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp?rev=50663&r1=50662&r2=50663&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp (original)
> +++ llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp Mon May  5 14:05:59 2008
> @@ -252,6 +252,19 @@
>   Predecessors.erase(I);
>  }
>
> +void MachineBasicBlock::transferSuccessors(MachineBasicBlock *fromMBB)
> +{
> +  if (this == fromMBB)
> +    return;
> +
> +  for(MachineBasicBlock::succ_iterator iter = fromMBB->succ_begin(),
> +      end = fromMBB->succ_end(); iter != end; ++iter) {
> +      addSuccessor(*iter);
> +  }
> +  while(!fromMBB->succ_empty())
> +    fromMBB->removeSuccessor(fromMBB->succ_begin());
> +}
> +
>  bool MachineBasicBlock::isSuccessor(MachineBasicBlock *MBB) const {
>   std::vector<MachineBasicBlock *>::const_iterator I =
>     std::find(Successors.begin(), Successors.end(), MBB);
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp?rev=50663&r1=50662&r2=50663&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Mon May  5 14:05:59 2008
> @@ -1235,32 +1235,58 @@
>     break;
>   }
>
> -  case ISD::ATOMIC_LCS:
> +  case ISD::ATOMIC_LCS: {
> +    unsigned int num_operands = 4;
> +    assert(Node->getNumOperands() == num_operands && "Invalid Atomic node!");
> +    SDOperand Ops[4];
> +    for (unsigned int x = 0; x < num_operands; ++x)
> +      Ops[x] = LegalizeOp(Node->getOperand(x));
> +    Result = DAG.UpdateNodeOperands(Result, &Ops[0], num_operands);
> +
> +    switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
> +      default: assert(0 && "This action is not supported yet!");
> +      case TargetLowering::Custom:
> +        Result = TLI.LowerOperation(Result, DAG);
> +        break;
> +      case TargetLowering::Legal:
> +        break;
> +    }
> +    AddLegalizedOperand(SDOperand(Node, 0), Result.getValue(0));
> +    AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1));
> +    return Result.getValue(Op.ResNo);
> +  }
>   case ISD::ATOMIC_LAS:
> +  case ISD::ATOMIC_LSS:
> +  case ISD::ATOMIC_LOAD_AND:
> +  case ISD::ATOMIC_LOAD_OR:
> +  case ISD::ATOMIC_LOAD_XOR:
> +  case ISD::ATOMIC_LOAD_MIN:
> +  case ISD::ATOMIC_LOAD_MAX:
> +  case ISD::ATOMIC_LOAD_UMIN:
> +  case ISD::ATOMIC_LOAD_UMAX:
>   case ISD::ATOMIC_SWAP: {
> -    assert(((Node->getNumOperands() == 4 && Node->getOpcode() == ISD::ATOMIC_LCS) ||
> -            (Node->getNumOperands() == 3 && Node->getOpcode() == ISD::ATOMIC_LAS) ||
> -            (Node->getNumOperands() == 3 && Node->getOpcode() == ISD::ATOMIC_SWAP)) &&
> -           "Invalid Atomic node!");
> -    int num = Node->getOpcode() == ISD::ATOMIC_LCS ? 4 : 3;
> -    SDOperand Ops[4];
> -    for (int x = 0; x < num; ++x)
> +    unsigned int num_operands = 3;
> +    assert(Node->getNumOperands() == num_operands && "Invalid Atomic node!");
> +    SDOperand Ops[3];
> +    for (unsigned int x = 0; x < num_operands; ++x)
>       Ops[x] = LegalizeOp(Node->getOperand(x));
> -    Result = DAG.UpdateNodeOperands(Result, &Ops[0], num);
> +    Result = DAG.UpdateNodeOperands(Result, &Ops[0], num_operands);
>
>     switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
>     default: assert(0 && "This action is not supported yet!");
>     case TargetLowering::Custom:
>       Result = TLI.LowerOperation(Result, DAG);
>       break;
> +    case TargetLowering::Expand:
> +      Result = SDOperand(TLI.ExpandOperationResult(Op.Val, DAG),0);
> +      break;
>     case TargetLowering::Legal:
>       break;
>     }
>     AddLegalizedOperand(SDOperand(Node, 0), Result.getValue(0));
>     AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1));
>     return Result.getValue(Op.ResNo);
> -  }
> -
> +  }
>   case ISD::Constant: {
>     ConstantSDNode *CN = cast<ConstantSDNode>(Node);
>     unsigned opAction =
> @@ -4242,6 +4268,14 @@
>     break;
>   }
>   case ISD::ATOMIC_LAS:
> +  case ISD::ATOMIC_LSS:
> +  case ISD::ATOMIC_LOAD_AND:
> +  case ISD::ATOMIC_LOAD_OR:
> +  case ISD::ATOMIC_LOAD_XOR:
> +  case ISD::ATOMIC_LOAD_MIN:
> +  case ISD::ATOMIC_LOAD_MAX:
> +  case ISD::ATOMIC_LOAD_UMIN:
> +  case ISD::ATOMIC_LOAD_UMAX:
>   case ISD::ATOMIC_SWAP: {
>     Tmp2 = PromoteOp(Node->getOperand(2));
>     Result = DAG.getAtomic(Node->getOpcode(), Node->getOperand(0),
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=50663&r1=50662&r2=50663&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Mon May  5 14:05:59 2008
> @@ -2855,7 +2855,11 @@
>  SDOperand SelectionDAG::getAtomic(unsigned Opcode, SDOperand Chain,
>                                   SDOperand Ptr, SDOperand Val,
>                                   MVT::ValueType VT) {
> -  assert((Opcode == ISD::ATOMIC_LAS || Opcode == ISD::ATOMIC_SWAP)
> +  assert((   Opcode == ISD::ATOMIC_LAS || Opcode == ISD::ATOMIC_LSS
> +          || Opcode == ISD::ATOMIC_SWAP || Opcode == ISD::ATOMIC_LOAD_AND
> +          || Opcode == ISD::ATOMIC_LOAD_OR || Opcode == ISD::ATOMIC_LOAD_XOR
> +          || Opcode == ISD::ATOMIC_LOAD_MIN || Opcode == ISD::ATOMIC_LOAD_MAX
> +          || Opcode == ISD::ATOMIC_LOAD_UMIN || Opcode == ISD::ATOMIC_LOAD_UMAX)
>          && "Invalid Atomic Op");
>   SDVTList VTs = getVTList(Val.getValueType(), MVT::Other);
>   FoldingSetNodeID ID;
> @@ -4269,7 +4273,15 @@
>   case ISD::MEMBARRIER:    return "MemBarrier";
>   case ISD::ATOMIC_LCS:    return "AtomicLCS";
>   case ISD::ATOMIC_LAS:    return "AtomicLAS";
> -  case ISD::ATOMIC_SWAP:    return "AtomicSWAP";
> +  case ISD::ATOMIC_LSS:    return "AtomicLSS";
> +  case ISD::ATOMIC_LOAD_AND:  return "AtomicLoadAnd";
> +  case ISD::ATOMIC_LOAD_OR:   return "AtomicLoadOr";
> +  case ISD::ATOMIC_LOAD_XOR:  return "AtomicLoadXor";
> +  case ISD::ATOMIC_LOAD_MIN:  return "AtomicLoadMin";
> +  case ISD::ATOMIC_LOAD_MAX:  return "AtomicLoadMax";
> +  case ISD::ATOMIC_LOAD_UMIN: return "AtomicLoadUMin";
> +  case ISD::ATOMIC_LOAD_UMAX: return "AtomicLoadUMax";
> +  case ISD::ATOMIC_SWAP:   return "AtomicSWAP";
>   case ISD::PCMARKER:      return "PCMarker";
>   case ISD::READCYCLECOUNTER: return "ReadCycleCounter";
>   case ISD::SRCVALUE:      return "SrcValue";
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=50663&r1=50662&r2=50663&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Mon May  5 14:05:59 2008
> @@ -732,6 +732,10 @@
>     assert(0 && "UserOp2 should not exist at instruction selection time!");
>     abort();
>   }
> +
> +private:
> +  inline const char *implVisitBinaryAtomic(CallInst& I, ISD::NodeType Op);
> +
>  };
>  } // end namespace llvm
>
> @@ -2769,6 +2773,22 @@
>   }
>  }
>
> +
> +/// Inlined utility function to implement binary input atomic intrinsics for
> +// visitIntrinsicCall: I is a call instruction
> +//                     Op is the associated NodeType for I
> +const char *
> +SelectionDAGLowering::implVisitBinaryAtomic(CallInst& I, ISD::NodeType Op) {
> +  SDOperand Root = getRoot();
> +  SDOperand O2 = getValue(I.getOperand(2));
> +  SDOperand L = DAG.getAtomic(Op, Root,
> +                              getValue(I.getOperand(1)),
> +                              O2, O2.getValueType());
> +  setValue(&I, L);
> +  DAG.setRoot(L.getValue(1));
> +  return 0;
> +}
> +
>  /// visitIntrinsicCall - Lower the call to the specified intrinsic function.  If
>  /// we want to emit this as a call to a named external function, return the name
>  /// otherwise lower it and return null.
> @@ -3205,27 +3225,26 @@
>     DAG.setRoot(L.getValue(1));
>     return 0;
>   }
> -  case Intrinsic::atomic_las: {
> -    SDOperand Root = getRoot();
> -    SDOperand O2 = getValue(I.getOperand(2));
> -    SDOperand L = DAG.getAtomic(ISD::ATOMIC_LAS, Root,
> -                                getValue(I.getOperand(1)),
> -                                O2, O2.getValueType());
> -    setValue(&I, L);
> -    DAG.setRoot(L.getValue(1));
> -    return 0;
> -  }
> -  case Intrinsic::atomic_swap: {
> -    SDOperand Root = getRoot();
> -    SDOperand O2 = getValue(I.getOperand(2));
> -    SDOperand L = DAG.getAtomic(ISD::ATOMIC_SWAP, Root,
> -                                getValue(I.getOperand(1)),
> -                                O2, O2.getValueType());
> -    setValue(&I, L);
> -    DAG.setRoot(L.getValue(1));
> -    return 0;
> -  }
> -
> +  case Intrinsic::atomic_las:
> +    return implVisitBinaryAtomic(I, ISD::ATOMIC_LAS);
> +  case Intrinsic::atomic_lss:
> +    return implVisitBinaryAtomic(I, ISD::ATOMIC_LSS);
> +  case Intrinsic::atomic_load_and:
> +    return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_AND);
> +  case Intrinsic::atomic_load_or:
> +    return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_OR);
> +  case Intrinsic::atomic_load_xor:
> +    return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_XOR);
> +  case Intrinsic::atomic_load_min:
> +    return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_MIN);
> +  case Intrinsic::atomic_load_max:
> +    return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_MAX);
> +  case Intrinsic::atomic_load_umin:
> +    return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_UMIN);
> +  case Intrinsic::atomic_load_umax:
> +      return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_UMAX);
> +  case Intrinsic::atomic_swap:
> +    return implVisitBinaryAtomic(I, ISD::ATOMIC_SWAP);
>   }
>  }
>
> @@ -4519,8 +4538,6 @@
>   AU.setPreservesAll();
>  }
>
> -
> -
>  bool SelectionDAGISel::runOnFunction(Function &Fn) {
>   // Get alias analysis for load/store combining.
>   AA = &getAnalysis<AliasAnalysis>();
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp?rev=50663&r1=50662&r2=50663&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Mon May  5 14:05:59 2008
> @@ -165,7 +165,7 @@
>
>  TargetLowering::TargetLowering(TargetMachine &tm)
>   : TM(tm), TD(TM.getTargetData()) {
> -  assert(ISD::BUILTIN_OP_END <= 156 &&
> +  assert(ISD::BUILTIN_OP_END <= OpActionsCapacity &&
>          "Fixed size array in TargetLowering is not large enough!");
>   // All operations default to being supported.
>   memset(OpActions, 0, sizeof(OpActions));
>
> Modified: llvm/trunk/lib/Target/TargetSelectionDAG.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/TargetSelectionDAG.td?rev=50663&r1=50662&r2=50663&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/TargetSelectionDAG.td (original)
> +++ llvm/trunk/lib/Target/TargetSelectionDAG.td Mon May  5 14:05:59 2008
> @@ -358,6 +358,22 @@
>                          [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
>  def atomic_swap : SDNode<"ISD::ATOMIC_SWAP", STDAtomic2,
>                          [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
> +def atomic_lss  : SDNode<"ISD::ATOMIC_LSS" , STDAtomic2,
> +                         [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
> +def atomic_load_and : SDNode<"ISD::ATOMIC_LOAD_AND" , STDAtomic2,
> +                         [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
> +def atomic_load_or  : SDNode<"ISD::ATOMIC_LOAD_OR" , STDAtomic2,
> +                         [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
> +def atomic_load_xor : SDNode<"ISD::ATOMIC_LOAD_XOR" , STDAtomic2,
> +                         [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
> +def atomic_load_min : SDNode<"ISD::ATOMIC_LOAD_MIN", STDAtomic2,
> +                         [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
> +def atomic_load_max : SDNode<"ISD::ATOMIC_LOAD_MAX", STDAtomic2,
> +                         [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
> +def atomic_load_umin : SDNode<"ISD::ATOMIC_LOAD_UMIN", STDAtomic2,
> +                         [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
> +def atomic_load_umax : SDNode<"ISD::ATOMIC_LOAD_UMAX", STDAtomic2,
> +                         [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
>
>  // Do not use ld, st directly. Use load, extload, sextload, zextload, store,
>  // and truncst (see below).
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=50663&r1=50662&r2=50663&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Mon May  5 14:05:59 2008
> @@ -292,10 +292,12 @@
>   if (!Subtarget->hasSSE2())
>     setOperationAction(ISD::MEMBARRIER    , MVT::Other, Expand);
>
> +  // Expand certain atomics
>   setOperationAction(ISD::ATOMIC_LCS     , MVT::i8, Custom);
>   setOperationAction(ISD::ATOMIC_LCS     , MVT::i16, Custom);
>   setOperationAction(ISD::ATOMIC_LCS     , MVT::i32, Custom);
>   setOperationAction(ISD::ATOMIC_LCS     , MVT::i64, Custom);
> +  setOperationAction(ISD::ATOMIC_LSS     , MVT::i32, Expand);
>
>   // Use the default ISD::LOCATION, ISD::DECLARE expansion.
>   setOperationAction(ISD::LOCATION, MVT::Other, Expand);
> @@ -5511,6 +5513,15 @@
>   return DAG.getNode(ISD::MERGE_VALUES, Tys, ResultVal, cpOutH.getValue(1)).Val;
>  }
>
> +SDNode* X86TargetLowering::ExpandATOMIC_LSS(SDNode* Op, SelectionDAG &DAG) {
> +  MVT::ValueType T = cast<AtomicSDNode>(Op)->getVT();
> +  assert (T == MVT::i32 && "Only know how to expand i32 LSS");
> +  SDOperand negOp = DAG.getNode(ISD::SUB, T,
> +                                DAG.getConstant(0, T), Op->getOperand(2));
> +  return DAG.getAtomic(ISD::ATOMIC_LAS, Op->getOperand(0),
> +                       Op->getOperand(1), negOp, T).Val;
> +}
> +
>  /// LowerOperation - Provide custom lowering hooks for some operations.
>  ///
>  SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
> @@ -5568,6 +5579,7 @@
>   case ISD::FP_TO_SINT:         return ExpandFP_TO_SINT(N, DAG);
>   case ISD::READCYCLECOUNTER:   return ExpandREADCYCLECOUNTER(N, DAG);
>   case ISD::ATOMIC_LCS:         return ExpandATOMIC_LCS(N, DAG);
> +  case ISD::ATOMIC_LSS:         return ExpandATOMIC_LSS(N,DAG);
>   }
>  }
>
> @@ -5732,6 +5744,187 @@
>  //                           X86 Scheduler Hooks
>  //===----------------------------------------------------------------------===//
>
> +// private utility function
> +MachineBasicBlock *
> +X86TargetLowering::EmitAtomicBitwiseWithCustomInserter(MachineInstr *bInstr,
> +                                                       MachineBasicBlock *MBB,
> +                                                       unsigned regOpc,
> +                                                       unsigned immOpc) {
> +  // For the atomic bitwise operator, we generate
> +  //   thisMBB:
> +  //   newMBB:
> +  //     ld  EAX = [bitinstr.addr]
> +  //     mov t1 = EAX
> +  //     op  t2 = t1, [bitinstr.val]
> +  //     lcs dest = [bitinstr.addr], t2  [EAX is implicit]
> +  //     bz  newMBB
> +  //     fallthrough -->nextMBB
> +  const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
> +  const BasicBlock *LLVM_BB = MBB->getBasicBlock();
> +  ilist<MachineBasicBlock>::iterator MBBIter = MBB;
> +  ++MBBIter;
> +
> +  /// First build the CFG
> +  MachineFunction *F = MBB->getParent();
> +  MachineBasicBlock *thisMBB = MBB;
> +  MachineBasicBlock *newMBB = new MachineBasicBlock(LLVM_BB);
> +  MachineBasicBlock *nextMBB = new MachineBasicBlock(LLVM_BB);
> +  F->getBasicBlockList().insert(MBBIter, newMBB);
> +  F->getBasicBlockList().insert(MBBIter, nextMBB);
> +
> +  // Move all successors to thisMBB to nextMBB
> +  nextMBB->transferSuccessors(thisMBB);
> +
> +  // Update thisMBB to fall through to newMBB
> +  thisMBB->addSuccessor(newMBB);
> +
> +  // newMBB jumps to itself and fall through to nextMBB
> +  newMBB->addSuccessor(nextMBB);
> +  newMBB->addSuccessor(newMBB);
> +
> +  // Insert instructions into newMBB based on incoming instruction
> +  assert(bInstr->getNumOperands() < 8 && "unexpected number of operands");
> +  MachineOperand& destOper = bInstr->getOperand(0);
> +  MachineOperand* argOpers[6];
> +  int numArgs = bInstr->getNumOperands() - 1;
> +  for (int i=0; i < numArgs; ++i)
> +    argOpers[i] = &bInstr->getOperand(i+1);
> +
> +  // x86 address has 4 operands: base, index, scale, and displacement
> +  int lastAddrIndx = 3; // [0,3]
> +  int valArgIndx = 4;
> +
> +  MachineInstrBuilder MIB = BuildMI(newMBB, TII->get(X86::MOV32rm), X86::EAX);
> +  for (int i=0; i <= lastAddrIndx; ++i)
> +    (*MIB).addOperand(*argOpers[i]);
> +
> +  unsigned t1 = F->getRegInfo().createVirtualRegister(X86::GR32RegisterClass);
> +  MIB = BuildMI(newMBB, TII->get(X86::MOV32rr), t1);
> +  MIB.addReg(X86::EAX);
> +
> +  unsigned t2 = F->getRegInfo().createVirtualRegister(X86::GR32RegisterClass);
> +  assert(   (argOpers[valArgIndx]->isReg() || argOpers[valArgIndx]->isImm())
> +         && "invalid operand");
> +  if (argOpers[valArgIndx]->isReg())
> +    MIB = BuildMI(newMBB, TII->get(regOpc), t2);
> +  else
> +    MIB = BuildMI(newMBB, TII->get(immOpc), t2);
> +  MIB.addReg(t1);
> +  (*MIB).addOperand(*argOpers[valArgIndx]);
> +
> +  MIB = BuildMI(newMBB, TII->get(X86::LCMPXCHG32));
> +  for (int i=0; i <= lastAddrIndx; ++i)
> +    (*MIB).addOperand(*argOpers[i]);
> +  MIB.addReg(t2);
> +
> +  MIB = BuildMI(newMBB, TII->get(X86::MOV32rr), destOper.getReg());
> +  MIB.addReg(X86::EAX);
> +
> +  // insert branch
> +  BuildMI(newMBB, TII->get(X86::JNE)).addMBB(newMBB);
> +
> +  delete bInstr;   // The pseudo instruction is gone now.
> +  return nextMBB;
> +}
> +
> +// private utility function
> +MachineBasicBlock *
> +X86TargetLowering::EmitAtomicMinMaxWithCustomInserter(MachineInstr *mInstr,
> +                                                      MachineBasicBlock *MBB,
> +                                                      unsigned cmovOpc) {
> +  // For the atomic min/max operator, we generate
> +  //   thisMBB:
> +  //   newMBB:
> +  //     ld EAX = [min/max.addr]
> +  //     mov t1 = EAX
> +  //     mov t2 = [min/max.val]
> +  //     cmp  t1, t2
> +  //     cmov[cond] t2 = t1
> +  //     lcs dest = [bitinstr.addr], t2  [EAX is implicit]
> +  //     bz   newMBB
> +  //     fallthrough -->nextMBB
> +  //
> +  const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
> +  const BasicBlock *LLVM_BB = MBB->getBasicBlock();
> +  ilist<MachineBasicBlock>::iterator MBBIter = MBB;
> +  ++MBBIter;
> +
> +  /// First build the CFG
> +  MachineFunction *F = MBB->getParent();
> +  MachineBasicBlock *thisMBB = MBB;
> +  MachineBasicBlock *newMBB = new MachineBasicBlock(LLVM_BB);
> +  MachineBasicBlock *nextMBB = new MachineBasicBlock(LLVM_BB);
> +  F->getBasicBlockList().insert(MBBIter, newMBB);
> +  F->getBasicBlockList().insert(MBBIter, nextMBB);
> +
> +  // Move all successors to thisMBB to nextMBB
> +  nextMBB->transferSuccessors(thisMBB);
> +
> +  // Update thisMBB to fall through to newMBB
> +  thisMBB->addSuccessor(newMBB);
> +
> +  // newMBB jumps to newMBB and fall through to nextMBB
> +  newMBB->addSuccessor(nextMBB);
> +  newMBB->addSuccessor(newMBB);
> +
> +  // Insert instructions into newMBB based on incoming instruction
> +  assert(mInstr->getNumOperands() < 8 && "unexpected number of operands");
> +  MachineOperand& destOper = mInstr->getOperand(0);
> +  MachineOperand* argOpers[6];
> +  int numArgs = mInstr->getNumOperands() - 1;
> +  for (int i=0; i < numArgs; ++i)
> +    argOpers[i] = &mInstr->getOperand(i+1);
> +
> +  // x86 address has 4 operands: base, index, scale, and displacement
> +  int lastAddrIndx = 3; // [0,3]
> +  int valArgIndx = 4;
> +
> +  MachineInstrBuilder MIB = BuildMI(newMBB, TII->get(X86::MOV32rm), X86::EAX);
> +  for (int i=0; i <= lastAddrIndx; ++i)
> +    (*MIB).addOperand(*argOpers[i]);
> +
> +  unsigned t1 = F->getRegInfo().createVirtualRegister(X86::GR32RegisterClass);
> +  MIB = BuildMI(newMBB, TII->get(X86::MOV32rr), t1);
> +  MIB.addReg(X86::EAX);
> +
> +  // We only support register and immediate values
> +  assert(   (argOpers[valArgIndx]->isReg() || argOpers[valArgIndx]->isImm())
> +         && "invalid operand");
> +
> +  unsigned t2 = F->getRegInfo().createVirtualRegister(X86::GR32RegisterClass);
> +  if (argOpers[valArgIndx]->isReg())
> +    MIB = BuildMI(newMBB, TII->get(X86::MOV32rr), t2);
> +  else
> +    MIB = BuildMI(newMBB, TII->get(X86::MOV32rr), t2);
> +  (*MIB).addOperand(*argOpers[valArgIndx]);
> +
> +  MIB = BuildMI(newMBB, TII->get(X86::CMP32rr));
> +  MIB.addReg(t1);
> +  MIB.addReg(t2);
> +
> +  // Generate movc
> +  unsigned t3 = F->getRegInfo().createVirtualRegister(X86::GR32RegisterClass);
> +  MIB = BuildMI(newMBB, TII->get(cmovOpc),t3);
> +  MIB.addReg(t2);
> +  MIB.addReg(t1);
> +
> +  // Cmp and exchange if none has modified the memory location
> +  MIB = BuildMI(newMBB, TII->get(X86::LCMPXCHG32));
> +  for (int i=0; i <= lastAddrIndx; ++i)
> +    (*MIB).addOperand(*argOpers[i]);
> +  MIB.addReg(t3);
> +
> +  MIB = BuildMI(newMBB, TII->get(X86::MOV32rr), destOper.getReg());
> +  MIB.addReg(X86::EAX);
> +
> +  // insert branch
> +  BuildMI(newMBB, TII->get(X86::JNE)).addMBB(newMBB);
> +
> +  delete mInstr;   // The pseudo instruction is gone now.
> +  return nextMBB;
> +}
> +
> +
>  MachineBasicBlock *
>  X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
>                                                MachineBasicBlock *BB) {
> @@ -5766,15 +5959,11 @@
>     MachineFunction *F = BB->getParent();
>     F->getBasicBlockList().insert(It, copy0MBB);
>     F->getBasicBlockList().insert(It, sinkMBB);
> -    // Update machine-CFG edges by first adding all successors of the current
> +    // Update machine-CFG edges by transferring all successors of the current
>     // block to the new block which will contain the Phi node for the select.
> -    for(MachineBasicBlock::succ_iterator i = BB->succ_begin(),
> -        e = BB->succ_end(); i != e; ++i)
> -      sinkMBB->addSuccessor(*i);
> -    // Next, remove all successors of the current block, and add the true
> -    // and fallthrough blocks as its successors.
> -    while(!BB->succ_empty())
> -      BB->removeSuccessor(BB->succ_begin());
> +    sinkMBB->transferSuccessors(BB);
> +
> +    // Add the true and fallthrough blocks as its successors.
>     BB->addSuccessor(copy0MBB);
>     BB->addSuccessor(sinkMBB);
>
> @@ -5874,6 +6063,23 @@
>     delete MI;   // The pseudo instruction is gone now.
>     return BB;
>   }
> +  case X86::ATOMAND32:
> +    return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND32rr,
> +                                                       X86::AND32ri);
> +  case X86::ATOMOR32:
> +    return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::OR32rr,
> +                                                       X86::OR32ri);
> +  case X86::ATOMXOR32:
> +    return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::XOR32rr,
> +                                                       X86::XOR32ri);
> +  case X86::ATOMMIN32:
> +    return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVL32rr);
> +  case X86::ATOMMAX32:
> +    return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVG32rr);
> +  case X86::ATOMUMIN32:
> +    return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVB32rr);
> +  case X86::ATOMUMAX32:
> +    return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVA32rr);
>   }
>  }
>
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.h?rev=50663&r1=50662&r2=50663&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86ISelLowering.h (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.h Mon May  5 14:05:59 2008
> @@ -346,6 +346,7 @@
>     virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI,
>                                                         MachineBasicBlock *MBB);
>
> +
>     /// getTargetNodeName - This method returns the name of a target specific
>     /// DAG node.
>     virtual const char *getTargetNodeName(unsigned Opcode) const;
> @@ -524,7 +525,8 @@
>     SDNode *ExpandFP_TO_SINT(SDNode *N, SelectionDAG &DAG);
>     SDNode *ExpandREADCYCLECOUNTER(SDNode *N, SelectionDAG &DAG);
>     SDNode *ExpandATOMIC_LCS(SDNode *N, SelectionDAG &DAG);
> -
> +    SDNode *ExpandATOMIC_LSS(SDNode *N, SelectionDAG &DAG);
> +
>     SDOperand EmitTargetCodeForMemset(SelectionDAG &DAG,
>                                       SDOperand Chain,
>                                       SDOperand Dst, SDOperand Src,
> @@ -537,6 +539,23 @@
>                                       bool AlwaysInline,
>                                       const Value *DstSV, uint64_t DstSVOff,
>                                       const Value *SrcSV, uint64_t SrcSVOff);
> +
> +    /// Utility function to emit atomic bitwise operations (and, or, xor).
> +    // It takes the bitwise instruction to expand, the associated machine basic
> +    // block, and the associated X86 opcodes for reg/reg and reg/imm.
> +    MachineBasicBlock *EmitAtomicBitwiseWithCustomInserter(
> +                                                    MachineInstr *BInstr,
> +                                                    MachineBasicBlock *BB,
> +                                                    unsigned regOpc,
> +                                                    unsigned immOpc);
> +
> +    /// Utility function to emit atomic min and max.  It takes the min/max
> +    // instruction to expand, the associated basic block, and the associated
> +    // cmov opcode for moving the min or max value.
> +    MachineBasicBlock *EmitAtomicMinMaxWithCustomInserter(MachineInstr *BInstr,
> +                                                          MachineBasicBlock *BB,
> +                                                          unsigned cmovOpc);
> +
>   };
>  }
>
>
> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=50663&r1=50662&r2=50663&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original)
> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Mon May  5 14:05:59 2008
> @@ -2598,6 +2598,63 @@
>                 TB, LOCK;
>  }
>
> +// Atomic exchange and and, or, xor
> +let Constraints = "$val = $dst", Defs = [EFLAGS],
> +                  usesCustomDAGSchedInserter = 1 in {
> +def ATOMAND32 : I<0xC1, MRMSrcMem,(outs GR32:$dst),(ins i32mem:$ptr, GR32:$val),
> +               "#ATOMAND32 PSUEDO!",
> +               [(set GR32:$dst, (atomic_load_and addr:$ptr, GR32:$val))]>,
> +                TB, LOCK;
> +}
> +
> +let Constraints = "$val = $dst", Defs = [EFLAGS],
> +                  usesCustomDAGSchedInserter = 1 in {
> +def ATOMOR32 : I<0xC1, MRMSrcMem, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val),
> +               "#ATOMOR32 PSUEDO!",
> +               [(set GR32:$dst, (atomic_load_or addr:$ptr, GR32:$val))]>,
> +                TB, LOCK;
> +}
> +
> +let Constraints = "$val = $dst", Defs = [EFLAGS],
> +                  usesCustomDAGSchedInserter = 1 in {
> +def ATOMXOR32 : I<0xC1, MRMSrcMem,(outs GR32:$dst),(ins i32mem:$ptr, GR32:$val),
> +               "#ATOMXOR32 PSUEDO!",
> +               [(set GR32:$dst, (atomic_load_xor addr:$ptr, GR32:$val))]>,
> +                TB, LOCK;
> +}
> +
> +let Constraints = "$val = $dst", Defs = [EFLAGS],
> +                  usesCustomDAGSchedInserter = 1 in {
> +def ATOMMIN32: I<0xC1, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$ptr, GR32:$val),
> +               "#ATOMMIN32 PSUEDO!",
> +               [(set GR32:$dst, (atomic_load_min addr:$ptr, GR32:$val))]>,
> +                TB, LOCK;
> +}
> +
> +let Constraints = "$val = $dst", Defs = [EFLAGS],
> +                  usesCustomDAGSchedInserter = 1 in {
> +def ATOMMAX32: I<0xC1, MRMSrcMem, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val),
> +               "#ATOMMAX32 PSUEDO!",
> +               [(set GR32:$dst, (atomic_load_max addr:$ptr, GR32:$val))]>,
> +                TB, LOCK;
> +}
> +
> +let Constraints = "$val = $dst", Defs = [EFLAGS],
> +                  usesCustomDAGSchedInserter = 1 in {
> +def ATOMUMIN32: I<0xC1, MRMSrcMem,(outs GR32:$dst),(ins i32mem:$ptr, GR32:$val),
> +               "#ATOMUMIN32 PSUEDO!",
> +               [(set GR32:$dst, (atomic_load_umin addr:$ptr, GR32:$val))]>,
> +                TB, LOCK;
> +}
> +
> +let Constraints = "$val = $dst", Defs = [EFLAGS],
> +                  usesCustomDAGSchedInserter = 1 in {
> +def ATOMUMAX32: I<0xC1, MRMSrcMem,(outs GR32:$dst),(ins i32mem:$ptr, GR32:$val),
> +               "#ATOMUMAX32 PSUEDO!",
> +               [(set GR32:$dst, (atomic_load_umax addr:$ptr, GR32:$val))]>,
> +                TB, LOCK;
> +}
> +
>  //===----------------------------------------------------------------------===//
>  // Non-Instruction Patterns
>  //===----------------------------------------------------------------------===//
>
> Modified: llvm/trunk/lib/Target/X86/X86Subtarget.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.cpp?rev=50663&r1=50662&r2=50663&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86Subtarget.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86Subtarget.cpp Mon May  5 14:05:59 2008
> @@ -247,7 +247,7 @@
>   , MaxInlineSizeThreshold(128)
>   , Is64Bit(is64Bit)
>   , TargetType(isELF) { // Default to ELF unless otherwise specified.
> -
> +
>   // Determine default and user specified characteristics
>   if (!FS.empty()) {
>     // If feature string is not empty, parse features string.
>
> Added: llvm/trunk/test/CodeGen/X86/atomic_op.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/atomic_op.ll?rev=50663&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/atomic_op.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/atomic_op.ll Mon May  5 14:05:59 2008
> @@ -0,0 +1,93 @@
> +; RUN: llvm-as < %s | llc -march=x86 -o %t1 -f
> +; RUN: grep "lock xaddl" %t1 | count 4
> +; RUN: grep "lock cmpxchgl"  %t1 | count 13
> +; RUN: grep "xchgl" %t1 | count 14
> +; RUN: grep "cmova" %t1 | count 2
> +; RUN: grep "cmovb" %t1 | count 2
> +; RUN: grep "cmovg" %t1 | count 2
> +; RUN: grep "cmovl" %t1 | count 2
> +
> +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
> +
> +define void @main(i32 %argc, i8** %argv) {
> +entry:
> +       %argc.addr = alloca i32         ; <i32*> [#uses=1]
> +       %argv.addr = alloca i8**                ; <i8***> [#uses=1]
> +       %val1 = alloca i32              ; <i32*> [#uses=2]
> +       %val2 = alloca i32              ; <i32*> [#uses=15]
> +       %andt = alloca i32              ; <i32*> [#uses=2]
> +       %ort = alloca i32               ; <i32*> [#uses=2]
> +       %xort = alloca i32              ; <i32*> [#uses=2]
> +       %old = alloca i32               ; <i32*> [#uses=18]
> +       %temp = alloca i32              ; <i32*> [#uses=2]
> +       store i32 %argc, i32* %argc.addr
> +       store i8** %argv, i8*** %argv.addr
> +       store i32 0, i32* %val1
> +       store i32 31, i32* %val2
> +       store i32 3855, i32* %andt
> +       store i32 3855, i32* %ort
> +       store i32 3855, i32* %xort
> +       store i32 4, i32* %temp
> +       %tmp = load i32* %temp          ; <i32> [#uses=1]
> +       call i32 @llvm.atomic.las.i32( i32* %val1, i32 %tmp )           ; <i32>:0 [#uses=1]
> +       store i32 %0, i32* %old
> +       call i32 @llvm.atomic.lss.i32( i32* %val2, i32 30 )             ; <i32>:1 [#uses=1]
> +       store i32 %1, i32* %old
> +       call i32 @llvm.atomic.las.i32( i32* %val2, i32 1 )              ; <i32>:2 [#uses=1]
> +       store i32 %2, i32* %old
> +       call i32 @llvm.atomic.lss.i32( i32* %val2, i32 1 )              ; <i32>:3 [#uses=1]
> +       store i32 %3, i32* %old
> +       call i32 @llvm.atomic.load.and.i32( i32* %andt, i32 4080 )              ; <i32>:4 [#uses=1]
> +       store i32 %4, i32* %old
> +       call i32 @llvm.atomic.load.or.i32( i32* %ort, i32 4080 )                ; <i32>:5 [#uses=1]
> +       store i32 %5, i32* %old
> +       call i32 @llvm.atomic.load.xor.i32( i32* %xort, i32 4080 )              ; <i32>:6 [#uses=1]
> +       store i32 %6, i32* %old
> +       call i32 @llvm.atomic.load.min.i32( i32* %val2, i32 16 )                ; <i32>:7 [#uses=1]
> +       store i32 %7, i32* %old
> +       %neg = sub i32 0, 1             ; <i32> [#uses=1]
> +       call i32 @llvm.atomic.load.min.i32( i32* %val2, i32 %neg )              ; <i32>:8 [#uses=1]
> +       store i32 %8, i32* %old
> +       call i32 @llvm.atomic.load.max.i32( i32* %val2, i32 1 )         ; <i32>:9 [#uses=1]
> +       store i32 %9, i32* %old
> +       call i32 @llvm.atomic.load.max.i32( i32* %val2, i32 0 )         ; <i32>:10 [#uses=1]
> +       store i32 %10, i32* %old
> +       call i32 @llvm.atomic.load.umax.i32( i32* %val2, i32 65535 )            ; <i32>:11 [#uses=1]
> +       store i32 %11, i32* %old
> +       call i32 @llvm.atomic.load.umax.i32( i32* %val2, i32 10 )               ; <i32>:12 [#uses=1]
> +       store i32 %12, i32* %old
> +       call i32 @llvm.atomic.load.umin.i32( i32* %val2, i32 1 )                ; <i32>:13 [#uses=1]
> +       store i32 %13, i32* %old
> +       call i32 @llvm.atomic.load.umin.i32( i32* %val2, i32 10 )               ; <i32>:14 [#uses=1]
> +       store i32 %14, i32* %old
> +       call i32 @llvm.atomic.swap.i32( i32* %val2, i32 1976 )          ; <i32>:15 [#uses=1]
> +       store i32 %15, i32* %old
> +       %neg1 = sub i32 0, 10           ; <i32> [#uses=1]
> +       call i32 @llvm.atomic.lcs.i32( i32* %val2, i32 %neg1, i32 1 )           ; <i32>:16 [#uses=1]
> +       store i32 %16, i32* %old
> +       call i32 @llvm.atomic.lcs.i32( i32* %val2, i32 1976, i32 1 )            ; <i32>:17 [#uses=1]
> +       store i32 %17, i32* %old
> +       ret void
> +}
> +
> +declare i32 @llvm.atomic.las.i32(i32*, i32) nounwind
> +
> +declare i32 @llvm.atomic.lss.i32(i32*, i32) nounwind
> +
> +declare i32 @llvm.atomic.load.and.i32(i32*, i32) nounwind
> +
> +declare i32 @llvm.atomic.load.or.i32(i32*, i32) nounwind
> +
> +declare i32 @llvm.atomic.load.xor.i32(i32*, i32) nounwind
> +
> +declare i32 @llvm.atomic.load.min.i32(i32*, i32) nounwind
> +
> +declare i32 @llvm.atomic.load.max.i32(i32*, i32) nounwind
> +
> +declare i32 @llvm.atomic.load.umax.i32(i32*, i32) nounwind
> +
> +declare i32 @llvm.atomic.load.umin.i32(i32*, i32) nounwind
> +
> +declare i32 @llvm.atomic.swap.i32(i32*, i32) nounwind
> +
> +declare i32 @llvm.atomic.lcs.i32(i32*, i32, i32) nounwind
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>



More information about the llvm-commits mailing list