summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/SelectionDAG
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-10-12 20:58:32 +0000
committerChris Lattner <sabre@nondot.org>2006-10-12 20:58:32 +0000
commitd0620d2773a9958420f9ae02a24b5a5ed3a713f2 (patch)
treea6197374361c2c7c5345b925148eb434b0c8b71a /llvm/lib/CodeGen/SelectionDAG
parentce34aa8fd7e1f953217f992ba44a648613e749a7 (diff)
downloadbcm5719-llvm-d0620d2773a9958420f9ae02a24b5a5ed3a713f2.tar.gz
bcm5719-llvm-d0620d2773a9958420f9ae02a24b5a5ed3a713f2.zip
Lower X%C into X/C+stuff. This allows the 'division by a constant' logic to
apply to rems as well as divs. This fixes PR945 and speeds up ReedSolomon from 14.57s to 10.90s (which is now faster than gcc). It compiles CodeGen/X86/rem.ll into: _test1: subl $4, %esp movl %esi, (%esp) movl $2155905153, %ecx movl 8(%esp), %esi movl %esi, %eax imull %ecx addl %esi, %edx movl %edx, %eax shrl $31, %eax sarl $7, %edx addl %eax, %edx imull $255, %edx, %eax subl %eax, %esi movl %esi, %eax movl (%esp), %esi addl $4, %esp ret _test2: movl 4(%esp), %eax movl %eax, %ecx sarl $31, %ecx shrl $24, %ecx addl %eax, %ecx andl $4294967040, %ecx subl %ecx, %eax ret _test3: subl $4, %esp movl %esi, (%esp) movl $2155905153, %ecx movl 8(%esp), %esi movl %esi, %eax mull %ecx shrl $7, %edx imull $255, %edx, %eax subl %eax, %esi movl %esi, %eax movl (%esp), %esi addl $4, %esp ret instead of div/idiv instructions. llvm-svn: 30920
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp24
1 files changed, 24 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 70ff8371f79..d6379dc858b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -885,6 +885,18 @@ SDOperand DAGCombiner::visitSREM(SDNode *N) {
if (TLI.MaskedValueIsZero(N1, SignBit) &&
TLI.MaskedValueIsZero(N0, SignBit))
return DAG.getNode(ISD::UREM, VT, N0, N1);
+
+ // Unconditionally lower X%C -> X-X/C*C. This allows the X/C logic to hack on
+ // the remainder operation.
+ if (N1C && !N1C->isNullValue()) {
+ SDOperand Div = DAG.getNode(ISD::SDIV, VT, N0, N1);
+ SDOperand Mul = DAG.getNode(ISD::MUL, VT, Div, N1);
+ SDOperand Sub = DAG.getNode(ISD::SUB, VT, N0, Mul);
+ AddToWorkList(Div.Val);
+ AddToWorkList(Mul.Val);
+ return Sub;
+ }
+
return SDOperand();
}
@@ -911,6 +923,18 @@ SDOperand DAGCombiner::visitUREM(SDNode *N) {
}
}
}
+
+ // Unconditionally lower X%C -> X-X/C*C. This allows the X/C logic to hack on
+ // the remainder operation.
+ if (N1C && !N1C->isNullValue()) {
+ SDOperand Div = DAG.getNode(ISD::UDIV, VT, N0, N1);
+ SDOperand Mul = DAG.getNode(ISD::MUL, VT, Div, N1);
+ SDOperand Sub = DAG.getNode(ISD::SUB, VT, N0, Mul);
+ AddToWorkList(Div.Val);
+ AddToWorkList(Mul.Val);
+ return Sub;
+ }
+
return SDOperand();
}
OpenPOWER on IntegriCloud