mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
BuildUDIV: If the divisor is even we can simplify the fixup of the multiplied value by introducing an early shift.
This allows us to compile "unsigned foo(unsigned x) { return x/28; }" into shrl $2, %edi imulq $613566757, %rdi, %rax shrq $32, %rax ret instead of movl %edi, %eax imulq $613566757, %rax, %rcx shrq $32, %rcx subl %ecx, %eax shrl %eax addl %ecx, %eax shrl $4, %eax on x86_64 llvm-svn: 127829
This commit is contained in:
parent
a85996c235
commit
52ffb6ea96
@ -3174,26 +3174,39 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,
|
||||
|
||||
// FIXME: We should use a narrower constant when the upper
|
||||
// bits are known to be zero.
|
||||
ConstantSDNode *N1C = cast<ConstantSDNode>(N->getOperand(1));
|
||||
APInt::mu magics = N1C->getAPIntValue().magicu();
|
||||
const APInt &N1C = cast<ConstantSDNode>(N->getOperand(1))->getAPIntValue();
|
||||
APInt::mu magics = N1C.magicu();
|
||||
|
||||
SDValue Q = N->getOperand(0);
|
||||
|
||||
// If the divisor is even, we can avoid using the expensive fixup by shifting
|
||||
// the divided value upfront.
|
||||
if (magics.a != 0 && !N1C[0]) {
|
||||
unsigned Shift = N1C.countTrailingZeros();
|
||||
Q = DAG.getNode(ISD::SRL, dl, VT, Q,
|
||||
DAG.getConstant(Shift, getShiftAmountTy(Q.getValueType())));
|
||||
if (Created)
|
||||
Created->push_back(Q.getNode());
|
||||
|
||||
// Get magic number for the shifted divisor.
|
||||
magics = N1C.lshr(Shift).magicu(Shift);
|
||||
assert(magics.a == 0 && "Should use cheap fixup now");
|
||||
}
|
||||
|
||||
// Multiply the numerator (operand 0) by the magic value
|
||||
// FIXME: We should support doing a MUL in a wider type
|
||||
SDValue Q;
|
||||
if (isOperationLegalOrCustom(ISD::MULHU, VT))
|
||||
Q = DAG.getNode(ISD::MULHU, dl, VT, N->getOperand(0),
|
||||
DAG.getConstant(magics.m, VT));
|
||||
Q = DAG.getNode(ISD::MULHU, dl, VT, Q, DAG.getConstant(magics.m, VT));
|
||||
else if (isOperationLegalOrCustom(ISD::UMUL_LOHI, VT))
|
||||
Q = SDValue(DAG.getNode(ISD::UMUL_LOHI, dl, DAG.getVTList(VT, VT),
|
||||
N->getOperand(0),
|
||||
DAG.getConstant(magics.m, VT)).getNode(), 1);
|
||||
Q = SDValue(DAG.getNode(ISD::UMUL_LOHI, dl, DAG.getVTList(VT, VT), Q,
|
||||
DAG.getConstant(magics.m, VT)).getNode(), 1);
|
||||
else
|
||||
return SDValue(); // No mulhu or equvialent
|
||||
if (Created)
|
||||
Created->push_back(Q.getNode());
|
||||
|
||||
if (magics.a == 0) {
|
||||
assert(magics.s < N1C->getAPIntValue().getBitWidth() &&
|
||||
assert(magics.s < N1C.getBitWidth() &&
|
||||
"We shouldn't generate an undefined shift!");
|
||||
return DAG.getNode(ISD::SRL, dl, VT, Q,
|
||||
DAG.getConstant(magics.s, getShiftAmountTy(Q.getValueType())));
|
||||
|
@ -60,3 +60,14 @@ entry:
|
||||
; CHECK: shrl $31, %ecx
|
||||
; CHECK: sarl $18, %eax
|
||||
}
|
||||
|
||||
define i32 @test7(i32 %x) nounwind {
|
||||
%div = udiv i32 %x, 28
|
||||
ret i32 %div
|
||||
; CHECK: test7:
|
||||
; CHECK: shrl $2
|
||||
; CHECK: movl $613566757
|
||||
; CHECK: mull
|
||||
; CHECK-NOT: shrl
|
||||
; CHECK: ret
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user