mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-23 17:32:49 +00:00
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:
parent
679c408768
commit
02b88a4586
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user