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
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index d555a14..a4de55c 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -2147,7 +2147,7 @@
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 96804bb..4df84f6 100644
--- a/lib/AsmParser/Lexer.l
+++ b/lib/AsmParser/Lexer.l
@@ -261,7 +261,10 @@
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 684b643..d40b653 100644
--- a/lib/AsmParser/llvmAsmParser.y
+++ b/lib/AsmParser/llvmAsmParser.y
@@ -836,7 +836,7 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
!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 d3df471..b1ec74e 100644
--- a/lib/Bytecode/Reader/Reader.cpp
+++ b/lib/Bytecode/Reader/Reader.cpp
@@ -652,7 +652,14 @@
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 @@
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 9be3a16..9930605 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -528,16 +528,12 @@
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 5a7181f..eec018a 100644
--- a/lib/ExecutionEngine/Interpreter/Execution.cpp
+++ b/lib/ExecutionEngine/Interpreter/Execution.cpp
@@ -48,6 +48,12 @@
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 @@
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 @@
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_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);
+ 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()) {
case Type::FloatTyID:
Dest.FloatVal = fmod(Src1.FloatVal, Src2.FloatVal);
break;
@@ -544,7 +580,9 @@
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 cef1ba6..4a04e02 100644
--- a/lib/Target/CBackend/CBackend.cpp
+++ b/lib/Target/CBackend/CBackend.cpp
@@ -593,7 +593,9 @@
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 @@
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 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 @@
// 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 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 @@
// 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 @@
}
break;
case Instruction::SDiv:
+ case Instruction::SRem:
if (OpTy->isUnsigned()) {
OpTy = OpTy->getSignedVersion();
shouldCast = true;
@@ -1774,8 +1791,7 @@
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 @@
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 cef1ba6..4a04e02 100644
--- a/lib/Target/CBackend/Writer.cpp
+++ b/lib/Target/CBackend/Writer.cpp
@@ -593,7 +593,9 @@
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 @@
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 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 @@
// 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 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 @@
// 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 @@
}
break;
case Instruction::SDiv:
+ case Instruction::SRem:
if (OpTy->isUnsigned()) {
OpTy = OpTy->getSignedVersion();
shouldCast = true;
@@ -1774,8 +1791,7 @@
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 @@
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 52262f4..d3a625b 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -131,12 +131,16 @@
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 @@
return Result;
}
-Instruction *InstCombiner::visitRem(BinaryOperator &I) {
+/// This function implements the transforms on rem instructions that work
+/// regardless of the kind of rem instruction it is (urem, srem, or frem). It
+/// is used by the visitors to those instructions.
+/// @brief Transforms common to all three rem instructions
+Instruction *InstCombiner::commonRemTransforms(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
-
+
// 0 % X == 0, we don't need to preserve faults!
if (Constant *LHS = dyn_cast<Constant>(Op0))
if (LHS->isNullValue())
@@ -2424,34 +2432,52 @@
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
if (isa<UndefValue>(Op1))
return ReplaceInstUsesWith(I, Op1); // X % undef -> undef
-
- if (I.getType()->isSigned()) {
- if (Value *RHSNeg = dyn_castNegVal(Op1))
- if (!isa<ConstantInt>(RHSNeg) || !RHSNeg->getType()->isSigned() ||
- cast<ConstantInt>(RHSNeg)->getSExtValue() > 0) {
- // X % -Y -> X % Y
- AddUsesToWorkList(I);
- I.setOperand(1, RHSNeg);
+
+ // Handle cases involving: rem X, (select Cond, Y, Z)
+ if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) {
+ // rem X, (Cond ? 0 : Y) -> rem X, Y. If the rem and the select are in
+ // the same basic block, then we replace the select with Y, and the
+ // condition of the select with false (if the cond value is in the same
+ // BB). If the select has uses other than the div, this allows them to be
+ // simplified also.
+ if (Constant *ST = dyn_cast<Constant>(SI->getOperand(1)))
+ if (ST->isNullValue()) {
+ Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0));
+ if (CondI && CondI->getParent() == I.getParent())
+ UpdateValueUsesWith(CondI, ConstantBool::getFalse());
+ else if (I.getParent() != SI->getParent() || SI->hasOneUse())
+ I.setOperand(1, SI->getOperand(2));
+ else
+ UpdateValueUsesWith(SI, SI->getOperand(2));
return &I;
}
-
- // If the top bits of both operands are zero (i.e. we can prove they are
- // unsigned inputs), turn this into a urem.
- uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1);
- if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) {
- const Type *NTy = Op0->getType()->getUnsignedVersion();
- Value *LHS = InsertCastBefore(Op0, NTy, I);
- Value *RHS;
- if (Constant *R = dyn_cast<Constant>(Op1))
- RHS = ConstantExpr::getCast(R, NTy);
- else
- RHS = InsertCastBefore(Op1, NTy, I);
- Instruction *Rem = BinaryOperator::createRem(LHS, RHS, I.getName());
- InsertNewInstBefore(Rem, I);
- return new CastInst(Rem, I.getType());
- }
+ // Likewise for: rem X, (Cond ? Y : 0) -> rem X, Y
+ if (Constant *ST = dyn_cast<Constant>(SI->getOperand(2)))
+ if (ST->isNullValue()) {
+ Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0));
+ if (CondI && CondI->getParent() == I.getParent())
+ UpdateValueUsesWith(CondI, ConstantBool::getTrue());
+ else if (I.getParent() != SI->getParent() || SI->hasOneUse())
+ I.setOperand(1, SI->getOperand(1));
+ else
+ UpdateValueUsesWith(SI, SI->getOperand(1));
+ return &I;
+ }
}
+ return 0;
+}
+
+/// This function implements the transforms common to both integer remainder
+/// instructions (urem and srem). It is called by the visitors to those integer
+/// remainder instructions.
+/// @brief Common integer remainder transforms
+Instruction *InstCombiner::commonIRemTransforms(BinaryOperator &I) {
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+ if (Instruction *common = commonRemTransforms(I))
+ return common;
+
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
// X % 0 == undef, we don't need to preserve faults!
if (RHS->equalsInt(0))
@@ -2460,13 +2486,6 @@
if (RHS->equalsInt(1)) // X % 1 == 0
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
- // Check to see if this is an unsigned remainder with an exact power of 2,
- // if so, convert to a bitwise and.
- if (ConstantInt *C = dyn_cast<ConstantInt>(RHS))
- if (RHS->getType()->isUnsigned())
- if (isPowerOf2_64(C->getZExtValue()))
- return BinaryOperator::createAnd(Op0, SubOne(C));
-
if (Instruction *Op0I = dyn_cast<Instruction>(Op0)) {
if (SelectInst *SI = dyn_cast<SelectInst>(Op0I)) {
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
@@ -2475,19 +2494,34 @@
if (Instruction *NV = FoldOpIntoPhi(I))
return NV;
}
-
- // X*C1%C2 --> 0 iff C1%C2 == 0
- if (ConstantExpr::getRem(GetFactor(Op0I), RHS)->isNullValue())
+ // (X * C1) % C2 --> 0 iff C1 % C2 == 0
+ if (ConstantExpr::getSRem(GetFactor(Op0I), RHS)->isNullValue())
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
}
}
+ return 0;
+}
+
+Instruction *InstCombiner::visitURem(BinaryOperator &I) {
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+ if (Instruction *common = commonIRemTransforms(I))
+ return common;
+
+ if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
+ // X urem C^2 -> X and C
+ // Check to see if this is an unsigned remainder with an exact power of 2,
+ // if so, convert to a bitwise and.
+ if (ConstantInt *C = dyn_cast<ConstantInt>(RHS))
+ if (isPowerOf2_64(C->getZExtValue()))
+ return BinaryOperator::createAnd(Op0, SubOne(C));
+ }
+
if (Instruction *RHSI = dyn_cast<Instruction>(I.getOperand(1))) {
- // Turn A % (C << N), where C is 2^k, into A & ((C << N)-1) [urem only].
- if (I.getType()->isUnsigned() &&
- RHSI->getOpcode() == Instruction::Shl &&
- isa<ConstantInt>(RHSI->getOperand(0)) &&
- RHSI->getOperand(0)->getType()->isUnsigned()) {
+ // Turn A % (C << N), where C is 2^k, into A & ((C << N)-1)
+ if (RHSI->getOpcode() == Instruction::Shl &&
+ isa<ConstantInt>(RHSI->getOperand(0))) {
unsigned C1 = cast<ConstantInt>(RHSI->getOperand(0))->getZExtValue();
if (isPowerOf2_64(C1)) {
Constant *N1 = ConstantInt::getAllOnesValue(I.getType());
@@ -2496,61 +2530,60 @@
return BinaryOperator::createAnd(Op0, Add);
}
}
-
- // If this is 'urem X, (Cond ? C1, C2)' where C1&C2 are powers of two,
- // transform this into: '(Cond ? (urem X, C1) : (urem X, C2))'.
- if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) {
- // rem X, (Cond ? 0 : Y) -> rem X, Y. If the rem and the select are in
- // the same basic block, then we replace the select with Y, and the
- // condition of the select with false (if the cond value is in the same
- // BB). If the select has uses other than the div, this allows them to be
- // simplified also.
- if (Constant *ST = dyn_cast<Constant>(SI->getOperand(1)))
- if (ST->isNullValue()) {
- Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0));
- if (CondI && CondI->getParent() == I.getParent())
- UpdateValueUsesWith(CondI, ConstantBool::getFalse());
- else if (I.getParent() != SI->getParent() || SI->hasOneUse())
- I.setOperand(1, SI->getOperand(2));
- else
- UpdateValueUsesWith(SI, SI->getOperand(2));
- return &I;
- }
- // Likewise for: rem X, (Cond ? Y : 0) -> rem X, Y
- if (Constant *ST = dyn_cast<Constant>(SI->getOperand(2)))
- if (ST->isNullValue()) {
- Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0));
- if (CondI && CondI->getParent() == I.getParent())
- UpdateValueUsesWith(CondI, ConstantBool::getTrue());
- else if (I.getParent() != SI->getParent() || SI->hasOneUse())
- I.setOperand(1, SI->getOperand(1));
- else
- UpdateValueUsesWith(SI, SI->getOperand(1));
- return &I;
- }
+ }
-
- if (ConstantInt *STO = dyn_cast<ConstantInt>(SI->getOperand(1)))
- if (ConstantInt *SFO = dyn_cast<ConstantInt>(SI->getOperand(2)))
- if (STO->getType()->isUnsigned() && SFO->getType()->isUnsigned()) {
- // STO == 0 and SFO == 0 handled above.
- if (isPowerOf2_64(STO->getZExtValue()) &&
- isPowerOf2_64(SFO->getZExtValue())) {
- Value *TrueAnd = InsertNewInstBefore(
- BinaryOperator::createAnd(Op0, SubOne(STO), SI->getName()+".t"),
- I);
- Value *FalseAnd = InsertNewInstBefore(
- BinaryOperator::createAnd(Op0, SubOne(SFO), SI->getName()+".f"),
- I);
- return new SelectInst(SI->getOperand(0), TrueAnd, FalseAnd);
- }
- }
- }
+ // urem X, (select Cond, 2^C1, 2^C2) --> select Cond, (and X, C1), (and X, C2)
+ // where C1&C2 are powers of two.
+ if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) {
+ if (ConstantInt *STO = dyn_cast<ConstantInt>(SI->getOperand(1)))
+ if (ConstantInt *SFO = dyn_cast<ConstantInt>(SI->getOperand(2))) {
+ // STO == 0 and SFO == 0 handled above.
+ if (isPowerOf2_64(STO->getZExtValue()) &&
+ isPowerOf2_64(SFO->getZExtValue())) {
+ Value *TrueAnd = InsertNewInstBefore(
+ BinaryOperator::createAnd(Op0, SubOne(STO), SI->getName()+".t"), I);
+ Value *FalseAnd = InsertNewInstBefore(
+ BinaryOperator::createAnd(Op0, SubOne(SFO), SI->getName()+".f"), I);
+ return new SelectInst(SI->getOperand(0), TrueAnd, FalseAnd);
+ }
+ }
}
return 0;
}
+Instruction *InstCombiner::visitSRem(BinaryOperator &I) {
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+ if (Instruction *common = commonIRemTransforms(I))
+ return common;
+
+ if (Value *RHSNeg = dyn_castNegVal(Op1))
+ if (!isa<ConstantInt>(RHSNeg) ||
+ cast<ConstantInt>(RHSNeg)->getSExtValue() > 0) {
+ // X % -Y -> X % Y
+ AddUsesToWorkList(I);
+ I.setOperand(1, RHSNeg);
+ return &I;
+ }
+
+ // If the top bits of both operands are zero (i.e. we can prove they are
+ // unsigned inputs), turn this into a urem.
+ uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1);
+ if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) {
+ // X srem Y -> X urem Y, iff X and Y don't have sign bit set
+ return BinaryOperator::createURem(Op0, Op1, I.getName());
+ }
+
+ return 0;
+}
+
+Instruction *InstCombiner::visitFRem(BinaryOperator &I) {
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+ return commonRemTransforms(I);
+}
+
// isMaxValueMinusOne - return true if this is Max-1
static bool isMaxValueMinusOne(const ConstantInt *C) {
if (C->getType()->isUnsigned())
@@ -4568,40 +4601,16 @@
// the second operand is a constant, simplify a bit.
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Op0)) {
switch (BO->getOpcode()) {
-#if 0
case Instruction::SRem:
// If we have a signed (X % (2^c)) == 0, turn it into an unsigned one.
if (CI->isNullValue() && isa<ConstantInt>(BO->getOperand(1)) &&
BO->hasOneUse()) {
int64_t V = cast<ConstantInt>(BO->getOperand(1))->getSExtValue();
if (V > 1 && isPowerOf2_64(V)) {
- Value *NewRem = InsertNewInstBefore(
- BinaryOperator::createURem(BO->getOperand(0),
- BO->getOperand(1),
- BO->getName()), I);
- return BinaryOperator::create(
- I.getOpcode(), NewRem,
- Constant::getNullValue(NewRem->getType()));
- }
- }
- break;
-#endif
-
- case Instruction::Rem:
- // If we have a signed (X % (2^c)) == 0, turn it into an unsigned one.
- if (CI->isNullValue() && isa<ConstantInt>(BO->getOperand(1)) &&
- BO->hasOneUse() && BO->getOperand(1)->getType()->isSigned()) {
- int64_t V = cast<ConstantInt>(BO->getOperand(1))->getSExtValue();
- if (V > 1 && isPowerOf2_64(V)) {
- unsigned L2 = Log2_64(V);
- const Type *UTy = BO->getType()->getUnsignedVersion();
- Value *NewX = InsertNewInstBefore(new CastInst(BO->getOperand(0),
- UTy, "tmp"), I);
- Constant *RHSCst = ConstantInt::get(UTy, 1ULL << L2);
- Value *NewRem =InsertNewInstBefore(BinaryOperator::createRem(NewX,
- RHSCst, BO->getName()), I);
+ Value *NewRem = InsertNewInstBefore(BinaryOperator::createURem(
+ BO->getOperand(0), BO->getOperand(1), BO->getName()), I);
return BinaryOperator::create(I.getOpcode(), NewRem,
- Constant::getNullValue(UTy));
+ Constant::getNullValue(BO->getType()));
}
}
break;
@@ -5766,6 +5775,8 @@
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 c4ffa4e..b47afbd 100644
--- a/lib/Transforms/Scalar/PredicateSimplifier.cpp
+++ b/lib/Transforms/Scalar/PredicateSimplifier.cpp
@@ -788,10 +788,12 @@
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 7d71085..2df52ae 100644
--- a/lib/Transforms/Scalar/Reassociate.cpp
+++ b/lib/Transforms/Scalar/Reassociate.cpp
@@ -116,7 +116,9 @@
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 2589739..7d55f7e 100644
--- a/lib/VMCore/ConstantFold.cpp
+++ b/lib/VMCore/ConstantFold.cpp
@@ -40,10 +40,12 @@
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 @@
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 @@
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 @@
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 @@
#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 @@
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 @@
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 @@
case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::FDiv:
- case Instruction::Rem:
- if (!isa<UndefValue>(V2)) // undef/X -> 0
+ case Instruction::URem:
+ case Instruction::SRem:
+ case Instruction::FRem:
+ if (!isa<UndefValue>(V2)) // undef / X -> 0
return Constant::getNullValue(V1->getType());
- return const_cast<Constant*>(V2); // X/undef -> undef
- case Instruction::Or: // X|undef -> -1
+ return const_cast<Constant*>(V2); // X / undef -> undef
+ case Instruction::Or: // X | undef -> -1
return ConstantInt::getAllOnesValue(V1->getType());
case Instruction::Shr:
- if (!isa<UndefValue>(V2)) {
+ if (!isa<UndefValue>(V2)) {
if (V1->getType()->isSigned())
- return const_cast<Constant*>(V1); // undef >>s X -> undef
+ return const_cast<Constant*>(V1); // undef >>s X -> undef
// undef >>u X -> 0
} else if (isa<UndefValue>(V1)) {
- return const_cast<Constant*>(V1); // undef >> undef -> undef
+ return const_cast<Constant*>(V1); // undef >> undef -> undef
} else {
if (V1->getType()->isSigned())
- return const_cast<Constant*>(V1); // X >>s undef -> X
- // X >>u undef -> 0
+ return const_cast<Constant*>(V1); // X >>s undef -> X
}
- return Constant::getNullValue(V1->getType());
+ return Constant::getNullValue(V1->getType());// X >>u undef -> 0
case Instruction::Shl:
// undef << X -> 0 X << undef -> 0
@@ -1366,10 +1391,6 @@
// 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 @@
if (CI->getZExtValue() == 1)
return const_cast<Constant*>(V1); // X / 1 == X
break;
- case Instruction::Rem:
+ case Instruction::URem:
+ case Instruction::SRem:
if (const ConstantInt *CI = dyn_cast<ConstantInt>(V2))
if (CI->getZExtValue() == 1)
- return Constant::getNullValue(CI->getType()); // X % 1 == 0
+ return Constant::getNullValue(CI->getType()); // X % 1 == 0
break;
case Instruction::And:
if (cast<ConstantIntegral>(V2)->isAllOnesValue())
@@ -1450,7 +1472,9 @@
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 9c92b90..bcfd387 100644
--- a/lib/VMCore/Constants.cpp
+++ b/lib/VMCore/Constants.cpp
@@ -78,7 +78,9 @@
case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::FDiv:
- case Instruction::Rem:
+ case Instruction::URem:
+ case Instruction::SRem:
+ case Instruction::FRem:
// Div and rem can trap if the RHS is not known to be non-zero.
if (!isa<ConstantInt>(getOperand(1)) || getOperand(1)->isNullValue())
return true;
@@ -457,8 +459,14 @@
Constant *ConstantExpr::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 @@
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 @@
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::get(unsigned Opcode, Constant *C1, Constant *C2) {
#ifndef NDEBUG
switch (Opcode) {
- case Instruction::Add: case Instruction::Sub:
+ case Instruction::Add:
+ case Instruction::Sub:
case Instruction::Mul:
- case Instruction::Rem:
assert(C1->getType() == C2->getType() && "Op types should be identical!");
assert((C1->getType()->isInteger() || C1->getType()->isFloatingPoint() ||
isa<PackedType>(C1->getType())) &&
"Tried to create an arithmetic operation on a non-arithmetic type!");
break;
-
case Instruction::UDiv:
case Instruction::SDiv:
assert(C1->getType() == C2->getType() && "Op types should be identical!");
@@ -1489,6 +1496,19 @@
&& cast<PackedType>(C1->getType())->getElementType()->isFloatingPoint()))
&& "Tried to create an arithmetic operation on a non-arithmetic type!");
break;
+ case Instruction::URem:
+ case Instruction::SRem:
+ assert(C1->getType() == C2->getType() && "Op types should be identical!");
+ assert((C1->getType()->isInteger() || (isa<PackedType>(C1->getType()) &&
+ cast<PackedType>(C1->getType())->getElementType()->isInteger())) &&
+ "Tried to create an arithmetic operation on a non-arithmetic type!");
+ break;
+ case Instruction::FRem:
+ assert(C1->getType() == C2->getType() && "Op types should be identical!");
+ assert((C1->getType()->isFloatingPoint() || (isa<PackedType>(C1->getType())
+ && cast<PackedType>(C1->getType())->getElementType()->isFloatingPoint()))
+ && "Tried to create an arithmetic operation on a non-arithmetic type!");
+ break;
case Instruction::And:
case Instruction::Or:
case Instruction::Xor:
diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp
index 9b5fa71..355c508 100644
--- a/lib/VMCore/Instruction.cpp
+++ b/lib/VMCore/Instruction.cpp
@@ -97,7 +97,9 @@
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 @@
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 790f6ac..3825d85 100644
--- a/lib/VMCore/Instructions.cpp
+++ b/lib/VMCore/Instructions.cpp
@@ -1023,7 +1023,6 @@
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 @@
cast<PackedType>(getType())->getElementType()->isFloatingPoint()))
&& "Incorrect operand type (not floating point) for FDIV");
break;
-
+ case URem:
+ case SRem:
+ assert(getType() == LHS->getType() &&
+ "Arithmetic operation should return same type as operands!");
+ assert((getType()->isInteger() || (isa<PackedType>(getType()) &&
+ cast<PackedType>(getType())->getElementType()->isInteger())) &&
+ "Incorrect operand type (not integer) for S/UREM");
+ break;
+ case FRem:
+ assert(getType() == LHS->getType() &&
+ "Arithmetic operation should return same type as operands!");
+ assert((getType()->isFloatingPoint() || (isa<PackedType>(getType()) &&
+ cast<PackedType>(getType())->getElementType()->isFloatingPoint()))
+ && "Incorrect operand type (not floating point) for FREM");
+ break;
case And: case Or:
case Xor:
assert(getType() == LHS->getType() &&