1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 03:33:20 +01:00

Re-work X86 code generation of atomic ops with spin-loop

- Rewrite/merge pseudo-atomic instruction emitters to address the
  following issue:
  * Reduce one unnecessary load in spin-loop

    previously the spin-loop looks like

        thisMBB:
        newMBB:
          ld  t1 = [bitinstr.addr]
          op  t2 = t1, [bitinstr.val]
          not t3 = t2  (if Invert)
          mov EAX = t1
          lcs dest = [bitinstr.addr], t3  [EAX is implicit]
          bz  newMBB
          fallthrough -->nextMBB

    the 'ld' at the beginning of newMBB should be lift out of the loop
    as lcs (or CMPXCHG on x86) will load the current memory value into
    EAX. This loop is refined as:

        thisMBB:
          EAX = LOAD [MI.addr]
        mainMBB:
          t1 = OP [MI.val], EAX
          LCMPXCHG [MI.addr], t1, [EAX is implicitly used & defined]
          JNE mainMBB
        sinkMBB:

  * Remove immopc as, so far, all pseudo-atomic instructions has
    all-register form only, there is no immedidate operand.

  * Remove unnecessary attributes/modifiers in pseudo-atomic instruction
    td

  * Fix issues in PR13458

- Add comprehensive tests on atomic ops on various data types.
  NOTE: Some of them are turned off due to missing functionality.

- Revise tests due to the new spin-loop generated.

llvm-svn: 164281
This commit is contained in:
Michael Liao 2012-09-20 03:06:15 +00:00
parent 7cdfe91e58
commit 34658dca78
13 changed files with 1717 additions and 561 deletions

File diff suppressed because it is too large Load Diff

View File

@ -861,36 +861,17 @@ namespace llvm {
MachineBasicBlock *BB) const;
MachineBasicBlock *EmitMwait(MachineInstr *MI, MachineBasicBlock *BB) const;
/// 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,
unsigned loadOpc,
unsigned cxchgOpc,
unsigned notOpc,
unsigned EAXreg,
const TargetRegisterClass *RC,
bool Invert = false) const;
/// Utility function to emit atomic-load-arith operations (and, or, xor,
/// nand, max, min, umax, umin). It takes the corresponding instruction to
/// expand, the associated machine basic block, and the associated X86
/// opcodes for reg/reg.
MachineBasicBlock *EmitAtomicLoadArith(MachineInstr *MI,
MachineBasicBlock *MBB) const;
MachineBasicBlock *EmitAtomicBit6432WithCustomInserter(
MachineInstr *BInstr,
MachineBasicBlock *BB,
unsigned regOpcL,
unsigned regOpcH,
unsigned immOpcL,
unsigned immOpcH,
bool Invert = false) const;
/// 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) const;
/// Utility function to emit atomic-load-arith operations (and, or, xor,
/// nand, add, sub, swap) for 64-bit operands on 32-bit target.
MachineBasicBlock *EmitAtomicLoadArith6432(MachineInstr *MI,
MachineBasicBlock *MBB) const;
// Utility function to emit the low-level va_arg code for X86-64.
MachineBasicBlock *EmitVAARG64WithCustomInserter(

View File

@ -483,8 +483,7 @@ def CMOV_RFP80 : I<0, Pseudo,
//===----------------------------------------------------------------------===//
// Atomic exchange, and, or, xor
let Constraints = "$val = $dst", Defs = [EFLAGS],
usesCustomInserter = 1 in {
let usesCustomInserter = 1 in {
def ATOMAND8 : I<0, Pseudo, (outs GR8:$dst),(ins i8mem:$ptr, GR8:$val),
"#ATOMAND8 PSEUDO!",
@ -578,11 +577,7 @@ def ATOMUMAX64: I<0, Pseudo, (outs GR64:$dst),(ins i64mem:$ptr, GR64:$val),
[(set GR64:$dst, (atomic_load_umax_64 addr:$ptr, GR64:$val))]>;
}
let Constraints = "$val1 = $dst1, $val2 = $dst2",
Defs = [EFLAGS, EAX, EBX, ECX, EDX],
Uses = [EAX, EBX, ECX, EDX],
mayLoad = 1, mayStore = 1,
usesCustomInserter = 1 in {
let mayLoad = 1, mayStore = 1, usesCustomInserter = 1 in {
def ATOMAND6432 : I<0, Pseudo, (outs GR32:$dst1, GR32:$dst2),
(ins i64mem:$ptr, GR32:$val1, GR32:$val2),
"#ATOMAND6432 PSEUDO!", []>;

View File

@ -2266,7 +2266,7 @@ static X86::CondCode getCondFromSETOpc(unsigned Opc) {
}
/// getCondFromCmovOpc - return condition code of a CMov opcode.
static X86::CondCode getCondFromCMovOpc(unsigned Opc) {
X86::CondCode X86::getCondFromCMovOpc(unsigned Opc) {
switch (Opc) {
default: return X86::COND_INVALID;
case X86::CMOVA16rm: case X86::CMOVA16rr: case X86::CMOVA32rm:
@ -3314,7 +3314,7 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2,
if (OldCC != X86::COND_INVALID)
OpcIsSET = true;
else
OldCC = getCondFromCMovOpc(Instr.getOpcode());
OldCC = X86::getCondFromCMovOpc(Instr.getOpcode());
}
if (OldCC == X86::COND_INVALID) return false;
}

View File

@ -61,6 +61,9 @@ namespace X86 {
// Turn condition code into conditional branch opcode.
unsigned GetCondBranchFromCond(CondCode CC);
// Turn CMov opcode into condition code.
CondCode getCondFromCMovOpc(unsigned Opc);
/// GetOppositeBranchCondition - Return the inverse of the specified cond,
/// e.g. turning COND_E to COND_NE.
CondCode GetOppositeBranchCondition(X86::CondCode CC);

View File

@ -7,17 +7,16 @@
define void @t(i64* nocapture %p) nounwind ssp {
entry:
; CHECK: t:
; CHECK: movl $1
; CHECK: movl (%ebp), %eax
; CHECK: movl 4(%ebp), %edx
; CHECK: movl ([[REG:%[a-z]+]]), %eax
; CHECK: movl 4([[REG]]), %edx
; CHECK: LBB0_1:
; CHECK-NOT: movl $1
; CHECK-NOT: movl $0
; CHECK: movl $1
; CHECK: addl
; CHECK: movl $0
; CHECK: adcl
; CHECK: lock
; CHECK: cmpxchg8b
; CHECK: jne
; CHECK-NEXT: cmpxchg8b ([[REG]])
; CHECK-NEXT: jne
%0 = atomicrmw add i64* %p, i64 1 seq_cst
ret void
}

View File

@ -0,0 +1,250 @@
; RUN: llc < %s -O0 -march=x86-64 -mcpu=corei7 | FileCheck %s --check-prefix X64
; RUN: llc < %s -O0 -march=x86 -mcpu=corei7 | FileCheck %s --check-prefix X32
@sc16 = external global i16
define void @atomic_fetch_add16() nounwind {
; X64: atomic_fetch_add16
; X32: atomic_fetch_add16
entry:
; 32-bit
%t1 = atomicrmw add i16* @sc16, i16 1 acquire
; X64: lock
; X64: incw
; X32: lock
; X32: incw
%t2 = atomicrmw add i16* @sc16, i16 3 acquire
; X64: lock
; X64: addw $3
; X32: lock
; X32: addw $3
%t3 = atomicrmw add i16* @sc16, i16 5 acquire
; X64: lock
; X64: xaddw
; X32: lock
; X32: xaddw
%t4 = atomicrmw add i16* @sc16, i16 %t3 acquire
; X64: lock
; X64: addw
; X32: lock
; X32: addw
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_sub16() nounwind {
; X64: atomic_fetch_sub16
; X32: atomic_fetch_sub16
%t1 = atomicrmw sub i16* @sc16, i16 1 acquire
; X64: lock
; X64: decw
; X32: lock
; X32: decw
%t2 = atomicrmw sub i16* @sc16, i16 3 acquire
; X64: lock
; X64: subw $3
; X32: lock
; X32: subw $3
%t3 = atomicrmw sub i16* @sc16, i16 5 acquire
; X64: lock
; X64: xaddw
; X32: lock
; X32: xaddw
%t4 = atomicrmw sub i16* @sc16, i16 %t3 acquire
; X64: lock
; X64: subw
; X32: lock
; X32: subw
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_and16() nounwind {
; X64: atomic_fetch_and16
; X32: atomic_fetch_and16
%t1 = atomicrmw and i16* @sc16, i16 3 acquire
; X64: lock
; X64: andw $3
; X32: lock
; X32: andw $3
%t2 = atomicrmw and i16* @sc16, i16 5 acquire
; X64: andw
; X64: lock
; X64: cmpxchgw
; X32: andw
; X32: lock
; X32: cmpxchgw
%t3 = atomicrmw and i16* @sc16, i16 %t2 acquire
; X64: lock
; X64: andw
; X32: lock
; X32: andw
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_or16() nounwind {
; X64: atomic_fetch_or16
; X32: atomic_fetch_or16
%t1 = atomicrmw or i16* @sc16, i16 3 acquire
; X64: lock
; X64: orw $3
; X32: lock
; X32: orw $3
%t2 = atomicrmw or i16* @sc16, i16 5 acquire
; X64: orw
; X64: lock
; X64: cmpxchgw
; X32: orw
; X32: lock
; X32: cmpxchgw
%t3 = atomicrmw or i16* @sc16, i16 %t2 acquire
; X64: lock
; X64: orw
; X32: lock
; X32: orw
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_xor16() nounwind {
; X64: atomic_fetch_xor16
; X32: atomic_fetch_xor16
%t1 = atomicrmw xor i16* @sc16, i16 3 acquire
; X64: lock
; X64: xorw $3
; X32: lock
; X32: xorw $3
%t2 = atomicrmw xor i16* @sc16, i16 5 acquire
; X64: xorw
; X64: lock
; X64: cmpxchgw
; X32: xorw
; X32: lock
; X32: cmpxchgw
%t3 = atomicrmw xor i16* @sc16, i16 %t2 acquire
; X64: lock
; X64: xorw
; X32: lock
; X32: xorw
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_nand16(i16 %x) nounwind {
; X64: atomic_fetch_nand16
; X32: atomic_fetch_nand16
%t1 = atomicrmw nand i16* @sc16, i16 %x acquire
; X64: andw
; X64: notw
; X64: lock
; X64: cmpxchgw
; X32: andw
; X32: notw
; X32: lock
; X32: cmpxchgw
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_max16(i16 %x) nounwind {
%t1 = atomicrmw max i16* @sc16, i16 %x acquire
; X64: cmpw
; X64: cmov
; X64: lock
; X64: cmpxchgw
; X32: cmpw
; X32: cmov
; X32: lock
; X32: cmpxchgw
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_min16(i16 %x) nounwind {
%t1 = atomicrmw min i16* @sc16, i16 %x acquire
; X64: cmpw
; X64: cmov
; X64: lock
; X64: cmpxchgw
; X32: cmpw
; X32: cmov
; X32: lock
; X32: cmpxchgw
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_umax16(i16 %x) nounwind {
%t1 = atomicrmw umax i16* @sc16, i16 %x acquire
; X64: cmpw
; X64: cmov
; X64: lock
; X64: cmpxchgw
; X32: cmpw
; X32: cmov
; X32: lock
; X32: cmpxchgw
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_umin16(i16 %x) nounwind {
%t1 = atomicrmw umin i16* @sc16, i16 %x acquire
; X64: cmpw
; X64: cmov
; X64: lock
; X64: cmpxchgw
; X32: cmpw
; X32: cmov
; X32: lock
; X32: cmpxchgw
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_cmpxchg16() nounwind {
%t1 = cmpxchg i16* @sc16, i16 0, i16 1 acquire
; X64: lock
; X64: cmpxchgw
; X32: lock
; X32: cmpxchgw
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_store16(i16 %x) nounwind {
store atomic i16 %x, i16* @sc16 release, align 4
; X64-NOT: lock
; X64: movw
; X32-NOT: lock
; X32: movw
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_swap16(i16 %x) nounwind {
%t1 = atomicrmw xchg i16* @sc16, i16 %x acquire
; X64-NOT: lock
; X64: xchgw
; X32-NOT: lock
; X32: xchgw
ret void
; X64: ret
; X32: ret
}

View File

@ -0,0 +1,250 @@
; RUN: llc < %s -O0 -march=x86-64 -mcpu=corei7 | FileCheck %s --check-prefix X64
; RUN: llc < %s -O0 -march=x86 -mcpu=corei7 | FileCheck %s --check-prefix X32
@sc32 = external global i32
define void @atomic_fetch_add32() nounwind {
; X64: atomic_fetch_add32
; X32: atomic_fetch_add32
entry:
; 32-bit
%t1 = atomicrmw add i32* @sc32, i32 1 acquire
; X64: lock
; X64: incl
; X32: lock
; X32: incl
%t2 = atomicrmw add i32* @sc32, i32 3 acquire
; X64: lock
; X64: addl $3
; X32: lock
; X32: addl $3
%t3 = atomicrmw add i32* @sc32, i32 5 acquire
; X64: lock
; X64: xaddl
; X32: lock
; X32: xaddl
%t4 = atomicrmw add i32* @sc32, i32 %t3 acquire
; X64: lock
; X64: addl
; X32: lock
; X32: addl
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_sub32() nounwind {
; X64: atomic_fetch_sub32
; X32: atomic_fetch_sub32
%t1 = atomicrmw sub i32* @sc32, i32 1 acquire
; X64: lock
; X64: decl
; X32: lock
; X32: decl
%t2 = atomicrmw sub i32* @sc32, i32 3 acquire
; X64: lock
; X64: subl $3
; X32: lock
; X32: subl $3
%t3 = atomicrmw sub i32* @sc32, i32 5 acquire
; X64: lock
; X64: xaddl
; X32: lock
; X32: xaddl
%t4 = atomicrmw sub i32* @sc32, i32 %t3 acquire
; X64: lock
; X64: subl
; X32: lock
; X32: subl
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_and32() nounwind {
; X64: atomic_fetch_and32
; X32: atomic_fetch_and32
%t1 = atomicrmw and i32* @sc32, i32 3 acquire
; X64: lock
; X64: andl $3
; X32: lock
; X32: andl $3
%t2 = atomicrmw and i32* @sc32, i32 5 acquire
; X64: andl
; X64: lock
; X64: cmpxchgl
; X32: andl
; X32: lock
; X32: cmpxchgl
%t3 = atomicrmw and i32* @sc32, i32 %t2 acquire
; X64: lock
; X64: andl
; X32: lock
; X32: andl
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_or32() nounwind {
; X64: atomic_fetch_or32
; X32: atomic_fetch_or32
%t1 = atomicrmw or i32* @sc32, i32 3 acquire
; X64: lock
; X64: orl $3
; X32: lock
; X32: orl $3
%t2 = atomicrmw or i32* @sc32, i32 5 acquire
; X64: orl
; X64: lock
; X64: cmpxchgl
; X32: orl
; X32: lock
; X32: cmpxchgl
%t3 = atomicrmw or i32* @sc32, i32 %t2 acquire
; X64: lock
; X64: orl
; X32: lock
; X32: orl
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_xor32() nounwind {
; X64: atomic_fetch_xor32
; X32: atomic_fetch_xor32
%t1 = atomicrmw xor i32* @sc32, i32 3 acquire
; X64: lock
; X64: xorl $3
; X32: lock
; X32: xorl $3
%t2 = atomicrmw xor i32* @sc32, i32 5 acquire
; X64: xorl
; X64: lock
; X64: cmpxchgl
; X32: xorl
; X32: lock
; X32: cmpxchgl
%t3 = atomicrmw xor i32* @sc32, i32 %t2 acquire
; X64: lock
; X64: xorl
; X32: lock
; X32: xorl
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_nand32(i32 %x) nounwind {
; X64: atomic_fetch_nand32
; X32: atomic_fetch_nand32
%t1 = atomicrmw nand i32* @sc32, i32 %x acquire
; X64: andl
; X64: notl
; X64: lock
; X64: cmpxchgl
; X32: andl
; X32: notl
; X32: lock
; X32: cmpxchgl
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_max32(i32 %x) nounwind {
%t1 = atomicrmw max i32* @sc32, i32 %x acquire
; X64: cmpl
; X64: cmov
; X64: lock
; X64: cmpxchgl
; X32: cmpl
; X32: cmov
; X32: lock
; X32: cmpxchgl
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_min32(i32 %x) nounwind {
%t1 = atomicrmw min i32* @sc32, i32 %x acquire
; X64: cmpl
; X64: cmov
; X64: lock
; X64: cmpxchgl
; X32: cmpl
; X32: cmov
; X32: lock
; X32: cmpxchgl
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_umax32(i32 %x) nounwind {
%t1 = atomicrmw umax i32* @sc32, i32 %x acquire
; X64: cmpl
; X64: cmov
; X64: lock
; X64: cmpxchgl
; X32: cmpl
; X32: cmov
; X32: lock
; X32: cmpxchgl
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_umin32(i32 %x) nounwind {
%t1 = atomicrmw umin i32* @sc32, i32 %x acquire
; X64: cmpl
; X64: cmov
; X64: lock
; X64: cmpxchgl
; X32: cmpl
; X32: cmov
; X32: lock
; X32: cmpxchgl
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_cmpxchg32() nounwind {
%t1 = cmpxchg i32* @sc32, i32 0, i32 1 acquire
; X64: lock
; X64: cmpxchgl
; X32: lock
; X32: cmpxchgl
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_store32(i32 %x) nounwind {
store atomic i32 %x, i32* @sc32 release, align 4
; X64-NOT: lock
; X64: movl
; X32-NOT: lock
; X32: movl
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_swap32(i32 %x) nounwind {
%t1 = atomicrmw xchg i32* @sc32, i32 %x acquire
; X64-NOT: lock
; X64: xchgl
; X32-NOT: lock
; X32: xchgl
ret void
; X64: ret
; X32: ret
}

View File

@ -0,0 +1,216 @@
; RUN: llc < %s -O0 -march=x86-64 -mcpu=corei7 | FileCheck %s --check-prefix X64
@sc64 = external global i64
define void @atomic_fetch_add64() nounwind {
; X64: atomic_fetch_add64
entry:
%t1 = atomicrmw add i64* @sc64, i64 1 acquire
; X64: lock
; X64: incq
%t2 = atomicrmw add i64* @sc64, i64 3 acquire
; X64: lock
; X64: addq $3
%t3 = atomicrmw add i64* @sc64, i64 5 acquire
; X64: lock
; X64: xaddq
%t4 = atomicrmw add i64* @sc64, i64 %t3 acquire
; X64: lock
; X64: addq
ret void
; X64: ret
}
define void @atomic_fetch_sub64() nounwind {
; X64: atomic_fetch_sub64
%t1 = atomicrmw sub i64* @sc64, i64 1 acquire
; X64: lock
; X64: decq
%t2 = atomicrmw sub i64* @sc64, i64 3 acquire
; X64: lock
; X64: subq $3
%t3 = atomicrmw sub i64* @sc64, i64 5 acquire
; X64: lock
; X64: xaddq
%t4 = atomicrmw sub i64* @sc64, i64 %t3 acquire
; X64: lock
; X64: subq
ret void
; X64: ret
}
define void @atomic_fetch_and64() nounwind {
; X64: atomic_fetch_and64
%t1 = atomicrmw and i64* @sc64, i64 3 acquire
; X64: lock
; X64: andq $3
%t2 = atomicrmw and i64* @sc64, i64 5 acquire
; X64: andq
; X64: lock
; X64: cmpxchgq
%t3 = atomicrmw and i64* @sc64, i64 %t2 acquire
; X64: lock
; X64: andq
ret void
; X64: ret
}
define void @atomic_fetch_or64() nounwind {
; X64: atomic_fetch_or64
%t1 = atomicrmw or i64* @sc64, i64 3 acquire
; X64: lock
; X64: orq $3
%t2 = atomicrmw or i64* @sc64, i64 5 acquire
; X64: orq
; X64: lock
; X64: cmpxchgq
%t3 = atomicrmw or i64* @sc64, i64 %t2 acquire
; X64: lock
; X64: orq
ret void
; X64: ret
}
define void @atomic_fetch_xor64() nounwind {
; X64: atomic_fetch_xor64
%t1 = atomicrmw xor i64* @sc64, i64 3 acquire
; X64: lock
; X64: xorq $3
%t2 = atomicrmw xor i64* @sc64, i64 5 acquire
; X64: xorq
; X64: lock
; X64: cmpxchgq
%t3 = atomicrmw xor i64* @sc64, i64 %t2 acquire
; X64: lock
; X64: xorq
ret void
; X64: ret
}
define void @atomic_fetch_nand64(i64 %x) nounwind {
; X64: atomic_fetch_nand64
; X32: atomic_fetch_nand64
%t1 = atomicrmw nand i64* @sc64, i64 %x acquire
; X64: andq
; X64: notq
; X64: lock
; X64: cmpxchgq
; X32: andl
; X32: andl
; X32: notl
; X32: notl
; X32: lock
; X32: cmpxchg8b
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_max64(i64 %x) nounwind {
%t1 = atomicrmw max i64* @sc64, i64 %x acquire
; X64: cmpq
; X64: cmov
; X64: lock
; X64: cmpxchgq
; X32: cmpl
; X32: cmpl
; X32: cmov
; X32: cmov
; X32: cmov
; X32: lock
; X32: cmpxchg8b
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_min64(i64 %x) nounwind {
%t1 = atomicrmw min i64* @sc64, i64 %x acquire
; X64: cmpq
; X64: cmov
; X64: lock
; X64: cmpxchgq
; X32: cmpl
; X32: cmpl
; X32: cmov
; X32: cmov
; X32: cmov
; X32: lock
; X32: cmpxchg8b
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_umax64(i64 %x) nounwind {
%t1 = atomicrmw umax i64* @sc64, i64 %x acquire
; X64: cmpq
; X64: cmov
; X64: lock
; X64: cmpxchgq
; X32: cmpl
; X32: cmpl
; X32: cmov
; X32: cmov
; X32: cmov
; X32: lock
; X32: cmpxchg8b
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_umin64(i64 %x) nounwind {
%t1 = atomicrmw umin i64* @sc64, i64 %x acquire
; X64: cmpq
; X64: cmov
; X64: lock
; X64: cmpxchgq
; X32: cmpl
; X32: cmpl
; X32: cmov
; X32: cmov
; X32: cmov
; X32: lock
; X32: cmpxchg8b
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_cmpxchg64() nounwind {
%t1 = cmpxchg i64* @sc64, i64 0, i64 1 acquire
; X64: lock
; X64: cmpxchgq
; X32: lock
; X32: cmpxchg8b
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_store64(i64 %x) nounwind {
store atomic i64 %x, i64* @sc64 release, align 8
; X64-NOT: lock
; X64: movq
; X32: lock
; X32: cmpxchg8b
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_swap64(i64 %x) nounwind {
%t1 = atomicrmw xchg i64* @sc64, i64 %x acquire
; X64-NOT: lock
; X64: xchgq
; X32: lock
; X32: xchg8b
ret void
; X64: ret
; X32: ret
}

View File

@ -0,0 +1,209 @@
; RUN: llc < %s -O0 -march=x86 -mcpu=corei7 | FileCheck %s --check-prefix X32
; XFAIL: *
@sc64 = external global i64
define void @atomic_fetch_add64() nounwind {
; X32: atomic_fetch_add64
entry:
%t1 = atomicrmw add i64* @sc64, i64 1 acquire
; X32: addl
; X32: adcl
; X32: lock
; X32: cmpxchg8b
%t2 = atomicrmw add i64* @sc64, i64 3 acquire
; X32: addl
; X32: adcl
; X32: lock
; X32: cmpxchg8b
%t3 = atomicrmw add i64* @sc64, i64 5 acquire
; X32: addl
; X32: adcl
; X32: lock
; X32: cmpxchg8b
%t4 = atomicrmw add i64* @sc64, i64 %t3 acquire
; X32: addl
; X32: adcl
; X32: lock
; X32: cmpxchg8b
ret void
; X32: ret
}
define void @atomic_fetch_sub64() nounwind {
; X32: atomic_fetch_sub64
%t1 = atomicrmw sub i64* @sc64, i64 1 acquire
; X32: subl
; X32: sbbl
; X32: lock
; X32: cmpxchg8b
%t2 = atomicrmw sub i64* @sc64, i64 3 acquire
; X32: subl
; X32: sbbl
; X32: lock
; X32: cmpxchg8b
%t3 = atomicrmw sub i64* @sc64, i64 5 acquire
; X32: subl
; X32: sbbl
; X32: lock
; X32: cmpxchg8b
%t4 = atomicrmw sub i64* @sc64, i64 %t3 acquire
; X32: subl
; X32: sbbl
; X32: lock
; X32: cmpxchg8b
ret void
; X32: ret
}
define void @atomic_fetch_and64() nounwind {
; X32: atomic_fetch_and64
%t1 = atomicrmw and i64* @sc64, i64 3 acquire
; X32: andl
; X32: andl
; X32: lock
; X32: cmpxchg8b
%t2 = atomicrmw and i64* @sc64, i64 5 acquire
; X32: andl
; X32: andl
; X32: lock
; X32: cmpxchg8b
%t3 = atomicrmw and i64* @sc64, i64 %t2 acquire
; X32: andl
; X32: andl
; X32: lock
; X32: cmpxchg8b
ret void
; X32: ret
}
define void @atomic_fetch_or64() nounwind {
; X32: atomic_fetch_or64
%t1 = atomicrmw or i64* @sc64, i64 3 acquire
; X32: orl
; X32: orl
; X32: lock
; X32: cmpxchg8b
%t2 = atomicrmw or i64* @sc64, i64 5 acquire
; X32: orl
; X32: orl
; X32: lock
; X32: cmpxchg8b
%t3 = atomicrmw or i64* @sc64, i64 %t2 acquire
; X32: orl
; X32: orl
; X32: lock
; X32: cmpxchg8b
ret void
; X32: ret
}
define void @atomic_fetch_xor64() nounwind {
; X32: atomic_fetch_xor64
%t1 = atomicrmw xor i64* @sc64, i64 3 acquire
; X32: xorl
; X32: xorl
; X32: lock
; X32: cmpxchg8b
%t2 = atomicrmw xor i64* @sc64, i64 5 acquire
; X32: xorl
; X32: xorl
; X32: lock
; X32: cmpxchg8b
%t3 = atomicrmw xor i64* @sc64, i64 %t2 acquire
; X32: xorl
; X32: xorl
; X32: lock
; X32: cmpxchg8b
ret void
; X32: ret
}
define void @atomic_fetch_nand64(i64 %x) nounwind {
; X32: atomic_fetch_nand64
%t1 = atomicrmw nand i64* @sc64, i64 %x acquire
; X32: andl
; X32: andl
; X32: notl
; X32: notl
; X32: lock
; X32: cmpxchg8b
ret void
; X32: ret
}
define void @atomic_fetch_max64(i64 %x) nounwind {
%t1 = atomicrmw max i64* @sc64, i64 %x acquire
; X32: cmpl
; X32: cmpl
; X32: cmov
; X32: cmov
; X32: cmov
; X32: lock
; X32: cmpxchg8b
ret void
; X32: ret
}
define void @atomic_fetch_min64(i64 %x) nounwind {
%t1 = atomicrmw min i64* @sc64, i64 %x acquire
; X32: cmpl
; X32: cmpl
; X32: cmov
; X32: cmov
; X32: cmov
; X32: lock
; X32: cmpxchg8b
ret void
; X32: ret
}
define void @atomic_fetch_umax64(i64 %x) nounwind {
%t1 = atomicrmw umax i64* @sc64, i64 %x acquire
; X32: cmpl
; X32: cmpl
; X32: cmov
; X32: cmov
; X32: cmov
; X32: lock
; X32: cmpxchg8b
ret void
; X32: ret
}
define void @atomic_fetch_umin64(i64 %x) nounwind {
%t1 = atomicrmw umin i64* @sc64, i64 %x acquire
; X32: cmpl
; X32: cmpl
; X32: cmov
; X32: cmov
; X32: cmov
; X32: lock
; X32: cmpxchg8b
ret void
; X32: ret
}
define void @atomic_fetch_cmpxchg64() nounwind {
%t1 = cmpxchg i64* @sc64, i64 0, i64 1 acquire
; X32: lock
; X32: cmpxchg8b
ret void
; X32: ret
}
define void @atomic_fetch_store64(i64 %x) nounwind {
store atomic i64 %x, i64* @sc64 release, align 8
; X32: lock
; X32: cmpxchg8b
ret void
; X32: ret
}
define void @atomic_fetch_swap64(i64 %x) nounwind {
%t1 = atomicrmw xchg i64* @sc64, i64 %x acquire
; X32: lock
; X32: xchg8b
ret void
; X32: ret
}

251
test/CodeGen/X86/atomic8.ll Normal file
View File

@ -0,0 +1,251 @@
; RUN: llc < %s -O0 -march=x86-64 -mcpu=corei7 | FileCheck %s --check-prefix X64
; RUN: llc < %s -O0 -march=x86 -mcpu=corei7 | FileCheck %s --check-prefix X32
; XFAIL: *
@sc8 = external global i8
define void @atomic_fetch_add8() nounwind {
; X64: atomic_fetch_add8
; X32: atomic_fetch_add8
entry:
; 32-bit
%t1 = atomicrmw add i8* @sc8, i8 1 acquire
; X64: lock
; X64: incb
; X32: lock
; X32: incb
%t2 = atomicrmw add i8* @sc8, i8 3 acquire
; X64: lock
; X64: addb $3
; X32: lock
; X32: addb $3
%t3 = atomicrmw add i8* @sc8, i8 5 acquire
; X64: lock
; X64: xaddb
; X32: lock
; X32: xaddb
%t4 = atomicrmw add i8* @sc8, i8 %t3 acquire
; X64: lock
; X64: addb
; X32: lock
; X32: addb
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_sub8() nounwind {
; X64: atomic_fetch_sub8
; X32: atomic_fetch_sub8
%t1 = atomicrmw sub i8* @sc8, i8 1 acquire
; X64: lock
; X64: decb
; X32: lock
; X32: decb
%t2 = atomicrmw sub i8* @sc8, i8 3 acquire
; X64: lock
; X64: subb $3
; X32: lock
; X32: subb $3
%t3 = atomicrmw sub i8* @sc8, i8 5 acquire
; X64: lock
; X64: xaddb
; X32: lock
; X32: xaddb
%t4 = atomicrmw sub i8* @sc8, i8 %t3 acquire
; X64: lock
; X64: subb
; X32: lock
; X32: subb
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_and8() nounwind {
; X64: atomic_fetch_and8
; X32: atomic_fetch_and8
%t1 = atomicrmw and i8* @sc8, i8 3 acquire
; X64: lock
; X64: andb $3
; X32: lock
; X32: andb $3
%t2 = atomicrmw and i8* @sc8, i8 5 acquire
; X64: andb
; X64: lock
; X64: cmpxchgb
; X32: andb
; X32: lock
; X32: cmpxchgb
%t3 = atomicrmw and i8* @sc8, i8 %t2 acquire
; X64: lock
; X64: andb
; X32: lock
; X32: andb
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_or8() nounwind {
; X64: atomic_fetch_or8
; X32: atomic_fetch_or8
%t1 = atomicrmw or i8* @sc8, i8 3 acquire
; X64: lock
; X64: orb $3
; X32: lock
; X32: orb $3
%t2 = atomicrmw or i8* @sc8, i8 5 acquire
; X64: orb
; X64: lock
; X64: cmpxchgb
; X32: orb
; X32: lock
; X32: cmpxchgb
%t3 = atomicrmw or i8* @sc8, i8 %t2 acquire
; X64: lock
; X64: orb
; X32: lock
; X32: orb
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_xor8() nounwind {
; X64: atomic_fetch_xor8
; X32: atomic_fetch_xor8
%t1 = atomicrmw xor i8* @sc8, i8 3 acquire
; X64: lock
; X64: xorb $3
; X32: lock
; X32: xorb $3
%t2 = atomicrmw xor i8* @sc8, i8 5 acquire
; X64: xorb
; X64: lock
; X64: cmpxchgb
; X32: xorb
; X32: lock
; X32: cmpxchgb
%t3 = atomicrmw xor i8* @sc8, i8 %t2 acquire
; X64: lock
; X64: xorb
; X32: lock
; X32: xorb
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_nand8(i8 %x) nounwind {
; X64: atomic_fetch_nand8
; X32: atomic_fetch_nand8
%t1 = atomicrmw nand i8* @sc8, i8 %x acquire
; X64: andb
; X64: notb
; X64: lock
; X64: cmpxchgb
; X32: andb
; X32: notb
; X32: lock
; X32: cmpxchgb
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_max8(i8 %x) nounwind {
%t1 = atomicrmw max i8* @sc8, i8 %x acquire
; X64: cmpb
; X64: cmov
; X64: lock
; X64: cmpxchgb
; X32: cmpb
; X32: cmov
; X32: lock
; X32: cmpxchgb
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_min8(i8 %x) nounwind {
%t1 = atomicrmw min i8* @sc8, i8 %x acquire
; X64: cmpb
; X64: cmov
; X64: lock
; X64: cmpxchgb
; X32: cmpb
; X32: cmov
; X32: lock
; X32: cmpxchgb
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_umax8(i8 %x) nounwind {
%t1 = atomicrmw umax i8* @sc8, i8 %x acquire
; X64: cmpb
; X64: cmov
; X64: lock
; X64: cmpxchgb
; X32: cmpb
; X32: cmov
; X32: lock
; X32: cmpxchgb
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_umin8(i8 %x) nounwind {
%t1 = atomicrmw umin i8* @sc8, i8 %x acquire
; X64: cmpb
; X64: cmov
; X64: lock
; X64: cmpxchgb
; X32: cmpb
; X32: cmov
; X32: lock
; X32: cmpxchgb
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_cmpxchg8() nounwind {
%t1 = cmpxchg i8* @sc8, i8 0, i8 1 acquire
; X64: lock
; X64: cmpxchgb
; X32: lock
; X32: cmpxchgb
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_store8(i8 %x) nounwind {
store atomic i8 %x, i8* @sc8 release, align 4
; X64-NOT: lock
; X64: movb
; X32-NOT: lock
; X32: movb
ret void
; X64: ret
; X32: ret
}
define void @atomic_fetch_swap8(i8 %x) nounwind {
%t1 = atomicrmw xchg i8* @sc8, i8 %x acquire
; X64-NOT: lock
; X64: xchgb
; X32-NOT: lock
; X32: xchgb
ret void
; X64: ret
; X32: ret
}

View File

@ -1,4 +1,4 @@
; RUN: llc < %s -mcpu=generic -march=x86 | FileCheck %s
; RUN: llc < %s -mcpu=generic -march=x86 -mattr=+cmov | FileCheck %s
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"
@ -107,13 +107,12 @@ entry:
; CHECK: cmpxchgl
%17 = cmpxchg i32* %val2, i32 1976, i32 1 monotonic
store i32 %17, i32* %old
; CHECK: movl [[R17atomic:.*]], %eax
; CHECK: movl $1401, %[[R17mask:[a-z]*]]
; CHECK: movl [[R17atomic:.*]], %eax
; CHECK: movl %eax, %[[R17newval:[a-z]*]]
; CHECK: andl %[[R17mask]], %[[R17newval]]
; CHECK: notl %[[R17newval]]
; CHECK: andl %eax, %[[R17mask]]
; CHECK: notl %[[R17mask]]
; CHECK: lock
; CHECK: cmpxchgl %[[R17newval]], [[R17atomic]]
; CHECK: cmpxchgl %[[R17mask]], [[R17atomic]]
; CHECK: jne
; CHECK: movl %eax,
%18 = atomicrmw nand i32* %val2, i32 1401 monotonic

View File

@ -0,0 +1,14 @@
; RUN: llc < %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-darwin11.4.2"
%v8_uniform_Stats.0.2.4.10 = type { i64, i64, i32, i32, i32, i32, i32, i32, i32, i32, i64, i64, i64, i32, i32, i32, i32, i32, i32, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i32, i64, [7 x i32], [7 x i64] }
@globalStats = external global %v8_uniform_Stats.0.2.4.10
define void @MergeStats() nounwind {
allocas:
%r.i.i720 = atomicrmw max i64* getelementptr inbounds (%v8_uniform_Stats.0.2.4.10* @globalStats, i64 0, i32 30), i64 0 seq_cst
ret void
}