Add missing i64 max/min/umax/umin on 32-bit target

- Turn on atomic6432.ll and add specific test case as well

llvm-svn: 164616
This commit is contained in:
Michael Liao 2012-09-25 18:08:13 +00:00
parent 97e019d375
commit b50e89ddce
5 changed files with 141 additions and 1 deletions

View File

@ -2040,6 +2040,10 @@ SDNode *X86DAGToDAGISel::Select(SDNode *Node) {
case X86ISD::ATOMSUB64_DAG:
case X86ISD::ATOMNAND64_DAG:
case X86ISD::ATOMAND64_DAG:
case X86ISD::ATOMMAX64_DAG:
case X86ISD::ATOMMIN64_DAG:
case X86ISD::ATOMUMAX64_DAG:
case X86ISD::ATOMUMIN64_DAG:
case X86ISD::ATOMSWAP64_DAG: {
unsigned Opc;
switch (Opcode) {
@ -2050,6 +2054,10 @@ SDNode *X86DAGToDAGISel::Select(SDNode *Node) {
case X86ISD::ATOMSUB64_DAG: Opc = X86::ATOMSUB6432; break;
case X86ISD::ATOMNAND64_DAG: Opc = X86::ATOMNAND6432; break;
case X86ISD::ATOMAND64_DAG: Opc = X86::ATOMAND6432; break;
case X86ISD::ATOMMAX64_DAG: Opc = X86::ATOMMAX6432; break;
case X86ISD::ATOMMIN64_DAG: Opc = X86::ATOMMIN6432; break;
case X86ISD::ATOMUMAX64_DAG: Opc = X86::ATOMUMAX6432; break;
case X86ISD::ATOMUMIN64_DAG: Opc = X86::ATOMUMIN6432; break;
case X86ISD::ATOMSWAP64_DAG: Opc = X86::ATOMSWAP6432; break;
}
SDNode *RetVal = SelectAtomic64(Node, Opc);

View File

@ -514,6 +514,10 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i64, Custom);
setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i64, Custom);
setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Custom);
setOperationAction(ISD::ATOMIC_LOAD_MAX, MVT::i64, Custom);
setOperationAction(ISD::ATOMIC_LOAD_MIN, MVT::i64, Custom);
setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i64, Custom);
setOperationAction(ISD::ATOMIC_LOAD_UMIN, MVT::i64, Custom);
}
if (Subtarget->hasCmpxchg16b()) {
@ -11593,6 +11597,10 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N,
case ISD::ATOMIC_LOAD_OR:
case ISD::ATOMIC_LOAD_SUB:
case ISD::ATOMIC_LOAD_XOR:
case ISD::ATOMIC_LOAD_MAX:
case ISD::ATOMIC_LOAD_MIN:
case ISD::ATOMIC_LOAD_UMAX:
case ISD::ATOMIC_LOAD_UMIN:
case ISD::ATOMIC_SWAP: {
unsigned Opc;
switch (N->getOpcode()) {
@ -11615,6 +11623,18 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N,
case ISD::ATOMIC_LOAD_XOR:
Opc = X86ISD::ATOMXOR64_DAG;
break;
case ISD::ATOMIC_LOAD_MAX:
Opc = X86ISD::ATOMMAX64_DAG;
break;
case ISD::ATOMIC_LOAD_MIN:
Opc = X86ISD::ATOMMIN64_DAG;
break;
case ISD::ATOMIC_LOAD_UMAX:
Opc = X86ISD::ATOMUMAX64_DAG;
break;
case ISD::ATOMIC_LOAD_UMIN:
Opc = X86ISD::ATOMUMIN64_DAG;
break;
case ISD::ATOMIC_SWAP:
Opc = X86ISD::ATOMSWAP64_DAG;
break;
@ -12004,6 +12024,10 @@ static unsigned getNonAtomic6432Opcode(unsigned Opc, unsigned &HiOpc) {
case X86::ATOMADD6432: HiOpc = X86::ADC32rr; return X86::ADD32rr;
case X86::ATOMSUB6432: HiOpc = X86::SBB32rr; return X86::SUB32rr;
case X86::ATOMSWAP6432: HiOpc = X86::MOV32rr; return X86::MOV32rr;
case X86::ATOMMAX6432: HiOpc = X86::SETLr; return X86::SETLr;
case X86::ATOMMIN6432: HiOpc = X86::SETGr; return X86::SETGr;
case X86::ATOMUMAX6432: HiOpc = X86::SETBr; return X86::SETBr;
case X86::ATOMUMIN6432: HiOpc = X86::SETAr; return X86::SETAr;
}
llvm_unreachable("Unhandled atomic-load-op opcode!");
}
@ -12321,6 +12345,7 @@ X86TargetLowering::EmitAtomicLoadArith6432(MachineInstr *MI,
SrcHiReg = MI->getOperand(CurOp++).getReg();
const TargetRegisterClass *RC = &X86::GR32RegClass;
const TargetRegisterClass *RC8 = &X86::GR8RegClass;
unsigned LCMPXCHGOpc = X86::LCMPXCHG8B;
unsigned LOADOpc = X86::MOV32rm;
@ -12408,6 +12433,55 @@ X86TargetLowering::EmitAtomicLoadArith6432(MachineInstr *MI,
BuildMI(mainMBB, DL, TII->get(NOTOpc), t1H).addReg(t2H);
break;
}
case X86::ATOMMAX6432:
case X86::ATOMMIN6432:
case X86::ATOMUMAX6432:
case X86::ATOMUMIN6432: {
unsigned HiOpc;
unsigned LoOpc = getNonAtomic6432Opcode(Opc, HiOpc);
unsigned cL = MRI.createVirtualRegister(RC8);
unsigned cH = MRI.createVirtualRegister(RC8);
unsigned cL32 = MRI.createVirtualRegister(RC);
unsigned cH32 = MRI.createVirtualRegister(RC);
unsigned cc = MRI.createVirtualRegister(RC);
// cl := cmp src_lo, lo
BuildMI(mainMBB, DL, TII->get(X86::CMP32rr))
.addReg(SrcLoReg).addReg(LoReg);
BuildMI(mainMBB, DL, TII->get(LoOpc), cL);
BuildMI(mainMBB, DL, TII->get(X86::MOVZX32rr8), cL32).addReg(cL);
// ch := cmp src_hi, hi
BuildMI(mainMBB, DL, TII->get(X86::CMP32rr))
.addReg(SrcHiReg).addReg(HiReg);
BuildMI(mainMBB, DL, TII->get(HiOpc), cH);
BuildMI(mainMBB, DL, TII->get(X86::MOVZX32rr8), cH32).addReg(cH);
// cc := if (src_hi == hi) ? cl : ch;
if (Subtarget->hasCMov()) {
BuildMI(mainMBB, DL, TII->get(X86::CMOVE32rr), cc)
.addReg(cH32).addReg(cL32);
} else {
MIB = BuildMI(mainMBB, DL, TII->get(X86::CMOV_GR32), cc)
.addReg(cH32).addReg(cL32)
.addImm(X86::COND_E);
mainMBB = EmitLoweredSelect(MIB, mainMBB);
}
BuildMI(mainMBB, DL, TII->get(X86::TEST32rr)).addReg(cc).addReg(cc);
if (Subtarget->hasCMov()) {
BuildMI(mainMBB, DL, TII->get(X86::CMOVNE32rr), t1L)
.addReg(SrcLoReg).addReg(LoReg);
BuildMI(mainMBB, DL, TII->get(X86::CMOVNE32rr), t1H)
.addReg(SrcHiReg).addReg(HiReg);
} else {
MIB = BuildMI(mainMBB, DL, TII->get(X86::CMOV_GR32), t1L)
.addReg(SrcLoReg).addReg(LoReg)
.addImm(X86::COND_NE);
mainMBB = EmitLoweredSelect(MIB, mainMBB);
MIB = BuildMI(mainMBB, DL, TII->get(X86::CMOV_GR32), t1H)
.addReg(SrcHiReg).addReg(HiReg)
.addImm(X86::COND_NE);
mainMBB = EmitLoweredSelect(MIB, mainMBB);
}
break;
}
case X86::ATOMSWAP6432: {
unsigned HiOpc;
unsigned LoOpc = getNonAtomic6432Opcode(Opc, HiOpc);
@ -13381,6 +13455,10 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
case X86::ATOMNAND6432:
case X86::ATOMADD6432:
case X86::ATOMSUB6432:
case X86::ATOMMAX6432:
case X86::ATOMMIN6432:
case X86::ATOMUMAX6432:
case X86::ATOMUMIN6432:
case X86::ATOMSWAP6432:
return EmitAtomicLoadArith6432(MI, BB);

View File

@ -348,6 +348,10 @@ namespace llvm {
ATOMXOR64_DAG,
ATOMAND64_DAG,
ATOMNAND64_DAG,
ATOMMAX64_DAG,
ATOMMIN64_DAG,
ATOMUMAX64_DAG,
ATOMUMIN64_DAG,
ATOMSWAP64_DAG,
// LCMPXCHG_DAG, LCMPXCHG8_DAG, LCMPXCHG16_DAG - Compare and swap.

View File

@ -0,0 +1,51 @@
; RUN: llc -march=x86 -mattr=+cmov -mtriple=i386-pc-linux < %s | FileCheck %s
@sc64 = external global i64
define void @atomic_maxmin_i6432() {
; CHECK: atomic_maxmin_i6432
%1 = atomicrmw max i64* @sc64, i64 5 acquire
; CHECK: [[LABEL:.LBB[0-9]+_[0-9]+]]
; CHECK: cmpl
; CHECK: setl
; CHECK: cmpl
; CHECK: setl
; CHECK: cmovne
; CHECK: cmovne
; CHECK: lock
; CHECK-NEXT: cmpxchg8b
; CHECK: jne [[LABEL]]
%2 = atomicrmw min i64* @sc64, i64 6 acquire
; CHECK: [[LABEL:.LBB[0-9]+_[0-9]+]]
; CHECK: cmpl
; CHECK: setg
; CHECK: cmpl
; CHECK: setg
; CHECK: cmovne
; CHECK: cmovne
; CHECK: lock
; CHECK-NEXT: cmpxchg8b
; CHECK: jne [[LABEL]]
%3 = atomicrmw umax i64* @sc64, i64 7 acquire
; CHECK: [[LABEL:.LBB[0-9]+_[0-9]+]]
; CHECK: cmpl
; CHECK: setb
; CHECK: cmpl
; CHECK: setb
; CHECK: cmovne
; CHECK: cmovne
; CHECK: lock
; CHECK-NEXT: cmpxchg8b
; CHECK: jne [[LABEL]]
%4 = atomicrmw umin i64* @sc64, i64 8 acquire
; CHECK: [[LABEL:.LBB[0-9]+_[0-9]+]]
; CHECK: cmpl
; CHECK: seta
; CHECK: cmpl
; CHECK: seta
; CHECK: cmovne
; CHECK: cmovne
; CHECK: lock
; CHECK-NEXT: cmpxchg8b
; CHECK: jne [[LABEL]]
ret void
}

View File

@ -1,5 +1,4 @@
; RUN: llc < %s -O0 -march=x86 -mcpu=corei7 | FileCheck %s --check-prefix X32
; XFAIL: *
@sc64 = external global i64