ISD::OR, and it's accompanying SelectBitfieldInsert

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22889 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nate Begeman 2005-08-19 00:38:14 +00:00
parent 679c408768
commit 02b88a4586

View File

@ -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