From 4471194d69cc99ed53dc1638e06053b069dc6454 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 8 Nov 2007 09:25:29 +0000 Subject: [PATCH] If both parts of smul_lohi, etc. are used, don't simplify. If only one part is used, try simplify it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43888 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 61 +++++------ test/CodeGen/X86/2007-11-07-MulBy4.ll | 129 +++++++++++++++++++++++ 2 files changed, 160 insertions(+), 30 deletions(-) create mode 100644 test/CodeGen/X86/2007-11-07-MulBy4.ll diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 140d80a7119..73d7db413f1 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1420,7 +1420,8 @@ SDOperand DAGCombiner::visitMULHU(SDNode *N) { bool DAGCombiner::SimplifyNodeWithTwoResults(SDNode *N, unsigned LoOp, unsigned HiOp) { // If the high half is not needed, just compute the low half. - if (!N->hasAnyUseOfValue(1) && + bool HiExists = N->hasAnyUseOfValue(1); + if (!HiExists && (!AfterLegalize || TLI.isOperationLegal(LoOp, N->getValueType(0)))) { DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), @@ -1431,7 +1432,8 @@ bool DAGCombiner::SimplifyNodeWithTwoResults(SDNode *N, } // If the low half is not needed, just compute the high half. - if (!N->hasAnyUseOfValue(0) && + bool LoExists = N->hasAnyUseOfValue(0); + if (!LoExists && (!AfterLegalize || TLI.isOperationLegal(HiOp, N->getValueType(1)))) { DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), @@ -1441,36 +1443,35 @@ bool DAGCombiner::SimplifyNodeWithTwoResults(SDNode *N, return true; } - // If the two computed results can be siplified separately, separate them. - SDOperand Lo = DAG.getNode(LoOp, N->getValueType(0), - N->op_begin(), N->getNumOperands()); - SDOperand Hi = DAG.getNode(HiOp, N->getValueType(1), - N->op_begin(), N->getNumOperands()); - unsigned LoExists = !Lo.use_empty(); - unsigned HiExists = !Hi.use_empty(); - SDOperand LoOpt = Lo; - SDOperand HiOpt = Hi; - if (!LoExists || !HiExists) { - SDOperand Pair = DAG.getNode(ISD::BUILD_PAIR, MVT::Other, Lo, Hi); - assert(Pair.use_empty() && "Pair with type MVT::Other already exists!"); - LoOpt = combine(Lo.Val); - HiOpt = combine(Hi.Val); - if (!LoOpt.Val) - LoOpt = Pair.getOperand(0); - if (!HiOpt.Val) - HiOpt = Pair.getOperand(1); - DAG.DeleteNode(Pair.Val); - } - if ((LoExists || LoOpt != Lo) && - (HiExists || HiOpt != Hi) && - TLI.isOperationLegal(LoOpt.getOpcode(), LoOpt.getValueType()) && - TLI.isOperationLegal(HiOpt.getOpcode(), HiOpt.getValueType())) { - DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), LoOpt); - DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), HiOpt); - return true; + // If both halves are used, return as it is. + if (LoExists && HiExists) + return false; + + // If the two computed results can be simplified separately, separate them. + bool RetVal = false; + if (LoExists) { + SDOperand Lo = DAG.getNode(LoOp, N->getValueType(0), + N->op_begin(), N->getNumOperands()); + SDOperand LoOpt = combine(Lo.Val); + if (LoOpt.Val && LoOpt != Lo && + TLI.isOperationLegal(LoOpt.getOpcode(), LoOpt.getValueType())) { + RetVal = true; + DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), LoOpt); + } } - return false; + if (HiExists) { + SDOperand Hi = DAG.getNode(HiOp, N->getValueType(1), + N->op_begin(), N->getNumOperands()); + SDOperand HiOpt = combine(Hi.Val); + if (HiOpt.Val && HiOpt != Hi && + TLI.isOperationLegal(HiOpt.getOpcode(), HiOpt.getValueType())) { + RetVal = true; + DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), HiOpt); + } + } + + return RetVal; } SDOperand DAGCombiner::visitSMUL_LOHI(SDNode *N) { diff --git a/test/CodeGen/X86/2007-11-07-MulBy4.ll b/test/CodeGen/X86/2007-11-07-MulBy4.ll new file mode 100644 index 00000000000..d7fb684a6ba --- /dev/null +++ b/test/CodeGen/X86/2007-11-07-MulBy4.ll @@ -0,0 +1,129 @@ +; RUN: llvm-as < %s | llc -march=x86 | not grep imul + + %struct.eebb = type { %struct.eebb*, i16* } + %struct.hf = type { %struct.hf*, i16*, i8*, i32, i32, %struct.eebb*, i32, i32, i8*, i8*, i8*, i8*, i16*, i8*, i16*, %struct.ri, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, [30 x i32], %struct.eebb, i32, i8* } + %struct.foo_data = type { i32, i32, i32, i32*, i32, i32, i8*, i8*, i32, i32, i32, i32, i32, i32, i32, i32, i8*, i16*, i16*, i16*, i16*, i32, i32, i32, %struct.ri*, i8*, %struct.hf* } + %struct.ri = type { %struct.ri*, i32, i8*, i16*, i32*, i32 } + +define fastcc i32 @foo(i16* %eptr, i8* %ecode, %struct.foo_data* %md, i32 %ims) { +entry: + %tmp36 = load i32* null, align 4 ; [#uses=1] + %tmp37 = icmp ult i32 0, %tmp36 ; [#uses=1] + br i1 %tmp37, label %cond_next79, label %cond_true + +cond_true: ; preds = %entry + ret i32 0 + +cond_next79: ; preds = %entry + %tmp85 = load i32* null, align 4 ; [#uses=1] + %tmp86 = icmp ult i32 0, %tmp85 ; [#uses=1] + br i1 %tmp86, label %cond_next130, label %cond_true89 + +cond_true89: ; preds = %cond_next79 + ret i32 0 + +cond_next130: ; preds = %cond_next79 + %tmp173 = icmp eq i32 0, 0 ; [#uses=1] + br i1 %tmp173, label %cond_next201, label %cond_true176 + +cond_true176: ; preds = %cond_next130 + ret i32 0 + +cond_next201: ; preds = %cond_next130 + switch i32 0, label %bb19955 [ + i32 0, label %bb1266 + i32 1, label %bb5018 + i32 2, label %bb5075 + i32 3, label %cond_true5534 + i32 4, label %cond_true5534 + i32 5, label %bb6039 + i32 6, label %bb6181 + i32 7, label %bb6323 + i32 8, label %bb6463 + i32 9, label %bb6605 + i32 10, label %bb6746 + i32 11, label %cond_next5871 + i32 16, label %bb5452 + i32 17, label %bb5395 + i32 19, label %bb4883 + i32 20, label %bb5136 + i32 23, label %bb12899 + i32 64, label %bb2162 + i32 69, label %bb1447 + i32 70, label %bb1737 + i32 71, label %bb1447 + i32 72, label %bb1737 + i32 73, label %cond_true1984 + i32 75, label %bb740 + i32 80, label %bb552 + ] + +bb552: ; preds = %cond_next201 + ret i32 0 + +bb740: ; preds = %cond_next201 + ret i32 0 + +bb1266: ; preds = %cond_next201 + ret i32 0 + +bb1447: ; preds = %cond_next201, %cond_next201 + ret i32 0 + +bb1737: ; preds = %cond_next201, %cond_next201 + ret i32 0 + +cond_true1984: ; preds = %cond_next201 + ret i32 0 + +bb2162: ; preds = %cond_next201 + ret i32 0 + +bb4883: ; preds = %cond_next201 + ret i32 0 + +bb5018: ; preds = %cond_next201 + ret i32 0 + +bb5075: ; preds = %cond_next201 + ret i32 0 + +bb5136: ; preds = %cond_next201 + ret i32 0 + +bb5395: ; preds = %cond_next201 + ret i32 0 + +bb5452: ; preds = %cond_next201 + ret i32 0 + +cond_true5534: ; preds = %cond_next201, %cond_next201 + ret i32 0 + +cond_next5871: ; preds = %cond_next201 + ret i32 0 + +bb6039: ; preds = %cond_next201 + ret i32 0 + +bb6181: ; preds = %cond_next201 + ret i32 0 + +bb6323: ; preds = %cond_next201 + ret i32 0 + +bb6463: ; preds = %cond_next201 + ret i32 0 + +bb6605: ; preds = %cond_next201 + ret i32 0 + +bb6746: ; preds = %cond_next201 + ret i32 0 + +bb12899: ; preds = %cond_next201 + ret i32 0 + +bb19955: ; preds = %cond_next201 + ret i32 0 +}