[llvm-commits] [llvm] r124992 - in /llvm/trunk: docs/LangRef.html include/llvm/Bitcode/LLVMBitCodes.h include/llvm/Constants.h include/llvm/InstrTypes.h include/llvm/Operator.h lib/AsmParser/LLParser.cpp lib/Bitcode/Reader/BitcodeReader.cpp lib/Bitcode/Writer/BitcodeWriter.cpp lib/Transforms/InstCombine/InstCombineMulDivRem.cpp lib/VMCore/AsmWriter.cpp lib/VMCore/Constants.cpp lib/VMCore/Instructions.cpp test/Assembler/flags.ll test/Transforms/InstCombine/exact-sdiv.ll test/Transforms/InstCombine/exact.ll

Chris Lattner sabre at nondot.org
Sun Feb 6 13:44:57 PST 2011


Author: lattner
Date: Sun Feb  6 15:44:57 2011
New Revision: 124992

URL: http://llvm.org/viewvc/llvm-project?rev=124992&view=rev
Log:
enhance vmcore to know that udiv's can be exact, and add a trivial
instcombine xform to exercise this.

Nothing forms exact udivs yet though.  This is progress on PR8862


Added:
    llvm/trunk/test/Transforms/InstCombine/exact.ll
      - copied, changed from r124987, llvm/trunk/test/Transforms/InstCombine/exact-sdiv.ll
Removed:
    llvm/trunk/test/Transforms/InstCombine/exact-sdiv.ll
Modified:
    llvm/trunk/docs/LangRef.html
    llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
    llvm/trunk/include/llvm/Constants.h
    llvm/trunk/include/llvm/InstrTypes.h
    llvm/trunk/include/llvm/Operator.h
    llvm/trunk/lib/AsmParser/LLParser.cpp
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
    llvm/trunk/lib/VMCore/AsmWriter.cpp
    llvm/trunk/lib/VMCore/Constants.cpp
    llvm/trunk/lib/VMCore/Instructions.cpp
    llvm/trunk/test/Assembler/flags.ll

Modified: llvm/trunk/docs/LangRef.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=124992&r1=124991&r2=124992&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.html (original)
+++ llvm/trunk/docs/LangRef.html Sun Feb  6 15:44:57 2011
@@ -3441,7 +3441,8 @@
 
 <h5>Syntax:</h5>
 <pre>
-  <result> = udiv <ty> <op1>, <op2>   <i>; yields {ty}:result</i>
+  <result> = udiv <ty> <op1>, <op2>         <i>; yields {ty}:result</i>
+  <result> = udiv exact <ty> <op1>, <op2>   <i>; yields {ty}:result</i>
 </pre>
 
 <h5>Overview:</h5>
@@ -3460,6 +3461,11 @@
 
 <p>Division by zero leads to undefined behavior.</p>
 
+<p>If the <tt>exact</tt> keyword is present, the result value of the
+   <tt>udiv</tt> is a <a href="#trapvalues">trap value</a> if %op1 is not a
+  multiple of %op2 (as such, "((a udiv exact b) mul b) == a").</p>
+
+
 <h5>Example:</h5>
 <pre>
   <result> = udiv i32 4, %var          <i>; yields {i32}:result = 4 / %var</i>

Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=124992&r1=124991&r2=124992&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
+++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Sun Feb  6 15:44:57 2011
@@ -199,10 +199,10 @@
     OBO_NO_SIGNED_WRAP = 1
   };
 
-  /// SDivOperatorOptionalFlags - Flags for serializing SDivOperator's
-  /// SubclassOptionalData contents.
-  enum SDivOperatorOptionalFlags {
-    SDIV_EXACT = 0
+  /// PossiblyExactOperatorOptionalFlags - Flags for serializing 
+  /// PossiblyExactOperator's SubclassOptionalData contents.
+  enum PossiblyExactOperatorOptionalFlags {
+    PEO_EXACT = 0
   };
 
   // The function body block (FUNCTION_BLOCK_ID) describes function bodies.  It

Modified: llvm/trunk/include/llvm/Constants.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Constants.h?rev=124992&r1=124991&r2=124992&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Constants.h (original)
+++ llvm/trunk/include/llvm/Constants.h Sun Feb  6 15:44:57 2011
@@ -725,6 +725,7 @@
   static Constant *getNSWMul(Constant *C1, Constant *C2);
   static Constant *getNUWMul(Constant *C1, Constant *C2);
   static Constant *getExactSDiv(Constant *C1, Constant *C2);
+  static Constant *getExactUDiv(Constant *C1, Constant *C2);
 
   /// Transparently provide more efficient getOperand methods.
   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);

Modified: llvm/trunk/include/llvm/InstrTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InstrTypes.h?rev=124992&r1=124991&r2=124992&view=diff
==============================================================================
--- llvm/trunk/include/llvm/InstrTypes.h (original)
+++ llvm/trunk/include/llvm/InstrTypes.h Sun Feb  6 15:44:57 2011
@@ -341,7 +341,7 @@
     BO->setIsExact(true);
     return BO;
   }
-
+  
   /// Helper functions to construct and inspect unary operations (NEG and NOT)
   /// via binary operators SUB and XOR:
   ///

Modified: llvm/trunk/include/llvm/Operator.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Operator.h?rev=124992&r1=124991&r2=124992&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Operator.h (original)
+++ llvm/trunk/include/llvm/Operator.h Sun Feb  6 15:44:57 2011
@@ -173,30 +173,47 @@
   }
 };
 
-/// SDivOperator - An Operator with opcode Instruction::SDiv.
-///
-class SDivOperator : public Operator {
+/// PossiblyExactOperator - A udiv or sdiv instruction, which can be marked as
+/// "exact", indicating that no bits are destroyed.
+class PossiblyExactOperator : public Operator {
 public:
   enum {
     IsExact = (1 << 0)
   };
-
-private:
-  ~SDivOperator(); // do not implement
-
+  
   friend class BinaryOperator;
   friend class ConstantExpr;
   void setIsExact(bool B) {
     SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact);
   }
-
+  
+private:
+  ~PossiblyExactOperator(); // do not implement
 public:
   /// isExact - Test whether this division is known to be exact, with
   /// zero remainder.
   bool isExact() const {
     return SubclassOptionalData & IsExact;
   }
-
+  
+  static inline bool classof(const ConstantExpr *CE) {
+    return CE->getOpcode() == Instruction::SDiv ||
+           CE->getOpcode() == Instruction::UDiv;
+  }
+  static inline bool classof(const Instruction *I) {
+    return I->getOpcode() == Instruction::SDiv ||
+           I->getOpcode() == Instruction::UDiv;
+  }
+  static inline bool classof(const Value *V) {
+    return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
+    (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
+  }
+};
+  
+/// SDivOperator - An Operator with opcode Instruction::SDiv.
+///
+class SDivOperator : public PossiblyExactOperator {
+public:
   // Methods for support type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const SDivOperator *) { return true; }
   static inline bool classof(const ConstantExpr *CE) {
@@ -211,6 +228,24 @@
   }
 };
 
+/// UDivOperator - An Operator with opcode Instruction::SDiv.
+///
+class UDivOperator : public PossiblyExactOperator {
+public:
+  // Methods for support type inquiry through isa, cast, and dyn_cast:
+  static inline bool classof(const UDivOperator *) { return true; }
+  static inline bool classof(const ConstantExpr *CE) {
+    return CE->getOpcode() == Instruction::UDiv;
+  }
+  static inline bool classof(const Instruction *I) {
+    return I->getOpcode() == Instruction::UDiv;
+  }
+  static inline bool classof(const Value *V) {
+    return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
+    (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
+  }
+};
+  
 class GEPOperator : public Operator {
   enum {
     IsInBounds = (1 << 0)

Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=124992&r1=124991&r2=124992&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Sun Feb  6 15:44:57 2011
@@ -2304,7 +2304,7 @@
         if (EatIfPresent(lltok::kw_nuw))
           NUW = true;
       }
-    } else if (Opc == Instruction::SDiv) {
+    } else if (Opc == Instruction::SDiv || Opc == Instruction::UDiv) {
       if (EatIfPresent(lltok::kw_exact))
         Exact = true;
     }
@@ -2347,7 +2347,7 @@
     unsigned Flags = 0;
     if (NUW)   Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
     if (NSW)   Flags |= OverflowingBinaryOperator::NoSignedWrap;
-    if (Exact) Flags |= SDivOperator::IsExact;
+    if (Exact) Flags |= PossiblyExactOperator::IsExact;
     Constant *C = ConstantExpr::get(Opc, Val0, Val1, Flags);
     ID.ConstantVal = C;
     ID.Kind = ValID::t_Constant;
@@ -3032,7 +3032,8 @@
   case lltok::kw_fsub:
   case lltok::kw_fmul:    return ParseArithmetic(Inst, PFS, KeywordVal, 2);
 
-  case lltok::kw_sdiv: {
+  case lltok::kw_sdiv:
+  case lltok::kw_udiv: {
     bool Exact = false;
     if (EatIfPresent(lltok::kw_exact))
       Exact = true;
@@ -3043,7 +3044,6 @@
     return Result;
   }
 
-  case lltok::kw_udiv:
   case lltok::kw_urem:
   case lltok::kw_srem:   return ParseArithmetic(Inst, PFS, KeywordVal, 1);
   case lltok::kw_fdiv:

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=124992&r1=124991&r2=124992&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Sun Feb  6 15:44:57 2011
@@ -1090,8 +1090,9 @@
               Flags |= OverflowingBinaryOperator::NoSignedWrap;
             if (Record[3] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
               Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
-          } else if (Opc == Instruction::SDiv) {
-            if (Record[3] & (1 << bitc::SDIV_EXACT))
+          } else if (Opc == Instruction::SDiv ||
+                     Opc == Instruction::UDiv) {
+            if (Record[3] & (1 << bitc::PEO_EXACT))
               Flags |= SDivOperator::IsExact;
           }
         }
@@ -1905,8 +1906,9 @@
             cast<BinaryOperator>(I)->setHasNoSignedWrap(true);
           if (Record[OpNum] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
             cast<BinaryOperator>(I)->setHasNoUnsignedWrap(true);
-        } else if (Opc == Instruction::SDiv) {
-          if (Record[OpNum] & (1 << bitc::SDIV_EXACT))
+        } else if (Opc == Instruction::SDiv ||
+                   Opc == Instruction::UDiv) {
+          if (Record[OpNum] & (1 << bitc::PEO_EXACT))
             cast<BinaryOperator>(I)->setIsExact(true);
         }
       }

Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=124992&r1=124991&r2=124992&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Sun Feb  6 15:44:57 2011
@@ -470,9 +470,10 @@
       Flags |= 1 << bitc::OBO_NO_SIGNED_WRAP;
     if (OBO->hasNoUnsignedWrap())
       Flags |= 1 << bitc::OBO_NO_UNSIGNED_WRAP;
-  } else if (const SDivOperator *Div = dyn_cast<SDivOperator>(V)) {
-    if (Div->isExact())
-      Flags |= 1 << bitc::SDIV_EXACT;
+  } else if (const PossiblyExactOperator *PEO =
+               dyn_cast<PossiblyExactOperator>(V)) {
+    if (PEO->isExact())
+      Flags |= 1 << bitc::PEO_EXACT;
   }
 
   return Flags;

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp?rev=124992&r1=124991&r2=124992&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp Sun Feb  6 15:44:57 2011
@@ -135,8 +135,8 @@
          BO->getOpcode() == Instruction::SDiv)) {
       Value *Op0BO = BO->getOperand(0), *Op1BO = BO->getOperand(1);
 
-      // If the division is exact, X % Y is zero.
-      if (SDivOperator *SDiv = dyn_cast<SDivOperator>(BO))
+      // If the division is exact, X % Y is zero, so we end up with X or -X.
+      if (PossiblyExactOperator *SDiv = dyn_cast<PossiblyExactOperator>(BO))
         if (SDiv->isExact()) {
           if (Op1BO == Op1C)
             return ReplaceInstUsesWith(I, Op0BO);

Modified: llvm/trunk/lib/VMCore/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/AsmWriter.cpp?rev=124992&r1=124991&r2=124992&view=diff
==============================================================================
--- llvm/trunk/lib/VMCore/AsmWriter.cpp (original)
+++ llvm/trunk/lib/VMCore/AsmWriter.cpp Sun Feb  6 15:44:57 2011
@@ -831,7 +831,8 @@
       Out << " nuw";
     if (OBO->hasNoSignedWrap())
       Out << " nsw";
-  } else if (const SDivOperator *Div = dyn_cast<SDivOperator>(U)) {
+  } else if (const PossiblyExactOperator *Div =
+               dyn_cast<PossiblyExactOperator>(U)) {
     if (Div->isExact())
       Out << " exact";
   } else if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {

Modified: llvm/trunk/lib/VMCore/Constants.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Constants.cpp?rev=124992&r1=124991&r2=124992&view=diff
==============================================================================
--- llvm/trunk/lib/VMCore/Constants.cpp (original)
+++ llvm/trunk/lib/VMCore/Constants.cpp Sun Feb  6 15:44:57 2011
@@ -683,7 +683,12 @@
 
 Constant* ConstantExpr::getExactSDiv(Constant* C1, Constant* C2) {
   return getTy(C1->getType(), Instruction::SDiv, C1, C2,
-               SDivOperator::IsExact);
+               PossiblyExactOperator::IsExact);
+}
+
+Constant* ConstantExpr::getExactUDiv(Constant* C1, Constant* C2) {
+  return getTy(C1->getType(), Instruction::UDiv, C1, C2,
+               PossiblyExactOperator::IsExact);
 }
 
 // Utility function for determining if a ConstantExpr is a CastOp or not. This

Modified: llvm/trunk/lib/VMCore/Instructions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instructions.cpp?rev=124992&r1=124991&r2=124992&view=diff
==============================================================================
--- llvm/trunk/lib/VMCore/Instructions.cpp (original)
+++ llvm/trunk/lib/VMCore/Instructions.cpp Sun Feb  6 15:44:57 2011
@@ -1822,7 +1822,7 @@
 }
 
 void BinaryOperator::setIsExact(bool b) {
-  cast<SDivOperator>(this)->setIsExact(b);
+  cast<PossiblyExactOperator>(this)->setIsExact(b);
 }
 
 bool BinaryOperator::hasNoUnsignedWrap() const {
@@ -1834,7 +1834,7 @@
 }
 
 bool BinaryOperator::isExact() const {
-  return cast<SDivOperator>(this)->isExact();
+  return cast<PossiblyExactOperator>(this)->isExact();
 }
 
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/test/Assembler/flags.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/flags.ll?rev=124992&r1=124991&r2=124992&view=diff
==============================================================================
--- llvm/trunk/test/Assembler/flags.ll (original)
+++ llvm/trunk/test/Assembler/flags.ll Sun Feb  6 15:44:57 2011
@@ -104,6 +104,19 @@
 	ret i64 %z
 }
 
+define i64 @udiv_exact(i64 %x, i64 %y) {
+; CHECK: %z = udiv exact i64 %x, %y
+	%z = udiv exact i64 %x, %y
+	ret i64 %z
+}
+
+define i64 @udiv_plain(i64 %x, i64 %y) {
+; CHECK: %z = udiv i64 %x, %y
+	%z = udiv i64 %x, %y
+	ret i64 %z
+}
+
+
 define i64* @gep_nw(i64* %p, i64 %x) {
 ; CHECK: %z = getelementptr inbounds i64* %p, i64 %x
 	%z = getelementptr inbounds i64* %p, i64 %x
@@ -136,6 +149,11 @@
 	ret i64 sdiv exact (i64 ptrtoint (i64* @addr to i64), i64 91)
 }
 
+define i64 @udiv_exact_ce() {
+; CHECK: ret i64 udiv exact (i64 ptrtoint (i64* @addr to i64), i64 91)
+	ret i64 udiv exact (i64 ptrtoint (i64* @addr to i64), i64 91)
+}
+
 define i64* @gep_nw_ce() {
 ; CHECK: ret i64* getelementptr inbounds (i64* @addr, i64 171)
         ret i64* getelementptr inbounds (i64* @addr, i64 171)
@@ -210,3 +228,4 @@
 ; CHECK: ret i64 mul nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
 	ret i64 mul nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
 }
+

Removed: llvm/trunk/test/Transforms/InstCombine/exact-sdiv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/exact-sdiv.ll?rev=124991&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/exact-sdiv.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/exact-sdiv.ll (removed)
@@ -1,52 +0,0 @@
-; RUN: opt < %s -instcombine -S | FileCheck %s
-
-; CHECK: define i32 @foo
-; CHECK: sdiv i32 %x, 8
-define i32 @foo(i32 %x) {
-  %y = sdiv i32 %x, 8
-  ret i32 %y
-}
-
-; CHECK: define i32 @bar
-; CHECK: ashr i32 %x, 3
-define i32 @bar(i32 %x) {
-  %y = sdiv exact i32 %x, 8
-  ret i32 %y
-}
-
-; CHECK: i32 @a0
-; CHECK: %y = srem i32 %x, 3
-; CHECK: %z = sub i32 %x, %y
-; CHECK: ret i32 %z
-define i32 @a0(i32 %x) {
-  %y = sdiv i32 %x, 3
-  %z = mul i32 %y, 3
-  ret i32 %z
-}
-
-; CHECK: i32 @b0
-; CHECK: ret i32 %x
-define i32 @b0(i32 %x) {
-  %y = sdiv exact i32 %x, 3
-  %z = mul i32 %y, 3
-  ret i32 %z
-}
-
-; CHECK: i32 @a1
-; CHECK: %y = srem i32 %x, 3
-; CHECK: %z = sub i32 %y, %x
-; CHECK: ret i32 %z
-define i32 @a1(i32 %x) {
-  %y = sdiv i32 %x, 3
-  %z = mul i32 %y, -3
-  ret i32 %z
-}
-
-; CHECK: i32 @b1
-; CHECK: %z = sub i32 0, %x
-; CHECK: ret i32 %z
-define i32 @b1(i32 %x) {
-  %y = sdiv exact i32 %x, 3
-  %z = mul i32 %y, -3
-  ret i32 %z
-}

Copied: llvm/trunk/test/Transforms/InstCombine/exact.ll (from r124987, llvm/trunk/test/Transforms/InstCombine/exact-sdiv.ll)
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/exact.ll?p2=llvm/trunk/test/Transforms/InstCombine/exact.ll&p1=llvm/trunk/test/Transforms/InstCombine/exact-sdiv.ll&r1=124987&r2=124992&rev=124992&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/exact-sdiv.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/exact.ll Sun Feb  6 15:44:57 2011
@@ -50,3 +50,11 @@
   %z = mul i32 %y, -3
   ret i32 %z
 }
+
+; CHECK: i32 @b2
+; CHECK: ret i32 %x
+define i32 @b2(i32 %x, i32 %w) {
+  %y = udiv exact i32 %x, %w
+  %z = mul i32 %y, %w
+  ret i32 %z
+}





More information about the llvm-commits mailing list