From 0a783f783ca05c961234385f5b269d4cf03dbbdb Mon Sep 17 00:00:00 2001 From: Reid Spencer Date: Thu, 2 Nov 2006 01:53:59 +0000 Subject: [PATCH] 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 --- docs/LangRef.html | 68 ++++- include/llvm/Constants.h | 4 +- include/llvm/Instruction.def | 80 +++--- include/llvm/Support/PatternMatch.h | 16 +- lib/Analysis/ScalarEvolution.cpp | 2 +- lib/AsmParser/Lexer.l | 5 +- lib/AsmParser/llvmAsmParser.y | 22 +- lib/Bytecode/Reader/Reader.cpp | 21 +- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 12 +- lib/ExecutionEngine/Interpreter/Execution.cpp | 62 ++++- lib/Target/CBackend/CBackend.cpp | 38 ++- lib/Target/CBackend/Writer.cpp | 38 ++- .../Scalar/InstructionCombining.cpp | 245 +++++++++--------- lib/Transforms/Scalar/PredicateSimplifier.cpp | 4 +- lib/Transforms/Scalar/Reassociate.cpp | 4 +- lib/VMCore/ConstantFold.cpp | 92 ++++--- lib/VMCore/Constants.cpp | 38 ++- lib/VMCore/Instruction.cpp | 8 +- lib/VMCore/Instructions.cpp | 17 +- .../Stacker/lib/compiler/StackerCompiler.cpp | 2 +- tools/llvm2cpp/CppWriter.cpp | 12 +- 21 files changed, 509 insertions(+), 281 deletions(-) diff --git a/docs/LangRef.html b/docs/LangRef.html index 0ed371a749b..97b53123564 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -80,7 +80,9 @@
  • 'udiv' Instruction
  • 'sdiv' Instruction
  • 'fdiv' Instruction
  • -
  • 'rem' Instruction
  • +
  • 'urem' Instruction
  • +
  • 'srem' Instruction
  • +
  • 'frem' Instruction
  • 'setcc' Instructions
  • @@ -1699,30 +1701,72 @@ versions of the values in which case the elements must be floating point.

    -
    'rem' + +
    +
    Syntax:
    +
      <result> = urem <ty> <var1>, <var2>   ; yields {ty}:result
    +
    +
    Overview:
    +

    The 'urem' instruction returns the remainder from the +unsigned division of its two arguments.

    +
    Arguments:
    +

    The two arguments to the 'urem' instruction must be +integer values. Both arguments must have identical +types.

    +
    Semantics:
    +

    This instruction returns the unsigned integer remainder of a division. +This instruction always performs an unsigned division to get the remainder, +regardless of whether the arguments are unsigned or not.

    +
    Example:
    +
      <result> = urem uint 4, %var          ; yields {uint}:result = 4 % %var
    +
    + +
    + +
    Syntax:
    -
      <result> = rem <ty> <var1>, <var2>   ; yields {ty}:result
    +
      <result> = srem <ty> <var1>, <var2>   ; yields {ty}:result
     
    Overview:
    -

    The 'rem' instruction returns the remainder from the -division of its two operands.

    +

    The 'srem' instruction returns the remainder from the +signed division of its two operands.

    Arguments:
    -

    The two arguments to the 'rem' instruction must be either integer or floating point -values. -This instruction can also take packed versions of the values. -Both arguments must have identical types.

    +

    The two arguments to the 'srem' instruction must be +integer values. Both arguments must have identical +types.

    Semantics:
    -

    This returns the remainder of a division (where the result +

    This instruction returns the remainder of a division (where the result has the same sign as the divisor), not the modulus (where the result has the same sign as the dividend) of a value. For more information about the difference, see The Math Forum.

    Example:
    -
      <result> = rem int 4, %var          ; yields {int}:result = 4 % %var
    +
      <result> = srem int 4, %var          ; yields {int}:result = 4 % %var
    +
    + +
    + + +
    +
    Syntax:
    +
      <result> = frem <ty> <var1>, <var2>   ; yields {ty}:result
    +
    +
    Overview:
    +

    The 'frem' instruction returns the remainder from the +division of its two operands.

    +
    Arguments:
    +

    The two arguments to the 'frem' instruction must be +floating point values. Both arguments must have +identical types.

    +
    Semantics:
    +

    This instruction returns the remainder of a division.

    +
    Example:
    +
      <result> = frem float 4.0, %var          ; yields {float}:result = 4.0 % %var
     
    diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index f5fff4d7fb4..e44e07e868c 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 91a467cf590..4f7f2f54838 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 f4c9ad50987..bee416a24e7 100644 --- a/include/llvm/Support/PatternMatch.h +++ b/include/llvm/Support/PatternMatch.h @@ -130,9 +130,21 @@ inline BinaryOp_match m_FDiv(const LHS &L, } template -inline BinaryOp_match m_Rem(const LHS &L, +inline BinaryOp_match m_URem(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_SRem(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_FRem(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); + return BinaryOp_match(L, R); } template diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index d555a14089a..a4de55c2c3e 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(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 96804bb75b4..4df84f685e6 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 684b643bbac..d40b653afda 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -836,7 +836,7 @@ sanitizeOpCode(OpcodeInfo &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 &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 ArithmeticOps LogicalOps SetCondOps // Binops Subcatagories -%token ADD SUB MUL UDIV SDIV FDIV REM AND OR XOR +%token ADD SUB MUL UDIV SDIV FDIV UREM SREM FREM AND OR XOR %token 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((*$2).get())) GEN_ERROR( "Arithmetic operator requires integer, FP, or packed operands!"); - if (isa((*$2).get()) && $1.opcode == Instruction::Rem) - GEN_ERROR("Rem not supported on packed types!"); + if (isa((*$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 d3df471a1c2..b1ec74e2d6c 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 9be3a16975b..99306050c13 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 5a7181f83eb..eec018ac010 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 cef1ba621ac..4a04e023eac 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(&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 cef1ba621ac..4a04e023eac 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 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(&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/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 52262f46c6b..d3a625b8bc1 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -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(Op0)) if (LHS->isNullValue()) @@ -2424,34 +2432,52 @@ Instruction *InstCombiner::visitRem(BinaryOperator &I) { return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); if (isa(Op1)) return ReplaceInstUsesWith(I, Op1); // X % undef -> undef - - if (I.getType()->isSigned()) { - if (Value *RHSNeg = dyn_castNegVal(Op1)) - if (!isa(RHSNeg) || !RHSNeg->getType()->isSigned() || - cast(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(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(SI->getOperand(1))) + if (ST->isNullValue()) { + Instruction *CondI = dyn_cast(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(SI->getOperand(2))) + if (ST->isNullValue()) { + Instruction *CondI = dyn_cast(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(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(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(RHS)) - if (RHS->getType()->isUnsigned()) - if (isPowerOf2_64(C->getZExtValue())) - return BinaryOperator::createAnd(Op0, SubOne(C)); - if (Instruction *Op0I = dyn_cast(Op0)) { if (SelectInst *SI = dyn_cast(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(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(RHS)) + if (isPowerOf2_64(C->getZExtValue())) + return BinaryOperator::createAnd(Op0, SubOne(C)); + } + if (Instruction *RHSI = dyn_cast(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(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(RHSI->getOperand(0))) { unsigned C1 = cast(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(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(SI->getOperand(1))) - if (ST->isNullValue()) { - Instruction *CondI = dyn_cast(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(SI->getOperand(2))) - if (ST->isNullValue()) { - Instruction *CondI = dyn_cast(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(Op1)) { + if (ConstantInt *STO = dyn_cast(SI->getOperand(1))) + if (ConstantInt *SFO = dyn_cast(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(SI->getOperand(1))) - if (ConstantInt *SFO = dyn_cast(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(RHSNeg) || + cast(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(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(BO->getOperand(1)) && BO->hasOneUse()) { int64_t V = cast(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(BO->getOperand(1)) && - BO->hasOneUse() && BO->getOperand(1)->getType()->isSigned()) { - int64_t V = cast(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 diff --git a/lib/Transforms/Scalar/PredicateSimplifier.cpp b/lib/Transforms/Scalar/PredicateSimplifier.cpp index c4ffa4e990e..b47afbd6051 100644 --- a/lib/Transforms/Scalar/PredicateSimplifier.cpp +++ b/lib/Transforms/Scalar/PredicateSimplifier.cpp @@ -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; diff --git a/lib/Transforms/Scalar/Reassociate.cpp b/lib/Transforms/Scalar/Reassociate.cpp index 7d710850f9d..2df52ae0efe 100644 --- a/lib/Transforms/Scalar/Reassociate.cpp +++ b/lib/Transforms/Scalar/Reassociate.cpp @@ -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; } diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index 2589739d52d..7d55f7ed4d8 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -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(V2)) // undef/X -> 0 + case Instruction::URem: + case Instruction::SRem: + case Instruction::FRem: + if (!isa(V2)) // undef / X -> 0 return Constant::getNullValue(V1->getType()); - return const_cast(V2); // X/undef -> undef - case Instruction::Or: // X|undef -> -1 + return const_cast(V2); // X / undef -> undef + case Instruction::Or: // X | undef -> -1 return ConstantInt::getAllOnesValue(V1->getType()); case Instruction::Shr: - if (!isa(V2)) { + if (!isa(V2)) { if (V1->getType()->isSigned()) - return const_cast(V1); // undef >>s X -> undef + return const_cast(V1); // undef >>s X -> undef // undef >>u X -> 0 } else if (isa(V1)) { - return const_cast(V1); // undef >> undef -> undef + return const_cast(V1); // undef >> undef -> undef } else { if (V1->getType()->isSigned()) - return const_cast(V1); // X >>s undef -> X - // X >>u undef -> 0 + return const_cast(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(V1); // X / 1 == X break; - case Instruction::Rem: + case Instruction::URem: + case Instruction::SRem: if (const ConstantInt *CI = dyn_cast(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(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; } diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 9c92b907783..bcfd3879dbe 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -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(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(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(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(C1->getType()) && + cast(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(C1->getType()) + && cast(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: diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp index 9b5fa714ea0..355c508b6a6 100644 --- a/lib/VMCore/Instruction.cpp +++ b/lib/VMCore/Instruction.cpp @@ -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: diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 790f6ac8a65..3825d857634 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -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(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(getType()) && + cast(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(getType()) && + cast(getType())->getElementType()->isFloatingPoint())) + && "Incorrect operand type (not floating point) for FREM"); + break; case And: case Or: case Xor: assert(getType() == LHS->getType() && diff --git a/projects/Stacker/lib/compiler/StackerCompiler.cpp b/projects/Stacker/lib/compiler/StackerCompiler.cpp index 58358712447..649c4a4d6a1 100644 --- a/projects/Stacker/lib/compiler/StackerCompiler.cpp +++ b/projects/Stacker/lib/compiler/StackerCompiler.cpp @@ -1052,7 +1052,7 @@ StackerCompiler::handle_word( int tkn ) LoadInst* op1 = cast(pop_integer(bb)); LoadInst* op2 = cast(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; diff --git a/tools/llvm2cpp/CppWriter.cpp b/tools/llvm2cpp/CppWriter.cpp index 089f1cac219..f74294fb3f2 100644 --- a/tools/llvm2cpp/CppWriter.cpp +++ b/tools/llvm2cpp/CppWriter.cpp @@ -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; -- 2.34.1