Skip to content

Commit e8f9387

Browse files
committedDec 11, 2015
[X86ISelLowering] Add additional support for multiplication-to-shift conversion.
Summary: This patch adds support of conversion (mul x, 2^N + 1) => (add (shl x, N), x) and (mul x, 2^N - 1) => (sub (shl x, N), x) if the multiplication can not be converted to LEA + SHL or LEA + LEA. LLVM has already supported this on ARM, and it should also be useful on X86. Note the patch currently only applies to cases where the constant operand is positive, and I am planing to add another patch to support negative cases after this. Reviewers: craig.topper, RKSimon Subscribers: aemerson, llvm-commits Differential Revision: http://reviews.llvm.org/D14603 llvm-svn: 255391
1 parent ac2adce commit e8f9387

File tree

2 files changed

+71
-3
lines changed

2 files changed

+71
-3
lines changed
 

‎llvm/lib/Target/X86/X86ISelLowering.cpp

+26-3
Original file line numberDiff line numberDiff line change
@@ -24738,9 +24738,11 @@ static SDValue PerformMulCombine(SDNode *N, SelectionDAG &DAG,
2473824738
MulAmt1 = 3;
2473924739
MulAmt2 = MulAmt / 3;
2474024740
}
24741+
24742+
SDLoc DL(N);
24743+
SDValue NewMul;
2474124744
if (MulAmt2 &&
2474224745
(isPowerOf2_64(MulAmt2) || MulAmt2 == 3 || MulAmt2 == 5 || MulAmt2 == 9)){
24743-
SDLoc DL(N);
2474424746

2474524747
if (isPowerOf2_64(MulAmt2) &&
2474624748
!(N->hasOneUse() && N->use_begin()->getOpcode() == ISD::ADD))
@@ -24749,7 +24751,6 @@ static SDValue PerformMulCombine(SDNode *N, SelectionDAG &DAG,
2474924751
// is an add.
2475024752
std::swap(MulAmt1, MulAmt2);
2475124753

24752-
SDValue NewMul;
2475324754
if (isPowerOf2_64(MulAmt1))
2475424755
NewMul = DAG.getNode(ISD::SHL, DL, VT, N->getOperand(0),
2475524756
DAG.getConstant(Log2_64(MulAmt1), DL, MVT::i8));
@@ -24763,10 +24764,32 @@ static SDValue PerformMulCombine(SDNode *N, SelectionDAG &DAG,
2476324764
else
2476424765
NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, NewMul,
2476524766
DAG.getConstant(MulAmt2, DL, VT));
24767+
}
24768+
24769+
if (!NewMul) {
24770+
uint64_t MaxVal = VT == MVT::i64 ? UINT64_MAX : UINT32_MAX;
24771+
assert(MulAmt != 0 && MulAmt != MaxVal &&
24772+
"Both cases that could cause potential "
24773+
"overflows should have already been handled.");
24774+
if (isPowerOf2_64(MulAmt - 1))
24775+
// (mul x, 2^N + 1) => (add (shl x, N), x)
24776+
NewMul = DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0),
24777+
DAG.getNode(ISD::SHL, DL, VT, N->getOperand(0),
24778+
DAG.getConstant(Log2_64(MulAmt - 1), DL,
24779+
MVT::i8)));
2476624780

24781+
else if (isPowerOf2_64(MulAmt + 1))
24782+
// (mul x, 2^N - 1) => (sub (shl x, N), x)
24783+
NewMul = DAG.getNode(ISD::SUB, DL, VT, DAG.getNode(ISD::SHL, DL, VT,
24784+
N->getOperand(0),
24785+
DAG.getConstant(Log2_64(MulAmt + 1),
24786+
DL, MVT::i8)), N->getOperand(0));
24787+
}
24788+
24789+
if (NewMul)
2476724790
// Do not add new nodes to DAG combiner worklist.
2476824791
DCI.CombineTo(N, NewMul, false);
24769-
}
24792+
2477024793
return SDValue();
2477124794
}
2477224795

‎llvm/test/CodeGen/X86/imul.ll

+45
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,48 @@ define i32 @mul40_32_minsize(i32 %A) minsize {
126126
%mul = mul i32 %A, 40
127127
ret i32 %mul
128128
}
129+
130+
define i32 @mul33_32(i32 %A) {
131+
; X64-LABEL: mul33_32:
132+
; X64: shll
133+
; X64-NEXT: leal
134+
; X86-LABEL: mul33_32:
135+
; X86: shll
136+
; X86-NEXT: addl
137+
%mul = mul i32 %A, 33
138+
ret i32 %mul
139+
}
140+
141+
define i32 @mul31_32(i32 %A) {
142+
; X64-LABEL: mul31_32:
143+
; X64: shll
144+
; X64-NEXT: subl
145+
; X86-LABEL: mul31_32:
146+
; X86: shll
147+
; X86-NEXT: subl
148+
%mul = mul i32 %A, 31
149+
ret i32 %mul
150+
}
151+
152+
define i32 @mul0_32(i32 %A) {
153+
; X64-LABEL: mul0_32:
154+
; X64: xorl %eax, %eax
155+
%mul = mul i32 %A, 0
156+
ret i32 %mul
157+
}
158+
159+
define i32 @mul4294967295_32(i32 %A) {
160+
; X64-LABEL: mul4294967295_32:
161+
; X64: negl %edi
162+
; X64-NEXT: movl %edi, %eax
163+
%mul = mul i32 %A, 4294967295
164+
ret i32 %mul
165+
}
166+
167+
define i64 @mul18446744073709551615_64(i64 %A) {
168+
; X64-LABEL: mul18446744073709551615_64:
169+
; X64: negq %rdi
170+
; X64-NEXT: movq %rdi, %rax
171+
%mul = mul i64 %A, 18446744073709551615
172+
ret i64 %mul
173+
}

0 commit comments

Comments
 (0)
Please sign in to comment.