aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReid Spencer <rspencer@reidspencer.com>2006-11-02 01:53:59 +0000
committerReid Spencer <rspencer@reidspencer.com>2006-11-02 01:53:59 +0000
commit0a783f783ca05c961234385f5b269d4cf03dbbdb (patch)
tree70d2d2b4be7b0f5624d954fd3c482eca33c7f43e
parent0ac6757586b80d0c82a6651780dcd9b09df251b0 (diff)
For PR950:
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
-rw-r--r--docs/LangRef.html68
-rw-r--r--include/llvm/Constants.h4
-rw-r--r--include/llvm/Instruction.def80
-rw-r--r--include/llvm/Support/PatternMatch.h16
-rw-r--r--lib/Analysis/ScalarEvolution.cpp2
-rw-r--r--lib/AsmParser/Lexer.l5
-rw-r--r--lib/AsmParser/llvmAsmParser.y22
-rw-r--r--lib/Bytecode/Reader/Reader.cpp21
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp12
-rw-r--r--lib/ExecutionEngine/Interpreter/Execution.cpp62
-rw-r--r--lib/Target/CBackend/CBackend.cpp38
-rw-r--r--lib/Target/CBackend/Writer.cpp38
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp245
-rw-r--r--lib/Transforms/Scalar/PredicateSimplifier.cpp4
-rw-r--r--lib/Transforms/Scalar/Reassociate.cpp4
-rw-r--r--lib/VMCore/ConstantFold.cpp92
-rw-r--r--lib/VMCore/Constants.cpp38
-rw-r--r--lib/VMCore/Instruction.cpp8
-rw-r--r--lib/VMCore/Instructions.cpp17
-rw-r--r--projects/Stacker/lib/compiler/StackerCompiler.cpp2
-rw-r--r--tools/llvm2cpp/CppWriter.cpp12
21 files changed, 509 insertions, 281 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 0ed371a749..97b5312356 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -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>
diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h
index f5fff4d7fb..e44e07e868 100644
--- a/include/llvm/Constants.h
+++ b/include/llvm/Constants.h
@@ -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);
diff --git a/include/llvm/Instruction.def b/include/llvm/Instruction.def
index 91a467cf59..4f7f2f5483 100644
--- a/include/llvm/Instruction.def
+++ b/include/llvm/Instruction.def
@@ -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
diff --git a/include/llvm/Support/PatternMatch.h b/include/llvm/Support/PatternMatch.h
index f4c9ad5098..bee416a24e 100644
--- a/include/llvm/Support/PatternMatch.h
+++ b/include/llvm/Support/PatternMatch.h
@@ -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>
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index d555a14089..a4de55c2c3 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -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);
diff --git a/lib/AsmParser/Lexer.l b/lib/AsmParser/Lexer.l
index 96804bb75b..4df84f685e 100644
--- a/lib/AsmParser/Lexer.l
+++ b/lib/AsmParser/Lexer.l
@@ -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); }
diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y
index 684b643bba..d40b653afd 100644
--- a/lib/AsmParser/llvmAsmParser.y
+++ b/lib/AsmParser/llvmAsmParser.y
@@ -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;
diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp
index d3df471a1c..b1ec74e2d6 100644
--- a/lib/Bytecode/Reader/Reader.cpp
+++ b/lib/Bytecode/Reader/Reader.cpp
@@ -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;
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 9be3a16975..99306050c1 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -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); }
diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp
index 5a7181f83e..eec018ac01 100644
--- a/lib/ExecutionEngine/Interpreter/Execution.cpp
+++ b/lib/ExecutionEngine/Interpreter/Execution.cpp
@@ -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;
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp
index cef1ba621a..4a04e023ea 100644
--- a/lib/Target/CBackend/CBackend.cpp
+++ b/lib/Target/CBackend/CBackend.cpp
@@ -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;
diff --git a/lib/Target/CBackend/Writer.cpp b/lib/Target/CBackend/Writer.cpp
index cef1ba621a..4a04e023ea 100644
--- a/lib/Target/CBackend/Writer.cpp
+++ b/lib/Target/CBackend/Writer.cpp
@@ -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 g