[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