diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index c2e4f1f816a..d78482673b0 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -615,6 +615,7 @@ namespace ISD { ATOMIC_LOAD_AND, ATOMIC_LOAD_OR, ATOMIC_LOAD_XOR, + ATOMIC_LOAD_NAND, ATOMIC_LOAD_MIN, ATOMIC_LOAD_MAX, ATOMIC_LOAD_UMIN, diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td index 633063eb48f..18c42e41f8a 100644 --- a/include/llvm/Intrinsics.td +++ b/include/llvm/Intrinsics.td @@ -302,6 +302,11 @@ def int_atomic_load_xor : Intrinsic<[llvm_anyint_ty, LLVMMatchType<0>], [IntrWriteArgMem]>, GCCBuiltin<"__sync_fetch_and_xor">; +def int_atomic_load_nand : Intrinsic<[llvm_anyint_ty, + LLVMPointerType>, + LLVMMatchType<0>], + [IntrWriteArgMem]>, + GCCBuiltin<"__sync_fetch_and_nand">; def int_atomic_load_min : Intrinsic<[llvm_anyint_ty, LLVMPointerType>, LLVMMatchType<0>], diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index dd5a350f49d..87bb1dbf142 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1254,6 +1254,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { case ISD::ATOMIC_LOAD_AND: case ISD::ATOMIC_LOAD_OR: case ISD::ATOMIC_LOAD_XOR: + case ISD::ATOMIC_LOAD_NAND: case ISD::ATOMIC_LOAD_MIN: case ISD::ATOMIC_LOAD_MAX: case ISD::ATOMIC_LOAD_UMIN: @@ -4285,6 +4286,7 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) { case ISD::ATOMIC_LOAD_AND: case ISD::ATOMIC_LOAD_OR: case ISD::ATOMIC_LOAD_XOR: + case ISD::ATOMIC_LOAD_NAND: case ISD::ATOMIC_LOAD_MIN: case ISD::ATOMIC_LOAD_MAX: case ISD::ATOMIC_LOAD_UMIN: diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 4f577fc269a..bca5e756d45 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2995,6 +2995,7 @@ SDOperand SelectionDAG::getAtomic(unsigned Opcode, SDOperand Chain, 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_NAND || Opcode == ISD::ATOMIC_LOAD_MIN || Opcode == ISD::ATOMIC_LOAD_MAX || Opcode == ISD::ATOMIC_LOAD_UMIN || Opcode == ISD::ATOMIC_LOAD_UMAX) && "Invalid Atomic Op"); @@ -4406,6 +4407,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { 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_NAND: return "AtomicLoadNand"; case ISD::ATOMIC_LOAD_MIN: return "AtomicLoadMin"; case ISD::ATOMIC_LOAD_MAX: return "AtomicLoadMax"; case ISD::ATOMIC_LOAD_UMIN: return "AtomicLoadUMin"; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index f1dc64d3296..a55f904b218 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -3526,6 +3526,8 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_OR); case Intrinsic::atomic_load_xor: return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_XOR); + case Intrinsic::atomic_load_nand: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_NAND); case Intrinsic::atomic_load_min: return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_MIN); case Intrinsic::atomic_load_max: diff --git a/lib/Target/TargetSelectionDAG.td b/lib/Target/TargetSelectionDAG.td index b7fadd1d757..38a604653f5 100644 --- a/lib/Target/TargetSelectionDAG.td +++ b/lib/Target/TargetSelectionDAG.td @@ -367,6 +367,8 @@ 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_nand: SDNode<"ISD::ATOMIC_LOAD_NAND", 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, diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 53f42b9c0d9..11442b5fa58 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -5963,7 +5963,8 @@ MachineBasicBlock * X86TargetLowering::EmitAtomicBitwiseWithCustomInserter(MachineInstr *bInstr, MachineBasicBlock *MBB, unsigned regOpc, - unsigned immOpc) { + unsigned immOpc, + bool invSrc) { // For the atomic bitwise operator, we generate // thisMBB: // newMBB: @@ -6012,7 +6013,14 @@ X86TargetLowering::EmitAtomicBitwiseWithCustomInserter(MachineInstr *bInstr, MachineInstrBuilder MIB = BuildMI(newMBB, TII->get(X86::MOV32rm), t1); for (int i=0; i <= lastAddrIndx; ++i) (*MIB).addOperand(*argOpers[i]); - + + unsigned tt = F->getRegInfo().createVirtualRegister(X86::GR32RegisterClass); + if (invSrc) { + MIB = BuildMI(newMBB, TII->get(X86::NOT32r), tt).addReg(t1); + } + else + tt = t1; + unsigned t2 = F->getRegInfo().createVirtualRegister(X86::GR32RegisterClass); assert( (argOpers[valArgIndx]->isReg() || argOpers[valArgIndx]->isImm()) && "invalid operand"); @@ -6020,9 +6028,9 @@ X86TargetLowering::EmitAtomicBitwiseWithCustomInserter(MachineInstr *bInstr, MIB = BuildMI(newMBB, TII->get(regOpc), t2); else MIB = BuildMI(newMBB, TII->get(immOpc), t2); - MIB.addReg(t1); + MIB.addReg(tt); (*MIB).addOperand(*argOpers[valArgIndx]); - + MIB = BuildMI(newMBB, TII->get(X86::MOV32rr), X86::EAX); MIB.addReg(t1); @@ -6286,6 +6294,9 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, case X86::ATOMXOR32: return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::XOR32rr, X86::XOR32ri); + case X86::ATOMNAND32: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND32rr, + X86::AND32ri, true); case X86::ATOMMIN32: return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVL32rr); case X86::ATOMMAX32: diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index c7a43a47a6c..f2b851e66e4 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -567,7 +567,8 @@ namespace llvm { MachineInstr *BInstr, MachineBasicBlock *BB, unsigned regOpc, - unsigned immOpc); + unsigned immOpc, + bool invSrc = false); /// Utility function to emit atomic min and max. It takes the min/max // instruction to expand, the associated basic block, and the associated diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 4b8dc100b9e..2630834b6a3 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -2633,45 +2633,25 @@ let Constraints = "$val = $dst", Defs = [EFLAGS], def ATOMAND32 : I<0, Pseudo, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), "#ATOMAND32 PSUEDO!", [(set GR32:$dst, (atomic_load_and addr:$ptr, GR32:$val))]>; -} - -let Constraints = "$val = $dst", Defs = [EFLAGS], - usesCustomDAGSchedInserter = 1 in { def ATOMOR32 : I<0, Pseudo, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), "#ATOMOR32 PSUEDO!", [(set GR32:$dst, (atomic_load_or addr:$ptr, GR32:$val))]>; -} - -let Constraints = "$val = $dst", Defs = [EFLAGS], - usesCustomDAGSchedInserter = 1 in { def ATOMXOR32 : I<0, Pseudo,(outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), "#ATOMXOR32 PSUEDO!", [(set GR32:$dst, (atomic_load_xor addr:$ptr, GR32:$val))]>; -} +def ATOMNAND32 : I<0, Pseudo,(outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), + "#ATOMXOR32 PSUEDO!", + [(set GR32:$dst, (atomic_load_nand addr:$ptr, GR32:$val))]>; -let Constraints = "$val = $dst", Defs = [EFLAGS], - usesCustomDAGSchedInserter = 1 in { def ATOMMIN32: I<0, Pseudo, (outs GR32:$dst), (ins i32mem:$ptr, GR32:$val), "#ATOMMIN32 PSUEDO!", [(set GR32:$dst, (atomic_load_min addr:$ptr, GR32:$val))]>; -} - -let Constraints = "$val = $dst", Defs = [EFLAGS], - usesCustomDAGSchedInserter = 1 in { def ATOMMAX32: I<0, Pseudo, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), "#ATOMMAX32 PSUEDO!", [(set GR32:$dst, (atomic_load_max addr:$ptr, GR32:$val))]>; -} - -let Constraints = "$val = $dst", Defs = [EFLAGS], - usesCustomDAGSchedInserter = 1 in { def ATOMUMIN32: I<0, Pseudo, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), "#ATOMUMIN32 PSUEDO!", [(set GR32:$dst, (atomic_load_umin addr:$ptr, GR32:$val))]>; -} - -let Constraints = "$val = $dst", Defs = [EFLAGS], - usesCustomDAGSchedInserter = 1 in { def ATOMUMAX32: I<0, Pseudo, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), "#ATOMUMAX32 PSUEDO!", [(set GR32:$dst, (atomic_load_umax addr:$ptr, GR32:$val))]>;