mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-13 14:47:00 +00:00
Pass function attributes instead of boolean in isIntDivCheap().
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@245921 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
602a9cd084
commit
46ff6da860
@ -228,7 +228,7 @@ public:
|
||||
/// several shifts, adds, and multiplies for this target.
|
||||
/// The definition of "cheaper" may depend on whether we're optimizing
|
||||
/// for speed or for size.
|
||||
virtual bool isIntDivCheap(EVT VT, bool OptSize) const {
|
||||
virtual bool isIntDivCheap(EVT VT, AttributeSet Attr) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2719,11 +2719,14 @@ public:
|
||||
SDValue BuildUDIV(SDNode *N, const APInt &Divisor, SelectionDAG &DAG,
|
||||
bool IsAfterLegalization,
|
||||
std::vector<SDNode *> *Created) const;
|
||||
|
||||
/// Targets may override this function to provide custom SDIV lowering for
|
||||
/// power-of-2 denominators. If the target returns an empty SDValue, LLVM
|
||||
/// assumes SDIV is expensive and replaces it with a series of other integer
|
||||
/// operations.
|
||||
virtual SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor,
|
||||
SelectionDAG &DAG,
|
||||
std::vector<SDNode *> *Created) const {
|
||||
return SDValue();
|
||||
}
|
||||
std::vector<SDNode *> *Created) const;
|
||||
|
||||
/// Indicate whether this target prefers to combine FDIVs with the same
|
||||
/// divisor. If the transform should never be done, return zero. If the
|
||||
|
@ -2183,7 +2183,6 @@ SDValue DAGCombiner::visitSDIV(SDNode *N) {
|
||||
N0, N1);
|
||||
}
|
||||
|
||||
bool MinSize = DAG.getMachineFunction().getFunction()->optForMinSize();
|
||||
// fold (sdiv X, pow2) -> simple ops after legalize
|
||||
// FIXME: We check for the exact bit here because the generic lowering gives
|
||||
// better results in that case. The target-specific lowering should learn how
|
||||
@ -2192,10 +2191,6 @@ SDValue DAGCombiner::visitSDIV(SDNode *N) {
|
||||
!cast<BinaryWithFlagsSDNode>(N)->Flags.hasExact() &&
|
||||
(N1C->getAPIntValue().isPowerOf2() ||
|
||||
(-N1C->getAPIntValue()).isPowerOf2())) {
|
||||
// If integer division is cheap, then don't perform the following fold.
|
||||
if (TLI.isIntDivCheap(N->getValueType(0), MinSize))
|
||||
return SDValue();
|
||||
|
||||
// Target-specific implementation of sdiv x, pow2.
|
||||
if (SDValue Res = BuildSDIVPow2(N))
|
||||
return Res;
|
||||
@ -2232,8 +2227,10 @@ SDValue DAGCombiner::visitSDIV(SDNode *N) {
|
||||
}
|
||||
|
||||
// If integer divide is expensive and we satisfy the requirements, emit an
|
||||
// alternate sequence.
|
||||
if (N1C && !TLI.isIntDivCheap(N->getValueType(0), MinSize))
|
||||
// alternate sequence. Targets may check function attributes for size/speed
|
||||
// trade-offs.
|
||||
AttributeSet Attr = DAG.getMachineFunction().getFunction()->getAttributes();
|
||||
if (N1C && !TLI.isIntDivCheap(N->getValueType(0), Attr))
|
||||
if (SDValue Op = BuildSDIV(N))
|
||||
return Op;
|
||||
|
||||
@ -2289,8 +2286,8 @@ SDValue DAGCombiner::visitUDIV(SDNode *N) {
|
||||
}
|
||||
|
||||
// fold (udiv x, c) -> alternate
|
||||
bool MinSize = DAG.getMachineFunction().getFunction()->optForMinSize();
|
||||
if (N1C && !TLI.isIntDivCheap(N->getValueType(0), MinSize))
|
||||
AttributeSet Attr = DAG.getMachineFunction().getFunction()->getAttributes();
|
||||
if (N1C && !TLI.isIntDivCheap(N->getValueType(0), Attr))
|
||||
if (SDValue Op = BuildUDIV(N))
|
||||
return Op;
|
||||
|
||||
|
@ -2725,6 +2725,16 @@ static SDValue BuildExactSDIV(const TargetLowering &TLI, SDValue Op1, APInt d,
|
||||
return Mul;
|
||||
}
|
||||
|
||||
SDValue TargetLowering::BuildSDIVPow2(SDNode *N, const APInt &Divisor,
|
||||
SelectionDAG &DAG,
|
||||
std::vector<SDNode *> *Created) const {
|
||||
AttributeSet Attr = DAG.getMachineFunction().getFunction()->getAttributes();
|
||||
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
|
||||
if (TLI.isIntDivCheap(N->getValueType(0), Attr))
|
||||
return SDValue(N,0); // Lower SDIV as SDIV
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
/// \brief Given an ISD::SDIV node expressing a divide by constant,
|
||||
/// return a DAG expression to select that will generate the same value by
|
||||
/// multiplying by a magic number.
|
||||
|
@ -26511,7 +26511,7 @@ bool X86TargetLowering::isTargetFTOL() const {
|
||||
return Subtarget->isTargetKnownWindowsMSVC() && !Subtarget->is64Bit();
|
||||
}
|
||||
|
||||
bool X86TargetLowering::isIntDivCheap(EVT VT, bool OptSize) const {
|
||||
bool X86TargetLowering::isIntDivCheap(EVT VT, AttributeSet Attr) const {
|
||||
// Integer division on x86 is expensive. However, when aggressively optimizing
|
||||
// for code size, we prefer to use a div instruction, as it is usually smaller
|
||||
// than the alternative sequence.
|
||||
@ -26519,5 +26519,7 @@ bool X86TargetLowering::isIntDivCheap(EVT VT, bool OptSize) const {
|
||||
// integer division, leaving the division as-is is a loss even in terms of
|
||||
// size, because it will have to be scalarized, while the alternative code
|
||||
// sequence can be performed in vector form.
|
||||
bool OptSize = Attr.hasAttribute(AttributeSet::FunctionIndex,
|
||||
Attribute::MinSize);
|
||||
return OptSize && !VT.isVector();
|
||||
}
|
||||
|
@ -902,7 +902,7 @@ namespace llvm {
|
||||
/// \brief Customize the preferred legalization strategy for certain types.
|
||||
LegalizeTypeAction getPreferredVectorAction(EVT VT) const override;
|
||||
|
||||
bool isIntDivCheap(EVT VT, bool OptSize) const override;
|
||||
bool isIntDivCheap(EVT VT, AttributeSet Attr) const override;
|
||||
|
||||
protected:
|
||||
std::pair<const TargetRegisterClass *, uint8_t>
|
||||
|
33
test/CodeGen/X86/sdiv-pow2.ll
Normal file
33
test/CodeGen/X86/sdiv-pow2.ll
Normal file
@ -0,0 +1,33 @@
|
||||
; RUN: llc -march=x86 < %s | FileCheck %s
|
||||
|
||||
; No attributes, should not use idiv
|
||||
define i32 @test1(i32 inreg %x) {
|
||||
entry:
|
||||
%div = sdiv i32 %x, 16
|
||||
ret i32 %div
|
||||
; CHECK-LABEL: test1:
|
||||
; CHECK-NOT: idivl
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
; Has minsize (-Oz) attribute, should generate idiv
|
||||
define i32 @test2(i32 inreg %x) minsize {
|
||||
entry:
|
||||
%div = sdiv i32 %x, 16
|
||||
ret i32 %div
|
||||
; CHECK-LABEL: test2:
|
||||
; CHECK: idivl
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
; Has optsize (-Os) attribute, should not generate idiv
|
||||
define i32 @test3(i32 inreg %x) optsize {
|
||||
entry:
|
||||
%div = sdiv i32 %x, 16
|
||||
ret i32 %div
|
||||
; CHECK-LABEL: test3:
|
||||
; CHECK-NOT: idivl
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user