Support XOR and AND optimization with no return value.

Finishes off rdar://8470697

llvm-svn: 131458
This commit is contained in:
Eric Christopher 2011-05-17 08:10:18 +00:00
parent abfe3131e3
commit a1d9e29552
2 changed files with 51 additions and 5 deletions

View File

@ -189,7 +189,7 @@ namespace {
SDNode *Select(SDNode *N); SDNode *Select(SDNode *N);
SDNode *SelectAtomic64(SDNode *Node, unsigned Opc); SDNode *SelectAtomic64(SDNode *Node, unsigned Opc);
SDNode *SelectAtomicLoadAdd(SDNode *Node, EVT NVT); SDNode *SelectAtomicLoadAdd(SDNode *Node, EVT NVT);
SDNode *SelectAtomicLoadOr(SDNode *Node, EVT NVT); SDNode *SelectAtomicLoadArith(SDNode *Node, EVT NVT);
bool MatchLoadInAddress(LoadSDNode *N, X86ISelAddressMode &AM); bool MatchLoadInAddress(LoadSDNode *N, X86ISelAddressMode &AM);
bool MatchWrapper(SDValue N, X86ISelAddressMode &AM); bool MatchWrapper(SDValue N, X86ISelAddressMode &AM);
@ -1484,6 +1484,8 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadAdd(SDNode *Node, EVT NVT) {
enum AtomicOpc { enum AtomicOpc {
OR, OR,
AND,
XOR,
AtomicOpcEnd AtomicOpcEnd
}; };
@ -1515,10 +1517,36 @@ static const unsigned int AtomicOpcTbl[AtomicOpcEnd][AtomicSzEnd] = {
X86::LOCK_OR64mi8, X86::LOCK_OR64mi8,
X86::LOCK_OR64mi32, X86::LOCK_OR64mi32,
X86::LOCK_OR64mr X86::LOCK_OR64mr
},
{
X86::LOCK_AND8mi,
X86::LOCK_AND8mr,
X86::LOCK_AND16mi8,
X86::LOCK_AND16mi,
X86::LOCK_AND16mr,
X86::LOCK_AND32mi8,
X86::LOCK_AND32mi,
X86::LOCK_AND32mr,
X86::LOCK_AND64mi8,
X86::LOCK_AND64mi32,
X86::LOCK_AND64mr
},
{
X86::LOCK_XOR8mi,
X86::LOCK_XOR8mr,
X86::LOCK_XOR16mi8,
X86::LOCK_XOR16mi,
X86::LOCK_XOR16mr,
X86::LOCK_XOR32mi8,
X86::LOCK_XOR32mi,
X86::LOCK_XOR32mr,
X86::LOCK_XOR64mi8,
X86::LOCK_XOR64mi32,
X86::LOCK_XOR64mr
} }
}; };
SDNode *X86DAGToDAGISel::SelectAtomicLoadOr(SDNode *Node, EVT NVT) { SDNode *X86DAGToDAGISel::SelectAtomicLoadArith(SDNode *Node, EVT NVT) {
if (Node->hasAnyUseOfValue(0)) if (Node->hasAnyUseOfValue(0))
return 0; return 0;
@ -1533,6 +1561,22 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadOr(SDNode *Node, EVT NVT) {
if (!SelectAddr(Node, Ptr, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) if (!SelectAddr(Node, Ptr, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4))
return 0; return 0;
// Which index into the table.
enum AtomicOpc Op;
switch (Node->getOpcode()) {
case ISD::ATOMIC_LOAD_OR:
Op = OR;
break;
case ISD::ATOMIC_LOAD_AND:
Op = AND;
break;
case ISD::ATOMIC_LOAD_XOR:
Op = XOR;
break;
default:
return 0;
}
bool isCN = false; bool isCN = false;
ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val); ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val);
if (CN) { if (CN) {
@ -1540,8 +1584,6 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadOr(SDNode *Node, EVT NVT) {
Val = CurDAG->getTargetConstant(CN->getSExtValue(), NVT); Val = CurDAG->getTargetConstant(CN->getSExtValue(), NVT);
} }
// Which index into the table.
enum AtomicOpc Op = OR;
unsigned Opc = 0; unsigned Opc = 0;
switch (NVT.getSimpleVT().SimpleTy) { switch (NVT.getSimpleVT().SimpleTy) {
default: return 0; default: return 0;
@ -1693,8 +1735,10 @@ SDNode *X86DAGToDAGISel::Select(SDNode *Node) {
return RetVal; return RetVal;
break; break;
} }
case ISD::ATOMIC_LOAD_XOR:
case ISD::ATOMIC_LOAD_AND:
case ISD::ATOMIC_LOAD_OR: { case ISD::ATOMIC_LOAD_OR: {
SDNode *RetVal = SelectAtomicLoadOr(Node, NVT); SDNode *RetVal = SelectAtomicLoadArith(Node, NVT);
if (RetVal) if (RetVal)
return RetVal; return RetVal;
break; break;

View File

@ -630,6 +630,8 @@ def #NAME#64mi8 : RIi8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4},
defm LOCK_ADD : LOCK_ArithBinOp<0x00, 0x80, 0x83, MRM0m, "add">; defm LOCK_ADD : LOCK_ArithBinOp<0x00, 0x80, 0x83, MRM0m, "add">;
defm LOCK_SUB : LOCK_ArithBinOp<0x28, 0x80, 0x83, MRM5m, "sub">; defm LOCK_SUB : LOCK_ArithBinOp<0x28, 0x80, 0x83, MRM5m, "sub">;
defm LOCK_OR : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM1m, "or">; defm LOCK_OR : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM1m, "or">;
defm LOCK_AND : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM4m, "and">;
defm LOCK_XOR : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM6m, "xor">;
// Optimized codegen when the non-memory output is not used. // Optimized codegen when the non-memory output is not used.
let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1 in { let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1 in {