From: Steve King Date: Tue, 25 Aug 2015 02:31:21 +0000 (+0000) Subject: Pass function attributes instead of boolean in isIntDivCheap(). X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=46ff6da86067575f805e745f5ac9f4d584f15b0a;p=oota-llvm.git 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 --- diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index b43ff2294c9..99e750e3de5 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -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 *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 *Created) const { - return SDValue(); - } + std::vector *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 diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index bd02b1e156b..3275daf3ffd 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -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(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; diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index ffffaf0fe6f..88ace8f5051 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -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 *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. diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 430ee22916c..ae40d6abcd5 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -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(); } diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index c0abf0beb0d..026c4d0cbda 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -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 diff --git a/test/CodeGen/X86/sdiv-pow2.ll b/test/CodeGen/X86/sdiv-pow2.ll new file mode 100644 index 00000000000..e89f76931e1 --- /dev/null +++ b/test/CodeGen/X86/sdiv-pow2.ll @@ -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 +} + +