diff options
author | Reid Spencer <rspencer@reidspencer.com> | 2006-11-02 01:53:59 +0000 |
---|---|---|
committer | Reid Spencer <rspencer@reidspencer.com> | 2006-11-02 01:53:59 +0000 |
commit | 0a783f783ca05c961234385f5b269d4cf03dbbdb (patch) | |
tree | 70d2d2b4be7b0f5624d954fd3c482eca33c7f43e | |
parent | 0ac6757586b80d0c82a6651780dcd9b09df251b0 (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.html | 68 | ||||
-rw-r--r-- | include/llvm/Constants.h | 4 | ||||
-rw-r--r-- | include/llvm/Instruction.def | 80 | ||||
-rw-r--r-- | include/llvm/Support/PatternMatch.h | 16 | ||||
-rw-r--r-- | lib/Analysis/ScalarEvolution.cpp | 2 | ||||
-rw-r--r-- | lib/AsmParser/Lexer.l | 5 | ||||
-rw-r--r-- | lib/AsmParser/llvmAsmParser.y | 22 | ||||
-rw-r--r-- | lib/Bytecode/Reader/Reader.cpp | 21 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 12 | ||||
-rw-r--r-- | lib/ExecutionEngine/Interpreter/Execution.cpp | 62 | ||||
-rw-r--r-- | lib/Target/CBackend/CBackend.cpp | 38 | ||||
-rw-r--r-- | lib/Target/CBackend/Writer.cpp | 38 | ||||
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 245 | ||||
-rw-r--r-- | lib/Transforms/Scalar/PredicateSimplifier.cpp | 4 | ||||
-rw-r--r-- | lib/Transforms/Scalar/Reassociate.cpp | 4 | ||||
-rw-r--r-- | lib/VMCore/ConstantFold.cpp | 92 | ||||
-rw-r--r-- | lib/VMCore/Constants.cpp | 38 | ||||
-rw-r--r-- | lib/VMCore/Instruction.cpp | 8 | ||||
-rw-r--r-- | lib/VMCore/Instructions.cpp | 17 | ||||
-rw-r--r-- | projects/Stacker/lib/compiler/StackerCompiler.cpp | 2 | ||||
-rw-r--r-- | tools/llvm2cpp/CppWriter.cpp | 12 |
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> <result> = urem <ty> <var1>, <var2> <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> <result> = 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> <result> = rem <ty> <var1>, <var2> <i>; yields {ty}:result</i> +<pre> <result> = srem <ty> <var1>, <var2> <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> <result> = rem int 4, %var <i>; yields {int}:result = 4 % %var</i> +<pre> <result> = 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> <result> = frem <ty> <var1>, <var2> <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> <result> = 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 |