diff options
author | Richard Osborne <richard@xmos.com> | 2010-03-10 16:19:31 +0000 |
---|---|---|
committer | Richard Osborne <richard@xmos.com> | 2010-03-10 16:19:31 +0000 |
commit | 2dacd1e9873a4fefb97c7cdf5317c5a5c6150a76 (patch) | |
tree | bb49fe73c78873468ed4c65598638ac62e94cdc0 | |
parent | 48ee0bbb729ae5b4757c74d029b9f5ce602f530a (diff) |
Fold add(add(mul(x,y),a),b) -> lmul(x,y,a,b) if the intermediate
results are unused elsewhere.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98157 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/XCore/XCoreISelLowering.cpp | 56 | ||||
-rw-r--r-- | test/CodeGen/XCore/mul64.ll | 12 |
2 files changed, 68 insertions, 0 deletions
diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index d27adf40f6..ad4dcfc67f 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -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); diff --git a/test/CodeGen/XCore/mul64.ll b/test/CodeGen/XCore/mul64.ll index c06fe5a20b..329e214d1d 100644 --- a/test/CodeGen/XCore/mul64.ll +++ b/test/CodeGen/XCore/mul64.ll @@ -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 |