mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-04 03:06:28 +00:00
Add a couple dag combines to transform mulhi/mullo into a wider multiply
when the wider type is legal. This allows us to compile: define zeroext i16 @test1(i16 zeroext %x) nounwind { entry: %div = udiv i16 %x, 33 ret i16 %div } into: test1: # @test1 movzwl 4(%esp), %eax imull $63551, %eax, %eax # imm = 0xF83F shrl $21, %eax ret instead of: test1: # @test1 movw $-1985, %ax # imm = 0xFFFFFFFFFFFFF83F mulw 4(%esp) andl $65504, %edx # imm = 0xFFE0 movl %edx, %eax shrl $5, %eax ret Implementing rdar://8760399 and example #4 from: http://blog.regehr.org/archives/320 We should implement the same thing for [su]mul_hilo, but I don't have immediate plans to do this. llvm-svn: 121696
This commit is contained in:
parent
0368bf7457
commit
14810c808b
@ -1916,6 +1916,7 @@ SDValue DAGCombiner::visitMULHS(SDNode *N) {
|
||||
SDValue N1 = N->getOperand(1);
|
||||
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
|
||||
EVT VT = N->getValueType(0);
|
||||
DebugLoc DL = N->getDebugLoc();
|
||||
|
||||
// fold (mulhs x, 0) -> 0
|
||||
if (N1C && N1C->isNullValue())
|
||||
@ -1929,6 +1930,22 @@ SDValue DAGCombiner::visitMULHS(SDNode *N) {
|
||||
if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF)
|
||||
return DAG.getConstant(0, VT);
|
||||
|
||||
// If the type twice as wide is legal, transform the mulhs to a wider multiply
|
||||
// plus a shift.
|
||||
if (VT.isSimple() && !VT.isVector()) {
|
||||
MVT Simple = VT.getSimpleVT();
|
||||
unsigned SimpleSize = Simple.getSizeInBits();
|
||||
EVT NewVT = EVT::getIntegerVT(*DAG.getContext(), SimpleSize*2);
|
||||
if (TLI.isOperationLegal(ISD::MUL, NewVT)) {
|
||||
N0 = DAG.getNode(ISD::SIGN_EXTEND, DL, NewVT, N0);
|
||||
N1 = DAG.getNode(ISD::SIGN_EXTEND, DL, NewVT, N1);
|
||||
N1 = DAG.getNode(ISD::MUL, DL, NewVT, N0, N1);
|
||||
N1 = DAG.getNode(ISD::SRA, DL, NewVT, N1,
|
||||
DAG.getConstant(SimpleSize, getShiftAmountTy()));
|
||||
return DAG.getNode(ISD::TRUNCATE, DL, VT, N1);
|
||||
}
|
||||
}
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
@ -1937,6 +1954,7 @@ SDValue DAGCombiner::visitMULHU(SDNode *N) {
|
||||
SDValue N1 = N->getOperand(1);
|
||||
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
|
||||
EVT VT = N->getValueType(0);
|
||||
DebugLoc DL = N->getDebugLoc();
|
||||
|
||||
// fold (mulhu x, 0) -> 0
|
||||
if (N1C && N1C->isNullValue())
|
||||
@ -1948,6 +1966,22 @@ SDValue DAGCombiner::visitMULHU(SDNode *N) {
|
||||
if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF)
|
||||
return DAG.getConstant(0, VT);
|
||||
|
||||
// If the type twice as wide is legal, transform the mulhu to a wider multiply
|
||||
// plus a shift.
|
||||
if (VT.isSimple() && !VT.isVector()) {
|
||||
MVT Simple = VT.getSimpleVT();
|
||||
unsigned SimpleSize = Simple.getSizeInBits();
|
||||
EVT NewVT = EVT::getIntegerVT(*DAG.getContext(), SimpleSize*2);
|
||||
if (TLI.isOperationLegal(ISD::MUL, NewVT)) {
|
||||
N0 = DAG.getNode(ISD::ZERO_EXTEND, DL, NewVT, N0);
|
||||
N1 = DAG.getNode(ISD::ZERO_EXTEND, DL, NewVT, N1);
|
||||
N1 = DAG.getNode(ISD::MUL, DL, NewVT, N0, N1);
|
||||
N1 = DAG.getNode(ISD::SRL, DL, NewVT, N1,
|
||||
DAG.getConstant(SimpleSize, getShiftAmountTy()));
|
||||
return DAG.getNode(ISD::TRUNCATE, DL, VT, N1);
|
||||
}
|
||||
}
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
@ -2011,6 +2045,7 @@ SDValue DAGCombiner::visitSMUL_LOHI(SDNode *N) {
|
||||
SDValue Res = SimplifyNodeWithTwoResults(N, ISD::MUL, ISD::MULHS);
|
||||
if (Res.getNode()) return Res;
|
||||
|
||||
// TODO: Transform smul_lohi to mul if the wider mul is legal!
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
@ -2018,6 +2053,7 @@ SDValue DAGCombiner::visitUMUL_LOHI(SDNode *N) {
|
||||
SDValue Res = SimplifyNodeWithTwoResults(N, ISD::MUL, ISD::MULHU);
|
||||
if (Res.getNode()) return Res;
|
||||
|
||||
// TODO: Transform umul_lohi to mul if the wider mul is legal!
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,42 @@
|
||||
; RUN: llc < %s -mtriple=i686-pc-linux-gnu | grep -- -1985 | count 1
|
||||
; RUN: llc < %s -mtriple=i686-pc-linux-gnu -asm-verbose=0 | FileCheck %s
|
||||
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
|
||||
target triple = "i686-pc-linux-gnu"
|
||||
|
||||
define zeroext i16 @a(i16 zeroext %x) nounwind {
|
||||
define zeroext i16 @test1(i16 zeroext %x) nounwind {
|
||||
entry:
|
||||
%div = udiv i16 %x, 33 ; <i32> [#uses=1]
|
||||
%div = udiv i16 %x, 33
|
||||
ret i16 %div
|
||||
; CHECK: test1:
|
||||
; CHECK: imull $63551, %eax, %eax
|
||||
; CHECK-NEXT: shrl $21, %eax
|
||||
; CHECK-NEXT: ret
|
||||
}
|
||||
|
||||
define zeroext i16 @test2(i8 signext %x, i16 zeroext %c) nounwind readnone ssp noredzone {
|
||||
entry:
|
||||
%div = udiv i16 %c, 3
|
||||
ret i16 %div
|
||||
|
||||
; CHECK: test2:
|
||||
; CHECK: imull $43691, %eax, %eax
|
||||
; CHECK-NEXT: shrl $17, %eax
|
||||
; CHECK-NEXT: ret
|
||||
}
|
||||
|
||||
define zeroext i8 @test3(i8 zeroext %x, i8 zeroext %c) nounwind readnone ssp noredzone {
|
||||
entry:
|
||||
%div = udiv i8 %c, 3
|
||||
ret i8 %div
|
||||
|
||||
; CHECK: test3:
|
||||
; CHECK: imull $171, %eax, %eax
|
||||
; CHECK-NEXT: shrb %ah
|
||||
; CHECK-NEXT: movzbl %ah, %eax
|
||||
; CHECK-NEXT: ret
|
||||
}
|
||||
|
||||
define signext i16 @test4(i16 signext %x) nounwind {
|
||||
entry:
|
||||
%div = sdiv i16 %x, 33 ; <i32> [#uses=1]
|
||||
ret i16 %div
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
; RUN: llc < %s -mtriple=i686-pc-linux-gnu | grep -- -1985
|
||||
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
|
||||
target triple = "i686-pc-linux-gnu"
|
||||
|
||||
define signext i16 @a(i16 signext %x) nounwind {
|
||||
entry:
|
||||
%div = sdiv i16 %x, 33 ; <i32> [#uses=1]
|
||||
ret i16 %div
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user