Swap PPC isel operands to allow for 0-folding

The PPC isel instruction can fold 0 into the first operand (thus eliminating
the need to materialize a zero-containing register when the 'true' result of
the isel is 0). When the isel is fed by a bit register operation that we can
invert, do so as part of the bit-register-operation peephole routine.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202469 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Hal Finkel 2014-02-28 06:11:16 +00:00
parent 49c76560f3
commit 3d2ce7a5a7
2 changed files with 134 additions and 27 deletions

View File

@ -189,6 +189,9 @@ private:
void PeepholePPC64();
void PeepholdCROps();
bool AllUsersSelectZero(SDNode *N);
void SwapAllSelectUsers(SDNode *N);
};
}
@ -1504,6 +1507,74 @@ void PPCDAGToDAGISel::PostprocessISelDAG() {
PeepholdCROps();
}
// Check if all users of this node will become isel where the second operand
// is the constant zero. If this is so, and if we can negate the condition,
// then we can flip the true and false operands. This will allow the zero to
// be folded with the isel so that we don't need to materialize a register
// containing zero.
bool PPCDAGToDAGISel::AllUsersSelectZero(SDNode *N) {
// If we're not using isel, then this does not matter.
if (!PPCSubTarget.hasISEL())
return false;
for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
UI != UE; ++UI) {
SDNode *User = *UI;
if (!User->isMachineOpcode())
return false;
if (User->getMachineOpcode() != PPC::SELECT_I4 &&
User->getMachineOpcode() != PPC::SELECT_I8)
return false;
SDNode *Op2 = User->getOperand(2).getNode();
if (!Op2->isMachineOpcode())
return false;
if (Op2->getMachineOpcode() != PPC::LI &&
Op2->getMachineOpcode() != PPC::LI8)
return false;
ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op2->getOperand(0));
if (!C)
return false;
if (!C->isNullValue())
return false;
}
return true;
}
void PPCDAGToDAGISel::SwapAllSelectUsers(SDNode *N) {
SmallVector<SDNode *, 4> ToReplace;
for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
UI != UE; ++UI) {
SDNode *User = *UI;
assert((User->getMachineOpcode() == PPC::SELECT_I4 ||
User->getMachineOpcode() == PPC::SELECT_I8) &&
"Must have all select users");
ToReplace.push_back(User);
}
for (SmallVector<SDNode *, 4>::iterator UI = ToReplace.begin(),
UE = ToReplace.end(); UI != UE; ++UI) {
SDNode *User = *UI;
SDNode *ResNode =
CurDAG->getMachineNode(User->getMachineOpcode(), SDLoc(User),
User->getValueType(0), User->getOperand(0),
User->getOperand(2),
User->getOperand(1));
DEBUG(dbgs() << "CR Peephole replacing:\nOld: ");
DEBUG(User->dump(CurDAG));
DEBUG(dbgs() << "\nNew: ");
DEBUG(ResNode->dump(CurDAG));
DEBUG(dbgs() << "\n");
ReplaceUses(User, ResNode);
}
}
void PPCDAGToDAGISel::PeepholdCROps() {
bool IsModified;
do {
@ -1563,6 +1634,7 @@ void PPCDAGToDAGISel::PeepholdCROps() {
break;
}
bool SelectSwap = false;
switch (Opcode) {
default: break;
case PPC::CRAND:
@ -1591,6 +1663,11 @@ void PPCDAGToDAGISel::PeepholdCROps() {
MVT::i1, MachineNode->getOperand(0),
MachineNode->getOperand(1).
getOperand(0));
else if (AllUsersSelectZero(MachineNode))
ResNode = CurDAG->getMachineNode(PPC::CRNAND, SDLoc(MachineNode),
MVT::i1, MachineNode->getOperand(0),
MachineNode->getOperand(1)),
SelectSwap = true;
break;
case PPC::CRNAND:
if (MachineNode->getOperand(0) == MachineNode->getOperand(1))
@ -1624,6 +1701,11 @@ void PPCDAGToDAGISel::PeepholdCROps() {
MVT::i1, MachineNode->getOperand(1).
getOperand(0),
MachineNode->getOperand(0));
else if (AllUsersSelectZero(MachineNode))
ResNode = CurDAG->getMachineNode(PPC::CRAND, SDLoc(MachineNode),
MVT::i1, MachineNode->getOperand(0),
MachineNode->getOperand(1)),
SelectSwap = true;
break;
case PPC::CROR:
if (MachineNode->getOperand(0) == MachineNode->getOperand(1))
@ -1651,6 +1733,11 @@ void PPCDAGToDAGISel::PeepholdCROps() {
MVT::i1, MachineNode->getOperand(0),
MachineNode->getOperand(1).
getOperand(0));
else if (AllUsersSelectZero(MachineNode))
ResNode = CurDAG->getMachineNode(PPC::CRNOR, SDLoc(MachineNode),
MVT::i1, MachineNode->getOperand(0),
MachineNode->getOperand(1)),
SelectSwap = true;
break;
case PPC::CRXOR:
if (MachineNode->getOperand(0) == MachineNode->getOperand(1))
@ -1685,6 +1772,11 @@ void PPCDAGToDAGISel::PeepholdCROps() {
MVT::i1, MachineNode->getOperand(0),
MachineNode->getOperand(1).
getOperand(0));
else if (AllUsersSelectZero(MachineNode))
ResNode = CurDAG->getMachineNode(PPC::CREQV, SDLoc(MachineNode),
MVT::i1, MachineNode->getOperand(0),
MachineNode->getOperand(1)),
SelectSwap = true;
break;
case PPC::CRNOR:
if (Op1Set || Op2Set)
@ -1713,6 +1805,11 @@ void PPCDAGToDAGISel::PeepholdCROps() {
MVT::i1, MachineNode->getOperand(1).
getOperand(0),
MachineNode->getOperand(0));
else if (AllUsersSelectZero(MachineNode))
ResNode = CurDAG->getMachineNode(PPC::CROR, SDLoc(MachineNode),
MVT::i1, MachineNode->getOperand(0),
MachineNode->getOperand(1)),
SelectSwap = true;
break;
case PPC::CREQV:
if (MachineNode->getOperand(0) == MachineNode->getOperand(1))
@ -1747,6 +1844,11 @@ void PPCDAGToDAGISel::PeepholdCROps() {
MVT::i1, MachineNode->getOperand(0),
MachineNode->getOperand(1).
getOperand(0));
else if (AllUsersSelectZero(MachineNode))
ResNode = CurDAG->getMachineNode(PPC::CRXOR, SDLoc(MachineNode),
MVT::i1, MachineNode->getOperand(0),
MachineNode->getOperand(1)),
SelectSwap = true;
break;
case PPC::CRANDC:
if (MachineNode->getOperand(0) == MachineNode->getOperand(1))
@ -1777,6 +1879,11 @@ void PPCDAGToDAGISel::PeepholdCROps() {
MVT::i1, MachineNode->getOperand(0),
MachineNode->getOperand(1).
getOperand(0));
else if (AllUsersSelectZero(MachineNode))
ResNode = CurDAG->getMachineNode(PPC::CRORC, SDLoc(MachineNode),
MVT::i1, MachineNode->getOperand(1),
MachineNode->getOperand(0)),
SelectSwap = true;
break;
case PPC::CRORC:
if (MachineNode->getOperand(0) == MachineNode->getOperand(1))
@ -1807,6 +1914,11 @@ void PPCDAGToDAGISel::PeepholdCROps() {
MVT::i1, MachineNode->getOperand(0),
MachineNode->getOperand(1).
getOperand(0));
else if (AllUsersSelectZero(MachineNode))
ResNode = CurDAG->getMachineNode(PPC::CRANDC, SDLoc(MachineNode),
MVT::i1, MachineNode->getOperand(1),
MachineNode->getOperand(0)),
SelectSwap = true;
break;
case PPC::SELECT_I4:
case PPC::SELECT_I8:
@ -1841,6 +1953,11 @@ void PPCDAGToDAGISel::PeepholdCROps() {
break;
}
// If we're inverting this node because it is used only by selects that
// we'd like to swap, then swap the selects before the node replacement.
if (SelectSwap)
SwapAllSelectUsers(MachineNode);
if (ResNode != MachineNode) {
DEBUG(dbgs() << "CR Peephole replacing:\nOld: ");
DEBUG(MachineNode->dump(CurDAG));

View File

@ -2,10 +2,6 @@
target datalayout = "E-m:e-i64:64-n32:64"
target triple = "powerpc64-unknown-linux-gnu"
; FIXME: For a number of these we load (1, 0) for the isel into two registers,
; whereas if we reverse the condition, we could use only one register (using ZERO
; for 0 in the isel).
; Function Attrs: nounwind readnone
define zeroext i1 @test1(float %v1, float %v2) #0 {
entry:
@ -18,12 +14,11 @@ entry:
; CHECK-DAG: fcmpu {{[0-9]+}}, 1, 2
; CHECK-DAG: li [[REG1:[0-9]+]], 1
; CHECK-DAG: lfs [[REG2:[0-9]+]],
; CHECK-DAG: li [[REG3:[0-9]+]], 0
; CHECK-DAG: fcmpu {{[0-9]+}}, 2, [[REG2]]
; CHECK: crnor
; CHECK: crnor
; CHECK: crand [[REG4:[0-9]+]],
; CHECK: isel 3, [[REG1]], [[REG3]], [[REG4]]
; CHECK: crnand [[REG4:[0-9]+]],
; CHECK: isel 3, 0, [[REG1]], [[REG4]]
; CHECK: blr
}
@ -39,12 +34,11 @@ entry:
; CHECK-DAG: fcmpu {{[0-9]+}}, 1, 2
; CHECK-DAG: li [[REG1:[0-9]+]], 1
; CHECK-DAG: lfs [[REG2:[0-9]+]],
; CHECK-DAG: li [[REG3:[0-9]+]], 0
; CHECK-DAG: fcmpu {{[0-9]+}}, 2, [[REG2]]
; CHECK: crnor
; CHECK: crnor
; CHECK: crxor [[REG4:[0-9]+]],
; CHECK: isel 3, [[REG1]], [[REG3]], [[REG4]]
; CHECK: creqv [[REG4:[0-9]+]],
; CHECK: isel 3, 0, [[REG1]], [[REG4]]
; CHECK: blr
}
@ -62,13 +56,12 @@ entry:
; CHECK-DAG: fcmpu {{[0-9]+}}, 1, 2
; CHECK-DAG: li [[REG1:[0-9]+]], 1
; CHECK-DAG: lfs [[REG2:[0-9]+]],
; CHECK-DAG: li [[REG3:[0-9]+]], 0
; CHECK-DAG: fcmpu {{[0-9]+}}, 2, [[REG2]]
; CHECK: crnor
; CHECK: crnor
; CHECK: crandc
; CHECK: crxor [[REG4:[0-9]+]],
; CHECK: isel 3, [[REG1]], [[REG3]], [[REG4]]
; CHECK: creqv [[REG4:[0-9]+]],
; CHECK: isel 3, 0, [[REG1]], [[REG4]]
; CHECK: blr
}
@ -96,11 +89,10 @@ entry:
; CHECK-LABEL: @test5
; CHECK-DAG: and [[REG1:[0-9]+]], 3, 4
; CHECK-DAG: cmpwi {{[0-9]+}}, 5, -2
; CHECK: li [[REG3:[0-9]+]], 1
; CHECK: andi. {{[0-9]+}}, [[REG1]], 1
; CHECK: li [[REG4:[0-9]+]], 0
; CHECK: crorc [[REG5:[0-9]+]],
; CHECK: isel 3, [[REG3]], [[REG4]], [[REG5]]
; CHECK-DAG: li [[REG3:[0-9]+]], 1
; CHECK-DAG: andi. {{[0-9]+}}, [[REG1]], 1
; CHECK-DAG: crandc [[REG5:[0-9]+]],
; CHECK: isel 3, 0, [[REG3]], [[REG5]]
; CHECK: blr
}
@ -116,12 +108,11 @@ entry:
; CHECK-DAG: andi. {{[0-9]+}}, 3, 1
; CHECK-DAG: cmpwi {{[0-9]+}}, 5, -2
; CHECK-DAG: cror [[REG1:[0-9]+]], 1, 1
; CHECK: andi. {{[0-9]+}}, 4, 1
; CHECK: li [[REG2:[0-9]+]], 1
; CHECK: li [[REG3:[0-9]+]], 0
; CHECK: crorc [[REG4:[0-9]+]], 1,
; CHECK: crand [[REG5:[0-9]+]], [[REG4]], [[REG1]]
; CHECK: isel 3, [[REG2]], [[REG3]], [[REG5]]
; CHECK-DAG: andi. {{[0-9]+}}, 4, 1
; CHECK-DAG: li [[REG2:[0-9]+]], 1
; CHECK-DAG: crorc [[REG4:[0-9]+]], 1,
; CHECK-DAG: crnand [[REG5:[0-9]+]], [[REG4]], [[REG1]]
; CHECK: isel 3, 0, [[REG2]], [[REG5]]
; CHECK: blr
}
@ -163,10 +154,9 @@ entry:
; CHECK-LABEL: @test10
; CHECK-DAG: cmpwi {{[0-9]+}}, 3, 0
; CHECK-DAG: cmpwi {{[0-9]+}}, 4, 0
; CHECK-DAG: li [[REG1:[0-9]+]], 0
; CHECK-DAG: li [[REG2:[0-9]+]], 1
; CHECK: crandc [[REG3:[0-9]+]],
; CHECK: isel 3, [[REG2]], [[REG1]], [[REG3]]
; CHECK-DAG: crorc [[REG3:[0-9]+]],
; CHECK: isel 3, 0, [[REG2]], [[REG3]]
; CHECK: blr
}