From 02b88a4586704f34bc65afca3348453eae69d1d3 Mon Sep 17 00:00:00 2001 From: Nate Begeman Date: Fri, 19 Aug 2005 00:38:14 +0000 Subject: [PATCH] ISD::OR, and it's accompanying SelectBitfieldInsert git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22889 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 137 ++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index c02336273fd..4e94717762d 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -53,7 +53,8 @@ namespace { unsigned OCHi, unsigned OCLo, bool IsArithmetic = false, bool Negate = false); - + SDNode *SelectBitfieldInsert(SDNode *N); + /// InstructionSelectBasicBlock - This callback is invoked by /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) { @@ -179,6 +180,115 @@ static bool isIntImmediate(SDOperand N, unsigned& Imm) { return false; } +/// 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 *PPC32DAGToDAGISel::SelectBitfieldInsert(SDNode *N) { + bool IsRotate = false; + unsigned TgtMask = 0xFFFFFFFF, InsMask = 0xFFFFFFFF, SH = 0; + unsigned Value; + + SDOperand Op0 = N->getOperand(0); + SDOperand Op1 = N->getOperand(1); + + 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; + } + } else { + return 0; + } + + // Generate Mask value for Insert + if (isIntImmediate(Op1.getOperand(1), Value)) { + 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; + } + } else { + return 0; + } + + // 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; + } + } + } + + // 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)) { + Op0 = CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, + Select(N->getOperand(0).getOperand(0)), + getI32Imm(SH), getI32Imm(0), getI32Imm(31)); + return Op0.Val; + } + SDOperand Tmp1 = (Op0IsAND && fullMask) ? Select(Op0.getOperand(0)) + : Select(Op0); + SDOperand Tmp2 = IsAndWithShiftOp ? Select(Op1.getOperand(0).getOperand(0)) + : Select(Op1.getOperand(0)); + Op0 = CurDAG->getTargetNode(PPC::RLWIMI, MVT::i32, Tmp1, Tmp2, + getI32Imm(SH), getI32Imm(MB), getI32Imm(ME)); + return Op0.Val; + } + return 0; +} + // SelectIntImmediateExpr - Choose code for integer operations with an immediate // operand. SDNode *PPC32DAGToDAGISel::SelectIntImmediateExpr(SDOperand LHS, SDOperand RHS, @@ -447,6 +557,31 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { Select(N->getOperand(1))); break; } + case ISD::OR: + if (SDNode *I = SelectBitfieldInsert(N)) { + CurDAG->ReplaceAllUsesWith(N, I); + N = I; + break; + } + if (SDNode *I = SelectIntImmediateExpr(N->getOperand(0), + N->getOperand(1), + PPC::ORIS, PPC::ORI)) { + CurDAG->ReplaceAllUsesWith(N, I); + N = I; + break; + } + // Finally, check for the case where we are being asked to select + // 'or (not(a), b)' or 'or (a, not(b))' which can be selected as orc. + if (isOprNot(N->getOperand(0).Val)) + CurDAG->SelectNodeTo(N, MVT::i32, PPC::ORC, Select(N->getOperand(1)), + Select(N->getOperand(0).getOperand(0))); + else if (isOprNot(N->getOperand(1).Val)) + CurDAG->SelectNodeTo(N, MVT::i32, PPC::ORC, Select(N->getOperand(0)), + Select(N->getOperand(1).getOperand(0))); + else + CurDAG->SelectNodeTo(N, MVT::i32, PPC::OR, Select(N->getOperand(0)), + Select(N->getOperand(1))); + break; case ISD::XOR: // Check whether or not this node is a logical 'not'. This is represented // by llvm as a xor with the constant value -1 (all bits set). If this is a