implement support for 64-bit add/sub, fix a broken assertion for 64-bit
authorChris Lattner <sabre@nondot.org>
Thu, 25 Aug 2005 23:21:06 +0000 (23:21 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 25 Aug 2005 23:21:06 +0000 (23:21 +0000)
return.  Allow the udiv breaker-upper to work with any non-zero constant
operand.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23066 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/PowerPC/PPCISelDAGToDAG.cpp

index 00989697b334488feb9c3ad015cbf818a22237a0..b55dca3411926c46b697cb9d77f50fa1261cdc65 100644 (file)
@@ -909,7 +909,7 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) {
     // If this is a divide by constant, we can emit code using some magic
     // constants to implement it as a multiply instead.
     unsigned Imm;
-    if (isIntImmediate(N->getOperand(1), Imm) && (signed)Imm > 1) {
+    if (isIntImmediate(N->getOperand(1), Imm) && Imm) {
       SDOperand Result = Select(BuildUDIVSequence(N));
       assert(Result.ResNo == 0);
       CurDAG->ReplaceAllUsesWith(N, Result.Val);
@@ -1129,6 +1129,62 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) {
                          Select(N->getOperand(0)));
     break;
   }
+    
+  case ISD::ADD_PARTS: {
+    SDOperand LHSL = Select(N->getOperand(0));
+    SDOperand LHSH = Select(N->getOperand(1));
+   
+    unsigned Imm;
+    bool ME, ZE;
+    if (isIntImmediate(N->getOperand(3), Imm)) {
+      ME = (signed)Imm == -1;
+      ZE = Imm == 0;
+    }
+
+    std::vector<SDOperand> Result;
+    SDOperand CarryFromLo;
+    if (isIntImmediate(N->getOperand(2), Imm) &&
+        ((signed)Imm >= -32768 || (signed)Imm < 32768)) {
+      // Codegen the low 32 bits of the add.  Interestingly, there is no
+      // shifted form of add immediate carrying.
+      CarryFromLo = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag,
+                                          LHSL, getI32Imm(Imm));
+    } else {
+      CarryFromLo = CurDAG->getTargetNode(PPC::ADDC, MVT::i32, MVT::Flag,
+                                          LHSL, Select(N->getOperand(2)));
+    }
+    Result.push_back(CarryFromLo);
+    CarryFromLo = CarryFromLo.getValue(1);
+    
+    // Codegen the high 32 bits, adding zero, minus one, or the full value
+    // along with the carry flag produced by addc/addic.
+    SDOperand ResultHi;
+    if (ZE)
+      ResultHi = CurDAG->getTargetNode(PPC::ADDZE, MVT::i32, LHSH, CarryFromLo);
+    else if (ME)
+      ResultHi = CurDAG->getTargetNode(PPC::ADDME, MVT::i32, LHSH, CarryFromLo);
+    else
+      ResultHi = CurDAG->getTargetNode(PPC::ADDE, MVT::i32, LHSH,
+                                       Select(N->getOperand(3)), CarryFromLo);
+    Result.push_back(ResultHi);
+    CurDAG->ReplaceAllUsesWith(N, Result);
+    return Result[Op.ResNo];
+  }
+  case ISD::SUB_PARTS: {
+    SDOperand LHSL = Select(N->getOperand(0));
+    SDOperand LHSH = Select(N->getOperand(1));
+    SDOperand RHSL = Select(N->getOperand(2));
+    SDOperand RHSH = Select(N->getOperand(3));
+
+    std::vector<SDOperand> Result;
+    Result.push_back(CurDAG->getTargetNode(PPC::SUBFC, MVT::i32, MVT::Flag,
+                                           RHSL, LHSL));
+    Result.push_back(CurDAG->getTargetNode(PPC::SUBFE, MVT::i32, RHSH, LHSH,
+                                           Result[0].getValue(1)));
+    CurDAG->ReplaceAllUsesWith(N, Result);
+    return Result[Op.ResNo];
+  }
+    
   case ISD::LOAD:
   case ISD::EXTLOAD:
   case ISD::ZEXTLOAD:
@@ -1419,7 +1475,7 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) {
       if (N->getNumOperands() > 2) {
         assert(N->getOperand(1).getValueType() == MVT::i32 &&
                N->getOperand(2).getValueType() == MVT::i32 &&
-               N->getNumOperands() == 2 && "Unknown two-register ret value!");
+               N->getNumOperands() == 3 && "Unknown two-register ret value!");
         Val = Select(N->getOperand(2));
         Chain = CurDAG->getCopyToReg(Chain, PPC::R4, Val);
       }