Changes in directory llvm/lib/Target/PowerPC:
PPCISelDAGToDAG.cpp updated: 1.180 -> 1.181 --- Log message: New rlwimi implementation, which is superior to the old one. There are still a couple missed optimizations, but we now generate all the possible rlwimis for multiple inserts into the same bitfield. More regression tests to come. --- Diffs of the changes: (+47 -88) PPCISelDAGToDAG.cpp | 135 ++++++++++++++++++---------------------------------- 1 files changed, 47 insertions(+), 88 deletions(-) Index: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp diff -u llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:1.180 llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:1.181 --- llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:1.180 Sat Apr 22 13:53:45 2006 +++ llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp Sat May 6 19:23:38 2006 @@ -391,15 +391,7 @@ /// SelectBitfieldInsert - turn an or of two masked values into /// the rotate left word immediate then mask insert (rlwimi) instruction. -/// Returns true on success, false if the caller still needs to select OR. -/// -/// Patterns matched: -/// 1. or shl, and 5. or and, and -/// 2. or and, shl 6. or shl, shr -/// 3. or shr, and 7. or shr, shl -/// 4. or and, shr SDNode *PPCDAGToDAGISel::SelectBitfieldInsert(SDNode *N) { - bool IsRotate = false; unsigned TgtMask = 0xFFFFFFFF, InsMask = 0xFFFFFFFF, SH = 0; unsigned Value; @@ -409,90 +401,57 @@ unsigned Op0Opc = Op0.getOpcode(); unsigned Op1Opc = Op1.getOpcode(); - // Verify that we have the correct opcodes - if (ISD::SHL != Op0Opc && ISD::SRL != Op0Opc && ISD::AND != Op0Opc) - return false; - if (ISD::SHL != Op1Opc && ISD::SRL != Op1Opc && ISD::AND != Op1Opc) - return false; - - // Generate Mask value for Target - if (isIntImmediate(Op0.getOperand(1), Value)) { - switch(Op0Opc) { - case ISD::SHL: TgtMask <<= Value; break; - case ISD::SRL: TgtMask >>= Value; break; - case ISD::AND: TgtMask &= Value; break; + uint64_t LKZ, LKO, RKZ, RKO; + TLI.ComputeMaskedBits(Op0, TgtMask, LKZ, LKO); + TLI.ComputeMaskedBits(Op1, TgtMask, RKZ, RKO); + + // FIXME: rotrwi / rotlwi + if ((LKZ | RKZ) == 0x00000000FFFFFFFFULL) { + unsigned PInsMask = ~RKZ; + unsigned PTgtMask = ~LKZ; + + // If the LHS has a foldable shift, then swap it to the RHS so that we can + // fold the shift into the insert. + if (Op0Opc == ISD::AND && Op1Opc == ISD::AND) { + if (Op0.getOperand(0).getOpcode() == ISD::SHL || + Op0.getOperand(0).getOpcode() == ISD::SRL) { + if (Op1.getOperand(0).getOpcode() != ISD::SHL && + Op1.getOperand(0).getOpcode() != ISD::SRL) { + std::swap(Op0, Op1); + std::swap(Op0Opc, Op1Opc); + std::swap(PInsMask, PTgtMask); + } + } } - } else { - return 0; - } - - // Generate Mask value for Insert - if (!isIntImmediate(Op1.getOperand(1), Value)) - return 0; - - switch(Op1Opc) { - case ISD::SHL: - SH = Value; - InsMask <<= SH; - if (Op0Opc == ISD::SRL) IsRotate = true; - break; - case ISD::SRL: - SH = Value; - InsMask >>= SH; - SH = 32-SH; - if (Op0Opc == ISD::SHL) IsRotate = true; - break; - case ISD::AND: - InsMask &= Value; - break; - } - - // If both of the inputs are ANDs and one of them has a logical shift by - // constant as its input, make that AND the inserted value so that we can - // combine the shift into the rotate part of the rlwimi instruction - bool IsAndWithShiftOp = false; - if (Op0Opc == ISD::AND && Op1Opc == ISD::AND) { - if (Op1.getOperand(0).getOpcode() == ISD::SHL || - Op1.getOperand(0).getOpcode() == ISD::SRL) { - if (isIntImmediate(Op1.getOperand(0).getOperand(1), Value)) { - SH = Op1.getOperand(0).getOpcode() == ISD::SHL ? Value : 32 - Value; - IsAndWithShiftOp = true; - } - } else if (Op0.getOperand(0).getOpcode() == ISD::SHL || - Op0.getOperand(0).getOpcode() == ISD::SRL) { - if (isIntImmediate(Op0.getOperand(0).getOperand(1), Value)) { - std::swap(Op0, Op1); - std::swap(TgtMask, InsMask); - SH = Op1.getOperand(0).getOpcode() == ISD::SHL ? Value : 32 - Value; - IsAndWithShiftOp = true; + + unsigned MB, ME; + if (isRunOfOnes(PInsMask, MB, ME)) { + SDOperand Tmp1, Tmp2, Tmp3; + bool DisjointMask = (PTgtMask ^ PInsMask) == 0xFFFFFFFF; + + if ((Op1Opc == ISD::SHL || Op1Opc == ISD::SRL) && + isIntImmediate(Op1.getOperand(1), Value)) { + Op1 = Op1.getOperand(0); + SH = (Op1Opc == ISD::SHL) ? Value : 32 - Value; + } + if (Op1Opc == ISD::AND) { + unsigned SHOpc = Op1.getOperand(0).getOpcode(); + if ((SHOpc == ISD::SHL || SHOpc == ISD::SRL) && + isIntImmediate(Op1.getOperand(0).getOperand(1), Value)) { + Op1 = Op1.getOperand(0).getOperand(0); + SH = (SHOpc == ISD::SHL) ? Value : 32 - Value; + } else { + Op1 = Op1.getOperand(0); + } } + + Tmp3 = (Op0Opc == ISD::AND && DisjointMask) ? Op0.getOperand(0) : Op0; + Select(Tmp1, Tmp3); + Select(Tmp2, Op1); + return CurDAG->getTargetNode(PPC::RLWIMI, MVT::i32, Tmp1, Tmp2, + getI32Imm(SH), getI32Imm(MB), getI32Imm(ME)); } } - - // Verify that the Target mask and Insert mask together form a full word mask - // and that the Insert mask is a run of set bits (which implies both are runs - // of set bits). Given that, Select the arguments and generate the rlwimi - // instruction. - unsigned MB, ME; - if (((TgtMask & InsMask) == 0) && isRunOfOnes(InsMask, MB, ME)) { - bool fullMask = (TgtMask ^ InsMask) == 0xFFFFFFFF; - bool Op0IsAND = Op0Opc == ISD::AND; - // Check for rotlwi / rotrwi here, a special case of bitfield insert - // where both bitfield halves are sourced from the same value. - if (IsRotate && fullMask && - N->getOperand(0).getOperand(0) == N->getOperand(1).getOperand(0)) { - SDOperand Tmp; - Select(Tmp, N->getOperand(0).getOperand(0)); - return CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, Tmp, - getI32Imm(SH), getI32Imm(0), getI32Imm(31)); - } - SDOperand Tmp1, Tmp2; - Select(Tmp1, ((Op0IsAND && fullMask) ? Op0.getOperand(0) : Op0)); - Select(Tmp2, (IsAndWithShiftOp ? Op1.getOperand(0).getOperand(0) - : Op1.getOperand(0))); - return CurDAG->getTargetNode(PPC::RLWIMI, MVT::i32, Tmp1, Tmp2, - getI32Imm(SH), getI32Imm(MB), getI32Imm(ME)); - } return 0; } _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits