[llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp

Nate Begeman natebegeman at mac.com
Thu Aug 18 00:30:58 PDT 2005



Changes in directory llvm/lib/Target/PowerPC:

PPC32ISelDAGToDAG.cpp updated: 1.7 -> 1.8
---
Log message:

Add support for ISD::AND, and its various optimized forms.


---
Diffs of the changes:  (+105 -0)

 PPC32ISelDAGToDAG.cpp |  105 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 105 insertions(+)


Index: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp
diff -u llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.7 llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.8
--- llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.7	Thu Aug 18 00:44:50 2005
+++ llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp	Thu Aug 18 02:30:46 2005
@@ -90,6 +90,71 @@
   return false;
 }
 
+// isOprShiftImm - Returns true if the specified operand is a shift opcode with
+// a immediate shift count less than 32.
+static bool isOprShiftImm(SDNode *N, unsigned& Opc, unsigned& SH) {
+  Opc = N->getOpcode();
+  return (Opc == ISD::SHL || Opc == ISD::SRL || Opc == ISD::SRA) &&
+    isIntImmediate(N->getOperand(1).Val, SH) && SH < 32;
+}
+
+// isRunOfOnes - Returns true iff Val consists of one contiguous run of 1s with
+// any number of 0s on either side.  The 1s are allowed to wrap from LSB to
+// MSB, so 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs.  0x0F0F0000 is
+// not, since all 1s are not contiguous.
+static bool isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) {
+  if (isShiftedMask_32(Val)) {
+    // look for the first non-zero bit
+    MB = CountLeadingZeros_32(Val);
+    // look for the first zero bit after the run of ones
+    ME = CountLeadingZeros_32((Val - 1) ^ Val);
+    return true;
+  } else if (isShiftedMask_32(Val = ~Val)) { // invert mask
+                                             // effectively look for the first zero bit
+    ME = CountLeadingZeros_32(Val) - 1;
+    // effectively look for the first one bit after the run of zeros
+    MB = CountLeadingZeros_32((Val - 1) ^ Val) + 1;
+    return true;
+  }
+  // no run present
+  return false;
+}
+
+// isRotateAndMask - Returns true if Mask and Shift can be folded in to a rotate
+// and mask opcode and mask operation.
+static bool isRotateAndMask(SDNode *N, unsigned Mask, bool IsShiftMask,
+                            unsigned &SH, unsigned &MB, unsigned &ME) {
+  unsigned Shift  = 32;
+  unsigned Indeterminant = ~0;  // bit mask marking indeterminant results
+  unsigned Opcode = N->getOpcode();
+  if (!isIntImmediate(N->getOperand(1).Val, Shift) || (Shift > 31))
+    return false;
+  
+  if (Opcode == ISD::SHL) {
+    // apply shift left to mask if it comes first
+    if (IsShiftMask) Mask = Mask << Shift;
+    // determine which bits are made indeterminant by shift
+    Indeterminant = ~(0xFFFFFFFFu << Shift);
+  } else if (Opcode == ISD::SRA || Opcode == ISD::SRL) { 
+    // apply shift right to mask if it comes first
+    if (IsShiftMask) Mask = Mask >> Shift;
+    // determine which bits are made indeterminant by shift
+    Indeterminant = ~(0xFFFFFFFFu >> Shift);
+    // adjust for the left rotate
+    Shift = 32 - Shift;
+  } else {
+    return false;
+  }
+  
+  // if the mask doesn't intersect any Indeterminant bits
+  if (Mask && !(Mask & Indeterminant)) {
+    SH = Shift;
+    // make sure the mask is still a mask (wrap arounds may not be)
+    return isRunOfOnes(Mask, MB, ME);
+  }
+  return false;
+}
+
 // isOpcWithIntImmediate - This method tests to see if the node is a specific
 // opcode and that it has a immediate integer right operand.
 // If so Imm will receive the 32 bit value.
@@ -346,6 +411,46 @@
     CurDAG->SelectNodeTo(N, MVT::i32, PPC::MULHWU, Select(N->getOperand(0)),
                          Select(N->getOperand(1)));
     break;
+  case ISD::AND: {
+    unsigned Imm, SH, MB, ME;
+    // If this is an and of a value rotated between 0 and 31 bits and then and'd
+    // with a mask, emit rlwinm
+    if (isIntImmediate(N->getOperand(1), Imm) && (isShiftedMask_32(Imm) ||
+                                                  isShiftedMask_32(~Imm))) {
+      SDOperand Val;
+      if (isRotateAndMask(N->getOperand(0).Val, Imm, false, SH, MB, ME)) {
+        Val = Select(N->getOperand(0).getOperand(0));
+      } else {
+        Val = Select(N->getOperand(0));
+        isRunOfOnes(Imm, MB, ME);
+        SH = 0;
+      }
+      CurDAG->SelectNodeTo(N, MVT::i32, PPC::RLWINM, Val, getI32Imm(SH),
+                           getI32Imm(MB), getI32Imm(ME));
+      break;
+    }
+    // If this is an and with an immediate that isn't a mask, then codegen it as
+    // high and low 16 bit immediate ands.
+    if (SDNode *I = SelectIntImmediateExpr(N->getOperand(0), 
+                                           N->getOperand(1),
+                                           PPC::ANDISo, PPC::ANDIo)) {
+      CurDAG->ReplaceAllUsesWith(N, I); 
+      N = I;
+      break;
+    }
+    // Finally, check for the case where we are being asked to select
+    // and (not(a), b) or and (a, not(b)) which can be selected as andc.
+    if (isOprNot(N->getOperand(0).Val))
+      CurDAG->SelectNodeTo(N, MVT::i32, PPC::ANDC, Select(N->getOperand(1)),
+                           Select(N->getOperand(0).getOperand(0)));
+    else if (isOprNot(N->getOperand(1).Val))
+      CurDAG->SelectNodeTo(N, MVT::i32, PPC::ANDC, Select(N->getOperand(0)),
+                           Select(N->getOperand(1).getOperand(0)));
+    else
+      CurDAG->SelectNodeTo(N, MVT::i32, PPC::AND, 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