diff options
author | Simon Pilgrim <llvm-dev@redking.me.uk> | 2018-08-08 14:51:19 +0000 |
---|---|---|
committer | Simon Pilgrim <llvm-dev@redking.me.uk> | 2018-08-08 14:51:19 +0000 |
commit | 164e8b0b5cbbcd31dcc78d422e8e564cd1b356b1 (patch) | |
tree | 9852e5decf84e76f4d81c712c6f711d77c7da1a0 /llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | |
parent | 5c579572811fbe6a5523baa5fd9b2119c6ed92a9 (diff) | |
download | bcm5719-llvm-164e8b0b5cbbcd31dcc78d422e8e564cd1b356b1.tar.gz bcm5719-llvm-164e8b0b5cbbcd31dcc78d422e8e564cd1b356b1.zip |
[TargetLowering] BuildUDIV - Add support for divide by one (PR38477)
Provide a pass-through of the numerator for divide by one cases - this is the same approach we take in DAGCombiner::visitSDIVLike.
I investigated whether we could achieve this by magic MULHU/SRL values but nothing appeared to work as we don't have a way for MULHU(x,c) -> x
llvm-svn: 339254
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 7e4766c5445..7f0ab5325f7 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -3569,7 +3569,6 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG, auto BuildUDIVPattern = [](const APInt &Divisor, unsigned &PreShift, APInt &Magic, unsigned &PostShift) { - assert(!Divisor.isOneValue() && "UDIV by one not supported"); // FIXME: We should use a narrower constant when the upper // bits are known to be zero. APInt::mu magics = Divisor.magicu(); @@ -3586,7 +3585,7 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG, Magic = magics.m; - if (magics.a == 0) { + if (magics.a == 0 || Divisor.isOneValue()) { assert(magics.s < Divisor.getBitWidth() && "We shouldn't generate an undefined shift!"); PostShift = magics.s; @@ -3615,9 +3614,6 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG, auto *C = dyn_cast<ConstantSDNode>(N1.getOperand(i)); if (!C || C->isNullValue() || C->getAPIntValue().getBitWidth() != EltBits) return SDValue(); - // TODO: Handle udiv by one. - if (C->isOne()) - return SDValue(); APInt MagicVal; unsigned PreShiftVal, PostShiftVal; bool SelNPQ = BuildUDIVPattern(C->getAPIntValue(), PreShiftVal, MagicVal, @@ -3687,10 +3683,15 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG, Created.push_back(NPQ.getNode()); Q = DAG.getNode(ISD::ADD, dl, VT, NPQ, Q); - Created.push_back(NPQ.getNode()); + Created.push_back(Q.getNode()); } - return DAG.getNode(ISD::SRL, dl, VT, Q, PostShift); + Q = DAG.getNode(ISD::SRL, dl, VT, Q, PostShift); + Created.push_back(Q.getNode()); + + SDValue One = DAG.getConstant(1, dl, VT); + SDValue IsOne = DAG.getSetCC(dl, VT, N1, One, ISD::SETEQ); + return DAG.getSelect(dl, VT, IsOne, N0, Q); } bool TargetLowering:: |