[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp

Chris Lattner lattner at cs.uiuc.edu
Tue Jan 18 20:19:55 PST 2005



Changes in directory llvm/lib/CodeGen/SelectionDAG:

LegalizeDAG.cpp updated: 1.43 -> 1.44
---
Log message:

Implement a way of expanding shifts.  This applies to targets that offer 
select operations or to shifts that are by a constant.  This automatically
implements (with no special code) all of the special cases for shift by 32,
shift by < 32 and shift by > 32.



---
Diffs of the changes:  (+94 -3)

Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.43 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.44
--- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.43	Tue Jan 18 15:57:59 2005
+++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp	Tue Jan 18 22:19:40 2005
@@ -119,6 +119,9 @@
   void ExpandOp(SDOperand O, SDOperand &Lo, SDOperand &Hi);
   SDOperand PromoteOp(SDOperand O);
 
+  bool ExpandShift(unsigned Opc, SDOperand Op, SDOperand Amt,
+                   SDOperand &Lo, SDOperand &Hi);
+
   SDOperand getIntPtrConstant(uint64_t Val) {
     return DAG.getConstant(Val, TLI.getPointerTy());
   }
@@ -1157,6 +1160,71 @@
   return Result;
 }
 
+/// ExpandShift - Try to find a clever way to expand this shift operation out to
+/// smaller elements.  If we can't find a way that is more efficient than a
+/// libcall on this target, return false.  Otherwise, return true with the
+/// low-parts expanded into Lo and Hi.
+bool SelectionDAGLegalize::ExpandShift(unsigned Opc, SDOperand Op,SDOperand Amt,
+                                       SDOperand &Lo, SDOperand &Hi) {
+  assert((Opc == ISD::SHL || Opc == ISD::SRA || Opc == ISD::SRL) &&
+         "This is not a shift!");
+  MVT::ValueType NVT = TLI.getTypeToTransformTo(Op.getValueType());
+
+  // If we have an efficient select operation (or if the selects will all fold
+  // away), lower to some complex code, otherwise just emit the libcall.
+  if (TLI.getOperationAction(ISD::SELECT, NVT) != TargetLowering::Legal &&
+      !isa<ConstantSDNode>(Amt))
+    return false;
+
+  SDOperand InL, InH;
+  ExpandOp(Op, InL, InH);
+  SDOperand ShAmt = LegalizeOp(Amt);
+  SDOperand OShAmt = ShAmt;  // Unmasked shift amount.
+  MVT::ValueType ShTy = ShAmt.getValueType();
+  
+  unsigned NVTBits = MVT::getSizeInBits(NVT);
+  SDOperand NAmt = DAG.getNode(ISD::SUB, ShTy,           // NAmt = 32-ShAmt
+                               DAG.getConstant(NVTBits, ShTy), ShAmt);
+
+  if (TLI.getShiftAmountFlavor() != TargetLowering::Mask) {
+    ShAmt = DAG.getNode(ISD::AND, ShTy, ShAmt,             // ShAmt &= 31
+                        DAG.getConstant(NVTBits-1, ShTy));
+    NAmt  = DAG.getNode(ISD::AND, ShTy, NAmt,              // NAmt &= 31
+                        DAG.getConstant(NVTBits-1, ShTy));
+  }
+
+  if (Opc == ISD::SHL) {
+    SDOperand T1 = DAG.getNode(ISD::OR, NVT,// T1 = (Hi << Amt) | (Lo >> NAmt)
+                               DAG.getNode(ISD::SHL, NVT, InH, ShAmt),
+                               DAG.getNode(ISD::SRL, NVT, InL, NAmt));
+    SDOperand T2 = DAG.getNode(ISD::SHL, NVT, InL, ShAmt); // T2 = Lo << Amt
+    
+    SDOperand Cond = DAG.getSetCC(ISD::SETGE, TLI.getSetCCResultTy(), OShAmt,
+                                  DAG.getConstant(NVTBits, ShTy));
+    Hi = DAG.getNode(ISD::SELECT, NVT, Cond, T2, T1);
+    Lo = DAG.getNode(ISD::SELECT, NVT, Cond, DAG.getConstant(0, NVT), T2);
+  } else {
+    SDOperand T1 = DAG.getNode(ISD::OR, NVT,// T1 = (Hi << NAmt) | (Lo >> Amt)
+                               DAG.getNode(ISD::SHL, NVT, InH, NAmt),
+                               DAG.getNode(ISD::SRL, NVT, InL, ShAmt));
+    bool isSign = Opc == ISD::SRA;
+    SDOperand T2 = DAG.getNode(Opc, NVT, InH, ShAmt);
+
+    SDOperand HiPart;
+    if (isSign)
+      HiPart = DAG.getNode(Opc, NVT, InH, DAG.getConstant(NVTBits-1, ShTy));
+    else
+      HiPart = DAG.getConstant(0, NVT);
+    SDOperand Cond = DAG.getSetCC(ISD::SETGE, TLI.getSetCCResultTy(), OShAmt,
+                                  DAG.getConstant(NVTBits, ShTy));
+    Lo = DAG.getNode(ISD::SELECT, NVT, Cond, T2, T1);
+    Hi = DAG.getNode(ISD::SELECT, NVT, Cond, HiPart,T2);
+  }
+  return true;
+}
+                                       
+
+
 /// ExpandOp - Expand the specified SDOperand into its two component pieces
 /// Lo&Hi.  Note that the Op MUST be an expanded type.  As a result of this, the
 /// LegalizeNodes map is filled in for any results that are not expanded, the
@@ -1316,6 +1384,32 @@
       LibCallName = "__fixunsdfdi";
     break;
 
+  case ISD::SHL:
+    // If we can emit an efficient shift operation, do so now.
+    if (ExpandShift(ISD::SHL, Node->getOperand(0), Node->getOperand(1),
+                    Lo, Hi))
+      break;
+    // Otherwise, emit a libcall.
+    LibCallName = "__ashldi3";
+    break;
+
+  case ISD::SRA:
+    // If we can emit an efficient shift operation, do so now.
+    if (ExpandShift(ISD::SRA, Node->getOperand(0), Node->getOperand(1),
+                    Lo, Hi))
+      break;
+    // Otherwise, emit a libcall.
+    LibCallName = "__ashrdi3";
+    break;
+  case ISD::SRL:
+    // If we can emit an efficient shift operation, do so now.
+    if (ExpandShift(ISD::SRL, Node->getOperand(0), Node->getOperand(1),
+                    Lo, Hi))
+      break;
+    // Otherwise, emit a libcall.
+    LibCallName = "__lshrdi3";
+    break;
+
   case ISD::ADD:  LibCallName = "__adddi3"; break;
   case ISD::SUB:  LibCallName = "__subdi3"; break;
   case ISD::MUL:  LibCallName = "__muldi3"; break;
@@ -1323,9 +1417,6 @@
   case ISD::UDIV: LibCallName = "__udivdi3"; break;
   case ISD::SREM: LibCallName = "__moddi3"; break;
   case ISD::UREM: LibCallName = "__umoddi3"; break;
-  case ISD::SHL:  LibCallName = "__ashldi3"; break;
-  case ISD::SRA:  LibCallName = "__ashrdi3"; break;
-  case ISD::SRL:  LibCallName = "__lshrdi3"; break;
   }
 
   // Int2FP -> __floatdisf/__floatdidf






More information about the llvm-commits mailing list