[llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp
Nate Begeman
natebegeman at mac.com
Thu Aug 18 17:38:30 PDT 2005
Changes in directory llvm/lib/Target/PowerPC:
PPC32ISelDAGToDAG.cpp updated: 1.13 -> 1.14
---
Log message:
ISD::OR, and it's accompanying SelectBitfieldInsert
---
Diffs of the changes: (+136 -1)
PPC32ISelDAGToDAG.cpp | 137 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 136 insertions(+), 1 deletion(-)
Index: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp
diff -u llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.13 llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.14
--- llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.13 Thu Aug 18 18:38:00 2005
+++ llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Thu Aug 18 19:38:14 2005
@@ -53,7 +53,8 @@
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 @@
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 @@
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
More information about the llvm-commits
mailing list