summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2009-06-04 22:49:04 +0000
committerDan Gohman <gohman@apple.com>2009-06-04 22:49:04 +0000
commita5b9645c4b7a1d8be5e41081b99f27b49b8aa8cf (patch)
tree7f5a9f6633be0c4e77a1bb00e5bfcfcca14e219b /llvm/lib
parent72a4d2fec138ad6d2becbc69c6d034246a056d09 (diff)
downloadbcm5719-llvm-a5b9645c4b7a1d8be5e41081b99f27b49b8aa8cf.tar.gz
bcm5719-llvm-a5b9645c4b7a1d8be5e41081b99f27b49b8aa8cf.zip
Split the Add, Sub, and Mul instruction opcodes into separate
integer and floating-point opcodes, introducing FAdd, FSub, and FMul. For now, the AsmParser, BitcodeReader, and IRBuilder all preserve backwards compatability, and the Core LLVM APIs preserve backwards compatibility for IR producers. Most front-ends won't need to change immediately. This implements the first step of the plan outlined here: http://nondot.org/sabre/LLVMNotes/IntegerOverflow.txt llvm-svn: 72897
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp2
-rw-r--r--llvm/lib/AsmParser/LLLexer.cpp4
-rw-r--r--llvm/lib/AsmParser/LLParser.cpp12
-rw-r--r--llvm/lib/AsmParser/LLToken.h3
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp9
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp9
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/FastISel.cpp24
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp46
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h9
-rw-r--r--llvm/lib/ExecutionEngine/ExecutionEngine.cpp21
-rw-r--r--llvm/lib/ExecutionEngine/Interpreter/Execution.cpp56
-rw-r--r--llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp3
-rw-r--r--llvm/lib/Target/CBackend/CBackend.cpp35
-rw-r--r--llvm/lib/Target/CppBackend/CPPBackend.cpp9
-rw-r--r--llvm/lib/Target/MSIL/MSILWriter.cpp8
-rw-r--r--llvm/lib/Transforms/Scalar/GVN.cpp6
-rw-r--r--llvm/lib/Transforms/Scalar/GVNPRE.cpp9
-rw-r--r--llvm/lib/Transforms/Scalar/IndVarSimplify.cpp2
-rw-r--r--llvm/lib/Transforms/Scalar/InstructionCombining.cpp216
-rw-r--r--llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp3
-rw-r--r--llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp2
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyCFG.cpp8
-rw-r--r--llvm/lib/VMCore/ConstantFold.cpp23
-rw-r--r--llvm/lib/VMCore/Constants.cpp49
-rw-r--r--llvm/lib/VMCore/Instruction.cpp19
-rw-r--r--llvm/lib/VMCore/Instructions.cpp70
26 files changed, 446 insertions, 211 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 29ff8aa4f4d..45f97b8f64b 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -771,7 +771,7 @@ bool llvm::CannotBeNegativeZero(const Value *V, unsigned Depth) {
if (I == 0) return false;
// (add x, 0.0) is guaranteed to return +0.0, not -0.0.
- if (I->getOpcode() == Instruction::Add &&
+ if (I->getOpcode() == Instruction::FAdd &&
isa<ConstantFP>(I->getOperand(1)) &&
cast<ConstantFP>(I->getOperand(1))->isNullValue())
return true;
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 340cfe152f5..2cfb36656a2 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -591,7 +591,9 @@ lltok::Kind LLLexer::LexIdentifier() {
if (Len == strlen(#STR) && !memcmp(StartChar, #STR, strlen(#STR))) { \
UIntVal = Instruction::Enum; return lltok::kw_##STR; }
- INSTKEYWORD(add, Add); INSTKEYWORD(sub, Sub); INSTKEYWORD(mul, Mul);
+ INSTKEYWORD(add, Add); INSTKEYWORD(fadd, FAdd);
+ INSTKEYWORD(sub, Sub); INSTKEYWORD(fsub, FSub);
+ INSTKEYWORD(mul, Mul); INSTKEYWORD(fmul, FMul);
INSTKEYWORD(udiv, UDiv); INSTKEYWORD(sdiv, SDiv); INSTKEYWORD(fdiv, FDiv);
INSTKEYWORD(urem, URem); INSTKEYWORD(srem, SRem); INSTKEYWORD(frem, FRem);
INSTKEYWORD(shl, Shl); INSTKEYWORD(lshr, LShr); INSTKEYWORD(ashr, AShr);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 4f8be889c70..b4577ad726d 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -1835,8 +1835,11 @@ bool LLParser::ParseValID(ValID &ID) {
// Binary Operators.
case lltok::kw_add:
+ case lltok::kw_fadd:
case lltok::kw_sub:
+ case lltok::kw_fsub:
case lltok::kw_mul:
+ case lltok::kw_fmul:
case lltok::kw_udiv:
case lltok::kw_sdiv:
case lltok::kw_fdiv:
@@ -2400,8 +2403,13 @@ bool LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
// Binary Operators.
case lltok::kw_add:
case lltok::kw_sub:
- case lltok::kw_mul: return ParseArithmetic(Inst, PFS, KeywordVal, 0);
-
+ case lltok::kw_mul:
+ // API compatibility: Accept either integer or floating-point types.
+ return ParseArithmetic(Inst, PFS, KeywordVal, 0);
+ case lltok::kw_fadd:
+ case lltok::kw_fsub:
+ case lltok::kw_fmul: return ParseArithmetic(Inst, PFS, KeywordVal, 2);
+
case lltok::kw_udiv:
case lltok::kw_sdiv:
case lltok::kw_urem:
diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h
index 2d1cfa5a053..c2ce5601d41 100644
--- a/llvm/lib/AsmParser/LLToken.h
+++ b/llvm/lib/AsmParser/LLToken.h
@@ -90,7 +90,8 @@ namespace lltok {
kw_ueq, kw_une,
// Instruction Opcodes (Opcode in UIntVal).
- kw_add, kw_sub, kw_mul, kw_udiv, kw_sdiv, kw_fdiv,
+ kw_add, kw_fadd, kw_sub, kw_fsub, kw_mul, kw_fmul,
+ kw_udiv, kw_sdiv, kw_fdiv,
kw_urem, kw_srem, kw_frem, kw_shl, kw_lshr, kw_ashr,
kw_and, kw_or, kw_xor, kw_icmp, kw_fcmp, kw_vicmp, kw_vfcmp,
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 1dad04bd8f6..3b44f56421f 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -104,9 +104,12 @@ static int GetDecodedCastOpcode(unsigned Val) {
static int GetDecodedBinaryOpcode(unsigned Val, const Type *Ty) {
switch (Val) {
default: return -1;
- case bitc::BINOP_ADD: return Instruction::Add;
- case bitc::BINOP_SUB: return Instruction::Sub;
- case bitc::BINOP_MUL: return Instruction::Mul;
+ case bitc::BINOP_ADD:
+ return Ty->isFPOrFPVector() ? Instruction::FAdd : Instruction::Add;
+ case bitc::BINOP_SUB:
+ return Ty->isFPOrFPVector() ? Instruction::FSub : Instruction::Sub;
+ case bitc::BINOP_MUL:
+ return Ty->isFPOrFPVector() ? Instruction::FMul : Instruction::Mul;
case bitc::BINOP_UDIV: return Instruction::UDiv;
case bitc::BINOP_SDIV:
return Ty->isFPOrFPVector() ? Instruction::FDiv : Instruction::SDiv;
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index bfc029c1f27..9f16728d492 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -77,9 +77,12 @@ static unsigned GetEncodedCastOpcode(unsigned Opcode) {
static unsigned GetEncodedBinaryOpcode(unsigned Opcode) {
switch (Opcode) {
default: assert(0 && "Unknown binary instruction!");
- case Instruction::Add: return bitc::BINOP_ADD;
- case Instruction::Sub: return bitc::BINOP_SUB;
- case Instruction::Mul: return bitc::BINOP_MUL;
+ case Instruction::Add:
+ case Instruction::FAdd: return bitc::BINOP_ADD;
+ case Instruction::Sub:
+ case Instruction::FSub: return bitc::BINOP_SUB;
+ case Instruction::Mul:
+ case Instruction::FMul: return bitc::BINOP_MUL;
case Instruction::UDiv: return bitc::BINOP_UDIV;
case Instruction::FDiv:
case Instruction::SDiv: return bitc::BINOP_SDIV;
diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
index 6becff32176..4a7dbebe2de 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -639,18 +639,18 @@ FastISel::FastEmitBranch(MachineBasicBlock *MSucc) {
bool
FastISel::SelectOperator(User *I, unsigned Opcode) {
switch (Opcode) {
- case Instruction::Add: {
- ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FADD : ISD::ADD;
- return SelectBinaryOp(I, Opc);
- }
- case Instruction::Sub: {
- ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FSUB : ISD::SUB;
- return SelectBinaryOp(I, Opc);
- }
- case Instruction::Mul: {
- ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FMUL : ISD::MUL;
- return SelectBinaryOp(I, Opc);
- }
+ case Instruction::Add:
+ return SelectBinaryOp(I, ISD::ADD);
+ case Instruction::FAdd:
+ return SelectBinaryOp(I, ISD::FADD);
+ case Instruction::Sub:
+ return SelectBinaryOp(I, ISD::SUB);
+ case Instruction::FSub:
+ return SelectBinaryOp(I, ISD::FSUB);
+ case Instruction::Mul:
+ return SelectBinaryOp(I, ISD::MUL);
+ case Instruction::FMul:
+ return SelectBinaryOp(I, ISD::FMUL);
case Instruction::SDiv:
return SelectBinaryOp(I, ISD::SDIV);
case Instruction::UDiv:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
index 889d7f5dd93..93750d6b98c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
@@ -842,20 +842,6 @@ void SelectionDAGLowering::visit(unsigned Opcode, User &I) {
}
}
-void SelectionDAGLowering::visitAdd(User &I) {
- if (I.getType()->isFPOrFPVector())
- visitBinary(I, ISD::FADD);
- else
- visitBinary(I, ISD::ADD);
-}
-
-void SelectionDAGLowering::visitMul(User &I) {
- if (I.getType()->isFPOrFPVector())
- visitBinary(I, ISD::FMUL);
- else
- visitBinary(I, ISD::MUL);
-}
-
SDValue SelectionDAGLowering::getValue(const Value *V) {
SDValue &N = NodeMap[V];
if (N.getNode()) return N;
@@ -2161,37 +2147,33 @@ void SelectionDAGLowering::visitSwitch(SwitchInst &SI) {
}
-void SelectionDAGLowering::visitSub(User &I) {
+void SelectionDAGLowering::visitFSub(User &I) {
// -0.0 - X --> fneg
const Type *Ty = I.getType();
if (isa<VectorType>(Ty)) {
if (ConstantVector *CV = dyn_cast<ConstantVector>(I.getOperand(0))) {
const VectorType *DestTy = cast<VectorType>(I.getType());
const Type *ElTy = DestTy->getElementType();
- if (ElTy->isFloatingPoint()) {
- unsigned VL = DestTy->getNumElements();
- std::vector<Constant*> NZ(VL, ConstantFP::getNegativeZero(ElTy));
- Constant *CNZ = ConstantVector::get(&NZ[0], NZ.size());
- if (CV == CNZ) {
- SDValue Op2 = getValue(I.getOperand(1));
- setValue(&I, DAG.getNode(ISD::FNEG, getCurDebugLoc(),
- Op2.getValueType(), Op2));
- return;
- }
- }
- }
- }
- if (Ty->isFloatingPoint()) {
- if (ConstantFP *CFP = dyn_cast<ConstantFP>(I.getOperand(0)))
- if (CFP->isExactlyValue(ConstantFP::getNegativeZero(Ty)->getValueAPF())) {
+ unsigned VL = DestTy->getNumElements();
+ std::vector<Constant*> NZ(VL, ConstantFP::getNegativeZero(ElTy));
+ Constant *CNZ = ConstantVector::get(&NZ[0], NZ.size());
+ if (CV == CNZ) {
SDValue Op2 = getValue(I.getOperand(1));
setValue(&I, DAG.getNode(ISD::FNEG, getCurDebugLoc(),
Op2.getValueType(), Op2));
return;
}
+ }
}
+ if (ConstantFP *CFP = dyn_cast<ConstantFP>(I.getOperand(0)))
+ if (CFP->isExactlyValue(ConstantFP::getNegativeZero(Ty)->getValueAPF())) {
+ SDValue Op2 = getValue(I.getOperand(1));
+ setValue(&I, DAG.getNode(ISD::FNEG, getCurDebugLoc(),
+ Op2.getValueType(), Op2));
+ return;
+ }
- visitBinary(I, Ty->isFPOrFPVector() ? ISD::FSUB : ISD::SUB);
+ visitBinary(I, ISD::FSUB);
}
void SelectionDAGLowering::visitBinary(User &I, unsigned OpCode) {
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h
index 578aa591ce6..057c8410da0 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h
@@ -469,9 +469,12 @@ private:
void visitBinary(User &I, unsigned OpCode);
void visitShift(User &I, unsigned Opcode);
- void visitAdd(User &I);
- void visitSub(User &I);
- void visitMul(User &I);
+ void visitAdd(User &I) { visitBinary(I, ISD::ADD); }
+ void visitFAdd(User &I) { visitBinary(I, ISD::FADD); }
+ void visitSub(User &I) { visitBinary(I, ISD::SUB); }
+ void visitFSub(User &I);
+ void visitMul(User &I) { visitBinary(I, ISD::MUL); }
+ void visitFMul(User &I) { visitBinary(I, ISD::FMUL); }
void visitURem(User &I) { visitBinary(I, ISD::UREM); }
void visitSRem(User &I) { visitBinary(I, ISD::SREM); }
void visitFRem(User &I) { visitBinary(I, ISD::FREM); }
diff --git a/llvm/lib/ExecutionEngine/ExecutionEngine.cpp b/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
index 29a05bbbdb6..a80513f3df9 100644
--- a/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -573,8 +573,11 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
return GV;
}
case Instruction::Add:
+ case Instruction::FAdd:
case Instruction::Sub:
+ case Instruction::FSub:
case Instruction::Mul:
+ case Instruction::FMul:
case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::URem:
@@ -605,11 +608,11 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
case Type::FloatTyID:
switch (CE->getOpcode()) {
default: assert(0 && "Invalid float opcode"); abort();
- case Instruction::Add:
+ case Instruction::FAdd:
GV.FloatVal = LHS.FloatVal + RHS.FloatVal; break;
- case Instruction::Sub:
+ case Instruction::FSub:
GV.FloatVal = LHS.FloatVal - RHS.FloatVal; break;
- case Instruction::Mul:
+ case Instruction::FMul:
GV.FloatVal = LHS.FloatVal * RHS.FloatVal; break;
case Instruction::FDiv:
GV.FloatVal = LHS.FloatVal / RHS.FloatVal; break;
@@ -620,11 +623,11 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
case Type::DoubleTyID:
switch (CE->getOpcode()) {
default: assert(0 && "Invalid double opcode"); abort();
- case Instruction::Add:
+ case Instruction::FAdd:
GV.DoubleVal = LHS.DoubleVal + RHS.DoubleVal; break;
- case Instruction::Sub:
+ case Instruction::FSub:
GV.DoubleVal = LHS.DoubleVal - RHS.DoubleVal; break;
- case Instruction::Mul:
+ case Instruction::FMul:
GV.DoubleVal = LHS.DoubleVal * RHS.DoubleVal; break;
case Instruction::FDiv:
GV.DoubleVal = LHS.DoubleVal / RHS.DoubleVal; break;
@@ -638,15 +641,15 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
APFloat apfLHS = APFloat(LHS.IntVal);
switch (CE->getOpcode()) {
default: assert(0 && "Invalid long double opcode"); abort();
- case Instruction::Add:
+ case Instruction::FAdd:
apfLHS.add(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
GV.IntVal = apfLHS.bitcastToAPInt();
break;
- case Instruction::Sub:
+ case Instruction::FSub:
apfLHS.subtract(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
GV.IntVal = apfLHS.bitcastToAPInt();
break;
- case Instruction::Mul:
+ case Instruction::FMul:
apfLHS.multiply(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
GV.IntVal = apfLHS.bitcastToAPInt();
break;
diff --git a/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp b/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp
index 765fed248f9..7dfeae0ab2e 100644
--- a/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp
+++ b/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp
@@ -64,45 +64,35 @@ void Interpreter::initializeExecutionEngine() {
Dest.TY##Val = Src1.TY##Val OP Src2.TY##Val; \
break
-#define IMPLEMENT_INTEGER_BINOP1(OP, TY) \
- case Type::IntegerTyID: { \
- Dest.IntVal = Src1.IntVal OP Src2.IntVal; \
- break; \
- }
-
-
-static void executeAddInst(GenericValue &Dest, GenericValue Src1,
- GenericValue Src2, const Type *Ty) {
+static void executeFAddInst(GenericValue &Dest, GenericValue Src1,
+ GenericValue Src2, const Type *Ty) {
switch (Ty->getTypeID()) {
- IMPLEMENT_INTEGER_BINOP1(+, Ty);
IMPLEMENT_BINARY_OPERATOR(+, Float);
IMPLEMENT_BINARY_OPERATOR(+, Double);
default:
- cerr << "Unhandled type for Add instruction: " << *Ty << "\n";
+ cerr << "Unhandled type for FAdd instruction: " << *Ty << "\n";
abort();
}
}
-static void executeSubInst(GenericValue &Dest, GenericValue Src1,
- GenericValue Src2, const Type *Ty) {
+static void executeFSubInst(GenericValue &Dest, GenericValue Src1,
+ GenericValue Src2, const Type *Ty) {
switch (Ty->getTypeID()) {
- IMPLEMENT_INTEGER_BINOP1(-, Ty);
IMPLEMENT_BINARY_OPERATOR(-, Float);
IMPLEMENT_BINARY_OPERATOR(-, Double);
default:
- cerr << "Unhandled type for Sub instruction: " << *Ty << "\n";
+ cerr << "Unhandled type for FSub instruction: " << *Ty << "\n";
abort();
}
}
-static void executeMulInst(GenericValue &Dest, GenericValue Src1,
- GenericValue Src2, const Type *Ty) {
+static void executeFMulInst(GenericValue &Dest, GenericValue Src1,
+ GenericValue Src2, const Type *Ty) {
switch (Ty->getTypeID()) {
- IMPLEMENT_INTEGER_BINOP1(*, Ty);
IMPLEMENT_BINARY_OPERATOR(*, Float);
IMPLEMENT_BINARY_OPERATOR(*, Double);
default:
- cerr << "Unhandled type for Mul instruction: " << *Ty << "\n";
+ cerr << "Unhandled type for FMul instruction: " << *Ty << "\n";
abort();
}
}
@@ -550,11 +540,14 @@ void Interpreter::visitBinaryOperator(BinaryOperator &I) {
GenericValue R; // Result
switch (I.getOpcode()) {
- case Instruction::Add: executeAddInst (R, Src1, Src2, Ty); break;
- case Instruction::Sub: executeSubInst (R, Src1, Src2, Ty); break;
- case Instruction::Mul: executeMulInst (R, Src1, Src2, Ty); break;
- case Instruction::FDiv: executeFDivInst (R, Src1, Src2, Ty); break;
- case Instruction::FRem: executeFRemInst (R, Src1, Src2, Ty); break;
+ case Instruction::Add: R.IntVal = Src1.IntVal + Src2.IntVal; break;
+ case Instruction::Sub: R.IntVal = Src1.IntVal - Src2.IntVal; break;
+ case Instruction::Mul: R.IntVal = Src1.IntVal * Src2.IntVal; break;
+ case Instruction::FAdd: executeFAddInst(R, Src1, Src2, Ty); break;
+ case Instruction::FSub: executeFSubInst(R, Src1, Src2, Ty); break;
+ case Instruction::FMul: executeFMulInst(R, Src1, Src2, Ty); break;
+ case Instruction::FDiv: executeFDivInst(R, Src1, Src2, Ty); break;
+ case Instruction::FRem: executeFRemInst(R, Src1, Src2, Ty); break;
case Instruction::UDiv: R.IntVal = Src1.IntVal.udiv(Src2.IntVal); break;
case Instruction::SDiv: R.IntVal = Src1.IntVal.sdiv(Src2.IntVal); break;
case Instruction::URem: R.IntVal = Src1.IntVal.urem(Src2.IntVal); break;
@@ -1258,18 +1251,21 @@ GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE,
GenericValue Dest;
const Type * Ty = CE->getOperand(0)->getType();
switch (CE->getOpcode()) {
- case Instruction::Add: executeAddInst (Dest, Op0, Op1, Ty); break;
- case Instruction::Sub: executeSubInst (Dest, Op0, Op1, Ty); break;
- case Instruction::Mul: executeMulInst (Dest, Op0, Op1, Ty); break;
+ case Instruction::Add: Dest.IntVal = Op0.IntVal + Op1.IntVal; break;
+ case Instruction::Sub: Dest.IntVal = Op0.IntVal - Op1.IntVal; break;
+ case Instruction::Mul: Dest.IntVal = Op0.IntVal * Op1.IntVal; break;
+ case Instruction::FAdd: executeFAddInst(Dest, Op0, Op1, Ty); break;
+ case Instruction::FSub: executeFSubInst(Dest, Op0, Op1, Ty); break;
+ case Instruction::FMul: executeFMulInst(Dest, Op0, Op1, Ty); break;
case Instruction::FDiv: executeFDivInst(Dest, Op0, Op1, Ty); break;
case Instruction::FRem: executeFRemInst(Dest, Op0, Op1, Ty); break;
case Instruction::SDiv: Dest.IntVal = Op0.IntVal.sdiv(Op1.IntVal); break;
case Instruction::UDiv: Dest.IntVal = Op0.IntVal.udiv(Op1.IntVal); break;
case Instruction::URem: Dest.IntVal = Op0.IntVal.urem(Op1.IntVal); break;
case Instruction::SRem: Dest.IntVal = Op0.IntVal.srem(Op1.IntVal); break;
- case Instruction::And: Dest.IntVal = Op0.IntVal.And(Op1.IntVal); break;
- case Instruction::Or: Dest.IntVal = Op0.IntVal.Or(Op1.IntVal); break;
- case Instruction::Xor: Dest.IntVal = Op0.IntVal.Xor(Op1.IntVal); break;
+ case Instruction::And: Dest.IntVal = Op0.IntVal & Op1.IntVal; break;
+ case Instruction::Or: Dest.IntVal = Op0.IntVal | Op1.IntVal; break;
+ case Instruction::Xor: Dest.IntVal = Op0.IntVal ^ Op1.IntVal; break;
case Instruction::Shl:
Dest.IntVal = Op0.IntVal.shl(Op1.IntVal.getZExtValue());
break;
diff --git a/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp b/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp
index d3b0820c5f0..43f23e44342 100644
--- a/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp
@@ -891,8 +891,11 @@ unsigned JITEmitter::addSizeOfGlobalsInConstantVal(const Constant *C,
break;
}
case Instruction::Add:
+ case Instruction::FAdd:
case Instruction::Sub:
+ case Instruction::FSub:
case Instruction::Mul:
+ case Instruction::FMul:
case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::URem:
diff --git a/llvm/lib/Target/CBackend/CBackend.cpp b/llvm/lib/Target/CBackend/CBackend.cpp
index 4d7b54503e8..ed3ff8171f2 100644
--- a/llvm/lib/Target/CBackend/CBackend.cpp
+++ b/llvm/lib/Target/CBackend/CBackend.cpp
@@ -1000,8 +1000,11 @@ void CWriter::printConstant(Constant *CPV, bool Static) {
Out << ')';
return;
case Instruction::Add:
+ case Instruction::FAdd:
case Instruction::Sub:
+ case Instruction::FSub:
case Instruction::Mul:
+ case Instruction::FMul:
case Instruction::SDiv:
case Instruction::UDiv:
case Instruction::FDiv:
@@ -1020,9 +1023,12 @@ void CWriter::printConstant(Constant *CPV, bool Static) {
bool NeedsClosingParens = printConstExprCast(CE, Static);
printConstantWithCast(CE->getOperand(0), CE->getOpcode());
switch (CE->getOpcode()) {
- case Instruction::Add: Out << " + "; break;
- case Instruction::Sub: Out << " - "; break;
- case Instruction::Mul: Out << " * "; break;
+ case Instruction::Add:
+ case Instruction::FAdd: Out << " + "; break;
+ case Instruction::Sub:
+ case Instruction::FSub: Out << " - "; break;
+ case Instruction::Mul:
+ case Instruction::FMul: Out << " * "; break;
case Instruction::URem:
case Instruction::SRem:
case Instruction::FRem: Out << " % "; break;
@@ -1322,8 +1328,6 @@ bool CWriter::printConstExprCast(const ConstantExpr* CE, bool Static) {
case Instruction::Mul:
// We need to cast integer arithmetic so that it is always performed
// as unsigned, to avoid undefined behavior on overflow.
- if (!Ty->isIntOrIntVector()) break;
- // FALL THROUGH
case Instruction::LShr:
case Instruction::URem:
case Instruction::UDiv: NeedsExplicitCast = true; break;
@@ -1387,8 +1391,6 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
case Instruction::Mul:
// We need to cast integer arithmetic so that it is always performed
// as unsigned, to avoid undefined behavior on overflow.
- if (!OpTy->isIntOrIntVector()) break;
- // FALL THROUGH
case Instruction::LShr:
case Instruction::UDiv:
case Instruction::URem:
@@ -1505,8 +1507,6 @@ bool CWriter::writeInstructionCast(const Instruction &I) {
case Instruction::Mul:
// We need to cast integer arithmetic so that it is always performed
// as unsigned, to avoid undefined behavior on overflow.
- if (!Ty->isIntOrIntVector()) break;
- // FALL THROUGH
case Instruction::LShr:
case Instruction::URem:
case Instruction::UDiv:
@@ -1552,8 +1552,6 @@ void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
case Instruction::Mul:
// We need to cast integer arithmetic so that it is always performed
// as unsigned, to avoid undefined behavior on overflow.
- if (!OpTy->isIntOrIntVector()) break;
- // FALL THROUGH
case Instruction::LShr:
case Instruction::UDiv:
case Instruction::URem: // Cast to unsigned first
@@ -2602,10 +2600,14 @@ void CWriter::visitBinaryOperator(Instruction &I) {
// If this is a negation operation, print it out as such. For FP, we don't
// want to print "-0.0 - X".
- if (BinaryOperator::isNeg(&I)) {
+ if (BinaryOperator::isNeg(&I) || BinaryOperator::isFNeg(&I)) {
Out << "-(";
writeOperand(BinaryOperator::getNegArgument(cast<BinaryOperator>(&I)));
Out << ")";
+ } else if (BinaryOperator::isFNeg(&I)) {
+ Out << "-(";
+ writeOperand(BinaryOperator::getFNegArgument(cast<BinaryOperator>(&I)));
+ Out << ")";
} else if (I.getOpcode() == Instruction::FRem) {
// Output a call to fmod/fmodf instead of emitting a%b
if (I.getType() == Type::FloatTy)
@@ -2630,9 +2632,12 @@ void CWriter::visitBinaryOperator(Instruction &I) {
writeOperandWithCast(I.getOperand(0), I.getOpcode());
switch (I.getOpcode()) {
- case Instruction::Add: Out << " + "; break;
- case Instruction::Sub: Out << " - "; break;
- case Instruction::Mul: Out << " * "; break;
+ case Instruction::Add:
+ case Instruction::FAdd: Out << " + "; break;
+ case Instruction::Sub:
+ case Instruction::FSub: Out << " - "; break;
+ case Instruction::Mul:
+ case Instruction::FMul: Out << " * "; break;
case Instruction::URem:
case Instruction::SRem:
case Instruction::FRem: Out << " % "; break;
diff --git a/llvm/lib/Target/CppBackend/CPPBackend.cpp b/llvm/lib/Target/CppBackend/CPPBackend.cpp
index 4082989c4c4..04a6829d9cf 100644
--- a/llvm/lib/Target/CppBackend/CPPBackend.cpp
+++ b/llvm/lib/Target/CppBackend/CPPBackend.cpp
@@ -865,8 +865,11 @@ namespace {
Out << "Constant* " << constName << " = ConstantExpr::";
switch (CE->getOpcode()) {
case Instruction::Add: Out << "getAdd("; break;
+ case Instruction::FAdd: Out << "getFAdd("; break;
case Instruction::Sub: Out << "getSub("; break;
+ case Instruction::FSub: Out << "getFSub("; break;
case Instruction::Mul: Out << "getMul("; break;
+ case Instruction::FMul: Out << "getFMul("; break;
case Instruction::UDiv: Out << "getUDiv("; break;
case Instruction::SDiv: Out << "getSDiv("; break;
case Instruction::FDiv: Out << "getFDiv("; break;
@@ -1159,8 +1162,11 @@ namespace {
break;
}
case Instruction::Add:
+ case Instruction::FAdd:
case Instruction::Sub:
+ case Instruction::FSub:
case Instruction::Mul:
+ case Instruction::FMul:
case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::FDiv:
@@ -1176,8 +1182,11 @@ namespace {
Out << "BinaryOperator* " << iName << " = BinaryOperator::Create(";
switch (I->getOpcode()) {
case Instruction::Add: Out << "Instruction::Add"; break;
+ case Instruction::FAdd: Out << "Instruction::FAdd"; break;
case Instruction::Sub: Out << "Instruction::Sub"; break;
+ case Instruction::FSub: Out << "Instruction::FSub"; break;
case Instruction::Mul: Out << "Instruction::Mul"; break;
+ case Instruction::FMul: Out << "Instruction::FMul"; break;
case Instruction::UDiv:Out << "Instruction::UDiv"; break;
case Instruction::SDiv:Out << "Instruction::SDiv"; break;
case Instruction::FDiv:Out << "Instruction::FDiv"; break;
diff --git a/llvm/lib/Target/MSIL/MSILWriter.cpp b/llvm/lib/Target/MSIL/MSILWriter.cpp
index ada851d4f22..37e5b1eccde 100644
--- a/llvm/lib/Target/MSIL/MSILWriter.cpp
+++ b/llvm/lib/Target/MSIL/MSILWriter.cpp
@@ -1060,12 +1060,15 @@ void MSILWriter::printInstruction(const Instruction* Inst) {
break;
// Binary
case Instruction::Add:
+ case Instruction::FAdd:
printBinaryInstruction("add",Left,Right);
break;
case Instruction::Sub:
+ case Instruction::FSub:
printBinaryInstruction("sub",Left,Right);
break;
- case Instruction::Mul:
+ case Instruction::Mul:
+ case Instruction::FMul:
printBinaryInstruction("mul",Left,Right);
break;
case Instruction::UDiv:
@@ -1322,12 +1325,15 @@ void MSILWriter::printConstantExpr(const ConstantExpr* CE) {
printSelectInstruction(CE->getOperand(0),CE->getOperand(1),CE->getOperand(2));
break;
case Instruction::Add:
+ case Instruction::FAdd:
printBinaryInstruction("add",left,right);
break;
case Instruction::Sub:
+ case Instruction::FSub:
printBinaryInstruction("sub",left,right);
break;
case Instruction::Mul:
+ case Instruction::FMul:
printBinaryInstruction("mul",left,right);
break;
case Instruction::UDiv:
diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
index 733dfa97a15..673d38b7f3a 100644
--- a/llvm/lib/Transforms/Scalar/GVN.cpp
+++ b/llvm/lib/Transforms/Scalar/GVN.cpp
@@ -59,7 +59,8 @@ cl::opt<bool> EnableLoadPRE("enable-load-pre", cl::init(true));
/// two values.
namespace {
struct VISIBILITY_HIDDEN Expression {
- enum ExpressionOpcode { ADD, SUB, MUL, UDIV, SDIV, FDIV, UREM, SREM,
+ enum ExpressionOpcode { ADD, FADD, SUB, FSUB, MUL, FMUL,
+ UDIV, SDIV, FDIV, UREM, SREM,
FREM, SHL, LSHR, ASHR, AND, OR, XOR, ICMPEQ,
ICMPNE, ICMPUGT, ICMPUGE, ICMPULT, ICMPULE,
ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ,
@@ -200,8 +201,11 @@ Expression::ExpressionOpcode ValueTable::getOpcode(BinaryOperator* BO) {
default: // THIS SHOULD NEVER HAPPEN
assert(0 && "Binary operator with unknown opcode?");
case Instruction::Add: return Expression::ADD;
+ case Instruction::FAdd: return Expression::FADD;
case Instruction::Sub: return Expression::SUB;
+ case Instruction::FSub: return Expression::FSUB;
case Instruction::Mul: return Expression::MUL;
+ case Instruction::FMul: return Expression::FMUL;
case Instruction::UDiv: return Expression::UDIV;
case Instruction::SDiv: return Expression::SDIV;
case Instruction::FDiv: return Expression::FDIV;
diff --git a/llvm/lib/Transforms/Scalar/GVNPRE.cpp b/llvm/lib/Transforms/Scalar/GVNPRE.cpp
index e3b09379a22..0f3153f2a7b 100644
--- a/llvm/lib/Transforms/Scalar/GVNPRE.cpp
+++ b/llvm/lib/Transforms/Scalar/GVNPRE.cpp
@@ -55,7 +55,8 @@ namespace {
/// two values.
struct Expression {
- enum ExpressionOpcode { ADD, SUB, MUL, UDIV, SDIV, FDIV, UREM, SREM,
+ enum ExpressionOpcode { ADD, FADD, SUB, FSUB, MUL, FMUL,
+ UDIV, SDIV, FDIV, UREM, SREM,
FREM, SHL, LSHR, ASHR, AND, OR, XOR, ICMPEQ,
ICMPNE, ICMPUGT, ICMPUGE, ICMPULT, ICMPULE,
ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ,
@@ -202,10 +203,16 @@ Expression::ExpressionOpcode
switch(BO->getOpcode()) {
case Instruction::Add:
return Expression::ADD;
+ case Instruction::FAdd:
+ return Expression::FADD;
case Instruction::Sub:
return Expression::SUB;
+ case Instruction::FSub:
+ return Expression::FSUB;
case Instruction::Mul:
return Expression::MUL;
+ case Instruction::FMul:
+ return Expression::FMUL;
case Instruction::UDiv:
return Expression::UDIV;
case Instruction::SDiv:
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
index af61eae16f8..83503fdea24 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -754,7 +754,7 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PH) {
BinaryOperator *Incr =
dyn_cast<BinaryOperator>(PH->getIncomingValue(BackEdge));
if (!Incr) return;
- if (Incr->getOpcode() != Instruction::Add) return;
+ if (Incr->getOpcode() != Instruction::FAdd) return;
ConstantFP *IncrValue = NULL;
unsigned IncrVIndex = 1;
if (Incr->getOperand(1) == PH)
diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
index 8bb16f3de19..97bd34c771c 100644
--- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -167,8 +167,11 @@ namespace {
// otherwise - Change was made, replace I with returned instruction
//
Instruction *visitAdd(BinaryOperator &I);
+ Instruction *visitFAdd(BinaryOperator &I);
Instruction *visitSub(BinaryOperator &I);
+ Instruction *visitFSub(BinaryOperator &I);
Instruction *visitMul(BinaryOperator &I);
+ Instruction *visitFMul(BinaryOperator &I);
Instruction *visitURem(BinaryOperator &I);
Instruction *visitSRem(BinaryOperator &I);
Instruction *visitFRem(BinaryOperator &I);
@@ -403,7 +406,8 @@ X("instcombine", "Combine redundant instructions");
// 0 -> undef, 1 -> Const, 2 -> Other, 3 -> Arg, 3 -> Unary, 4 -> OtherInst
static unsigned getComplexity(Value *V) {
if (isa<Instruction>(V)) {
- if (BinaryOperator::isNeg(V) || BinaryOperator::isNot(V))
+ if (BinaryOperator::isNeg(V) || BinaryOperator::isFNeg(V) ||
+ BinaryOperator::isNot(V))
return 3;
return 4;
}
@@ -576,6 +580,25 @@ static inline Value *dyn_castNegVal(Value *V) {
return 0;
}
+// dyn_castFNegVal - Given a 'fsub' instruction, return the RHS of the
+// instruction if the LHS is a constant negative zero (which is the 'negate'
+// form).
+//
+static inline Value *dyn_castFNegVal(Value *V) {
+ if (BinaryOperator::isFNeg(V))
+ return BinaryOperator::getFNegArgument(V);
+
+ // Constants can be considered to be negated values if they can be folded.
+ if (ConstantFP *C = dyn_cast<ConstantFP>(V))
+ return ConstantExpr::getFNeg(C);
+
+ if (ConstantVector *C = dyn_cast<ConstantVector>(V))
+ if (C->getType()->getElementType()->isFloatingPoint())
+ return ConstantExpr::getFNeg(C);
+
+ return 0;
+}
+
static inline Value *dyn_castNotVal(Value *V) {
if (BinaryOperator::isNot(V))
return BinaryOperator::getNotArgument(V);
@@ -1733,12 +1756,12 @@ Value *InstCombiner::SimplifyDemandedVectorElts(Value *V, APInt DemandedElts,
default: assert(0 && "Case stmts out of sync!");
case Intrinsic::x86_sse_sub_ss:
case Intrinsic::x86_sse2_sub_sd:
- TmpV = InsertNewInstBefore(BinaryOperator::CreateSub(LHS, RHS,
+ TmpV = InsertNewInstBefore(BinaryOperator::CreateFSub(LHS, RHS,
II->getName()), *II);
break;
case Intrinsic::x86_sse_mul_ss:
case Intrinsic::x86_sse2_mul_sd:
- TmpV = InsertNewInstBefore(BinaryOperator::CreateMul(LHS, RHS,
+ TmpV = InsertNewInstBefore(BinaryOperator::CreateFMul(LHS, RHS,
II->getName()), *II);
break;
}
@@ -2052,14 +2075,8 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
return ReplaceInstUsesWith(I, RHS);
// X + 0 --> X
- if (!I.getType()->isFPOrFPVector()) { // NOTE: -0 + +0 = +0.
- if (RHSC->isNullValue())
- return ReplaceInstUsesWith(I, LHS);
- } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(RHSC)) {
- if (CFP->isExactlyValue(ConstantFP::getNegativeZero
- (I.getType())->getValueAPF()))
- return ReplaceInstUsesWith(I, LHS);
- }
+ if (RHSC->isNullValue())
+ return ReplaceInstUsesWith(I, LHS);
if (ConstantInt *CI = dyn_cast<ConstantInt>(RHSC)) {
// X + (signbit) --> X ^ signbit
@@ -2317,11 +2334,6 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
return SelectInst::Create(SI->getCondition(), A, N);
}
}
-
- // Check for X+0.0. Simplify it to X if we know X is not -0.0.
- if (ConstantFP *CFP = dyn_cast<ConstantFP>(RHS))
- if (CFP->getValueAPF().isPosZero() && CannotBeNegativeZero(LHS))
- return ReplaceInstUsesWith(I, LHS);
// Check for (add (sext x), y), see if we can merge this into an
// integer add followed by a sext.
@@ -2359,7 +2371,42 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
}
}
}
-
+
+ return Changed ? &I : 0;
+}
+
+Instruction *InstCombiner::visitFAdd(BinaryOperator &I) {
+ bool Changed = SimplifyCommutative(I);
+ Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
+
+ if (Constant *RHSC = dyn_cast<Constant>(RHS)) {
+ // X + 0 --> X
+ if (ConstantFP *CFP = dyn_cast<ConstantFP>(RHSC)) {
+ if (CFP->isExactlyValue(ConstantFP::getNegativeZero
+ (I.getType())->getValueAPF()))
+ return ReplaceInstUsesWith(I, LHS);
+ }
+
+ if (isa<PHINode>(LHS))
+ if (Instruction *NV = FoldOpIntoPhi(I))
+ return NV;
+ }
+
+ // -A + B --> B - A
+ // -A + -B --> -(A + B)
+ if (Value *LHSV = dyn_castFNegVal(LHS))
+ return BinaryOperator::CreateFSub(RHS, LHSV);
+
+ // A + -B --> A - B
+ if (!isa<Constant>(RHS))
+ if (Value *V = dyn_castFNegVal(RHS))
+ return BinaryOperator::CreateFSub(LHS, V);
+
+ // Check for X+0.0. Simplify it to X if we know X is not -0.0.
+ if (ConstantFP *CFP = dyn_cast<ConstantFP>(RHS))
+ if (CFP->getValueAPF().isPosZero() && CannotBeNegativeZero(LHS))
+ return ReplaceInstUsesWith(I, LHS);
+
// Check for (add double (sitofp x), y), see if we can merge this into an
// integer add followed by a promotion.
if (SIToFPInst *LHSConv = dyn_cast<SIToFPInst>(LHS)) {
@@ -2407,8 +2454,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
Instruction *InstCombiner::visitSub(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
- if (Op0 == Op1 && // sub X, X -> 0
- !I.getType()->isFPOrFPVector())
+ if (Op0 == Op1) // sub X, X -> 0
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
// If this is a 'B = x-(-A)', change to B = x+A...
@@ -2469,8 +2515,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
return BinaryOperator::CreateXor(Op0, Op1);
if (BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1)) {
- if (Op1I->getOpcode() == Instruction::Add &&
- !Op0->getType()->isFPOrFPVector()) {
+ if (Op1I->getOpcode() == Instruction::Add) {
if (Op1I->getOperand(0) == Op0) // X-(X+Y) == -Y
return BinaryOperator::CreateNeg(Op1I->getOperand(1), I.getName());
else if (Op1I->getOperand(1) == Op0) // X-(Y+X) == -Y
@@ -2487,8 +2532,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
// Replace (x - (y - z)) with (x + (z - y)) if the (y - z) subexpression
// is not used by anyone else...
//
- if (Op1I->getOpcode() == Instruction::Sub &&
- !Op1I->getType()->isFPOrFPVector()) {
+ if (Op1I->getOpcode() == Instruction::Sub) {
// Swap the two operands of the subexpr...
Value *IIOp0 = Op1I->getOperand(0), *IIOp1 = Op1I->getOperand(1);
Op1I->setOperand(0, IIOp1);
@@ -2526,18 +2570,17 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
}
}
- if (!Op0->getType()->isFPOrFPVector())
- if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
- if (Op0I->getOpcode() == Instruction::Add) {
- if (Op0I->getOperand(0) == Op1) // (Y+X)-Y == X
- return ReplaceInstUsesWith(I, Op0I->getOperand(1));
- else if (Op0I->getOperand(1) == Op1) // (X+Y)-Y == X
- return ReplaceInstUsesWith(I, Op0I->getOperand(0));
- } else if (Op0I->getOpcode() == Instruction::Sub) {
- if (Op0I->getOperand(0) == Op1) // (X-Y)-X == -Y
- return BinaryOperator::CreateNeg(Op0I->getOperand(1), I.getName());
- }
+ if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
+ if (Op0I->getOpcode() == Instruction::Add) {
+ if (Op0I->getOperand(0) == Op1) // (Y+X)-Y == X
+ return ReplaceInstUsesWith(I, Op0I->getOperand(1));
+ else if (Op0I->getOperand(1) == Op1) // (X+Y)-Y == X
+ return ReplaceInstUsesWith(I, Op0I->getOperand(0));
+ } else if (Op0I->getOpcode() == Instruction::Sub) {
+ if (Op0I->getOperand(0) == Op1) // (X-Y)-X == -Y
+ return BinaryOperator::CreateNeg(Op0I->getOperand(1), I.getName());
}
+ }
ConstantInt *C1;
if (Value *X = dyn_castFoldableMul(Op0, C1)) {
@@ -2551,6 +2594,40 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
return 0;
}
+Instruction *InstCombiner::visitFSub(BinaryOperator &I) {
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+ // If this is a 'B = x-(-A)', change to B = x+A...
+ if (Value *V = dyn_castFNegVal(Op1))
+ return BinaryOperator::CreateFAdd(Op0, V);
+
+ if (BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1)) {
+ if (Op1I->getOpcode() == Instruction::FAdd) {
+ if (Op1I->getOperand(0) == Op0) // X-(X+Y) == -Y
+ return BinaryOperator::CreateFNeg(Op1I->getOperand(1), I.getName());
+ else if (Op1I->getOperand(1) == Op0) // X-(Y+X) == -Y
+ return BinaryOperator::CreateFNeg(Op1I->getOperand(0), I.getName());
+ }
+
+ if (Op1I->hasOneUse()) {
+ // Replace (x - (y - z)) with (x + (z - y)) if the (y - z) subexpression
+ // is not used by anyone else...
+ //
+ if (Op1I->getOpcode() == Instruction::FSub) {
+ // Swap the two operands of the subexpr...
+ Value *IIOp0 = Op1I->getOperand(0), *IIOp1 = Op1I->getOperand(1);
+ Op1I->setOperand(0, IIOp1);
+ Op1I->setOperand(1, IIOp0);
+
+ // Create the new top level fadd instruction...
+ return BinaryOperator::CreateFAdd(Op0, Op1);
+ }
+ }
+ }
+
+ return 0;
+}
+
/// isSignBitCheck - Given an exploded icmp instruction, return true if the
/// comparison only checks the sign bit. If it only checks the sign bit, set
/// TrueIfSigned if the result of the comparison is true when the input value is
@@ -2613,13 +2690,6 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
return BinaryOperator::CreateShl(Op0,
ConstantInt::get(Op0->getType(), Val.logBase2()));
}
- } else if (ConstantFP *Op1F = dyn_cast<ConstantFP>(Op1)) {
- // TODO: If Op1 is zero and Op0 is finite, return zero.
-
- // "In IEEE floating point, x*1 is not equivalent to x for nans. However,
- // ANSI says we can drop signals, so we can do this anyway." (from GCC)
- if (Op1F->isExactlyValue(1.0))
- return ReplaceInstUsesWith(I, Op0); // Eliminate 'mul double %X, 1.0'
} else if (isa<VectorType>(Op1->getType())) {
// TODO: If Op1 is all zeros and Op0 is all finite, return all zeros.
@@ -2629,9 +2699,6 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
// As above, vector X*splat(1.0) -> X in all defined cases.
if (Constant *Splat = Op1V->getSplatValue()) {
- if (ConstantFP *F = dyn_cast<ConstantFP>(Splat))
- if (F->isExactlyValue(1.0))
- return ReplaceInstUsesWith(I, Op0);
if (ConstantInt *CI = dyn_cast<ConstantInt>(Splat))
if (CI->equalsInt(1))
return ReplaceInstUsesWith(I, Op0);
@@ -2755,6 +2822,45 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
return Changed ? &I : 0;
}
+Instruction *InstCombiner::visitFMul(BinaryOperator &I) {
+ bool Changed = SimplifyCommutative(I);
+ Value *Op0 = I.getOperand(0);
+
+ // Simplify mul instructions with a constant RHS...
+ if (Constant *Op1 = dyn_cast<Constant>(I.getOperand(1))) {
+ if (ConstantFP *Op1F = dyn_cast<ConstantFP>(Op1)) {
+ // "In IEEE floating point, x*1 is not equivalent to x for nans. However,
+ // ANSI says we can drop signals, so we can do this anyway." (from GCC)
+ if (Op1F->isExactlyValue(1.0))
+ return ReplaceInstUsesWith(I, Op0); // Eliminate 'mul double %X, 1.0'
+ } else if (isa<VectorType>(Op1->getType())) {
+ if (ConstantVector *Op1V = dyn_cast<ConstantVector>(Op1)) {
+ // As above, vector X*splat(1.0) -> X in all defined cases.
+ if (Constant *Splat = Op1V->getSplatValue()) {
+ if (ConstantFP *F = dyn_cast<ConstantFP>(Splat))
+ if (F->isExactlyValue(1.0))
+ return ReplaceInstUsesWith(I, Op0);
+ }
+ }
+ }
+
+ // Try to fold constant mul into select arguments.
+ if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
+ if (Instruction *R = FoldOpIntoSelect(I, SI, this))
+ return R;
+
+ if (isa<PHINode>(Op0))
+ if (Instruction *NV = FoldOpIntoPhi(I))
+ return NV;
+ }
+
+ if (Value *Op0v = dyn_castFNegVal(Op0)) // -X * -Y = X*Y
+ if (Value *Op1v = dyn_castFNegVal(I.getOperand(1)))
+ return BinaryOperator::CreateFMul(Op0v, Op1v);
+
+ return Changed ? &I : 0;
+}
+
/// SimplifyDivRemOfSelect - Try to fold a divide or remainder of a select
/// instruction.
bool InstCombiner::SimplifyDivRemOfSelect(BinaryOperator &I) {
@@ -8562,17 +8668,17 @@ Instruction *InstCombiner::visitFPTrunc(FPTruncInst &CI) {
if (Instruction *I = commonCastTransforms(CI))
return I;
- // If we have fptrunc(add (fpextend x), (fpextend y)), where x and y are
+ // If we have fptrunc(fadd (fpextend x), (fpextend y)), where x and y are
// smaller than the destination type, we can eliminate the truncate by doing
- // the add as the smaller type. This applies to add/sub/mul/div as well as
+ // the add as the smaller type. This applies to fadd/fsub/fmul/fdiv as well as
// many builtins (sqrt, etc).
BinaryOperator *OpI = dyn_cast<BinaryOperator>(CI.getOperand(0));
if (OpI && OpI->hasOneUse()) {
switch (OpI->getOpcode()) {
default: break;
- case Instruction::Add:
- case Instruction::Sub:
- case Instruction::Mul:
+ case Instruction::FAdd:
+ case Instruction::FSub:
+ case Instruction::FMul:
case Instruction::FDiv:
case Instruction::FRem:
const Type *SrcTy = OpI->getType();
@@ -9322,11 +9428,15 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
// Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))). This is
// even legal for FP.
- if (TI->getOpcode() == Instruction::Sub &&
- FI->getOpcode() == Instruction::Add) {
+ if ((TI->getOpcode() == Instruction::Sub &&
+ FI->getOpcode() == Instruction::Add) ||
+ (TI->getOpcode() == Instruction::FSub &&
+ FI->getOpcode() == Instruction::FAdd)) {
AddOp = FI; SubOp = TI;
- } else if (FI->getOpcode() == Instruction::Sub &&
- TI->getOpcode() == Instruction::Add) {
+ } else if ((FI->getOpcode() == Instruction::Sub &&
+ TI->getOpcode() == Instruction::Add) ||
+ (FI->getOpcode() == Instruction::FSub &&
+ TI->getOpcode() == Instruction::FAdd)) {
AddOp = TI; SubOp = FI;
}
diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index 92270b5b647..f05afeca32a 100644
--- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -2268,7 +2268,8 @@ void LoopStrengthReduce::OptimizeShadowIV(Loop *L) {
/* create new increment. '++d' in above example. */
ConstantFP *CFP = ConstantFP::get(DestTy, C->getZExtValue());
BinaryOperator *NewIncr =
- BinaryOperator::Create(Incr->getOpcode(),
+ BinaryOperator::Create(Incr->getOpcode() == Instruction::Add ?
+ Instruction::FAdd : Instruction::FSub,
NewPH, CFP, "IV.S.next.", Incr);
NewPH->addIncoming(NewInit, PH->getIncomingBlock(Entry));
diff --git a/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp
index 4b0064090cf..59989c92d74 100644
--- a/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp
@@ -1009,7 +1009,7 @@ struct VISIBILITY_HIDDEN PowOpt : public LibCallOptimization {
if (Op2C->isExactlyValue(1.0)) // pow(x, 1.0) -> x
return Op1;
if (Op2C->isExactlyValue(2.0)) // pow(x, 2.0) -> x*x
- return B.CreateMul(Op1, Op1, "pow2");
+ return B.CreateFMul(Op1, Op1, "pow2");
if (Op2C->isExactlyValue(-1.0)) // pow(x, -1.0) -> 1.0/x
return B.CreateFDiv(ConstantFP::get(CI->getType(), 1.0), Op1, "powrecip");
return 0;
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 2cde765560b..bcc6b819013 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -419,9 +419,6 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB,
case Instruction::LShr:
case Instruction::AShr:
case Instruction::ICmp:
- case Instruction::FCmp:
- if (I->getOperand(0)->getType()->isFPOrFPVector())
- return false; // FP arithmetic might trap.
break; // These are all cheap and non-trapping instructions.
}
@@ -1012,9 +1009,8 @@ static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *BB1) {
default: return false; // Not safe / profitable to hoist.
case Instruction::Add:
case Instruction::Sub:
- // FP arithmetic might trap. Not worth doing for vector ops.
- if (HInst->getType()->isFloatingPoint()
- || isa<VectorType>(HInst->getType()))
+ // Not worth doing for vector ops.
+ if (isa<VectorType>(HInst->getType()))
return false;
break;
case Instruction::And:
diff --git a/llvm/lib/VMCore/ConstantFold.cpp b/llvm/lib/VMCore/ConstantFold.cpp
index 7e4902fd563..1d293ccbd44 100644
--- a/llvm/lib/VMCore/ConstantFold.cpp
+++ b/llvm/lib/VMCore/ConstantFold.cpp
@@ -602,10 +602,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
return Constant::getNullValue(C1->getType());
case Instruction::UDiv:
case Instruction::SDiv:
- case Instruction::FDiv:
case Instruction::URem:
case Instruction::SRem:
- case Instruction::FRem:
if (!isa<UndefValue>(C2)) // undef / X -> 0
return Constant::getNullValue(C1->getType());
return const_cast<Constant*>(C2); // X / undef -> undef
@@ -783,13 +781,13 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
switch (Opcode) {
default:
break;
- case Instruction::Add:
+ case Instruction::FAdd:
(void)C3V.add(C2V, APFloat::rmNearestTiesToEven);
return ConstantFP::get(C3V);
- case Instruction::Sub:
+ case Instruction::FSub:
(void)C3V.subtract(C2V, APFloat::rmNearestTiesToEven);
return ConstantFP::get(C3V);
- case Instruction::Mul:
+ case Instruction::FMul:
(void)C3V.multiply(C2V, APFloat::rmNearestTiesToEven);
return ConstantFP::get(C3V);
case Instruction::FDiv:
@@ -808,12 +806,18 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
switch (Opcode) {
default:
break;
- case Instruction::Add:
+ case Instruction::Add:
return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getAdd);
- case Instruction::Sub:
+ case Instruction::FAdd:
+ return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getFAdd);
+ case Instruction::Sub:
return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getSub);
- case Instruction::Mul:
+ case Instruction::FSub:
+ return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getFSub);
+ case Instruction::Mul:
return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getMul);
+ case Instruction::FMul:
+ return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getFMul);
case Instruction::UDiv:
return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getUDiv);
case Instruction::SDiv:
@@ -851,7 +855,9 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
// other way if possible.
switch (Opcode) {
case Instruction::Add:
+ case Instruction::FAdd:
case Instruction::Mul:
+ case Instruction::FMul:
case Instruction::And:
case Instruction::Or:
case Instruction::Xor:
@@ -862,6 +868,7 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
case Instruction::LShr:
case Instruction::AShr:
case Instruction::Sub:
+ case Instruction::FSub:
case Instruction::SDiv:
case Instruction::UDiv:
case Instruction::FDiv:
diff --git a/llvm/lib/VMCore/Constants.cpp b/llvm/lib/VMCore/Constants.cpp
index 97f3ac9c270..69c503dff95 100644
--- a/llvm/lib/VMCore/Constants.cpp
+++ b/llvm/lib/VMCore/Constants.cpp
@@ -775,26 +775,46 @@ const SmallVector<unsigned, 4> &ConstantExpr::getIndices() const {
/// specify the full Instruction::OPCODE identifier.
///
Constant *ConstantExpr::getNeg(Constant *C) {
+ // API compatibility: Adjust integer opcodes to floating-point opcodes.
+ if (C->getType()->isFPOrFPVector())
+ return getFNeg(C);
+ assert(C->getType()->isIntOrIntVector() &&
+ "Cannot NEG a nonintegral value!");
return get(Instruction::Sub,
ConstantExpr::getZeroValueForNegationExpr(C->getType()),
C);
}
+Constant *ConstantExpr::getFNeg(Constant *C) {
+ assert(C->getType()->isFPOrFPVector() &&
+ "Cannot FNEG a non-floating-point value!");
+ return get(Instruction::FSub,
+ ConstantExpr::getZeroValueForNegationExpr(C->getType()),
+ C);
+}
Constant *ConstantExpr::getNot(Constant *C) {
- assert((isa<IntegerType>(C->getType()) ||
- cast<VectorType>(C->getType())->getElementType()->isInteger()) &&
- "Cannot NOT a nonintegral value!");
+ assert(C->getType()->isIntOrIntVector() &&
+ "Cannot NOT a nonintegral value!");
return get(Instruction::Xor, C,
Constant::getAllOnesValue(C->getType()));
}
Constant *ConstantExpr::getAdd(Constant *C1, Constant *C2) {
return get(Instruction::Add, C1, C2);
}
+Constant *ConstantExpr::getFAdd(Constant *C1, Constant *C2) {
+ return get(Instruction::FAdd, C1, C2);
+}
Constant *ConstantExpr::getSub(Constant *C1, Constant *C2) {
return get(Instruction::Sub, C1, C2);
}
+Constant *ConstantExpr::getFSub(Constant *C1, Constant *C2) {
+ return get(Instruction::FSub, C1, C2);
+}
Constant *ConstantExpr::getMul(Constant *C1, Constant *C2) {
return get(Instruction::Mul, C1, C2);
}
+Constant *ConstantExpr::getFMul(Constant *C1, Constant *C2) {
+ return get(Instruction::FMul, C1, C2);
+}
Constant *ConstantExpr::getUDiv(Constant *C1, Constant *C2) {
return get(Instruction::UDiv, C1, C2);
}
@@ -2142,15 +2162,28 @@ Constant *ConstantExpr::getCompareTy(unsigned short predicate,
}
Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
+ // API compatibility: Adjust integer opcodes to floating-point opcodes.
+ if (C1->getType()->isFPOrFPVector()) {
+ if (Opcode == Instruction::Add) Opcode = Instruction::FAdd;
+ else if (Opcode == Instruction::Sub) Opcode = Instruction::FSub;
+ else if (Opcode == Instruction::Mul) Opcode = Instruction::FMul;
+ }
#ifndef NDEBUG
switch (Opcode) {
- case Instruction::Add:
+ case Instruction::Add:
case Instruction::Sub:
- case Instruction::Mul:
+ case Instruction::Mul:
assert(C1->getType() == C2->getType() && "Op types should be identical!");
- assert((C1->getType()->isInteger() || C1->getType()->isFloatingPoint() ||
- isa<VectorType>(C1->getType())) &&
- "Tried to create an arithmetic operation on a non-arithmetic type!");
+ assert(C1->getType()->isIntOrIntVector() &&
+ "Tried to create an integer operation on a non-integer type!");
+ break;
+ case Instruction::FAdd:
+ case Instruction::FSub:
+ case Instruction::FMul:
+ assert(C1->getType() == C2->getType() && "Op types should be identical!");
+ assert(C1->getType()->isFPOrFPVector() &&
+ "Tried to create a floating-point operation on a "
+ "non-floating-point type!");
break;
case Instruction::UDiv:
case Instruction::SDiv:
diff --git a/llvm/lib/VMCore/Instruction.cpp b/llvm/lib/VMCore/Instruction.cpp
index 9e030b78e9e..7556b8ebe76 100644
--- a/llvm/lib/VMCore/Instruction.cpp
+++ b/llvm/lib/VMCore/Instruction.cpp
@@ -101,8 +101,11 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
// Standard binary operators...
case Add: return "add";
+ case FAdd: return "fadd";
case Sub: return "sub";
+ case FSub: return "fsub";
case Mul: return "mul";
+ case FMul: return "fmul";
case UDiv: return "udiv";
case SDiv: return "sdiv";
case FDiv: return "fdiv";
@@ -330,19 +333,13 @@ bool Instruction::mayThrow() const {
/// isAssociative - Return true if the instruction is associative:
///
-/// Associative operators satisfy: x op (y op z) === (x op y) op z)
+/// Associative operators satisfy: x op (y op z) === (x op y) op z
///
-/// In LLVM, the Add, Mul, And, Or, and Xor operators are associative, when not
-/// applied to floating point types.
+/// In LLVM, the Add, Mul, And, Or, and Xor operators are associative.
///
bool Instruction::isAssociative(unsigned Opcode, const Type *Ty) {
- if (Opcode == And || Opcode == Or || Opcode == Xor)
- return true;
-
- // Add/Mul reassociate unless they are FP or FP vectors.
- if (Opcode == Add || Opcode == Mul)
- return !Ty->isFPOrFPVector();
- return 0;
+ return Opcode == And || Opcode == Or || Opcode == Xor ||
+ Opcode == Add || Opcode == Mul;
}
/// isCommutative - Return true if the instruction is commutative:
@@ -355,7 +352,9 @@ bool Instruction::isAssociative(unsigned Opcode, const Type *Ty) {
bool Instruction::isCommutative(unsigned op) {
switch (op) {
case Add:
+ case FAdd:
case Mul:
+ case FMul:
case And:
case Or:
case Xor:
diff --git a/llvm/lib/VMCore/Instructions.cpp b/llvm/lib/VMCore/Instructions.cpp
index fe30271f844..4c228fe81c0 100644
--- a/llvm/lib/VMCore/Instructions.cpp
+++ b/llvm/lib/VMCore/Instructions.cpp
@@ -1502,29 +1502,43 @@ const Type* ExtractValueInst::getIndexedType(const Type *Agg,
// BinaryOperator Class
//===----------------------------------------------------------------------===//
+/// AdjustIType - Map Add, Sub, and Mul to FAdd, FSub, and FMul when the
+/// type is floating-point, to help provide compatibility with an older API.
+///
+static BinaryOperator::BinaryOps AdjustIType(BinaryOperator::BinaryOps iType,
+ const Type *Ty) {
+ // API compatibility: Adjust integer opcodes to floating-point opcodes.
+ if (Ty->isFPOrFPVector()) {
+ if (iType == BinaryOperator::Add) iType = BinaryOperator::FAdd;
+ else if (iType == BinaryOperator::Sub) iType = BinaryOperator::FSub;
+ else if (iType == BinaryOperator::Mul) iType = BinaryOperator::FMul;
+ }
+ return iType;
+}
+
BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2,
const Type *Ty, const std::string &Name,
Instruction *InsertBefore)
- : Instruction(Ty, iType,
+ : Instruction(Ty, AdjustIType(iType, Ty),
OperandTraits<BinaryOperator>::op_begin(this),
OperandTraits<BinaryOperator>::operands(this),
InsertBefore) {
Op<0>() = S1;
Op<1>() = S2;
- init(iType);
+ init(AdjustIType(iType, Ty));
setName(Name);
}
BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2,
const Type *Ty, const std::string &Name,
BasicBlock *InsertAtEnd)
- : Instruction(Ty, iType,
+ : Instruction(Ty, AdjustIType(iType, Ty),
OperandTraits<BinaryOperator>::op_begin(this),
OperandTraits<BinaryOperator>::operands(this),
InsertAtEnd) {
Op<0>() = S1;
Op<1>() = S2;
- init(iType);
+ init(AdjustIType(iType, Ty));
setName(Name);
}
@@ -1537,12 +1551,19 @@ void BinaryOperator::init(BinaryOps iType) {
#ifndef NDEBUG
switch (iType) {
case Add: case Sub:
- case Mul:
+ case Mul:
+ assert(getType() == LHS->getType() &&
+ "Arithmetic operation should return same type as operands!");
+ assert(getType()->isIntOrIntVector() &&
+ "Tried to create an integer operation on a non-integer type!");
+ break;
+ case FAdd: case FSub:
+ case FMul:
assert(getType() == LHS->getType() &&
"Arithmetic operation should return same type as operands!");
- assert((getType()->isInteger() || getType()->isFloatingPoint() ||
- isa<VectorType>(getType())) &&
- "Tried to create an arithmetic operation on a non-arithmetic type!");
+ assert(getType()->isFPOrFPVector() &&
+ "Tried to create a floating-point operation on a "
+ "non-floating-point type!");
break;
case UDiv:
case SDiv:
@@ -1631,6 +1652,22 @@ BinaryOperator *BinaryOperator::CreateNeg(Value *Op, const std::string &Name,
Op->getType(), Name, InsertAtEnd);
}
+BinaryOperator *BinaryOperator::CreateFNeg(Value *Op, const std::string &Name,
+ Instruction *InsertBefore) {
+ Value *zero = ConstantExpr::getZeroValueForNegationExpr(Op->getType());
+ return new BinaryOperator(Instruction::FSub,
+ zero, Op,
+ Op->getType(), Name, InsertBefore);
+}
+
+BinaryOperator *BinaryOperator::CreateFNeg(Value *Op, const std::string &Name,
+ BasicBlock *InsertAtEnd) {
+ Value *zero = ConstantExpr::getZeroValueForNegationExpr(Op->getType());
+ return new BinaryOperator(Instruction::FSub,
+ zero, Op,
+ Op->getType(), Name, InsertAtEnd);
+}
+
BinaryOperator *BinaryOperator::CreateNot(Value *Op, const std::string &Name,
Instruction *InsertBefore) {
Constant *C;
@@ -1679,6 +1716,14 @@ bool BinaryOperator::isNeg(const Value *V) {
return false;
}
+bool BinaryOperator::isFNeg(const Value *V) {
+ if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V))
+ if (Bop->getOpcode() == Instruction::FSub)
+ return Bop->getOperand(0) ==
+ ConstantExpr::getZeroValueForNegationExpr(Bop->getType());
+ return false;
+}
+
bool BinaryOperator::isNot(const Value *V) {
if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V))
return (Bop->getOpcode() == Instruction::Xor &&
@@ -1696,6 +1741,15 @@ const Value *BinaryOperator::getNegArgument(const Value *BinOp) {
return getNegArgument(const_cast<Value*>(BinOp));
}
+Value *BinaryOperator::getFNegArgument(Value *BinOp) {
+ assert(isFNeg(BinOp) && "getFNegArgument from non-'fneg' instruction!");
+ return cast<BinaryOperator>(BinOp)->getOperand(1);
+}
+
+const Value *BinaryOperator::getFNegArgument(const Value *BinOp) {
+ return getFNegArgument(const_cast<Value*>(BinOp));
+}
+
Value *BinaryOperator::getNotArgument(Value *BinOp) {
assert(isNot(BinOp) && "getNotArgument on non-'not' instruction!");
BinaryOperator *BO = cast<BinaryOperator>(BinOp);
OpenPOWER on IntegriCloud