[llvm-commits] CVS: llvm/lib/Target/X86/X86ISelPattern.cpp

Chris Lattner lattner at cs.uiuc.edu
Fri Apr 1 20:01:27 PST 2005



Changes in directory llvm/lib/Target/X86:

X86ISelPattern.cpp updated: 1.96 -> 1.97
---
Log message:

Add support for 64-bit shifts.


---
Diffs of the changes:  (+84 -16)

 X86ISelPattern.cpp |  100 ++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 84 insertions(+), 16 deletions(-)


Index: llvm/lib/Target/X86/X86ISelPattern.cpp
diff -u llvm/lib/Target/X86/X86ISelPattern.cpp:1.96 llvm/lib/Target/X86/X86ISelPattern.cpp:1.97
--- llvm/lib/Target/X86/X86ISelPattern.cpp:1.96	Fri Apr  1 16:46:45 2005
+++ llvm/lib/Target/X86/X86ISelPattern.cpp	Fri Apr  1 22:01:14 2005
@@ -1319,29 +1319,34 @@
   unsigned &Reg = ExprMap[N];
   if (Reg) return Reg;
   
-  if (N.getOpcode() != ISD::CALL && N.getOpcode() != ISD::ADD_PARTS &&
-      N.getOpcode() != ISD::SUB_PARTS)
+  switch (N.getOpcode()) {
+  default:
     Reg = Result = (N.getValueType() != MVT::Other) ?
-      MakeReg(N.getValueType()) : 1;
-  else {
+                            MakeReg(N.getValueType()) : 1;
+    break;
+  case ISD::CALL:
     // If this is a call instruction, make sure to prepare ALL of the result
     // values as well as the chain.
-    if (N.getOpcode() == ISD::CALL) {
-      if (Node->getNumValues() == 1)
-        Reg = Result = 1;  // Void call, just a chain.
-      else {
-        Result = MakeReg(Node->getValueType(0));
-        ExprMap[N.getValue(0)] = Result;
-        for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
-          ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
-        ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1;
-      }
-    } else {
+    if (Node->getNumValues() == 1)
+      Reg = Result = 1;  // Void call, just a chain.
+    else {
       Result = MakeReg(Node->getValueType(0));
       ExprMap[N.getValue(0)] = Result;
-      for (unsigned i = 1, e = N.Val->getNumValues(); i != e; ++i)
+      for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
         ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
+      ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1;
     }
+    break;
+  case ISD::ADD_PARTS:
+  case ISD::SUB_PARTS:
+  case ISD::SHL_PARTS:
+  case ISD::SRL_PARTS:
+  case ISD::SRA_PARTS:
+    Result = MakeReg(Node->getValueType(0));
+    ExprMap[N.getValue(0)] = Result;
+    for (unsigned i = 1, e = N.Val->getNumValues(); i != e; ++i)
+      ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
+    break;
   }
   
   switch (N.getOpcode()) {
@@ -2024,6 +2029,69 @@
     return Result+N.ResNo;
   }
 
+  case ISD::SHL_PARTS:
+  case ISD::SRA_PARTS:
+  case ISD::SRL_PARTS: {
+    assert(N.getNumOperands() == 3 && N.getValueType() == MVT::i32 &&
+           "Not an i64 shift!");
+    unsigned ShiftOpLo = SelectExpr(N.getOperand(0));
+    unsigned ShiftOpHi = SelectExpr(N.getOperand(1));
+    unsigned TmpReg = MakeReg(MVT::i32);
+    if (N.getOpcode() == ISD::SRA_PARTS) {
+      // If this is a SHR of a Long, then we need to do funny sign extension
+      // stuff.  TmpReg gets the value to use as the high-part if we are
+      // shifting more than 32 bits.
+      BuildMI(BB, X86::SAR32ri, 2, TmpReg).addReg(ShiftOpHi).addImm(31);
+    } else {
+      // Other shifts use a fixed zero value if the shift is more than 32 bits.
+      BuildMI(BB, X86::MOV32ri, 1, TmpReg).addImm(0);
+    }
+
+    // Initialize CL with the shift amount.
+    unsigned ShiftAmountReg = SelectExpr(N.getOperand(2));
+    BuildMI(BB, X86::MOV8rr, 1, X86::CL).addReg(ShiftAmountReg);
+
+    unsigned TmpReg2 = MakeReg(MVT::i32);
+    unsigned TmpReg3 = MakeReg(MVT::i32);
+    if (N.getOpcode() == ISD::SHL_PARTS) {
+      // TmpReg2 = shld inHi, inLo
+      BuildMI(BB, X86::SHLD32rrCL, 2,TmpReg2).addReg(ShiftOpHi)
+        .addReg(ShiftOpLo);
+      // TmpReg3 = shl  inLo, CL
+      BuildMI(BB, X86::SHL32rCL, 1, TmpReg3).addReg(ShiftOpLo);
+      
+      // Set the flags to indicate whether the shift was by more than 32 bits.
+      BuildMI(BB, X86::TEST8ri, 2).addReg(X86::CL).addImm(32);
+      
+      // DestHi = (>32) ? TmpReg3 : TmpReg2;
+      BuildMI(BB, X86::CMOVNE32rr, 2, 
+              Result+1).addReg(TmpReg2).addReg(TmpReg3);
+      // DestLo = (>32) ? TmpReg : TmpReg3;
+      BuildMI(BB, X86::CMOVNE32rr, 2,
+              Result).addReg(TmpReg3).addReg(TmpReg);
+    } else {
+      // TmpReg2 = shrd inLo, inHi
+      BuildMI(BB, X86::SHRD32rrCL,2,TmpReg2).addReg(ShiftOpLo)
+        .addReg(ShiftOpHi);
+      // TmpReg3 = s[ah]r  inHi, CL
+      BuildMI(BB, N.getOpcode() == ISD::SRA_PARTS ? X86::SAR32rCL 
+                                                  : X86::SHR32rCL, 1, TmpReg3)
+        .addReg(ShiftOpHi);
+      
+      // Set the flags to indicate whether the shift was by more than 32 bits.
+      BuildMI(BB, X86::TEST8ri, 2).addReg(X86::CL).addImm(32);
+      
+      // DestLo = (>32) ? TmpReg3 : TmpReg2;
+      BuildMI(BB, X86::CMOVNE32rr, 2, 
+              Result).addReg(TmpReg2).addReg(TmpReg3);
+      
+      // DestHi = (>32) ? TmpReg : TmpReg3;
+      BuildMI(BB, X86::CMOVNE32rr, 2, 
+              Result+1).addReg(TmpReg3).addReg(TmpReg);
+    }
+    return Result+N.ResNo;
+  }
+
   case ISD::SELECT:
     if (getRegPressure(N.getOperand(1)) > getRegPressure(N.getOperand(2))) {
       Tmp2 = SelectExpr(N.getOperand(1));






More information about the llvm-commits mailing list