From: Hal Finkel Date: Fri, 28 Feb 2014 06:11:16 +0000 (+0000) Subject: Swap PPC isel operands to allow for 0-folding X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=3d2ce7a5a71c580142f974300899c0140eef4c65 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 --- diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index b9eecbe16f3..44821d31b51 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -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(Op2->getOperand(0)); + if (!C) + return false; + + if (!C->isNullValue()) + return false; + } + + return true; +} + +void PPCDAGToDAGISel::SwapAllSelectUsers(SDNode *N) { + SmallVector 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::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)); diff --git a/test/CodeGen/PowerPC/crbits.ll b/test/CodeGen/PowerPC/crbits.ll index 998e940e8a6..7021102e523 100644 --- a/test/CodeGen/PowerPC/crbits.ll +++ b/test/CodeGen/PowerPC/crbits.ll @@ -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 }