For PR950:
authorReid Spencer <rspencer@reidspencer.com>
Thu, 2 Nov 2006 01:53:59 +0000 (01:53 +0000)
committerReid Spencer <rspencer@reidspencer.com>
Thu, 2 Nov 2006 01:53:59 +0000 (01:53 +0000)
Replace the REM instruction with UREM, SREM and FREM.

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

21 files changed:
docs/LangRef.html
include/llvm/Constants.h
include/llvm/Instruction.def
include/llvm/Support/PatternMatch.h
lib/Analysis/ScalarEvolution.cpp
lib/AsmParser/Lexer.l
lib/AsmParser/llvmAsmParser.y
lib/Bytecode/Reader/Reader.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
lib/ExecutionEngine/Interpreter/Execution.cpp
lib/Target/CBackend/CBackend.cpp
lib/Target/CBackend/Writer.cpp
lib/Transforms/Scalar/InstructionCombining.cpp
lib/Transforms/Scalar/PredicateSimplifier.cpp
lib/Transforms/Scalar/Reassociate.cpp
lib/VMCore/ConstantFold.cpp
lib/VMCore/Constants.cpp
lib/VMCore/Instruction.cpp
lib/VMCore/Instructions.cpp
projects/Stacker/lib/compiler/StackerCompiler.cpp
tools/llvm2cpp/CppWriter.cpp

index 0ed371a749bede110407e6fece037fbeed8dbe2e..97b53123564bbc8a44f1a831735240b25f59fc17 100644 (file)
@@ -80,7 +80,9 @@
           <li><a href="#i_udiv">'<tt>udiv</tt>' Instruction</a></li>
           <li><a href="#i_sdiv">'<tt>sdiv</tt>' Instruction</a></li>
           <li><a href="#i_fdiv">'<tt>fdiv</tt>' Instruction</a></li>
-          <li><a href="#i_rem">'<tt>rem</tt>' Instruction</a></li>
+          <li><a href="#i_urem">'<tt>urem</tt>' Instruction</a></li>
+          <li><a href="#i_srem">'<tt>srem</tt>' Instruction</a></li>
+          <li><a href="#i_frem">'<tt>frem</tt>' Instruction</a></li>
           <li><a href="#i_setcc">'<tt>set<i>cc</i></tt>' Instructions</a></li>
         </ol>
       </li>
@@ -1699,30 +1701,72 @@ versions of the values in which case the elements must be floating point.</p>
 </pre>
 </div>
 <!-- _______________________________________________________________________ -->
-<div class="doc_subsubsection"> <a name="i_rem">'<tt>rem</tt>'
+<div class="doc_subsubsection"> <a name="i_urem">'<tt>urem</tt>' Instruction</a>
+</div>
+<div class="doc_text">
+<h5>Syntax:</h5>
+<pre>  &lt;result&gt; = urem &lt;ty&gt; &lt;var1&gt;, &lt;var2&gt;   <i>; yields {ty}:result</i>
+</pre>
+<h5>Overview:</h5>
+<p>The '<tt>urem</tt>' instruction returns the remainder from the
+unsigned division of its two arguments.</p>
+<h5>Arguments:</h5>
+<p>The two arguments to the '<tt>urem</tt>' instruction must be
+<a href="#t_integer">integer</a> values. Both arguments must have identical
+types.</p>
+<h5>Semantics:</h5>
+<p>This instruction returns the unsigned integer <i>remainder</i> of a division.
+This instruction always performs an unsigned division to get the remainder,
+regardless of whether the arguments are unsigned or not.</p>
+<h5>Example:</h5>
+<pre>  &lt;result&gt; = urem uint 4, %var          <i>; yields {uint}:result = 4 % %var</i>
+</pre>
+
+</div>
+<!-- _______________________________________________________________________ -->
+<div class="doc_subsubsection"> <a name="i_srem">'<tt>srem</tt>'
 Instruction</a> </div>
 <div class="doc_text">
 <h5>Syntax:</h5>
-<pre>  &lt;result&gt; = rem &lt;ty&gt; &lt;var1&gt;, &lt;var2&gt;   <i>; yields {ty}:result</i>
+<pre>  &lt;result&gt; = srem &lt;ty&gt; &lt;var1&gt;, &lt;var2&gt;   <i>; yields {ty}:result</i>
 </pre>
 <h5>Overview:</h5>
-<p>The '<tt>rem</tt>' instruction returns the remainder from the
-division of its two operands.</p>
+<p>The '<tt>srem</tt>' instruction returns the remainder from the
+signed division of its two operands.</p>
 <h5>Arguments:</h5>
-<p>The two arguments to the '<tt>rem</tt>' instruction must be either <a
- href="#t_integer">integer</a> or <a href="#t_floating">floating point</a>
-values. 
-This instruction can also take <a href="#t_packed">packed</a> versions of the values.
-Both arguments must have identical types.</p>
+<p>The two arguments to the '<tt>srem</tt>' instruction must be 
+<a href="#t_integer">integer</a> values.  Both arguments must have identical 
+types.</p>
 <h5>Semantics:</h5>
-<p>This returns the <i>remainder</i> of a division (where the result
+<p>This instruction returns the <i>remainder</i> of a division (where the result
 has the same sign as the divisor), not the <i>modulus</i> (where the
 result has the same sign as the dividend) of a value.  For more
 information about the difference, see <a
  href="http://mathforum.org/dr.math/problems/anne.4.28.99.html">The
 Math Forum</a>.</p>
 <h5>Example:</h5>
-<pre>  &lt;result&gt; = rem int 4, %var          <i>; yields {int}:result = 4 % %var</i>
+<pre>  &lt;result&gt; = srem int 4, %var          <i>; yields {int}:result = 4 % %var</i>
+</pre>
+
+</div>
+<!-- _______________________________________________________________________ -->
+<div class="doc_subsubsection"> <a name="i_frem">'<tt>frem</tt>'
+Instruction</a> </div>
+<div class="doc_text">
+<h5>Syntax:</h5>
+<pre>  &lt;result&gt; = frem &lt;ty&gt; &lt;var1&gt;, &lt;var2&gt;   <i>; yields {ty}:result</i>
+</pre>
+<h5>Overview:</h5>
+<p>The '<tt>frem</tt>' instruction returns the remainder from the
+division of its two operands.</p>
+<h5>Arguments:</h5>
+<p>The two arguments to the '<tt>frem</tt>' instruction must be
+<a href="#t_floating">floating point</a> values.  Both arguments must have 
+identical types.</p>
+<h5>Semantics:</h5>
+<p>This instruction returns the <i>remainder</i> of a division.</p>
+<h5>Example:</h5>
+<pre>  &lt;result&gt; = frem float 4.0, %var          <i>; yields {float}:result = 4.0 % %var</i>
 </pre>
 
 </div>
index f5fff4d7fb494a97e0ff72befbb456b2cfd5765a..e44e07e868c27ef2d664d221bf78c0ee8fd852bc 100644 (file)
@@ -551,7 +551,9 @@ public:
   static Constant *getUDiv(Constant *C1, Constant *C2);
   static Constant *getSDiv(Constant *C1, Constant *C2);
   static Constant *getFDiv(Constant *C1, Constant *C2);
-  static Constant *getRem(Constant *C1, Constant *C2);
+  static Constant *getURem(Constant *C1, Constant *C2); // unsigned rem
+  static Constant *getSRem(Constant *C1, Constant *C2); // signed rem
+  static Constant *getFRem(Constant *C1, Constant *C2);
   static Constant *getAnd(Constant *C1, Constant *C2);
   static Constant *getOr(Constant *C1, Constant *C2);
   static Constant *getXor(Constant *C1, Constant *C2);
index 91a467cf59064163eead716248090dc288ec34fe..4f7f2f54838a41f773b4f2734f86124bbd7e6ccb 100644 (file)
@@ -90,53 +90,55 @@ HANDLE_TERM_INST  ( 6, Unreachable, UnreachableInst)
 
 // Standard binary operators...
  FIRST_BINARY_INST( 7)
-HANDLE_BINARY_INST( 7, Add   , BinaryOperator)
-HANDLE_BINARY_INST( 8, Sub   , BinaryOperator)
-HANDLE_BINARY_INST( 9, Mul   , BinaryOperator)
-HANDLE_BINARY_INST(10, UDiv  , BinaryOperator)
-HANDLE_BINARY_INST(11, SDiv  , BinaryOperator)
-HANDLE_BINARY_INST(12, FDiv  , BinaryOperator)
-HANDLE_BINARY_INST(13, Rem   , BinaryOperator)
+HANDLE_BINARY_INST( 7, Add  , BinaryOperator)
+HANDLE_BINARY_INST( 8, Sub  , BinaryOperator)
+HANDLE_BINARY_INST( 9, Mul  , BinaryOperator)
+HANDLE_BINARY_INST(10, UDiv , BinaryOperator)
+HANDLE_BINARY_INST(11, SDiv , BinaryOperator)
+HANDLE_BINARY_INST(12, FDiv , BinaryOperator)
+HANDLE_BINARY_INST(13, URem , BinaryOperator)
+HANDLE_BINARY_INST(14, SRem , BinaryOperator)
+HANDLE_BINARY_INST(15, FRem , BinaryOperator)
 
 // Logical operators...
-HANDLE_BINARY_INST(14, And   , BinaryOperator)
-HANDLE_BINARY_INST(15, Or    , BinaryOperator)
-HANDLE_BINARY_INST(16, Xor   , BinaryOperator)
+HANDLE_BINARY_INST(16, And   , BinaryOperator)
+HANDLE_BINARY_INST(17, Or    , BinaryOperator)
+HANDLE_BINARY_INST(18, Xor   , BinaryOperator)
 
 // Binary comparison operators...
-HANDLE_BINARY_INST(17, SetEQ , SetCondInst)
-HANDLE_BINARY_INST(18, SetNE , SetCondInst)
-HANDLE_BINARY_INST(19, SetLE , SetCondInst)
-HANDLE_BINARY_INST(20, SetGE , SetCondInst)
-HANDLE_BINARY_INST(21, SetLT , SetCondInst)
-HANDLE_BINARY_INST(22, SetGT , SetCondInst)
-  LAST_BINARY_INST(22)
+HANDLE_BINARY_INST(19, SetEQ , SetCondInst)
+HANDLE_BINARY_INST(20, SetNE , SetCondInst)
+HANDLE_BINARY_INST(21, SetLE , SetCondInst)
+HANDLE_BINARY_INST(22, SetGE , SetCondInst)
+HANDLE_BINARY_INST(23, SetLT , SetCondInst)
+HANDLE_BINARY_INST(24, SetGT , SetCondInst)
+  LAST_BINARY_INST(24)
 
 // Memory operators...
- FIRST_MEMORY_INST(23)
-HANDLE_MEMORY_INST(23, Malloc, MallocInst)  // Heap management instructions
-HANDLE_MEMORY_INST(24, Free  , FreeInst  )
-HANDLE_MEMORY_INST(25, Alloca, AllocaInst)  // Stack management
-HANDLE_MEMORY_INST(26, Load  , LoadInst  )  // Memory manipulation instrs
-HANDLE_MEMORY_INST(27, Store , StoreInst )
-HANDLE_MEMORY_INST(28, GetElementPtr, GetElementPtrInst)
-  LAST_MEMORY_INST(28)
+ FIRST_MEMORY_INST(25)
+HANDLE_MEMORY_INST(25, Malloc, MallocInst)  // Heap management instructions
+HANDLE_MEMORY_INST(26, Free  , FreeInst  )
+HANDLE_MEMORY_INST(27, Alloca, AllocaInst)  // Stack management
+HANDLE_MEMORY_INST(28, Load  , LoadInst  )  // Memory manipulation instrs
+HANDLE_MEMORY_INST(29, Store , StoreInst )
+HANDLE_MEMORY_INST(30, GetElementPtr, GetElementPtrInst)
+  LAST_MEMORY_INST(30)
 
 // Other operators...
- FIRST_OTHER_INST(29)
-HANDLE_OTHER_INST(29, PHI    , PHINode    )  // PHI node instruction
-HANDLE_OTHER_INST(30, Cast   , CastInst   )  // Type cast
-HANDLE_OTHER_INST(31, Call   , CallInst   )  // Call a function
-HANDLE_OTHER_INST(32, Shl    , ShiftInst  )  // Shift operations
-HANDLE_OTHER_INST(33, Shr    , ShiftInst  )
-HANDLE_OTHER_INST(34, Select , SelectInst )  // select instruction
-HANDLE_OTHER_INST(35, UserOp1, Instruction)  // May be used internally in a pass
-HANDLE_OTHER_INST(36, UserOp2, Instruction)
-HANDLE_OTHER_INST(37, VAArg  , VAArgInst  )  // vaarg instruction
-HANDLE_OTHER_INST(38, ExtractElement, ExtractElementInst)// extract from vector.
-HANDLE_OTHER_INST(39, InsertElement, InsertElementInst)  // insert into vector
-HANDLE_OTHER_INST(40, ShuffleVector, ShuffleVectorInst)  // shuffle two vectors.
-  LAST_OTHER_INST(40)
+ FIRST_OTHER_INST(31)
+HANDLE_OTHER_INST(31, PHI    , PHINode    )  // PHI node instruction
+HANDLE_OTHER_INST(32, Cast   , CastInst   )  // Type cast
+HANDLE_OTHER_INST(33, Call   , CallInst   )  // Call a function
+HANDLE_OTHER_INST(34, Shl    , ShiftInst  )  // Shift operations
+HANDLE_OTHER_INST(35, Shr    , ShiftInst  )
+HANDLE_OTHER_INST(36, Select , SelectInst )  // select instruction
+HANDLE_OTHER_INST(37, UserOp1, Instruction)  // May be used internally in a pass
+HANDLE_OTHER_INST(38, UserOp2, Instruction)
+HANDLE_OTHER_INST(39, VAArg  , VAArgInst  )  // vaarg instruction
+HANDLE_OTHER_INST(40, ExtractElement, ExtractElementInst)// extract from vector.
+HANDLE_OTHER_INST(41, InsertElement, InsertElementInst)  // insert into vector
+HANDLE_OTHER_INST(42, ShuffleVector, ShuffleVectorInst)  // shuffle two vectors.
+  LAST_OTHER_INST(42)
 
 #undef  FIRST_TERM_INST
 #undef HANDLE_TERM_INST
index f4c9ad50987114fe5c785ccad501293b37eb351f..bee416a24e70ebec66be1bc7f73d77b7dc57485f 100644 (file)
@@ -130,9 +130,21 @@ inline BinaryOp_match<LHS, RHS, Instruction::FDiv> m_FDiv(const LHS &L,
 }
 
 template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Rem> m_Rem(const LHS &L,
+inline BinaryOp_match<LHS, RHS, Instruction::URem> m_URem(const LHS &L,
+                                                          const RHS &R) {
+  return BinaryOp_match<LHS, RHS, Instruction::URem>(L, R);
+}
+
+template<typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::SRem> m_SRem(const LHS &L,
+                                                          const RHS &R) {
+  return BinaryOp_match<LHS, RHS, Instruction::SRem>(L, R);
+}
+
+template<typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FRem> m_FRem(const LHS &L,
                                                         const RHS &R) {
-  return BinaryOp_match<LHS, RHS, Instruction::Rem>(L, R);
+  return BinaryOp_match<LHS, RHS, Instruction::FRem>(L, R);
 }
 
 template<typename LHS, typename RHS>
index d555a14089adc1aaf7852ac2e7894a9976235f46..a4de55c2c3e185f6f73eaf8c239d1074c4ee44e8 100644 (file)
@@ -2147,7 +2147,7 @@ SCEVHandle ScalarEvolutionsImpl::HowFarToZero(SCEV *V, const Loop *L) {
       if (SCEVConstant *StartC = dyn_cast<SCEVConstant>(Start)) {
         ConstantInt *StartCC = StartC->getValue();
         Constant *StartNegC = ConstantExpr::getNeg(StartCC);
-        Constant *Rem = ConstantExpr::getRem(StartNegC, StepC->getValue());
+        Constant *Rem = ConstantExpr::getSRem(StartNegC, StepC->getValue());
         if (Rem->isNullValue()) {
           Constant *Result =ConstantExpr::getSDiv(StartNegC,StepC->getValue());
           return SCEVUnknown::get(Result);
index 96804bb75b4edb8eb710897e18d2de4bb87dcef7..4df84f685e64e34bbc2b025a239266d40c6edaa6 100644 (file)
@@ -261,7 +261,10 @@ div             { RET_TOK_OBSOLETE(BinaryOpVal, UDiv, UDIV); }
 udiv            { RET_TOK(BinaryOpVal, UDiv, UDIV); }
 sdiv            { RET_TOK(BinaryOpVal, SDiv, SDIV); }
 fdiv            { RET_TOK(BinaryOpVal, FDiv, FDIV); }
-rem             { RET_TOK(BinaryOpVal, Rem, REM); }
+rem             { RET_TOK_OBSOLETE(BinaryOpVal, URem, UREM); }
+urem            { RET_TOK(BinaryOpVal, URem, UREM); }
+srem            { RET_TOK(BinaryOpVal, SRem, SREM); }
+frem            { RET_TOK(BinaryOpVal, FRem, FREM); }
 and             { RET_TOK(BinaryOpVal, And, AND); }
 or              { RET_TOK(BinaryOpVal, Or , OR ); }
 xor             { RET_TOK(BinaryOpVal, Xor, XOR); }
index 684b643bbacae738c3cce84787d2ea5124e5d3a4..d40b653afda56f7cc83fdae9b93fa25804fb2f33 100644 (file)
@@ -836,7 +836,7 @@ sanitizeOpCode(OpcodeInfo<Instruction::BinaryOps> &OI, const PATypeHolder& PATy)
   // Depending on the opcode ..
   switch (OI.opcode) {
     default:
-      GenerateError("Invalid Obsolete OpCode");
+      GenerateError("Invalid obsolete opCode (check Lexer.l)");
       break;
     case Instruction::UDiv:
       // Handle cases where the opcode needs to change
@@ -845,12 +845,17 @@ sanitizeOpCode(OpcodeInfo<Instruction::BinaryOps> &OI, const PATypeHolder& PATy)
       else if (Ty->isSigned())
         OI.opcode = Instruction::SDiv;
       break;
+    case Instruction::URem:
+      if (Ty->isFloatingPoint()) 
+        OI.opcode = Instruction::FRem;
+      else if (Ty->isSigned())
+        OI.opcode = Instruction::SRem;
+      break;
   }
   // Its not obsolete any more, we fixed it.
   OI.obsolete = false;
 }
-
-
+  
 // common code from the two 'RunVMAsmParser' functions
 static Module* RunParser(Module * M) {
 
@@ -1113,7 +1118,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
 
 // Binary Operators
 %type  <BinaryOpVal> ArithmeticOps LogicalOps SetCondOps // Binops Subcatagories
-%token <BinaryOpVal> ADD SUB MUL UDIV SDIV FDIV REM AND OR XOR
+%token <BinaryOpVal> ADD SUB MUL UDIV SDIV FDIV UREM SREM FREM AND OR XOR
 %token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE  // Binary Comparators
 
 // Memory Instructions
@@ -1151,7 +1156,7 @@ EINT64VAL : EUINT64VAL {
 // Operations that are notably excluded from this list include:
 // RET, BR, & SWITCH because they end basic blocks and are treated specially.
 //
-ArithmeticOps: ADD | SUB | MUL | UDIV | SDIV | FDIV | REM ;
+ArithmeticOps: ADD | SUB | MUL | UDIV | SDIV | FDIV | UREM | SREM | FREM;
 LogicalOps   : AND | OR | XOR;
 SetCondOps   : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
 
@@ -2465,8 +2470,11 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
         !isa<PackedType>((*$2).get()))
       GEN_ERROR(
         "Arithmetic operator requires integer, FP, or packed operands!");
-    if (isa<PackedType>((*$2).get()) && $1.opcode == Instruction::Rem)
-      GEN_ERROR("Rem not supported on packed types!");
+    if (isa<PackedType>((*$2).get()) && 
+        ($1.opcode == Instruction::URem || 
+         $1.opcode == Instruction::SRem ||
+         $1.opcode == Instruction::FRem))
+      GEN_ERROR("U/S/FRem not supported on packed types!");
     // Upgrade the opcode from obsolete versions before we do anything with it.
     sanitizeOpCode($1,*$2);
     CHECK_FOR_ERROR;
index d3df471a1c2db87f8bdff1199a46ad840185fb16..b1ec74e2d6c0dfb736576c8bfb018a7bd906d999 100644 (file)
@@ -652,7 +652,14 @@ BytecodeReader::handleObsoleteOpcodes(
       break;
 
     case 11: // Rem
-        Opcode = Instruction::Rem;
+      // As with "Div", make the signed/unsigned or floating point Rem 
+      // instruction choice based on the type of the operands.
+      if (iType == 10 || iType == 11)
+        Opcode = Instruction::FRem;
+      else if (iType >= 2 && iType <= 9 && iType % 2 != 0)
+        Opcode = Instruction::SRem;
+      else
+        Opcode = Instruction::URem;
       break;
     case 12: // And
       Opcode = Instruction::And;
@@ -1654,18 +1661,16 @@ inline unsigned fixCEOpcodes(
       else
         Opcode = Instruction::UDiv;
       break;
-
     case 11: // Rem
-      // As with "Div", make the signed/unsigned Rem instruction choice based
-      // on the type of the instruction.
+      // As with "Div", make the signed/unsigned or floating point Rem 
+      // instruction choice based on the type of the operands.
       if (ArgVec[0]->getType()->isFloatingPoint())
-        Opcode = Instruction::Rem;
+        Opcode = Instruction::FRem;
       else if (ArgVec[0]->getType()->isSigned())
-        Opcode = Instruction::Rem;
+        Opcode = Instruction::SRem;
       else
-        Opcode = Instruction::Rem;
+        Opcode = Instruction::URem;
       break;
-
     case 12: // And
       Opcode = Instruction::And;
       break;
index 9be3a16975bab37ef55fc53bccd14e6da430cb81..99306050c1361a9308404d9372a70f8d4945f548 100644 (file)
@@ -528,16 +528,12 @@ public:
     else
       visitIntBinary(I, ISD::MUL, ISD::VMUL); 
   }
+  void visitURem(User &I) { visitIntBinary(I, ISD::UREM, 0); }
+  void visitSRem(User &I) { visitIntBinary(I, ISD::SREM, 0); }
+  void visitFRem(User &I) { visitFPBinary (I, ISD::FREM, 0); }
   void visitUDiv(User &I) { visitIntBinary(I, ISD::UDIV, ISD::VUDIV); }
   void visitSDiv(User &I) { visitIntBinary(I, ISD::SDIV, ISD::VSDIV); }
-  void visitFDiv(User &I) { visitFPBinary(I, ISD::FDIV,  ISD::VSDIV); }
-  void visitRem(User &I) {
-    const Type *Ty = I.getType();
-    if (Ty->isFloatingPoint())
-      visitFPBinary(I, ISD::FREM, 0);
-    else 
-      visitIntBinary(I, Ty->isSigned() ? ISD::SREM : ISD::UREM, 0);
-  }
+  void visitFDiv(User &I) { visitFPBinary (I, ISD::FDIV, ISD::VSDIV); }
   void visitAnd(User &I) { visitIntBinary(I, ISD::AND, ISD::VAND); }
   void visitOr (User &I) { visitIntBinary(I, ISD::OR,  ISD::VOR); }
   void visitXor(User &I) { visitIntBinary(I, ISD::XOR, ISD::VXOR); }
index 5a7181f83eb92515a8ea0ce5c1903cc213cd42d7..eec018ac010903d5d507e33ed36b0ec87320589b 100644 (file)
@@ -48,6 +48,12 @@ static GenericValue executeSDivInst(GenericValue Src1, GenericValue Src2,
                                     const Type *Ty);
 static GenericValue executeFDivInst(GenericValue Src1, GenericValue Src2,
                                     const Type *Ty);
+static GenericValue executeURemInst(GenericValue Src1, GenericValue Src2,
+                                    const Type *Ty);
+static GenericValue executeSRemInst(GenericValue Src1, GenericValue Src2,
+                                    const Type *Ty);
+static GenericValue executeFRemInst(GenericValue Src1, GenericValue Src2,
+                                    const Type *Ty);
 static GenericValue executeAndInst(GenericValue Src1, GenericValue Src2,
                                    const Type *Ty);
 static GenericValue executeOrInst(GenericValue Src1, GenericValue Src2,
@@ -105,10 +111,18 @@ GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE,
     return executeFDivInst(getOperandValue(CE->getOperand(0), SF),
                            getOperandValue(CE->getOperand(1), SF),
                            CE->getOperand(0)->getType());
-  case Instruction::Rem:
-    return executeRemInst(getOperandValue(CE->getOperand(0), SF),
+  case Instruction::URem:
+    return executeURemInst(getOperandValue(CE->getOperand(0), SF),
                           getOperandValue(CE->getOperand(1), SF),
                           CE->getOperand(0)->getType());
+  case Instruction::SRem:
+    return executeSRemInst(getOperandValue(CE->getOperand(0), SF),
+                          getOperandValue(CE->getOperand(1), SF),
+                          CE->getOperand(0)->getType());
+  case Instruction::FRem:
+    return executeFRemInst(getOperandValue(CE->getOperand(0), SF),
+                           getOperandValue(CE->getOperand(1), SF),
+                           CE->getOperand(0)->getType());
   case Instruction::And:
     return executeAndInst(getOperandValue(CE->getOperand(0), SF),
                           getOperandValue(CE->getOperand(1), SF),
@@ -300,18 +314,40 @@ static GenericValue executeFDivInst(GenericValue Src1, GenericValue Src2,
   return Dest;
 }
 
-static GenericValue executeRemInst(GenericValue Src1, GenericValue Src2,
+static GenericValue executeURemInst(GenericValue Src1, GenericValue Src2,
+                                   const Type *Ty) {
+  GenericValue Dest;
+  switch (Ty->getTypeID()) {
+    IMPLEMENT_SIGNLESS_BINOP(%, UByte,  SByte);
+    IMPLEMENT_SIGNLESS_BINOP(%, UShort, Short);
+    IMPLEMENT_SIGNLESS_BINOP(%, UInt,   Int);
+    IMPLEMENT_SIGNLESS_BINOP(%, ULong,  Long);
+  default:
+    std::cout << "Unhandled type for URem instruction: " << *Ty << "\n";
+    abort();
+  }
+  return Dest;
+}
+
+static GenericValue executeSRemInst(GenericValue Src1, GenericValue Src2,
+                                   const Type *Ty) {
+  GenericValue Dest;
+  switch (Ty->getTypeID()) {
+    IMPLEMENT_SIGNLESS_BINOP(%, SByte, UByte);
+    IMPLEMENT_SIGNLESS_BINOP(%, Short, UShort);
+    IMPLEMENT_SIGNLESS_BINOP(%, Int,   UInt);
+    IMPLEMENT_SIGNLESS_BINOP(%, Long,  ULong);
+  default:
+    std::cout << "Unhandled type for Rem instruction: " << *Ty << "\n";
+    abort();
+  }
+  return Dest;
+}
+
+static GenericValue executeFRemInst(GenericValue Src1, GenericValue Src2,
                                    const Type *Ty) {
   GenericValue Dest;
   switch (Ty->getTypeID()) {
-    IMPLEMENT_BINARY_OPERATOR(%, UByte);
-    IMPLEMENT_BINARY_OPERATOR(%, SByte);
-    IMPLEMENT_BINARY_OPERATOR(%, UShort);
-    IMPLEMENT_BINARY_OPERATOR(%, Short);
-    IMPLEMENT_BINARY_OPERATOR(%, UInt);
-    IMPLEMENT_BINARY_OPERATOR(%, Int);
-    IMPLEMENT_BINARY_OPERATOR(%, ULong);
-    IMPLEMENT_BINARY_OPERATOR(%, Long);
   case Type::FloatTyID:
     Dest.FloatVal = fmod(Src1.FloatVal, Src2.FloatVal);
     break;
@@ -544,7 +580,9 @@ void Interpreter::visitBinaryOperator(BinaryOperator &I) {
   case Instruction::UDiv:  R = executeUDivInst (Src1, Src2, Ty); break;
   case Instruction::SDiv:  R = executeSDivInst (Src1, Src2, Ty); break;
   case Instruction::FDiv:  R = executeFDivInst (Src1, Src2, Ty); break;
-  case Instruction::Rem:   R = executeRemInst  (Src1, Src2, Ty); break;
+  case Instruction::URem:  R = executeURemInst (Src1, Src2, Ty); break;
+  case Instruction::SRem:  R = executeSRemInst (Src1, Src2, Ty); break;
+  case Instruction::FRem:  R = executeFRemInst (Src1, Src2, Ty); break;
   case Instruction::And:   R = executeAndInst  (Src1, Src2, Ty); break;
   case Instruction::Or:    R = executeOrInst   (Src1, Src2, Ty); break;
   case Instruction::Xor:   R = executeXorInst  (Src1, Src2, Ty); break;
index cef1ba621ac4619043126a3d4bfc7c9f071102be..4a04e023eacc34e622c4562d83b7b5d066d9a17b 100644 (file)
@@ -593,7 +593,9 @@ void CWriter::printConstant(Constant *CPV) {
     case Instruction::SDiv:
     case Instruction::UDiv:
     case Instruction::FDiv:
-    case Instruction::Rem:
+    case Instruction::URem:
+    case Instruction::SRem:
+    case Instruction::FRem:
     case Instruction::And:
     case Instruction::Or:
     case Instruction::Xor:
@@ -613,10 +615,12 @@ void CWriter::printConstant(Constant *CPV) {
       case Instruction::Add: Out << " + "; break;
       case Instruction::Sub: Out << " - "; break;
       case Instruction::Mul: Out << " * "; break;
+      case Instruction::URem:
+      case Instruction::SRem: 
+      case Instruction::FRem: Out << " % "; break;
       case Instruction::UDiv: 
       case Instruction::SDiv: 
       case Instruction::FDiv: Out << " / "; break;
-      case Instruction::Rem: Out << " % "; break;
       case Instruction::And: Out << " & "; break;
       case Instruction::Or:  Out << " | "; break;
       case Instruction::Xor: Out << " ^ "; break;
@@ -825,8 +829,12 @@ bool CWriter::printConstExprCast(const ConstantExpr* CE) {
   bool Result = false;
   const Type* Ty = CE->getOperand(0)->getType();
   switch (CE->getOpcode()) {
-  case Instruction::UDiv: Result = Ty->isSigned(); break;
-  case Instruction::SDiv: Result = Ty->isUnsigned(); break;
+  case Instruction::UDiv: 
+  case Instruction::URem: 
+    Result = Ty->isSigned(); break;
+  case Instruction::SDiv: 
+  case Instruction::SRem: 
+    Result = Ty->isUnsigned(); break;
   default: break;
   }
   if (Result) {
@@ -856,13 +864,16 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
       // for most instructions, it doesn't matter
       break; 
     case Instruction::UDiv:
-      // For UDiv to have unsigned operands
+    case Instruction::URem:
+      // For UDiv/URem get correct type
       if (OpTy->isSigned()) {
         OpTy = OpTy->getUnsignedVersion();
         shouldCast = true;
       }
       break;
     case Instruction::SDiv:
+    case Instruction::SRem:
+      // For SDiv/SRem get correct type
       if (OpTy->isUnsigned()) {
         OpTy = OpTy->getSignedVersion();
         shouldCast = true;
@@ -919,8 +930,12 @@ bool CWriter::writeInstructionCast(const Instruction &I) {
   bool Result = false;
   const Type* Ty = I.getOperand(0)->getType();
   switch (I.getOpcode()) {
-  case Instruction::UDiv: Result = Ty->isSigned(); break;
-  case Instruction::SDiv: Result = Ty->isUnsigned(); break;
+  case Instruction::UDiv: 
+  case Instruction::URem: 
+    Result = Ty->isSigned(); break;
+  case Instruction::SDiv: 
+  case Instruction::SRem: 
+    Result = Ty->isUnsigned(); break;
   default: break;
   }
   if (Result) {
@@ -950,6 +965,7 @@ void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
       // for most instructions, it doesn't matter
       break; 
     case Instruction::UDiv:
+    case Instruction::URem:
       // For UDiv to have unsigned operands
       if (OpTy->isSigned()) {
         OpTy = OpTy->getUnsignedVersion();
@@ -957,6 +973,7 @@ void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
       }
       break;
     case Instruction::SDiv:
+    case Instruction::SRem:
       if (OpTy->isUnsigned()) {
         OpTy = OpTy->getSignedVersion();
         shouldCast = true;
@@ -1774,8 +1791,7 @@ void CWriter::visitBinaryOperator(Instruction &I) {
     Out << "-(";
     writeOperand(BinaryOperator::getNegArgument(cast<BinaryOperator>(&I)));
     Out << ")";
-  } else if (I.getOpcode() == Instruction::Rem && 
-             I.getType()->isFloatingPoint()) {
+  } else if (I.getOpcode() == Instruction::FRem) {
     // Output a call to fmod/fmodf instead of emitting a%b
     if (I.getType() == Type::FloatTy)
       Out << "fmodf(";
@@ -1800,10 +1816,12 @@ void CWriter::visitBinaryOperator(Instruction &I) {
     case Instruction::Add: Out << " + "; break;
     case Instruction::Sub: Out << " - "; break;
     case Instruction::Mul: Out << '*'; break;
+    case Instruction::URem:
+    case Instruction::SRem:
+    case Instruction::FRem: Out << '%'; break;
     case Instruction::UDiv:
     case Instruction::SDiv: 
     case Instruction::FDiv: Out << '/'; break;
-    case Instruction::Rem: Out << '%'; break;
     case Instruction::And: Out << " & "; break;
     case Instruction::Or: Out << " | "; break;
     case Instruction::Xor: Out << " ^ "; break;
index cef1ba621ac4619043126a3d4bfc7c9f071102be..4a04e023eacc34e622c4562d83b7b5d066d9a17b 100644 (file)
@@ -593,7 +593,9 @@ void CWriter::printConstant(Constant *CPV) {
     case Instruction::SDiv:
     case Instruction::UDiv:
     case Instruction::FDiv:
-    case Instruction::Rem:
+    case Instruction::URem:
+    case Instruction::SRem:
+    case Instruction::FRem:
     case Instruction::And:
     case Instruction::Or:
     case Instruction::Xor:
@@ -613,10 +615,12 @@ void CWriter::printConstant(Constant *CPV) {
       case Instruction::Add: Out << " + "; break;
       case Instruction::Sub: Out << " - "; break;
       case Instruction::Mul: Out << " * "; break;
+      case Instruction::URem:
+      case Instruction::SRem: 
+      case Instruction::FRem: Out << " % "; break;
       case Instruction::UDiv: 
       case Instruction::SDiv: 
       case Instruction::FDiv: Out << " / "; break;
-      case Instruction::Rem: Out << " % "; break;
       case Instruction::And: Out << " & "; break;
       case Instruction::Or:  Out << " | "; break;
       case Instruction::Xor: Out << " ^ "; break;
@@ -825,8 +829,12 @@ bool CWriter::printConstExprCast(const ConstantExpr* CE) {
   bool Result = false;
   const Type* Ty = CE->getOperand(0)->getType();
   switch (CE->getOpcode()) {
-  case Instruction::UDiv: Result = Ty->isSigned(); break;
-  case Instruction::SDiv: Result = Ty->isUnsigned(); break;
+  case Instruction::UDiv: 
+  case Instruction::URem: 
+    Result = Ty->isSigned(); break;
+  case Instruction::SDiv: 
+  case Instruction::SRem: 
+    Result = Ty->isUnsigned(); break;
   default: break;
   }
   if (Result) {
@@ -856,13 +864,16 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
       // for most instructions, it doesn't matter
       break; 
     case Instruction::UDiv:
-      // For UDiv to have unsigned operands
+    case Instruction::URem:
+      // For UDiv/URem get correct type
       if (OpTy->isSigned()) {
         OpTy = OpTy->getUnsignedVersion();
         shouldCast = true;
       }
       break;
     case Instruction::SDiv:
+    case Instruction::SRem:
+      // For SDiv/SRem get correct type
       if (OpTy->isUnsigned()) {
         OpTy = OpTy->getSignedVersion();
         shouldCast = true;
@@ -919,8 +930,12 @@ bool CWriter::writeInstructionCast(const Instruction &I) {
   bool Result = false;
   const Type* Ty = I.getOperand(0)->getType();
   switch (I.getOpcode()) {
-  case Instruction::UDiv: Result = Ty->isSigned(); break;
-  case Instruction::SDiv: Result = Ty->isUnsigned(); break;
+  case Instruction::UDiv: 
+  case Instruction::URem: 
+    Result = Ty->isSigned(); break;
+  case Instruction::SDiv: 
+  case Instruction::SRem: 
+    Result = Ty->isUnsigned(); break;
   default: break;
   }
   if (Result) {
@@ -950,6 +965,7 @@ void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
       // for most instructions, it doesn't matter
       break; 
     case Instruction::UDiv:
+    case Instruction::URem:
       // For UDiv to have unsigned operands
       if (OpTy->isSigned()) {
         OpTy = OpTy->getUnsignedVersion();
@@ -957,6 +973,7 @@ void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
       }
       break;
     case Instruction::SDiv:
+    case Instruction::SRem:
       if (OpTy->isUnsigned()) {
         OpTy = OpTy->getSignedVersion();
         shouldCast = true;
@@ -1774,8 +1791,7 @@ void CWriter::visitBinaryOperator(Instruction &I) {
     Out << "-(";
     writeOperand(BinaryOperator::getNegArgument(cast<BinaryOperator>(&I)));
     Out << ")";
-  } else if (I.getOpcode() == Instruction::Rem && 
-             I.getType()->isFloatingPoint()) {
+  } else if (I.getOpcode() == Instruction::FRem) {
     // Output a call to fmod/fmodf instead of emitting a%b
     if (I.getType() == Type::FloatTy)
       Out << "fmodf(";
@@ -1800,10 +1816,12 @@ void CWriter::visitBinaryOperator(Instruction &I) {
     case Instruction::Add: Out << " + "; break;
     case Instruction::Sub: Out << " - "; break;
     case Instruction::Mul: Out << '*'; break;
+    case Instruction::URem:
+    case Instruction::SRem:
+    case Instruction::FRem: Out << '%'; break;
     case Instruction::UDiv:
     case Instruction::SDiv: 
     case Instruction::FDiv: Out << '/'; break;
-    case Instruction::Rem: Out << '%'; break;
     case Instruction::And: Out << " & "; break;
     case Instruction::Or: Out << " | "; break;
     case Instruction::Xor: Out << " ^ "; break;
index 52262f46c6b3d4a0ec30793681251b177012aa1f..d3a625b8bc113cd2f527b56f9cd5eb13ede0b7f2 100644 (file)
@@ -131,12 +131,16 @@ namespace {
     Instruction *visitAdd(BinaryOperator &I);
     Instruction *visitSub(BinaryOperator &I);
     Instruction *visitMul(BinaryOperator &I);
+    Instruction *visitURem(BinaryOperator &I);
+    Instruction *visitSRem(BinaryOperator &I);
+    Instruction *visitFRem(BinaryOperator &I);
+    Instruction *commonRemTransforms(BinaryOperator &I);
+    Instruction *commonIRemTransforms(BinaryOperator &I);
     Instruction *commonDivTransforms(BinaryOperator &I);
     Instruction *commonIDivTransforms(BinaryOperator &I);
     Instruction *visitUDiv(BinaryOperator &I);
     Instruction *visitSDiv(BinaryOperator &I);
     Instruction *visitFDiv(BinaryOperator &I);
-    Instruction *visitRem(BinaryOperator &I);
     Instruction *visitAnd(BinaryOperator &I);
     Instruction *visitOr (BinaryOperator &I);
     Instruction *visitXor(BinaryOperator &I);
@@ -2412,9 +2416,13 @@ static Constant *GetFactor(Value *V) {
   return Result;
 }
 
-Instruction *InstCombiner::visitRem(BinaryOperator &I) {
+/// This function implements the transforms on rem instructions that work
+/// regardless of the kind of rem instruction it is (urem, srem, or frem). It 
+/// is used by the visitors to those instructions.
+/// @brief Transforms common to all three rem instructions
+Instruction *InstCombiner::commonRemTransforms(BinaryOperator &I) {
   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
-  
+
   // 0 % X == 0, we don't need to preserve faults!
   if (Constant *LHS = dyn_cast<Constant>(Op0))
     if (LHS->isNullValue())
@@ -2424,34 +2432,52 @@ Instruction *InstCombiner::visitRem(BinaryOperator &I) {
     return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
   if (isa<UndefValue>(Op1))
     return ReplaceInstUsesWith(I, Op1);  // X % undef -> undef
-  
-  if (I.getType()->isSigned()) {
-    if (Value *RHSNeg = dyn_castNegVal(Op1))
-      if (!isa<ConstantInt>(RHSNeg) || !RHSNeg->getType()->isSigned() ||
-          cast<ConstantInt>(RHSNeg)->getSExtValue() > 0) {
-        // X % -Y -> X % Y
-        AddUsesToWorkList(I);
-        I.setOperand(1, RHSNeg);
+
+  // Handle cases involving: rem X, (select Cond, Y, Z)
+  if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) {
+    // rem X, (Cond ? 0 : Y) -> rem X, Y.  If the rem and the select are in
+    // the same basic block, then we replace the select with Y, and the
+    // condition of the select with false (if the cond value is in the same
+    // BB).  If the select has uses other than the div, this allows them to be
+    // simplified also.
+    if (Constant *ST = dyn_cast<Constant>(SI->getOperand(1)))
+      if (ST->isNullValue()) {
+        Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0));
+        if (CondI && CondI->getParent() == I.getParent())
+          UpdateValueUsesWith(CondI, ConstantBool::getFalse());
+        else if (I.getParent() != SI->getParent() || SI->hasOneUse())
+          I.setOperand(1, SI->getOperand(2));
+        else
+          UpdateValueUsesWith(SI, SI->getOperand(2));
+        return &I;
+      }
+    // Likewise for: rem X, (Cond ? Y : 0) -> rem X, Y
+    if (Constant *ST = dyn_cast<Constant>(SI->getOperand(2)))
+      if (ST->isNullValue()) {
+        Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0));
+        if (CondI && CondI->getParent() == I.getParent())
+          UpdateValueUsesWith(CondI, ConstantBool::getTrue());
+        else if (I.getParent() != SI->getParent() || SI->hasOneUse())
+          I.setOperand(1, SI->getOperand(1));
+        else
+          UpdateValueUsesWith(SI, SI->getOperand(1));
         return &I;
       }
-   
-    // If the top bits of both operands are zero (i.e. we can prove they are
-    // unsigned inputs), turn this into a urem.
-    uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1);
-    if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) {
-      const Type *NTy = Op0->getType()->getUnsignedVersion();
-      Value *LHS = InsertCastBefore(Op0, NTy, I);
-      Value *RHS;
-      if (Constant *R = dyn_cast<Constant>(Op1))
-        RHS = ConstantExpr::getCast(R, NTy);
-      else
-        RHS = InsertCastBefore(Op1, NTy, I);
-      Instruction *Rem = BinaryOperator::createRem(LHS, RHS, I.getName());
-      InsertNewInstBefore(Rem, I);
-      return new CastInst(Rem, I.getType());
-    }
   }
 
+  return 0;
+}
+
+/// This function implements the transforms common to both integer remainder
+/// instructions (urem and srem). It is called by the visitors to those integer
+/// remainder instructions.
+/// @brief Common integer remainder transforms
+Instruction *InstCombiner::commonIRemTransforms(BinaryOperator &I) {
+  Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+  if (Instruction *common = commonRemTransforms(I))
+    return common;
+
   if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
     // X % 0 == undef, we don't need to preserve faults!
     if (RHS->equalsInt(0))
@@ -2460,13 +2486,6 @@ Instruction *InstCombiner::visitRem(BinaryOperator &I) {
     if (RHS->equalsInt(1))  // X % 1 == 0
       return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
 
-    // Check to see if this is an unsigned remainder with an exact power of 2,
-    // if so, convert to a bitwise and.
-    if (ConstantInt *C = dyn_cast<ConstantInt>(RHS))
-      if (RHS->getType()->isUnsigned())
-        if (isPowerOf2_64(C->getZExtValue()))
-          return BinaryOperator::createAnd(Op0, SubOne(C));
-
     if (Instruction *Op0I = dyn_cast<Instruction>(Op0)) {
       if (SelectInst *SI = dyn_cast<SelectInst>(Op0I)) {
         if (Instruction *R = FoldOpIntoSelect(I, SI, this))
@@ -2475,19 +2494,34 @@ Instruction *InstCombiner::visitRem(BinaryOperator &I) {
         if (Instruction *NV = FoldOpIntoPhi(I))
           return NV;
       }
-      
-      // X*C1%C2 --> 0  iff  C1%C2 == 0
-      if (ConstantExpr::getRem(GetFactor(Op0I), RHS)->isNullValue())
+      // (X * C1) % C2 --> 0  iff  C1 % C2 == 0
+      if (ConstantExpr::getSRem(GetFactor(Op0I), RHS)->isNullValue())
         return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
     }
   }
 
+  return 0;
+}
+
+Instruction *InstCombiner::visitURem(BinaryOperator &I) {
+  Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+  if (Instruction *common = commonIRemTransforms(I))
+    return common;
+  
+  if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
+    // X urem C^2 -> X and C
+    // Check to see if this is an unsigned remainder with an exact power of 2,
+    // if so, convert to a bitwise and.
+    if (ConstantInt *C = dyn_cast<ConstantInt>(RHS))
+      if (isPowerOf2_64(C->getZExtValue()))
+        return BinaryOperator::createAnd(Op0, SubOne(C));
+  }
+
   if (Instruction *RHSI = dyn_cast<Instruction>(I.getOperand(1))) {
-    // Turn A % (C << N), where C is 2^k, into A & ((C << N)-1) [urem only].
-    if (I.getType()->isUnsigned() && 
-        RHSI->getOpcode() == Instruction::Shl &&
-        isa<ConstantInt>(RHSI->getOperand(0)) && 
-        RHSI->getOperand(0)->getType()->isUnsigned()) {
+    // Turn A % (C << N), where C is 2^k, into A & ((C << N)-1)  
+    if (RHSI->getOpcode() == Instruction::Shl &&
+        isa<ConstantInt>(RHSI->getOperand(0))) {
       unsigned C1 = cast<ConstantInt>(RHSI->getOperand(0))->getZExtValue();
       if (isPowerOf2_64(C1)) {
         Constant *N1 = ConstantInt::getAllOnesValue(I.getType());
@@ -2496,61 +2530,60 @@ Instruction *InstCombiner::visitRem(BinaryOperator &I) {
         return BinaryOperator::createAnd(Op0, Add);
       }
     }
-    
-    // If this is 'urem X, (Cond ? C1, C2)' where C1&C2 are powers of two,
-    // transform this into: '(Cond ? (urem X, C1) : (urem X, C2))'.
-    if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) {
-      // rem X, (Cond ? 0 : Y) -> rem X, Y.  If the rem and the select are in
-      // the same basic block, then we replace the select with Y, and the
-      // condition of the select with false (if the cond value is in the same
-      // BB).  If the select has uses other than the div, this allows them to be
-      // simplified also.
-      if (Constant *ST = dyn_cast<Constant>(SI->getOperand(1)))
-        if (ST->isNullValue()) {
-          Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0));
-          if (CondI && CondI->getParent() == I.getParent())
-            UpdateValueUsesWith(CondI, ConstantBool::getFalse());
-          else if (I.getParent() != SI->getParent() || SI->hasOneUse())
-            I.setOperand(1, SI->getOperand(2));
-          else
-            UpdateValueUsesWith(SI, SI->getOperand(2));
-          return &I;
-        }
-      // Likewise for: rem X, (Cond ? Y : 0) -> rem X, Y
-      if (Constant *ST = dyn_cast<Constant>(SI->getOperand(2)))
-        if (ST->isNullValue()) {
-          Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0));
-          if (CondI && CondI->getParent() == I.getParent())
-            UpdateValueUsesWith(CondI, ConstantBool::getTrue());
-          else if (I.getParent() != SI->getParent() || SI->hasOneUse())
-            I.setOperand(1, SI->getOperand(1));
-          else
-            UpdateValueUsesWith(SI, SI->getOperand(1));
-          return &I;
+  }
+
+  // urem X, (select Cond, 2^C1, 2^C2) --> select Cond, (and X, C1), (and X, C2)
+  // where C1&C2 are powers of two.
+  if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) {
+    if (ConstantInt *STO = dyn_cast<ConstantInt>(SI->getOperand(1)))
+      if (ConstantInt *SFO = dyn_cast<ConstantInt>(SI->getOperand(2))) {
+        // STO == 0 and SFO == 0 handled above.
+        if (isPowerOf2_64(STO->getZExtValue()) && 
+            isPowerOf2_64(SFO->getZExtValue())) {
+          Value *TrueAnd = InsertNewInstBefore(
+            BinaryOperator::createAnd(Op0, SubOne(STO), SI->getName()+".t"), I);
+          Value *FalseAnd = InsertNewInstBefore(
+            BinaryOperator::createAnd(Op0, SubOne(SFO), SI->getName()+".f"), I);
+          return new SelectInst(SI->getOperand(0), TrueAnd, FalseAnd);
         }
+      }
+  }
+  
+  return 0;
+}
 
-      
-      if (ConstantInt *STO = dyn_cast<ConstantInt>(SI->getOperand(1)))
-        if (ConstantInt *SFO = dyn_cast<ConstantInt>(SI->getOperand(2))) 
-          if (STO->getType()->isUnsigned() && SFO->getType()->isUnsigned()) {
-            // STO == 0 and SFO == 0 handled above.
-            if (isPowerOf2_64(STO->getZExtValue()) && 
-                isPowerOf2_64(SFO->getZExtValue())) {
-              Value *TrueAnd = InsertNewInstBefore(
-                BinaryOperator::createAnd(Op0, SubOne(STO), SI->getName()+".t"),
-                  I);
-              Value *FalseAnd = InsertNewInstBefore(
-                BinaryOperator::createAnd(Op0, SubOne(SFO), SI->getName()+".f"),
-                  I);
-              return new SelectInst(SI->getOperand(0), TrueAnd, FalseAnd);
-            }
-          }
+Instruction *InstCombiner::visitSRem(BinaryOperator &I) {
+  Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+  if (Instruction *common = commonIRemTransforms(I))
+    return common;
+  
+  if (Value *RHSNeg = dyn_castNegVal(Op1))
+    if (!isa<ConstantInt>(RHSNeg) || 
+        cast<ConstantInt>(RHSNeg)->getSExtValue() > 0) {
+      // X % -Y -> X % Y
+      AddUsesToWorkList(I);
+      I.setOperand(1, RHSNeg);
+      return &I;
     }
+  // If the top bits of both operands are zero (i.e. we can prove they are
+  // unsigned inputs), turn this into a urem.
+  uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1);
+  if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) {
+    // X srem Y -> X urem Y, iff X and Y don't have sign bit set
+    return BinaryOperator::createURem(Op0, Op1, I.getName());
   }
-  
+
   return 0;
 }
 
+Instruction *InstCombiner::visitFRem(BinaryOperator &I) {
+  Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+  return commonRemTransforms(I);
+}
+
 // isMaxValueMinusOne - return true if this is Max-1
 static bool isMaxValueMinusOne(const ConstantInt *C) {
   if (C->getType()->isUnsigned()) 
@@ -4568,40 +4601,16 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
       // the second operand is a constant, simplify a bit.
       if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Op0)) {
         switch (BO->getOpcode()) {
-#if 0
         case Instruction::SRem:
           // If we have a signed (X % (2^c)) == 0, turn it into an unsigned one.
           if (CI->isNullValue() && isa<ConstantInt>(BO->getOperand(1)) &&
               BO->hasOneUse()) {
             int64_t V = cast<ConstantInt>(BO->getOperand(1))->getSExtValue();
             if (V > 1 && isPowerOf2_64(V)) {
-              Value *NewRem = InsertNewInstBefore(
-                  BinaryOperator::createURem(BO->getOperand(0), 
-                                             BO->getOperand(1),
-                                             BO->getName()), I);
-              return BinaryOperator::create(
-                I.getOpcode(), NewRem, 
-                Constant::getNullValue(NewRem->getType()));
-            }
-          }
-          break;
-#endif
-
-        case Instruction::Rem:
-          // If we have a signed (X % (2^c)) == 0, turn it into an unsigned one.
-          if (CI->isNullValue() && isa<ConstantInt>(BO->getOperand(1)) &&
-              BO->hasOneUse() && BO->getOperand(1)->getType()->isSigned()) {
-            int64_t V = cast<ConstantInt>(BO->getOperand(1))->getSExtValue();
-            if (V > 1 && isPowerOf2_64(V)) {
-              unsigned L2 = Log2_64(V);
-              const Type *UTy = BO->getType()->getUnsignedVersion();
-              Value *NewX = InsertNewInstBefore(new CastInst(BO->getOperand(0),
-                                                             UTy, "tmp"), I);
-              Constant *RHSCst = ConstantInt::get(UTy, 1ULL << L2);
-              Value *NewRem =InsertNewInstBefore(BinaryOperator::createRem(NewX,
-                                                    RHSCst, BO->getName()), I);
+              Value *NewRem = InsertNewInstBefore(BinaryOperator::createURem(
+                  BO->getOperand(0), BO->getOperand(1), BO->getName()), I);
               return BinaryOperator::create(I.getOpcode(), NewRem,
-                                            Constant::getNullValue(UTy));
+                Constant::getNullValue(BO->getType()));
             }
           }
           break;
@@ -5766,6 +5775,8 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) {
         break;
       case Instruction::SDiv:
       case Instruction::UDiv:
+      case Instruction::SRem:
+      case Instruction::URem:
         // If we are just changing the sign, rewrite.
         if (DestBitSize == SrcBitSize) {
           // Don't insert two casts if they cannot be eliminated.  We allow two
index c4ffa4e990e42ee92a2a487d00d3c4a21e7b591f..b47afbd605148e465ff47bcc04a2df27a5bd8a41 100644 (file)
@@ -788,10 +788,12 @@ void PredicateSimplifier::Forwards::visitBinaryOperator(BinaryOperator &BO) {
   Instruction::BinaryOps ops = BO.getOpcode();
 
   switch (ops) {
+    case Instruction::URem:
+    case Instruction::SRem:
     case Instruction::UDiv:
     case Instruction::SDiv:
     case Instruction::FDiv:
-    case Instruction::Rem: {
+    case Instruction::FRem: {
       Value *Divisor = BO.getOperand(1);
       KP.addNotEqual(Constant::getNullValue(Divisor->getType()), Divisor);
       break;
index 7d710850f9df61a0e286bb31f4886958a6debd51..2df52ae0efe9d29f3431206919767fde1eecac16 100644 (file)
@@ -116,7 +116,9 @@ static bool isUnmovableInstruction(Instruction *I) {
       I->getOpcode() == Instruction::UDiv || 
       I->getOpcode() == Instruction::SDiv ||
       I->getOpcode() == Instruction::FDiv ||
-      I->getOpcode() == Instruction::Rem)
+      I->getOpcode() == Instruction::URem ||
+      I->getOpcode() == Instruction::SRem ||
+      I->getOpcode() == Instruction::FRem)
     return true;
   return false;
 }
index 2589739d52df0ead30d398f6dedb6d48da804c48..7d55f7ed4d8ea717b17413605ae160b514481f05 100644 (file)
@@ -40,10 +40,12 @@ namespace {
     virtual Constant *add(const Constant *V1, const Constant *V2) const = 0;
     virtual Constant *sub(const Constant *V1, const Constant *V2) const = 0;
     virtual Constant *mul(const Constant *V1, const Constant *V2) const = 0;
+    virtual Constant *urem(const Constant *V1, const Constant *V2) const = 0;
+    virtual Constant *srem(const Constant *V1, const Constant *V2) const = 0;
+    virtual Constant *frem(const Constant *V1, const Constant *V2) const = 0;
     virtual Constant *udiv(const Constant *V1, const Constant *V2) const = 0;
     virtual Constant *sdiv(const Constant *V1, const Constant *V2) const = 0;
     virtual Constant *fdiv(const Constant *V1, const Constant *V2) const = 0;
-    virtual Constant *rem(const Constant *V1, const Constant *V2) const = 0;
     virtual Constant *op_and(const Constant *V1, const Constant *V2) const = 0;
     virtual Constant *op_or (const Constant *V1, const Constant *V2) const = 0;
     virtual Constant *op_xor(const Constant *V1, const Constant *V2) const = 0;
@@ -117,8 +119,14 @@ class VISIBILITY_HIDDEN TemplateRules : public ConstRules {
   virtual Constant *fdiv(const Constant *V1, const Constant *V2) const {
     return SubClassName::FDiv((const ArgType *)V1, (const ArgType *)V2);
   }
-  virtual Constant *rem(const Constant *V1, const Constant *V2) const {
-    return SubClassName::Rem((const ArgType *)V1, (const ArgType *)V2);
+  virtual Constant *urem(const Constant *V1, const Constant *V2) const {
+    return SubClassName::URem((const ArgType *)V1, (const ArgType *)V2);
+  }
+  virtual Constant *srem(const Constant *V1, const Constant *V2) const {
+    return SubClassName::SRem((const ArgType *)V1, (const ArgType *)V2);
+  }
+  virtual Constant *frem(const Constant *V1, const Constant *V2) const {
+    return SubClassName::FRem((const ArgType *)V1, (const ArgType *)V2);
   }
   virtual Constant *op_and(const Constant *V1, const Constant *V2) const {
     return SubClassName::And((const ArgType *)V1, (const ArgType *)V2);
@@ -192,7 +200,9 @@ class VISIBILITY_HIDDEN TemplateRules : public ConstRules {
   static Constant *SDiv(const ArgType *V1, const ArgType *V2) { return 0; }
   static Constant *UDiv(const ArgType *V1, const ArgType *V2) { return 0; }
   static Constant *FDiv(const ArgType *V1, const ArgType *V2) { return 0; }
-  static Constant *Rem (const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *URem(const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *SRem(const ArgType *V1, const ArgType *V2) { return 0; }
+  static Constant *FRem(const ArgType *V1, const ArgType *V2) { return 0; }
   static Constant *And (const ArgType *V1, const ArgType *V2) { return 0; }
   static Constant *Or  (const ArgType *V1, const ArgType *V2) { return 0; }
   static Constant *Xor (const ArgType *V1, const ArgType *V2) { return 0; }
@@ -392,8 +402,14 @@ struct VISIBILITY_HIDDEN ConstantPackedRules
   static Constant *FDiv(const ConstantPacked *V1, const ConstantPacked *V2) {
     return EvalVectorOp(V1, V2, ConstantExpr::getFDiv);
   }
-  static Constant *Rem(const ConstantPacked *V1, const ConstantPacked *V2) {
-    return EvalVectorOp(V1, V2, ConstantExpr::getRem);
+  static Constant *URem(const ConstantPacked *V1, const ConstantPacked *V2) {
+    return EvalVectorOp(V1, V2, ConstantExpr::getURem);
+  }
+  static Constant *SRem(const ConstantPacked *V1, const ConstantPacked *V2) {
+    return EvalVectorOp(V1, V2, ConstantExpr::getSRem);
+  }
+  static Constant *FRem(const ConstantPacked *V1, const ConstantPacked *V2) {
+    return EvalVectorOp(V1, V2, ConstantExpr::getFRem);
   }
   static Constant *And(const ConstantPacked *V1, const ConstantPacked *V2) {
     return EvalVectorOp(V1, V2, ConstantExpr::getAnd);
@@ -510,30 +526,36 @@ struct VISIBILITY_HIDDEN DirectIntRules
 #undef DEF_CAST
 
   static Constant *UDiv(const ConstantInt *V1, const ConstantInt *V2) {
-    if (V2->isNullValue()) 
+    if (V2->isNullValue())                   // X / 0
       return 0;
     BuiltinType R = (BuiltinType)(V1->getZExtValue() / V2->getZExtValue());
     return ConstantInt::get(*Ty, R);
   }
 
   static Constant *SDiv(const ConstantInt *V1, const ConstantInt *V2) {
-    if (V2->isNullValue()) 
+    if (V2->isNullValue())                   // X / 0
       return 0;
     if (V2->isAllOnesValue() &&              // MIN_INT / -1
         (BuiltinType)V1->getSExtValue() == -(BuiltinType)V1->getSExtValue())
       return 0;
-    BuiltinType R = 
-      (BuiltinType)(V1->getSExtValue() / V2->getSExtValue());
+    BuiltinType R = (BuiltinType)(V1->getSExtValue() / V2->getSExtValue());
     return ConstantInt::get(*Ty, R);
   }
 
-  static Constant *Rem(const ConstantInt *V1, const ConstantInt *V2) {
+  static Constant *URem(const ConstantInt *V1,
+                        const ConstantInt *V2) {
     if (V2->isNullValue()) return 0;         // X / 0
-    if (V2->isAllOnesValue() &&              // MIN_INT / -1
-        (BuiltinType)V1->getZExtValue() == -(BuiltinType)V1->getZExtValue())
+    BuiltinType R = (BuiltinType)(V1->getZExtValue() % V2->getZExtValue());
+    return ConstantInt::get(*Ty, R);
+  }
+
+  static Constant *SRem(const ConstantInt *V1,
+                        const ConstantInt *V2) {
+    if (V2->isNullValue()) return 0;         // X % 0
+    if (V2->isAllOnesValue() &&              // MIN_INT % -1
+        (BuiltinType)V1->getSExtValue() == -(BuiltinType)V1->getSExtValue())
       return 0;
-    BuiltinType R = 
-      (BuiltinType)V1->getZExtValue() % (BuiltinType)V2->getZExtValue();
+    BuiltinType R = (BuiltinType)(V1->getSExtValue() % V2->getSExtValue());
     return ConstantInt::get(*Ty, R);
   }
 
@@ -632,7 +654,7 @@ struct VISIBILITY_HIDDEN DirectFPRules
   DEF_CAST(Double, ConstantFP , double)
 #undef DEF_CAST
 
-  static Constant *Rem(const ConstantFP *V1, const ConstantFP *V2) {
+  static Constant *FRem(const ConstantFP *V1, const ConstantFP *V2) {
     if (V2->isNullValue()) return 0;
     BuiltinType Result = std::fmod((BuiltinType)V1->getValue(),
                                    (BuiltinType)V2->getValue());
@@ -1250,7 +1272,9 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
   case Instruction::UDiv:    C = ConstRules::get(V1, V2).udiv(V1, V2); break;
   case Instruction::SDiv:    C = ConstRules::get(V1, V2).sdiv(V1, V2); break;
   case Instruction::FDiv:    C = ConstRules::get(V1, V2).fdiv(V1, V2); break;
-  case Instruction::Rem:     C = ConstRules::get(V1, V2).rem(V1, V2); break;
+  case Instruction::URem:    C = ConstRules::get(V1, V2).urem(V1, V2); break;
+  case Instruction::SRem:    C = ConstRules::get(V1, V2).srem(V1, V2); break;
+  case Instruction::FRem:    C = ConstRules::get(V1, V2).frem(V1, V2); break;
   case Instruction::And:     C = ConstRules::get(V1, V2).op_and(V1, V2); break;
   case Instruction::Or:      C = ConstRules::get(V1, V2).op_or (V1, V2); break;
   case Instruction::Xor:     C = ConstRules::get(V1, V2).op_xor(V1, V2); break;
@@ -1335,25 +1359,26 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
     case Instruction::UDiv:
     case Instruction::SDiv:
     case Instruction::FDiv:
-    case Instruction::Rem:
-      if (!isa<UndefValue>(V2))     // undef/X -> 0
+    case Instruction::URem:
+    case Instruction::SRem:
+    case Instruction::FRem:
+      if (!isa<UndefValue>(V2))                    // undef / X -> 0
         return Constant::getNullValue(V1->getType());
-      return const_cast<Constant*>(V2);                // X/undef -> undef
-    case Instruction::Or:           // X|undef -> -1
+      return const_cast<Constant*>(V2);            // X / undef -> undef
+    case Instruction::Or:                          // X | undef -> -1
       return ConstantInt::getAllOnesValue(V1->getType());
     case Instruction::Shr:
-      if (!isa<UndefValue>(V2)) {
+      if (!isa<UndefValue>(V2)) {      
         if (V1->getType()->isSigned())
-          return const_cast<Constant*>(V1);  // undef >>s X -> undef
+          return const_cast<Constant*>(V1);        // undef >>s X -> undef
         // undef >>u X -> 0
       } else if (isa<UndefValue>(V1)) {
-        return const_cast<Constant*>(V1);   //  undef >> undef -> undef
+        return const_cast<Constant*>(V1);          // undef >> undef -> undef
       } else {
         if (V1->getType()->isSigned())
-          return const_cast<Constant*>(V1);  // X >>s undef -> X
-        // X >>u undef -> 0
+          return const_cast<Constant*>(V1);        // X >>s undef -> X
       }
-      return Constant::getNullValue(V1->getType());
+      return Constant::getNullValue(V1->getType());// X >>u undef -> 0
 
     case Instruction::Shl:
       // undef << X -> 0   X << undef -> 0
@@ -1366,10 +1391,6 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
       // There are many possible foldings we could do here.  We should probably
       // at least fold add of a pointer with an integer into the appropriate
       // getelementptr.  This will improve alias analysis a bit.
-
-
-
-
     } else {
       // Just implement a couple of simple identities.
       switch (Opcode) {
@@ -1391,10 +1412,11 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
           if (CI->getZExtValue() == 1)
             return const_cast<Constant*>(V1);                     // X / 1 == X
         break;
-      case Instruction::Rem:
+      case Instruction::URem:
+      case Instruction::SRem:
         if (const ConstantInt *CI = dyn_cast<ConstantInt>(V2))
           if (CI->getZExtValue() == 1)
-            return Constant::getNullValue(CI->getType()); // X % 1 == 0
+            return Constant::getNullValue(CI->getType());         // X % 1 == 0
         break;
       case Instruction::And:
         if (cast<ConstantIntegral>(V2)->isAllOnesValue())
@@ -1450,7 +1472,9 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
     case Instruction::SDiv:
     case Instruction::UDiv:
     case Instruction::FDiv:
-    case Instruction::Rem:
+    case Instruction::URem:
+    case Instruction::SRem:
+    case Instruction::FRem:
     default:  // These instructions cannot be flopped around.
       break;
     }
index 9c92b90778382b8ab17097b71bd5c18017b471e5..bcfd3879dbe0ceb2e9f21cd2bdce2a94f95b9507 100644 (file)
@@ -78,7 +78,9 @@ bool Constant::canTrap() const {
   case Instruction::UDiv:
   case Instruction::SDiv:
   case Instruction::FDiv:
-  case Instruction::Rem:
+  case Instruction::URem:
+  case Instruction::SRem:
+  case Instruction::FRem:
     // Div and rem can trap if the RHS is not known to be non-zero.
     if (!isa<ConstantInt>(getOperand(1)) || getOperand(1)->isNullValue())
       return true;
@@ -457,8 +459,14 @@ Constant *ConstantExpr::getSDiv(Constant *C1, Constant *C2) {
 Constant *ConstantExpr::getFDiv(Constant *C1, Constant *C2) {
   return get(Instruction::FDiv, C1, C2);
 }
-Constant *ConstantExpr::getRem(Constant *C1, Constant *C2) {
-  return get(Instruction::Rem, C1, C2);
+Constant *ConstantExpr::getURem(Constant *C1, Constant *C2) {
+  return get(Instruction::URem, C1, C2);
+}
+Constant *ConstantExpr::getSRem(Constant *C1, Constant *C2) {
+  return get(Instruction::SRem, C1, C2);
+}
+Constant *ConstantExpr::getFRem(Constant *C1, Constant *C2) {
+  return get(Instruction::FRem, C1, C2);
 }
 Constant *ConstantExpr::getAnd(Constant *C1, Constant *C2) {
   return get(Instruction::And, C1, C2);
@@ -1362,7 +1370,7 @@ namespace llvm {
         break;
       default:
         assert(OldC->getOpcode() >= Instruction::BinaryOpsBegin &&
-               OldC->getOpcode() < Instruction::BinaryOpsEnd);
+               OldC->getOpcode() <  Instruction::BinaryOpsEnd);
         New = ConstantExpr::getTy(NewTy, OldC->getOpcode(), OldC->getOperand(0),
                                   OldC->getOperand(1));
         break;
@@ -1448,8 +1456,8 @@ Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode,
   if (Opcode == Instruction::Shl || Opcode == Instruction::Shr)
     return getShiftTy(ReqTy, Opcode, C1, C2);
   // Check the operands for consistency first
-  assert((Opcode >= Instruction::BinaryOpsBegin &&
-          Opcode < Instruction::BinaryOpsEnd) &&
+  assert(Opcode >= Instruction::BinaryOpsBegin &&
+         Opcode <  Instruction::BinaryOpsEnd   &&
          "Invalid opcode in binary constant expression");
   assert(C1->getType() == C2->getType() &&
          "Operand types in binary constant expression should match");
@@ -1467,15 +1475,14 @@ Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode,
 Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
 #ifndef NDEBUG
   switch (Opcode) {
-  case Instruction::Add: case Instruction::Sub:
+  case Instruction::Add: 
+  case Instruction::Sub:
   case Instruction::Mul: 
-  case Instruction::Rem:
     assert(C1->getType() == C2->getType() && "Op types should be identical!");
     assert((C1->getType()->isInteger() || C1->getType()->isFloatingPoint() ||
             isa<PackedType>(C1->getType())) &&
            "Tried to create an arithmetic operation on a non-arithmetic type!");
     break;
-
   case Instruction::UDiv: 
   case Instruction::SDiv: 
     assert(C1->getType() == C2->getType() && "Op types should be identical!");
@@ -1489,6 +1496,19 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
       && cast<PackedType>(C1->getType())->getElementType()->isFloatingPoint())) 
       && "Tried to create an arithmetic operation on a non-arithmetic type!");
     break;
+  case Instruction::URem: 
+  case Instruction::SRem: 
+    assert(C1->getType() == C2->getType() && "Op types should be identical!");
+    assert((C1->getType()->isInteger() || (isa<PackedType>(C1->getType()) &&
+      cast<PackedType>(C1->getType())->getElementType()->isInteger())) &&
+           "Tried to create an arithmetic operation on a non-arithmetic type!");
+    break;
+  case Instruction::FRem:
+    assert(C1->getType() == C2->getType() && "Op types should be identical!");
+    assert((C1->getType()->isFloatingPoint() || (isa<PackedType>(C1->getType())
+      && cast<PackedType>(C1->getType())->getElementType()->isFloatingPoint())) 
+      && "Tried to create an arithmetic operation on a non-arithmetic type!");
+    break;
   case Instruction::And:
   case Instruction::Or:
   case Instruction::Xor:
index 9b5fa714ea0ee8c1d41c17dde0db1542885ec60d..355c508b6a6ff908874e0b18e2cc6d9c8285c00a 100644 (file)
@@ -97,7 +97,9 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
   case UDiv: return "udiv";
   case SDiv: return "sdiv";
   case FDiv: return "fdiv";
-  case Rem: return "rem";
+  case URem: return "urem";
+  case SRem: return "srem";
+  case FRem: return "frem";
 
   // Logical operators...
   case And: return "and";
@@ -227,7 +229,9 @@ bool Instruction::isTrapping(unsigned op) {
   case UDiv:
   case SDiv:
   case FDiv:
-  case Rem:
+  case URem:
+  case SRem:
+  case FRem:
   case Load:
   case Store:
   case Call:
index 790f6ac8a65d443a589dfe94d7611d7ccade47bd..3825d857634cd67ee3c13f6fb3633140c629d7e5 100644 (file)
@@ -1023,7 +1023,6 @@ void BinaryOperator::init(BinaryOps iType)
   switch (iType) {
   case Add: case Sub:
   case Mul: 
-  case Rem:
     assert(getType() == LHS->getType() &&
            "Arithmetic operation should return same type as operands!");
     assert((getType()->isInteger() || getType()->isFloatingPoint() ||
@@ -1045,7 +1044,21 @@ void BinaryOperator::init(BinaryOps iType)
             cast<PackedType>(getType())->getElementType()->isFloatingPoint())) 
             && "Incorrect operand type (not floating point) for FDIV");
     break;
-
+  case URem: 
+  case SRem: 
+    assert(getType() == LHS->getType() &&
+           "Arithmetic operation should return same type as operands!");
+    assert((getType()->isInteger() || (isa<PackedType>(getType()) && 
+            cast<PackedType>(getType())->getElementType()->isInteger())) &&
+           "Incorrect operand type (not integer) for S/UREM");
+    break;
+  case FRem:
+    assert(getType() == LHS->getType() &&
+           "Arithmetic operation should return same type as operands!");
+    assert((getType()->isFloatingPoint() || (isa<PackedType>(getType()) &&
+            cast<PackedType>(getType())->getElementType()->isFloatingPoint())) 
+            && "Incorrect operand type (not floating point) for FREM");
+    break;
   case And: case Or:
   case Xor:
     assert(getType() == LHS->getType() &&
index 583587124473130b07b0d5814396b5a2f7456d67..649c4a4d6a19304d70964e8f5bc192b65b82696f 100644 (file)
@@ -1052,7 +1052,7 @@ StackerCompiler::handle_word( int tkn )
         LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
         LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
         BinaryOperator* divop =
-            BinaryOperator::create( Instruction::Rem, op1, op2);
+            BinaryOperator::create( Instruction::SRem, op1, op2);
         bb->getInstList().push_back( divop );
         push_value( bb, divop );
         break;
index 089f1cac2196ce2b9edb3193e73538d00da90bd0..f74294fb3f2d7b04dbdcb63f101eafe6ac083a89 100644 (file)
@@ -776,7 +776,9 @@ void CppWriter::printConstant(const Constant *CV) {
         case Instruction::UDiv:   Out << "getUDiv"; break;
         case Instruction::SDiv:   Out << "getSDiv"; break;
         case Instruction::FDiv:   Out << "getFDiv"; break;
-        case Instruction::Rem:    Out << "getRem"; break;
+        case Instruction::URem:   Out << "getURem"; break;
+        case Instruction::SRem:   Out << "getSRem"; break;
+        case Instruction::FRem:   Out << "getFRem"; break;
         case Instruction::And:    Out << "getAnd"; break;
         case Instruction::Or:     Out << "getOr"; break;
         case Instruction::Xor:    Out << "getXor"; break;
@@ -1026,7 +1028,9 @@ CppWriter::printInstruction(const Instruction *I, const std::string& bbname) {
     case Instruction::UDiv:
     case Instruction::SDiv:
     case Instruction::FDiv:
-    case Instruction::Rem:
+    case Instruction::URem:
+    case Instruction::SRem:
+    case Instruction::FRem:
     case Instruction::And:
     case Instruction::Or:
     case Instruction::Xor:
@@ -1040,7 +1044,9 @@ CppWriter::printInstruction(const Instruction *I, const std::string& bbname) {
         case Instruction::UDiv:Out << "Instruction::UDiv"; break;
         case Instruction::SDiv:Out << "Instruction::SDiv"; break;
         case Instruction::FDiv:Out << "Instruction::FDiv"; break;
-        case Instruction::Rem: Out << "Instruction::Rem"; break;
+        case Instruction::URem:Out << "Instruction::URem"; break;
+        case Instruction::SRem:Out << "Instruction::SRem"; break;
+        case Instruction::FRem:Out << "Instruction::FRem"; break;
         case Instruction::And: Out << "Instruction::And"; break;
         case Instruction::Or:  Out << "Instruction::Or";  break;
         case Instruction::Xor: Out << "Instruction::Xor"; break;