1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-20 03:23:01 +02: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:
Benjamin Kramer 2011-03-17 20:39:14 +00:00
parent a85996c235
commit 52ffb6ea96
2 changed files with 33 additions and 9 deletions

View File

@ -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())));

View File

@ -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
}