Pass function attributes instead of boolean in isIntDivCheap().
authorSteve King <steve@metrokings.com>
Tue, 25 Aug 2015 02:31:21 +0000 (02:31 +0000)
committerSteve King <steve@metrokings.com>
Tue, 25 Aug 2015 02:31:21 +0000 (02:31 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@245921 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetLowering.h
lib/CodeGen/SelectionDAG/DAGCombiner.cpp
lib/CodeGen/SelectionDAG/TargetLowering.cpp
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86ISelLowering.h
test/CodeGen/X86/sdiv-pow2.ll [new file with mode: 0644]

index b43ff2294c938cca03b3682402497be48ed12e36..99e750e3de53a8934f97badb3ee718a33de785a2 100644 (file)
@@ -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
index bd02b1e156bc0dbf951459dda7e07b432de79afd..3275daf3ffdd56b3de910d256a46748813c1cb08 100644 (file)
@@ -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;
 
index ffffaf0fe6f927d2fbd25feee806615924303d09..88ace8f505173c7d7de9a1e793323fa4b38cb5e7 100644 (file)
@@ -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.
index 430ee22916c01f8f3a6d8b47810a2aa670269adc..ae40d6abcd5ac29400aeaa488223f9a048fa12a6 100644 (file)
@@ -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();
 }
index c0abf0beb0d736cec790a81e7e8e08f37b9c0ff0..026c4d0cbdac472814e022aabe96b8f18f47e44d 100644 (file)
@@ -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>
diff --git a/test/CodeGen/X86/sdiv-pow2.ll b/test/CodeGen/X86/sdiv-pow2.ll
new file mode 100644 (file)
index 0000000..e89f769
--- /dev/null
@@ -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
+}
+
+