Fold add(add(mul(x,y),a),b) -> lmul(x,y,a,b) if the intermediate
authorRichard Osborne <richard@xmos.com>
Wed, 10 Mar 2010 16:19:31 +0000 (16:19 +0000)
committerRichard Osborne <richard@xmos.com>
Wed, 10 Mar 2010 16:19:31 +0000 (16:19 +0000)
results are unused elsewhere.

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

lib/Target/XCore/XCoreISelLowering.cpp
test/CodeGen/XCore/mul64.ll

index d27adf40f6c0061c7a3a716ae1d13c20f1cd2c9f..ad4dcfc67f2c5471614458bf2ad9f51c2aebb17e 100644 (file)
@@ -154,6 +154,7 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
 
   // We have target-specific dag combine patterns for the following nodes:
   setTargetDAGCombine(ISD::STORE);
+  setTargetDAGCombine(ISD::ADD);
 }
 
 SDValue XCoreTargetLowering::
@@ -1279,6 +1280,61 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
     }
   }
   break;
+  case ISD::ADD: {
+    // Fold expressions such as add(add(mul(x,y),a),b) -> lmul(x, y, a, b).
+    // This is only profitable if the intermediate results are unused
+    // elsewhere.
+    SDValue N0 = N->getOperand(0);
+    SDValue N1 = N->getOperand(1);
+    SDValue AddOp;
+    SDValue OtherOp;
+    if (N0.getOpcode() == ISD::ADD) {
+      AddOp = N0;
+      OtherOp = N1;
+    } else if (N1.getOpcode() == ISD::ADD) {
+      AddOp = N1;
+      OtherOp = N0;
+    } else {
+      break;
+    }
+    SDValue Addend0, Addend1;
+    SDValue Mul0;
+    SDValue Mul1;
+    if (OtherOp.getOpcode() == ISD::MUL) {
+      // add(add(a,b),mul(x,y))
+      if (!OtherOp.hasOneUse() || !AddOp.hasOneUse())
+        break;
+      Mul0 = OtherOp.getOperand(0);
+      Mul1 = OtherOp.getOperand(1);
+      Addend0 = AddOp.getOperand(0);
+      Addend1 = AddOp.getOperand(1);
+    } else if (AddOp.getOperand(0).getOpcode() == ISD::MUL) {
+      // add(add(mul(x,y),a),b)
+      if (!AddOp.getOperand(0).hasOneUse())
+        break;
+      Mul0 = AddOp.getOperand(0).getOperand(0);
+      Mul1 = AddOp.getOperand(0).getOperand(1);
+      Addend0 = AddOp.getOperand(1);
+      Addend1 = OtherOp;
+    } else if (AddOp.getOperand(1).getOpcode() == ISD::MUL) {
+      // add(add(a,mul(x,y)),b)
+      if (!AddOp.getOperand(1).hasOneUse())
+        break;
+      Mul0 = AddOp.getOperand(1).getOperand(0);
+      Mul1 = AddOp.getOperand(1).getOperand(1);
+      Addend0 = AddOp.getOperand(0);
+      Addend1 = OtherOp;
+    } else {
+      break;
+    }
+    SDValue Zero = DAG.getConstant(0, MVT::i32);
+    SDValue Ignored = DAG.getNode(XCoreISD::LMUL, dl,
+                                  DAG.getVTList(MVT::i32, MVT::i32), Mul0,
+                                  Mul1, Addend0, Addend1);
+    SDValue Result(Ignored.getNode(), 1);
+    return Result;
+  }
+  break;
   case ISD::STORE: {
     // Replace unaligned store of unaligned load with memmove.
     StoreSDNode *ST  = cast<StoreSDNode>(N);
index c06fe5a20b3aec889c35aaea0836388060cf3cd1..329e214d1d23fc0d7841cda1a8ab5b8008c8543e 100644 (file)
@@ -25,3 +25,15 @@ entry:
 ; CHECK-NEXT: mov r0, r3
 ; CHECK-NEXT: mov r1, r2
 ; CHECK-NEXT: retsp 0
+
+define i64 @mul64(i64 %a, i64 %b) {
+entry:
+       %0 = mul i64 %a, %b
+       ret i64 %0
+}
+; CHECK: mul64:
+; CHECK: ldc r11, 0
+; CHECK-NEXT: lmul r11, r4, r0, r2, r11, r11
+; CHECK-NEXT: mul r0, r0, r3
+; CHECK-NEXT: lmul r0, r1, r1, r2, r11, r0
+; CHECK-NEXT: mov r0, r4