implement .ll and .bc support for nsw/nuw on shl and exact on lshr/ashr.
authorChris Lattner <sabre@nondot.org>
Mon, 7 Feb 2011 16:40:21 +0000 (16:40 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 7 Feb 2011 16:40:21 +0000 (16:40 +0000)
Factor some code better.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125006 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LangRef.html
include/llvm/Constants.h
include/llvm/Operator.h
lib/AsmParser/LLParser.cpp
lib/Bitcode/Reader/BitcodeReader.cpp
lib/VMCore/Constants.cpp
test/Assembler/2003-05-21-MalformedShiftCrash.ll
test/Assembler/flags.ll

index f7997495e04ce87581d9e1708f15d94b6ae2b537..dbe385387af437380565d7e6d9f39eab48813ac9 100644 (file)
@@ -3684,7 +3684,10 @@ Instruction</a> </div>
 
 <h5>Syntax:</h5>
 <pre>
-  &lt;result&gt; = shl &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt;   <i>; yields {ty}:result</i>
+  &lt;result&gt; = shl &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt;           <i>; yields {ty}:result</i>
+  &lt;result&gt; = shl nuw &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt;       <i>; yields {ty}:result</i>
+  &lt;result&gt; = shl nsw &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt;       <i>; yields {ty}:result</i>
+  &lt;result&gt; = shl nuw nsw &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt;   <i>; yields {ty}:result</i>
 </pre>
 
 <h5>Overview:</h5>
@@ -3704,6 +3707,14 @@ Instruction</a> </div>
    vectors, each vector element of <tt>op1</tt> is shifted by the corresponding
    shift amount in <tt>op2</tt>.</p>
 
+<p>If the <tt>nuw</tt> keyword is present, then the shift produces a 
+   <a href="#trapvalues">trap value</a> if it shifts out any non-zero bits.  If
+   the <tt>nsw</tt> keywrod is present, then the shift produces a
+   <a href="#trapvalues">trap value</a> if it shifts out any bits that disagree
+   with the resultant sign bit.  As such, NUW/NSW have the same semantics as
+   they would if the shift were expressed as a mul instruction with the same
+   nsw/nuw bits in (mul %op1, (shl 1, %op2)).</p>
+
 <h5>Example:</h5>
 <pre>
   &lt;result&gt; = shl i32 4, %var   <i>; yields {i32}: 4 &lt;&lt; %var</i>
@@ -3723,7 +3734,8 @@ Instruction</a> </div>
 
 <h5>Syntax:</h5>
 <pre>
-  &lt;result&gt; = lshr &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt;   <i>; yields {ty}:result</i>
+  &lt;result&gt; = lshr &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt;         <i>; yields {ty}:result</i>
+  &lt;result&gt; = lshr exact &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt;   <i>; yields {ty}:result</i>
 </pre>
 
 <h5>Overview:</h5>
@@ -3743,6 +3755,11 @@ Instruction</a> </div>
    vectors, each vector element of <tt>op1</tt> is shifted by the corresponding
    shift amount in <tt>op2</tt>.</p>
 
+<p>If the <tt>exact</tt> keyword is present, the result value of the
+   <tt>lshr</tt> is a <a href="#trapvalues">trap value</a> if any of the bits
+   shifted out are non-zero.</p>
+
+
 <h5>Example:</h5>
 <pre>
   &lt;result&gt; = lshr i32 4, 1   <i>; yields {i32}:result = 2</i>
@@ -3762,7 +3779,8 @@ Instruction</a> </div>
 
 <h5>Syntax:</h5>
 <pre>
-  &lt;result&gt; = ashr &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt;   <i>; yields {ty}:result</i>
+  &lt;result&gt; = ashr &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt;         <i>; yields {ty}:result</i>
+  &lt;result&gt; = ashr exact &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt;   <i>; yields {ty}:result</i>
 </pre>
 
 <h5>Overview:</h5>
@@ -3783,6 +3801,10 @@ Instruction</a> </div>
    the arguments are vectors, each vector element of <tt>op1</tt> is shifted by
    the corresponding shift amount in <tt>op2</tt>.</p>
 
+<p>If the <tt>exact</tt> keyword is present, the result value of the
+   <tt>ashr</tt> is a <a href="#trapvalues">trap value</a> if any of the bits
+   shifted out are non-zero.</p>
+
 <h5>Example:</h5>
 <pre>
   &lt;result&gt; = ashr i32 4, 1   <i>; yields {i32}:result = 2</i>
index b782737d31a04d914cfcb93e6829366d94ee458d..56f39b9b09208fbd11ad154fd7d407b3a24f47ca 100644 (file)
@@ -724,8 +724,12 @@ public:
   static Constant *getNUWSub(Constant *C1, Constant *C2);
   static Constant *getNSWMul(Constant *C1, Constant *C2);
   static Constant *getNUWMul(Constant *C1, Constant *C2);
+  static Constant *getNSWShl(Constant *C1, Constant *C2);
+  static Constant *getNUWShl(Constant *C1, Constant *C2);
   static Constant *getExactSDiv(Constant *C1, Constant *C2);
   static Constant *getExactUDiv(Constant *C1, Constant *C2);
+  static Constant *getExactAShr(Constant *C1, Constant *C2);
+  static Constant *getExactLShr(Constant *C1, Constant *C2);
 
   /// Transparently provide more efficient getOperand methods.
   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
index eaa28ad47fa21d4bf957e9bd921405996eccab44..ff2a0ad5e4e9893d807a0e01bfd97990988008a6 100644 (file)
@@ -106,66 +106,14 @@ public:
   static inline bool classof(const Instruction *I) {
     return I->getOpcode() == Instruction::Add ||
            I->getOpcode() == Instruction::Sub ||
-           I->getOpcode() == Instruction::Mul;
+           I->getOpcode() == Instruction::Mul ||
+           I->getOpcode() == Instruction::Shl;
   }
   static inline bool classof(const ConstantExpr *CE) {
     return CE->getOpcode() == Instruction::Add ||
            CE->getOpcode() == Instruction::Sub ||
-           CE->getOpcode() == Instruction::Mul;
-  }
-  static inline bool classof(const Value *V) {
-    return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
-           (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
-  }
-};
-
-/// AddOperator - Utility class for integer addition operators.
-///
-class AddOperator : public OverflowingBinaryOperator {
-  ~AddOperator(); // do not implement
-public:
-  static inline bool classof(const AddOperator *) { return true; }
-  static inline bool classof(const Instruction *I) {
-    return I->getOpcode() == Instruction::Add;
-  }
-  static inline bool classof(const ConstantExpr *CE) {
-    return CE->getOpcode() == Instruction::Add;
-  }
-  static inline bool classof(const Value *V) {
-    return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
-           (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
-  }
-};
-
-/// SubOperator - Utility class for integer subtraction operators.
-///
-class SubOperator : public OverflowingBinaryOperator {
-  ~SubOperator(); // do not implement
-public:
-  static inline bool classof(const SubOperator *) { return true; }
-  static inline bool classof(const Instruction *I) {
-    return I->getOpcode() == Instruction::Sub;
-  }
-  static inline bool classof(const ConstantExpr *CE) {
-    return CE->getOpcode() == Instruction::Sub;
-  }
-  static inline bool classof(const Value *V) {
-    return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
-           (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
-  }
-};
-
-/// MulOperator - Utility class for integer multiplication operators.
-///
-class MulOperator : public OverflowingBinaryOperator {
-  ~MulOperator(); // do not implement
-public:
-  static inline bool classof(const MulOperator *) { return true; }
-  static inline bool classof(const Instruction *I) {
-    return I->getOpcode() == Instruction::Mul;
-  }
-  static inline bool classof(const ConstantExpr *CE) {
-    return CE->getOpcode() == Instruction::Mul;
+           CE->getOpcode() == Instruction::Mul ||
+           CE->getOpcode() == Instruction::Shl;
   }
   static inline bool classof(const Value *V) {
     return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
@@ -196,63 +144,74 @@ public:
     return SubclassOptionalData & IsExact;
   }
   
-  static inline bool classof(const ConstantExpr *CE) {
-    return CE->getOpcode() == Instruction::SDiv ||
-           CE->getOpcode() == Instruction::UDiv;
+  static bool isPossiblyExactOpcode(unsigned OpC) {
+    return OpC == Instruction::SDiv ||
+           OpC == Instruction::UDiv ||
+           OpC == Instruction::AShr ||
+           OpC == Instruction::LShr;
   }
-  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) {
-    return CE->getOpcode() == Instruction::SDiv;
+    return isPossiblyExactOpcode(CE->getOpcode());
   }
   static inline bool classof(const Instruction *I) {
-    return I->getOpcode() == Instruction::SDiv;
+    return isPossiblyExactOpcode(I->getOpcode());
   }
   static inline bool classof(const Value *V) {
     return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
            (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
   }
 };
+  
 
-/// UDivOperator - An Operator with opcode Instruction::UDiv.
-///
-class UDivOperator : public PossiblyExactOperator {
+  
+/// ConcreteOperator - A helper template for defining operators for individual
+/// opcodes.
+template<typename SuperClass, unsigned Opc>
+class ConcreteOperator : public SuperClass {
+  ~ConcreteOperator(); // DO NOT IMPLEMENT
 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 ConcreteOperator<SuperClass, Opc> *) {
+    return true;
   }
   static inline bool classof(const Instruction *I) {
-    return I->getOpcode() == Instruction::UDiv;
+    return I->getOpcode() == Opc;
+  }
+  static inline bool classof(const ConstantExpr *CE) {
+    return CE->getOpcode() == Opc;
   }
   static inline bool classof(const Value *V) {
     return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
-    (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
+           (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
   }
 };
+
+class AddOperator
+  : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> {};
+class SubOperator
+  : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> {};
+class MulOperator
+  : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> {};
+class ShlOperator
+  : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> {};
+
+  
+class SDivOperator
+  : public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> {};
+class UDivOperator
+  : public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> {};
+class AShrOperator
+  : public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> {};
+class LShrOperator
+  : public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> {};
+  
   
-class GEPOperator : public Operator {
+  
+class GEPOperator
+  : public ConcreteOperator<Operator, Instruction::GetElementPtr> {
   enum {
     IsInBounds = (1 << 0)
   };
 
-  ~GEPOperator(); // do not implement
-
   friend class GetElementPtrInst;
   friend class ConstantExpr;
   void setIsInBounds(bool B) {
@@ -301,8 +260,8 @@ public:
   /// value, just potentially different types.
   bool hasAllZeroIndices() const {
     for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) {
-      if (Constant *C = dyn_cast<Constant>(I))
-        if (C->isNullValue())
+      if (ConstantInt *C = dyn_cast<ConstantInt>(I))
+        if (C->isZero())
           continue;
       return false;
     }
@@ -319,21 +278,6 @@ public:
     }
     return true;
   }
-  
-
-  // Methods for support type inquiry through isa, cast, and dyn_cast:
-  static inline bool classof(const GEPOperator *) { return true; }
-  static inline bool classof(const GetElementPtrInst *) { return true; }
-  static inline bool classof(const ConstantExpr *CE) {
-    return CE->getOpcode() == Instruction::GetElementPtr;
-  }
-  static inline bool classof(const Instruction *I) {
-    return I->getOpcode() == Instruction::GetElementPtr;
-  }
-  static inline bool classof(const Value *V) {
-    return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
-           (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
-  }
 };
 
 } // End llvm namespace
index 6d71c9e3e60fcf29fe11d5c0dd9462109e2a3276..cb4ddcba72ad73a951155d2747f7a31a8f3e72f6 100644 (file)
@@ -2286,7 +2286,10 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
   case lltok::kw_fdiv:
   case lltok::kw_urem:
   case lltok::kw_srem:
-  case lltok::kw_frem: {
+  case lltok::kw_frem:
+  case lltok::kw_shl:
+  case lltok::kw_lshr:
+  case lltok::kw_ashr: {
     bool NUW = false;
     bool NSW = false;
     bool Exact = false;
@@ -2294,9 +2297,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
     Constant *Val0, *Val1;
     Lex.Lex();
     LocTy ModifierLoc = Lex.getLoc();
-    if (Opc == Instruction::Add ||
-        Opc == Instruction::Sub ||
-        Opc == Instruction::Mul) {
+    if (Opc == Instruction::Add || Opc == Instruction::Sub ||
+        Opc == Instruction::Mul || Opc == Instruction::Shl) {
       if (EatIfPresent(lltok::kw_nuw))
         NUW = true;
       if (EatIfPresent(lltok::kw_nsw)) {
@@ -2304,7 +2306,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
         if (EatIfPresent(lltok::kw_nuw))
           NUW = true;
       }
-    } else if (Opc == Instruction::SDiv || Opc == Instruction::UDiv) {
+    } else if (Opc == Instruction::SDiv || Opc == Instruction::UDiv ||
+               Opc == Instruction::LShr || Opc == Instruction::AShr) {
       if (EatIfPresent(lltok::kw_exact))
         Exact = true;
     }
@@ -2331,6 +2334,9 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
     case Instruction::SDiv:
     case Instruction::URem:
     case Instruction::SRem:
+    case Instruction::Shl:
+    case Instruction::AShr:
+    case Instruction::LShr:
       if (!Val0->getType()->isIntOrIntVectorTy())
         return Error(ID.Loc, "constexpr requires integer operands");
       break;
@@ -2355,9 +2361,6 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
   }
 
   // Logical Operations
-  case lltok::kw_shl:
-  case lltok::kw_lshr:
-  case lltok::kw_ashr:
   case lltok::kw_and:
   case lltok::kw_or:
   case lltok::kw_xor: {
@@ -3002,55 +3005,38 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
   // Binary Operators.
   case lltok::kw_add:
   case lltok::kw_sub:
-  case lltok::kw_mul: {
-    bool NUW = false;
-    bool NSW = false;
+  case lltok::kw_mul:
+  case lltok::kw_shl: {
     LocTy ModifierLoc = Lex.getLoc();
-    if (EatIfPresent(lltok::kw_nuw))
-      NUW = true;
-    if (EatIfPresent(lltok::kw_nsw)) {
-      NSW = true;
-      if (EatIfPresent(lltok::kw_nuw))
-        NUW = true;
-    }
-    bool Result = ParseArithmetic(Inst, PFS, KeywordVal, 1);
-    if (!Result) {
-      if (!Inst->getType()->isIntOrIntVectorTy()) {
-        if (NUW)
-          return Error(ModifierLoc, "nuw only applies to integer operations");
-        if (NSW)
-          return Error(ModifierLoc, "nsw only applies to integer operations");
-      }
-      if (NUW)
-        cast<BinaryOperator>(Inst)->setHasNoUnsignedWrap(true);
-      if (NSW)
-        cast<BinaryOperator>(Inst)->setHasNoSignedWrap(true);
-    }
-    return Result;
+    bool NUW = EatIfPresent(lltok::kw_nuw);
+    bool NSW = EatIfPresent(lltok::kw_nsw);
+    if (!NUW) NUW = EatIfPresent(lltok::kw_nuw);
+    
+    if (ParseArithmetic(Inst, PFS, KeywordVal, 1)) return true;
+    
+    if (NUW) cast<BinaryOperator>(Inst)->setHasNoUnsignedWrap(true);
+    if (NSW) cast<BinaryOperator>(Inst)->setHasNoSignedWrap(true);
+    return false;
   }
   case lltok::kw_fadd:
   case lltok::kw_fsub:
   case lltok::kw_fmul:    return ParseArithmetic(Inst, PFS, KeywordVal, 2);
 
   case lltok::kw_sdiv:
-  case lltok::kw_udiv: {
-    bool Exact = false;
-    if (EatIfPresent(lltok::kw_exact))
-      Exact = true;
-    bool Result = ParseArithmetic(Inst, PFS, KeywordVal, 1);
-    if (!Result)
-      if (Exact)
-        cast<BinaryOperator>(Inst)->setIsExact(true);
-    return Result;
+  case lltok::kw_udiv:
+  case lltok::kw_lshr:
+  case lltok::kw_ashr: {
+    bool Exact = EatIfPresent(lltok::kw_exact);
+
+    if (ParseArithmetic(Inst, PFS, KeywordVal, 1)) return true;
+    if (Exact) cast<BinaryOperator>(Inst)->setIsExact(true);
+    return false;
   }
 
   case lltok::kw_urem:
   case lltok::kw_srem:   return ParseArithmetic(Inst, PFS, KeywordVal, 1);
   case lltok::kw_fdiv:
   case lltok::kw_frem:   return ParseArithmetic(Inst, PFS, KeywordVal, 2);
-  case lltok::kw_shl:
-  case lltok::kw_lshr:
-  case lltok::kw_ashr:
   case lltok::kw_and:
   case lltok::kw_or:
   case lltok::kw_xor:    return ParseLogical(Inst, PFS, KeywordVal);
index a744d833026674ce8e580306762c51807dde17cc..d812a6d465cd0ca5d1c8c4bda28d3c70b5ceb46c 100644 (file)
@@ -1085,13 +1085,16 @@ bool BitcodeReader::ParseConstants() {
         if (Record.size() >= 4) {
           if (Opc == Instruction::Add ||
               Opc == Instruction::Sub ||
-              Opc == Instruction::Mul) {
+              Opc == Instruction::Mul ||
+              Opc == Instruction::Shl) {
             if (Record[3] & (1 << bitc::OBO_NO_SIGNED_WRAP))
               Flags |= OverflowingBinaryOperator::NoSignedWrap;
             if (Record[3] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
               Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
           } else if (Opc == Instruction::SDiv ||
-                     Opc == Instruction::UDiv) {
+                     Opc == Instruction::UDiv ||
+                     Opc == Instruction::LShr ||
+                     Opc == Instruction::AShr) {
             if (Record[3] & (1 << bitc::PEO_EXACT))
               Flags |= SDivOperator::IsExact;
           }
@@ -1901,13 +1904,16 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
       if (OpNum < Record.size()) {
         if (Opc == Instruction::Add ||
             Opc == Instruction::Sub ||
-            Opc == Instruction::Mul) {
+            Opc == Instruction::Mul ||
+            Opc == Instruction::Shl) {
           if (Record[OpNum] & (1 << bitc::OBO_NO_SIGNED_WRAP))
             cast<BinaryOperator>(I)->setHasNoSignedWrap(true);
           if (Record[OpNum] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
             cast<BinaryOperator>(I)->setHasNoUnsignedWrap(true);
         } else if (Opc == Instruction::SDiv ||
-                   Opc == Instruction::UDiv) {
+                   Opc == Instruction::UDiv ||
+                   Opc == Instruction::LShr ||
+                   Opc == Instruction::AShr) {
           if (Record[OpNum] & (1 << bitc::PEO_EXACT))
             cast<BinaryOperator>(I)->setIsExact(true);
         }
index d2359e5bcda48ee5309ce339443f752918595d74..b9b7b3f5393660fedb516a6608353a007b86b752 100644 (file)
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements the Constantclasses.
+// This file implements the Constant *classes.
 //
 //===----------------------------------------------------------------------===//
 
@@ -72,7 +72,7 @@ Constant *Constant::getNullValue(const Type *Ty) {
   }
 }
 
-ConstantConstant::getIntegerValue(const Type *Ty, const APInt &V) {
+Constant *Constant::getIntegerValue(const Type *Ty, const APInt &V) {
   const Type *ScalarTy = Ty->getScalarType();
 
   // Create the base integer constant.
@@ -89,7 +89,7 @@ Constant* Constant::getIntegerValue(const Type *Ty, const APInt &V) {
   return C;
 }
 
-ConstantConstant::getAllOnesValue(const Type *Ty) {
+Constant *Constant::getAllOnesValue(const Type *Ty) {
   if (const IntegerType *ITy = dyn_cast<IntegerType>(Ty))
     return ConstantInt::get(Ty->getContext(),
                             APInt::getAllOnesValue(ITy->getBitWidth()));
@@ -296,7 +296,7 @@ ConstantInt *ConstantInt::get(LLVMContext &Context, const APInt& V) {
   return Slot;
 }
 
-ConstantConstantInt::get(const Type* Ty, uint64_t V, bool isSigned) {
+Constant *ConstantInt::get(const Type* Ty, uint64_t V, bool isSigned) {
   Constant *C = get(cast<IntegerType>(Ty->getScalarType()),
                                V, isSigned);
 
@@ -321,7 +321,7 @@ Constant *ConstantInt::getSigned(const Type *Ty, int64_t V) {
   return get(Ty, V, true);
 }
 
-ConstantConstantInt::get(const Type* Ty, const APInt& V) {
+Constant *ConstantInt::get(const Type* Ty, const APInt& V) {
   ConstantInt *C = get(Ty->getContext(), V);
   assert(C->getType() == Ty->getScalarType() &&
          "ConstantInt type doesn't match the type implied by its value!");
@@ -360,7 +360,7 @@ static const fltSemantics *TypeToFloatSemantics(const Type *Ty) {
 /// get() - This returns a constant fp for the specified value in the
 /// specified type.  This should only be used for simple constant values like
 /// 2.0/1.0 etc, that are known-valid both as double and as the target format.
-ConstantConstantFP::get(const Type* Ty, double V) {
+Constant *ConstantFP::get(const Type* Ty, double V) {
   LLVMContext &Context = Ty->getContext();
   
   APFloat FV(V);
@@ -378,7 +378,7 @@ Constant* ConstantFP::get(const Type* Ty, double V) {
 }
 
 
-ConstantConstantFP::get(const Type* Ty, StringRef Str) {
+Constant *ConstantFP::get(const Type* Ty, StringRef Str) {
   LLVMContext &Context = Ty->getContext();
 
   APFloat FV(*TypeToFloatSemantics(Ty->getScalarType()), Str);
@@ -401,7 +401,7 @@ ConstantFP* ConstantFP::getNegativeZero(const Type* Ty) {
 }
 
 
-ConstantConstantFP::getZeroValueForNegation(const Type* Ty) {
+Constant *ConstantFP::getZeroValueForNegation(const Type* Ty) {
   if (const VectorType *PTy = dyn_cast<VectorType>(Ty))
     if (PTy->getElementType()->isFloatingPointTy()) {
       std::vector<Constant*> zeros(PTy->getNumElements(),
@@ -509,7 +509,7 @@ Constant *ConstantArray::get(const ArrayType *Ty,
 }
 
 
-Constant* ConstantArray::get(const ArrayType* T, Constant* const* Vals,
+Constant *ConstantArray::get(const ArrayType* T, Constant *const* Vals,
                              unsigned NumVals) {
   // FIXME: make this the primary ctor method.
   return get(T, std::vector<Constant*>(Vals, Vals+NumVals));
@@ -521,7 +521,7 @@ Constant* ConstantArray::get(const ArrayType* T, Constant* const* Vals,
 /// Otherwise, the length parameter specifies how much of the string to use 
 /// and it won't be null terminated.
 ///
-ConstantConstantArray::get(LLVMContext &Context, StringRef Str,
+Constant *ConstantArray::get(LLVMContext &Context, StringRef Str,
                              bool AddNull) {
   std::vector<Constant*> ElementVals;
   ElementVals.reserve(Str.size() + size_t(AddNull));
@@ -557,7 +557,7 @@ ConstantStruct::ConstantStruct(const StructType *T,
 }
 
 // ConstantStruct accessors.
-ConstantConstantStruct::get(const StructType* T,
+Constant *ConstantStruct::get(const StructType* T,
                               const std::vector<Constant*>& V) {
   LLVMContextImpl* pImpl = T->getContext().pImpl;
   
@@ -569,7 +569,7 @@ Constant* ConstantStruct::get(const StructType* T,
   return ConstantAggregateZero::get(T);
 }
 
-ConstantConstantStruct::get(LLVMContext &Context,
+Constant *ConstantStruct::get(LLVMContext &Context,
                               const std::vector<Constant*>& V, bool packed) {
   std::vector<const Type*> StructEls;
   StructEls.reserve(V.size());
@@ -578,8 +578,8 @@ Constant* ConstantStruct::get(LLVMContext &Context,
   return get(StructType::get(Context, StructEls, packed), V);
 }
 
-ConstantConstantStruct::get(LLVMContext &Context,
-                              Constantconst *Vals, unsigned NumVals,
+Constant *ConstantStruct::get(LLVMContext &Context,
+                              Constant *const *Vals, unsigned NumVals,
                               bool Packed) {
   // FIXME: make this the primary ctor method.
   return get(Context, std::vector<Constant*>(Vals, Vals+NumVals), Packed);
@@ -601,7 +601,7 @@ ConstantVector::ConstantVector(const VectorType *T,
 }
 
 // ConstantVector accessors.
-ConstantConstantVector::get(const VectorType* T,
+Constant *ConstantVector::get(const VectorType* T,
                               const std::vector<Constant*>& V) {
   assert(!V.empty() && "Vectors can't be empty");
   LLVMContext &Context = T->getContext();
@@ -629,68 +629,89 @@ Constant* ConstantVector::get(const VectorType* T,
   return pImpl->VectorConstants.getOrCreate(T, V);
 }
 
-ConstantConstantVector::get(const std::vector<Constant*>& V) {
+Constant *ConstantVector::get(const std::vector<Constant*>& V) {
   assert(!V.empty() && "Cannot infer type if V is empty");
   return get(VectorType::get(V.front()->getType(),V.size()), V);
 }
 
-Constant* ConstantVector::get(Constant* const* Vals, unsigned NumVals) {
+Constant *ConstantVector::get(Constant *const* Vals, unsigned NumVals) {
   // FIXME: make this the primary ctor method.
   return get(std::vector<Constant*>(Vals, Vals+NumVals));
 }
 
-Constant* ConstantExpr::getNSWNeg(Constant* C) {
+Constant *ConstantExpr::getNSWNeg(Constant *C) {
   assert(C->getType()->isIntOrIntVectorTy() &&
          "Cannot NEG a nonintegral value!");
   return getNSWSub(ConstantFP::getZeroValueForNegation(C->getType()), C);
 }
 
-Constant* ConstantExpr::getNUWNeg(Constant* C) {
+Constant *ConstantExpr::getNUWNeg(Constant *C) {
   assert(C->getType()->isIntOrIntVectorTy() &&
          "Cannot NEG a nonintegral value!");
   return getNUWSub(ConstantFP::getZeroValueForNegation(C->getType()), C);
 }
 
-Constant* ConstantExpr::getNSWAdd(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getNSWAdd(Constant *C1, Constant *C2) {
   return getTy(C1->getType(), Instruction::Add, C1, C2,
                OverflowingBinaryOperator::NoSignedWrap);
 }
 
-Constant* ConstantExpr::getNUWAdd(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getNUWAdd(Constant *C1, Constant *C2) {
   return getTy(C1->getType(), Instruction::Add, C1, C2,
                OverflowingBinaryOperator::NoUnsignedWrap);
 }
 
-Constant* ConstantExpr::getNSWSub(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getNSWSub(Constant *C1, Constant *C2) {
   return getTy(C1->getType(), Instruction::Sub, C1, C2,
                OverflowingBinaryOperator::NoSignedWrap);
 }
 
-Constant* ConstantExpr::getNUWSub(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getNUWSub(Constant *C1, Constant *C2) {
   return getTy(C1->getType(), Instruction::Sub, C1, C2,
                OverflowingBinaryOperator::NoUnsignedWrap);
 }
 
-Constant* ConstantExpr::getNSWMul(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getNSWMul(Constant *C1, Constant *C2) {
   return getTy(C1->getType(), Instruction::Mul, C1, C2,
                OverflowingBinaryOperator::NoSignedWrap);
 }
 
-Constant* ConstantExpr::getNUWMul(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getNUWMul(Constant *C1, Constant *C2) {
   return getTy(C1->getType(), Instruction::Mul, C1, C2,
                OverflowingBinaryOperator::NoUnsignedWrap);
 }
 
-Constant* ConstantExpr::getExactSDiv(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getNSWShl(Constant *C1, Constant *C2) {
+  return getTy(C1->getType(), Instruction::Shl, C1, C2,
+               OverflowingBinaryOperator::NoSignedWrap);
+}
+
+Constant *ConstantExpr::getNUWShl(Constant *C1, Constant *C2) {
+  return getTy(C1->getType(), Instruction::Shl, C1, C2,
+               OverflowingBinaryOperator::NoUnsignedWrap);
+}
+
+Constant *ConstantExpr::getExactSDiv(Constant *C1, Constant *C2) {
   return getTy(C1->getType(), Instruction::SDiv, C1, C2,
                PossiblyExactOperator::IsExact);
 }
 
-Constant* ConstantExpr::getExactUDiv(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getExactUDiv(Constant *C1, Constant *C2) {
   return getTy(C1->getType(), Instruction::UDiv, C1, C2,
                PossiblyExactOperator::IsExact);
 }
 
+Constant *ConstantExpr::getExactAShr(Constant *C1, Constant *C2) {
+  return getTy(C1->getType(), Instruction::AShr, C1, C2,
+               PossiblyExactOperator::IsExact);
+}
+
+Constant *ConstantExpr::getExactLShr(Constant *C1, Constant *C2) {
+  return getTy(C1->getType(), Instruction::LShr, C1, C2,
+               PossiblyExactOperator::IsExact);
+}
+
+
 // Utility function for determining if a ConstantExpr is a CastOp or not. This
 // can't be inline because we don't want to #include Instruction.h into
 // Constant.h
@@ -816,7 +837,7 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const {
 /// operands replaced with the specified values.  The specified operands must
 /// match count and type with the existing ones.
 Constant *ConstantExpr::
-getWithOperands(Constantconst *Ops, unsigned NumOps) const {
+getWithOperands(Constant *const *Ops, unsigned NumOps) const {
   assert(NumOps == getNumOperands() && "Operand count mismatch!");
   bool AnyChange = false;
   for (unsigned i = 0; i != NumOps; ++i) {
@@ -1486,7 +1507,7 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
   return getTy(C1->getType(), Opcode, C1, C2, Flags);
 }
 
-ConstantConstantExpr::getSizeOf(const Type* Ty) {
+Constant *ConstantExpr::getSizeOf(const Type* Ty) {
   // sizeof is implemented as: (i64) gep (Ty*)null, 1
   // Note that a non-inbounds gep is used, as null isn't within any object.
   Constant *GEPIdx = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 1);
@@ -1496,7 +1517,7 @@ Constant* ConstantExpr::getSizeOf(const Type* Ty) {
                      Type::getInt64Ty(Ty->getContext()));
 }
 
-ConstantConstantExpr::getAlignOf(const Type* Ty) {
+Constant *ConstantExpr::getAlignOf(const Type* Ty) {
   // alignof is implemented as: (i64) gep ({i1,Ty}*)null, 0, 1
   // Note that a non-inbounds gep is used, as null isn't within any object.
   const Type *AligningTy = StructType::get(Ty->getContext(),
@@ -1510,12 +1531,12 @@ Constant* ConstantExpr::getAlignOf(const Type* Ty) {
                      Type::getInt64Ty(Ty->getContext()));
 }
 
-ConstantConstantExpr::getOffsetOf(const StructType* STy, unsigned FieldNo) {
+Constant *ConstantExpr::getOffsetOf(const StructType* STy, unsigned FieldNo) {
   return getOffsetOf(STy, ConstantInt::get(Type::getInt32Ty(STy->getContext()),
                                            FieldNo));
 }
 
-ConstantConstantExpr::getOffsetOf(const Type* Ty, Constant *FieldNo) {
+Constant *ConstantExpr::getOffsetOf(const Type* Ty, Constant *FieldNo) {
   // offsetof is implemented as: (i64) gep (Ty*)null, 0, FieldNo
   // Note that a non-inbounds gep is used, as null isn't within any object.
   Constant *GEPIdx[] = {
@@ -1823,7 +1844,7 @@ Constant *ConstantExpr::getExtractValue(Constant *Agg,
   return getExtractValueTy(ReqTy, Agg, IdxList, NumIdx);
 }
 
-Constant* ConstantExpr::getNeg(Constant* C) {
+Constant *ConstantExpr::getNeg(Constant *C) {
   assert(C->getType()->isIntOrIntVectorTy() &&
          "Cannot NEG a nonintegral value!");
   return get(Instruction::Sub,
@@ -1831,7 +1852,7 @@ Constant* ConstantExpr::getNeg(Constant* C) {
              C);
 }
 
-Constant* ConstantExpr::getFNeg(Constant* C) {
+Constant *ConstantExpr::getFNeg(Constant *C) {
   assert(C->getType()->isFPOrFPVectorTy() &&
          "Cannot FNEG a non-floating-point value!");
   return get(Instruction::FSub,
@@ -1839,81 +1860,81 @@ Constant* ConstantExpr::getFNeg(Constant* C) {
              C);
 }
 
-Constant* ConstantExpr::getNot(Constant* C) {
+Constant *ConstantExpr::getNot(Constant *C) {
   assert(C->getType()->isIntOrIntVectorTy() &&
          "Cannot NOT a nonintegral value!");
   return get(Instruction::Xor, C, Constant::getAllOnesValue(C->getType()));
 }
 
-Constant* ConstantExpr::getAdd(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getAdd(Constant *C1, Constant *C2) {
   return get(Instruction::Add, C1, C2);
 }
 
-Constant* ConstantExpr::getFAdd(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getFAdd(Constant *C1, Constant *C2) {
   return get(Instruction::FAdd, C1, C2);
 }
 
-Constant* ConstantExpr::getSub(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getSub(Constant *C1, Constant *C2) {
   return get(Instruction::Sub, C1, C2);
 }
 
-Constant* ConstantExpr::getFSub(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getFSub(Constant *C1, Constant *C2) {
   return get(Instruction::FSub, C1, C2);
 }
 
-Constant* ConstantExpr::getMul(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getMul(Constant *C1, Constant *C2) {
   return get(Instruction::Mul, C1, C2);
 }
 
-Constant* ConstantExpr::getFMul(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getFMul(Constant *C1, Constant *C2) {
   return get(Instruction::FMul, C1, C2);
 }
 
-Constant* ConstantExpr::getUDiv(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getUDiv(Constant *C1, Constant *C2) {
   return get(Instruction::UDiv, C1, C2);
 }
 
-Constant* ConstantExpr::getSDiv(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getSDiv(Constant *C1, Constant *C2) {
   return get(Instruction::SDiv, C1, C2);
 }
 
-Constant* ConstantExpr::getFDiv(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getFDiv(Constant *C1, Constant *C2) {
   return get(Instruction::FDiv, C1, C2);
 }
 
-Constant* ConstantExpr::getURem(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getURem(Constant *C1, Constant *C2) {
   return get(Instruction::URem, C1, C2);
 }
 
-Constant* ConstantExpr::getSRem(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getSRem(Constant *C1, Constant *C2) {
   return get(Instruction::SRem, C1, C2);
 }
 
-Constant* ConstantExpr::getFRem(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getFRem(Constant *C1, Constant *C2) {
   return get(Instruction::FRem, C1, C2);
 }
 
-Constant* ConstantExpr::getAnd(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getAnd(Constant *C1, Constant *C2) {
   return get(Instruction::And, C1, C2);
 }
 
-Constant* ConstantExpr::getOr(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getOr(Constant *C1, Constant *C2) {
   return get(Instruction::Or, C1, C2);
 }
 
-Constant* ConstantExpr::getXor(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getXor(Constant *C1, Constant *C2) {
   return get(Instruction::Xor, C1, C2);
 }
 
-Constant* ConstantExpr::getShl(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getShl(Constant *C1, Constant *C2) {
   return get(Instruction::Shl, C1, C2);
 }
 
-Constant* ConstantExpr::getLShr(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getLShr(Constant *C1, Constant *C2) {
   return get(Instruction::LShr, C1, C2);
 }
 
-Constant* ConstantExpr::getAShr(Constant* C1, Constant* C2) {
+Constant *ConstantExpr::getAShr(Constant *C1, Constant *C2) {
   return get(Instruction::AShr, C1, C2);
 }
 
index c661f7c0771efd1a8a44299a1cb718b68301d668..a845d89bb6c92b9862debe1b9643c37fb650f3b1 100644 (file)
@@ -1,4 +1,4 @@
 ; Found by inspection of the code
-; RUN: not llvm-as < %s > /dev/null |& grep {constexpr requires integer or integer vector operands}
+; RUN: not llvm-as < %s > /dev/null |& grep {constexpr requires integer operands}
 
 global i32 ashr (float 1.0, float 2.0)
index 82b35b5c21000a2fc14d3176c3b56d1dd9a393bb..310b807c5d5636cf2f638861c03306526eb8ff66 100644 (file)
@@ -92,6 +92,12 @@ define i64 @mul_both_reversed(i64 %x, i64 %y) {
        ret i64 %z
 }
 
+define i64 @shl_both(i64 %x, i64 %y) {
+; CHECK: %z = shl nuw nsw i64 %x, %y
+       %z = shl nuw nsw i64 %x, %y
+       ret i64 %z
+}
+
 define i64 @sdiv_exact(i64 %x, i64 %y) {
 ; CHECK: %z = sdiv exact i64 %x, %y
        %z = sdiv exact i64 %x, %y
@@ -116,6 +122,29 @@ define i64 @udiv_plain(i64 %x, i64 %y) {
        ret i64 %z
 }
 
+define i64 @ashr_plain(i64 %x, i64 %y) {
+; CHECK: %z = ashr i64 %x, %y
+       %z = ashr i64 %x, %y
+       ret i64 %z
+}
+
+define i64 @ashr_exact(i64 %x, i64 %y) {
+; CHECK: %z = ashr exact i64 %x, %y
+       %z = ashr exact i64 %x, %y
+       ret i64 %z
+}
+
+define i64 @lshr_plain(i64 %x, i64 %y) {
+; CHECK: %z = lshr i64 %x, %y
+       %z = lshr i64 %x, %y
+       ret i64 %z
+}
+
+define i64 @lshr_exact(i64 %x, i64 %y) {
+; CHECK: %z = lshr exact i64 %x, %y
+       %z = lshr exact i64 %x, %y
+       ret i64 %z
+}
 
 define i64* @gep_nw(i64* %p, i64 %x) {
 ; CHECK: %z = getelementptr inbounds i64* %p, i64 %x
@@ -154,6 +183,16 @@ define i64 @udiv_exact_ce() {
        ret i64 udiv exact (i64 ptrtoint (i64* @addr to i64), i64 91)
 }
 
+define i64 @ashr_exact_ce() {
+; CHECK: ret i64 ashr exact (i64 ptrtoint (i64* @addr to i64), i64 9)
+       ret i64 ashr exact (i64 ptrtoint (i64* @addr to i64), i64 9)
+}
+
+define i64 @lshr_exact_ce() {
+; CHECK: ret i64 lshr exact (i64 ptrtoint (i64* @addr to i64), i64 9)
+       ret i64 lshr exact (i64 ptrtoint (i64* @addr to i64), i64 9)
+}
+
 define i64* @gep_nw_ce() {
 ; CHECK: ret i64* getelementptr inbounds (i64* @addr, i64 171)
         ret i64* getelementptr inbounds (i64* @addr, i64 171)
@@ -214,6 +253,12 @@ define i64 @mul_signed_ce() {
        ret i64 mul nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
 }
 
+define i64 @shl_signed_ce() {
+; CHECK: ret i64 shl nsw (i64 ptrtoint (i64* @addr to i64), i64 17)
+       ret i64 shl nsw (i64 ptrtoint (i64* @addr to i64), i64 17)
+}
+
+
 define i64 @add_unsigned_ce() {
 ; CHECK: ret i64 add nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
        ret i64 add nuw (i64 ptrtoint (i64* @addr to i64), i64 91)