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:
parent
7cdfe91e58
commit
34658dca78
File diff suppressed because it is too large
Load Diff
@ -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(
|
||||
|
@ -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!", []>;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
|
250
test/CodeGen/X86/atomic16.ll
Normal file
250
test/CodeGen/X86/atomic16.ll
Normal 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
|
||||
}
|
250
test/CodeGen/X86/atomic32.ll
Normal file
250
test/CodeGen/X86/atomic32.ll
Normal 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
|
||||
}
|
216
test/CodeGen/X86/atomic64.ll
Normal file
216
test/CodeGen/X86/atomic64.ll
Normal 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
|
||||
}
|
209
test/CodeGen/X86/atomic6432.ll
Normal file
209
test/CodeGen/X86/atomic6432.ll
Normal 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
251
test/CodeGen/X86/atomic8.ll
Normal 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
|
||||
}
|
@ -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
|
||||
|
14
test/CodeGen/X86/pr13458.ll
Normal file
14
test/CodeGen/X86/pr13458.ll
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user