[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