Skip to content

Commit 8c2ad81

Browse files
author
Evan Cheng
committed
Emit a single _udivmodsi4 libcall instead of two separate _udivsi3 and
_umodsi3 libcalls if they have the same arguments. This optimization was apparently broken if one of the node was replaced in place. rdar://11714607 llvm-svn: 158900
1 parent 422080f commit 8c2ad81

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1930,9 +1930,11 @@ static bool isDivRemLibcallAvailable(SDNode *Node, bool isSigned,
19301930
return TLI.getLibcallName(LC) != 0;
19311931
}
19321932

1933-
/// UseDivRem - Only issue divrem libcall if both quotient and remainder are
1933+
/// useDivRem - Only issue divrem libcall if both quotient and remainder are
19341934
/// needed.
1935-
static bool UseDivRem(SDNode *Node, bool isSigned, bool isDIV) {
1935+
static bool useDivRem(SDNode *Node, bool isSigned, bool isDIV) {
1936+
// The other use might have been replaced with a divrem already.
1937+
unsigned DivRemOpc = isSigned ? ISD::SDIVREM : ISD::UDIVREM;
19361938
unsigned OtherOpcode = 0;
19371939
if (isSigned)
19381940
OtherOpcode = isDIV ? ISD::SREM : ISD::SDIV;
@@ -1946,7 +1948,7 @@ static bool UseDivRem(SDNode *Node, bool isSigned, bool isDIV) {
19461948
SDNode *User = *UI;
19471949
if (User == Node)
19481950
continue;
1949-
if (User->getOpcode() == OtherOpcode &&
1951+
if ((User->getOpcode() == OtherOpcode || User->getOpcode() == DivRemOpc) &&
19501952
User->getOperand(0) == Op0 &&
19511953
User->getOperand(1) == Op1)
19521954
return true;
@@ -3092,7 +3094,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
30923094
Tmp3 = Node->getOperand(1);
30933095
if (TLI.isOperationLegalOrCustom(DivRemOpc, VT) ||
30943096
(isDivRemLibcallAvailable(Node, isSigned, TLI) &&
3095-
UseDivRem(Node, isSigned, false))) {
3097+
useDivRem(Node, isSigned, false))) {
30963098
Tmp1 = DAG.getNode(DivRemOpc, dl, VTs, Tmp2, Tmp3).getValue(1);
30973099
} else if (TLI.isOperationLegalOrCustom(DivOpc, VT)) {
30983100
// X % Y -> X-X/Y*Y
@@ -3120,7 +3122,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
31203122
SDVTList VTs = DAG.getVTList(VT, VT);
31213123
if (TLI.isOperationLegalOrCustom(DivRemOpc, VT) ||
31223124
(isDivRemLibcallAvailable(Node, isSigned, TLI) &&
3123-
UseDivRem(Node, isSigned, true)))
3125+
useDivRem(Node, isSigned, true)))
31243126
Tmp1 = DAG.getNode(DivRemOpc, dl, VTs, Node->getOperand(0),
31253127
Node->getOperand(1));
31263128
else if (isSigned)

llvm/test/CodeGen/ARM/divmod.ll

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: llc < %s -mtriple=arm-apple-ios5.0 | FileCheck %s
1+
; RUN: llc < %s -mtriple=arm-apple-ios5.0 -mcpu=cortex-a8 | FileCheck %s
22

33
define void @foo(i32 %x, i32 %y, i32* nocapture %P) nounwind ssp {
44
entry:
@@ -56,3 +56,17 @@ bb1:
5656

5757
declare i32 @llvm.objectsize.i32(i8*, i1) nounwind readnone
5858
declare i8* @__memset_chk(i8*, i32, i32, i32) nounwind
59+
60+
; rdar://11714607
61+
define i32 @howmany(i32 %x, i32 %y) nounwind {
62+
entry:
63+
; CHECK: howmany:
64+
; CHECK: bl ___udivmodsi4
65+
; CHECK-NOT: ___udivsi3
66+
%rem = urem i32 %x, %y
67+
%div = udiv i32 %x, %y
68+
%not.cmp = icmp ne i32 %rem, 0
69+
%add = zext i1 %not.cmp to i32
70+
%cond = add i32 %add, %div
71+
ret i32 %cond
72+
}

0 commit comments

Comments
 (0)