mirror of
https://github.com/RPCSX/llvm.git
synced 2025-04-02 08:11:54 +00:00
For PR950:
This patch removes the SetCC instructions and replaces them with the ICmp and FCmp instructions. The SetCondInst instruction has been removed and been replaced with ICmpInst and FCmpInst. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32751 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
add2bd7f59
commit
e4d87aa2de
@ -58,7 +58,7 @@ static Function *CreateFibFunction(Module *M) {
|
||||
BasicBlock* RecurseBB = new BasicBlock("recurse", FibF);
|
||||
|
||||
// Create the "if (arg < 2) goto exitbb"
|
||||
Value *CondInst = BinaryOperator::createSetLE(ArgX, Two, "cond", BB);
|
||||
Value *CondInst = new ICmpInst(ICmpInst::ICMP_SLE, ArgX, Two, "cond", BB);
|
||||
new BranchInst(RetBB, RecurseBB, CondInst, BB);
|
||||
|
||||
// Create: ret int 1
|
||||
|
@ -83,7 +83,7 @@ static Function *CreateFibFunction(Module *M)
|
||||
BasicBlock* RecurseBB = new BasicBlock("recurse", FibF);
|
||||
|
||||
// Create the "if (arg < 2) goto exitbb"
|
||||
Value *CondInst = BinaryOperator::createSetLE(ArgX, Two, "cond", BB);
|
||||
Value *CondInst = new ICmpInst(ICmpInst::ICMP_SLE, ArgX, Two, "cond", BB);
|
||||
new BranchInst(RetBB, RecurseBB, CondInst, BB);
|
||||
|
||||
// Create: ret int 1
|
||||
|
@ -426,8 +426,10 @@ namespace llvm {
|
||||
/// looking at this is that it returns the first iteration number where the
|
||||
/// value is not in the condition, thus computing the exit count. If the
|
||||
/// iteration count can't be computed, an instance of SCEVCouldNotCompute is
|
||||
/// returned.
|
||||
SCEVHandle getNumIterationsInRange(ConstantRange Range) const;
|
||||
/// returned. The isSigned parameter indicates whether the ConstantRange
|
||||
/// should be treated as signed or unsigned.
|
||||
SCEVHandle getNumIterationsInRange(ConstantRange Range,
|
||||
bool isSigned) const;
|
||||
|
||||
SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
|
||||
const SCEVHandle &Conc) const;
|
||||
|
@ -496,8 +496,8 @@ protected:
|
||||
// ConstantExprs in intermediate forms.
|
||||
static Constant *getTy(const Type *Ty, unsigned Opcode,
|
||||
Constant *C1, Constant *C2);
|
||||
static Constant *getCompareTy(unsigned Opcode, unsigned short pred,
|
||||
Constant *C1, Constant *C2);
|
||||
static Constant *getCompareTy(unsigned short pred, Constant *C1,
|
||||
Constant *C2);
|
||||
static Constant *getShiftTy(const Type *Ty,
|
||||
unsigned Opcode, Constant *C1, Constant *C2);
|
||||
static Constant *getSelectTy(const Type *Ty,
|
||||
@ -604,8 +604,7 @@ public:
|
||||
static Constant *get(unsigned Opcode, Constant *C1, Constant *C2);
|
||||
|
||||
/// @brief Return an ICmp or FCmp comparison operator constant expression.
|
||||
static Constant *getCompare(unsigned Opcode, unsigned short pred,
|
||||
Constant *C1, Constant *C2);
|
||||
static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2);
|
||||
|
||||
/// ConstantExpr::get* - Return some common constants without having to
|
||||
/// specify the full Instruction::OPCODE identifier.
|
||||
@ -624,12 +623,6 @@ public:
|
||||
static Constant *getAnd(Constant *C1, Constant *C2);
|
||||
static Constant *getOr(Constant *C1, Constant *C2);
|
||||
static Constant *getXor(Constant *C1, Constant *C2);
|
||||
static Constant *getSetEQ(Constant *C1, Constant *C2);
|
||||
static Constant *getSetNE(Constant *C1, Constant *C2);
|
||||
static Constant *getSetLT(Constant *C1, Constant *C2);
|
||||
static Constant *getSetGT(Constant *C1, Constant *C2);
|
||||
static Constant *getSetLE(Constant *C1, Constant *C2);
|
||||
static Constant *getSetGE(Constant *C1, Constant *C2);
|
||||
static Constant* getICmp(unsigned short pred, Constant* LHS, Constant* RHS);
|
||||
static Constant* getFCmp(unsigned short pred, Constant* LHS, Constant* RHS);
|
||||
static Constant *getShl(Constant *C1, Constant *C2);
|
||||
|
@ -543,6 +543,20 @@ public:
|
||||
/// @brief Determine if this is an equals/not equals predicate.
|
||||
bool isEquality();
|
||||
|
||||
/// @returns true if the predicate is unsigned, false otherwise.
|
||||
/// @brief Determine if the predicate is an unsigned operation.
|
||||
static bool isUnsigned(unsigned short predicate);
|
||||
|
||||
/// @returns true if the predicate is signed, false otherwise.
|
||||
/// @brief Determine if the predicate is an signed operation.
|
||||
static bool isSigned(unsigned short predicate);
|
||||
|
||||
/// @brief Determine if the predicate is an ordered operation.
|
||||
static bool isOrdered(unsigned short predicate);
|
||||
|
||||
/// @brief Determine if the predicate is an unordered operation.
|
||||
static bool isUnordered(unsigned short predicate);
|
||||
|
||||
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const CmpInst *) { return true; }
|
||||
static inline bool classof(const Instruction *I) {
|
||||
|
@ -118,61 +118,53 @@ HANDLE_BINARY_INST(15, FRem , BinaryOperator)
|
||||
HANDLE_BINARY_INST(16, And , BinaryOperator)
|
||||
HANDLE_BINARY_INST(17, Or , BinaryOperator)
|
||||
HANDLE_BINARY_INST(18, Xor , BinaryOperator)
|
||||
|
||||
// Binary comparison operators...
|
||||
HANDLE_BINARY_INST(19, SetEQ , SetCondInst)
|
||||
HANDLE_BINARY_INST(20, SetNE , SetCondInst)
|
||||
HANDLE_BINARY_INST(21, SetLE , SetCondInst)
|
||||
HANDLE_BINARY_INST(22, SetGE , SetCondInst)
|
||||
HANDLE_BINARY_INST(23, SetLT , SetCondInst)
|
||||
HANDLE_BINARY_INST(24, SetGT , SetCondInst)
|
||||
LAST_BINARY_INST(24)
|
||||
LAST_BINARY_INST(18)
|
||||
|
||||
// Memory operators...
|
||||
FIRST_MEMORY_INST(25)
|
||||
HANDLE_MEMORY_INST(25, Malloc, MallocInst) // Heap management instructions
|
||||
HANDLE_MEMORY_INST(26, Free , FreeInst )
|
||||
HANDLE_MEMORY_INST(27, Alloca, AllocaInst) // Stack management
|
||||
HANDLE_MEMORY_INST(28, Load , LoadInst ) // Memory manipulation instrs
|
||||
HANDLE_MEMORY_INST(29, Store , StoreInst )
|
||||
HANDLE_MEMORY_INST(30, GetElementPtr, GetElementPtrInst)
|
||||
LAST_MEMORY_INST(30)
|
||||
FIRST_MEMORY_INST(19)
|
||||
HANDLE_MEMORY_INST(19, Malloc, MallocInst) // Heap management instructions
|
||||
HANDLE_MEMORY_INST(20, Free , FreeInst )
|
||||
HANDLE_MEMORY_INST(21, Alloca, AllocaInst) // Stack management
|
||||
HANDLE_MEMORY_INST(22, Load , LoadInst ) // Memory manipulation instrs
|
||||
HANDLE_MEMORY_INST(23, Store , StoreInst )
|
||||
HANDLE_MEMORY_INST(24, GetElementPtr, GetElementPtrInst)
|
||||
LAST_MEMORY_INST(24)
|
||||
|
||||
// Cast operators ...
|
||||
// NOTE: The order matters here because CastInst::isEliminableCastPair
|
||||
// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
|
||||
FIRST_CAST_INST(31)
|
||||
HANDLE_CAST_INST(31, Trunc , TruncInst ) // Truncate integers
|
||||
HANDLE_CAST_INST(32, ZExt , ZExtInst ) // Zero extend integers
|
||||
HANDLE_CAST_INST(33, SExt , SExtInst ) // Sign extend integers
|
||||
HANDLE_CAST_INST(34, FPToUI , FPToUIInst ) // floating point -> UInt
|
||||
HANDLE_CAST_INST(35, FPToSI , FPToSIInst ) // floating point -> SInt
|
||||
HANDLE_CAST_INST(36, UIToFP , UIToFPInst ) // UInt -> floating point
|
||||
HANDLE_CAST_INST(37, SIToFP , SIToFPInst ) // SInt -> floating point
|
||||
HANDLE_CAST_INST(38, FPTrunc , FPTruncInst ) // Truncate floating point
|
||||
HANDLE_CAST_INST(39, FPExt , FPExtInst ) // Extend floating point
|
||||
HANDLE_CAST_INST(40, PtrToInt, PtrToIntInst) // Pointer -> Integer
|
||||
HANDLE_CAST_INST(41, IntToPtr, IntToPtrInst) // Integer -> Pointer
|
||||
HANDLE_CAST_INST(42, BitCast , BitCastInst ) // Type cast
|
||||
LAST_CAST_INST(42)
|
||||
FIRST_CAST_INST(25)
|
||||
HANDLE_CAST_INST(25, Trunc , TruncInst ) // Truncate integers
|
||||
HANDLE_CAST_INST(26, ZExt , ZExtInst ) // Zero extend integers
|
||||
HANDLE_CAST_INST(27, SExt , SExtInst ) // Sign extend integers
|
||||
HANDLE_CAST_INST(28, FPToUI , FPToUIInst ) // floating point -> UInt
|
||||
HANDLE_CAST_INST(29, FPToSI , FPToSIInst ) // floating point -> SInt
|
||||
HANDLE_CAST_INST(30, UIToFP , UIToFPInst ) // UInt -> floating point
|
||||
HANDLE_CAST_INST(31, SIToFP , SIToFPInst ) // SInt -> floating point
|
||||
HANDLE_CAST_INST(32, FPTrunc , FPTruncInst ) // Truncate floating point
|
||||
HANDLE_CAST_INST(33, FPExt , FPExtInst ) // Extend floating point
|
||||
HANDLE_CAST_INST(34, PtrToInt, PtrToIntInst) // Pointer -> Integer
|
||||
HANDLE_CAST_INST(35, IntToPtr, IntToPtrInst) // Integer -> Pointer
|
||||
HANDLE_CAST_INST(36, BitCast , BitCastInst ) // Type cast
|
||||
LAST_CAST_INST(36)
|
||||
|
||||
// Other operators...
|
||||
FIRST_OTHER_INST(43)
|
||||
HANDLE_OTHER_INST(43, ICmp , ICmpInst ) // Integer comparison instruction
|
||||
HANDLE_OTHER_INST(44, FCmp , FCmpInst ) // Floating point comparison instr.
|
||||
HANDLE_OTHER_INST(45, PHI , PHINode ) // PHI node instruction
|
||||
HANDLE_OTHER_INST(46, Call , CallInst ) // Call a function
|
||||
HANDLE_OTHER_INST(47, Shl , ShiftInst ) // Shift Left operations (logical)
|
||||
HANDLE_OTHER_INST(48, LShr , ShiftInst ) // Logical Shift right (unsigned)
|
||||
HANDLE_OTHER_INST(49, AShr , ShiftInst ) // Arithmetic shift right (signed)
|
||||
HANDLE_OTHER_INST(50, Select , SelectInst ) // select instruction
|
||||
HANDLE_OTHER_INST(51, UserOp1, Instruction) // May be used internally in a pass
|
||||
HANDLE_OTHER_INST(52, UserOp2, Instruction) // Internal to passes only
|
||||
HANDLE_OTHER_INST(53, VAArg , VAArgInst ) // vaarg instruction
|
||||
HANDLE_OTHER_INST(54, ExtractElement, ExtractElementInst)// extract from vector.
|
||||
HANDLE_OTHER_INST(55, InsertElement, InsertElementInst) // insert into vector
|
||||
HANDLE_OTHER_INST(56, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
|
||||
LAST_OTHER_INST(56)
|
||||
FIRST_OTHER_INST(37)
|
||||
HANDLE_OTHER_INST(37, ICmp , ICmpInst ) // Integer comparison instruction
|
||||
HANDLE_OTHER_INST(38, FCmp , FCmpInst ) // Floating point comparison instr.
|
||||
HANDLE_OTHER_INST(39, PHI , PHINode ) // PHI node instruction
|
||||
HANDLE_OTHER_INST(40, Call , CallInst ) // Call a function
|
||||
HANDLE_OTHER_INST(41, Shl , ShiftInst ) // Shift Left operations (logical)
|
||||
HANDLE_OTHER_INST(42, LShr , ShiftInst ) // Logical Shift right (unsigned)
|
||||
HANDLE_OTHER_INST(43, AShr , ShiftInst ) // Arithmetic shift right (signed)
|
||||
HANDLE_OTHER_INST(44, Select , SelectInst ) // select instruction
|
||||
HANDLE_OTHER_INST(45, UserOp1, Instruction) // May be used internally in a pass
|
||||
HANDLE_OTHER_INST(46, UserOp2, Instruction) // Internal to passes only
|
||||
HANDLE_OTHER_INST(47, VAArg , VAArgInst ) // vaarg instruction
|
||||
HANDLE_OTHER_INST(48, ExtractElement, ExtractElementInst)// extract from vector.
|
||||
HANDLE_OTHER_INST(49, InsertElement, InsertElementInst) // insert into vector
|
||||
HANDLE_OTHER_INST(50, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
|
||||
LAST_OTHER_INST(50)
|
||||
|
||||
#undef FIRST_TERM_INST
|
||||
#undef HANDLE_TERM_INST
|
||||
|
@ -71,6 +71,16 @@ public:
|
||||
/// extra information (e.g. load is volatile) agree.
|
||||
bool isIdenticalTo(Instruction *I) const;
|
||||
|
||||
/// This function determines if the specified instruction executes the same
|
||||
/// operation as the current one. This means that the opcodes, type, operand
|
||||
/// types and any other factors affecting the operation must be the same. This
|
||||
/// is similar to isIdenticalTo except the operands themselves don't have to
|
||||
/// be identical.
|
||||
/// @returns true if the specified instruction is the same operation as
|
||||
/// the current one.
|
||||
/// @brief Determine if one instruction is the same operation as another.
|
||||
bool isSameOperationAs(Instruction *I) const;
|
||||
|
||||
/// use_back - Specialize the methods defined in Value, as we know that an
|
||||
/// instruction can only be used by other instructions.
|
||||
Instruction *use_back() { return cast<Instruction>(*use_begin());}
|
||||
@ -155,12 +165,6 @@ public:
|
||||
bool isCommutative() const { return isCommutative(getOpcode()); }
|
||||
static bool isCommutative(unsigned op);
|
||||
|
||||
/// isComparison - Return true if the instruction is a Set* instruction:
|
||||
///
|
||||
bool isComparison() const { return isComparison(getOpcode()); }
|
||||
static bool isComparison(unsigned op);
|
||||
|
||||
|
||||
/// isTrappingInstruction - Return true if the instruction may trap.
|
||||
///
|
||||
bool isTrapping() const {
|
||||
|
@ -440,7 +440,8 @@ public:
|
||||
ICMP_SLT = 40, ///< signed less than
|
||||
ICMP_SLE = 41, ///< signed less or equal
|
||||
FIRST_ICMP_PREDICATE = ICMP_EQ,
|
||||
LAST_ICMP_PREDICATE = ICMP_SLE
|
||||
LAST_ICMP_PREDICATE = ICMP_SLE,
|
||||
BAD_ICMP_PREDICATE = ICMP_SLE + 1
|
||||
};
|
||||
|
||||
/// @brief Constructor with insert-before-instruction semantics.
|
||||
@ -490,16 +491,30 @@ public:
|
||||
/// This is a static version that you can use without an instruction
|
||||
/// available.
|
||||
/// @brief Return the predicate as if the operands were swapped.
|
||||
static Predicate getSwappedPredicate(Predicate Opcode);
|
||||
static Predicate getSwappedPredicate(Predicate pred);
|
||||
|
||||
/// For example, EQ->EQ, SLE->SLE, UGT->SGT, etc.
|
||||
/// @returns the predicate that would be the result if the operand were
|
||||
/// regarded as signed.
|
||||
/// @brief Return the signed version of the predicate
|
||||
Predicate getSignedPredicate() const {
|
||||
return getSignedPredicate(getPredicate());
|
||||
}
|
||||
|
||||
/// This is a static version that you can use without an instruction.
|
||||
/// @brief Return the signed version of the predicate.
|
||||
static Predicate getSignedPredicate(Predicate pred);
|
||||
|
||||
/// This also tests for commutativity. If isEquality() returns true then
|
||||
/// the predicate is also commutative. Only the equality predicates are
|
||||
/// commutative.
|
||||
/// the predicate is also commutative.
|
||||
/// @returns true if the predicate of this instruction is EQ or NE.
|
||||
/// @brief Determine if this is an equality predicate.
|
||||
bool isEquality() const {
|
||||
return SubclassData == ICMP_EQ || SubclassData == ICMP_NE;
|
||||
}
|
||||
|
||||
/// @returns true if the predicate of this ICmpInst is commutative
|
||||
/// @brief Determine if this relation is commutative.
|
||||
bool isCommutative() const { return isEquality(); }
|
||||
|
||||
/// @returns true if the predicate is relational (not EQ or NE).
|
||||
@ -508,6 +523,14 @@ public:
|
||||
return !isEquality();
|
||||
}
|
||||
|
||||
/// @returns true if the predicate of this ICmpInst is signed, false otherwise
|
||||
/// @brief Determine if this instruction's predicate is signed.
|
||||
bool isSignedPredicate() { return isSignedPredicate(getPredicate()); }
|
||||
|
||||
/// @returns true if the predicate provided is signed, false otherwise
|
||||
/// @brief Determine if the predicate is signed.
|
||||
static bool isSignedPredicate(Predicate pred);
|
||||
|
||||
/// Exchange the two operands to this instruction in such a way that it does
|
||||
/// not modify the semantics of the instruction. The predicate value may be
|
||||
/// changed to retain the same result if the predicate is order dependent
|
||||
@ -559,7 +582,8 @@ public:
|
||||
FCMP_UNE =14, ///< 1 1 1 0 True if unordered or not equal
|
||||
FCMP_TRUE =15, ///< 1 1 1 1 Always true (always folded)
|
||||
FIRST_FCMP_PREDICATE = FCMP_FALSE,
|
||||
LAST_FCMP_PREDICATE = FCMP_TRUE
|
||||
LAST_FCMP_PREDICATE = FCMP_TRUE,
|
||||
BAD_FCMP_PREDICATE = FCMP_TRUE + 1
|
||||
};
|
||||
|
||||
/// @brief Constructor with insert-before-instruction semantics.
|
||||
@ -646,71 +670,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SetCondInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// SetCondInst class - Represent a setCC operator, where CC is eq, ne, lt, gt,
|
||||
/// le, or ge.
|
||||
///
|
||||
class SetCondInst : public BinaryOperator {
|
||||
public:
|
||||
SetCondInst(BinaryOps Opcode, Value *LHS, Value *RHS,
|
||||
const std::string &Name = "", Instruction *InsertBefore = 0);
|
||||
SetCondInst(BinaryOps Opcode, Value *LHS, Value *RHS,
|
||||
const std::string &Name, BasicBlock *InsertAtEnd);
|
||||
|
||||
/// getInverseCondition - Return the inverse of the current condition opcode.
|
||||
/// For example seteq -> setne, setgt -> setle, setlt -> setge, etc...
|
||||
///
|
||||
BinaryOps getInverseCondition() const {
|
||||
return getInverseCondition(getOpcode());
|
||||
}
|
||||
|
||||
/// getInverseCondition - Static version that you can use without an
|
||||
/// instruction available.
|
||||
///
|
||||
static BinaryOps getInverseCondition(BinaryOps Opcode);
|
||||
|
||||
/// getSwappedCondition - Return the condition opcode that would be the result
|
||||
/// of exchanging the two operands of the setcc instruction without changing
|
||||
/// the result produced. Thus, seteq->seteq, setle->setge, setlt->setgt, etc.
|
||||
///
|
||||
BinaryOps getSwappedCondition() const {
|
||||
return getSwappedCondition(getOpcode());
|
||||
}
|
||||
|
||||
/// getSwappedCondition - Static version that you can use without an
|
||||
/// instruction available.
|
||||
///
|
||||
static BinaryOps getSwappedCondition(BinaryOps Opcode);
|
||||
|
||||
/// isEquality - Return true if this comparison is an ==/!= comparison.
|
||||
///
|
||||
bool isEquality() const {
|
||||
return getOpcode() == SetEQ || getOpcode() == SetNE;
|
||||
}
|
||||
|
||||
/// isRelational - Return true if this comparison is a </>/<=/>= comparison.
|
||||
///
|
||||
bool isRelational() const {
|
||||
return !isEquality();
|
||||
}
|
||||
|
||||
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const SetCondInst *) { return true; }
|
||||
static inline bool classof(const Instruction *I) {
|
||||
return I->getOpcode() == SetEQ || I->getOpcode() == SetNE ||
|
||||
I->getOpcode() == SetLE || I->getOpcode() == SetGE ||
|
||||
I->getOpcode() == SetLT || I->getOpcode() == SetGT;
|
||||
}
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CallInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include <typeinfo>
|
||||
#include <cassert>
|
||||
|
||||
//#define USE_OLD_PASSMANAGER 1
|
||||
#define USE_OLD_PASSMANAGER 1
|
||||
|
||||
namespace llvm {
|
||||
|
||||
|
@ -12,13 +12,19 @@
|
||||
// constant, which MAY wrap around the end of the numeric range. To do this, it
|
||||
// keeps track of a [lower, upper) bound, which specifies an interval just like
|
||||
// STL iterators. When used with boolean values, the following are important
|
||||
// ranges (other integral ranges use min/max values for special range values):
|
||||
// ranges: :
|
||||
//
|
||||
// [F, F) = {} = Empty set
|
||||
// [T, F) = {T}
|
||||
// [F, T) = {F}
|
||||
// [T, T) = {F, T} = Full set
|
||||
//
|
||||
// The other integral ranges use min/max values for special range values. For
|
||||
// example, for 8-bit types, it uses:
|
||||
// [0, 0) = {} = Empty set
|
||||
// [255, 255) = {0..255} = Full Set
|
||||
//
|
||||
// Note that ConstantRange always keeps unsigned values.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_CONSTANT_RANGE_H
|
||||
@ -51,9 +57,11 @@ class ConstantRange {
|
||||
///
|
||||
ConstantRange(Constant *Lower, Constant *Upper);
|
||||
|
||||
/// Initialize a set of values that all satisfy the condition with C.
|
||||
///
|
||||
ConstantRange(unsigned SetCCOpcode, ConstantIntegral *C);
|
||||
/// Initialize a set of values that all satisfy the predicate with C. The
|
||||
/// predicate should be either an ICmpInst::Predicate or FCmpInst::Predicate
|
||||
/// value.
|
||||
/// @brief Get a range for a relation with a constant integral.
|
||||
ConstantRange(unsigned short predicate, ConstantIntegral *C);
|
||||
|
||||
/// getLower - Return the lower value for this range...
|
||||
///
|
||||
@ -79,11 +87,13 @@ class ConstantRange {
|
||||
/// isWrappedSet - Return true if this set wraps around the top of the range,
|
||||
/// for example: [100, 8)
|
||||
///
|
||||
bool isWrappedSet() const;
|
||||
bool isWrappedSet(bool isSigned) const;
|
||||
|
||||
/// contains - Return true if the specified value is in the set.
|
||||
/// The isSigned parameter indicates whether the comparisons should be
|
||||
/// performed as if the values are signed or not.
|
||||
///
|
||||
bool contains(ConstantInt *Val) const;
|
||||
bool contains(ConstantInt *Val, bool isSigned) const;
|
||||
|
||||
/// getSingleElement - If this set contains a single element, return it,
|
||||
/// otherwise return null.
|
||||
@ -117,7 +127,7 @@ class ConstantRange {
|
||||
/// one of the sets but not the other. For example: [100, 8) intersect [3,
|
||||
/// 120) yields [3, 120)
|
||||
///
|
||||
ConstantRange intersectWith(const ConstantRange &CR) const;
|
||||
ConstantRange intersectWith(const ConstantRange &CR, bool isSigned) const;
|
||||
|
||||
/// union - Return the range that results from the union of this range with
|
||||
/// another range. The resultant range is guaranteed to include the elements
|
||||
@ -125,7 +135,7 @@ class ConstantRange {
|
||||
/// [3, 15), which includes 9, 10, and 11, which were not included in either
|
||||
/// set before.
|
||||
///
|
||||
ConstantRange unionWith(const ConstantRange &CR) const;
|
||||
ConstantRange unionWith(const ConstantRange &CR, bool isSigned) const;
|
||||
|
||||
/// zeroExtend - Return a new range in the specified integer type, which must
|
||||
/// be strictly larger than the current type. The returned range will
|
||||
|
@ -167,7 +167,6 @@ public:
|
||||
RetTy visitInvokeInst(InvokeInst &I) { DELEGATE(TerminatorInst);}
|
||||
RetTy visitUnwindInst(UnwindInst &I) { DELEGATE(TerminatorInst);}
|
||||
RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);}
|
||||
RetTy visitSetCondInst(SetCondInst &I) { DELEGATE(BinaryOperator);}
|
||||
RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);}
|
||||
RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);}
|
||||
RetTy visitMallocInst(MallocInst &I) { DELEGATE(AllocationInst);}
|
||||
|
@ -247,13 +247,6 @@ struct BinaryOpClass_match {
|
||||
}
|
||||
};
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
inline BinaryOpClass_match<LHS, RHS, SetCondInst, Instruction::BinaryOps>
|
||||
m_SetCond(Instruction::BinaryOps &Op, const LHS &L, const RHS &R) {
|
||||
return BinaryOpClass_match<LHS, RHS,
|
||||
SetCondInst, Instruction::BinaryOps>(Op, L, R);
|
||||
}
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
inline BinaryOpClass_match<LHS, RHS, ShiftInst, Instruction::OtherOps>
|
||||
m_Shift(Instruction::OtherOps &Op, const LHS &L, const RHS &R) {
|
||||
@ -269,6 +262,45 @@ m_Shift(const LHS &L, const RHS &R) {
|
||||
ShiftInst, Instruction::OtherOps>(Op, L, R);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Matchers for CmpInst classes
|
||||
//
|
||||
|
||||
template<typename LHS_t, typename RHS_t, typename Class, typename PredicateTy>
|
||||
struct CmpClass_match {
|
||||
PredicateTy &Predicate;
|
||||
LHS_t L;
|
||||
RHS_t R;
|
||||
|
||||
CmpClass_match(PredicateTy &Pred, const LHS_t &LHS,
|
||||
const RHS_t &RHS)
|
||||
: Predicate(Pred), L(LHS), R(RHS) {}
|
||||
|
||||
template<typename OpTy>
|
||||
bool match(OpTy *V) {
|
||||
if (Class *I = dyn_cast<Class>(V))
|
||||
if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) {
|
||||
Predicate = I->getPredicate();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
|
||||
m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
|
||||
return CmpClass_match<LHS, RHS,
|
||||
ICmpInst, ICmpInst::Predicate>(Pred, L, R);
|
||||
}
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
|
||||
m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
|
||||
return CmpClass_match<LHS, RHS,
|
||||
FCmpInst, FCmpInst::Predicate>(Pred, L, R);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Matchers for unary operators
|
||||
//
|
||||
|
@ -49,13 +49,15 @@ bool ConstantFoldTerminator(BasicBlock *BB);
|
||||
Constant *ConstantFoldInstruction(Instruction *I);
|
||||
|
||||
/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
|
||||
/// specified opcode and operands. If successful, the constant result is
|
||||
/// returned, if not, null is returned. Note that this function can fail when
|
||||
/// attempting to fold instructions like loads and stores, which have no
|
||||
/// constant expression form.
|
||||
/// specified operands. If successful, the constant result is returned, if not,
|
||||
/// null is returned. Note that this function can fail when attempting to
|
||||
/// fold instructions like loads and stores, which have no constant expression
|
||||
/// form.
|
||||
///
|
||||
Constant *ConstantFoldInstOperands(unsigned Opc, const Type *DestTy,
|
||||
const std::vector<Constant*> &Ops);
|
||||
Constant *ConstantFoldInstOperands(
|
||||
const Instruction *I, ///< The model instruction
|
||||
const std::vector<Constant*> &Ops ///< The constant operands to use.
|
||||
);
|
||||
|
||||
|
||||
/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a
|
||||
|
@ -590,7 +590,8 @@ BasicAliasAnalysis::CheckGEPInstructions(
|
||||
// Make sure they are comparable (ie, not constant expressions), and
|
||||
// make sure the GEP with the smaller leading constant is GEP1.
|
||||
if (G1OC) {
|
||||
Constant *Compare = ConstantExpr::getSetGT(G1OC, G2OC);
|
||||
Constant *Compare = ConstantExpr::getICmp(ICmpInst::ICMP_SGT,
|
||||
G1OC, G2OC);
|
||||
if (ConstantBool *CV = dyn_cast<ConstantBool>(Compare)) {
|
||||
if (CV->getValue()) // If they are comparable and G2 > G1
|
||||
std::swap(GEP1Ops, GEP2Ops); // Make GEP1 < GEP2
|
||||
|
@ -24,56 +24,43 @@
|
||||
#include "llvm/Support/ConstantRange.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/Instruction.h"
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/Type.h"
|
||||
#include "llvm/Support/Streams.h"
|
||||
#include <ostream>
|
||||
using namespace llvm;
|
||||
|
||||
static ConstantIntegral *getMaxValue(const Type *Ty) {
|
||||
switch (Ty->getTypeID()) {
|
||||
case Type::BoolTyID: return ConstantBool::getTrue();
|
||||
case Type::SByteTyID:
|
||||
case Type::ShortTyID:
|
||||
case Type::IntTyID:
|
||||
case Type::LongTyID: {
|
||||
// Calculate 011111111111111...
|
||||
unsigned TypeBits = Ty->getPrimitiveSize()*8;
|
||||
int64_t Val = INT64_MAX; // All ones
|
||||
Val >>= 64-TypeBits; // Shift out unwanted 1 bits...
|
||||
return ConstantInt::get(Ty, Val);
|
||||
}
|
||||
|
||||
case Type::UByteTyID:
|
||||
case Type::UShortTyID:
|
||||
case Type::UIntTyID:
|
||||
case Type::ULongTyID: return ConstantInt::getAllOnesValue(Ty);
|
||||
|
||||
default: return 0;
|
||||
static ConstantIntegral *getMaxValue(const Type *Ty, bool isSigned = false) {
|
||||
if (Ty == Type::BoolTy)
|
||||
return ConstantBool::getTrue();
|
||||
if (Ty->isInteger()) {
|
||||
if (isSigned) {
|
||||
// Calculate 011111111111111...
|
||||
unsigned TypeBits = Ty->getPrimitiveSize()*8;
|
||||
int64_t Val = INT64_MAX; // All ones
|
||||
Val >>= 64-TypeBits; // Shift out unwanted 1 bits...
|
||||
return ConstantInt::get(Ty, Val);
|
||||
}
|
||||
return ConstantInt::getAllOnesValue(Ty);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Static constructor to create the minimum constant for an integral type...
|
||||
static ConstantIntegral *getMinValue(const Type *Ty) {
|
||||
switch (Ty->getTypeID()) {
|
||||
case Type::BoolTyID: return ConstantBool::getFalse();
|
||||
case Type::SByteTyID:
|
||||
case Type::ShortTyID:
|
||||
case Type::IntTyID:
|
||||
case Type::LongTyID: {
|
||||
// Calculate 1111111111000000000000
|
||||
unsigned TypeBits = Ty->getPrimitiveSize()*8;
|
||||
int64_t Val = -1; // All ones
|
||||
Val <<= TypeBits-1; // Shift over to the right spot
|
||||
return ConstantInt::get(Ty, Val);
|
||||
}
|
||||
|
||||
case Type::UByteTyID:
|
||||
case Type::UShortTyID:
|
||||
case Type::UIntTyID:
|
||||
case Type::ULongTyID: return ConstantInt::get(Ty, 0);
|
||||
|
||||
default: return 0;
|
||||
static ConstantIntegral *getMinValue(const Type *Ty, bool isSigned = false) {
|
||||
if (Ty == Type::BoolTy)
|
||||
return ConstantBool::getFalse();
|
||||
if (Ty->isInteger()) {
|
||||
if (isSigned) {
|
||||
// Calculate 1111111111000000000000
|
||||
unsigned TypeBits = Ty->getPrimitiveSize()*8;
|
||||
int64_t Val = -1; // All ones
|
||||
Val <<= TypeBits-1; // Shift over to the right spot
|
||||
return ConstantInt::get(Ty, Val);
|
||||
}
|
||||
return ConstantInt::get(Ty, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static ConstantIntegral *Next(ConstantIntegral *CI) {
|
||||
if (ConstantBool *CB = dyn_cast<ConstantBool>(CI))
|
||||
@ -84,25 +71,30 @@ static ConstantIntegral *Next(ConstantIntegral *CI) {
|
||||
return cast<ConstantIntegral>(Result);
|
||||
}
|
||||
|
||||
static bool LT(ConstantIntegral *A, ConstantIntegral *B) {
|
||||
Constant *C = ConstantExpr::getSetLT(A, B);
|
||||
static bool LT(ConstantIntegral *A, ConstantIntegral *B, bool isSigned) {
|
||||
Constant *C = ConstantExpr::getICmp(
|
||||
(isSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT), A, B);
|
||||
assert(isa<ConstantBool>(C) && "Constant folding of integrals not impl??");
|
||||
return cast<ConstantBool>(C)->getValue();
|
||||
}
|
||||
|
||||
static bool LTE(ConstantIntegral *A, ConstantIntegral *B) {
|
||||
Constant *C = ConstantExpr::getSetLE(A, B);
|
||||
static bool LTE(ConstantIntegral *A, ConstantIntegral *B, bool isSigned) {
|
||||
Constant *C = ConstantExpr::getICmp(
|
||||
(isSigned ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE), A, B);
|
||||
assert(isa<ConstantBool>(C) && "Constant folding of integrals not impl??");
|
||||
return cast<ConstantBool>(C)->getValue();
|
||||
}
|
||||
|
||||
static bool GT(ConstantIntegral *A, ConstantIntegral *B) { return LT(B, A); }
|
||||
static bool GT(ConstantIntegral *A, ConstantIntegral *B, bool isSigned) {
|
||||
return LT(B, A, isSigned); }
|
||||
|
||||
static ConstantIntegral *Min(ConstantIntegral *A, ConstantIntegral *B) {
|
||||
return LT(A, B) ? A : B;
|
||||
static ConstantIntegral *Min(ConstantIntegral *A, ConstantIntegral *B,
|
||||
bool isSigned) {
|
||||
return LT(A, B, isSigned) ? A : B;
|
||||
}
|
||||
static ConstantIntegral *Max(ConstantIntegral *A, ConstantIntegral *B) {
|
||||
return GT(A, B) ? A : B;
|
||||
static ConstantIntegral *Max(ConstantIntegral *A, ConstantIntegral *B,
|
||||
bool isSigned) {
|
||||
return GT(A, B, isSigned) ? A : B;
|
||||
}
|
||||
|
||||
/// Initialize a full (the default) or empty set for the specified type.
|
||||
@ -118,47 +110,62 @@ ConstantRange::ConstantRange(const Type *Ty, bool Full) {
|
||||
|
||||
/// Initialize a range to hold the single specified value.
|
||||
///
|
||||
ConstantRange::ConstantRange(Constant *V)
|
||||
: Lower(cast<ConstantIntegral>(V)), Upper(Next(cast<ConstantIntegral>(V))) {
|
||||
}
|
||||
ConstantRange::ConstantRange(Constant *V)
|
||||
: Lower(cast<ConstantIntegral>(V)), Upper(Next(cast<ConstantIntegral>(V))) { }
|
||||
|
||||
/// Initialize a range of values explicitly... this will assert out if
|
||||
/// Lower==Upper and Lower != Min or Max for its type (or if the two constants
|
||||
/// have different types)
|
||||
///
|
||||
ConstantRange::ConstantRange(Constant *L, Constant *U)
|
||||
ConstantRange::ConstantRange(Constant *L, Constant *U)
|
||||
: Lower(cast<ConstantIntegral>(L)), Upper(cast<ConstantIntegral>(U)) {
|
||||
assert(Lower->getType() == Upper->getType() &&
|
||||
"Incompatible types for ConstantRange!");
|
||||
|
||||
// Make sure that if L & U are equal that they are either Min or Max...
|
||||
assert((L != U || (L == getMaxValue(L->getType()) ||
|
||||
L == getMinValue(L->getType()))) &&
|
||||
"Lower == Upper, but they aren't min or max for type!");
|
||||
L == getMinValue(L->getType())))
|
||||
&& "Lower == Upper, but they aren't min or max for type!");
|
||||
}
|
||||
|
||||
/// Initialize a set of values that all satisfy the condition with C.
|
||||
///
|
||||
ConstantRange::ConstantRange(unsigned SetCCOpcode, ConstantIntegral *C) {
|
||||
switch (SetCCOpcode) {
|
||||
default: assert(0 && "Invalid SetCC opcode to ConstantRange ctor!");
|
||||
case Instruction::SetEQ: Lower = C; Upper = Next(C); return;
|
||||
case Instruction::SetNE: Upper = C; Lower = Next(C); return;
|
||||
case Instruction::SetLT:
|
||||
ConstantRange::ConstantRange(unsigned short ICmpOpcode, ConstantIntegral *C) {
|
||||
switch (ICmpOpcode) {
|
||||
default: assert(0 && "Invalid ICmp opcode to ConstantRange ctor!");
|
||||
case ICmpInst::ICMP_EQ: Lower = C; Upper = Next(C); return;
|
||||
case ICmpInst::ICMP_NE: Upper = C; Lower = Next(C); return;
|
||||
case ICmpInst::ICMP_ULT:
|
||||
Lower = getMinValue(C->getType());
|
||||
Upper = C;
|
||||
return;
|
||||
case Instruction::SetGT:
|
||||
Lower = Next(C);
|
||||
Upper = getMinValue(C->getType()); // Min = Next(Max)
|
||||
case ICmpInst::ICMP_SLT:
|
||||
Lower = getMinValue(C->getType(), true);
|
||||
Upper = C;
|
||||
return;
|
||||
case Instruction::SetLE:
|
||||
case ICmpInst::ICMP_UGT:
|
||||
Lower = Next(C);
|
||||
Upper = getMinValue(C->getType()); // Min = Next(Max)
|
||||
return;
|
||||
case ICmpInst::ICMP_SGT:
|
||||
Lower = Next(C);
|
||||
Upper = getMinValue(C->getType(), true); // Min = Next(Max)
|
||||
return;
|
||||
case ICmpInst::ICMP_ULE:
|
||||
Lower = getMinValue(C->getType());
|
||||
Upper = Next(C);
|
||||
return;
|
||||
case Instruction::SetGE:
|
||||
case ICmpInst::ICMP_SLE:
|
||||
Lower = getMinValue(C->getType(), true);
|
||||
Upper = Next(C);
|
||||
return;
|
||||
case ICmpInst::ICMP_UGE:
|
||||
Lower = C;
|
||||
Upper = getMinValue(C->getType()); // Min = Next(Max)
|
||||
Upper = getMinValue(C->getType()); // Min = Next(Max)
|
||||
return;
|
||||
case ICmpInst::ICMP_SGE:
|
||||
Lower = C;
|
||||
Upper = getMinValue(C->getType(), true); // Min = Next(Max)
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -182,11 +189,10 @@ bool ConstantRange::isEmptySet() const {
|
||||
/// isWrappedSet - Return true if this set wraps around the top of the range,
|
||||
/// for example: [100, 8)
|
||||
///
|
||||
bool ConstantRange::isWrappedSet() const {
|
||||
return GT(Lower, Upper);
|
||||
bool ConstantRange::isWrappedSet(bool isSigned) const {
|
||||
return GT(Lower, Upper, isSigned);
|
||||
}
|
||||
|
||||
|
||||
/// getSingleElement - If this set contains a single element, return it,
|
||||
/// otherwise return null.
|
||||
ConstantIntegral *ConstantRange::getSingleElement() const {
|
||||
@ -212,19 +218,17 @@ uint64_t ConstantRange::getSetSize() const {
|
||||
|
||||
/// contains - Return true if the specified value is in the set.
|
||||
///
|
||||
bool ConstantRange::contains(ConstantInt *Val) const {
|
||||
bool ConstantRange::contains(ConstantInt *Val, bool isSigned) const {
|
||||
if (Lower == Upper) {
|
||||
if (isFullSet()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isWrappedSet())
|
||||
return LTE(Lower, Val) && LT(Val, Upper);
|
||||
return LTE(Lower, Val) || LT(Val, Upper);
|
||||
if (!isWrappedSet(isSigned))
|
||||
return LTE(Lower, Val, isSigned) && LT(Val, Upper, isSigned);
|
||||
return LTE(Lower, Val, isSigned) || LT(Val, Upper, isSigned);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// subtract - Subtract the specified constant from the endpoints of this
|
||||
/// constant range.
|
||||
ConstantRange ConstantRange::subtract(ConstantInt *CI) const {
|
||||
@ -241,15 +245,16 @@ ConstantRange ConstantRange::subtract(ConstantInt *CI) const {
|
||||
// it is known that LHS is wrapped and RHS isn't.
|
||||
//
|
||||
static ConstantRange intersect1Wrapped(const ConstantRange &LHS,
|
||||
const ConstantRange &RHS) {
|
||||
assert(LHS.isWrappedSet() && !RHS.isWrappedSet());
|
||||
const ConstantRange &RHS,
|
||||
bool isSigned) {
|
||||
assert(LHS.isWrappedSet(isSigned) && !RHS.isWrappedSet(isSigned));
|
||||
|
||||
// Check to see if we overlap on the Left side of RHS...
|
||||
//
|
||||
if (LT(RHS.getLower(), LHS.getUpper())) {
|
||||
if (LT(RHS.getLower(), LHS.getUpper(), isSigned)) {
|
||||
// We do overlap on the left side of RHS, see if we overlap on the right of
|
||||
// RHS...
|
||||
if (GT(RHS.getUpper(), LHS.getLower())) {
|
||||
if (GT(RHS.getUpper(), LHS.getLower(), isSigned)) {
|
||||
// Ok, the result overlaps on both the left and right sides. See if the
|
||||
// resultant interval will be smaller if we wrap or not...
|
||||
//
|
||||
@ -262,11 +267,10 @@ static ConstantRange intersect1Wrapped(const ConstantRange &LHS,
|
||||
// No overlap on the right, just on the left.
|
||||
return ConstantRange(RHS.getLower(), LHS.getUpper());
|
||||
}
|
||||
|
||||
} else {
|
||||
// We don't overlap on the left side of RHS, see if we overlap on the right
|
||||
// of RHS...
|
||||
if (GT(RHS.getUpper(), LHS.getLower())) {
|
||||
if (GT(RHS.getUpper(), LHS.getLower(), isSigned)) {
|
||||
// Simple overlap...
|
||||
return ConstantRange(LHS.getLower(), RHS.getUpper());
|
||||
} else {
|
||||
@ -279,30 +283,31 @@ static ConstantRange intersect1Wrapped(const ConstantRange &LHS,
|
||||
/// intersect - Return the range that results from the intersection of this
|
||||
/// range with another range.
|
||||
///
|
||||
ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
|
||||
ConstantRange ConstantRange::intersectWith(const ConstantRange &CR,
|
||||
bool isSigned) const {
|
||||
assert(getType() == CR.getType() && "ConstantRange types don't agree!");
|
||||
// Handle common special cases
|
||||
if (isEmptySet() || CR.isFullSet()) return *this;
|
||||
if (isFullSet() || CR.isEmptySet()) return CR;
|
||||
|
||||
if (!isWrappedSet()) {
|
||||
if (!CR.isWrappedSet()) {
|
||||
ConstantIntegral *L = Max(Lower, CR.Lower);
|
||||
ConstantIntegral *U = Min(Upper, CR.Upper);
|
||||
if (!isWrappedSet(isSigned)) {
|
||||
if (!CR.isWrappedSet(isSigned)) {
|
||||
ConstantIntegral *L = Max(Lower, CR.Lower, isSigned);
|
||||
ConstantIntegral *U = Min(Upper, CR.Upper, isSigned);
|
||||
|
||||
if (LT(L, U)) // If range isn't empty...
|
||||
if (LT(L, U, isSigned)) // If range isn't empty...
|
||||
return ConstantRange(L, U);
|
||||
else
|
||||
return ConstantRange(getType(), false); // Otherwise, return empty set
|
||||
} else
|
||||
return intersect1Wrapped(CR, *this);
|
||||
return intersect1Wrapped(CR, *this, isSigned);
|
||||
} else { // We know "this" is wrapped...
|
||||
if (!CR.isWrappedSet())
|
||||
return intersect1Wrapped(*this, CR);
|
||||
if (!CR.isWrappedSet(isSigned))
|
||||
return intersect1Wrapped(*this, CR, isSigned);
|
||||
else {
|
||||
// Both ranges are wrapped...
|
||||
ConstantIntegral *L = Max(Lower, CR.Lower);
|
||||
ConstantIntegral *U = Min(Upper, CR.Upper);
|
||||
ConstantIntegral *L = Max(Lower, CR.Lower, isSigned);
|
||||
ConstantIntegral *U = Min(Upper, CR.Upper, isSigned);
|
||||
return ConstantRange(L, U);
|
||||
}
|
||||
}
|
||||
@ -315,7 +320,8 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
|
||||
/// 15), which includes 9, 10, and 11, which were not included in either set
|
||||
/// before.
|
||||
///
|
||||
ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const {
|
||||
ConstantRange ConstantRange::unionWith(const ConstantRange &CR,
|
||||
bool isSigned) const {
|
||||
assert(getType() == CR.getType() && "ConstantRange types don't agree!");
|
||||
|
||||
assert(0 && "Range union not implemented yet!");
|
||||
@ -325,7 +331,7 @@ ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const {
|
||||
|
||||
/// zeroExtend - Return a new range in the specified integer type, which must
|
||||
/// be strictly larger than the current type. The returned range will
|
||||
/// correspond to the possible range of values if the source range had been
|
||||
/// correspond to the possible range of values as if the source range had been
|
||||
/// zero extended.
|
||||
ConstantRange ConstantRange::zeroExtend(const Type *Ty) const {
|
||||
assert(getLower()->getType()->getPrimitiveSize() < Ty->getPrimitiveSize() &&
|
||||
@ -346,7 +352,7 @@ ConstantRange ConstantRange::zeroExtend(const Type *Ty) const {
|
||||
|
||||
/// truncate - Return a new range in the specified integer type, which must be
|
||||
/// strictly smaller than the current type. The returned range will
|
||||
/// correspond to the possible range of values if the source range had been
|
||||
/// correspond to the possible range of values as if the source range had been
|
||||
/// truncated to the specified type.
|
||||
ConstantRange ConstantRange::truncate(const Type *Ty) const {
|
||||
assert(getLower()->getType()->getPrimitiveSize() > Ty->getPrimitiveSize() &&
|
||||
@ -360,7 +366,6 @@ ConstantRange ConstantRange::truncate(const Type *Ty) const {
|
||||
ConstantExpr::getTrunc(getUpper(), Ty));
|
||||
}
|
||||
|
||||
|
||||
/// print - Print out the bounds to a stream...
|
||||
///
|
||||
void ConstantRange::print(std::ostream &OS) const {
|
||||
|
@ -325,7 +325,8 @@ namespace {
|
||||
void visitGetElementPtrInst(GetElementPtrInst &GEP);
|
||||
void visitPHINode(PHINode &PN);
|
||||
void visitCastInst(CastInst &CI);
|
||||
void visitSetCondInst(SetCondInst &SCI) {} // NOOP!
|
||||
void visitICmpInst(ICmpInst &ICI) {} // NOOP!
|
||||
void visitFCmpInst(FCmpInst &ICI) {} // NOOP!
|
||||
void visitSelectInst(SelectInst &SI);
|
||||
void visitVAArg(VAArgInst &I);
|
||||
void visitInstruction(Instruction &I);
|
||||
@ -778,6 +779,8 @@ void Andersens::visitInstruction(Instruction &I) {
|
||||
case Instruction::Shl:
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr:
|
||||
case Instruction::ICmp:
|
||||
case Instruction::FCmp:
|
||||
return;
|
||||
default:
|
||||
// Is this something we aren't handling yet?
|
||||
|
@ -251,8 +251,8 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else if (SetCondInst *SCI = dyn_cast<SetCondInst>(*UI)) {
|
||||
if (!isa<ConstantPointerNull>(SCI->getOperand(1)))
|
||||
} else if (ICmpInst *ICI = dyn_cast<ICmpInst>(*UI)) {
|
||||
if (!isa<ConstantPointerNull>(ICI->getOperand(1)))
|
||||
return true; // Allow comparison against null.
|
||||
} else if (FreeInst *F = dyn_cast<FreeInst>(*UI)) {
|
||||
Writers.push_back(F->getParent()->getParent());
|
||||
|
@ -536,7 +536,7 @@ Instruction *Loop::getCanonicalInductionVariableIncrement() const {
|
||||
/// returns null.
|
||||
///
|
||||
Value *Loop::getTripCount() const {
|
||||
// Canonical loops will end with a 'setne I, V', where I is the incremented
|
||||
// Canonical loops will end with a 'cmp ne I, V', where I is the incremented
|
||||
// canonical induction variable and V is the trip count of the loop.
|
||||
Instruction *Inc = getCanonicalInductionVariableIncrement();
|
||||
if (Inc == 0) return 0;
|
||||
@ -546,15 +546,17 @@ Value *Loop::getTripCount() const {
|
||||
IV->getIncomingBlock(contains(IV->getIncomingBlock(1)));
|
||||
|
||||
if (BranchInst *BI = dyn_cast<BranchInst>(BackedgeBlock->getTerminator()))
|
||||
if (BI->isConditional())
|
||||
if (SetCondInst *SCI = dyn_cast<SetCondInst>(BI->getCondition()))
|
||||
if (SCI->getOperand(0) == Inc)
|
||||
if (BI->isConditional()) {
|
||||
if (ICmpInst *ICI = dyn_cast<ICmpInst>(BI->getCondition())) {
|
||||
if (ICI->getOperand(0) == Inc)
|
||||
if (BI->getSuccessor(0) == getHeader()) {
|
||||
if (SCI->getOpcode() == Instruction::SetNE)
|
||||
return SCI->getOperand(1);
|
||||
} else if (SCI->getOpcode() == Instruction::SetEQ) {
|
||||
return SCI->getOperand(1);
|
||||
if (ICI->getPredicate() == ICmpInst::ICMP_NE)
|
||||
return ICI->getOperand(1);
|
||||
} else if (ICI->getPredicate() == ICmpInst::ICMP_EQ) {
|
||||
return ICI->getOperand(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -177,8 +177,7 @@ SCEVHandle SCEVConstant::get(ConstantInt *V) {
|
||||
// are signless. There won't be a need to bitcast then.
|
||||
if (V->getType()->isSigned()) {
|
||||
const Type *NewTy = V->getType()->getUnsignedVersion();
|
||||
V = cast<ConstantInt>(
|
||||
ConstantExpr::getBitCast(V, NewTy));
|
||||
V = cast<ConstantInt>(ConstantExpr::getBitCast(V, NewTy));
|
||||
}
|
||||
|
||||
SCEVConstant *&R = (*SCEVConstants)[V];
|
||||
@ -461,15 +460,8 @@ SCEVHandle SCEVUnknown::getIntegerSCEV(int Val, const Type *Ty) {
|
||||
C = Constant::getNullValue(Ty);
|
||||
else if (Ty->isFloatingPoint())
|
||||
C = ConstantFP::get(Ty, Val);
|
||||
/// FIXME:Signless. when integer types are signless, just change this to:
|
||||
/// else
|
||||
/// C = ConstantInt::get(Ty, Val);
|
||||
else if (Ty->isSigned())
|
||||
else
|
||||
C = ConstantInt::get(Ty, Val);
|
||||
else {
|
||||
C = ConstantInt::get(Ty->getSignedVersion(), Val);
|
||||
C = ConstantExpr::getBitCast(C, Ty);
|
||||
}
|
||||
return SCEVUnknown::get(C);
|
||||
}
|
||||
|
||||
@ -514,8 +506,7 @@ static SCEVHandle PartialFact(SCEVHandle V, unsigned NumSteps) {
|
||||
for (; NumSteps; --NumSteps)
|
||||
Result *= Val-(NumSteps-1);
|
||||
Constant *Res = ConstantInt::get(Type::ULongTy, Result);
|
||||
return SCEVUnknown::get(
|
||||
ConstantExpr::getTruncOrBitCast(Res, V->getType()));
|
||||
return SCEVUnknown::get(ConstantExpr::getTruncOrBitCast(Res, V->getType()));
|
||||
}
|
||||
|
||||
const Type *Ty = V->getType();
|
||||
@ -1162,7 +1153,7 @@ namespace {
|
||||
SCEVHandle ComputeLoadConstantCompareIterationCount(LoadInst *LI,
|
||||
Constant *RHS,
|
||||
const Loop *L,
|
||||
unsigned SetCCOpcode);
|
||||
ICmpInst::Predicate p);
|
||||
|
||||
/// ComputeIterationCountExhaustively - If the trip is known to execute a
|
||||
/// constant number of times (the condition evolves only from constants),
|
||||
@ -1521,17 +1512,21 @@ SCEVHandle ScalarEvolutionsImpl::ComputeIterationCount(const Loop *L) {
|
||||
BranchInst *ExitBr = dyn_cast<BranchInst>(ExitingBlock->getTerminator());
|
||||
if (ExitBr == 0) return UnknownValue;
|
||||
assert(ExitBr->isConditional() && "If unconditional, it can't be in loop!");
|
||||
SetCondInst *ExitCond = dyn_cast<SetCondInst>(ExitBr->getCondition());
|
||||
if (ExitCond == 0) // Not a setcc
|
||||
ICmpInst *ExitCond = dyn_cast<ICmpInst>(ExitBr->getCondition());
|
||||
|
||||
// If its not an integer comparison then compute it the hard way.
|
||||
// Note that ICmpInst deals with pointer comparisons too so we must check
|
||||
// the type of the operand.
|
||||
if (ExitCond == 0 || !ExitCond->getOperand(0)->getType()->isIntegral())
|
||||
return ComputeIterationCountExhaustively(L, ExitBr->getCondition(),
|
||||
ExitBr->getSuccessor(0) == ExitBlock);
|
||||
|
||||
// If the condition was exit on true, convert the condition to exit on false.
|
||||
Instruction::BinaryOps Cond;
|
||||
// If the condition was exit on true, convert the condition to exit on false
|
||||
ICmpInst::Predicate Cond;
|
||||
if (ExitBr->getSuccessor(1) == ExitBlock)
|
||||
Cond = ExitCond->getOpcode();
|
||||
Cond = ExitCond->getPredicate();
|
||||
else
|
||||
Cond = ExitCond->getInverseCondition();
|
||||
Cond = ExitCond->getInversePredicate();
|
||||
|
||||
// Handle common loops like: for (X = "string"; *X; ++X)
|
||||
if (LoadInst *LI = dyn_cast<LoadInst>(ExitCond->getOperand(0)))
|
||||
@ -1550,12 +1545,12 @@ SCEVHandle ScalarEvolutionsImpl::ComputeIterationCount(const Loop *L) {
|
||||
Tmp = getSCEVAtScope(RHS, L);
|
||||
if (!isa<SCEVCouldNotCompute>(Tmp)) RHS = Tmp;
|
||||
|
||||
// At this point, we would like to compute how many iterations of the loop the
|
||||
// predicate will return true for these inputs.
|
||||
// At this point, we would like to compute how many iterations of the
|
||||
// loop the predicate will return true for these inputs.
|
||||
if (isa<SCEVConstant>(LHS) && !isa<SCEVConstant>(RHS)) {
|
||||
// If there is a constant, force it into the RHS.
|
||||
std::swap(LHS, RHS);
|
||||
Cond = SetCondInst::getSwappedCondition(Cond);
|
||||
Cond = ICmpInst::getSwappedPredicate(Cond);
|
||||
}
|
||||
|
||||
// FIXME: think about handling pointer comparisons! i.e.:
|
||||
@ -1590,53 +1585,48 @@ SCEVHandle ScalarEvolutionsImpl::ComputeIterationCount(const Loop *L) {
|
||||
CompRange = ConstantRange(NewL, NewU);
|
||||
}
|
||||
|
||||
SCEVHandle Ret = AddRec->getNumIterationsInRange(CompRange);
|
||||
SCEVHandle Ret = AddRec->getNumIterationsInRange(CompRange,
|
||||
ICmpInst::isSignedPredicate(Cond));
|
||||
if (!isa<SCEVCouldNotCompute>(Ret)) return Ret;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Cond) {
|
||||
case Instruction::SetNE: // while (X != Y)
|
||||
case ICmpInst::ICMP_NE: { // while (X != Y)
|
||||
// Convert to: while (X-Y != 0)
|
||||
if (LHS->getType()->isInteger()) {
|
||||
SCEVHandle TC = HowFarToZero(SCEV::getMinusSCEV(LHS, RHS), L);
|
||||
if (!isa<SCEVCouldNotCompute>(TC)) return TC;
|
||||
}
|
||||
SCEVHandle TC = HowFarToZero(SCEV::getMinusSCEV(LHS, RHS), L);
|
||||
if (!isa<SCEVCouldNotCompute>(TC)) return TC;
|
||||
break;
|
||||
case Instruction::SetEQ:
|
||||
}
|
||||
case ICmpInst::ICMP_EQ: {
|
||||
// Convert to: while (X-Y == 0) // while (X == Y)
|
||||
if (LHS->getType()->isInteger()) {
|
||||
SCEVHandle TC = HowFarToNonZero(SCEV::getMinusSCEV(LHS, RHS), L);
|
||||
if (!isa<SCEVCouldNotCompute>(TC)) return TC;
|
||||
}
|
||||
SCEVHandle TC = HowFarToNonZero(SCEV::getMinusSCEV(LHS, RHS), L);
|
||||
if (!isa<SCEVCouldNotCompute>(TC)) return TC;
|
||||
break;
|
||||
case Instruction::SetLT:
|
||||
if (LHS->getType()->isInteger() &&
|
||||
ExitCond->getOperand(0)->getType()->isSigned()) {
|
||||
SCEVHandle TC = HowManyLessThans(LHS, RHS, L);
|
||||
if (!isa<SCEVCouldNotCompute>(TC)) return TC;
|
||||
}
|
||||
}
|
||||
case ICmpInst::ICMP_SLT: {
|
||||
SCEVHandle TC = HowManyLessThans(LHS, RHS, L);
|
||||
if (!isa<SCEVCouldNotCompute>(TC)) return TC;
|
||||
break;
|
||||
case Instruction::SetGT:
|
||||
if (LHS->getType()->isInteger() &&
|
||||
ExitCond->getOperand(0)->getType()->isSigned()) {
|
||||
SCEVHandle TC = HowManyLessThans(RHS, LHS, L);
|
||||
if (!isa<SCEVCouldNotCompute>(TC)) return TC;
|
||||
}
|
||||
}
|
||||
case ICmpInst::ICMP_SGT: {
|
||||
SCEVHandle TC = HowManyLessThans(RHS, LHS, L);
|
||||
if (!isa<SCEVCouldNotCompute>(TC)) return TC;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
#if 0
|
||||
cerr << "ComputeIterationCount ";
|
||||
if (ExitCond->getOperand(0)->getType()->isUnsigned())
|
||||
cerr << "[unsigned] ";
|
||||
cerr << *LHS << " "
|
||||
<< Instruction::getOpcodeName(Cond) << " " << *RHS << "\n";
|
||||
<< Instruction::getOpcodeName(Instruction::ICmp)
|
||||
<< " " << *RHS << "\n";
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
return ComputeIterationCountExhaustively(L, ExitCond,
|
||||
ExitBr->getSuccessor(0) == ExitBlock);
|
||||
ExitBr->getSuccessor(0) == ExitBlock);
|
||||
}
|
||||
|
||||
static ConstantInt *
|
||||
@ -1686,7 +1676,8 @@ GetAddressedElementFromGlobal(GlobalVariable *GV,
|
||||
/// 'setcc load X, cst', try to se if we can compute the trip count.
|
||||
SCEVHandle ScalarEvolutionsImpl::
|
||||
ComputeLoadConstantCompareIterationCount(LoadInst *LI, Constant *RHS,
|
||||
const Loop *L, unsigned SetCCOpcode) {
|
||||
const Loop *L,
|
||||
ICmpInst::Predicate predicate) {
|
||||
if (LI->isVolatile()) return UnknownValue;
|
||||
|
||||
// Check to see if the loaded pointer is a getelementptr of a global.
|
||||
@ -1742,7 +1733,7 @@ ComputeLoadConstantCompareIterationCount(LoadInst *LI, Constant *RHS,
|
||||
if (Result == 0) break; // Cannot compute!
|
||||
|
||||
// Evaluate the condition for this iteration.
|
||||
Result = ConstantExpr::get(SetCCOpcode, Result, RHS);
|
||||
Result = ConstantExpr::getICmp(predicate, Result, RHS);
|
||||
if (!isa<ConstantBool>(Result)) break; // Couldn't decide for sure
|
||||
if (cast<ConstantBool>(Result)->getValue() == false) {
|
||||
#if 0
|
||||
@ -1761,7 +1752,7 @@ ComputeLoadConstantCompareIterationCount(LoadInst *LI, Constant *RHS,
|
||||
/// CanConstantFold - Return true if we can constant fold an instruction of the
|
||||
/// specified type, assuming that all operands were constants.
|
||||
static bool CanConstantFold(const Instruction *I) {
|
||||
if (isa<BinaryOperator>(I) || isa<ShiftInst>(I) ||
|
||||
if (isa<BinaryOperator>(I) || isa<ShiftInst>(I) || isa<CmpInst>(I) ||
|
||||
isa<SelectInst>(I) || isa<CastInst>(I) || isa<GetElementPtrInst>(I))
|
||||
return true;
|
||||
|
||||
@ -1790,11 +1781,18 @@ static Constant *ConstantFold(const Instruction *I,
|
||||
return ConstantFoldCall(cast<Function>(GV), Operands);
|
||||
}
|
||||
return 0;
|
||||
case Instruction::GetElementPtr:
|
||||
case Instruction::GetElementPtr: {
|
||||
Constant *Base = Operands[0];
|
||||
Operands.erase(Operands.begin());
|
||||
return ConstantExpr::getGetElementPtr(Base, Operands);
|
||||
}
|
||||
case Instruction::ICmp:
|
||||
return ConstantExpr::getICmp(
|
||||
cast<ICmpInst>(I)->getPredicate(), Operands[0], Operands[1]);
|
||||
case Instruction::FCmp:
|
||||
return ConstantExpr::getFCmp(
|
||||
cast<FCmpInst>(I)->getPredicate(), Operands[0], Operands[1]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2226,8 +2224,8 @@ SCEVHandle ScalarEvolutionsImpl::HowFarToZero(SCEV *V, const Loop *L) {
|
||||
// Pick the smallest positive root value.
|
||||
assert(R1->getType()->isUnsigned()&&"Didn't canonicalize to unsigned?");
|
||||
if (ConstantBool *CB =
|
||||
dyn_cast<ConstantBool>(ConstantExpr::getSetLT(R1->getValue(),
|
||||
R2->getValue()))) {
|
||||
dyn_cast<ConstantBool>(ConstantExpr::getICmp(ICmpInst::ICMP_ULT,
|
||||
R1->getValue(), R2->getValue()))) {
|
||||
if (CB->getValue() == false)
|
||||
std::swap(R1, R2); // R1 is the minimum root now.
|
||||
|
||||
@ -2257,7 +2255,8 @@ SCEVHandle ScalarEvolutionsImpl::HowFarToNonZero(SCEV *V, const Loop *L) {
|
||||
// already. If so, the backedge will execute zero times.
|
||||
if (SCEVConstant *C = dyn_cast<SCEVConstant>(V)) {
|
||||
Constant *Zero = Constant::getNullValue(C->getValue()->getType());
|
||||
Constant *NonZero = ConstantExpr::getSetNE(C->getValue(), Zero);
|
||||
Constant *NonZero =
|
||||
ConstantExpr::getICmp(ICmpInst::ICMP_NE, C->getValue(), Zero);
|
||||
if (NonZero == ConstantBool::getTrue())
|
||||
return getSCEV(Zero);
|
||||
return UnknownValue; // Otherwise it will loop infinitely.
|
||||
@ -2318,40 +2317,46 @@ HowManyLessThans(SCEV *LHS, SCEV *RHS, const Loop *L) {
|
||||
|
||||
// Now that we found a conditional branch that dominates the loop, check to
|
||||
// see if it is the comparison we are looking for.
|
||||
SetCondInst *SCI =dyn_cast<SetCondInst>(LoopEntryPredicate->getCondition());
|
||||
if (!SCI) return UnknownValue;
|
||||
Value *PreCondLHS = SCI->getOperand(0);
|
||||
Value *PreCondRHS = SCI->getOperand(1);
|
||||
Instruction::BinaryOps Cond;
|
||||
if (LoopEntryPredicate->getSuccessor(0) == PreheaderDest)
|
||||
Cond = SCI->getOpcode();
|
||||
else
|
||||
Cond = SCI->getInverseCondition();
|
||||
if (ICmpInst *ICI = dyn_cast<ICmpInst>(LoopEntryPredicate->getCondition())){
|
||||
Value *PreCondLHS = ICI->getOperand(0);
|
||||
Value *PreCondRHS = ICI->getOperand(1);
|
||||
ICmpInst::Predicate Cond;
|
||||
if (LoopEntryPredicate->getSuccessor(0) == PreheaderDest)
|
||||
Cond = ICI->getPredicate();
|
||||
else
|
||||
Cond = ICI->getInversePredicate();
|
||||
|
||||
switch (Cond) {
|
||||
case Instruction::SetGT:
|
||||
std::swap(PreCondLHS, PreCondRHS);
|
||||
Cond = Instruction::SetLT;
|
||||
// Fall Through.
|
||||
case Instruction::SetLT:
|
||||
if (PreCondLHS->getType()->isInteger() &&
|
||||
PreCondLHS->getType()->isSigned()) {
|
||||
if (RHS != getSCEV(PreCondRHS))
|
||||
return UnknownValue; // Not a comparison against 'm'.
|
||||
|
||||
if (SCEV::getMinusSCEV(AddRec->getOperand(0), One)
|
||||
!= getSCEV(PreCondLHS))
|
||||
return UnknownValue; // Not a comparison against 'n-1'.
|
||||
switch (Cond) {
|
||||
case ICmpInst::ICMP_UGT:
|
||||
std::swap(PreCondLHS, PreCondRHS);
|
||||
Cond = ICmpInst::ICMP_ULT;
|
||||
break;
|
||||
} else {
|
||||
return UnknownValue;
|
||||
case ICmpInst::ICMP_SGT:
|
||||
std::swap(PreCondLHS, PreCondRHS);
|
||||
Cond = ICmpInst::ICMP_SLT;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
//cerr << "Computed Loop Trip Count as: "
|
||||
// << *SCEV::getMinusSCEV(RHS, AddRec->getOperand(0)) << "\n";
|
||||
return SCEV::getMinusSCEV(RHS, AddRec->getOperand(0));
|
||||
if (Cond == ICmpInst::ICMP_SLT) {
|
||||
if (PreCondLHS->getType()->isInteger()) {
|
||||
if (RHS != getSCEV(PreCondRHS))
|
||||
return UnknownValue; // Not a comparison against 'm'.
|
||||
|
||||
if (SCEV::getMinusSCEV(AddRec->getOperand(0), One)
|
||||
!= getSCEV(PreCondLHS))
|
||||
return UnknownValue; // Not a comparison against 'n-1'.
|
||||
}
|
||||
else return UnknownValue;
|
||||
} else if (Cond == ICmpInst::ICMP_ULT)
|
||||
return UnknownValue;
|
||||
|
||||
// cerr << "Computed Loop Trip Count as: "
|
||||
// << // *SCEV::getMinusSCEV(RHS, AddRec->getOperand(0)) << "\n";
|
||||
return SCEV::getMinusSCEV(RHS, AddRec->getOperand(0));
|
||||
}
|
||||
else
|
||||
return UnknownValue;
|
||||
}
|
||||
|
||||
return UnknownValue;
|
||||
@ -2362,7 +2367,8 @@ HowManyLessThans(SCEV *LHS, SCEV *RHS, const Loop *L) {
|
||||
/// this is that it returns the first iteration number where the value is not in
|
||||
/// the condition, thus computing the exit count. If the iteration count can't
|
||||
/// be computed, an instance of SCEVCouldNotCompute is returned.
|
||||
SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
|
||||
SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range,
|
||||
bool isSigned) const {
|
||||
if (Range.isFullSet()) // Infinite loop.
|
||||
return new SCEVCouldNotCompute();
|
||||
|
||||
@ -2374,7 +2380,7 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
|
||||
SCEVHandle Shifted = SCEVAddRecExpr::get(Operands, getLoop());
|
||||
if (SCEVAddRecExpr *ShiftedAddRec = dyn_cast<SCEVAddRecExpr>(Shifted))
|
||||
return ShiftedAddRec->getNumIterationsInRange(
|
||||
Range.subtract(SC->getValue()));
|
||||
Range.subtract(SC->getValue()),isSigned);
|
||||
// This is strange and shouldn't happen.
|
||||
return new SCEVCouldNotCompute();
|
||||
}
|
||||
@ -2392,7 +2398,7 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
|
||||
// First check to see if the range contains zero. If not, the first
|
||||
// iteration exits.
|
||||
ConstantInt *Zero = ConstantInt::get(getType(), 0);
|
||||
if (!Range.contains(Zero)) return SCEVConstant::get(Zero);
|
||||
if (!Range.contains(Zero, isSigned)) return SCEVConstant::get(Zero);
|
||||
|
||||
if (isAffine()) {
|
||||
// If this is an affine expression then we have this situation:
|
||||
@ -2418,12 +2424,12 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
|
||||
// range, then we computed our trip count, otherwise wrap around or other
|
||||
// things must have happened.
|
||||
ConstantInt *Val = EvaluateConstantChrecAtConstant(this, ExitValue);
|
||||
if (Range.contains(Val))
|
||||
if (Range.contains(Val, isSigned))
|
||||
return new SCEVCouldNotCompute(); // Something strange happened
|
||||
|
||||
// Ensure that the previous value is in the range. This is a sanity check.
|
||||
assert(Range.contains(EvaluateConstantChrecAtConstant(this,
|
||||
ConstantExpr::getSub(ExitValue, One))) &&
|
||||
ConstantExpr::getSub(ExitValue, One)), isSigned) &&
|
||||
"Linear scev computation is off in a bad way!");
|
||||
return SCEVConstant::get(cast<ConstantInt>(ExitValue));
|
||||
} else if (isQuadratic()) {
|
||||
@ -2444,8 +2450,8 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
|
||||
// Pick the smallest positive root value.
|
||||
assert(R1->getType()->isUnsigned() && "Didn't canonicalize to unsigned?");
|
||||
if (ConstantBool *CB =
|
||||
dyn_cast<ConstantBool>(ConstantExpr::getSetLT(R1->getValue(),
|
||||
R2->getValue()))) {
|
||||
dyn_cast<ConstantBool>(ConstantExpr::getICmp(ICmpInst::ICMP_ULT,
|
||||
R1->getValue(), R2->getValue()))) {
|
||||
if (CB->getValue() == false)
|
||||
std::swap(R1, R2); // R1 is the minimum root now.
|
||||
|
||||
@ -2454,14 +2460,14 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
|
||||
// for "X*X < 5", for example, we should not return a root of 2.
|
||||
ConstantInt *R1Val = EvaluateConstantChrecAtConstant(this,
|
||||
R1->getValue());
|
||||
if (Range.contains(R1Val)) {
|
||||
if (Range.contains(R1Val, isSigned)) {
|
||||
// The next iteration must be out of the range...
|
||||
Constant *NextVal =
|
||||
ConstantExpr::getAdd(R1->getValue(),
|
||||
ConstantInt::get(R1->getType(), 1));
|
||||
|
||||
R1Val = EvaluateConstantChrecAtConstant(this, NextVal);
|
||||
if (!Range.contains(R1Val))
|
||||
if (!Range.contains(R1Val, isSigned))
|
||||
return SCEVUnknown::get(NextVal);
|
||||
return new SCEVCouldNotCompute(); // Something strange happened
|
||||
}
|
||||
@ -2472,7 +2478,7 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
|
||||
ConstantExpr::getSub(R1->getValue(),
|
||||
ConstantInt::get(R1->getType(), 1));
|
||||
R1Val = EvaluateConstantChrecAtConstant(this, NextVal);
|
||||
if (Range.contains(R1Val))
|
||||
if (Range.contains(R1Val, isSigned))
|
||||
return R1;
|
||||
return new SCEVCouldNotCompute(); // Something strange happened
|
||||
}
|
||||
@ -2494,7 +2500,7 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
|
||||
return new SCEVCouldNotCompute();
|
||||
|
||||
// Check to see if we found the value!
|
||||
if (!Range.contains(cast<SCEVConstant>(Val)->getValue()))
|
||||
if (!Range.contains(cast<SCEVConstant>(Val)->getValue(), isSigned))
|
||||
return SCEVConstant::get(TestVal);
|
||||
|
||||
// Increment to test the next index.
|
||||
|
@ -161,6 +161,11 @@ static inline bool isIdenticalBinaryInst(const Instruction &I1,
|
||||
I1.getParent()->getParent() != I2->getParent()->getParent())
|
||||
return false;
|
||||
|
||||
// If they are CmpInst instructions, check their predicates
|
||||
if (CmpInst *CI1 = dyn_cast<CmpInst>(&const_cast<Instruction&>(I1)))
|
||||
if (CI1->getPredicate() != cast<CmpInst>(I2)->getPredicate())
|
||||
return false;
|
||||
|
||||
// They are identical if both operands are the same!
|
||||
if (I1.getOperand(0) == I2->getOperand(0) &&
|
||||
I1.getOperand(1) == I2->getOperand(1))
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -260,12 +260,6 @@ frem { RET_TOK(BinaryOpVal, FRem, FREM); }
|
||||
and { RET_TOK(BinaryOpVal, And, AND); }
|
||||
or { RET_TOK(BinaryOpVal, Or , OR ); }
|
||||
xor { RET_TOK(BinaryOpVal, Xor, XOR); }
|
||||
setne { RET_TOK(BinaryOpVal, SetNE, SETNE); }
|
||||
seteq { RET_TOK(BinaryOpVal, SetEQ, SETEQ); }
|
||||
setlt { RET_TOK(BinaryOpVal, SetLT, SETLT); }
|
||||
setgt { RET_TOK(BinaryOpVal, SetGT, SETGT); }
|
||||
setle { RET_TOK(BinaryOpVal, SetLE, SETLE); }
|
||||
setge { RET_TOK(BinaryOpVal, SetGE, SETGE); }
|
||||
icmp { RET_TOK(OtherOpVal, ICmp, ICMP); }
|
||||
fcmp { RET_TOK(OtherOpVal, FCmp, FCMP); }
|
||||
eq { return EQ; }
|
||||
|
@ -260,12 +260,6 @@ frem { RET_TOK(BinaryOpVal, FRem, FREM); }
|
||||
and { RET_TOK(BinaryOpVal, And, AND); }
|
||||
or { RET_TOK(BinaryOpVal, Or , OR ); }
|
||||
xor { RET_TOK(BinaryOpVal, Xor, XOR); }
|
||||
setne { RET_TOK(BinaryOpVal, SetNE, SETNE); }
|
||||
seteq { RET_TOK(BinaryOpVal, SetEQ, SETEQ); }
|
||||
setlt { RET_TOK(BinaryOpVal, SetLT, SETLT); }
|
||||
setgt { RET_TOK(BinaryOpVal, SetGT, SETGT); }
|
||||
setle { RET_TOK(BinaryOpVal, SetLE, SETLE); }
|
||||
setge { RET_TOK(BinaryOpVal, SetGE, SETGE); }
|
||||
icmp { RET_TOK(OtherOpVal, ICmp, ICMP); }
|
||||
fcmp { RET_TOK(OtherOpVal, FCmp, FCMP); }
|
||||
eq { return EQ; }
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
/* A Bison parser, made by GNU Bison 1.875c. */
|
||||
/* A Bison parser, made by GNU Bison 2.1. */
|
||||
|
||||
/* Skeleton parser for Yacc-like parsing with Bison,
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -15,8 +15,8 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* As a special exception, when this file is copied by Bison into a
|
||||
Bison output file, you may use that output file without restriction.
|
||||
@ -116,63 +116,58 @@
|
||||
AND = 342,
|
||||
OR = 343,
|
||||
XOR = 344,
|
||||
SETLE = 345,
|
||||
SETGE = 346,
|
||||
SETLT = 347,
|
||||
SETGT = 348,
|
||||
SETEQ = 349,
|
||||
SETNE = 350,
|
||||
ICMP = 351,
|
||||
FCMP = 352,
|
||||
EQ = 353,
|
||||
NE = 354,
|
||||
SLT = 355,
|
||||
SGT = 356,
|
||||
SLE = 357,
|
||||
SGE = 358,
|
||||
ULT = 359,
|
||||
UGT = 360,
|
||||
ULE = 361,
|
||||
UGE = 362,
|
||||
OEQ = 363,
|
||||
ONE = 364,
|
||||
OLT = 365,
|
||||
OGT = 366,
|
||||
OLE = 367,
|
||||
OGE = 368,
|
||||
ORD = 369,
|
||||
UNO = 370,
|
||||
UEQ = 371,
|
||||
UNE = 372,
|
||||
MALLOC = 373,
|
||||
ALLOCA = 374,
|
||||
FREE = 375,
|
||||
LOAD = 376,
|
||||
STORE = 377,
|
||||
GETELEMENTPTR = 378,
|
||||
TRUNC = 379,
|
||||
ZEXT = 380,
|
||||
SEXT = 381,
|
||||
FPTRUNC = 382,
|
||||
FPEXT = 383,
|
||||
BITCAST = 384,
|
||||
UITOFP = 385,
|
||||
SITOFP = 386,
|
||||
FPTOUI = 387,
|
||||
FPTOSI = 388,
|
||||
INTTOPTR = 389,
|
||||
PTRTOINT = 390,
|
||||
PHI_TOK = 391,
|
||||
SELECT = 392,
|
||||
SHL = 393,
|
||||
LSHR = 394,
|
||||
ASHR = 395,
|
||||
VAARG = 396,
|
||||
EXTRACTELEMENT = 397,
|
||||
INSERTELEMENT = 398,
|
||||
SHUFFLEVECTOR = 399
|
||||
ICMP = 345,
|
||||
FCMP = 346,
|
||||
EQ = 347,
|
||||
NE = 348,
|
||||
SLT = 349,
|
||||
SGT = 350,
|
||||
SLE = 351,
|
||||
SGE = 352,
|
||||
ULT = 353,
|
||||
UGT = 354,
|
||||
ULE = 355,
|
||||
UGE = 356,
|
||||
OEQ = 357,
|
||||
ONE = 358,
|
||||
OLT = 359,
|
||||
OGT = 360,
|
||||
OLE = 361,
|
||||
OGE = 362,
|
||||
ORD = 363,
|
||||
UNO = 364,
|
||||
UEQ = 365,
|
||||
UNE = 366,
|
||||
MALLOC = 367,
|
||||
ALLOCA = 368,
|
||||
FREE = 369,
|
||||
LOAD = 370,
|
||||
STORE = 371,
|
||||
GETELEMENTPTR = 372,
|
||||
TRUNC = 373,
|
||||
ZEXT = 374,
|
||||
SEXT = 375,
|
||||
FPTRUNC = 376,
|
||||
FPEXT = 377,
|
||||
BITCAST = 378,
|
||||
UITOFP = 379,
|
||||
SITOFP = 380,
|
||||
FPTOUI = 381,
|
||||
FPTOSI = 382,
|
||||
INTTOPTR = 383,
|
||||
PTRTOINT = 384,
|
||||
PHI_TOK = 385,
|
||||
SELECT = 386,
|
||||
SHL = 387,
|
||||
LSHR = 388,
|
||||
ASHR = 389,
|
||||
VAARG = 390,
|
||||
EXTRACTELEMENT = 391,
|
||||
INSERTELEMENT = 392,
|
||||
SHUFFLEVECTOR = 393
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
#define ESINT64VAL 258
|
||||
#define EUINT64VAL 259
|
||||
#define SINTVAL 260
|
||||
@ -260,67 +255,61 @@
|
||||
#define AND 342
|
||||
#define OR 343
|
||||
#define XOR 344
|
||||
#define SETLE 345
|
||||
#define SETGE 346
|
||||
#define SETLT 347
|
||||
#define SETGT 348
|
||||
#define SETEQ 349
|
||||
#define SETNE 350
|
||||
#define ICMP 351
|
||||
#define FCMP 352
|
||||
#define EQ 353
|
||||
#define NE 354
|
||||
#define SLT 355
|
||||
#define SGT 356
|
||||
#define SLE 357
|
||||
#define SGE 358
|
||||
#define ULT 359
|
||||
#define UGT 360
|
||||
#define ULE 361
|
||||
#define UGE 362
|
||||
#define OEQ 363
|
||||
#define ONE 364
|
||||
#define OLT 365
|
||||
#define OGT 366
|
||||
#define OLE 367
|
||||
#define OGE 368
|
||||
#define ORD 369
|
||||
#define UNO 370
|
||||
#define UEQ 371
|
||||
#define UNE 372
|
||||
#define MALLOC 373
|
||||
#define ALLOCA 374
|
||||
#define FREE 375
|
||||
#define LOAD 376
|
||||
#define STORE 377
|
||||
#define GETELEMENTPTR 378
|
||||
#define TRUNC 379
|
||||
#define ZEXT 380
|
||||
#define SEXT 381
|
||||
#define FPTRUNC 382
|
||||
#define FPEXT 383
|
||||
#define BITCAST 384
|
||||
#define UITOFP 385
|
||||
#define SITOFP 386
|
||||
#define FPTOUI 387
|
||||
#define FPTOSI 388
|
||||
#define INTTOPTR 389
|
||||
#define PTRTOINT 390
|
||||
#define PHI_TOK 391
|
||||
#define SELECT 392
|
||||
#define SHL 393
|
||||
#define LSHR 394
|
||||
#define ASHR 395
|
||||
#define VAARG 396
|
||||
#define EXTRACTELEMENT 397
|
||||
#define INSERTELEMENT 398
|
||||
#define SHUFFLEVECTOR 399
|
||||
#define ICMP 345
|
||||
#define FCMP 346
|
||||
#define EQ 347
|
||||
#define NE 348
|
||||
#define SLT 349
|
||||
#define SGT 350
|
||||
#define SLE 351
|
||||
#define SGE 352
|
||||
#define ULT 353
|
||||
#define UGT 354
|
||||
#define ULE 355
|
||||
#define UGE 356
|
||||
#define OEQ 357
|
||||
#define ONE 358
|
||||
#define OLT 359
|
||||
#define OGT 360
|
||||
#define OLE 361
|
||||
#define OGE 362
|
||||
#define ORD 363
|
||||
#define UNO 364
|
||||
#define UEQ 365
|
||||
#define UNE 366
|
||||
#define MALLOC 367
|
||||
#define ALLOCA 368
|
||||
#define FREE 369
|
||||
#define LOAD 370
|
||||
#define STORE 371
|
||||
#define GETELEMENTPTR 372
|
||||
#define TRUNC 373
|
||||
#define ZEXT 374
|
||||
#define SEXT 375
|
||||
#define FPTRUNC 376
|
||||
#define FPEXT 377
|
||||
#define BITCAST 378
|
||||
#define UITOFP 379
|
||||
#define SITOFP 380
|
||||
#define FPTOUI 381
|
||||
#define FPTOSI 382
|
||||
#define INTTOPTR 383
|
||||
#define PTRTOINT 384
|
||||
#define PHI_TOK 385
|
||||
#define SELECT 386
|
||||
#define SHL 387
|
||||
#define LSHR 388
|
||||
#define ASHR 389
|
||||
#define VAARG 390
|
||||
#define EXTRACTELEMENT 391
|
||||
#define INSERTELEMENT 392
|
||||
#define SHUFFLEVECTOR 393
|
||||
|
||||
|
||||
|
||||
|
||||
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
|
||||
#line 855 "/home/vadve/alenhar2/llvm.old/lib/AsmParser/llvmAsmParser.y"
|
||||
#line 855 "/proj/llvm/llvm-3/lib/AsmParser/llvmAsmParser.y"
|
||||
typedef union YYSTYPE {
|
||||
llvm::Module *ModuleVal;
|
||||
llvm::Function *FunctionVal;
|
||||
@ -363,8 +352,8 @@ typedef union YYSTYPE {
|
||||
llvm::ICmpInst::Predicate IPredicate;
|
||||
llvm::FCmpInst::Predicate FPredicate;
|
||||
} YYSTYPE;
|
||||
/* Line 1275 of yacc.c. */
|
||||
#line 368 "llvmAsmParser.tab.h"
|
||||
/* Line 1447 of yacc.c. */
|
||||
#line 357 "llvmAsmParser.tab.h"
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
|
@ -958,9 +958,8 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
|
||||
%token <TermOpVal> RET BR SWITCH INVOKE UNWIND UNREACHABLE
|
||||
|
||||
// Binary Operators
|
||||
%type <BinaryOpVal> ArithmeticOps LogicalOps SetCondOps // Binops Subcatagories
|
||||
%type <BinaryOpVal> ArithmeticOps LogicalOps // Binops Subcatagories
|
||||
%token <BinaryOpVal> ADD SUB MUL UDIV SDIV FDIV UREM SREM FREM AND OR XOR
|
||||
%token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comparators
|
||||
%token <OtherOpVal> ICMP FCMP
|
||||
%type <IPredicate> IPredicates
|
||||
%type <FPredicate> FPredicates
|
||||
@ -999,7 +998,6 @@ INTVAL : UINTVAL {
|
||||
//
|
||||
ArithmeticOps: ADD | SUB | MUL | UDIV | SDIV | FDIV | UREM | SREM | FREM;
|
||||
LogicalOps : AND | OR | XOR;
|
||||
SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
|
||||
CastOps : TRUNC | ZEXT | SEXT | FPTRUNC | FPEXT | BITCAST |
|
||||
UITOFP | SITOFP | FPTOUI | FPTOSI | INTTOPTR | PTRTOINT;
|
||||
ShiftOps : SHL | LSHR | ASHR;
|
||||
@ -1574,12 +1572,6 @@ ConstExpr: CastOps '(' ConstVal TO Types ')' {
|
||||
$$ = ConstantExpr::get($1, $3, $5);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| SetCondOps '(' ConstVal ',' ConstVal ')' {
|
||||
if ($3->getType() != $5->getType())
|
||||
GEN_ERROR("setcc operand types must match!");
|
||||
$$ = ConstantExpr::get($1, $3, $5);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| ICMP IPredicates '(' ConstVal ',' ConstVal ')' {
|
||||
if ($4->getType() != $6->getType())
|
||||
GEN_ERROR("icmp operand types must match!");
|
||||
@ -2369,20 +2361,6 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
GEN_ERROR("binary operator returned null!");
|
||||
delete $2;
|
||||
}
|
||||
| SetCondOps Types ValueRef ',' ValueRef {
|
||||
if(isa<PackedType>((*$2).get())) {
|
||||
GEN_ERROR(
|
||||
"PackedTypes currently not supported in setcc instructions!");
|
||||
}
|
||||
Value* tmpVal1 = getVal(*$2, $3);
|
||||
CHECK_FOR_ERROR
|
||||
Value* tmpVal2 = getVal(*$2, $5);
|
||||
CHECK_FOR_ERROR
|
||||
$$ = new SetCondInst($1, tmpVal1, tmpVal2);
|
||||
if ($$ == 0)
|
||||
GEN_ERROR("binary operator returned null!");
|
||||
delete $2;
|
||||
}
|
||||
| ICMP IPredicates Types ValueRef ',' ValueRef {
|
||||
if (isa<PackedType>((*$3).get()))
|
||||
GEN_ERROR("Packed types not supported by icmp instruction");
|
||||
|
@ -926,7 +926,6 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
|
||||
|
||||
// EUINT64VAL - A positive number within uns. long long range
|
||||
%token <UInt64Val> EUINT64VAL
|
||||
%type <SInt64Val> EINT64VAL
|
||||
|
||||
%token <SIntVal> SINTVAL // Signed 32 bit ints...
|
||||
%token <UIntVal> UINTVAL // Unsigned 32 bit ints...
|
||||
@ -959,9 +958,8 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
|
||||
%token <TermOpVal> RET BR SWITCH INVOKE UNWIND UNREACHABLE
|
||||
|
||||
// Binary Operators
|
||||
%type <BinaryOpVal> ArithmeticOps LogicalOps SetCondOps // Binops Subcatagories
|
||||
%type <BinaryOpVal> ArithmeticOps LogicalOps // Binops Subcatagories
|
||||
%token <BinaryOpVal> ADD SUB MUL UDIV SDIV FDIV UREM SREM FREM AND OR XOR
|
||||
%token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comparators
|
||||
%token <OtherOpVal> ICMP FCMP
|
||||
%type <IPredicate> IPredicates
|
||||
%type <FPredicate> FPredicates
|
||||
@ -995,21 +993,11 @@ INTVAL : UINTVAL {
|
||||
CHECK_FOR_ERROR
|
||||
};
|
||||
|
||||
|
||||
EINT64VAL : ESINT64VAL; // These have same type and can't cause problems...
|
||||
EINT64VAL : EUINT64VAL {
|
||||
if ($1 > (uint64_t)INT64_MAX) // Outside of my range!
|
||||
GEN_ERROR("Value too large for type!");
|
||||
$$ = (int64_t)$1;
|
||||
CHECK_FOR_ERROR
|
||||
};
|
||||
|
||||
// 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 | UREM | SREM | FREM;
|
||||
LogicalOps : AND | OR | XOR;
|
||||
SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
|
||||
CastOps : TRUNC | ZEXT | SEXT | FPTRUNC | FPEXT | BITCAST |
|
||||
UITOFP | SITOFP | FPTOUI | FPTOSI | INTTOPTR | PTRTOINT;
|
||||
ShiftOps : SHL | LSHR | ASHR;
|
||||
@ -1486,7 +1474,13 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr
|
||||
delete $1;
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| SIntType EINT64VAL { // integral constants
|
||||
| SIntType ESINT64VAL { // integral constants
|
||||
if (!ConstantInt::isValueValidForType($1, $2))
|
||||
GEN_ERROR("Constant value doesn't fit in type!");
|
||||
$$ = ConstantInt::get($1, $2);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| SIntType EUINT64VAL { // integral constants
|
||||
if (!ConstantInt::isValueValidForType($1, $2))
|
||||
GEN_ERROR("Constant value doesn't fit in type!");
|
||||
$$ = ConstantInt::get($1, $2);
|
||||
@ -1498,6 +1492,12 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr
|
||||
$$ = ConstantInt::get($1, $2);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| UIntType ESINT64VAL {
|
||||
if (!ConstantInt::isValueValidForType($1, $2))
|
||||
GEN_ERROR("Constant value doesn't fit in type!");
|
||||
$$ = ConstantInt::get($1, $2);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| BOOL TRUETOK { // Boolean constants
|
||||
$$ = ConstantBool::getTrue();
|
||||
CHECK_FOR_ERROR
|
||||
@ -1572,12 +1572,6 @@ ConstExpr: CastOps '(' ConstVal TO Types ')' {
|
||||
$$ = ConstantExpr::get($1, $3, $5);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| SetCondOps '(' ConstVal ',' ConstVal ')' {
|
||||
if ($3->getType() != $5->getType())
|
||||
GEN_ERROR("setcc operand types must match!");
|
||||
$$ = ConstantExpr::get($1, $3, $5);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| ICMP IPredicates '(' ConstVal ',' ConstVal ')' {
|
||||
if ($4->getType() != $6->getType())
|
||||
GEN_ERROR("icmp operand types must match!");
|
||||
@ -2367,20 +2361,6 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
GEN_ERROR("binary operator returned null!");
|
||||
delete $2;
|
||||
}
|
||||
| SetCondOps Types ValueRef ',' ValueRef {
|
||||
if(isa<PackedType>((*$2).get())) {
|
||||
GEN_ERROR(
|
||||
"PackedTypes currently not supported in setcc instructions!");
|
||||
}
|
||||
Value* tmpVal1 = getVal(*$2, $3);
|
||||
CHECK_FOR_ERROR
|
||||
Value* tmpVal2 = getVal(*$2, $5);
|
||||
CHECK_FOR_ERROR
|
||||
$$ = new SetCondInst($1, tmpVal1, tmpVal2);
|
||||
if ($$ == 0)
|
||||
GEN_ERROR("binary operator returned null!");
|
||||
delete $2;
|
||||
}
|
||||
| ICMP IPredicates Types ValueRef ',' ValueRef {
|
||||
if (isa<PackedType>((*$3).get()))
|
||||
GEN_ERROR("Packed types not supported by icmp instruction");
|
||||
|
@ -432,8 +432,8 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
|
||||
Value *L = CI->getOperand(1);
|
||||
Value *R = CI->getOperand(2);
|
||||
|
||||
Value *LIsNan = new SetCondInst(Instruction::SetNE, L, L, "LIsNan", CI);
|
||||
Value *RIsNan = new SetCondInst(Instruction::SetNE, R, R, "RIsNan", CI);
|
||||
Value *LIsNan = new FCmpInst(FCmpInst::FCMP_ONE, L, L, "LIsNan", CI);
|
||||
Value *RIsNan = new FCmpInst(FCmpInst::FCMP_ONE, R, R, "RIsNan", CI);
|
||||
CI->replaceAllUsesWith(
|
||||
BinaryOperator::create(Instruction::Or, LIsNan, RIsNan,
|
||||
"isunordered", CI));
|
||||
|
@ -541,20 +541,6 @@ public:
|
||||
void visitAShr(User &I) { visitShift(I, ISD::SRA); }
|
||||
void visitICmp(User &I);
|
||||
void visitFCmp(User &I);
|
||||
void visitSetCC(User &I, ISD::CondCode SignedOpc, ISD::CondCode UnsignedOpc,
|
||||
ISD::CondCode FPOpc);
|
||||
void visitSetEQ(User &I) { visitSetCC(I, ISD::SETEQ, ISD::SETEQ,
|
||||
ISD::SETOEQ); }
|
||||
void visitSetNE(User &I) { visitSetCC(I, ISD::SETNE, ISD::SETNE,
|
||||
ISD::SETUNE); }
|
||||
void visitSetLE(User &I) { visitSetCC(I, ISD::SETLE, ISD::SETULE,
|
||||
ISD::SETOLE); }
|
||||
void visitSetGE(User &I) { visitSetCC(I, ISD::SETGE, ISD::SETUGE,
|
||||
ISD::SETOGE); }
|
||||
void visitSetLT(User &I) { visitSetCC(I, ISD::SETLT, ISD::SETULT,
|
||||
ISD::SETOLT); }
|
||||
void visitSetGT(User &I) { visitSetCC(I, ISD::SETGT, ISD::SETUGT,
|
||||
ISD::SETOGT); }
|
||||
// Visit the conversion instructions
|
||||
void visitTrunc(User &I);
|
||||
void visitZExt(User &I);
|
||||
@ -851,9 +837,10 @@ void SelectionDAGLowering::FindMergedConditions(Value *Cond,
|
||||
MachineBasicBlock *CurBB,
|
||||
unsigned Opc) {
|
||||
// If this node is not part of the or/and tree, emit it as a branch.
|
||||
BinaryOperator *BOp = dyn_cast<BinaryOperator>(Cond);
|
||||
Instruction *BOp = dyn_cast<Instruction>(Cond);
|
||||
|
||||
if (!BOp || (unsigned)BOp->getOpcode() != Opc || !BOp->hasOneUse() ||
|
||||
if (!BOp || !(isa<BinaryOperator>(BOp) || isa<CmpInst>(BOp)) ||
|
||||
(unsigned)BOp->getOpcode() != Opc || !BOp->hasOneUse() ||
|
||||
BOp->getParent() != CurBB->getBasicBlock() ||
|
||||
!InBlock(BOp->getOperand(0), CurBB->getBasicBlock()) ||
|
||||
!InBlock(BOp->getOperand(1), CurBB->getBasicBlock())) {
|
||||
@ -875,61 +862,60 @@ void SelectionDAGLowering::FindMergedConditions(Value *Cond,
|
||||
}
|
||||
|
||||
|
||||
// If the leaf of the tree is a setcond inst, merge the condition into the
|
||||
// caseblock.
|
||||
if (BOp && isa<SetCondInst>(BOp) &&
|
||||
// The operands of the setcc have to be in this block. We don't know
|
||||
// If the leaf of the tree is a comparison, merge the condition into
|
||||
// the caseblock.
|
||||
if ((isa<ICmpInst>(Cond) || isa<FCmpInst>(Cond)) &&
|
||||
// The operands of the cmp have to be in this block. We don't know
|
||||
// how to export them from some other block. If this is the first block
|
||||
// of the sequence, no exporting is needed.
|
||||
(CurBB == CurMBB ||
|
||||
(isExportableFromCurrentBlock(BOp->getOperand(0), BB) &&
|
||||
isExportableFromCurrentBlock(BOp->getOperand(1), BB)))) {
|
||||
ISD::CondCode SignCond, UnsCond, FPCond, Condition;
|
||||
switch (BOp->getOpcode()) {
|
||||
default: assert(0 && "Unknown setcc opcode!");
|
||||
case Instruction::SetEQ:
|
||||
SignCond = ISD::SETEQ;
|
||||
UnsCond = ISD::SETEQ;
|
||||
FPCond = ISD::SETOEQ;
|
||||
break;
|
||||
case Instruction::SetNE:
|
||||
SignCond = ISD::SETNE;
|
||||
UnsCond = ISD::SETNE;
|
||||
FPCond = ISD::SETUNE;
|
||||
break;
|
||||
case Instruction::SetLE:
|
||||
SignCond = ISD::SETLE;
|
||||
UnsCond = ISD::SETULE;
|
||||
FPCond = ISD::SETOLE;
|
||||
break;
|
||||
case Instruction::SetGE:
|
||||
SignCond = ISD::SETGE;
|
||||
UnsCond = ISD::SETUGE;
|
||||
FPCond = ISD::SETOGE;
|
||||
break;
|
||||
case Instruction::SetLT:
|
||||
SignCond = ISD::SETLT;
|
||||
UnsCond = ISD::SETULT;
|
||||
FPCond = ISD::SETOLT;
|
||||
break;
|
||||
case Instruction::SetGT:
|
||||
SignCond = ISD::SETGT;
|
||||
UnsCond = ISD::SETUGT;
|
||||
FPCond = ISD::SETOGT;
|
||||
break;
|
||||
BOp = cast<Instruction>(Cond);
|
||||
ISD::CondCode Condition;
|
||||
if (ICmpInst *IC = dyn_cast<ICmpInst>(Cond)) {
|
||||
switch (IC->getPredicate()) {
|
||||
default: assert(0 && "Unknown icmp predicate opcode!");
|
||||
case ICmpInst::ICMP_EQ: Condition = ISD::SETEQ; break;
|
||||
case ICmpInst::ICMP_NE: Condition = ISD::SETNE; break;
|
||||
case ICmpInst::ICMP_SLE: Condition = ISD::SETLE; break;
|
||||
case ICmpInst::ICMP_ULE: Condition = ISD::SETULE; break;
|
||||
case ICmpInst::ICMP_SGE: Condition = ISD::SETGE; break;
|
||||
case ICmpInst::ICMP_UGE: Condition = ISD::SETUGE; break;
|
||||
case ICmpInst::ICMP_SLT: Condition = ISD::SETLT; break;
|
||||
case ICmpInst::ICMP_ULT: Condition = ISD::SETULT; break;
|
||||
case ICmpInst::ICMP_SGT: Condition = ISD::SETGT; break;
|
||||
case ICmpInst::ICMP_UGT: Condition = ISD::SETUGT; break;
|
||||
}
|
||||
} else if (FCmpInst *FC = dyn_cast<FCmpInst>(Cond)) {
|
||||
ISD::CondCode FPC, FOC;
|
||||
switch (FC->getPredicate()) {
|
||||
default: assert(0 && "Unknown fcmp predicate opcode!");
|
||||
case FCmpInst::FCMP_FALSE: FOC = FPC = ISD::SETFALSE; break;
|
||||
case FCmpInst::FCMP_OEQ: FOC = ISD::SETEQ; FPC = ISD::SETOEQ; break;
|
||||
case FCmpInst::FCMP_OGT: FOC = ISD::SETGT; FPC = ISD::SETOGT; break;
|
||||
case FCmpInst::FCMP_OGE: FOC = ISD::SETGE; FPC = ISD::SETOGE; break;
|
||||
case FCmpInst::FCMP_OLT: FOC = ISD::SETLT; FPC = ISD::SETOLT; break;
|
||||
case FCmpInst::FCMP_OLE: FOC = ISD::SETLE; FPC = ISD::SETOLE; break;
|
||||
case FCmpInst::FCMP_ONE: FOC = ISD::SETNE; FPC = ISD::SETONE; break;
|
||||
case FCmpInst::FCMP_ORD: FOC = ISD::SETEQ; FPC = ISD::SETO; break;
|
||||
case FCmpInst::FCMP_UNO: FOC = ISD::SETNE; FPC = ISD::SETUO; break;
|
||||
case FCmpInst::FCMP_UEQ: FOC = ISD::SETEQ; FPC = ISD::SETUEQ; break;
|
||||
case FCmpInst::FCMP_UGT: FOC = ISD::SETGT; FPC = ISD::SETUGT; break;
|
||||
case FCmpInst::FCMP_UGE: FOC = ISD::SETGE; FPC = ISD::SETUGE; break;
|
||||
case FCmpInst::FCMP_ULT: FOC = ISD::SETLT; FPC = ISD::SETULT; break;
|
||||
case FCmpInst::FCMP_ULE: FOC = ISD::SETLE; FPC = ISD::SETULE; break;
|
||||
case FCmpInst::FCMP_UNE: FOC = ISD::SETNE; FPC = ISD::SETUNE; break;
|
||||
case FCmpInst::FCMP_TRUE: FOC = FPC = ISD::SETTRUE; break;
|
||||
}
|
||||
if (FiniteOnlyFPMath())
|
||||
Condition = FOC;
|
||||
else
|
||||
Condition = FPC;
|
||||
} else {
|
||||
assert(0 && "Unknown compare instruction");
|
||||
}
|
||||
|
||||
const Type *OpType = BOp->getOperand(0)->getType();
|
||||
if (const PackedType *PTy = dyn_cast<PackedType>(OpType))
|
||||
OpType = PTy->getElementType();
|
||||
|
||||
if (!FiniteOnlyFPMath() && OpType->isFloatingPoint())
|
||||
Condition = FPCond;
|
||||
else if (OpType->isUnsigned())
|
||||
Condition = UnsCond;
|
||||
else
|
||||
Condition = SignCond;
|
||||
|
||||
SelectionDAGISel::CaseBlock CB(Condition, BOp->getOperand(0),
|
||||
BOp->getOperand(1), TBB, FBB, CurBB);
|
||||
SwitchCases.push_back(CB);
|
||||
@ -1462,11 +1448,15 @@ void SelectionDAGLowering::visitShift(User &I, unsigned Opcode) {
|
||||
}
|
||||
|
||||
void SelectionDAGLowering::visitICmp(User &I) {
|
||||
ICmpInst *IC = cast<ICmpInst>(&I);
|
||||
SDOperand Op1 = getValue(IC->getOperand(0));
|
||||
SDOperand Op2 = getValue(IC->getOperand(1));
|
||||
ICmpInst::Predicate predicate = ICmpInst::BAD_ICMP_PREDICATE;
|
||||
if (ICmpInst *IC = dyn_cast<ICmpInst>(&I))
|
||||
predicate = IC->getPredicate();
|
||||
else if (ConstantExpr *IC = dyn_cast<ConstantExpr>(&I))
|
||||
predicate = ICmpInst::Predicate(IC->getPredicate());
|
||||
SDOperand Op1 = getValue(I.getOperand(0));
|
||||
SDOperand Op2 = getValue(I.getOperand(1));
|
||||
ISD::CondCode Opcode;
|
||||
switch (IC->getPredicate()) {
|
||||
switch (predicate) {
|
||||
case ICmpInst::ICMP_EQ : Opcode = ISD::SETEQ; break;
|
||||
case ICmpInst::ICMP_NE : Opcode = ISD::SETNE; break;
|
||||
case ICmpInst::ICMP_UGT : Opcode = ISD::SETUGT; break;
|
||||
@ -1486,46 +1476,41 @@ void SelectionDAGLowering::visitICmp(User &I) {
|
||||
}
|
||||
|
||||
void SelectionDAGLowering::visitFCmp(User &I) {
|
||||
FCmpInst *FC = cast<FCmpInst>(&I);
|
||||
SDOperand Op1 = getValue(FC->getOperand(0));
|
||||
SDOperand Op2 = getValue(FC->getOperand(1));
|
||||
ISD::CondCode Opcode;
|
||||
switch (FC->getPredicate()) {
|
||||
case FCmpInst::FCMP_FALSE : Opcode = ISD::SETFALSE;
|
||||
case FCmpInst::FCMP_OEQ : Opcode = ISD::SETOEQ;
|
||||
case FCmpInst::FCMP_OGT : Opcode = ISD::SETOGT;
|
||||
case FCmpInst::FCMP_OGE : Opcode = ISD::SETOGE;
|
||||
case FCmpInst::FCMP_OLT : Opcode = ISD::SETOLT;
|
||||
case FCmpInst::FCMP_OLE : Opcode = ISD::SETOLE;
|
||||
case FCmpInst::FCMP_ONE : Opcode = ISD::SETONE;
|
||||
case FCmpInst::FCMP_ORD : Opcode = ISD::SETO;
|
||||
case FCmpInst::FCMP_UNO : Opcode = ISD::SETUO;
|
||||
case FCmpInst::FCMP_UEQ : Opcode = ISD::SETUEQ;
|
||||
case FCmpInst::FCMP_UGT : Opcode = ISD::SETUGT;
|
||||
case FCmpInst::FCMP_UGE : Opcode = ISD::SETUGE;
|
||||
case FCmpInst::FCMP_ULT : Opcode = ISD::SETULT;
|
||||
case FCmpInst::FCMP_ULE : Opcode = ISD::SETULE;
|
||||
case FCmpInst::FCMP_UNE : Opcode = ISD::SETUNE;
|
||||
case FCmpInst::FCMP_TRUE : Opcode = ISD::SETTRUE;
|
||||
default:
|
||||
assert(!"Invalid FCmp predicate value");
|
||||
Opcode = ISD::SETFALSE;
|
||||
break;
|
||||
}
|
||||
setValue(&I, DAG.getSetCC(MVT::i1, Op1, Op2, Opcode));
|
||||
}
|
||||
|
||||
void SelectionDAGLowering::visitSetCC(User &I,ISD::CondCode SignedOpcode,
|
||||
ISD::CondCode UnsignedOpcode,
|
||||
ISD::CondCode FPOpcode) {
|
||||
FCmpInst::Predicate predicate = FCmpInst::BAD_FCMP_PREDICATE;
|
||||
if (FCmpInst *FC = dyn_cast<FCmpInst>(&I))
|
||||
predicate = FC->getPredicate();
|
||||
else if (ConstantExpr *FC = dyn_cast<ConstantExpr>(&I))
|
||||
predicate = FCmpInst::Predicate(FC->getPredicate());
|
||||
SDOperand Op1 = getValue(I.getOperand(0));
|
||||
SDOperand Op2 = getValue(I.getOperand(1));
|
||||
ISD::CondCode Opcode = SignedOpcode;
|
||||
if (!FiniteOnlyFPMath() && I.getOperand(0)->getType()->isFloatingPoint())
|
||||
Opcode = FPOpcode;
|
||||
else if (I.getOperand(0)->getType()->isUnsigned())
|
||||
Opcode = UnsignedOpcode;
|
||||
setValue(&I, DAG.getSetCC(MVT::i1, Op1, Op2, Opcode));
|
||||
ISD::CondCode Condition, FOC, FPC;
|
||||
switch (predicate) {
|
||||
case FCmpInst::FCMP_FALSE: FOC = FPC = ISD::SETFALSE; break;
|
||||
case FCmpInst::FCMP_OEQ: FOC = ISD::SETEQ; FPC = ISD::SETOEQ; break;
|
||||
case FCmpInst::FCMP_OGT: FOC = ISD::SETGT; FPC = ISD::SETOGT; break;
|
||||
case FCmpInst::FCMP_OGE: FOC = ISD::SETGE; FPC = ISD::SETOGE; break;
|
||||
case FCmpInst::FCMP_OLT: FOC = ISD::SETLT; FPC = ISD::SETOLT; break;
|
||||
case FCmpInst::FCMP_OLE: FOC = ISD::SETLE; FPC = ISD::SETOLE; break;
|
||||
case FCmpInst::FCMP_ONE: FOC = ISD::SETNE; FPC = ISD::SETONE; break;
|
||||
case FCmpInst::FCMP_ORD: FOC = ISD::SETEQ; FPC = ISD::SETO; break;
|
||||
case FCmpInst::FCMP_UNO: FOC = ISD::SETNE; FPC = ISD::SETUO; break;
|
||||
case FCmpInst::FCMP_UEQ: FOC = ISD::SETEQ; FPC = ISD::SETUEQ; break;
|
||||
case FCmpInst::FCMP_UGT: FOC = ISD::SETGT; FPC = ISD::SETUGT; break;
|
||||
case FCmpInst::FCMP_UGE: FOC = ISD::SETGE; FPC = ISD::SETUGE; break;
|
||||
case FCmpInst::FCMP_ULT: FOC = ISD::SETLT; FPC = ISD::SETULT; break;
|
||||
case FCmpInst::FCMP_ULE: FOC = ISD::SETLE; FPC = ISD::SETULE; break;
|
||||
case FCmpInst::FCMP_UNE: FOC = ISD::SETNE; FPC = ISD::SETUNE; break;
|
||||
case FCmpInst::FCMP_TRUE: FOC = FPC = ISD::SETTRUE; break;
|
||||
default:
|
||||
assert(!"Invalid FCmp predicate value");
|
||||
FOC = FPC = ISD::SETFALSE;
|
||||
break;
|
||||
}
|
||||
if (FiniteOnlyFPMath())
|
||||
Condition = FOC;
|
||||
else
|
||||
Condition = FPC;
|
||||
setValue(&I, DAG.getSetCC(MVT::i1, Op1, Op2, Condition));
|
||||
}
|
||||
|
||||
void SelectionDAGLowering::visitSelect(User &I) {
|
||||
|
@ -55,18 +55,8 @@ static GenericValue executeOrInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeXorInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeSetEQInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeSetNEInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeSetLTInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeSetGTInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeSetLEInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeSetGEInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeCmpInst(unsigned predicate, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty);
|
||||
static GenericValue executeShlInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeLShrInst(GenericValue Src1, GenericValue Src2,
|
||||
@ -144,30 +134,12 @@ GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE,
|
||||
return executeXorInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::SetEQ:
|
||||
return executeSetEQInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::SetNE:
|
||||
return executeSetNEInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::SetLE:
|
||||
return executeSetLEInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::SetGE:
|
||||
return executeSetGEInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::SetLT:
|
||||
return executeSetLTInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::SetGT:
|
||||
return executeSetGTInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::FCmp:
|
||||
case Instruction::ICmp:
|
||||
return executeCmpInst(CE->getPredicate(),
|
||||
getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::Shl:
|
||||
return executeShlInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
@ -434,33 +406,227 @@ static GenericValue executeXorInst(GenericValue Src1, GenericValue Src2,
|
||||
return Dest;
|
||||
}
|
||||
|
||||
#define IMPLEMENT_SETCC(OP, TY) \
|
||||
case Type::TY##TyID: Dest.BoolVal = Src1.TY##Val OP Src2.TY##Val; break
|
||||
#define IMPLEMENT_CMP(OP, TY1, TY2) \
|
||||
case Type::TY1##TyID: Dest.BoolVal = Src1.TY2##Val OP Src2.TY2##Val; break
|
||||
|
||||
// Handle pointers specially because they must be compared with only as much
|
||||
// width as the host has. We _do not_ want to be comparing 64 bit values when
|
||||
// running on a 32-bit target, otherwise the upper 32 bits might mess up
|
||||
// comparisons if they contain garbage.
|
||||
#define IMPLEMENT_POINTERSETCC(OP) \
|
||||
#define IMPLEMENT_POINTERCMP(OP) \
|
||||
case Type::PointerTyID: \
|
||||
Dest.BoolVal = (void*)(intptr_t)Src1.PointerVal OP \
|
||||
(void*)(intptr_t)Src2.PointerVal; break
|
||||
|
||||
static GenericValue executeSetEQInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
static GenericValue executeICMP_EQ(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_CMP(==, UByte, UByte);
|
||||
IMPLEMENT_CMP(==, SByte, SByte);
|
||||
IMPLEMENT_CMP(==, UShort, UShort);
|
||||
IMPLEMENT_CMP(==, Short, Short);
|
||||
IMPLEMENT_CMP(==, UInt, UInt);
|
||||
IMPLEMENT_CMP(==, Int, Int);
|
||||
IMPLEMENT_CMP(==, ULong, ULong);
|
||||
IMPLEMENT_CMP(==, Long, Long);
|
||||
IMPLEMENT_POINTERCMP(==);
|
||||
default:
|
||||
cerr << "Unhandled type for ICMP_EQ predicate: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeICMP_NE(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_CMP(!=, UByte, UByte);
|
||||
IMPLEMENT_CMP(!=, SByte, SByte);
|
||||
IMPLEMENT_CMP(!=, UShort,UShort);
|
||||
IMPLEMENT_CMP(!=, Short, Short);
|
||||
IMPLEMENT_CMP(!=, UInt, UInt);
|
||||
IMPLEMENT_CMP(!=, Int, Int);
|
||||
IMPLEMENT_CMP(!=, ULong, ULong);
|
||||
IMPLEMENT_CMP(!=, Long, Long);
|
||||
IMPLEMENT_POINTERCMP(!=);
|
||||
default:
|
||||
cerr << "Unhandled type for ICMP_NE predicate: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeICMP_ULT(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_CMP(<, SByte, UByte);
|
||||
IMPLEMENT_CMP(<, Short, UShort);
|
||||
IMPLEMENT_CMP(<, Int, UInt);
|
||||
IMPLEMENT_CMP(<, Long, ULong);
|
||||
IMPLEMENT_CMP(<, UByte, UByte);
|
||||
IMPLEMENT_CMP(<, UShort, UShort);
|
||||
IMPLEMENT_CMP(<, UInt, UInt);
|
||||
IMPLEMENT_CMP(<, ULong, ULong);
|
||||
IMPLEMENT_POINTERCMP(<);
|
||||
default:
|
||||
cerr << "Unhandled type for ICMP_ULT predicate: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeICMP_SLT(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_CMP(<, SByte, SByte);
|
||||
IMPLEMENT_CMP(<, Short, Short);
|
||||
IMPLEMENT_CMP(<, Int, Int);
|
||||
IMPLEMENT_CMP(<, Long, Long);
|
||||
IMPLEMENT_CMP(<, UByte, SByte);
|
||||
IMPLEMENT_CMP(<, UShort, Short);
|
||||
IMPLEMENT_CMP(<, UInt, Int);
|
||||
IMPLEMENT_CMP(<, ULong, Long);
|
||||
IMPLEMENT_POINTERCMP(<);
|
||||
default:
|
||||
cerr << "Unhandled type for ICMP_SLT predicate: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeICMP_UGT(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_CMP(>, SByte, UByte);
|
||||
IMPLEMENT_CMP(>, Short, UShort);
|
||||
IMPLEMENT_CMP(>, Int, UInt);
|
||||
IMPLEMENT_CMP(>, Long, ULong);
|
||||
IMPLEMENT_CMP(>, UByte, UByte);
|
||||
IMPLEMENT_CMP(>, UShort, UShort);
|
||||
IMPLEMENT_CMP(>, UInt, UInt);
|
||||
IMPLEMENT_CMP(>, ULong, ULong);
|
||||
IMPLEMENT_POINTERCMP(>);
|
||||
default:
|
||||
cerr << "Unhandled type for ICMP_UGT predicate: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeICMP_SGT(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_CMP(>, SByte, SByte);
|
||||
IMPLEMENT_CMP(>, Short, Short);
|
||||
IMPLEMENT_CMP(>, Int, Int);
|
||||
IMPLEMENT_CMP(>, Long, Long);
|
||||
IMPLEMENT_CMP(>, UByte, SByte);
|
||||
IMPLEMENT_CMP(>, UShort, Short);
|
||||
IMPLEMENT_CMP(>, UInt, Int);
|
||||
IMPLEMENT_CMP(>, ULong, Long);
|
||||
IMPLEMENT_POINTERCMP(>);
|
||||
default:
|
||||
cerr << "Unhandled type for ICMP_SGT predicate: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeICMP_ULE(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_CMP(<=, SByte, UByte);
|
||||
IMPLEMENT_CMP(<=, Short, UShort);
|
||||
IMPLEMENT_CMP(<=, Int, UInt);
|
||||
IMPLEMENT_CMP(<=, Long, ULong);
|
||||
IMPLEMENT_CMP(<=, UByte, UByte);
|
||||
IMPLEMENT_CMP(<=, UShort, UShort);
|
||||
IMPLEMENT_CMP(<=, UInt, UInt);
|
||||
IMPLEMENT_CMP(<=, ULong, ULong);
|
||||
IMPLEMENT_POINTERCMP(<=);
|
||||
default:
|
||||
cerr << "Unhandled type for ICMP_ULE predicate: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeICMP_SLE(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_CMP(<=, SByte, SByte);
|
||||
IMPLEMENT_CMP(<=, Short, Short);
|
||||
IMPLEMENT_CMP(<=, Int, Int);
|
||||
IMPLEMENT_CMP(<=, Long, Long);
|
||||
IMPLEMENT_CMP(<=, UByte, SByte);
|
||||
IMPLEMENT_CMP(<=, UShort, Short);
|
||||
IMPLEMENT_CMP(<=, UInt, Int);
|
||||
IMPLEMENT_CMP(<=, ULong, Long);
|
||||
IMPLEMENT_POINTERCMP(<=);
|
||||
default:
|
||||
cerr << "Unhandled type for ICMP_SLE predicate: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeICMP_UGE(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_CMP(>=, SByte, UByte);
|
||||
IMPLEMENT_CMP(>=, Short, UShort);
|
||||
IMPLEMENT_CMP(>=, Int, UInt);
|
||||
IMPLEMENT_CMP(>=, Long, ULong);
|
||||
IMPLEMENT_CMP(>=, UByte, UByte);
|
||||
IMPLEMENT_CMP(>=, UShort, UShort);
|
||||
IMPLEMENT_CMP(>=, UInt, UInt);
|
||||
IMPLEMENT_CMP(>=, ULong, ULong);
|
||||
IMPLEMENT_POINTERCMP(>=);
|
||||
default:
|
||||
cerr << "Unhandled type for ICMP_UGE predicate: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeICMP_SGE(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_CMP(>=, SByte, SByte);
|
||||
IMPLEMENT_CMP(>=, Short, Short);
|
||||
IMPLEMENT_CMP(>=, Int, Int);
|
||||
IMPLEMENT_CMP(>=, Long, Long);
|
||||
IMPLEMENT_CMP(>=, UByte, SByte);
|
||||
IMPLEMENT_CMP(>=, UShort, Short);
|
||||
IMPLEMENT_CMP(>=, UInt, Int);
|
||||
IMPLEMENT_CMP(>=, ULong, Long);
|
||||
IMPLEMENT_POINTERCMP(>=);
|
||||
default:
|
||||
cerr << "Unhandled type for ICMP_SGE predicate: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
#define IMPLEMENT_SETCC(OP, TY) \
|
||||
case Type::TY##TyID: Dest.BoolVal = Src1.TY##Val OP Src2.TY##Val; break
|
||||
|
||||
static GenericValue executeFCMP_EQ(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_SETCC(==, UByte);
|
||||
IMPLEMENT_SETCC(==, SByte);
|
||||
IMPLEMENT_SETCC(==, UShort);
|
||||
IMPLEMENT_SETCC(==, Short);
|
||||
IMPLEMENT_SETCC(==, UInt);
|
||||
IMPLEMENT_SETCC(==, Int);
|
||||
IMPLEMENT_SETCC(==, ULong);
|
||||
IMPLEMENT_SETCC(==, Long);
|
||||
IMPLEMENT_SETCC(==, Float);
|
||||
IMPLEMENT_SETCC(==, Double);
|
||||
IMPLEMENT_POINTERSETCC(==);
|
||||
default:
|
||||
cerr << "Unhandled type for SetEQ instruction: " << *Ty << "\n";
|
||||
abort();
|
||||
@ -468,21 +634,12 @@ static GenericValue executeSetEQInst(GenericValue Src1, GenericValue Src2,
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeSetNEInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
static GenericValue executeFCMP_NE(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_SETCC(!=, UByte);
|
||||
IMPLEMENT_SETCC(!=, SByte);
|
||||
IMPLEMENT_SETCC(!=, UShort);
|
||||
IMPLEMENT_SETCC(!=, Short);
|
||||
IMPLEMENT_SETCC(!=, UInt);
|
||||
IMPLEMENT_SETCC(!=, Int);
|
||||
IMPLEMENT_SETCC(!=, ULong);
|
||||
IMPLEMENT_SETCC(!=, Long);
|
||||
IMPLEMENT_SETCC(!=, Float);
|
||||
IMPLEMENT_SETCC(!=, Double);
|
||||
IMPLEMENT_POINTERSETCC(!=);
|
||||
|
||||
default:
|
||||
cerr << "Unhandled type for SetNE instruction: " << *Ty << "\n";
|
||||
@ -491,21 +648,12 @@ static GenericValue executeSetNEInst(GenericValue Src1, GenericValue Src2,
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeSetLEInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
static GenericValue executeFCMP_LE(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_SETCC(<=, UByte);
|
||||
IMPLEMENT_SETCC(<=, SByte);
|
||||
IMPLEMENT_SETCC(<=, UShort);
|
||||
IMPLEMENT_SETCC(<=, Short);
|
||||
IMPLEMENT_SETCC(<=, UInt);
|
||||
IMPLEMENT_SETCC(<=, Int);
|
||||
IMPLEMENT_SETCC(<=, ULong);
|
||||
IMPLEMENT_SETCC(<=, Long);
|
||||
IMPLEMENT_SETCC(<=, Float);
|
||||
IMPLEMENT_SETCC(<=, Double);
|
||||
IMPLEMENT_POINTERSETCC(<=);
|
||||
default:
|
||||
cerr << "Unhandled type for SetLE instruction: " << *Ty << "\n";
|
||||
abort();
|
||||
@ -513,21 +661,12 @@ static GenericValue executeSetLEInst(GenericValue Src1, GenericValue Src2,
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeSetGEInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
static GenericValue executeFCMP_GE(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_SETCC(>=, UByte);
|
||||
IMPLEMENT_SETCC(>=, SByte);
|
||||
IMPLEMENT_SETCC(>=, UShort);
|
||||
IMPLEMENT_SETCC(>=, Short);
|
||||
IMPLEMENT_SETCC(>=, UInt);
|
||||
IMPLEMENT_SETCC(>=, Int);
|
||||
IMPLEMENT_SETCC(>=, ULong);
|
||||
IMPLEMENT_SETCC(>=, Long);
|
||||
IMPLEMENT_SETCC(>=, Float);
|
||||
IMPLEMENT_SETCC(>=, Double);
|
||||
IMPLEMENT_POINTERSETCC(>=);
|
||||
default:
|
||||
cerr << "Unhandled type for SetGE instruction: " << *Ty << "\n";
|
||||
abort();
|
||||
@ -535,21 +674,12 @@ static GenericValue executeSetGEInst(GenericValue Src1, GenericValue Src2,
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeSetLTInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
static GenericValue executeFCMP_LT(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_SETCC(<, UByte);
|
||||
IMPLEMENT_SETCC(<, SByte);
|
||||
IMPLEMENT_SETCC(<, UShort);
|
||||
IMPLEMENT_SETCC(<, Short);
|
||||
IMPLEMENT_SETCC(<, UInt);
|
||||
IMPLEMENT_SETCC(<, Int);
|
||||
IMPLEMENT_SETCC(<, ULong);
|
||||
IMPLEMENT_SETCC(<, Long);
|
||||
IMPLEMENT_SETCC(<, Float);
|
||||
IMPLEMENT_SETCC(<, Double);
|
||||
IMPLEMENT_POINTERSETCC(<);
|
||||
default:
|
||||
cerr << "Unhandled type for SetLT instruction: " << *Ty << "\n";
|
||||
abort();
|
||||
@ -557,21 +687,12 @@ static GenericValue executeSetLTInst(GenericValue Src1, GenericValue Src2,
|
||||
return Dest;
|
||||
}
|
||||
|
||||
static GenericValue executeSetGTInst(GenericValue Src1, GenericValue Src2,
|
||||
static GenericValue executeFCMP_GT(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty) {
|
||||
GenericValue Dest;
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_SETCC(>, UByte);
|
||||
IMPLEMENT_SETCC(>, SByte);
|
||||
IMPLEMENT_SETCC(>, UShort);
|
||||
IMPLEMENT_SETCC(>, Short);
|
||||
IMPLEMENT_SETCC(>, UInt);
|
||||
IMPLEMENT_SETCC(>, Int);
|
||||
IMPLEMENT_SETCC(>, ULong);
|
||||
IMPLEMENT_SETCC(>, Long);
|
||||
IMPLEMENT_SETCC(>, Float);
|
||||
IMPLEMENT_SETCC(>, Double);
|
||||
IMPLEMENT_POINTERSETCC(>);
|
||||
default:
|
||||
cerr << "Unhandled type for SetGT instruction: " << *Ty << "\n";
|
||||
abort();
|
||||
@ -579,6 +700,108 @@ static GenericValue executeSetGTInst(GenericValue Src1, GenericValue Src2,
|
||||
return Dest;
|
||||
}
|
||||
|
||||
void Interpreter::visitFCmpInst(FCmpInst &I) {
|
||||
ExecutionContext &SF = ECStack.back();
|
||||
const Type *Ty = I.getOperand(0)->getType();
|
||||
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
|
||||
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
|
||||
GenericValue R; // Result
|
||||
|
||||
switch (I.getPredicate()) {
|
||||
case FCmpInst::FCMP_FALSE: R.BoolVal = false;
|
||||
case FCmpInst::FCMP_ORD: R = executeFCMP_EQ(Src1, Src2, Ty); break; ///???
|
||||
case FCmpInst::FCMP_UNO: R = executeFCMP_NE(Src1, Src2, Ty); break; ///???
|
||||
case FCmpInst::FCMP_OEQ:
|
||||
case FCmpInst::FCMP_UEQ: R = executeFCMP_EQ(Src1, Src2, Ty); break;
|
||||
case FCmpInst::FCMP_ONE:
|
||||
case FCmpInst::FCMP_UNE: R = executeFCMP_NE(Src1, Src2, Ty); break;
|
||||
case FCmpInst::FCMP_OLT:
|
||||
case FCmpInst::FCMP_ULT: R = executeFCMP_LT(Src1, Src2, Ty); break;
|
||||
case FCmpInst::FCMP_OGT:
|
||||
case FCmpInst::FCMP_UGT: R = executeFCMP_GT(Src1, Src2, Ty); break;
|
||||
case FCmpInst::FCMP_OLE:
|
||||
case FCmpInst::FCMP_ULE: R = executeFCMP_LE(Src1, Src2, Ty); break;
|
||||
case FCmpInst::FCMP_OGE:
|
||||
case FCmpInst::FCMP_UGE: R = executeFCMP_GE(Src1, Src2, Ty); break;
|
||||
case FCmpInst::FCMP_TRUE: R.BoolVal = true;
|
||||
default:
|
||||
cerr << "Don't know how to handle this FCmp predicate!\n-->" << I;
|
||||
abort();
|
||||
}
|
||||
|
||||
SetValue(&I, R, SF);
|
||||
}
|
||||
|
||||
void Interpreter::visitICmpInst(ICmpInst &I) {
|
||||
ExecutionContext &SF = ECStack.back();
|
||||
const Type *Ty = I.getOperand(0)->getType();
|
||||
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
|
||||
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
|
||||
GenericValue R; // Result
|
||||
|
||||
switch (I.getPredicate()) {
|
||||
case ICmpInst::ICMP_EQ: R = executeICMP_EQ(Src1, Src2, Ty); break;
|
||||
case ICmpInst::ICMP_NE: R = executeICMP_NE(Src1, Src2, Ty); break;
|
||||
case ICmpInst::ICMP_ULT: R = executeICMP_ULT(Src1, Src2, Ty); break;
|
||||
case ICmpInst::ICMP_SLT: R = executeICMP_SLT(Src1, Src2, Ty); break;
|
||||
case ICmpInst::ICMP_UGT: R = executeICMP_UGT(Src1, Src2, Ty); break;
|
||||
case ICmpInst::ICMP_SGT: R = executeICMP_SGT(Src1, Src2, Ty); break;
|
||||
case ICmpInst::ICMP_ULE: R = executeICMP_ULE(Src1, Src2, Ty); break;
|
||||
case ICmpInst::ICMP_SLE: R = executeICMP_SLE(Src1, Src2, Ty); break;
|
||||
case ICmpInst::ICMP_UGE: R = executeICMP_UGE(Src1, Src2, Ty); break;
|
||||
case ICmpInst::ICMP_SGE: R = executeICMP_SGE(Src1, Src2, Ty); break;
|
||||
default:
|
||||
cerr << "Don't know how to handle this ICmp predicate!\n-->" << I;
|
||||
abort();
|
||||
}
|
||||
|
||||
SetValue(&I, R, SF);
|
||||
}
|
||||
|
||||
static GenericValue executeCmpInst(unsigned predicate, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
GenericValue Result;
|
||||
switch (predicate) {
|
||||
case ICmpInst::ICMP_EQ: return executeICMP_EQ(Src1, Src2, Ty);
|
||||
case ICmpInst::ICMP_NE: return executeICMP_NE(Src1, Src2, Ty);
|
||||
case ICmpInst::ICMP_UGT: return executeICMP_UGT(Src1, Src2, Ty);
|
||||
case ICmpInst::ICMP_SGT: return executeICMP_SGT(Src1, Src2, Ty);
|
||||
case ICmpInst::ICMP_ULT: return executeICMP_ULT(Src1, Src2, Ty);
|
||||
case ICmpInst::ICMP_SLT: return executeICMP_SLT(Src1, Src2, Ty);
|
||||
case ICmpInst::ICMP_UGE: return executeICMP_UGE(Src1, Src2, Ty);
|
||||
case ICmpInst::ICMP_SGE: return executeICMP_SGE(Src1, Src2, Ty);
|
||||
case ICmpInst::ICMP_ULE: return executeICMP_ULE(Src1, Src2, Ty);
|
||||
case ICmpInst::ICMP_SLE: return executeICMP_SLE(Src1, Src2, Ty);
|
||||
case FCmpInst::FCMP_ORD: return executeFCMP_EQ(Src1, Src2, Ty); break;
|
||||
case FCmpInst::FCMP_UNO: return executeFCMP_NE(Src1, Src2, Ty); break;
|
||||
case FCmpInst::FCMP_OEQ:
|
||||
case FCmpInst::FCMP_UEQ: return executeFCMP_EQ(Src1, Src2, Ty); break;
|
||||
case FCmpInst::FCMP_ONE:
|
||||
case FCmpInst::FCMP_UNE: return executeFCMP_NE(Src1, Src2, Ty); break;
|
||||
case FCmpInst::FCMP_OLT:
|
||||
case FCmpInst::FCMP_ULT: return executeFCMP_LT(Src1, Src2, Ty); break;
|
||||
case FCmpInst::FCMP_OGT:
|
||||
case FCmpInst::FCMP_UGT: return executeFCMP_GT(Src1, Src2, Ty); break;
|
||||
case FCmpInst::FCMP_OLE:
|
||||
case FCmpInst::FCMP_ULE: return executeFCMP_LE(Src1, Src2, Ty); break;
|
||||
case FCmpInst::FCMP_OGE:
|
||||
case FCmpInst::FCMP_UGE: return executeFCMP_GE(Src1, Src2, Ty); break;
|
||||
case FCmpInst::FCMP_FALSE: {
|
||||
GenericValue Result;
|
||||
Result.BoolVal = false;
|
||||
return Result;
|
||||
}
|
||||
case FCmpInst::FCMP_TRUE: {
|
||||
GenericValue Result;
|
||||
Result.BoolVal = true;
|
||||
return Result;
|
||||
}
|
||||
default:
|
||||
cerr << "Unhandled Cmp predicate\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::visitBinaryOperator(BinaryOperator &I) {
|
||||
ExecutionContext &SF = ECStack.back();
|
||||
const Type *Ty = I.getOperand(0)->getType();
|
||||
@ -599,12 +822,6 @@ void Interpreter::visitBinaryOperator(BinaryOperator &I) {
|
||||
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;
|
||||
case Instruction::SetEQ: R = executeSetEQInst(Src1, Src2, Ty); break;
|
||||
case Instruction::SetNE: R = executeSetNEInst(Src1, Src2, Ty); break;
|
||||
case Instruction::SetLE: R = executeSetLEInst(Src1, Src2, Ty); break;
|
||||
case Instruction::SetGE: R = executeSetGEInst(Src1, Src2, Ty); break;
|
||||
case Instruction::SetLT: R = executeSetLTInst(Src1, Src2, Ty); break;
|
||||
case Instruction::SetGT: R = executeSetGTInst(Src1, Src2, Ty); break;
|
||||
default:
|
||||
cerr << "Don't know how to handle this binary operator!\n-->" << I;
|
||||
abort();
|
||||
@ -732,8 +949,8 @@ void Interpreter::visitSwitchInst(SwitchInst &I) {
|
||||
// Check to see if any of the cases match...
|
||||
BasicBlock *Dest = 0;
|
||||
for (unsigned i = 2, e = I.getNumOperands(); i != e; i += 2)
|
||||
if (executeSetEQInst(CondVal,
|
||||
getOperandValue(I.getOperand(i), SF), ElTy).BoolVal) {
|
||||
if (executeICMP_EQ(CondVal,
|
||||
getOperandValue(I.getOperand(i), SF), ElTy).BoolVal) {
|
||||
Dest = cast<BasicBlock>(I.getOperand(i+1));
|
||||
break;
|
||||
}
|
||||
|
@ -136,6 +136,8 @@ public:
|
||||
void visitSwitchInst(SwitchInst &I);
|
||||
|
||||
void visitBinaryOperator(BinaryOperator &I);
|
||||
void visitICmpInst(ICmpInst &I);
|
||||
void visitFCmpInst(FCmpInst &I);
|
||||
void visitAllocationInst(AllocationInst &I);
|
||||
void visitFreeInst(FreeInst &I);
|
||||
void visitLoadInst(LoadInst &I);
|
||||
|
@ -24,56 +24,43 @@
|
||||
#include "llvm/Support/ConstantRange.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/Instruction.h"
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/Type.h"
|
||||
#include "llvm/Support/Streams.h"
|
||||
#include <ostream>
|
||||
using namespace llvm;
|
||||
|
||||
static ConstantIntegral *getMaxValue(const Type *Ty) {
|
||||
switch (Ty->getTypeID()) {
|
||||
case Type::BoolTyID: return ConstantBool::getTrue();
|
||||
case Type::SByteTyID:
|
||||
case Type::ShortTyID:
|
||||
case Type::IntTyID:
|
||||
case Type::LongTyID: {
|
||||
// Calculate 011111111111111...
|
||||
unsigned TypeBits = Ty->getPrimitiveSize()*8;
|
||||
int64_t Val = INT64_MAX; // All ones
|
||||
Val >>= 64-TypeBits; // Shift out unwanted 1 bits...
|
||||
return ConstantInt::get(Ty, Val);
|
||||
}
|
||||
|
||||
case Type::UByteTyID:
|
||||
case Type::UShortTyID:
|
||||
case Type::UIntTyID:
|
||||
case Type::ULongTyID: return ConstantInt::getAllOnesValue(Ty);
|
||||
|
||||
default: return 0;
|
||||
static ConstantIntegral *getMaxValue(const Type *Ty, bool isSigned = false) {
|
||||
if (Ty == Type::BoolTy)
|
||||
return ConstantBool::getTrue();
|
||||
if (Ty->isInteger()) {
|
||||
if (isSigned) {
|
||||
// Calculate 011111111111111...
|
||||
unsigned TypeBits = Ty->getPrimitiveSize()*8;
|
||||
int64_t Val = INT64_MAX; // All ones
|
||||
Val >>= 64-TypeBits; // Shift out unwanted 1 bits...
|
||||
return ConstantInt::get(Ty, Val);
|
||||
}
|
||||
return ConstantInt::getAllOnesValue(Ty);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Static constructor to create the minimum constant for an integral type...
|
||||
static ConstantIntegral *getMinValue(const Type *Ty) {
|
||||
switch (Ty->getTypeID()) {
|
||||
case Type::BoolTyID: return ConstantBool::getFalse();
|
||||
case Type::SByteTyID:
|
||||
case Type::ShortTyID:
|
||||
case Type::IntTyID:
|
||||
case Type::LongTyID: {
|
||||
// Calculate 1111111111000000000000
|
||||
unsigned TypeBits = Ty->getPrimitiveSize()*8;
|
||||
int64_t Val = -1; // All ones
|
||||
Val <<= TypeBits-1; // Shift over to the right spot
|
||||
return ConstantInt::get(Ty, Val);
|
||||
}
|
||||
|
||||
case Type::UByteTyID:
|
||||
case Type::UShortTyID:
|
||||
case Type::UIntTyID:
|
||||
case Type::ULongTyID: return ConstantInt::get(Ty, 0);
|
||||
|
||||
default: return 0;
|
||||
static ConstantIntegral *getMinValue(const Type *Ty, bool isSigned = false) {
|
||||
if (Ty == Type::BoolTy)
|
||||
return ConstantBool::getFalse();
|
||||
if (Ty->isInteger()) {
|
||||
if (isSigned) {
|
||||
// Calculate 1111111111000000000000
|
||||
unsigned TypeBits = Ty->getPrimitiveSize()*8;
|
||||
int64_t Val = -1; // All ones
|
||||
Val <<= TypeBits-1; // Shift over to the right spot
|
||||
return ConstantInt::get(Ty, Val);
|
||||
}
|
||||
return ConstantInt::get(Ty, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static ConstantIntegral *Next(ConstantIntegral *CI) {
|
||||
if (ConstantBool *CB = dyn_cast<ConstantBool>(CI))
|
||||
@ -84,25 +71,30 @@ static ConstantIntegral *Next(ConstantIntegral *CI) {
|
||||
return cast<ConstantIntegral>(Result);
|
||||
}
|
||||
|
||||
static bool LT(ConstantIntegral *A, ConstantIntegral *B) {
|
||||
Constant *C = ConstantExpr::getSetLT(A, B);
|
||||
static bool LT(ConstantIntegral *A, ConstantIntegral *B, bool isSigned) {
|
||||
Constant *C = ConstantExpr::getICmp(
|
||||
(isSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT), A, B);
|
||||
assert(isa<ConstantBool>(C) && "Constant folding of integrals not impl??");
|
||||
return cast<ConstantBool>(C)->getValue();
|
||||
}
|
||||
|
||||
static bool LTE(ConstantIntegral *A, ConstantIntegral *B) {
|
||||
Constant *C = ConstantExpr::getSetLE(A, B);
|
||||
static bool LTE(ConstantIntegral *A, ConstantIntegral *B, bool isSigned) {
|
||||
Constant *C = ConstantExpr::getICmp(
|
||||
(isSigned ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE), A, B);
|
||||
assert(isa<ConstantBool>(C) && "Constant folding of integrals not impl??");
|
||||
return cast<ConstantBool>(C)->getValue();
|
||||
}
|
||||
|
||||
static bool GT(ConstantIntegral *A, ConstantIntegral *B) { return LT(B, A); }
|
||||
static bool GT(ConstantIntegral *A, ConstantIntegral *B, bool isSigned) {
|
||||
return LT(B, A, isSigned); }
|
||||
|
||||
static ConstantIntegral *Min(ConstantIntegral *A, ConstantIntegral *B) {
|
||||
return LT(A, B) ? A : B;
|
||||
static ConstantIntegral *Min(ConstantIntegral *A, ConstantIntegral *B,
|
||||
bool isSigned) {
|
||||
return LT(A, B, isSigned) ? A : B;
|
||||
}
|
||||
static ConstantIntegral *Max(ConstantIntegral *A, ConstantIntegral *B) {
|
||||
return GT(A, B) ? A : B;
|
||||
static ConstantIntegral *Max(ConstantIntegral *A, ConstantIntegral *B,
|
||||
bool isSigned) {
|
||||
return GT(A, B, isSigned) ? A : B;
|
||||
}
|
||||
|
||||
/// Initialize a full (the default) or empty set for the specified type.
|
||||
@ -118,47 +110,62 @@ ConstantRange::ConstantRange(const Type *Ty, bool Full) {
|
||||
|
||||
/// Initialize a range to hold the single specified value.
|
||||
///
|
||||
ConstantRange::ConstantRange(Constant *V)
|
||||
: Lower(cast<ConstantIntegral>(V)), Upper(Next(cast<ConstantIntegral>(V))) {
|
||||
}
|
||||
ConstantRange::ConstantRange(Constant *V)
|
||||
: Lower(cast<ConstantIntegral>(V)), Upper(Next(cast<ConstantIntegral>(V))) { }
|
||||
|
||||
/// Initialize a range of values explicitly... this will assert out if
|
||||
/// Lower==Upper and Lower != Min or Max for its type (or if the two constants
|
||||
/// have different types)
|
||||
///
|
||||
ConstantRange::ConstantRange(Constant *L, Constant *U)
|
||||
ConstantRange::ConstantRange(Constant *L, Constant *U)
|
||||
: Lower(cast<ConstantIntegral>(L)), Upper(cast<ConstantIntegral>(U)) {
|
||||
assert(Lower->getType() == Upper->getType() &&
|
||||
"Incompatible types for ConstantRange!");
|
||||
|
||||
// Make sure that if L & U are equal that they are either Min or Max...
|
||||
assert((L != U || (L == getMaxValue(L->getType()) ||
|
||||
L == getMinValue(L->getType()))) &&
|
||||
"Lower == Upper, but they aren't min or max for type!");
|
||||
L == getMinValue(L->getType())))
|
||||
&& "Lower == Upper, but they aren't min or max for type!");
|
||||
}
|
||||
|
||||
/// Initialize a set of values that all satisfy the condition with C.
|
||||
///
|
||||
ConstantRange::ConstantRange(unsigned SetCCOpcode, ConstantIntegral *C) {
|
||||
switch (SetCCOpcode) {
|
||||
default: assert(0 && "Invalid SetCC opcode to ConstantRange ctor!");
|
||||
case Instruction::SetEQ: Lower = C; Upper = Next(C); return;
|
||||
case Instruction::SetNE: Upper = C; Lower = Next(C); return;
|
||||
case Instruction::SetLT:
|
||||
ConstantRange::ConstantRange(unsigned short ICmpOpcode, ConstantIntegral *C) {
|
||||
switch (ICmpOpcode) {
|
||||
default: assert(0 && "Invalid ICmp opcode to ConstantRange ctor!");
|
||||
case ICmpInst::ICMP_EQ: Lower = C; Upper = Next(C); return;
|
||||
case ICmpInst::ICMP_NE: Upper = C; Lower = Next(C); return;
|
||||
case ICmpInst::ICMP_ULT:
|
||||
Lower = getMinValue(C->getType());
|
||||
Upper = C;
|
||||
return;
|
||||
case Instruction::SetGT:
|
||||
Lower = Next(C);
|
||||
Upper = getMinValue(C->getType()); // Min = Next(Max)
|
||||
case ICmpInst::ICMP_SLT:
|
||||
Lower = getMinValue(C->getType(), true);
|
||||
Upper = C;
|
||||
return;
|
||||
case Instruction::SetLE:
|
||||
case ICmpInst::ICMP_UGT:
|
||||
Lower = Next(C);
|
||||
Upper = getMinValue(C->getType()); // Min = Next(Max)
|
||||
return;
|
||||
case ICmpInst::ICMP_SGT:
|
||||
Lower = Next(C);
|
||||
Upper = getMinValue(C->getType(), true); // Min = Next(Max)
|
||||
return;
|
||||
case ICmpInst::ICMP_ULE:
|
||||
Lower = getMinValue(C->getType());
|
||||
Upper = Next(C);
|
||||
return;
|
||||
case Instruction::SetGE:
|
||||
case ICmpInst::ICMP_SLE:
|
||||
Lower = getMinValue(C->getType(), true);
|
||||
Upper = Next(C);
|
||||
return;
|
||||
case ICmpInst::ICMP_UGE:
|
||||
Lower = C;
|
||||
Upper = getMinValue(C->getType()); // Min = Next(Max)
|
||||
Upper = getMinValue(C->getType()); // Min = Next(Max)
|
||||
return;
|
||||
case ICmpInst::ICMP_SGE:
|
||||
Lower = C;
|
||||
Upper = getMinValue(C->getType(), true); // Min = Next(Max)
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -182,11 +189,10 @@ bool ConstantRange::isEmptySet() const {
|
||||
/// isWrappedSet - Return true if this set wraps around the top of the range,
|
||||
/// for example: [100, 8)
|
||||
///
|
||||
bool ConstantRange::isWrappedSet() const {
|
||||
return GT(Lower, Upper);
|
||||
bool ConstantRange::isWrappedSet(bool isSigned) const {
|
||||
return GT(Lower, Upper, isSigned);
|
||||
}
|
||||
|
||||
|
||||
/// getSingleElement - If this set contains a single element, return it,
|
||||
/// otherwise return null.
|
||||
ConstantIntegral *ConstantRange::getSingleElement() const {
|
||||
@ -212,19 +218,17 @@ uint64_t ConstantRange::getSetSize() const {
|
||||
|
||||
/// contains - Return true if the specified value is in the set.
|
||||
///
|
||||
bool ConstantRange::contains(ConstantInt *Val) const {
|
||||
bool ConstantRange::contains(ConstantInt *Val, bool isSigned) const {
|
||||
if (Lower == Upper) {
|
||||
if (isFullSet()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isWrappedSet())
|
||||
return LTE(Lower, Val) && LT(Val, Upper);
|
||||
return LTE(Lower, Val) || LT(Val, Upper);
|
||||
if (!isWrappedSet(isSigned))
|
||||
return LTE(Lower, Val, isSigned) && LT(Val, Upper, isSigned);
|
||||
return LTE(Lower, Val, isSigned) || LT(Val, Upper, isSigned);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// subtract - Subtract the specified constant from the endpoints of this
|
||||
/// constant range.
|
||||
ConstantRange ConstantRange::subtract(ConstantInt *CI) const {
|
||||
@ -241,15 +245,16 @@ ConstantRange ConstantRange::subtract(ConstantInt *CI) const {
|
||||
// it is known that LHS is wrapped and RHS isn't.
|
||||
//
|
||||
static ConstantRange intersect1Wrapped(const ConstantRange &LHS,
|
||||
const ConstantRange &RHS) {
|
||||
assert(LHS.isWrappedSet() && !RHS.isWrappedSet());
|
||||
const ConstantRange &RHS,
|
||||
bool isSigned) {
|
||||
assert(LHS.isWrappedSet(isSigned) && !RHS.isWrappedSet(isSigned));
|
||||
|
||||
// Check to see if we overlap on the Left side of RHS...
|
||||
//
|
||||
if (LT(RHS.getLower(), LHS.getUpper())) {
|
||||
if (LT(RHS.getLower(), LHS.getUpper(), isSigned)) {
|
||||
// We do overlap on the left side of RHS, see if we overlap on the right of
|
||||
// RHS...
|
||||
if (GT(RHS.getUpper(), LHS.getLower())) {
|
||||
if (GT(RHS.getUpper(), LHS.getLower(), isSigned)) {
|
||||
// Ok, the result overlaps on both the left and right sides. See if the
|
||||
// resultant interval will be smaller if we wrap or not...
|
||||
//
|
||||
@ -262,11 +267,10 @@ static ConstantRange intersect1Wrapped(const ConstantRange &LHS,
|
||||
// No overlap on the right, just on the left.
|
||||
return ConstantRange(RHS.getLower(), LHS.getUpper());
|
||||
}
|
||||
|
||||
} else {
|
||||
// We don't overlap on the left side of RHS, see if we overlap on the right
|
||||
// of RHS...
|
||||
if (GT(RHS.getUpper(), LHS.getLower())) {
|
||||
if (GT(RHS.getUpper(), LHS.getLower(), isSigned)) {
|
||||
// Simple overlap...
|
||||
return ConstantRange(LHS.getLower(), RHS.getUpper());
|
||||
} else {
|
||||
@ -279,30 +283,31 @@ static ConstantRange intersect1Wrapped(const ConstantRange &LHS,
|
||||
/// intersect - Return the range that results from the intersection of this
|
||||
/// range with another range.
|
||||
///
|
||||
ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
|
||||
ConstantRange ConstantRange::intersectWith(const ConstantRange &CR,
|
||||
bool isSigned) const {
|
||||
assert(getType() == CR.getType() && "ConstantRange types don't agree!");
|
||||
// Handle common special cases
|
||||
if (isEmptySet() || CR.isFullSet()) return *this;
|
||||
if (isFullSet() || CR.isEmptySet()) return CR;
|
||||
|
||||
if (!isWrappedSet()) {
|
||||
if (!CR.isWrappedSet()) {
|
||||
ConstantIntegral *L = Max(Lower, CR.Lower);
|
||||
ConstantIntegral *U = Min(Upper, CR.Upper);
|
||||
if (!isWrappedSet(isSigned)) {
|
||||
if (!CR.isWrappedSet(isSigned)) {
|
||||
ConstantIntegral *L = Max(Lower, CR.Lower, isSigned);
|
||||
ConstantIntegral *U = Min(Upper, CR.Upper, isSigned);
|
||||
|
||||
if (LT(L, U)) // If range isn't empty...
|
||||
if (LT(L, U, isSigned)) // If range isn't empty...
|
||||
return ConstantRange(L, U);
|
||||
else
|
||||
return ConstantRange(getType(), false); // Otherwise, return empty set
|
||||
} else
|
||||
return intersect1Wrapped(CR, *this);
|
||||
return intersect1Wrapped(CR, *this, isSigned);
|
||||
} else { // We know "this" is wrapped...
|
||||
if (!CR.isWrappedSet())
|
||||
return intersect1Wrapped(*this, CR);
|
||||
if (!CR.isWrappedSet(isSigned))
|
||||
return intersect1Wrapped(*this, CR, isSigned);
|
||||
else {
|
||||
// Both ranges are wrapped...
|
||||
ConstantIntegral *L = Max(Lower, CR.Lower);
|
||||
ConstantIntegral *U = Min(Upper, CR.Upper);
|
||||
ConstantIntegral *L = Max(Lower, CR.Lower, isSigned);
|
||||
ConstantIntegral *U = Min(Upper, CR.Upper, isSigned);
|
||||
return ConstantRange(L, U);
|
||||
}
|
||||
}
|
||||
@ -315,7 +320,8 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
|
||||
/// 15), which includes 9, 10, and 11, which were not included in either set
|
||||
/// before.
|
||||
///
|
||||
ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const {
|
||||
ConstantRange ConstantRange::unionWith(const ConstantRange &CR,
|
||||
bool isSigned) const {
|
||||
assert(getType() == CR.getType() && "ConstantRange types don't agree!");
|
||||
|
||||
assert(0 && "Range union not implemented yet!");
|
||||
@ -325,7 +331,7 @@ ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const {
|
||||
|
||||
/// zeroExtend - Return a new range in the specified integer type, which must
|
||||
/// be strictly larger than the current type. The returned range will
|
||||
/// correspond to the possible range of values if the source range had been
|
||||
/// correspond to the possible range of values as if the source range had been
|
||||
/// zero extended.
|
||||
ConstantRange ConstantRange::zeroExtend(const Type *Ty) const {
|
||||
assert(getLower()->getType()->getPrimitiveSize() < Ty->getPrimitiveSize() &&
|
||||
@ -346,7 +352,7 @@ ConstantRange ConstantRange::zeroExtend(const Type *Ty) const {
|
||||
|
||||
/// truncate - Return a new range in the specified integer type, which must be
|
||||
/// strictly smaller than the current type. The returned range will
|
||||
/// correspond to the possible range of values if the source range had been
|
||||
/// correspond to the possible range of values as if the source range had been
|
||||
/// truncated to the specified type.
|
||||
ConstantRange ConstantRange::truncate(const Type *Ty) const {
|
||||
assert(getLower()->getType()->getPrimitiveSize() > Ty->getPrimitiveSize() &&
|
||||
@ -360,7 +366,6 @@ ConstantRange ConstantRange::truncate(const Type *Ty) const {
|
||||
ConstantExpr::getTrunc(getUpper(), Ty));
|
||||
}
|
||||
|
||||
|
||||
/// print - Print out the bounds to a stream...
|
||||
///
|
||||
void ConstantRange::print(std::ostream &OS) const {
|
||||
|
@ -116,6 +116,9 @@ namespace {
|
||||
std::ostream &printType(std::ostream &Out, const Type *Ty,
|
||||
const std::string &VariableName = "",
|
||||
bool IgnoreName = false);
|
||||
std::ostream &printPrimitiveType(std::ostream &Out, const Type *Ty,
|
||||
bool isSigned,
|
||||
const std::string &NameSoFar = "");
|
||||
|
||||
void printStructReturnPointerFunctionType(std::ostream &Out,
|
||||
const PointerType *Ty);
|
||||
@ -124,6 +127,7 @@ namespace {
|
||||
void writeOperandRaw(Value *Operand);
|
||||
void writeOperandInternal(Value *Operand);
|
||||
void writeOperandWithCast(Value* Operand, unsigned Opcode);
|
||||
void writeOperandWithCast(Value* Operand, ICmpInst::Predicate predicate);
|
||||
bool writeInstructionCast(const Instruction &I);
|
||||
|
||||
private :
|
||||
@ -154,9 +158,10 @@ namespace {
|
||||
// printed and an extra copy of the expr is not emitted.
|
||||
//
|
||||
static bool isInlinableInst(const Instruction &I) {
|
||||
// Always inline setcc instructions, even if they are shared by multiple
|
||||
// Always inline cmp instructions, even if they are shared by multiple
|
||||
// expressions. GCC generates horrible code if we don't.
|
||||
if (isa<SetCondInst>(I)) return true;
|
||||
if (isa<CmpInst>(I))
|
||||
return true;
|
||||
|
||||
// Must be an expression, must be used exactly once. If it is dead, we
|
||||
// emit it inline where it would go.
|
||||
@ -211,6 +216,8 @@ namespace {
|
||||
|
||||
void visitPHINode(PHINode &I);
|
||||
void visitBinaryOperator(Instruction &I);
|
||||
void visitICmpInst(ICmpInst &I);
|
||||
void visitFCmpInst(FCmpInst &I);
|
||||
|
||||
void visitCastInst (CastInst &I);
|
||||
void visitSelectInst(SelectInst &I);
|
||||
@ -351,6 +358,32 @@ void CWriter::printStructReturnPointerFunctionType(std::ostream &Out,
|
||||
printType(Out, RetTy, tstr);
|
||||
}
|
||||
|
||||
std::ostream &
|
||||
CWriter::printPrimitiveType(std::ostream &Out, const Type *Ty, bool isSigned,
|
||||
const std::string &NameSoFar) {
|
||||
assert(Ty->isPrimitiveType() && "Invalid type for printPrimitiveType");
|
||||
switch (Ty->getTypeID()) {
|
||||
case Type::VoidTyID: return Out << "void " << NameSoFar;
|
||||
case Type::BoolTyID: return Out << "bool " << NameSoFar;
|
||||
case Type::UByteTyID:
|
||||
case Type::SByteTyID:
|
||||
return Out << (isSigned?"signed":"unsigned") << " char " << NameSoFar;
|
||||
case Type::UShortTyID:
|
||||
case Type::ShortTyID:
|
||||
return Out << (isSigned?"signed":"unsigned") << " short " << NameSoFar;
|
||||
case Type::UIntTyID:
|
||||
case Type::IntTyID:
|
||||
return Out << (isSigned?"signed":"unsigned") << " int " << NameSoFar;
|
||||
case Type::ULongTyID:
|
||||
case Type::LongTyID:
|
||||
return Out << (isSigned?"signed":"unsigned") << " long long " << NameSoFar;
|
||||
case Type::FloatTyID: return Out << "float " << NameSoFar;
|
||||
case Type::DoubleTyID: return Out << "double " << NameSoFar;
|
||||
default :
|
||||
cerr << "Unknown primitive type: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
// Pass the Type* and the variable name and this prints out the variable
|
||||
// declaration.
|
||||
@ -358,24 +391,13 @@ void CWriter::printStructReturnPointerFunctionType(std::ostream &Out,
|
||||
std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
|
||||
const std::string &NameSoFar,
|
||||
bool IgnoreName) {
|
||||
if (Ty->isPrimitiveType())
|
||||
switch (Ty->getTypeID()) {
|
||||
case Type::VoidTyID: return Out << "void " << NameSoFar;
|
||||
case Type::BoolTyID: return Out << "bool " << NameSoFar;
|
||||
case Type::UByteTyID: return Out << "unsigned char " << NameSoFar;
|
||||
case Type::SByteTyID: return Out << "signed char " << NameSoFar;
|
||||
case Type::UShortTyID: return Out << "unsigned short " << NameSoFar;
|
||||
case Type::ShortTyID: return Out << "short " << NameSoFar;
|
||||
case Type::UIntTyID: return Out << "unsigned " << NameSoFar;
|
||||
case Type::IntTyID: return Out << "int " << NameSoFar;
|
||||
case Type::ULongTyID: return Out << "unsigned long long " << NameSoFar;
|
||||
case Type::LongTyID: return Out << "signed long long " << NameSoFar;
|
||||
case Type::FloatTyID: return Out << "float " << NameSoFar;
|
||||
case Type::DoubleTyID: return Out << "double " << NameSoFar;
|
||||
default :
|
||||
cerr << "Unknown primitive type: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
if (Ty->isPrimitiveType()) {
|
||||
// FIXME:Signedness. When integer types are signless, this should just
|
||||
// always pass "false" for the sign of the primitive type. The instructions
|
||||
// will figure out how the value is to be interpreted.
|
||||
printPrimitiveType(Out, Ty, true, NameSoFar);
|
||||
return Out;
|
||||
}
|
||||
|
||||
// Check to see if the type is named.
|
||||
if (!IgnoreName || isa<OpaqueType>(Ty)) {
|
||||
@ -578,41 +600,66 @@ static bool isFPCSafeToPrint(const ConstantFP *CFP) {
|
||||
|
||||
/// Print out the casting for a cast operation. This does the double casting
|
||||
/// necessary for conversion to the destination type, if necessary.
|
||||
/// @returns true if a closing paren is necessary
|
||||
/// @brief Print a cast
|
||||
void CWriter::printCast(unsigned opc, const Type *SrcTy, const Type *DstTy) {
|
||||
Out << '(';
|
||||
printType(Out, DstTy);
|
||||
Out << ')';
|
||||
// Print the destination type cast
|
||||
switch (opc) {
|
||||
case Instruction::UIToFP:
|
||||
case Instruction::SIToFP:
|
||||
case Instruction::IntToPtr:
|
||||
case Instruction::Trunc:
|
||||
case Instruction::BitCast:
|
||||
case Instruction::FPExt:
|
||||
case Instruction::FPTrunc: // For these the DstTy sign doesn't matter
|
||||
Out << '(';
|
||||
printType(Out, DstTy);
|
||||
Out << ')';
|
||||
break;
|
||||
case Instruction::ZExt:
|
||||
case Instruction::PtrToInt:
|
||||
case Instruction::FPToUI: // For these, make sure we get an unsigned dest
|
||||
Out << '(';
|
||||
printPrimitiveType(Out, DstTy, false);
|
||||
Out << ')';
|
||||
break;
|
||||
case Instruction::SExt:
|
||||
case Instruction::FPToSI: // For these, make sure we get a signed dest
|
||||
Out << '(';
|
||||
printPrimitiveType(Out, DstTy, true);
|
||||
Out << ')';
|
||||
break;
|
||||
default:
|
||||
assert(0 && "Invalid cast opcode");
|
||||
}
|
||||
|
||||
// Print the source type cast
|
||||
switch (opc) {
|
||||
case Instruction::UIToFP:
|
||||
case Instruction::ZExt:
|
||||
if (SrcTy->isSigned()) {
|
||||
Out << '(';
|
||||
printType(Out, SrcTy->getUnsignedVersion());
|
||||
Out << ')';
|
||||
}
|
||||
Out << '(';
|
||||
printPrimitiveType(Out, SrcTy, false);
|
||||
Out << ')';
|
||||
break;
|
||||
case Instruction::SIToFP:
|
||||
case Instruction::SExt:
|
||||
if (SrcTy->isUnsigned()) {
|
||||
Out << '(';
|
||||
printType(Out, SrcTy->getSignedVersion());
|
||||
Out << ')';
|
||||
}
|
||||
Out << '(';
|
||||
printPrimitiveType(Out, SrcTy, true);
|
||||
Out << ')';
|
||||
break;
|
||||
case Instruction::IntToPtr:
|
||||
case Instruction::PtrToInt:
|
||||
// Avoid "cast to pointer from integer of different size" warnings
|
||||
Out << "(unsigned long)";
|
||||
break;
|
||||
// Avoid "cast to pointer from integer of different size" warnings
|
||||
Out << "(unsigned long)";
|
||||
break;
|
||||
case Instruction::Trunc:
|
||||
case Instruction::BitCast:
|
||||
case Instruction::FPExt:
|
||||
case Instruction::FPTrunc:
|
||||
case Instruction::FPToSI:
|
||||
case Instruction::FPToUI:
|
||||
break; // These don't need a source cast.
|
||||
default:
|
||||
assert(0 && "Invalid cast opcode");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -679,12 +726,8 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
case Instruction::And:
|
||||
case Instruction::Or:
|
||||
case Instruction::Xor:
|
||||
case Instruction::SetEQ:
|
||||
case Instruction::SetNE:
|
||||
case Instruction::SetLT:
|
||||
case Instruction::SetLE:
|
||||
case Instruction::SetGT:
|
||||
case Instruction::SetGE:
|
||||
case Instruction::ICmp:
|
||||
case Instruction::FCmp:
|
||||
case Instruction::Shl:
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr:
|
||||
@ -705,15 +748,43 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
case Instruction::And: Out << " & "; break;
|
||||
case Instruction::Or: Out << " | "; break;
|
||||
case Instruction::Xor: Out << " ^ "; break;
|
||||
case Instruction::SetEQ: Out << " == "; break;
|
||||
case Instruction::SetNE: Out << " != "; break;
|
||||
case Instruction::SetLT: Out << " < "; break;
|
||||
case Instruction::SetLE: Out << " <= "; break;
|
||||
case Instruction::SetGT: Out << " > "; break;
|
||||
case Instruction::SetGE: Out << " >= "; break;
|
||||
case Instruction::Shl: Out << " << "; break;
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr: Out << " >> "; break;
|
||||
case Instruction::ICmp:
|
||||
switch (CE->getPredicate()) {
|
||||
case ICmpInst::ICMP_EQ: Out << " == "; break;
|
||||
case ICmpInst::ICMP_NE: Out << " != "; break;
|
||||
case ICmpInst::ICMP_SLT:
|
||||
case ICmpInst::ICMP_ULT: Out << " < "; break;
|
||||
case ICmpInst::ICMP_SLE:
|
||||
case ICmpInst::ICMP_ULE: Out << " <= "; break;
|
||||
case ICmpInst::ICMP_SGT:
|
||||
case ICmpInst::ICMP_UGT: Out << " > "; break;
|
||||
case ICmpInst::ICMP_SGE:
|
||||
case ICmpInst::ICMP_UGE: Out << " >= "; break;
|
||||
default: assert(0 && "Illegal ICmp predicate");
|
||||
}
|
||||
break;
|
||||
case Instruction::FCmp:
|
||||
switch (CE->getPredicate()) {
|
||||
case FCmpInst::FCMP_ORD:
|
||||
case FCmpInst::FCMP_UEQ:
|
||||
case FCmpInst::FCMP_OEQ: Out << " == "; break;
|
||||
case FCmpInst::FCMP_UNO:
|
||||
case FCmpInst::FCMP_UNE:
|
||||
case FCmpInst::FCMP_ONE: Out << " != "; break;
|
||||
case FCmpInst::FCMP_OLT:
|
||||
case FCmpInst::FCMP_ULT: Out << " < "; break;
|
||||
case FCmpInst::FCMP_OLE:
|
||||
case FCmpInst::FCMP_ULE: Out << " <= "; break;
|
||||
case FCmpInst::FCMP_OGT:
|
||||
case FCmpInst::FCMP_UGT: Out << " > "; break;
|
||||
case FCmpInst::FCMP_OGE:
|
||||
case FCmpInst::FCMP_UGE: Out << " >= "; break;
|
||||
default: assert(0 && "Illegal FCmp predicate");
|
||||
}
|
||||
break;
|
||||
default: assert(0 && "Illegal opcode here!");
|
||||
}
|
||||
printConstantWithCast(CE->getOperand(1), CE->getOpcode());
|
||||
@ -730,7 +801,7 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
}
|
||||
} else if (isa<UndefValue>(CPV) && CPV->getType()->isFirstClassType()) {
|
||||
Out << "((";
|
||||
printType(Out, CPV->getType());
|
||||
printType(Out, CPV->getType()); // sign doesn't matter
|
||||
Out << ")/*UNDEF*/0)";
|
||||
return;
|
||||
}
|
||||
@ -740,9 +811,23 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
Out << (cast<ConstantBool>(CPV)->getValue() ? '1' : '0');
|
||||
break;
|
||||
case Type::SByteTyID:
|
||||
case Type::ShortTyID:
|
||||
Out << cast<ConstantInt>(CPV)->getSExtValue();
|
||||
case Type::UByteTyID:
|
||||
Out << "((char)" << cast<ConstantInt>(CPV)->getSExtValue() << ")";
|
||||
break;
|
||||
case Type::ShortTyID:
|
||||
case Type::UShortTyID:
|
||||
Out << "((short)" << cast<ConstantInt>(CPV)->getSExtValue() << ")";
|
||||
break;
|
||||
case Type::IntTyID:
|
||||
case Type::UIntTyID:
|
||||
Out << "((int)" << cast<ConstantInt>(CPV)->getSExtValue() << ")";
|
||||
break;
|
||||
case Type::LongTyID:
|
||||
case Type::ULongTyID:
|
||||
Out << "((long long)" << cast<ConstantInt>(CPV)->getSExtValue() << "ll)";
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case Type::IntTyID:
|
||||
if ((int)cast<ConstantInt>(CPV)->getSExtValue() == (int)0x80000000)
|
||||
Out << "((int)0x80000000U)"; // Handle MININT specially to avoid warning
|
||||
@ -767,6 +852,7 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
case Type::ULongTyID:
|
||||
Out << cast<ConstantInt>(CPV)->getZExtValue() << "ull";
|
||||
break;
|
||||
#endif
|
||||
|
||||
case Type::FloatTyID:
|
||||
case Type::DoubleTyID: {
|
||||
@ -890,7 +976,7 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
case Type::PointerTyID:
|
||||
if (isa<ConstantPointerNull>(CPV)) {
|
||||
Out << "((";
|
||||
printType(Out, CPV->getType());
|
||||
printType(Out, CPV->getType()); // sign doesn't matter
|
||||
Out << ")/*NULL*/0)";
|
||||
break;
|
||||
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(CPV)) {
|
||||
@ -910,17 +996,20 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
bool CWriter::printConstExprCast(const ConstantExpr* CE) {
|
||||
bool NeedsExplicitCast = false;
|
||||
const Type *Ty = CE->getOperand(0)->getType();
|
||||
bool TypeIsSigned = false;
|
||||
switch (CE->getOpcode()) {
|
||||
case Instruction::LShr:
|
||||
case Instruction::URem:
|
||||
case Instruction::UDiv:
|
||||
NeedsExplicitCast = Ty->isSigned(); break;
|
||||
case Instruction::UDiv: NeedsExplicitCast = true; break;
|
||||
case Instruction::AShr:
|
||||
case Instruction::SRem:
|
||||
case Instruction::SDiv:
|
||||
NeedsExplicitCast = Ty->isUnsigned(); break;
|
||||
case Instruction::ZExt:
|
||||
case Instruction::SDiv: NeedsExplicitCast = true; TypeIsSigned = true; break;
|
||||
case Instruction::SExt:
|
||||
Ty = CE->getType();
|
||||
NeedsExplicitCast = true;
|
||||
TypeIsSigned = true;
|
||||
break;
|
||||
case Instruction::ZExt:
|
||||
case Instruction::Trunc:
|
||||
case Instruction::FPTrunc:
|
||||
case Instruction::FPExt:
|
||||
@ -938,7 +1027,10 @@ bool CWriter::printConstExprCast(const ConstantExpr* CE) {
|
||||
}
|
||||
if (NeedsExplicitCast) {
|
||||
Out << "((";
|
||||
printType(Out, Ty);
|
||||
if (Ty->isPrimitiveType())
|
||||
printPrimitiveType(Out, Ty, TypeIsSigned);
|
||||
else
|
||||
printType(Out, Ty);
|
||||
Out << ")(";
|
||||
}
|
||||
return NeedsExplicitCast;
|
||||
@ -954,6 +1046,7 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
|
||||
|
||||
// Indicate whether to do the cast or not.
|
||||
bool shouldCast = false;
|
||||
bool typeIsSigned = false;
|
||||
|
||||
// Based on the Opcode for which this Constant is being written, determine
|
||||
// the new type to which the operand should be casted by setting the value
|
||||
@ -966,20 +1059,13 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
|
||||
case Instruction::LShr:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::URem:
|
||||
// For UDiv/URem get correct type
|
||||
if (OpTy->isSigned()) {
|
||||
OpTy = OpTy->getUnsignedVersion();
|
||||
shouldCast = true;
|
||||
}
|
||||
shouldCast = true;
|
||||
break;
|
||||
case Instruction::AShr:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::SRem:
|
||||
// For SDiv/SRem get correct type
|
||||
if (OpTy->isUnsigned()) {
|
||||
OpTy = OpTy->getSignedVersion();
|
||||
shouldCast = true;
|
||||
}
|
||||
shouldCast = true;
|
||||
typeIsSigned = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -987,13 +1073,12 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
|
||||
// operand.
|
||||
if (shouldCast) {
|
||||
Out << "((";
|
||||
printType(Out, OpTy);
|
||||
printPrimitiveType(Out, OpTy, typeIsSigned);
|
||||
Out << ")";
|
||||
printConstant(CPV);
|
||||
Out << ")";
|
||||
} else
|
||||
writeOperand(CPV);
|
||||
|
||||
printConstant(CPV);
|
||||
}
|
||||
|
||||
void CWriter::writeOperandInternal(Value *Operand) {
|
||||
@ -1038,40 +1123,25 @@ void CWriter::writeOperand(Value *Operand) {
|
||||
// This function takes care of detecting that case and printing the cast
|
||||
// for the Instruction.
|
||||
bool CWriter::writeInstructionCast(const Instruction &I) {
|
||||
bool NeedsExplicitCast = false;
|
||||
const Type *Ty = I.getOperand(0)->getType();
|
||||
switch (I.getOpcode()) {
|
||||
case Instruction::LShr:
|
||||
case Instruction::URem:
|
||||
case Instruction::UDiv:
|
||||
NeedsExplicitCast = Ty->isSigned(); break;
|
||||
Out << "((";
|
||||
printPrimitiveType(Out, Ty, false);
|
||||
Out << ")(";
|
||||
return true;
|
||||
case Instruction::AShr:
|
||||
case Instruction::SRem:
|
||||
case Instruction::SDiv:
|
||||
NeedsExplicitCast = Ty->isUnsigned(); break;
|
||||
case Instruction::ZExt:
|
||||
case Instruction::SExt:
|
||||
case Instruction::Trunc:
|
||||
case Instruction::FPTrunc:
|
||||
case Instruction::FPExt:
|
||||
case Instruction::UIToFP:
|
||||
case Instruction::SIToFP:
|
||||
case Instruction::FPToUI:
|
||||
case Instruction::FPToSI:
|
||||
case Instruction::PtrToInt:
|
||||
case Instruction::IntToPtr:
|
||||
case Instruction::BitCast:
|
||||
Ty = I.getType();
|
||||
NeedsExplicitCast = true;
|
||||
break;
|
||||
Out << "((";
|
||||
printPrimitiveType(Out, Ty, true);
|
||||
Out << ")(";
|
||||
return true;
|
||||
default: break;
|
||||
}
|
||||
if (NeedsExplicitCast) {
|
||||
Out << "((";
|
||||
printType(Out, Ty);
|
||||
Out << ")(";
|
||||
}
|
||||
return NeedsExplicitCast;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write the operand with a cast to another type based on the Opcode being used.
|
||||
@ -1085,6 +1155,9 @@ void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
|
||||
// Indicate whether to do the cast or not.
|
||||
bool shouldCast = false;
|
||||
|
||||
// Indicate whether the cast should be to a signed type or not.
|
||||
bool castIsSigned = false;
|
||||
|
||||
// Based on the Opcode for which this Operand is being written, determine
|
||||
// the new type to which the operand should be casted by setting the value
|
||||
// of OpTy. If we change OpTy, also set shouldCast to true.
|
||||
@ -1094,20 +1167,15 @@ void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
|
||||
break;
|
||||
case Instruction::LShr:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::URem:
|
||||
// For UDiv to have unsigned operands
|
||||
if (OpTy->isSigned()) {
|
||||
OpTy = OpTy->getUnsignedVersion();
|
||||
shouldCast = true;
|
||||
}
|
||||
case Instruction::URem: // Cast to unsigned first
|
||||
shouldCast = true;
|
||||
castIsSigned = false;
|
||||
break;
|
||||
case Instruction::AShr:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::SRem:
|
||||
if (OpTy->isUnsigned()) {
|
||||
OpTy = OpTy->getSignedVersion();
|
||||
shouldCast = true;
|
||||
}
|
||||
case Instruction::SRem: // Cast to signed first
|
||||
shouldCast = true;
|
||||
castIsSigned = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1115,13 +1183,62 @@ void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
|
||||
// operand.
|
||||
if (shouldCast) {
|
||||
Out << "((";
|
||||
printType(Out, OpTy);
|
||||
printPrimitiveType(Out, OpTy, castIsSigned);
|
||||
Out << ")";
|
||||
writeOperand(Operand);
|
||||
Out << ")";
|
||||
} else
|
||||
writeOperand(Operand);
|
||||
}
|
||||
|
||||
// Write the operand with a cast to another type based on the icmp predicate
|
||||
// being used.
|
||||
void CWriter::writeOperandWithCast(Value* Operand, ICmpInst::Predicate predicate) {
|
||||
|
||||
// Extract the operand's type, we'll need it.
|
||||
const Type* OpTy = Operand->getType();
|
||||
|
||||
// Indicate whether to do the cast or not.
|
||||
bool shouldCast = false;
|
||||
|
||||
// Indicate whether the cast should be to a signed type or not.
|
||||
bool castIsSigned = false;
|
||||
|
||||
// Based on the Opcode for which this Operand is being written, determine
|
||||
// the new type to which the operand should be casted by setting the value
|
||||
// of OpTy. If we change OpTy, also set shouldCast to true.
|
||||
switch (predicate) {
|
||||
default:
|
||||
// for eq and ne, it doesn't matter
|
||||
break;
|
||||
case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_UGE:
|
||||
case ICmpInst::ICMP_ULT:
|
||||
case ICmpInst::ICMP_ULE:
|
||||
shouldCast = true;
|
||||
break;
|
||||
case ICmpInst::ICMP_SGT:
|
||||
case ICmpInst::ICMP_SGE:
|
||||
case ICmpInst::ICMP_SLT:
|
||||
case ICmpInst::ICMP_SLE:
|
||||
shouldCast = true;
|
||||
castIsSigned = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Write out the casted operand if we should, otherwise just write the
|
||||
// operand.
|
||||
if (shouldCast) {
|
||||
Out << "((";
|
||||
if (OpTy->isPrimitiveType())
|
||||
printPrimitiveType(Out, OpTy, castIsSigned);
|
||||
else
|
||||
printType(Out, OpTy);
|
||||
Out << ")";
|
||||
writeOperand(Operand);
|
||||
Out << ")";
|
||||
} else
|
||||
writeOperand(Operand);
|
||||
}
|
||||
|
||||
// generateCompilerSpecificCode - This is where we add conditional compilation
|
||||
@ -1725,7 +1842,7 @@ void CWriter::printFunction(Function &F) {
|
||||
PrintedVar = true;
|
||||
}
|
||||
// We need a temporary for the BitCast to use so it can pluck a value out
|
||||
// of a uniont to do the BitCast. This is separate from the need for a
|
||||
// of a union to do the BitCast. This is separate from the need for a
|
||||
// variable to hold the result of the BitCast.
|
||||
if (isFPIntBitCast(*I)) {
|
||||
Out << " llvmBitCastUnion " << Mang->getValueName(&*I)
|
||||
@ -1992,12 +2109,6 @@ void CWriter::visitBinaryOperator(Instruction &I) {
|
||||
case Instruction::And: Out << " & "; break;
|
||||
case Instruction::Or: Out << " | "; break;
|
||||
case Instruction::Xor: Out << " ^ "; break;
|
||||
case Instruction::SetEQ: Out << " == "; break;
|
||||
case Instruction::SetNE: Out << " != "; break;
|
||||
case Instruction::SetLE: Out << " <= "; break;
|
||||
case Instruction::SetGE: Out << " >= "; break;
|
||||
case Instruction::SetLT: Out << " < "; break;
|
||||
case Instruction::SetGT: Out << " > "; break;
|
||||
case Instruction::Shl : Out << " << "; break;
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr: Out << " >> "; break;
|
||||
@ -2014,6 +2125,70 @@ void CWriter::visitBinaryOperator(Instruction &I) {
|
||||
}
|
||||
}
|
||||
|
||||
void CWriter::visitICmpInst(ICmpInst &I) {
|
||||
// We must cast the results of icmp which might be promoted.
|
||||
bool needsCast = false;
|
||||
|
||||
// Write out the cast of the instruction's value back to the proper type
|
||||
// if necessary.
|
||||
bool NeedsClosingParens = writeInstructionCast(I);
|
||||
|
||||
// Certain icmp predicate require the operand to be forced to a specific type
|
||||
// so we use writeOperandWithCast here instead of writeOperand. Similarly
|
||||
// below for operand 1
|
||||
writeOperandWithCast(I.getOperand(0), I.getPredicate());
|
||||
|
||||
switch (I.getPredicate()) {
|
||||
case ICmpInst::ICMP_EQ: Out << " == "; break;
|
||||
case ICmpInst::ICMP_NE: Out << " != "; break;
|
||||
case ICmpInst::ICMP_ULE:
|
||||
case ICmpInst::ICMP_SLE: Out << " <= "; break;
|
||||
case ICmpInst::ICMP_UGE:
|
||||
case ICmpInst::ICMP_SGE: Out << " >= "; break;
|
||||
case ICmpInst::ICMP_ULT:
|
||||
case ICmpInst::ICMP_SLT: Out << " < "; break;
|
||||
case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_SGT: Out << " > "; break;
|
||||
default: cerr << "Invalid icmp predicate!" << I; abort();
|
||||
}
|
||||
|
||||
writeOperandWithCast(I.getOperand(1), I.getPredicate());
|
||||
if (NeedsClosingParens)
|
||||
Out << "))";
|
||||
|
||||
if (needsCast) {
|
||||
Out << "))";
|
||||
}
|
||||
}
|
||||
|
||||
void CWriter::visitFCmpInst(FCmpInst &I) {
|
||||
// Write the first operand
|
||||
writeOperand(I.getOperand(0));
|
||||
|
||||
// Write the predicate
|
||||
switch (I.getPredicate()) {
|
||||
case FCmpInst::FCMP_FALSE: Out << " 0 "; break;
|
||||
case FCmpInst::FCMP_ORD:
|
||||
case FCmpInst::FCMP_OEQ:
|
||||
case FCmpInst::FCMP_UEQ: Out << " == "; break;
|
||||
case FCmpInst::FCMP_UNO:
|
||||
case FCmpInst::FCMP_ONE:
|
||||
case FCmpInst::FCMP_UNE: Out << " != "; break;
|
||||
case FCmpInst::FCMP_ULE:
|
||||
case FCmpInst::FCMP_OLE: Out << " <= "; break;
|
||||
case FCmpInst::FCMP_UGE:
|
||||
case FCmpInst::FCMP_OGE: Out << " >= "; break;
|
||||
case FCmpInst::FCMP_ULT:
|
||||
case FCmpInst::FCMP_OLT: Out << " < "; break;
|
||||
case FCmpInst::FCMP_UGT:
|
||||
case FCmpInst::FCMP_OGT: Out << " > "; break;
|
||||
case FCmpInst::FCMP_TRUE: Out << " 1 "; break;
|
||||
default: cerr << "Invalid fcmp predicate!" << I; abort();
|
||||
}
|
||||
// Write the second operand
|
||||
writeOperand(I.getOperand(1));
|
||||
}
|
||||
|
||||
static const char * getFloatBitCastField(const Type *Ty) {
|
||||
switch (Ty->getTypeID()) {
|
||||
default: assert(0 && "Invalid Type");
|
||||
|
@ -11,4 +11,4 @@ LEVEL = ../../..
|
||||
LIBRARYNAME = LLVMCBackend
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
||||
CompileCommonOpts := $(CompileCommonOpts) -Wno-format
|
||||
CompileCommonOpts += -Wno-format
|
||||
|
@ -116,6 +116,9 @@ namespace {
|
||||
std::ostream &printType(std::ostream &Out, const Type *Ty,
|
||||
const std::string &VariableName = "",
|
||||
bool IgnoreName = false);
|
||||
std::ostream &printPrimitiveType(std::ostream &Out, const Type *Ty,
|
||||
bool isSigned,
|
||||
const std::string &NameSoFar = "");
|
||||
|
||||
void printStructReturnPointerFunctionType(std::ostream &Out,
|
||||
const PointerType *Ty);
|
||||
@ -124,6 +127,7 @@ namespace {
|
||||
void writeOperandRaw(Value *Operand);
|
||||
void writeOperandInternal(Value *Operand);
|
||||
void writeOperandWithCast(Value* Operand, unsigned Opcode);
|
||||
void writeOperandWithCast(Value* Operand, ICmpInst::Predicate predicate);
|
||||
bool writeInstructionCast(const Instruction &I);
|
||||
|
||||
private :
|
||||
@ -154,9 +158,10 @@ namespace {
|
||||
// printed and an extra copy of the expr is not emitted.
|
||||
//
|
||||
static bool isInlinableInst(const Instruction &I) {
|
||||
// Always inline setcc instructions, even if they are shared by multiple
|
||||
// Always inline cmp instructions, even if they are shared by multiple
|
||||
// expressions. GCC generates horrible code if we don't.
|
||||
if (isa<SetCondInst>(I)) return true;
|
||||
if (isa<CmpInst>(I))
|
||||
return true;
|
||||
|
||||
// Must be an expression, must be used exactly once. If it is dead, we
|
||||
// emit it inline where it would go.
|
||||
@ -211,6 +216,8 @@ namespace {
|
||||
|
||||
void visitPHINode(PHINode &I);
|
||||
void visitBinaryOperator(Instruction &I);
|
||||
void visitICmpInst(ICmpInst &I);
|
||||
void visitFCmpInst(FCmpInst &I);
|
||||
|
||||
void visitCastInst (CastInst &I);
|
||||
void visitSelectInst(SelectInst &I);
|
||||
@ -351,6 +358,32 @@ void CWriter::printStructReturnPointerFunctionType(std::ostream &Out,
|
||||
printType(Out, RetTy, tstr);
|
||||
}
|
||||
|
||||
std::ostream &
|
||||
CWriter::printPrimitiveType(std::ostream &Out, const Type *Ty, bool isSigned,
|
||||
const std::string &NameSoFar) {
|
||||
assert(Ty->isPrimitiveType() && "Invalid type for printPrimitiveType");
|
||||
switch (Ty->getTypeID()) {
|
||||
case Type::VoidTyID: return Out << "void " << NameSoFar;
|
||||
case Type::BoolTyID: return Out << "bool " << NameSoFar;
|
||||
case Type::UByteTyID:
|
||||
case Type::SByteTyID:
|
||||
return Out << (isSigned?"signed":"unsigned") << " char " << NameSoFar;
|
||||
case Type::UShortTyID:
|
||||
case Type::ShortTyID:
|
||||
return Out << (isSigned?"signed":"unsigned") << " short " << NameSoFar;
|
||||
case Type::UIntTyID:
|
||||
case Type::IntTyID:
|
||||
return Out << (isSigned?"signed":"unsigned") << " int " << NameSoFar;
|
||||
case Type::ULongTyID:
|
||||
case Type::LongTyID:
|
||||
return Out << (isSigned?"signed":"unsigned") << " long long " << NameSoFar;
|
||||
case Type::FloatTyID: return Out << "float " << NameSoFar;
|
||||
case Type::DoubleTyID: return Out << "double " << NameSoFar;
|
||||
default :
|
||||
cerr << "Unknown primitive type: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
// Pass the Type* and the variable name and this prints out the variable
|
||||
// declaration.
|
||||
@ -358,24 +391,13 @@ void CWriter::printStructReturnPointerFunctionType(std::ostream &Out,
|
||||
std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
|
||||
const std::string &NameSoFar,
|
||||
bool IgnoreName) {
|
||||
if (Ty->isPrimitiveType())
|
||||
switch (Ty->getTypeID()) {
|
||||
case Type::VoidTyID: return Out << "void " << NameSoFar;
|
||||
case Type::BoolTyID: return Out << "bool " << NameSoFar;
|
||||
case Type::UByteTyID: return Out << "unsigned char " << NameSoFar;
|
||||
case Type::SByteTyID: return Out << "signed char " << NameSoFar;
|
||||
case Type::UShortTyID: return Out << "unsigned short " << NameSoFar;
|
||||
case Type::ShortTyID: return Out << "short " << NameSoFar;
|
||||
case Type::UIntTyID: return Out << "unsigned " << NameSoFar;
|
||||
case Type::IntTyID: return Out << "int " << NameSoFar;
|
||||
case Type::ULongTyID: return Out << "unsigned long long " << NameSoFar;
|
||||
case Type::LongTyID: return Out << "signed long long " << NameSoFar;
|
||||
case Type::FloatTyID: return Out << "float " << NameSoFar;
|
||||
case Type::DoubleTyID: return Out << "double " << NameSoFar;
|
||||
default :
|
||||
cerr << "Unknown primitive type: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
if (Ty->isPrimitiveType()) {
|
||||
// FIXME:Signedness. When integer types are signless, this should just
|
||||
// always pass "false" for the sign of the primitive type. The instructions
|
||||
// will figure out how the value is to be interpreted.
|
||||
printPrimitiveType(Out, Ty, true, NameSoFar);
|
||||
return Out;
|
||||
}
|
||||
|
||||
// Check to see if the type is named.
|
||||
if (!IgnoreName || isa<OpaqueType>(Ty)) {
|
||||
@ -578,41 +600,66 @@ static bool isFPCSafeToPrint(const ConstantFP *CFP) {
|
||||
|
||||
/// Print out the casting for a cast operation. This does the double casting
|
||||
/// necessary for conversion to the destination type, if necessary.
|
||||
/// @returns true if a closing paren is necessary
|
||||
/// @brief Print a cast
|
||||
void CWriter::printCast(unsigned opc, const Type *SrcTy, const Type *DstTy) {
|
||||
Out << '(';
|
||||
printType(Out, DstTy);
|
||||
Out << ')';
|
||||
// Print the destination type cast
|
||||
switch (opc) {
|
||||
case Instruction::UIToFP:
|
||||
case Instruction::SIToFP:
|
||||
case Instruction::IntToPtr:
|
||||
case Instruction::Trunc:
|
||||
case Instruction::BitCast:
|
||||
case Instruction::FPExt:
|
||||
case Instruction::FPTrunc: // For these the DstTy sign doesn't matter
|
||||
Out << '(';
|
||||
printType(Out, DstTy);
|
||||
Out << ')';
|
||||
break;
|
||||
case Instruction::ZExt:
|
||||
case Instruction::PtrToInt:
|
||||
case Instruction::FPToUI: // For these, make sure we get an unsigned dest
|
||||
Out << '(';
|
||||
printPrimitiveType(Out, DstTy, false);
|
||||
Out << ')';
|
||||
break;
|
||||
case Instruction::SExt:
|
||||
case Instruction::FPToSI: // For these, make sure we get a signed dest
|
||||
Out << '(';
|
||||
printPrimitiveType(Out, DstTy, true);
|
||||
Out << ')';
|
||||
break;
|
||||
default:
|
||||
assert(0 && "Invalid cast opcode");
|
||||
}
|
||||
|
||||
// Print the source type cast
|
||||
switch (opc) {
|
||||
case Instruction::UIToFP:
|
||||
case Instruction::ZExt:
|
||||
if (SrcTy->isSigned()) {
|
||||
Out << '(';
|
||||
printType(Out, SrcTy->getUnsignedVersion());
|
||||
Out << ')';
|
||||
}
|
||||
Out << '(';
|
||||
printPrimitiveType(Out, SrcTy, false);
|
||||
Out << ')';
|
||||
break;
|
||||
case Instruction::SIToFP:
|
||||
case Instruction::SExt:
|
||||
if (SrcTy->isUnsigned()) {
|
||||
Out << '(';
|
||||
printType(Out, SrcTy->getSignedVersion());
|
||||
Out << ')';
|
||||
}
|
||||
Out << '(';
|
||||
printPrimitiveType(Out, SrcTy, true);
|
||||
Out << ')';
|
||||
break;
|
||||
case Instruction::IntToPtr:
|
||||
case Instruction::PtrToInt:
|
||||
// Avoid "cast to pointer from integer of different size" warnings
|
||||
Out << "(unsigned long)";
|
||||
break;
|
||||
// Avoid "cast to pointer from integer of different size" warnings
|
||||
Out << "(unsigned long)";
|
||||
break;
|
||||
case Instruction::Trunc:
|
||||
case Instruction::BitCast:
|
||||
case Instruction::FPExt:
|
||||
case Instruction::FPTrunc:
|
||||
case Instruction::FPToSI:
|
||||
case Instruction::FPToUI:
|
||||
break; // These don't need a source cast.
|
||||
default:
|
||||
assert(0 && "Invalid cast opcode");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -679,12 +726,8 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
case Instruction::And:
|
||||
case Instruction::Or:
|
||||
case Instruction::Xor:
|
||||
case Instruction::SetEQ:
|
||||
case Instruction::SetNE:
|
||||
case Instruction::SetLT:
|
||||
case Instruction::SetLE:
|
||||
case Instruction::SetGT:
|
||||
case Instruction::SetGE:
|
||||
case Instruction::ICmp:
|
||||
case Instruction::FCmp:
|
||||
case Instruction::Shl:
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr:
|
||||
@ -705,15 +748,43 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
case Instruction::And: Out << " & "; break;
|
||||
case Instruction::Or: Out << " | "; break;
|
||||
case Instruction::Xor: Out << " ^ "; break;
|
||||
case Instruction::SetEQ: Out << " == "; break;
|
||||
case Instruction::SetNE: Out << " != "; break;
|
||||
case Instruction::SetLT: Out << " < "; break;
|
||||
case Instruction::SetLE: Out << " <= "; break;
|
||||
case Instruction::SetGT: Out << " > "; break;
|
||||
case Instruction::SetGE: Out << " >= "; break;
|
||||
case Instruction::Shl: Out << " << "; break;
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr: Out << " >> "; break;
|
||||
case Instruction::ICmp:
|
||||
switch (CE->getPredicate()) {
|
||||
case ICmpInst::ICMP_EQ: Out << " == "; break;
|
||||
case ICmpInst::ICMP_NE: Out << " != "; break;
|
||||
case ICmpInst::ICMP_SLT:
|
||||
case ICmpInst::ICMP_ULT: Out << " < "; break;
|
||||
case ICmpInst::ICMP_SLE:
|
||||
case ICmpInst::ICMP_ULE: Out << " <= "; break;
|
||||
case ICmpInst::ICMP_SGT:
|
||||
case ICmpInst::ICMP_UGT: Out << " > "; break;
|
||||
case ICmpInst::ICMP_SGE:
|
||||
case ICmpInst::ICMP_UGE: Out << " >= "; break;
|
||||
default: assert(0 && "Illegal ICmp predicate");
|
||||
}
|
||||
break;
|
||||
case Instruction::FCmp:
|
||||
switch (CE->getPredicate()) {
|
||||
case FCmpInst::FCMP_ORD:
|
||||
case FCmpInst::FCMP_UEQ:
|
||||
case FCmpInst::FCMP_OEQ: Out << " == "; break;
|
||||
case FCmpInst::FCMP_UNO:
|
||||
case FCmpInst::FCMP_UNE:
|
||||
case FCmpInst::FCMP_ONE: Out << " != "; break;
|
||||
case FCmpInst::FCMP_OLT:
|
||||
case FCmpInst::FCMP_ULT: Out << " < "; break;
|
||||
case FCmpInst::FCMP_OLE:
|
||||
case FCmpInst::FCMP_ULE: Out << " <= "; break;
|
||||
case FCmpInst::FCMP_OGT:
|
||||
case FCmpInst::FCMP_UGT: Out << " > "; break;
|
||||
case FCmpInst::FCMP_OGE:
|
||||
case FCmpInst::FCMP_UGE: Out << " >= "; break;
|
||||
default: assert(0 && "Illegal FCmp predicate");
|
||||
}
|
||||
break;
|
||||
default: assert(0 && "Illegal opcode here!");
|
||||
}
|
||||
printConstantWithCast(CE->getOperand(1), CE->getOpcode());
|
||||
@ -730,7 +801,7 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
}
|
||||
} else if (isa<UndefValue>(CPV) && CPV->getType()->isFirstClassType()) {
|
||||
Out << "((";
|
||||
printType(Out, CPV->getType());
|
||||
printType(Out, CPV->getType()); // sign doesn't matter
|
||||
Out << ")/*UNDEF*/0)";
|
||||
return;
|
||||
}
|
||||
@ -740,9 +811,23 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
Out << (cast<ConstantBool>(CPV)->getValue() ? '1' : '0');
|
||||
break;
|
||||
case Type::SByteTyID:
|
||||
case Type::ShortTyID:
|
||||
Out << cast<ConstantInt>(CPV)->getSExtValue();
|
||||
case Type::UByteTyID:
|
||||
Out << "((char)" << cast<ConstantInt>(CPV)->getSExtValue() << ")";
|
||||
break;
|
||||
case Type::ShortTyID:
|
||||
case Type::UShortTyID:
|
||||
Out << "((short)" << cast<ConstantInt>(CPV)->getSExtValue() << ")";
|
||||
break;
|
||||
case Type::IntTyID:
|
||||
case Type::UIntTyID:
|
||||
Out << "((int)" << cast<ConstantInt>(CPV)->getSExtValue() << ")";
|
||||
break;
|
||||
case Type::LongTyID:
|
||||
case Type::ULongTyID:
|
||||
Out << "((long long)" << cast<ConstantInt>(CPV)->getSExtValue() << "ll)";
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case Type::IntTyID:
|
||||
if ((int)cast<ConstantInt>(CPV)->getSExtValue() == (int)0x80000000)
|
||||
Out << "((int)0x80000000U)"; // Handle MININT specially to avoid warning
|
||||
@ -767,6 +852,7 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
case Type::ULongTyID:
|
||||
Out << cast<ConstantInt>(CPV)->getZExtValue() << "ull";
|
||||
break;
|
||||
#endif
|
||||
|
||||
case Type::FloatTyID:
|
||||
case Type::DoubleTyID: {
|
||||
@ -890,7 +976,7 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
case Type::PointerTyID:
|
||||
if (isa<ConstantPointerNull>(CPV)) {
|
||||
Out << "((";
|
||||
printType(Out, CPV->getType());
|
||||
printType(Out, CPV->getType()); // sign doesn't matter
|
||||
Out << ")/*NULL*/0)";
|
||||
break;
|
||||
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(CPV)) {
|
||||
@ -910,17 +996,20 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
bool CWriter::printConstExprCast(const ConstantExpr* CE) {
|
||||
bool NeedsExplicitCast = false;
|
||||
const Type *Ty = CE->getOperand(0)->getType();
|
||||
bool TypeIsSigned = false;
|
||||
switch (CE->getOpcode()) {
|
||||
case Instruction::LShr:
|
||||
case Instruction::URem:
|
||||
case Instruction::UDiv:
|
||||
NeedsExplicitCast = Ty->isSigned(); break;
|
||||
case Instruction::UDiv: NeedsExplicitCast = true; break;
|
||||
case Instruction::AShr:
|
||||
case Instruction::SRem:
|
||||
case Instruction::SDiv:
|
||||
NeedsExplicitCast = Ty->isUnsigned(); break;
|
||||
case Instruction::ZExt:
|
||||
case Instruction::SDiv: NeedsExplicitCast = true; TypeIsSigned = true; break;
|
||||
case Instruction::SExt:
|
||||
Ty = CE->getType();
|
||||
NeedsExplicitCast = true;
|
||||
TypeIsSigned = true;
|
||||
break;
|
||||
case Instruction::ZExt:
|
||||
case Instruction::Trunc:
|
||||
case Instruction::FPTrunc:
|
||||
case Instruction::FPExt:
|
||||
@ -938,7 +1027,10 @@ bool CWriter::printConstExprCast(const ConstantExpr* CE) {
|
||||
}
|
||||
if (NeedsExplicitCast) {
|
||||
Out << "((";
|
||||
printType(Out, Ty);
|
||||
if (Ty->isPrimitiveType())
|
||||
printPrimitiveType(Out, Ty, TypeIsSigned);
|
||||
else
|
||||
printType(Out, Ty);
|
||||
Out << ")(";
|
||||
}
|
||||
return NeedsExplicitCast;
|
||||
@ -954,6 +1046,7 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
|
||||
|
||||
// Indicate whether to do the cast or not.
|
||||
bool shouldCast = false;
|
||||
bool typeIsSigned = false;
|
||||
|
||||
// Based on the Opcode for which this Constant is being written, determine
|
||||
// the new type to which the operand should be casted by setting the value
|
||||
@ -966,20 +1059,13 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
|
||||
case Instruction::LShr:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::URem:
|
||||
// For UDiv/URem get correct type
|
||||
if (OpTy->isSigned()) {
|
||||
OpTy = OpTy->getUnsignedVersion();
|
||||
shouldCast = true;
|
||||
}
|
||||
shouldCast = true;
|
||||
break;
|
||||
case Instruction::AShr:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::SRem:
|
||||
// For SDiv/SRem get correct type
|
||||
if (OpTy->isUnsigned()) {
|
||||
OpTy = OpTy->getSignedVersion();
|
||||
shouldCast = true;
|
||||
}
|
||||
shouldCast = true;
|
||||
typeIsSigned = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -987,13 +1073,12 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
|
||||
// operand.
|
||||
if (shouldCast) {
|
||||
Out << "((";
|
||||
printType(Out, OpTy);
|
||||
printPrimitiveType(Out, OpTy, typeIsSigned);
|
||||
Out << ")";
|
||||
printConstant(CPV);
|
||||
Out << ")";
|
||||
} else
|
||||
writeOperand(CPV);
|
||||
|
||||
printConstant(CPV);
|
||||
}
|
||||
|
||||
void CWriter::writeOperandInternal(Value *Operand) {
|
||||
@ -1038,40 +1123,25 @@ void CWriter::writeOperand(Value *Operand) {
|
||||
// This function takes care of detecting that case and printing the cast
|
||||
// for the Instruction.
|
||||
bool CWriter::writeInstructionCast(const Instruction &I) {
|
||||
bool NeedsExplicitCast = false;
|
||||
const Type *Ty = I.getOperand(0)->getType();
|
||||
switch (I.getOpcode()) {
|
||||
case Instruction::LShr:
|
||||
case Instruction::URem:
|
||||
case Instruction::UDiv:
|
||||
NeedsExplicitCast = Ty->isSigned(); break;
|
||||
Out << "((";
|
||||
printPrimitiveType(Out, Ty, false);
|
||||
Out << ")(";
|
||||
return true;
|
||||
case Instruction::AShr:
|
||||
case Instruction::SRem:
|
||||
case Instruction::SDiv:
|
||||
NeedsExplicitCast = Ty->isUnsigned(); break;
|
||||
case Instruction::ZExt:
|
||||
case Instruction::SExt:
|
||||
case Instruction::Trunc:
|
||||
case Instruction::FPTrunc:
|
||||
case Instruction::FPExt:
|
||||
case Instruction::UIToFP:
|
||||
case Instruction::SIToFP:
|
||||
case Instruction::FPToUI:
|
||||
case Instruction::FPToSI:
|
||||
case Instruction::PtrToInt:
|
||||
case Instruction::IntToPtr:
|
||||
case Instruction::BitCast:
|
||||
Ty = I.getType();
|
||||
NeedsExplicitCast = true;
|
||||
break;
|
||||
Out << "((";
|
||||
printPrimitiveType(Out, Ty, true);
|
||||
Out << ")(";
|
||||
return true;
|
||||
default: break;
|
||||
}
|
||||
if (NeedsExplicitCast) {
|
||||
Out << "((";
|
||||
printType(Out, Ty);
|
||||
Out << ")(";
|
||||
}
|
||||
return NeedsExplicitCast;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write the operand with a cast to another type based on the Opcode being used.
|
||||
@ -1085,6 +1155,9 @@ void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
|
||||
// Indicate whether to do the cast or not.
|
||||
bool shouldCast = false;
|
||||
|
||||
// Indicate whether the cast should be to a signed type or not.
|
||||
bool castIsSigned = false;
|
||||
|
||||
// Based on the Opcode for which this Operand is being written, determine
|
||||
// the new type to which the operand should be casted by setting the value
|
||||
// of OpTy. If we change OpTy, also set shouldCast to true.
|
||||
@ -1094,20 +1167,15 @@ void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
|
||||
break;
|
||||
case Instruction::LShr:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::URem:
|
||||
// For UDiv to have unsigned operands
|
||||
if (OpTy->isSigned()) {
|
||||
OpTy = OpTy->getUnsignedVersion();
|
||||
shouldCast = true;
|
||||
}
|
||||
case Instruction::URem: // Cast to unsigned first
|
||||
shouldCast = true;
|
||||
castIsSigned = false;
|
||||
break;
|
||||
case Instruction::AShr:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::SRem:
|
||||
if (OpTy->isUnsigned()) {
|
||||
OpTy = OpTy->getSignedVersion();
|
||||
shouldCast = true;
|
||||
}
|
||||
case Instruction::SRem: // Cast to signed first
|
||||
shouldCast = true;
|
||||
castIsSigned = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1115,13 +1183,62 @@ void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
|
||||
// operand.
|
||||
if (shouldCast) {
|
||||
Out << "((";
|
||||
printType(Out, OpTy);
|
||||
printPrimitiveType(Out, OpTy, castIsSigned);
|
||||
Out << ")";
|
||||
writeOperand(Operand);
|
||||
Out << ")";
|
||||
} else
|
||||
writeOperand(Operand);
|
||||
}
|
||||
|
||||
// Write the operand with a cast to another type based on the icmp predicate
|
||||
// being used.
|
||||
void CWriter::writeOperandWithCast(Value* Operand, ICmpInst::Predicate predicate) {
|
||||
|
||||
// Extract the operand's type, we'll need it.
|
||||
const Type* OpTy = Operand->getType();
|
||||
|
||||
// Indicate whether to do the cast or not.
|
||||
bool shouldCast = false;
|
||||
|
||||
// Indicate whether the cast should be to a signed type or not.
|
||||
bool castIsSigned = false;
|
||||
|
||||
// Based on the Opcode for which this Operand is being written, determine
|
||||
// the new type to which the operand should be casted by setting the value
|
||||
// of OpTy. If we change OpTy, also set shouldCast to true.
|
||||
switch (predicate) {
|
||||
default:
|
||||
// for eq and ne, it doesn't matter
|
||||
break;
|
||||
case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_UGE:
|
||||
case ICmpInst::ICMP_ULT:
|
||||
case ICmpInst::ICMP_ULE:
|
||||
shouldCast = true;
|
||||
break;
|
||||
case ICmpInst::ICMP_SGT:
|
||||
case ICmpInst::ICMP_SGE:
|
||||
case ICmpInst::ICMP_SLT:
|
||||
case ICmpInst::ICMP_SLE:
|
||||
shouldCast = true;
|
||||
castIsSigned = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Write out the casted operand if we should, otherwise just write the
|
||||
// operand.
|
||||
if (shouldCast) {
|
||||
Out << "((";
|
||||
if (OpTy->isPrimitiveType())
|
||||
printPrimitiveType(Out, OpTy, castIsSigned);
|
||||
else
|
||||
printType(Out, OpTy);
|
||||
Out << ")";
|
||||
writeOperand(Operand);
|
||||
Out << ")";
|
||||
} else
|
||||
writeOperand(Operand);
|
||||
}
|
||||
|
||||
// generateCompilerSpecificCode - This is where we add conditional compilation
|
||||
@ -1725,7 +1842,7 @@ void CWriter::printFunction(Function &F) {
|
||||
PrintedVar = true;
|
||||
}
|
||||
// We need a temporary for the BitCast to use so it can pluck a value out
|
||||
// of a uniont to do the BitCast. This is separate from the need for a
|
||||
// of a union to do the BitCast. This is separate from the need for a
|
||||
// variable to hold the result of the BitCast.
|
||||
if (isFPIntBitCast(*I)) {
|
||||
Out << " llvmBitCastUnion " << Mang->getValueName(&*I)
|
||||
@ -1992,12 +2109,6 @@ void CWriter::visitBinaryOperator(Instruction &I) {
|
||||
case Instruction::And: Out << " & "; break;
|
||||
case Instruction::Or: Out << " | "; break;
|
||||
case Instruction::Xor: Out << " ^ "; break;
|
||||
case Instruction::SetEQ: Out << " == "; break;
|
||||
case Instruction::SetNE: Out << " != "; break;
|
||||
case Instruction::SetLE: Out << " <= "; break;
|
||||
case Instruction::SetGE: Out << " >= "; break;
|
||||
case Instruction::SetLT: Out << " < "; break;
|
||||
case Instruction::SetGT: Out << " > "; break;
|
||||
case Instruction::Shl : Out << " << "; break;
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr: Out << " >> "; break;
|
||||
@ -2014,6 +2125,70 @@ void CWriter::visitBinaryOperator(Instruction &I) {
|
||||
}
|
||||
}
|
||||
|
||||
void CWriter::visitICmpInst(ICmpInst &I) {
|
||||
// We must cast the results of icmp which might be promoted.
|
||||
bool needsCast = false;
|
||||
|
||||
// Write out the cast of the instruction's value back to the proper type
|
||||
// if necessary.
|
||||
bool NeedsClosingParens = writeInstructionCast(I);
|
||||
|
||||
// Certain icmp predicate require the operand to be forced to a specific type
|
||||
// so we use writeOperandWithCast here instead of writeOperand. Similarly
|
||||
// below for operand 1
|
||||
writeOperandWithCast(I.getOperand(0), I.getPredicate());
|
||||
|
||||
switch (I.getPredicate()) {
|
||||
case ICmpInst::ICMP_EQ: Out << " == "; break;
|
||||
case ICmpInst::ICMP_NE: Out << " != "; break;
|
||||
case ICmpInst::ICMP_ULE:
|
||||
case ICmpInst::ICMP_SLE: Out << " <= "; break;
|
||||
case ICmpInst::ICMP_UGE:
|
||||
case ICmpInst::ICMP_SGE: Out << " >= "; break;
|
||||
case ICmpInst::ICMP_ULT:
|
||||
case ICmpInst::ICMP_SLT: Out << " < "; break;
|
||||
case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_SGT: Out << " > "; break;
|
||||
default: cerr << "Invalid icmp predicate!" << I; abort();
|
||||
}
|
||||
|
||||
writeOperandWithCast(I.getOperand(1), I.getPredicate());
|
||||
if (NeedsClosingParens)
|
||||
Out << "))";
|
||||
|
||||
if (needsCast) {
|
||||
Out << "))";
|
||||
}
|
||||
}
|
||||
|
||||
void CWriter::visitFCmpInst(FCmpInst &I) {
|
||||
// Write the first operand
|
||||
writeOperand(I.getOperand(0));
|
||||
|
||||
// Write the predicate
|
||||
switch (I.getPredicate()) {
|
||||
case FCmpInst::FCMP_FALSE: Out << " 0 "; break;
|
||||
case FCmpInst::FCMP_ORD:
|
||||
case FCmpInst::FCMP_OEQ:
|
||||
case FCmpInst::FCMP_UEQ: Out << " == "; break;
|
||||
case FCmpInst::FCMP_UNO:
|
||||
case FCmpInst::FCMP_ONE:
|
||||
case FCmpInst::FCMP_UNE: Out << " != "; break;
|
||||
case FCmpInst::FCMP_ULE:
|
||||
case FCmpInst::FCMP_OLE: Out << " <= "; break;
|
||||
case FCmpInst::FCMP_UGE:
|
||||
case FCmpInst::FCMP_OGE: Out << " >= "; break;
|
||||
case FCmpInst::FCMP_ULT:
|
||||
case FCmpInst::FCMP_OLT: Out << " < "; break;
|
||||
case FCmpInst::FCMP_UGT:
|
||||
case FCmpInst::FCMP_OGT: Out << " > "; break;
|
||||
case FCmpInst::FCMP_TRUE: Out << " 1 "; break;
|
||||
default: cerr << "Invalid fcmp predicate!" << I; abort();
|
||||
}
|
||||
// Write the second operand
|
||||
writeOperand(I.getOperand(1));
|
||||
}
|
||||
|
||||
static const char * getFloatBitCastField(const Type *Ty) {
|
||||
switch (Ty->getTypeID()) {
|
||||
default: assert(0 && "Invalid Type");
|
||||
|
@ -324,7 +324,7 @@ unsigned short read_16_be(const unsigned char *adr) {
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
-instcombine should handle this transform:
|
||||
setcc (sdiv X / C1 ), C2
|
||||
icmp pred (sdiv X / C1 ), C2
|
||||
when X, C1, and C2 are unsigned. Similarly for udiv and signed operands.
|
||||
|
||||
Currently InstCombine avoids this transform but will do it when the signs of
|
||||
|
@ -463,10 +463,13 @@ static bool OperandConvertibleToType(User *U, Value *V, const Type *Ty,
|
||||
return ValueConvertibleToType(I, Ty, CTMap, TD) &&
|
||||
ExpressionConvertibleToType(OtherOp, Ty, CTMap, TD);
|
||||
}
|
||||
case Instruction::SetEQ:
|
||||
case Instruction::SetNE: {
|
||||
Value *OtherOp = I->getOperand((V == I->getOperand(0)) ? 1 : 0);
|
||||
return ExpressionConvertibleToType(OtherOp, Ty, CTMap, TD);
|
||||
case Instruction::ICmp: {
|
||||
if (cast<ICmpInst>(I)->getPredicate() == ICmpInst::ICMP_EQ ||
|
||||
cast<ICmpInst>(I)->getPredicate() == ICmpInst::ICMP_NE) {
|
||||
Value *OtherOp = I->getOperand((V == I->getOperand(0)) ? 1 : 0);
|
||||
return ExpressionConvertibleToType(OtherOp, Ty, CTMap, TD);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr:
|
||||
@ -717,9 +720,7 @@ static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
|
||||
}
|
||||
|
||||
case Instruction::Add:
|
||||
case Instruction::Sub:
|
||||
case Instruction::SetEQ:
|
||||
case Instruction::SetNE: {
|
||||
case Instruction::Sub: {
|
||||
Res = BinaryOperator::create(cast<BinaryOperator>(I)->getOpcode(),
|
||||
Dummy, Dummy, Name);
|
||||
VMC.ExprMap[I] = Res; // Add node to expression eagerly
|
||||
@ -731,6 +732,19 @@ static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
|
||||
Res->setOperand(OtherIdx, NewOther);
|
||||
break;
|
||||
}
|
||||
case Instruction::ICmp: {
|
||||
ICmpInst::Predicate pred = cast<ICmpInst>(I)->getPredicate();
|
||||
if (pred == ICmpInst::ICMP_EQ || pred == ICmpInst::ICMP_NE) {
|
||||
Res = new ICmpInst(pred, Dummy, Dummy, Name);
|
||||
VMC.ExprMap[I] = Res; // Add node to expression eagerly
|
||||
unsigned OtherIdx = (OldVal == I->getOperand(0)) ? 1 : 0;
|
||||
Value *OtherOp = I->getOperand(OtherIdx);
|
||||
Res->setOperand(!OtherIdx, NewVal);
|
||||
Value *NewOther = ConvertExpressionToType(OtherOp, NewTy, VMC, TD);
|
||||
Res->setOperand(OtherIdx, NewOther);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Instruction::Shl:
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr:
|
||||
|
@ -238,7 +238,7 @@ static bool AnalyzeGlobal(Value *V, GlobalStatus &GS,
|
||||
if (AnalyzeGlobal(I, GS, PHIUsers)) return true;
|
||||
GS.isNotSuitableForSRA = true;
|
||||
GS.HasPHIUser = true;
|
||||
} else if (isa<SetCondInst>(I)) {
|
||||
} else if (isa<CmpInst>(I)) {
|
||||
GS.isNotSuitableForSRA = true;
|
||||
} else if (isa<MemCpyInst>(I) || isa<MemMoveInst>(I)) {
|
||||
if (I->getOperand(1) == V)
|
||||
@ -507,7 +507,7 @@ static bool AllUsesOfValueWillTrapIfNull(Value *V) {
|
||||
if (!AllUsesOfValueWillTrapIfNull(CI)) return false;
|
||||
} else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(*UI)) {
|
||||
if (!AllUsesOfValueWillTrapIfNull(GEPI)) return false;
|
||||
} else if (isa<SetCondInst>(*UI) &&
|
||||
} else if (isa<ICmpInst>(*UI) &&
|
||||
isa<ConstantPointerNull>(UI->getOperand(1))) {
|
||||
// Ignore setcc X, null
|
||||
} else {
|
||||
@ -720,29 +720,33 @@ static GlobalVariable *OptimizeGlobalAddressOfMalloc(GlobalVariable *GV,
|
||||
if (LoadInst *LI = dyn_cast<LoadInst>(GV->use_back())) {
|
||||
while (!LI->use_empty()) {
|
||||
Use &LoadUse = LI->use_begin().getUse();
|
||||
if (!isa<SetCondInst>(LoadUse.getUser()))
|
||||
if (!isa<ICmpInst>(LoadUse.getUser()))
|
||||
LoadUse = RepValue;
|
||||
else {
|
||||
// Replace the setcc X, 0 with a use of the bool value.
|
||||
SetCondInst *SCI = cast<SetCondInst>(LoadUse.getUser());
|
||||
Value *LV = new LoadInst(InitBool, InitBool->getName()+".val", SCI);
|
||||
ICmpInst *CI = cast<ICmpInst>(LoadUse.getUser());
|
||||
// Replace the cmp X, 0 with a use of the bool value.
|
||||
Value *LV = new LoadInst(InitBool, InitBool->getName()+".val", CI);
|
||||
InitBoolUsed = true;
|
||||
switch (SCI->getOpcode()) {
|
||||
default: assert(0 && "Unknown opcode!");
|
||||
case Instruction::SetLT:
|
||||
switch (CI->getPredicate()) {
|
||||
default: assert(0 && "Unknown ICmp Predicate!");
|
||||
case ICmpInst::ICMP_ULT:
|
||||
case ICmpInst::ICMP_SLT:
|
||||
LV = ConstantBool::getFalse(); // X < null -> always false
|
||||
break;
|
||||
case Instruction::SetEQ:
|
||||
case Instruction::SetLE:
|
||||
LV = BinaryOperator::createNot(LV, "notinit", SCI);
|
||||
case ICmpInst::ICMP_ULE:
|
||||
case ICmpInst::ICMP_SLE:
|
||||
case ICmpInst::ICMP_EQ:
|
||||
LV = BinaryOperator::createNot(LV, "notinit", CI);
|
||||
break;
|
||||
case Instruction::SetNE:
|
||||
case Instruction::SetGE:
|
||||
case Instruction::SetGT:
|
||||
case ICmpInst::ICMP_NE:
|
||||
case ICmpInst::ICMP_UGE:
|
||||
case ICmpInst::ICMP_SGE:
|
||||
case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_SGT:
|
||||
break; // no change.
|
||||
}
|
||||
SCI->replaceAllUsesWith(LV);
|
||||
SCI->eraseFromParent();
|
||||
CI->replaceAllUsesWith(LV);
|
||||
CI->eraseFromParent();
|
||||
}
|
||||
}
|
||||
LI->eraseFromParent();
|
||||
@ -783,7 +787,7 @@ static GlobalVariable *OptimizeGlobalAddressOfMalloc(GlobalVariable *GV,
|
||||
static bool ValueIsOnlyUsedLocallyOrStoredToOneGlobal(Instruction *V,
|
||||
GlobalVariable *GV) {
|
||||
for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI)
|
||||
if (isa<LoadInst>(*UI) || isa<SetCondInst>(*UI)) {
|
||||
if (isa<LoadInst>(*UI) || isa<CmpInst>(*UI)) {
|
||||
// Fine, ignore.
|
||||
} else if (StoreInst *SI = dyn_cast<StoreInst>(*UI)) {
|
||||
if (SI->getOperand(0) == V && SI->getOperand(1) != GV)
|
||||
@ -832,8 +836,8 @@ static bool GlobalLoadUsesSimpleEnoughForHeapSRA(GlobalVariable *GV) {
|
||||
for (Value::use_iterator UI = LI->use_begin(), E = LI->use_end(); UI != E;
|
||||
++UI) {
|
||||
// Comparison against null is ok.
|
||||
if (SetCondInst *SCI = dyn_cast<SetCondInst>(*UI)) {
|
||||
if (!isa<ConstantPointerNull>(SCI->getOperand(1)))
|
||||
if (ICmpInst *ICI = dyn_cast<ICmpInst>(*UI)) {
|
||||
if (!isa<ConstantPointerNull>(ICI->getOperand(1)))
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
@ -865,7 +869,7 @@ static void RewriteUsesOfLoadForHeapSRoA(LoadInst *Ptr,
|
||||
Instruction *User = Ptr->use_back();
|
||||
|
||||
// If this is a comparison against null, handle it.
|
||||
if (SetCondInst *SCI = dyn_cast<SetCondInst>(User)) {
|
||||
if (ICmpInst *SCI = dyn_cast<ICmpInst>(User)) {
|
||||
assert(isa<ConstantPointerNull>(SCI->getOperand(1)));
|
||||
// If we have a setcc of the loaded pointer, we can use a setcc of any
|
||||
// field.
|
||||
@ -877,9 +881,9 @@ static void RewriteUsesOfLoadForHeapSRoA(LoadInst *Ptr,
|
||||
NPtr = InsertedLoadsForPtr.back();
|
||||
}
|
||||
|
||||
Value *New = new SetCondInst(SCI->getOpcode(), NPtr,
|
||||
Constant::getNullValue(NPtr->getType()),
|
||||
SCI->getName(), SCI);
|
||||
Value *New = new ICmpInst(SCI->getPredicate(), NPtr,
|
||||
Constant::getNullValue(NPtr->getType()),
|
||||
SCI->getName(), SCI);
|
||||
SCI->replaceAllUsesWith(New);
|
||||
SCI->eraseFromParent();
|
||||
continue;
|
||||
@ -959,7 +963,7 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, MallocInst *MI){
|
||||
// }
|
||||
Value *RunningOr = 0;
|
||||
for (unsigned i = 0, e = FieldMallocs.size(); i != e; ++i) {
|
||||
Value *Cond = new SetCondInst(Instruction::SetEQ, FieldMallocs[i],
|
||||
Value *Cond = new ICmpInst(ICmpInst::ICMP_EQ, FieldMallocs[i],
|
||||
Constant::getNullValue(FieldMallocs[i]->getType()),
|
||||
"isnull", MI);
|
||||
if (!RunningOr)
|
||||
@ -986,9 +990,9 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, MallocInst *MI){
|
||||
// pointer, because some may be null while others are not.
|
||||
for (unsigned i = 0, e = FieldGlobals.size(); i != e; ++i) {
|
||||
Value *GVVal = new LoadInst(FieldGlobals[i], "tmp", NullPtrBlock);
|
||||
Value *Cmp = new SetCondInst(Instruction::SetNE, GVVal,
|
||||
Constant::getNullValue(GVVal->getType()),
|
||||
"tmp", NullPtrBlock);
|
||||
Value *Cmp = new ICmpInst(ICmpInst::ICMP_NE, GVVal,
|
||||
Constant::getNullValue(GVVal->getType()),
|
||||
"tmp", NullPtrBlock);
|
||||
BasicBlock *FreeBlock = new BasicBlock("free_it", OrigBB->getParent());
|
||||
BasicBlock *NextBlock = new BasicBlock("next", OrigBB->getParent());
|
||||
new BranchInst(FreeBlock, NextBlock, Cmp, NullPtrBlock);
|
||||
@ -1710,6 +1714,10 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal,
|
||||
InstResult = ConstantExpr::get(SI->getOpcode(),
|
||||
getVal(Values, SI->getOperand(0)),
|
||||
getVal(Values, SI->getOperand(1)));
|
||||
} else if (CmpInst *CI = dyn_cast<CmpInst>(CurInst)) {
|
||||
InstResult = ConstantExpr::getCompare(CI->getPredicate(),
|
||||
getVal(Values, CI->getOperand(0)),
|
||||
getVal(Values, CI->getOperand(1)));
|
||||
} else if (CastInst *CI = dyn_cast<CastInst>(CurInst)) {
|
||||
InstResult = ConstantExpr::getCast(CI->getOpcode(),
|
||||
getVal(Values, CI->getOperand(0)),
|
||||
|
@ -887,8 +887,8 @@ struct StrLenOptimization : public LibCallOptimization {
|
||||
|
||||
// Does the call to strlen have exactly one use?
|
||||
if (ci->hasOneUse())
|
||||
// Is that single use a binary operator?
|
||||
if (BinaryOperator* bop = dyn_cast<BinaryOperator>(ci->use_back()))
|
||||
// Is that single use a icmp operator?
|
||||
if (ICmpInst* bop = dyn_cast<ICmpInst>(ci->use_back()))
|
||||
// Is it compared against a constant integer?
|
||||
if (ConstantInt* CI = dyn_cast<ConstantInt>(bop->getOperand(1)))
|
||||
{
|
||||
@ -897,15 +897,15 @@ struct StrLenOptimization : public LibCallOptimization {
|
||||
|
||||
// If its compared against length 0 with == or !=
|
||||
if (val == 0 &&
|
||||
(bop->getOpcode() == Instruction::SetEQ ||
|
||||
bop->getOpcode() == Instruction::SetNE))
|
||||
(bop->getPredicate() == ICmpInst::ICMP_EQ ||
|
||||
bop->getPredicate() == ICmpInst::ICMP_NE))
|
||||
{
|
||||
// strlen(x) != 0 -> *x != 0
|
||||
// strlen(x) == 0 -> *x == 0
|
||||
LoadInst* load = new LoadInst(str,str->getName()+".first",ci);
|
||||
BinaryOperator* rbop = BinaryOperator::create(bop->getOpcode(),
|
||||
load, ConstantInt::get(Type::SByteTy,0),
|
||||
bop->getName()+".strlen", ci);
|
||||
ICmpInst* rbop = new ICmpInst(bop->getPredicate(), load,
|
||||
ConstantInt::get(Type::SByteTy,0),
|
||||
bop->getName()+".strlen", ci);
|
||||
bop->replaceAllUsesWith(rbop);
|
||||
bop->eraseFromParent();
|
||||
ci->eraseFromParent();
|
||||
@ -933,10 +933,11 @@ static bool IsOnlyUsedInEqualsZeroComparison(Instruction *I) {
|
||||
for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
|
||||
UI != E; ++UI) {
|
||||
Instruction *User = cast<Instruction>(*UI);
|
||||
if (User->getOpcode() == Instruction::SetNE ||
|
||||
User->getOpcode() == Instruction::SetEQ) {
|
||||
if (isa<Constant>(User->getOperand(1)) &&
|
||||
cast<Constant>(User->getOperand(1))->isNullValue())
|
||||
if (ICmpInst *IC = dyn_cast<ICmpInst>(User)) {
|
||||
if ((IC->getPredicate() == ICmpInst::ICMP_NE ||
|
||||
IC->getPredicate() == ICmpInst::ICMP_EQ) &&
|
||||
isa<Constant>(IC->getOperand(1)) &&
|
||||
cast<Constant>(IC->getOperand(1))->isNullValue())
|
||||
continue;
|
||||
} else if (CastInst *CI = dyn_cast<CastInst>(User))
|
||||
if (CI->getType() == Type::BoolTy)
|
||||
@ -1739,7 +1740,7 @@ public:
|
||||
BinaryOperator* sub_inst = BinaryOperator::createSub(cast,
|
||||
ConstantInt::get(Type::UIntTy,0x30),
|
||||
ci->getOperand(1)->getName()+".sub",ci);
|
||||
SetCondInst* setcond_inst = new SetCondInst(Instruction::SetLE,sub_inst,
|
||||
ICmpInst* setcond_inst = new ICmpInst(ICmpInst::ICMP_ULE,sub_inst,
|
||||
ConstantInt::get(Type::UIntTy,9),
|
||||
ci->getOperand(1)->getName()+".cmp",ci);
|
||||
CastInst* c2 = new ZExtInst(setcond_inst, Type::IntTy,
|
||||
@ -1764,12 +1765,9 @@ public:
|
||||
virtual bool OptimizeCall(CallInst *CI, SimplifyLibCalls &SLC) {
|
||||
// isascii(c) -> (unsigned)c < 128
|
||||
Value *V = CI->getOperand(1);
|
||||
if (V->getType()->isSigned())
|
||||
V = new BitCastInst(V, V->getType()->getUnsignedVersion(), V->getName(),
|
||||
CI);
|
||||
Value *Cmp = BinaryOperator::createSetLT(V, ConstantInt::get(V->getType(),
|
||||
128),
|
||||
V->getName()+".isascii", CI);
|
||||
Value *Cmp = new ICmpInst(ICmpInst::ICMP_ULT, V,
|
||||
ConstantInt::get(V->getType(), 128),
|
||||
V->getName()+".isascii", CI);
|
||||
if (Cmp->getType() != CI->getType())
|
||||
Cmp = new BitCastInst(Cmp, CI->getType(), Cmp->getName(), CI);
|
||||
CI->replaceAllUsesWith(Cmp);
|
||||
@ -1872,9 +1870,9 @@ public:
|
||||
"tmp", TheCall);
|
||||
V2 = BinaryOperator::createAdd(V2, ConstantInt::get(Type::IntTy, 1),
|
||||
"tmp", TheCall);
|
||||
Value *Cond =
|
||||
BinaryOperator::createSetEQ(V, Constant::getNullValue(V->getType()),
|
||||
"tmp", TheCall);
|
||||
Value *Cond = new ICmpInst(ICmpInst::ICMP_EQ, V,
|
||||
Constant::getNullValue(V->getType()), "tmp",
|
||||
TheCall);
|
||||
V2 = new SelectInst(Cond, ConstantInt::get(Type::IntTy, 0), V2,
|
||||
TheCall->getName(), TheCall);
|
||||
TheCall->replaceAllUsesWith(V2);
|
||||
|
@ -197,9 +197,9 @@ void GlobalRandomCounter::ProcessChoicePoint(BasicBlock* bb) {
|
||||
//decrement counter
|
||||
LoadInst* l = new LoadInst(Counter, "counter", t);
|
||||
|
||||
SetCondInst* s = new SetCondInst(Instruction::SetEQ, l,
|
||||
ConstantInt::get(T, 0),
|
||||
"countercc", t);
|
||||
ICmpInst* s = new ICmpInst(ICmpInst::ICMP_EQ, l, ConstantInt::get(T, 0),
|
||||
"countercc", t);
|
||||
|
||||
Value* nv = BinaryOperator::createSub(l, ConstantInt::get(T, 1),
|
||||
"counternew", t);
|
||||
new StoreInst(nv, Counter, t);
|
||||
@ -270,9 +270,9 @@ void GlobalRandomCounterOpt::ProcessChoicePoint(BasicBlock* bb) {
|
||||
//decrement counter
|
||||
LoadInst* l = new LoadInst(AI, "counter", t);
|
||||
|
||||
SetCondInst* s = new SetCondInst(Instruction::SetEQ, l,
|
||||
ConstantInt::get(T, 0),
|
||||
"countercc", t);
|
||||
ICmpInst* s = new ICmpInst(ICmpInst::ICMP_EQ, l, ConstantInt::get(T, 0),
|
||||
"countercc", t);
|
||||
|
||||
Value* nv = BinaryOperator::createSub(l, ConstantInt::get(T, 1),
|
||||
"counternew", t);
|
||||
new StoreInst(nv, AI, t);
|
||||
@ -305,9 +305,10 @@ void CycleCounter::ProcessChoicePoint(BasicBlock* bb) {
|
||||
BinaryOperator::createAnd(c, ConstantInt::get(Type::ULongTy, rm),
|
||||
"mrdcc", t);
|
||||
|
||||
SetCondInst* s = new SetCondInst(Instruction::SetEQ, b,
|
||||
ConstantInt::get(Type::ULongTy, 0),
|
||||
"mrdccc", t);
|
||||
ICmpInst *s = new ICmpInst(ICmpInst::ICMP_EQ, b,
|
||||
ConstantInt::get(Type::ULongTy, 0),
|
||||
"mrdccc", t);
|
||||
|
||||
t->setCondition(s);
|
||||
}
|
||||
|
||||
|
@ -393,9 +393,6 @@ bool RPR::PeepholeOptimize(BasicBlock *BB, BasicBlock::iterator &BI) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool RPR::DoRaisePass(Function &F) {
|
||||
bool Changed = false;
|
||||
for (Function::iterator BB = F.begin(), BBE = F.end(); BB != BBE; ++BB)
|
||||
|
@ -45,36 +45,36 @@
|
||||
#include <algorithm>
|
||||
using namespace llvm;
|
||||
|
||||
STATISTIC(NumSetCCRemoved, "Number of setcc instruction eliminated");
|
||||
STATISTIC(NumCmpRemoved, "Number of cmp instruction eliminated");
|
||||
STATISTIC(NumOperandsCann, "Number of operands canonicalized");
|
||||
STATISTIC(BranchRevectors, "Number of branches revectored");
|
||||
|
||||
namespace {
|
||||
class ValueInfo;
|
||||
class Relation {
|
||||
Value *Val; // Relation to what value?
|
||||
Instruction::BinaryOps Rel; // SetCC relation, or Add if no information
|
||||
Value *Val; // Relation to what value?
|
||||
unsigned Rel; // SetCC or ICmp relation, or Add if no information
|
||||
public:
|
||||
Relation(Value *V) : Val(V), Rel(Instruction::Add) {}
|
||||
bool operator<(const Relation &R) const { return Val < R.Val; }
|
||||
Value *getValue() const { return Val; }
|
||||
Instruction::BinaryOps getRelation() const { return Rel; }
|
||||
unsigned getRelation() const { return Rel; }
|
||||
|
||||
// contradicts - Return true if the relationship specified by the operand
|
||||
// contradicts already known information.
|
||||
//
|
||||
bool contradicts(Instruction::BinaryOps Rel, const ValueInfo &VI) const;
|
||||
bool contradicts(unsigned Rel, const ValueInfo &VI) const;
|
||||
|
||||
// incorporate - Incorporate information in the argument into this relation
|
||||
// entry. This assumes that the information doesn't contradict itself. If
|
||||
// any new information is gained, true is returned, otherwise false is
|
||||
// returned to indicate that nothing was updated.
|
||||
//
|
||||
bool incorporate(Instruction::BinaryOps Rel, ValueInfo &VI);
|
||||
bool incorporate(unsigned Rel, ValueInfo &VI);
|
||||
|
||||
// KnownResult - Whether or not this condition determines the result of a
|
||||
// setcc in the program. False & True are intentionally 0 & 1 so we can
|
||||
// convert to bool by casting after checking for unknown.
|
||||
// setcc or icmp in the program. False & True are intentionally 0 & 1
|
||||
// so we can convert to bool by casting after checking for unknown.
|
||||
//
|
||||
enum KnownResult { KnownFalse = 0, KnownTrue = 1, Unknown = 2 };
|
||||
|
||||
@ -82,7 +82,7 @@ namespace {
|
||||
// the specified relationship is true or false, return that. If we cannot
|
||||
// determine the result required, return Unknown.
|
||||
//
|
||||
KnownResult getImpliedResult(Instruction::BinaryOps Rel) const;
|
||||
KnownResult getImpliedResult(unsigned Rel) const;
|
||||
|
||||
// print - Output this relation to the specified stream
|
||||
void print(std::ostream &OS) const;
|
||||
@ -269,19 +269,16 @@ namespace {
|
||||
void PropagateBranchInfo(BranchInst *BI);
|
||||
void PropagateSwitchInfo(SwitchInst *SI);
|
||||
void PropagateEquality(Value *Op0, Value *Op1, RegionInfo &RI);
|
||||
void PropagateRelation(Instruction::BinaryOps Opcode, Value *Op0,
|
||||
void PropagateRelation(unsigned Opcode, Value *Op0,
|
||||
Value *Op1, RegionInfo &RI);
|
||||
void UpdateUsersOfValue(Value *V, RegionInfo &RI);
|
||||
void IncorporateInstruction(Instruction *Inst, RegionInfo &RI);
|
||||
void ComputeReplacements(RegionInfo &RI);
|
||||
|
||||
|
||||
// getSetCCResult - Given a setcc instruction, determine if the result is
|
||||
// getCmpResult - Given a icmp instruction, determine if the result is
|
||||
// determined by facts we already know about the region under analysis.
|
||||
// Return KnownTrue, KnownFalse, or Unknown based on what we can determine.
|
||||
//
|
||||
Relation::KnownResult getSetCCResult(SetCondInst *SC, const RegionInfo &RI);
|
||||
|
||||
// Return KnownTrue, KnownFalse, or UnKnown based on what we can determine.
|
||||
Relation::KnownResult getCmpResult(CmpInst *ICI, const RegionInfo &RI);
|
||||
|
||||
bool SimplifyBasicBlock(BasicBlock &BB, const RegionInfo &RI);
|
||||
bool SimplifyInstruction(Instruction *Inst, const RegionInfo &RI);
|
||||
@ -448,12 +445,12 @@ bool CEE::ForwardCorrelatedEdgeDestination(TerminatorInst *TI, unsigned SuccNo,
|
||||
return false;
|
||||
|
||||
// We can only forward the branch over the block if the block ends with a
|
||||
// setcc we can determine the outcome for.
|
||||
// cmp we can determine the outcome for.
|
||||
//
|
||||
// FIXME: we can make this more generic. Code below already handles more
|
||||
// generic case.
|
||||
SetCondInst *SCI = dyn_cast<SetCondInst>(BI->getCondition());
|
||||
if (SCI == 0) return false;
|
||||
if (!isa<CmpInst>(BI->getCondition()))
|
||||
return false;
|
||||
|
||||
// Make a new RegionInfo structure so that we can simulate the effect of the
|
||||
// PHI nodes in the block we are skipping over...
|
||||
@ -472,10 +469,10 @@ bool CEE::ForwardCorrelatedEdgeDestination(TerminatorInst *TI, unsigned SuccNo,
|
||||
int OpNum = PN->getBasicBlockIndex(BB);
|
||||
assert(OpNum != -1 && "PHI doesn't have incoming edge for predecessor!?");
|
||||
PropagateEquality(PN, PN->getIncomingValue(OpNum), NewRI);
|
||||
} else if (SetCondInst *SCI = dyn_cast<SetCondInst>(I)) {
|
||||
Relation::KnownResult Res = getSetCCResult(SCI, NewRI);
|
||||
} else if (CmpInst *CI = dyn_cast<CmpInst>(I)) {
|
||||
Relation::KnownResult Res = getCmpResult(CI, NewRI);
|
||||
if (Res == Relation::Unknown) return false;
|
||||
PropagateEquality(SCI, ConstantBool::get(Res), NewRI);
|
||||
PropagateEquality(CI, ConstantBool::get(Res), NewRI);
|
||||
} else {
|
||||
assert(isa<BranchInst>(*I) && "Unexpected instruction type!");
|
||||
}
|
||||
@ -827,7 +824,8 @@ void CEE::PropagateEquality(Value *Op0, Value *Op1, RegionInfo &RI) {
|
||||
Relation &KnownRelation = VI.getRelation(Op1);
|
||||
|
||||
// If we already know they're equal, don't reprocess...
|
||||
if (KnownRelation.getRelation() == Instruction::SetEQ)
|
||||
if (KnownRelation.getRelation() == FCmpInst::FCMP_OEQ ||
|
||||
KnownRelation.getRelation() == ICmpInst::ICMP_EQ)
|
||||
return;
|
||||
|
||||
// If this is boolean, check to see if one of the operands is a constant. If
|
||||
@ -863,32 +861,55 @@ void CEE::PropagateEquality(Value *Op0, Value *Op1, RegionInfo &RI) {
|
||||
PropagateEquality(BinaryOperator::getNotArgument(BOp),
|
||||
ConstantBool::get(!CB->getValue()), RI);
|
||||
|
||||
// If we know the value of a SetCC instruction, propagate the information
|
||||
// If we know the value of a FCmp instruction, propagate the information
|
||||
// about the relation into this region as well.
|
||||
//
|
||||
if (SetCondInst *SCI = dyn_cast<SetCondInst>(Inst)) {
|
||||
if (FCmpInst *FCI = dyn_cast<FCmpInst>(Inst)) {
|
||||
if (CB->getValue()) { // If we know the condition is true...
|
||||
// Propagate info about the LHS to the RHS & RHS to LHS
|
||||
PropagateRelation(SCI->getOpcode(), SCI->getOperand(0),
|
||||
SCI->getOperand(1), RI);
|
||||
PropagateRelation(SCI->getSwappedCondition(),
|
||||
SCI->getOperand(1), SCI->getOperand(0), RI);
|
||||
PropagateRelation(FCI->getPredicate(), FCI->getOperand(0),
|
||||
FCI->getOperand(1), RI);
|
||||
PropagateRelation(FCI->getSwappedPredicate(),
|
||||
FCI->getOperand(1), FCI->getOperand(0), RI);
|
||||
|
||||
} else { // If we know the condition is false...
|
||||
// We know the opposite of the condition is true...
|
||||
Instruction::BinaryOps C = SCI->getInverseCondition();
|
||||
FCmpInst::Predicate C = FCI->getInversePredicate();
|
||||
|
||||
PropagateRelation(C, SCI->getOperand(0), SCI->getOperand(1), RI);
|
||||
PropagateRelation(SetCondInst::getSwappedCondition(C),
|
||||
SCI->getOperand(1), SCI->getOperand(0), RI);
|
||||
PropagateRelation(C, FCI->getOperand(0), FCI->getOperand(1), RI);
|
||||
PropagateRelation(FCmpInst::getSwappedPredicate(C),
|
||||
FCI->getOperand(1), FCI->getOperand(0), RI);
|
||||
}
|
||||
}
|
||||
|
||||
// If we know the value of a ICmp instruction, propagate the information
|
||||
// about the relation into this region as well.
|
||||
//
|
||||
if (ICmpInst *ICI = dyn_cast<ICmpInst>(Inst)) {
|
||||
if (CB->getValue()) { // If we know the condition is true...
|
||||
// Propagate info about the LHS to the RHS & RHS to LHS
|
||||
PropagateRelation(ICI->getPredicate(), ICI->getOperand(0),
|
||||
ICI->getOperand(1), RI);
|
||||
PropagateRelation(ICI->getSwappedPredicate(), ICI->getOperand(1),
|
||||
ICI->getOperand(1), RI);
|
||||
|
||||
} else { // If we know the condition is false ...
|
||||
// We know the opposite of the condition is true...
|
||||
ICmpInst::Predicate C = ICI->getInversePredicate();
|
||||
|
||||
PropagateRelation(C, ICI->getOperand(0), ICI->getOperand(1), RI);
|
||||
PropagateRelation(ICmpInst::getSwappedPredicate(C),
|
||||
ICI->getOperand(1), ICI->getOperand(0), RI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Propagate information about Op0 to Op1 & visa versa
|
||||
PropagateRelation(Instruction::SetEQ, Op0, Op1, RI);
|
||||
PropagateRelation(Instruction::SetEQ, Op1, Op0, RI);
|
||||
PropagateRelation(ICmpInst::ICMP_EQ, Op0, Op1, RI);
|
||||
PropagateRelation(ICmpInst::ICMP_EQ, Op1, Op0, RI);
|
||||
PropagateRelation(FCmpInst::FCMP_OEQ, Op0, Op1, RI);
|
||||
PropagateRelation(FCmpInst::FCMP_OEQ, Op1, Op0, RI);
|
||||
}
|
||||
|
||||
|
||||
@ -896,7 +917,7 @@ void CEE::PropagateEquality(Value *Op0, Value *Op1, RegionInfo &RI) {
|
||||
// blocks in the specified region. Propagate the information about Op0 and
|
||||
// anything derived from it into this region.
|
||||
//
|
||||
void CEE::PropagateRelation(Instruction::BinaryOps Opcode, Value *Op0,
|
||||
void CEE::PropagateRelation(unsigned Opcode, Value *Op0,
|
||||
Value *Op1, RegionInfo &RI) {
|
||||
assert(Op0->getType() == Op1->getType() && "Equal types expected!");
|
||||
|
||||
@ -921,7 +942,10 @@ void CEE::PropagateRelation(Instruction::BinaryOps Opcode, Value *Op0,
|
||||
if (Op1R.contradicts(Opcode, VI)) {
|
||||
Op1R.contradicts(Opcode, VI);
|
||||
cerr << "Contradiction found for opcode: "
|
||||
<< Instruction::getOpcodeName(Opcode) << "\n";
|
||||
<< ((isa<ICmpInst>(Op0)||isa<ICmpInst>(Op1)) ?
|
||||
Instruction::getOpcodeName(Instruction::ICmp) :
|
||||
Instruction::getOpcodeName(Opcode))
|
||||
<< "\n";
|
||||
Op1R.print(*cerr.stream());
|
||||
return;
|
||||
}
|
||||
@ -964,11 +988,11 @@ void CEE::UpdateUsersOfValue(Value *V, RegionInfo &RI) {
|
||||
// value produced by this instruction
|
||||
//
|
||||
void CEE::IncorporateInstruction(Instruction *Inst, RegionInfo &RI) {
|
||||
if (SetCondInst *SCI = dyn_cast<SetCondInst>(Inst)) {
|
||||
if (CmpInst *CI = dyn_cast<CmpInst>(Inst)) {
|
||||
// See if we can figure out a result for this instruction...
|
||||
Relation::KnownResult Result = getSetCCResult(SCI, RI);
|
||||
Relation::KnownResult Result = getCmpResult(CI, RI);
|
||||
if (Result != Relation::Unknown) {
|
||||
PropagateEquality(SCI, ConstantBool::get(Result != 0), RI);
|
||||
PropagateEquality(CI, ConstantBool::get(Result != 0), RI);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1002,7 +1026,14 @@ void CEE::ComputeReplacements(RegionInfo &RI) {
|
||||
// Loop over the relationships known about Op0.
|
||||
const std::vector<Relation> &Relationships = VI.getRelationships();
|
||||
for (unsigned i = 0, e = Relationships.size(); i != e; ++i)
|
||||
if (Relationships[i].getRelation() == Instruction::SetEQ) {
|
||||
if (Relationships[i].getRelation() == FCmpInst::FCMP_OEQ) {
|
||||
unsigned R = getRank(Relationships[i].getValue());
|
||||
if (R < MinRank) {
|
||||
MinRank = R;
|
||||
Replacement = Relationships[i].getValue();
|
||||
}
|
||||
}
|
||||
else if (Relationships[i].getRelation() == ICmpInst::ICMP_EQ) {
|
||||
unsigned R = getRank(Relationships[i].getValue());
|
||||
if (R < MinRank) {
|
||||
MinRank = R;
|
||||
@ -1028,16 +1059,17 @@ bool CEE::SimplifyBasicBlock(BasicBlock &BB, const RegionInfo &RI) {
|
||||
// Convert instruction arguments to canonical forms...
|
||||
Changed |= SimplifyInstruction(Inst, RI);
|
||||
|
||||
if (SetCondInst *SCI = dyn_cast<SetCondInst>(Inst)) {
|
||||
if (CmpInst *CI = dyn_cast<CmpInst>(Inst)) {
|
||||
// Try to simplify a setcc instruction based on inherited information
|
||||
Relation::KnownResult Result = getSetCCResult(SCI, RI);
|
||||
Relation::KnownResult Result = getCmpResult(CI, RI);
|
||||
if (Result != Relation::Unknown) {
|
||||
DOUT << "Replacing setcc with " << Result << " constant: " << *SCI;
|
||||
DEBUG(cerr << "Replacing icmp with " << Result
|
||||
<< " constant: " << *CI);
|
||||
|
||||
SCI->replaceAllUsesWith(ConstantBool::get((bool)Result));
|
||||
CI->replaceAllUsesWith(ConstantBool::get((bool)Result));
|
||||
// The instruction is now dead, remove it from the program.
|
||||
SCI->getParent()->getInstList().erase(SCI);
|
||||
++NumSetCCRemoved;
|
||||
CI->getParent()->getInstList().erase(CI);
|
||||
++NumCmpRemoved;
|
||||
Changed = true;
|
||||
}
|
||||
}
|
||||
@ -1069,33 +1101,35 @@ bool CEE::SimplifyInstruction(Instruction *I, const RegionInfo &RI) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
|
||||
// getSetCCResult - Try to simplify a setcc instruction based on information
|
||||
// inherited from a dominating setcc instruction. V is one of the operands to
|
||||
// the setcc instruction, and VI is the set of information known about it. We
|
||||
// getCmpResult - Try to simplify a cmp instruction based on information
|
||||
// inherited from a dominating icmp instruction. V is one of the operands to
|
||||
// the icmp instruction, and VI is the set of information known about it. We
|
||||
// take two cases into consideration here. If the comparison is against a
|
||||
// constant value, we can use the constant range to see if the comparison is
|
||||
// possible to succeed. If it is not a comparison against a constant, we check
|
||||
// to see if there is a known relationship between the two values. If so, we
|
||||
// may be able to eliminate the check.
|
||||
//
|
||||
Relation::KnownResult CEE::getSetCCResult(SetCondInst *SCI,
|
||||
const RegionInfo &RI) {
|
||||
Value *Op0 = SCI->getOperand(0), *Op1 = SCI->getOperand(1);
|
||||
Instruction::BinaryOps Opcode = SCI->getOpcode();
|
||||
Relation::KnownResult CEE::getCmpResult(CmpInst *CI,
|
||||
const RegionInfo &RI) {
|
||||
Value *Op0 = CI->getOperand(0), *Op1 = CI->getOperand(1);
|
||||
unsigned short predicate = CI->getPredicate();
|
||||
|
||||
if (isa<Constant>(Op0)) {
|
||||
if (isa<Constant>(Op1)) {
|
||||
if (Constant *Result = ConstantFoldInstruction(SCI)) {
|
||||
// Wow, this is easy, directly eliminate the SetCondInst.
|
||||
DOUT << "Replacing setcc with constant fold: " << *SCI;
|
||||
if (Constant *Result = ConstantFoldInstruction(CI)) {
|
||||
// Wow, this is easy, directly eliminate the ICmpInst.
|
||||
DEBUG(cerr << "Replacing cmp with constant fold: " << *CI);
|
||||
return cast<ConstantBool>(Result)->getValue()
|
||||
? Relation::KnownTrue : Relation::KnownFalse;
|
||||
}
|
||||
} else {
|
||||
// We want to swap this instruction so that operand #0 is the constant.
|
||||
std::swap(Op0, Op1);
|
||||
Opcode = SCI->getSwappedCondition();
|
||||
if (isa<ICmpInst>(CI))
|
||||
predicate = cast<ICmpInst>(CI)->getSwappedPredicate();
|
||||
else
|
||||
predicate = cast<FCmpInst>(CI)->getSwappedPredicate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1107,12 +1141,13 @@ Relation::KnownResult CEE::getSetCCResult(SetCondInst *SCI,
|
||||
|
||||
// At this point, we know that if we have a constant argument that it is in
|
||||
// Op1. Check to see if we know anything about comparing value with a
|
||||
// constant, and if we can use this info to fold the setcc.
|
||||
// constant, and if we can use this info to fold the icmp.
|
||||
//
|
||||
if (ConstantIntegral *C = dyn_cast<ConstantIntegral>(Op1)) {
|
||||
// Check to see if we already know the result of this comparison...
|
||||
ConstantRange R = ConstantRange(Opcode, C);
|
||||
ConstantRange Int = R.intersectWith(Op0VI->getBounds());
|
||||
ConstantRange R = ConstantRange(predicate, C);
|
||||
ConstantRange Int = R.intersectWith(Op0VI->getBounds(),
|
||||
ICmpInst::isSignedPredicate(ICmpInst::Predicate(predicate)));
|
||||
|
||||
// If the intersection of the two ranges is empty, then the condition
|
||||
// could never be true!
|
||||
@ -1134,7 +1169,7 @@ Relation::KnownResult CEE::getSetCCResult(SetCondInst *SCI,
|
||||
//
|
||||
// Do we have value information about Op0 and a relation to Op1?
|
||||
if (const Relation *Op2R = Op0VI->requestRelation(Op1))
|
||||
Result = Op2R->getImpliedResult(Opcode);
|
||||
Result = Op2R->getImpliedResult(predicate);
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
@ -1147,7 +1182,7 @@ Relation::KnownResult CEE::getSetCCResult(SetCondInst *SCI,
|
||||
// contradicts - Return true if the relationship specified by the operand
|
||||
// contradicts already known information.
|
||||
//
|
||||
bool Relation::contradicts(Instruction::BinaryOps Op,
|
||||
bool Relation::contradicts(unsigned Op,
|
||||
const ValueInfo &VI) const {
|
||||
assert (Op != Instruction::Add && "Invalid relation argument!");
|
||||
|
||||
@ -1155,24 +1190,48 @@ bool Relation::contradicts(Instruction::BinaryOps Op,
|
||||
// does not contradict properties known about the bounds of the constant.
|
||||
//
|
||||
if (ConstantIntegral *C = dyn_cast<ConstantIntegral>(Val))
|
||||
if (ConstantRange(Op, C).intersectWith(VI.getBounds()).isEmptySet())
|
||||
return true;
|
||||
if (Op >= ICmpInst::FIRST_ICMP_PREDICATE &&
|
||||
Op <= ICmpInst::LAST_ICMP_PREDICATE)
|
||||
if (ConstantRange(Op, C).intersectWith(VI.getBounds(),
|
||||
ICmpInst::isSignedPredicate(ICmpInst::Predicate(Op))).isEmptySet())
|
||||
return true;
|
||||
|
||||
switch (Rel) {
|
||||
default: assert(0 && "Unknown Relationship code!");
|
||||
case Instruction::Add: return false; // Nothing known, nothing contradicts
|
||||
case Instruction::SetEQ:
|
||||
return Op == Instruction::SetLT || Op == Instruction::SetGT ||
|
||||
Op == Instruction::SetNE;
|
||||
case Instruction::SetNE: return Op == Instruction::SetEQ;
|
||||
case Instruction::SetLE: return Op == Instruction::SetGT;
|
||||
case Instruction::SetGE: return Op == Instruction::SetLT;
|
||||
case Instruction::SetLT:
|
||||
return Op == Instruction::SetEQ || Op == Instruction::SetGT ||
|
||||
Op == Instruction::SetGE;
|
||||
case Instruction::SetGT:
|
||||
return Op == Instruction::SetEQ || Op == Instruction::SetLT ||
|
||||
Op == Instruction::SetLE;
|
||||
case ICmpInst::ICMP_EQ:
|
||||
return Op == ICmpInst::ICMP_ULT || Op == ICmpInst::ICMP_SLT ||
|
||||
Op == ICmpInst::ICMP_UGT || Op == ICmpInst::ICMP_SGT ||
|
||||
Op == ICmpInst::ICMP_NE;
|
||||
case ICmpInst::ICMP_NE: return Op == ICmpInst::ICMP_EQ;
|
||||
case ICmpInst::ICMP_ULE:
|
||||
case ICmpInst::ICMP_SLE: return Op == ICmpInst::ICMP_UGT ||
|
||||
Op == ICmpInst::ICMP_SGT;
|
||||
case ICmpInst::ICMP_UGE:
|
||||
case ICmpInst::ICMP_SGE: return Op == ICmpInst::ICMP_ULT ||
|
||||
Op == ICmpInst::ICMP_SLT;
|
||||
case ICmpInst::ICMP_ULT:
|
||||
case ICmpInst::ICMP_SLT:
|
||||
return Op == ICmpInst::ICMP_EQ || Op == ICmpInst::ICMP_UGT ||
|
||||
Op == ICmpInst::ICMP_SGT || Op == ICmpInst::ICMP_UGE ||
|
||||
Op == ICmpInst::ICMP_SGE;
|
||||
case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_SGT:
|
||||
return Op == ICmpInst::ICMP_EQ || Op == ICmpInst::ICMP_ULT ||
|
||||
Op == ICmpInst::ICMP_SLT || Op == ICmpInst::ICMP_ULE ||
|
||||
Op == ICmpInst::ICMP_SLE;
|
||||
case FCmpInst::FCMP_OEQ:
|
||||
return Op == FCmpInst::FCMP_OLT || Op == FCmpInst::FCMP_OGT ||
|
||||
Op == FCmpInst::FCMP_ONE;
|
||||
case FCmpInst::FCMP_ONE: return Op == FCmpInst::FCMP_OEQ;
|
||||
case FCmpInst::FCMP_OLE: return Op == FCmpInst::FCMP_OGT;
|
||||
case FCmpInst::FCMP_OGE: return Op == FCmpInst::FCMP_OLT;
|
||||
case FCmpInst::FCMP_OLT:
|
||||
return Op == FCmpInst::FCMP_OEQ || Op == FCmpInst::FCMP_OGT ||
|
||||
Op == FCmpInst::FCMP_OGE;
|
||||
case FCmpInst::FCMP_OGT:
|
||||
return Op == FCmpInst::FCMP_OEQ || Op == FCmpInst::FCMP_OLT ||
|
||||
Op == FCmpInst::FCMP_OLE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1181,7 +1240,7 @@ bool Relation::contradicts(Instruction::BinaryOps Op,
|
||||
// new information is gained, true is returned, otherwise false is returned to
|
||||
// indicate that nothing was updated.
|
||||
//
|
||||
bool Relation::incorporate(Instruction::BinaryOps Op, ValueInfo &VI) {
|
||||
bool Relation::incorporate(unsigned Op, ValueInfo &VI) {
|
||||
assert(!contradicts(Op, VI) &&
|
||||
"Cannot incorporate contradictory information!");
|
||||
|
||||
@ -1189,30 +1248,64 @@ bool Relation::incorporate(Instruction::BinaryOps Op, ValueInfo &VI) {
|
||||
// range that is possible for the value to have...
|
||||
//
|
||||
if (ConstantIntegral *C = dyn_cast<ConstantIntegral>(Val))
|
||||
VI.getBounds() = ConstantRange(Op, C).intersectWith(VI.getBounds());
|
||||
if (Op >= ICmpInst::FIRST_ICMP_PREDICATE &&
|
||||
Op <= ICmpInst::LAST_ICMP_PREDICATE)
|
||||
VI.getBounds() = ConstantRange(Op, C).intersectWith(VI.getBounds(),
|
||||
ICmpInst::isSignedPredicate(ICmpInst::Predicate(Op)));
|
||||
|
||||
switch (Rel) {
|
||||
default: assert(0 && "Unknown prior value!");
|
||||
case Instruction::Add: Rel = Op; return true;
|
||||
case Instruction::SetEQ: return false; // Nothing is more precise
|
||||
case Instruction::SetNE: return false; // Nothing is more precise
|
||||
case Instruction::SetLT: return false; // Nothing is more precise
|
||||
case Instruction::SetGT: return false; // Nothing is more precise
|
||||
case Instruction::SetLE:
|
||||
if (Op == Instruction::SetEQ || Op == Instruction::SetLT) {
|
||||
case ICmpInst::ICMP_EQ:
|
||||
case ICmpInst::ICMP_NE:
|
||||
case ICmpInst::ICMP_ULT:
|
||||
case ICmpInst::ICMP_SLT:
|
||||
case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_SGT: return false; // Nothing is more precise
|
||||
case ICmpInst::ICMP_ULE:
|
||||
case ICmpInst::ICMP_SLE:
|
||||
if (Op == ICmpInst::ICMP_EQ || Op == ICmpInst::ICMP_ULT ||
|
||||
Op == ICmpInst::ICMP_SLT) {
|
||||
Rel = Op;
|
||||
return true;
|
||||
} else if (Op == Instruction::SetNE) {
|
||||
Rel = Instruction::SetLT;
|
||||
} else if (Op == ICmpInst::ICMP_NE) {
|
||||
Rel = Rel == ICmpInst::ICMP_ULE ? ICmpInst::ICMP_ULT :
|
||||
ICmpInst::ICMP_SLT;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case Instruction::SetGE: return Op == Instruction::SetLT;
|
||||
if (Op == Instruction::SetEQ || Op == Instruction::SetGT) {
|
||||
case ICmpInst::ICMP_UGE:
|
||||
case ICmpInst::ICMP_SGE:
|
||||
if (Op == ICmpInst::ICMP_EQ || ICmpInst::ICMP_UGT ||
|
||||
Op == ICmpInst::ICMP_SGT) {
|
||||
Rel = Op;
|
||||
return true;
|
||||
} else if (Op == Instruction::SetNE) {
|
||||
Rel = Instruction::SetGT;
|
||||
} else if (Op == ICmpInst::ICMP_NE) {
|
||||
Rel = Rel == ICmpInst::ICMP_UGE ? ICmpInst::ICMP_UGT :
|
||||
ICmpInst::ICMP_SGT;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case FCmpInst::FCMP_OEQ: return false; // Nothing is more precise
|
||||
case FCmpInst::FCMP_ONE: return false; // Nothing is more precise
|
||||
case FCmpInst::FCMP_OLT: return false; // Nothing is more precise
|
||||
case FCmpInst::FCMP_OGT: return false; // Nothing is more precise
|
||||
case FCmpInst::FCMP_OLE:
|
||||
if (Op == FCmpInst::FCMP_OEQ || Op == FCmpInst::FCMP_OLT) {
|
||||
Rel = Op;
|
||||
return true;
|
||||
} else if (Op == FCmpInst::FCMP_ONE) {
|
||||
Rel = FCmpInst::FCMP_OLT;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case FCmpInst::FCMP_OGE:
|
||||
return Op == FCmpInst::FCMP_OLT;
|
||||
if (Op == FCmpInst::FCMP_OEQ || Op == FCmpInst::FCMP_OGT) {
|
||||
Rel = Op;
|
||||
return true;
|
||||
} else if (Op == FCmpInst::FCMP_ONE) {
|
||||
Rel = FCmpInst::FCMP_OGT;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1224,28 +1317,67 @@ bool Relation::incorporate(Instruction::BinaryOps Op, ValueInfo &VI) {
|
||||
// determine the result required, return Unknown.
|
||||
//
|
||||
Relation::KnownResult
|
||||
Relation::getImpliedResult(Instruction::BinaryOps Op) const {
|
||||
Relation::getImpliedResult(unsigned Op) const {
|
||||
if (Rel == Op) return KnownTrue;
|
||||
if (Rel == SetCondInst::getInverseCondition(Op)) return KnownFalse;
|
||||
if (Op >= ICmpInst::FIRST_ICMP_PREDICATE &&
|
||||
Op <= ICmpInst::LAST_ICMP_PREDICATE) {
|
||||
if (Rel == unsigned(ICmpInst::getInversePredicate(ICmpInst::Predicate(Op))))
|
||||
return KnownFalse;
|
||||
} else if (Op <= FCmpInst::LAST_FCMP_PREDICATE) {
|
||||
if (Rel == unsigned(FCmpInst::getInversePredicate(FCmpInst::Predicate(Op))))
|
||||
return KnownFalse;
|
||||
}
|
||||
|
||||
switch (Rel) {
|
||||
default: assert(0 && "Unknown prior value!");
|
||||
case Instruction::SetEQ:
|
||||
if (Op == Instruction::SetLE || Op == Instruction::SetGE) return KnownTrue;
|
||||
if (Op == Instruction::SetLT || Op == Instruction::SetGT) return KnownFalse;
|
||||
case ICmpInst::ICMP_EQ:
|
||||
if (Op == ICmpInst::ICMP_ULE || Op == ICmpInst::ICMP_SLE ||
|
||||
Op == ICmpInst::ICMP_UGE || Op == ICmpInst::ICMP_SGE) return KnownTrue;
|
||||
if (Op == ICmpInst::ICMP_ULT || Op == ICmpInst::ICMP_SLT ||
|
||||
Op == ICmpInst::ICMP_UGT || Op == ICmpInst::ICMP_SGT) return KnownFalse;
|
||||
break;
|
||||
case Instruction::SetLT:
|
||||
if (Op == Instruction::SetNE || Op == Instruction::SetLE) return KnownTrue;
|
||||
if (Op == Instruction::SetEQ) return KnownFalse;
|
||||
case ICmpInst::ICMP_ULT:
|
||||
case ICmpInst::ICMP_SLT:
|
||||
if (Op == ICmpInst::ICMP_ULE || Op == ICmpInst::ICMP_SLE ||
|
||||
Op == ICmpInst::ICMP_NE) return KnownTrue;
|
||||
if (Op == ICmpInst::ICMP_EQ) return KnownFalse;
|
||||
break;
|
||||
case Instruction::SetGT:
|
||||
if (Op == Instruction::SetNE || Op == Instruction::SetGE) return KnownTrue;
|
||||
if (Op == Instruction::SetEQ) return KnownFalse;
|
||||
case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_SGT:
|
||||
if (Op == ICmpInst::ICMP_UGE || Op == ICmpInst::ICMP_SGE ||
|
||||
Op == ICmpInst::ICMP_NE) return KnownTrue;
|
||||
if (Op == ICmpInst::ICMP_EQ) return KnownFalse;
|
||||
break;
|
||||
case Instruction::SetNE:
|
||||
case Instruction::SetLE:
|
||||
case Instruction::SetGE:
|
||||
case Instruction::Add:
|
||||
case FCmpInst::FCMP_OEQ:
|
||||
if (Op == FCmpInst::FCMP_OLE || Op == FCmpInst::FCMP_OGE) return KnownTrue;
|
||||
if (Op == FCmpInst::FCMP_OLT || Op == FCmpInst::FCMP_OGT) return KnownFalse;
|
||||
break;
|
||||
case FCmpInst::FCMP_OLT:
|
||||
if (Op == FCmpInst::FCMP_ONE || Op == FCmpInst::FCMP_OLE) return KnownTrue;
|
||||
if (Op == FCmpInst::FCMP_OEQ) return KnownFalse;
|
||||
break;
|
||||
case FCmpInst::FCMP_OGT:
|
||||
if (Op == FCmpInst::FCMP_ONE || Op == FCmpInst::FCMP_OGE) return KnownTrue;
|
||||
if (Op == FCmpInst::FCMP_OEQ) return KnownFalse;
|
||||
break;
|
||||
case ICmpInst::ICMP_NE:
|
||||
case ICmpInst::ICMP_SLE:
|
||||
case ICmpInst::ICMP_ULE:
|
||||
case ICmpInst::ICMP_UGE:
|
||||
case ICmpInst::ICMP_SGE:
|
||||
case FCmpInst::FCMP_ONE:
|
||||
case FCmpInst::FCMP_OLE:
|
||||
case FCmpInst::FCMP_OGE:
|
||||
case FCmpInst::FCMP_FALSE:
|
||||
case FCmpInst::FCMP_ORD:
|
||||
case FCmpInst::FCMP_UNO:
|
||||
case FCmpInst::FCMP_UEQ:
|
||||
case FCmpInst::FCMP_UGT:
|
||||
case FCmpInst::FCMP_UGE:
|
||||
case FCmpInst::FCMP_ULT:
|
||||
case FCmpInst::FCMP_ULE:
|
||||
case FCmpInst::FCMP_UNE:
|
||||
case FCmpInst::FCMP_TRUE:
|
||||
break;
|
||||
}
|
||||
return Unknown;
|
||||
@ -1298,12 +1430,30 @@ void Relation::print(std::ostream &OS) const {
|
||||
OS << " is ";
|
||||
switch (Rel) {
|
||||
default: OS << "*UNKNOWN*"; break;
|
||||
case Instruction::SetEQ: OS << "== "; break;
|
||||
case Instruction::SetNE: OS << "!= "; break;
|
||||
case Instruction::SetLT: OS << "< "; break;
|
||||
case Instruction::SetGT: OS << "> "; break;
|
||||
case Instruction::SetLE: OS << "<= "; break;
|
||||
case Instruction::SetGE: OS << ">= "; break;
|
||||
case ICmpInst::ICMP_EQ:
|
||||
case FCmpInst::FCMP_ORD:
|
||||
case FCmpInst::FCMP_UEQ:
|
||||
case FCmpInst::FCMP_OEQ: OS << "== "; break;
|
||||
case ICmpInst::ICMP_NE:
|
||||
case FCmpInst::FCMP_UNO:
|
||||
case FCmpInst::FCMP_UNE:
|
||||
case FCmpInst::FCMP_ONE: OS << "!= "; break;
|
||||
case ICmpInst::ICMP_ULT:
|
||||
case ICmpInst::ICMP_SLT:
|
||||
case FCmpInst::FCMP_ULT:
|
||||
case FCmpInst::FCMP_OLT: OS << "< "; break;
|
||||
case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_SGT:
|
||||
case FCmpInst::FCMP_UGT:
|
||||
case FCmpInst::FCMP_OGT: OS << "> "; break;
|
||||
case ICmpInst::ICMP_ULE:
|
||||
case ICmpInst::ICMP_SLE:
|
||||
case FCmpInst::FCMP_ULE:
|
||||
case FCmpInst::FCMP_OLE: OS << "<= "; break;
|
||||
case ICmpInst::ICMP_UGE:
|
||||
case ICmpInst::ICMP_SGE:
|
||||
case FCmpInst::FCMP_UGE:
|
||||
case FCmpInst::FCMP_OGE: OS << ">= "; break;
|
||||
}
|
||||
|
||||
WriteAsOperand(OS, Val);
|
||||
|
@ -271,14 +271,14 @@ Instruction *IndVarSimplify::LinearFunctionTestReplace(Loop *L,
|
||||
Value *ExitCnt = RW.expandCodeFor(TripCount, Preheader->getTerminator(),
|
||||
IndVar->getType());
|
||||
|
||||
// Insert a new setne or seteq instruction before the branch.
|
||||
Instruction::BinaryOps Opcode;
|
||||
// Insert a new icmp_ne or icmp_eq instruction before the branch.
|
||||
ICmpInst::Predicate Opcode;
|
||||
if (L->contains(BI->getSuccessor(0)))
|
||||
Opcode = Instruction::SetNE;
|
||||
Opcode = ICmpInst::ICMP_NE;
|
||||
else
|
||||
Opcode = Instruction::SetEQ;
|
||||
Opcode = ICmpInst::ICMP_EQ;
|
||||
|
||||
Value *Cond = new SetCondInst(Opcode, IndVar, ExitCnt, "exitcond", BI);
|
||||
Value *Cond = new ICmpInst(Opcode, IndVar, ExitCnt, "exitcond", BI);
|
||||
BI->setCondition(Cond);
|
||||
++NumLFTR;
|
||||
Changed = true;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -385,7 +385,7 @@ bool LICM::canSinkOrHoistInst(Instruction &I) {
|
||||
|
||||
// Otherwise these instructions are hoistable/sinkable
|
||||
return isa<BinaryOperator>(I) || isa<ShiftInst>(I) || isa<CastInst>(I) ||
|
||||
isa<SelectInst>(I) || isa<GetElementPtrInst>(I);
|
||||
isa<SelectInst>(I) || isa<GetElementPtrInst>(I) || isa<CmpInst>(I);
|
||||
}
|
||||
|
||||
/// isNotUsedInLoop - Return true if the only users of this instruction are
|
||||
|
@ -1191,9 +1191,6 @@ void LoopStrengthReduce::StrengthReduceStridedIVUsers(const SCEVHandle &Stride,
|
||||
void LoopStrengthReduce::OptimizeIndvars(Loop *L) {
|
||||
// TODO: implement optzns here.
|
||||
|
||||
|
||||
|
||||
|
||||
// Finally, get the terminating condition for the loop if possible. If we
|
||||
// can, we want to change it to use a post-incremented version of its
|
||||
// induction variable, to allow coalescing the live ranges for the IV into
|
||||
@ -1203,10 +1200,10 @@ void LoopStrengthReduce::OptimizeIndvars(Loop *L) {
|
||||
BasicBlock *LatchBlock =
|
||||
SomePHI->getIncomingBlock(SomePHI->getIncomingBlock(0) == Preheader);
|
||||
BranchInst *TermBr = dyn_cast<BranchInst>(LatchBlock->getTerminator());
|
||||
if (!TermBr || TermBr->isUnconditional() ||
|
||||
!isa<SetCondInst>(TermBr->getCondition()))
|
||||
if (!TermBr || TermBr->isUnconditional() ||
|
||||
!isa<ICmpInst>(TermBr->getCondition()))
|
||||
return;
|
||||
SetCondInst *Cond = cast<SetCondInst>(TermBr->getCondition());
|
||||
ICmpInst *Cond = cast<ICmpInst>(TermBr->getCondition());
|
||||
|
||||
// Search IVUsesByStride to find Cond's IVUse if there is one.
|
||||
IVStrideUse *CondUse = 0;
|
||||
@ -1239,7 +1236,7 @@ void LoopStrengthReduce::OptimizeIndvars(Loop *L) {
|
||||
Cond->moveBefore(TermBr);
|
||||
} else {
|
||||
// Otherwise, clone the terminating condition and insert into the loopend.
|
||||
Cond = cast<SetCondInst>(Cond->clone());
|
||||
Cond = cast<ICmpInst>(Cond->clone());
|
||||
Cond->setName(L->getHeader()->getName() + ".termcond");
|
||||
LatchBlock->getInstList().insert(TermBr, Cond);
|
||||
|
||||
@ -1360,9 +1357,9 @@ void LoopStrengthReduce::runOnLoop(Loop *L) {
|
||||
// FIXME: this needs to eliminate an induction variable even if it's being
|
||||
// compared against some value to decide loop termination.
|
||||
if (PN->hasOneUse()) {
|
||||
BinaryOperator *BO = dyn_cast<BinaryOperator>(*(PN->use_begin()));
|
||||
if (BO && BO->hasOneUse()) {
|
||||
if (PN == *(BO->use_begin())) {
|
||||
Instruction *BO = dyn_cast<Instruction>(*PN->use_begin());
|
||||
if (BO && (isa<BinaryOperator>(BO) || isa<CmpInst>(BO))) {
|
||||
if (BO->hasOneUse() && PN == *(BO->use_begin())) {
|
||||
DeadInsts.insert(BO);
|
||||
// Break the cycle, then delete the PHI.
|
||||
PN->replaceAllUsesWith(UndefValue::get(PN->getType()));
|
||||
|
@ -486,12 +486,11 @@ static void EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val,
|
||||
// Insert a conditional branch on LIC to the two preheaders. The original
|
||||
// code is the true version and the new code is the false version.
|
||||
Value *BranchVal = LIC;
|
||||
if (!isa<ConstantBool>(Val)) {
|
||||
BranchVal = BinaryOperator::createSetEQ(LIC, Val, "tmp", InsertPt);
|
||||
} else if (Val != ConstantBool::getTrue()) {
|
||||
if (!isa<ConstantBool>(Val))
|
||||
BranchVal = new ICmpInst(ICmpInst::ICMP_EQ, LIC, Val, "tmp", InsertPt);
|
||||
else if (Val != ConstantBool::getTrue())
|
||||
// We want to enter the new loop when the condition is true.
|
||||
std::swap(TrueDest, FalseDest);
|
||||
}
|
||||
|
||||
// Insert the new branch.
|
||||
new BranchInst(TrueDest, FalseDest, BranchVal, InsertPt);
|
||||
|
@ -54,6 +54,10 @@ public:
|
||||
/// @param BO the binary operator to convert
|
||||
void visitBinaryOperator(BinaryOperator& BO);
|
||||
|
||||
/// @brief Lowers packed icmp operations.
|
||||
/// @param CI the icmp operator to convert
|
||||
void visitICmpInst(ICmpInst& IC);
|
||||
|
||||
/// @brief Lowers packed select instructions.
|
||||
/// @param SELI the select operator to convert
|
||||
void visitSelectInst(SelectInst& SELI);
|
||||
@ -269,6 +273,35 @@ void LowerPacked::visitBinaryOperator(BinaryOperator& BO)
|
||||
}
|
||||
}
|
||||
|
||||
void LowerPacked::visitICmpInst(ICmpInst& IC)
|
||||
{
|
||||
// Make sure both operands are PackedTypes
|
||||
if (isa<PackedType>(IC.getOperand(0)->getType())) {
|
||||
std::vector<Value*>& op0Vals = getValues(IC.getOperand(0));
|
||||
std::vector<Value*>& op1Vals = getValues(IC.getOperand(1));
|
||||
std::vector<Value*> result;
|
||||
assert((op0Vals.size() == op1Vals.size()) &&
|
||||
"The two packed operand to scalar maps must be equal in size.");
|
||||
|
||||
result.reserve(op0Vals.size());
|
||||
|
||||
// generate the new binary op and save the result
|
||||
for (unsigned i = 0; i != op0Vals.size(); ++i) {
|
||||
result.push_back(CmpInst::create(IC.getOpcode(),
|
||||
IC.getPredicate(),
|
||||
op0Vals[i],
|
||||
op1Vals[i],
|
||||
IC.getName() +
|
||||
"." + utostr(i),
|
||||
&IC));
|
||||
}
|
||||
|
||||
setValues(&IC,result);
|
||||
Changed = true;
|
||||
instrsToRemove.push_back(&IC);
|
||||
}
|
||||
}
|
||||
|
||||
void LowerPacked::visitStoreInst(StoreInst& SI)
|
||||
{
|
||||
if (const PackedType* PKT =
|
||||
@ -376,12 +409,12 @@ void LowerPacked::visitInsertElementInst(InsertElementInst& IE)
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i != Vals.size(); ++i) {
|
||||
SetCondInst *setcc =
|
||||
new SetCondInst(Instruction::SetEQ, Idx,
|
||||
ConstantInt::get(Type::UIntTy, i),
|
||||
"setcc", &IE);
|
||||
ICmpInst *icmp =
|
||||
new ICmpInst(ICmpInst::ICMP_EQ, Idx,
|
||||
ConstantInt::get(Type::UIntTy, i),
|
||||
"icmp", &IE);
|
||||
SelectInst *select =
|
||||
new SelectInst(setcc, Elt, Vals[i], "select", &IE);
|
||||
new SelectInst(icmp, Elt, Vals[i], "select", &IE);
|
||||
result.push_back(select);
|
||||
}
|
||||
}
|
||||
|
@ -559,7 +559,8 @@ namespace {
|
||||
void addToWorklist(Instruction *I) {
|
||||
//DOUT << "addToWorklist: " << *I << "\n";
|
||||
|
||||
if (!isa<BinaryOperator>(I) && !isa<SelectInst>(I)) return;
|
||||
if (!isa<BinaryOperator>(I) && !isa<SelectInst>(I) && !isa<CmpInst>(I))
|
||||
return;
|
||||
|
||||
const Type *Ty = I->getType();
|
||||
if (Ty == Type::VoidTy || Ty->isFPOrFPVector()) return;
|
||||
@ -855,102 +856,6 @@ namespace {
|
||||
addEqual(BO, ConstantExpr::get(BO->getOpcode(), CI1, CI2));
|
||||
|
||||
switch (BO->getOpcode()) {
|
||||
case Instruction::SetEQ:
|
||||
// "seteq int %a, %b" EQ true then %a EQ %b
|
||||
// "seteq int %a, %b" EQ false then %a NE %b
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addEqual(Op0, Op1);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addNotEqual(Op0, Op1);
|
||||
|
||||
// %a EQ %b then "seteq int %a, %b" EQ true
|
||||
// %a NE %b then "seteq int %a, %b" EQ false
|
||||
if (isEqual(Op0, Op1))
|
||||
addEqual(BO, ConstantBool::getTrue());
|
||||
else if (isNotEqual(Op0, Op1))
|
||||
addEqual(BO, ConstantBool::getFalse());
|
||||
|
||||
break;
|
||||
case Instruction::SetNE:
|
||||
// "setne int %a, %b" EQ true then %a NE %b
|
||||
// "setne int %a, %b" EQ false then %a EQ %b
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addNotEqual(Op0, Op1);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addEqual(Op0, Op1);
|
||||
|
||||
// %a EQ %b then "setne int %a, %b" EQ false
|
||||
// %a NE %b then "setne int %a, %b" EQ true
|
||||
if (isEqual(Op0, Op1))
|
||||
addEqual(BO, ConstantBool::getFalse());
|
||||
else if (isNotEqual(Op0, Op1))
|
||||
addEqual(BO, ConstantBool::getTrue());
|
||||
|
||||
break;
|
||||
case Instruction::SetLT:
|
||||
// "setlt int %a, %b" EQ true then %a LT %b
|
||||
// "setlt int %a, %b" EQ false then %b LE %a
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addLess(Op0, Op1);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addLessEqual(Op1, Op0);
|
||||
|
||||
// %a LT %b then "setlt int %a, %b" EQ true
|
||||
// %a GE %b then "setlt int %a, %b" EQ false
|
||||
if (isLess(Op0, Op1))
|
||||
addEqual(BO, ConstantBool::getTrue());
|
||||
else if (isGreaterEqual(Op0, Op1))
|
||||
addEqual(BO, ConstantBool::getFalse());
|
||||
|
||||
break;
|
||||
case Instruction::SetLE:
|
||||
// "setle int %a, %b" EQ true then %a LE %b
|
||||
// "setle int %a, %b" EQ false then %b LT %a
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addLessEqual(Op0, Op1);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addLess(Op1, Op0);
|
||||
|
||||
// %a LE %b then "setle int %a, %b" EQ true
|
||||
// %a GT %b then "setle int %a, %b" EQ false
|
||||
if (isLessEqual(Op0, Op1))
|
||||
addEqual(BO, ConstantBool::getTrue());
|
||||
else if (isGreater(Op0, Op1))
|
||||
addEqual(BO, ConstantBool::getFalse());
|
||||
|
||||
break;
|
||||
case Instruction::SetGT:
|
||||
// "setgt int %a, %b" EQ true then %b LT %a
|
||||
// "setgt int %a, %b" EQ false then %a LE %b
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addLess(Op1, Op0);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addLessEqual(Op0, Op1);
|
||||
|
||||
// %a GT %b then "setgt int %a, %b" EQ true
|
||||
// %a LE %b then "setgt int %a, %b" EQ false
|
||||
if (isGreater(Op0, Op1))
|
||||
addEqual(BO, ConstantBool::getTrue());
|
||||
else if (isLessEqual(Op0, Op1))
|
||||
addEqual(BO, ConstantBool::getFalse());
|
||||
|
||||
break;
|
||||
case Instruction::SetGE:
|
||||
// "setge int %a, %b" EQ true then %b LE %a
|
||||
// "setge int %a, %b" EQ false then %a LT %b
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addLessEqual(Op1, Op0);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addLess(Op0, Op1);
|
||||
|
||||
// %a GE %b then "setge int %a, %b" EQ true
|
||||
// %a LT %b then "setlt int %a, %b" EQ false
|
||||
if (isGreaterEqual(Op0, Op1))
|
||||
addEqual(BO, ConstantBool::getTrue());
|
||||
else if (isLess(Op0, Op1))
|
||||
addEqual(BO, ConstantBool::getFalse());
|
||||
|
||||
break;
|
||||
case Instruction::And: {
|
||||
// "and int %a, %b" EQ -1 then %a EQ -1 and %b EQ -1
|
||||
// "and bool %a, %b" EQ true then %a EQ true and %b EQ true
|
||||
@ -1030,6 +935,250 @@ namespace {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (FCmpInst *CI = dyn_cast<FCmpInst>(I)) {
|
||||
Value *Op0 = cIG.canonicalize(CI->getOperand(0)),
|
||||
*Op1 = cIG.canonicalize(CI->getOperand(1));
|
||||
|
||||
ConstantFP *CI1 = dyn_cast<ConstantFP>(Op0),
|
||||
*CI2 = dyn_cast<ConstantFP>(Op1);
|
||||
|
||||
if (CI1 && CI2)
|
||||
addEqual(CI, ConstantExpr::getFCmp(CI->getPredicate(), CI1, CI2));
|
||||
|
||||
switch (CI->getPredicate()) {
|
||||
case FCmpInst::FCMP_OEQ:
|
||||
case FCmpInst::FCMP_UEQ:
|
||||
// "eq int %a, %b" EQ true then %a EQ %b
|
||||
// "eq int %a, %b" EQ false then %a NE %b
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addEqual(Op0, Op1);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addNotEqual(Op0, Op1);
|
||||
|
||||
// %a EQ %b then "eq int %a, %b" EQ true
|
||||
// %a NE %b then "eq int %a, %b" EQ false
|
||||
if (isEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getTrue());
|
||||
else if (isNotEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getFalse());
|
||||
|
||||
break;
|
||||
case FCmpInst::FCMP_ONE:
|
||||
case FCmpInst::FCMP_UNE:
|
||||
// "ne int %a, %b" EQ true then %a NE %b
|
||||
// "ne int %a, %b" EQ false then %a EQ %b
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addNotEqual(Op0, Op1);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addEqual(Op0, Op1);
|
||||
|
||||
// %a EQ %b then "ne int %a, %b" EQ false
|
||||
// %a NE %b then "ne int %a, %b" EQ true
|
||||
if (isEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getFalse());
|
||||
else if (isNotEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getTrue());
|
||||
|
||||
break;
|
||||
case FCmpInst::FCMP_ULT:
|
||||
case FCmpInst::FCMP_OLT:
|
||||
// "lt int %a, %b" EQ true then %a LT %b
|
||||
// "lt int %a, %b" EQ false then %b LE %a
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addLess(Op0, Op1);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addLessEqual(Op1, Op0);
|
||||
|
||||
// %a LT %b then "lt int %a, %b" EQ true
|
||||
// %a GE %b then "lt int %a, %b" EQ false
|
||||
if (isLess(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getTrue());
|
||||
else if (isGreaterEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getFalse());
|
||||
|
||||
break;
|
||||
case FCmpInst::FCMP_ULE:
|
||||
case FCmpInst::FCMP_OLE:
|
||||
// "le int %a, %b" EQ true then %a LE %b
|
||||
// "le int %a, %b" EQ false then %b LT %a
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addLessEqual(Op0, Op1);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addLess(Op1, Op0);
|
||||
|
||||
// %a LE %b then "le int %a, %b" EQ true
|
||||
// %a GT %b then "le int %a, %b" EQ false
|
||||
if (isLessEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getTrue());
|
||||
else if (isGreater(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getFalse());
|
||||
|
||||
break;
|
||||
case FCmpInst::FCMP_UGT:
|
||||
case FCmpInst::FCMP_OGT:
|
||||
// "gt int %a, %b" EQ true then %b LT %a
|
||||
// "gt int %a, %b" EQ false then %a LE %b
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addLess(Op1, Op0);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addLessEqual(Op0, Op1);
|
||||
|
||||
// %a GT %b then "gt int %a, %b" EQ true
|
||||
// %a LE %b then "gt int %a, %b" EQ false
|
||||
if (isGreater(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getTrue());
|
||||
else if (isLessEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getFalse());
|
||||
|
||||
break;
|
||||
case FCmpInst::FCMP_UGE:
|
||||
case FCmpInst::FCMP_OGE:
|
||||
// "ge int %a, %b" EQ true then %b LE %a
|
||||
// "ge int %a, %b" EQ false then %a LT %b
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addLessEqual(Op1, Op0);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addLess(Op0, Op1);
|
||||
|
||||
// %a GE %b then "ge int %a, %b" EQ true
|
||||
// %a LT %b then "lt int %a, %b" EQ false
|
||||
if (isGreaterEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getTrue());
|
||||
else if (isLess(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getFalse());
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// "%x = add int %y, %z" and %x EQ %y then %z EQ 0
|
||||
// "%x = mul int %y, %z" and %x EQ %y then %z EQ 1
|
||||
// 1. Repeat all of the above, with order of operands reversed.
|
||||
// "%x = fdiv float %y, %z" and %x EQ %y then %z EQ 1
|
||||
Value *Known = Op0, *Unknown = Op1;
|
||||
if (Known != BO) std::swap(Known, Unknown);
|
||||
} else if (ICmpInst *CI = dyn_cast<ICmpInst>(I)) {
|
||||
Value *Op0 = cIG.canonicalize(CI->getOperand(0)),
|
||||
*Op1 = cIG.canonicalize(CI->getOperand(1));
|
||||
|
||||
ConstantIntegral *CI1 = dyn_cast<ConstantIntegral>(Op0),
|
||||
*CI2 = dyn_cast<ConstantIntegral>(Op1);
|
||||
|
||||
if (CI1 && CI2)
|
||||
addEqual(CI, ConstantExpr::getICmp(CI->getPredicate(), CI1, CI2));
|
||||
|
||||
switch (CI->getPredicate()) {
|
||||
case ICmpInst::ICMP_EQ:
|
||||
// "eq int %a, %b" EQ true then %a EQ %b
|
||||
// "eq int %a, %b" EQ false then %a NE %b
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addEqual(Op0, Op1);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addNotEqual(Op0, Op1);
|
||||
|
||||
// %a EQ %b then "eq int %a, %b" EQ true
|
||||
// %a NE %b then "eq int %a, %b" EQ false
|
||||
if (isEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getTrue());
|
||||
else if (isNotEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getFalse());
|
||||
|
||||
break;
|
||||
case ICmpInst::ICMP_NE:
|
||||
// "ne int %a, %b" EQ true then %a NE %b
|
||||
// "ne int %a, %b" EQ false then %a EQ %b
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addNotEqual(Op0, Op1);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addEqual(Op0, Op1);
|
||||
|
||||
// %a EQ %b then "ne int %a, %b" EQ false
|
||||
// %a NE %b then "ne int %a, %b" EQ true
|
||||
if (isEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getFalse());
|
||||
else if (isNotEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getTrue());
|
||||
|
||||
break;
|
||||
case ICmpInst::ICMP_ULT:
|
||||
case ICmpInst::ICMP_SLT:
|
||||
// "lt int %a, %b" EQ true then %a LT %b
|
||||
// "lt int %a, %b" EQ false then %b LE %a
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addLess(Op0, Op1);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addLessEqual(Op1, Op0);
|
||||
|
||||
// %a LT %b then "lt int %a, %b" EQ true
|
||||
// %a GE %b then "lt int %a, %b" EQ false
|
||||
if (isLess(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getTrue());
|
||||
else if (isGreaterEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getFalse());
|
||||
|
||||
break;
|
||||
case ICmpInst::ICMP_ULE:
|
||||
case ICmpInst::ICMP_SLE:
|
||||
// "le int %a, %b" EQ true then %a LE %b
|
||||
// "le int %a, %b" EQ false then %b LT %a
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addLessEqual(Op0, Op1);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addLess(Op1, Op0);
|
||||
|
||||
// %a LE %b then "le int %a, %b" EQ true
|
||||
// %a GT %b then "le int %a, %b" EQ false
|
||||
if (isLessEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getTrue());
|
||||
else if (isGreater(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getFalse());
|
||||
|
||||
break;
|
||||
case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_SGT:
|
||||
// "gt int %a, %b" EQ true then %b LT %a
|
||||
// "gt int %a, %b" EQ false then %a LE %b
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addLess(Op1, Op0);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addLessEqual(Op0, Op1);
|
||||
|
||||
// %a GT %b then "gt int %a, %b" EQ true
|
||||
// %a LE %b then "gt int %a, %b" EQ false
|
||||
if (isGreater(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getTrue());
|
||||
else if (isLessEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getFalse());
|
||||
|
||||
break;
|
||||
case ICmpInst::ICMP_UGE:
|
||||
case ICmpInst::ICMP_SGE:
|
||||
// "ge int %a, %b" EQ true then %b LE %a
|
||||
// "ge int %a, %b" EQ false then %a LT %b
|
||||
if (Canonical == ConstantBool::getTrue())
|
||||
addLessEqual(Op1, Op0);
|
||||
else if (Canonical == ConstantBool::getFalse())
|
||||
addLess(Op0, Op1);
|
||||
|
||||
// %a GE %b then "ge int %a, %b" EQ true
|
||||
// %a LT %b then "lt int %a, %b" EQ false
|
||||
if (isGreaterEqual(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getTrue());
|
||||
else if (isLess(Op0, Op1))
|
||||
addEqual(CI, ConstantBool::getFalse());
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// "%x = add int %y, %z" and %x EQ %y then %z EQ 0
|
||||
// "%x = mul int %y, %z" and %x EQ %y then %z EQ 1
|
||||
// 1. Repeat all of the above, with order of operands reversed.
|
||||
// "%x = fdiv float %y, %z" and %x EQ %y then %z EQ 1
|
||||
Value *Known = Op0, *Unknown = Op1;
|
||||
if (Known != BO) std::swap(Known, Unknown);
|
||||
} else if (SelectInst *SI = dyn_cast<SelectInst>(I)) {
|
||||
// Given: "%a = select bool %x, int %b, int %c"
|
||||
// %a EQ %b then %x EQ true
|
||||
@ -1108,6 +1257,7 @@ namespace {
|
||||
void visitStoreInst(StoreInst &SI);
|
||||
|
||||
void visitBinaryOperator(BinaryOperator &BO);
|
||||
void visitCmpInst(CmpInst &CI) {}
|
||||
};
|
||||
|
||||
// Used by terminator instructions to proceed from the current basic
|
||||
|
@ -95,10 +95,11 @@ namespace {
|
||||
FunctionPass *llvm::createReassociatePass() { return new Reassociate(); }
|
||||
|
||||
void Reassociate::RemoveDeadBinaryOp(Value *V) {
|
||||
BinaryOperator *BOp = dyn_cast<BinaryOperator>(V);
|
||||
if (!BOp || !BOp->use_empty()) return;
|
||||
Instruction *Op = dyn_cast<Instruction>(V);
|
||||
if (!Op || !isa<BinaryOperator>(Op) || !isa<CmpInst>(Op) || !Op->use_empty())
|
||||
return;
|
||||
|
||||
Value *LHS = BOp->getOperand(0), *RHS = BOp->getOperand(1);
|
||||
Value *LHS = Op->getOperand(0), *RHS = Op->getOperand(1);
|
||||
RemoveDeadBinaryOp(LHS);
|
||||
RemoveDeadBinaryOp(RHS);
|
||||
}
|
||||
@ -755,7 +756,7 @@ void Reassociate::ReassociateBB(BasicBlock *BB) {
|
||||
}
|
||||
|
||||
// Reject cases where it is pointless to do this.
|
||||
if (!isa<BinaryOperator>(BI) || BI->getType()->isFloatingPoint() ||
|
||||
if (!isa<BinaryOperator>(BI) || BI->getType()->isFloatingPoint() ||
|
||||
isa<PackedType>(BI->getType()))
|
||||
continue; // Floating point ops are not associative.
|
||||
|
||||
|
@ -373,6 +373,7 @@ private:
|
||||
void visitCastInst(CastInst &I);
|
||||
void visitSelectInst(SelectInst &I);
|
||||
void visitBinaryOperator(Instruction &I);
|
||||
void visitCmpInst(CmpInst &I);
|
||||
void visitShiftInst(ShiftInst &I) { visitBinaryOperator(I); }
|
||||
void visitExtractElementInst(ExtractElementInst &I);
|
||||
void visitInsertElementInst(InsertElementInst &I);
|
||||
@ -796,6 +797,93 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) {
|
||||
}
|
||||
}
|
||||
|
||||
// Handle ICmpInst instruction...
|
||||
void SCCPSolver::visitCmpInst(CmpInst &I) {
|
||||
LatticeVal &IV = ValueState[&I];
|
||||
if (IV.isOverdefined()) return;
|
||||
|
||||
LatticeVal &V1State = getValueState(I.getOperand(0));
|
||||
LatticeVal &V2State = getValueState(I.getOperand(1));
|
||||
|
||||
if (V1State.isOverdefined() || V2State.isOverdefined()) {
|
||||
// If both operands are PHI nodes, it is possible that this instruction has
|
||||
// a constant value, despite the fact that the PHI node doesn't. Check for
|
||||
// this condition now.
|
||||
if (PHINode *PN1 = dyn_cast<PHINode>(I.getOperand(0)))
|
||||
if (PHINode *PN2 = dyn_cast<PHINode>(I.getOperand(1)))
|
||||
if (PN1->getParent() == PN2->getParent()) {
|
||||
// Since the two PHI nodes are in the same basic block, they must have
|
||||
// entries for the same predecessors. Walk the predecessor list, and
|
||||
// if all of the incoming values are constants, and the result of
|
||||
// evaluating this expression with all incoming value pairs is the
|
||||
// same, then this expression is a constant even though the PHI node
|
||||
// is not a constant!
|
||||
LatticeVal Result;
|
||||
for (unsigned i = 0, e = PN1->getNumIncomingValues(); i != e; ++i) {
|
||||
LatticeVal &In1 = getValueState(PN1->getIncomingValue(i));
|
||||
BasicBlock *InBlock = PN1->getIncomingBlock(i);
|
||||
LatticeVal &In2 =
|
||||
getValueState(PN2->getIncomingValueForBlock(InBlock));
|
||||
|
||||
if (In1.isOverdefined() || In2.isOverdefined()) {
|
||||
Result.markOverdefined();
|
||||
break; // Cannot fold this operation over the PHI nodes!
|
||||
} else if (In1.isConstant() && In2.isConstant()) {
|
||||
Constant *V = ConstantExpr::getCompare(I.getPredicate(),
|
||||
In1.getConstant(),
|
||||
In2.getConstant());
|
||||
if (Result.isUndefined())
|
||||
Result.markConstant(V);
|
||||
else if (Result.isConstant() && Result.getConstant() != V) {
|
||||
Result.markOverdefined();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we found a constant value here, then we know the instruction is
|
||||
// constant despite the fact that the PHI nodes are overdefined.
|
||||
if (Result.isConstant()) {
|
||||
markConstant(IV, &I, Result.getConstant());
|
||||
// Remember that this instruction is virtually using the PHI node
|
||||
// operands.
|
||||
UsersOfOverdefinedPHIs.insert(std::make_pair(PN1, &I));
|
||||
UsersOfOverdefinedPHIs.insert(std::make_pair(PN2, &I));
|
||||
return;
|
||||
} else if (Result.isUndefined()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Okay, this really is overdefined now. Since we might have
|
||||
// speculatively thought that this was not overdefined before, and
|
||||
// added ourselves to the UsersOfOverdefinedPHIs list for the PHIs,
|
||||
// make sure to clean out any entries that we put there, for
|
||||
// efficiency.
|
||||
std::multimap<PHINode*, Instruction*>::iterator It, E;
|
||||
tie(It, E) = UsersOfOverdefinedPHIs.equal_range(PN1);
|
||||
while (It != E) {
|
||||
if (It->second == &I) {
|
||||
UsersOfOverdefinedPHIs.erase(It++);
|
||||
} else
|
||||
++It;
|
||||
}
|
||||
tie(It, E) = UsersOfOverdefinedPHIs.equal_range(PN2);
|
||||
while (It != E) {
|
||||
if (It->second == &I) {
|
||||
UsersOfOverdefinedPHIs.erase(It++);
|
||||
} else
|
||||
++It;
|
||||
}
|
||||
}
|
||||
|
||||
markOverdefined(IV, &I);
|
||||
} else if (V1State.isConstant() && V2State.isConstant()) {
|
||||
markConstant(IV, &I, ConstantExpr::getCompare(I.getPredicate(),
|
||||
V1State.getConstant(),
|
||||
V2State.getConstant()));
|
||||
}
|
||||
}
|
||||
|
||||
void SCCPSolver::visitExtractElementInst(ExtractElementInst &I) {
|
||||
// FIXME : SCCP does not handle vectors properly.
|
||||
markOverdefined(&I);
|
||||
|
@ -394,9 +394,9 @@ void SROA::CanonicalizeAllocaUsers(AllocationInst *AI) {
|
||||
assert(NumElements == 2 && "Unhandled case!");
|
||||
// All users of the GEP must be loads. At each use of the GEP, insert
|
||||
// two loads of the appropriate indexed GEP and select between them.
|
||||
Value *IsOne = BinaryOperator::createSetNE(I.getOperand(),
|
||||
Value *IsOne = new ICmpInst(ICmpInst::ICMP_NE, I.getOperand(),
|
||||
Constant::getNullValue(I.getOperand()->getType()),
|
||||
"isone", GEPI);
|
||||
"isone", GEPI);
|
||||
// Insert the new GEP instructions, which are properly indexed.
|
||||
std::vector<Value*> Indices(GEPI->op_begin()+1, GEPI->op_end());
|
||||
Indices[1] = Constant::getNullValue(Type::IntTy);
|
||||
|
@ -278,7 +278,15 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB) {
|
||||
/// mapping its operands through ValueMap if they are available.
|
||||
Constant *PruningFunctionCloner::
|
||||
ConstantFoldMappedInstruction(const Instruction *I) {
|
||||
if (isa<BinaryOperator>(I) || isa<ShiftInst>(I)) {
|
||||
if (isa<CmpInst>(I)) {
|
||||
if (Constant *Op0 = dyn_cast_or_null<Constant>(MapValue(I->getOperand(0),
|
||||
ValueMap)))
|
||||
if (Constant *Op1 = dyn_cast_or_null<Constant>(MapValue(I->getOperand(1),
|
||||
ValueMap)))
|
||||
return ConstantExpr::getCompare(cast<CmpInst>(I)->getPredicate(), Op0,
|
||||
Op1);
|
||||
return 0;
|
||||
} else if (isa<BinaryOperator>(I) || isa<ShiftInst>(I)) {
|
||||
if (Constant *Op0 = dyn_cast_or_null<Constant>(MapValue(I->getOperand(0),
|
||||
ValueMap)))
|
||||
if (Constant *Op1 = dyn_cast_or_null<Constant>(MapValue(I->getOperand(1),
|
||||
@ -295,7 +303,7 @@ ConstantFoldMappedInstruction(const Instruction *I) {
|
||||
else
|
||||
return 0; // All operands not constant!
|
||||
|
||||
return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Ops);
|
||||
return ConstantFoldInstOperands(I, Ops);
|
||||
}
|
||||
|
||||
/// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto,
|
||||
|
@ -71,6 +71,7 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I) {
|
||||
case 2:
|
||||
Op1 = dyn_cast<Constant>(I->getOperand(1));
|
||||
if (Op1 == 0) return 0; // Not a constant?, can't fold
|
||||
/* FALL THROUGH */
|
||||
case 1:
|
||||
Op0 = dyn_cast<Constant>(I->getOperand(0));
|
||||
if (Op0 == 0) return 0; // Not a constant?, can't fold
|
||||
@ -79,13 +80,14 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I) {
|
||||
}
|
||||
|
||||
if (isa<BinaryOperator>(I) || isa<ShiftInst>(I)) {
|
||||
if (Constant *Op0 = dyn_cast<Constant>(I->getOperand(0)))
|
||||
if (Constant *Op1 = dyn_cast<Constant>(I->getOperand(1)))
|
||||
return ConstantExpr::get(I->getOpcode(), Op0, Op1);
|
||||
return 0; // Operands not constants.
|
||||
return ConstantExpr::get(I->getOpcode(), Op0, Op1);
|
||||
} else if (isa<ICmpInst>(I)) {
|
||||
return ConstantExpr::getICmp(cast<ICmpInst>(I)->getPredicate(), Op0, Op1);
|
||||
} else if (isa<FCmpInst>(I)) {
|
||||
return ConstantExpr::getFCmp(cast<FCmpInst>(I)->getPredicate(), Op0, Op1);
|
||||
}
|
||||
|
||||
// Scan the operand list, checking to see if the are all constants, if so,
|
||||
// Scan the operand list, checking to see if they are all constants, if so,
|
||||
// hand off to ConstantFoldInstOperands.
|
||||
std::vector<Constant*> Ops;
|
||||
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
|
||||
@ -94,7 +96,7 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I) {
|
||||
else
|
||||
return 0; // All operands not constant!
|
||||
|
||||
return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Ops);
|
||||
return ConstantFoldInstOperands(I, Ops);
|
||||
}
|
||||
|
||||
/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
|
||||
@ -103,9 +105,13 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I) {
|
||||
/// attempting to fold instructions like loads and stores, which have no
|
||||
/// constant expression form.
|
||||
///
|
||||
Constant *llvm::ConstantFoldInstOperands(unsigned Opc, const Type *DestTy,
|
||||
Constant *llvm::ConstantFoldInstOperands(const Instruction* I,
|
||||
const std::vector<Constant*> &Ops) {
|
||||
if (Opc >= Instruction::BinaryOpsBegin && Opc < Instruction::BinaryOpsEnd)
|
||||
unsigned Opc = I->getOpcode();
|
||||
const Type *DestTy = I->getType();
|
||||
|
||||
// Handle easy binops first
|
||||
if (isa<BinaryOperator>(I))
|
||||
return ConstantExpr::get(Opc, Ops[0], Ops[1]);
|
||||
|
||||
switch (Opc) {
|
||||
@ -118,6 +124,10 @@ Constant *llvm::ConstantFoldInstOperands(unsigned Opc, const Type *DestTy,
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
case Instruction::ICmp:
|
||||
case Instruction::FCmp:
|
||||
return ConstantExpr::getCompare(cast<CmpInst>(I)->getPredicate(), Ops[0],
|
||||
Ops[1]);
|
||||
case Instruction::Shl:
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr:
|
||||
@ -257,8 +267,8 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB) {
|
||||
} else if (SI->getNumSuccessors() == 2) {
|
||||
// Otherwise, we can fold this switch into a conditional branch
|
||||
// instruction if it has only one non-default destination.
|
||||
Value *Cond = new SetCondInst(Instruction::SetEQ, SI->getCondition(),
|
||||
SI->getSuccessorValue(1), "cond", SI);
|
||||
Value *Cond = new ICmpInst(ICmpInst::ICMP_EQ, SI->getCondition(),
|
||||
SI->getSuccessorValue(1), "cond", SI);
|
||||
// Insert the new branch...
|
||||
new BranchInst(SI->getSuccessor(1), SI->getSuccessor(0), Cond, SI);
|
||||
|
||||
|
@ -517,9 +517,9 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) {
|
||||
EntryBB->getTerminator());
|
||||
|
||||
// Compare the return value to zero.
|
||||
Value *IsNormal = BinaryOperator::createSetEQ(SJRet,
|
||||
Constant::getNullValue(SJRet->getType()),
|
||||
"notunwind", EntryBB->getTerminator());
|
||||
Value *IsNormal = new ICmpInst(ICmpInst::ICMP_EQ, SJRet,
|
||||
Constant::getNullValue(SJRet->getType()),
|
||||
"notunwind", EntryBB->getTerminator());
|
||||
// Nuke the uncond branch.
|
||||
EntryBB->getTerminator()->eraseFromParent();
|
||||
|
||||
@ -551,9 +551,9 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) {
|
||||
}
|
||||
|
||||
// Load the JBList, if it's null, then there was no catch!
|
||||
Value *NotNull = BinaryOperator::createSetNE(BufPtr,
|
||||
Constant::getNullValue(BufPtr->getType()),
|
||||
"notnull", UnwindHandler);
|
||||
Value *NotNull = new ICmpInst(ICmpInst::ICMP_NE, BufPtr,
|
||||
Constant::getNullValue(BufPtr->getType()),
|
||||
"notnull", UnwindHandler);
|
||||
new BranchInst(UnwindBlock, TermBlock, NotNull, UnwindHandler);
|
||||
|
||||
// Create the block to do the longjmp.
|
||||
|
@ -143,8 +143,7 @@ BasicBlock* LowerSwitch::switchConvert(CaseItr Begin, CaseItr End,
|
||||
BasicBlock* NewNode = new BasicBlock("NodeBlock");
|
||||
F->getBasicBlockList().insert(OrigBlock->getNext(), NewNode);
|
||||
|
||||
SetCondInst* Comp = new SetCondInst(Instruction::SetLT, Val, Pivot.first,
|
||||
"Pivot");
|
||||
ICmpInst* Comp = new ICmpInst(ICmpInst::ICMP_ULT, Val, Pivot.first, "Pivot");
|
||||
NewNode->getInstList().push_back(Comp);
|
||||
new BranchInst(LBranch, RBranch, Comp, NewNode);
|
||||
return NewNode;
|
||||
@ -165,8 +164,8 @@ BasicBlock* LowerSwitch::newLeafBlock(Case& Leaf, Value* Val,
|
||||
F->getBasicBlockList().insert(OrigBlock->getNext(), NewLeaf);
|
||||
|
||||
// Make the seteq instruction...
|
||||
SetCondInst* Comp = new SetCondInst(Instruction::SetEQ, Val,
|
||||
Leaf.first, "SwitchLeaf");
|
||||
ICmpInst* Comp = new ICmpInst(ICmpInst::ICMP_EQ, Val,
|
||||
Leaf.first, "SwitchLeaf");
|
||||
NewLeaf->getInstList().push_back(Comp);
|
||||
|
||||
// Make the conditional branch...
|
||||
|
@ -369,12 +369,8 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB,
|
||||
case Instruction::Shl:
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr:
|
||||
case Instruction::SetEQ:
|
||||
case Instruction::SetNE:
|
||||
case Instruction::SetLT:
|
||||
case Instruction::SetGT:
|
||||
case Instruction::SetLE:
|
||||
case Instruction::SetGE:
|
||||
case Instruction::ICmp:
|
||||
case Instruction::FCmp:
|
||||
break; // These are all cheap and non-trapping instructions.
|
||||
}
|
||||
|
||||
@ -390,12 +386,13 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB,
|
||||
return true;
|
||||
}
|
||||
|
||||
// GatherConstantSetEQs - Given a potentially 'or'd together collection of seteq
|
||||
// instructions that compare a value against a constant, return the value being
|
||||
// compared, and stick the constant into the Values vector.
|
||||
// GatherConstantSetEQs - Given a potentially 'or'd together collection of
|
||||
// icmp_eq instructions that compare a value against a constant, return the
|
||||
// value being compared, and stick the constant into the Values vector.
|
||||
static Value *GatherConstantSetEQs(Value *V, std::vector<ConstantInt*> &Values){
|
||||
if (Instruction *Inst = dyn_cast<Instruction>(V))
|
||||
if (Inst->getOpcode() == Instruction::SetEQ) {
|
||||
if (Inst->getOpcode() == Instruction::ICmp &&
|
||||
cast<ICmpInst>(Inst)->getPredicate() == ICmpInst::ICMP_EQ) {
|
||||
if (ConstantInt *C = dyn_cast<ConstantInt>(Inst->getOperand(1))) {
|
||||
Values.push_back(C);
|
||||
return Inst->getOperand(0);
|
||||
@ -417,7 +414,8 @@ static Value *GatherConstantSetEQs(Value *V, std::vector<ConstantInt*> &Values){
|
||||
// being compared, and stick the constant into the Values vector.
|
||||
static Value *GatherConstantSetNEs(Value *V, std::vector<ConstantInt*> &Values){
|
||||
if (Instruction *Inst = dyn_cast<Instruction>(V))
|
||||
if (Inst->getOpcode() == Instruction::SetNE) {
|
||||
if (Inst->getOpcode() == Instruction::ICmp &&
|
||||
cast<ICmpInst>(Inst)->getPredicate() == ICmpInst::ICMP_NE) {
|
||||
if (ConstantInt *C = dyn_cast<ConstantInt>(Inst->getOperand(1))) {
|
||||
Values.push_back(C);
|
||||
return Inst->getOperand(0);
|
||||
@ -503,11 +501,11 @@ static Value *isValueEqualityComparison(TerminatorInst *TI) {
|
||||
}
|
||||
if (BranchInst *BI = dyn_cast<BranchInst>(TI))
|
||||
if (BI->isConditional() && BI->getCondition()->hasOneUse())
|
||||
if (SetCondInst *SCI = dyn_cast<SetCondInst>(BI->getCondition()))
|
||||
if ((SCI->getOpcode() == Instruction::SetEQ ||
|
||||
SCI->getOpcode() == Instruction::SetNE) &&
|
||||
isa<ConstantInt>(SCI->getOperand(1)))
|
||||
return SCI->getOperand(0);
|
||||
if (ICmpInst *ICI = dyn_cast<ICmpInst>(BI->getCondition()))
|
||||
if ((ICI->getPredicate() == ICmpInst::ICMP_EQ ||
|
||||
ICI->getPredicate() == ICmpInst::ICMP_NE) &&
|
||||
isa<ConstantInt>(ICI->getOperand(1)))
|
||||
return ICI->getOperand(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -525,11 +523,11 @@ GetValueEqualityComparisonCases(TerminatorInst *TI,
|
||||
}
|
||||
|
||||
BranchInst *BI = cast<BranchInst>(TI);
|
||||
SetCondInst *SCI = cast<SetCondInst>(BI->getCondition());
|
||||
Cases.push_back(std::make_pair(cast<ConstantInt>(SCI->getOperand(1)),
|
||||
BI->getSuccessor(SCI->getOpcode() ==
|
||||
Instruction::SetNE)));
|
||||
return BI->getSuccessor(SCI->getOpcode() == Instruction::SetEQ);
|
||||
ICmpInst *ICI = cast<ICmpInst>(BI->getCondition());
|
||||
Cases.push_back(std::make_pair(cast<ConstantInt>(ICI->getOperand(1)),
|
||||
BI->getSuccessor(ICI->getPredicate() ==
|
||||
ICmpInst::ICMP_NE)));
|
||||
return BI->getSuccessor(ICI->getPredicate() == ICmpInst::ICMP_EQ);
|
||||
}
|
||||
|
||||
|
||||
@ -847,8 +845,8 @@ static bool HoistThenElseCodeToIf(BranchInst *BI) {
|
||||
BasicBlock *BB2 = BI->getSuccessor(1); // The false destination
|
||||
|
||||
Instruction *I1 = BB1->begin(), *I2 = BB2->begin();
|
||||
if (I1->getOpcode() != I2->getOpcode() || !I1->isIdenticalTo(I2) ||
|
||||
isa<PHINode>(I1) || isa<InvokeInst>(I1))
|
||||
if (I1->getOpcode() != I2->getOpcode() || isa<PHINode>(I1) ||
|
||||
isa<InvokeInst>(I1) || !I1->isIdenticalTo(I2))
|
||||
return false;
|
||||
|
||||
// If we get here, we can hoist at least one instruction.
|
||||
@ -1443,8 +1441,9 @@ bool llvm::SimplifyCFG(BasicBlock *BB) {
|
||||
// predecessor and use logical operations to pick the right destination.
|
||||
BasicBlock *TrueDest = BI->getSuccessor(0);
|
||||
BasicBlock *FalseDest = BI->getSuccessor(1);
|
||||
if (BinaryOperator *Cond = dyn_cast<BinaryOperator>(BI->getCondition()))
|
||||
if (Cond->getParent() == BB && &BB->front() == Cond &&
|
||||
if (Instruction *Cond = dyn_cast<Instruction>(BI->getCondition()))
|
||||
if ((isa<CmpInst>(Cond) || isa<BinaryOperator>(Cond)) &&
|
||||
Cond->getParent() == BB && &BB->front() == Cond &&
|
||||
Cond->getNext() == BI && Cond->hasOneUse() &&
|
||||
TrueDest != BB && FalseDest != BB)
|
||||
for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI!=E; ++PI)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -45,8 +45,8 @@ namespace llvm {
|
||||
const Constant *Mask);
|
||||
Constant *ConstantFoldBinaryInstruction(unsigned Opcode, const Constant *V1,
|
||||
const Constant *V2);
|
||||
Constant *ConstantFoldCompare(unsigned opcode, Constant *C1, Constant *C2,
|
||||
unsigned short predicate);
|
||||
Constant *ConstantFoldCompareInstruction(unsigned short predicate,
|
||||
Constant *C1, Constant *C2);
|
||||
Constant *ConstantFoldGetElementPtr(const Constant *C,
|
||||
const std::vector<Value*> &IdxList);
|
||||
} // End llvm namespace
|
||||
|
@ -45,8 +45,8 @@ namespace llvm {
|
||||
const Constant *Mask);
|
||||
Constant *ConstantFoldBinaryInstruction(unsigned Opcode, const Constant *V1,
|
||||
const Constant *V2);
|
||||
Constant *ConstantFoldCompare(unsigned opcode, Constant *C1, Constant *C2,
|
||||
unsigned short predicate);
|
||||
Constant *ConstantFoldCompareInstruction(unsigned short predicate,
|
||||
Constant *C1, Constant *C2);
|
||||
Constant *ConstantFoldGetElementPtr(const Constant *C,
|
||||
const std::vector<Value*> &IdxList);
|
||||
} // End llvm namespace
|
||||
|
@ -265,12 +265,6 @@ ConstantPacked::~ConstantPacked() {
|
||||
delete [] OperandList;
|
||||
}
|
||||
|
||||
static bool isSetCC(unsigned Opcode) {
|
||||
return Opcode == Instruction::SetEQ || Opcode == Instruction::SetNE ||
|
||||
Opcode == Instruction::SetLT || Opcode == Instruction::SetGT ||
|
||||
Opcode == Instruction::SetLE || Opcode == Instruction::SetGE;
|
||||
}
|
||||
|
||||
// We declare several classes private to this file, so use an anonymous
|
||||
// namespace
|
||||
namespace {
|
||||
@ -290,8 +284,7 @@ class VISIBILITY_HIDDEN BinaryConstantExpr : public ConstantExpr {
|
||||
Use Ops[2];
|
||||
public:
|
||||
BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2)
|
||||
: ConstantExpr(isSetCC(Opcode) ? Type::BoolTy : C1->getType(),
|
||||
Opcode, Ops, 2) {
|
||||
: ConstantExpr(C1->getType(), Opcode, Ops, 2) {
|
||||
Ops[0].init(C1, this);
|
||||
Ops[1].init(C2, this);
|
||||
}
|
||||
@ -448,24 +441,6 @@ Constant *ConstantExpr::getOr(Constant *C1, Constant *C2) {
|
||||
Constant *ConstantExpr::getXor(Constant *C1, Constant *C2) {
|
||||
return get(Instruction::Xor, C1, C2);
|
||||
}
|
||||
Constant *ConstantExpr::getSetEQ(Constant *C1, Constant *C2) {
|
||||
return get(Instruction::SetEQ, C1, C2);
|
||||
}
|
||||
Constant *ConstantExpr::getSetNE(Constant *C1, Constant *C2) {
|
||||
return get(Instruction::SetNE, C1, C2);
|
||||
}
|
||||
Constant *ConstantExpr::getSetLT(Constant *C1, Constant *C2) {
|
||||
return get(Instruction::SetLT, C1, C2);
|
||||
}
|
||||
Constant *ConstantExpr::getSetGT(Constant *C1, Constant *C2) {
|
||||
return get(Instruction::SetGT, C1, C2);
|
||||
}
|
||||
Constant *ConstantExpr::getSetLE(Constant *C1, Constant *C2) {
|
||||
return get(Instruction::SetLE, C1, C2);
|
||||
}
|
||||
Constant *ConstantExpr::getSetGE(Constant *C1, Constant *C2) {
|
||||
return get(Instruction::SetGE, C1, C2);
|
||||
}
|
||||
unsigned ConstantExpr::getPredicate() const {
|
||||
assert(getOpcode() == Instruction::FCmp || getOpcode() == Instruction::ICmp);
|
||||
return dynamic_cast<const CompareConstantExpr*>(this)->predicate;
|
||||
@ -582,6 +557,9 @@ getWithOperands(const std::vector<Constant*> &Ops) const {
|
||||
std::vector<Constant*> ActualOps(Ops.begin()+1, Ops.end());
|
||||
return ConstantExpr::getGetElementPtr(Ops[0], ActualOps);
|
||||
}
|
||||
case Instruction::ICmp:
|
||||
case Instruction::FCmp:
|
||||
return ConstantExpr::getCompare(getPredicate(), Ops[0], Ops[1]);
|
||||
default:
|
||||
assert(getNumOperands() == 2 && "Must be binary operator?");
|
||||
return ConstantExpr::get(getOpcode(), Ops[0], Ops[1]);
|
||||
@ -1657,8 +1635,7 @@ Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode,
|
||||
assert(C1->getType() == C2->getType() &&
|
||||
"Operand types in binary constant expression should match");
|
||||
|
||||
if (ReqTy == C1->getType() || (Instruction::isComparison(Opcode) &&
|
||||
ReqTy == Type::BoolTy))
|
||||
if (ReqTy == C1->getType() || ReqTy == Type::BoolTy)
|
||||
if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2))
|
||||
return FC; // Fold a few common cases...
|
||||
|
||||
@ -1667,11 +1644,23 @@ Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode,
|
||||
return ExprConstants->getOrCreate(ReqTy, Key);
|
||||
}
|
||||
|
||||
Constant *ConstantExpr::getCompareTy(unsigned Opcode, unsigned short predicate,
|
||||
Constant *ConstantExpr::getCompareTy(unsigned short predicate,
|
||||
Constant *C1, Constant *C2) {
|
||||
if (Opcode == Instruction::ICmp)
|
||||
return getICmp(predicate, C1, C2);
|
||||
return getFCmp(predicate, C1, C2);
|
||||
switch (predicate) {
|
||||
default: assert(0 && "Invalid CmpInst predicate");
|
||||
case FCmpInst::FCMP_FALSE: case FCmpInst::FCMP_OEQ: case FCmpInst::FCMP_OGT:
|
||||
case FCmpInst::FCMP_OGE: case FCmpInst::FCMP_OLT: case FCmpInst::FCMP_OLE:
|
||||
case FCmpInst::FCMP_ONE: case FCmpInst::FCMP_ORD: case FCmpInst::FCMP_UNO:
|
||||
case FCmpInst::FCMP_UEQ: case FCmpInst::FCMP_UGT: case FCmpInst::FCMP_UGE:
|
||||
case FCmpInst::FCMP_ULT: case FCmpInst::FCMP_ULE: case FCmpInst::FCMP_UNE:
|
||||
case FCmpInst::FCMP_TRUE:
|
||||
return getFCmp(predicate, C1, C2);
|
||||
case ICmpInst::ICMP_EQ: case ICmpInst::ICMP_NE: case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_UGE: case ICmpInst::ICMP_ULT: case ICmpInst::ICMP_ULE:
|
||||
case ICmpInst::ICMP_SGT: case ICmpInst::ICMP_SGE: case ICmpInst::ICMP_SLT:
|
||||
case ICmpInst::ICMP_SLE:
|
||||
return getICmp(predicate, C1, C2);
|
||||
}
|
||||
}
|
||||
|
||||
Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
|
||||
@ -1718,10 +1707,6 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
|
||||
assert((C1->getType()->isIntegral() || isa<PackedType>(C1->getType())) &&
|
||||
"Tried to create a logical operation on a non-integral type!");
|
||||
break;
|
||||
case Instruction::SetLT: case Instruction::SetGT: case Instruction::SetLE:
|
||||
case Instruction::SetGE: case Instruction::SetEQ: case Instruction::SetNE:
|
||||
assert(C1->getType() == C2->getType() && "Op types should be identical!");
|
||||
break;
|
||||
case Instruction::Shl:
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr:
|
||||
@ -1737,10 +1722,10 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
|
||||
return getTy(C1->getType(), Opcode, C1, C2);
|
||||
}
|
||||
|
||||
Constant *ConstantExpr::getCompare(unsigned Opcode, unsigned short pred,
|
||||
Constant *ConstantExpr::getCompare(unsigned short pred,
|
||||
Constant *C1, Constant *C2) {
|
||||
assert(C1->getType() == C2->getType() && "Op types should be identical!");
|
||||
return getCompareTy(Opcode, pred, C1, C2);
|
||||
return getCompareTy(pred, C1, C2);
|
||||
}
|
||||
|
||||
Constant *ConstantExpr::getSelectTy(const Type *ReqTy, Constant *C,
|
||||
@ -1826,7 +1811,7 @@ ConstantExpr::getICmp(unsigned short pred, Constant* LHS, Constant* RHS) {
|
||||
assert(pred >= ICmpInst::FIRST_ICMP_PREDICATE &&
|
||||
pred <= ICmpInst::LAST_ICMP_PREDICATE && "Invalid ICmp Predicate");
|
||||
|
||||
if (Constant *FC = ConstantFoldCompare(Instruction::ICmp, LHS, RHS, pred))
|
||||
if (Constant *FC = ConstantFoldCompareInstruction(pred, LHS, RHS))
|
||||
return FC; // Fold a few common cases...
|
||||
|
||||
// Look up the constant in the table first to ensure uniqueness
|
||||
@ -1843,7 +1828,7 @@ ConstantExpr::getFCmp(unsigned short pred, Constant* LHS, Constant* RHS) {
|
||||
assert(LHS->getType() == RHS->getType());
|
||||
assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && "Invalid FCmp Predicate");
|
||||
|
||||
if (Constant *FC = ConstantFoldCompare(Instruction::FCmp, LHS, RHS, pred))
|
||||
if (Constant *FC = ConstantFoldCompareInstruction(pred, LHS, RHS))
|
||||
return FC; // Fold a few common cases...
|
||||
|
||||
// Look up the constant in the table first to ensure uniqueness
|
||||
|
@ -106,14 +106,6 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
|
||||
case Or : return "or";
|
||||
case Xor: return "xor";
|
||||
|
||||
// SetCC operators...
|
||||
case SetLE: return "setle";
|
||||
case SetGE: return "setge";
|
||||
case SetLT: return "setlt";
|
||||
case SetGT: return "setgt";
|
||||
case SetEQ: return "seteq";
|
||||
case SetNE: return "setne";
|
||||
|
||||
// Memory instructions...
|
||||
case Malloc: return "malloc";
|
||||
case Free: return "free";
|
||||
@ -176,11 +168,38 @@ bool Instruction::isIdenticalTo(Instruction *I) const {
|
||||
return LI->isVolatile() == cast<LoadInst>(I)->isVolatile();
|
||||
if (const StoreInst *SI = dyn_cast<StoreInst>(this))
|
||||
return SI->isVolatile() == cast<StoreInst>(I)->isVolatile();
|
||||
if (const CmpInst *CI = dyn_cast<CmpInst>(this))
|
||||
return CI->getPredicate() == cast<CmpInst>(I)->getPredicate();
|
||||
if (const CallInst *CI = dyn_cast<CallInst>(this))
|
||||
return CI->isTailCall() == cast<CallInst>(I)->isTailCall();
|
||||
return true;
|
||||
}
|
||||
|
||||
// isSameOperationAs
|
||||
bool Instruction::isSameOperationAs(Instruction *I) const {
|
||||
if (getOpcode() != I->getOpcode() || getType() != I->getType() ||
|
||||
getNumOperands() != I->getNumOperands())
|
||||
return false;
|
||||
|
||||
// We have two instructions of identical opcode and #operands. Check to see
|
||||
// if all operands are the same type
|
||||
for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
|
||||
if (getOperand(i)->getType() != I->getOperand(i)->getType())
|
||||
return false;
|
||||
|
||||
// Check special state that is a part of some instructions.
|
||||
if (const LoadInst *LI = dyn_cast<LoadInst>(this))
|
||||
return LI->isVolatile() == cast<LoadInst>(I)->isVolatile();
|
||||
if (const StoreInst *SI = dyn_cast<StoreInst>(this))
|
||||
return SI->isVolatile() == cast<StoreInst>(I)->isVolatile();
|
||||
if (const CmpInst *CI = dyn_cast<CmpInst>(this))
|
||||
return CI->getPredicate() == cast<CmpInst>(I)->getPredicate();
|
||||
if (const CallInst *CI = dyn_cast<CallInst>(this))
|
||||
return CI->isTailCall() == cast<CallInst>(I)->isTailCall();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// isAssociative - Return true if the instruction is associative:
|
||||
///
|
||||
@ -213,31 +232,12 @@ bool Instruction::isCommutative(unsigned op) {
|
||||
case And:
|
||||
case Or:
|
||||
case Xor:
|
||||
case SetEQ:
|
||||
case SetNE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// isComparison - Return true if the instruction is a Set* instruction:
|
||||
///
|
||||
bool Instruction::isComparison(unsigned op) {
|
||||
switch (op) {
|
||||
case SetEQ:
|
||||
case SetNE:
|
||||
case SetLT:
|
||||
case SetGT:
|
||||
case SetLE:
|
||||
case SetGE:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// isTrappingInstruction - Return true if the instruction may trap.
|
||||
///
|
||||
bool Instruction::isTrapping(unsigned op) {
|
||||
|
@ -1068,9 +1068,6 @@ void BinaryOperator::init(BinaryOps iType)
|
||||
cast<PackedType>(getType())->getElementType()->isIntegral())) &&
|
||||
"Tried to create a logical operation on a non-integral type!");
|
||||
break;
|
||||
case SetLT: case SetGT: case SetLE:
|
||||
case SetGE: case SetEQ: case SetNE:
|
||||
assert(getType() == Type::BoolTy && "Setcc must return bool!");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1082,15 +1079,7 @@ BinaryOperator *BinaryOperator::create(BinaryOps Op, Value *S1, Value *S2,
|
||||
Instruction *InsertBefore) {
|
||||
assert(S1->getType() == S2->getType() &&
|
||||
"Cannot create binary operator with two operands of differing type!");
|
||||
switch (Op) {
|
||||
// Binary comparison operators...
|
||||
case SetLT: case SetGT: case SetLE:
|
||||
case SetGE: case SetEQ: case SetNE:
|
||||
return new SetCondInst(Op, S1, S2, Name, InsertBefore);
|
||||
|
||||
default:
|
||||
return new BinaryOperator(Op, S1, S2, S1->getType(), Name, InsertBefore);
|
||||
}
|
||||
return new BinaryOperator(Op, S1, S2, S1->getType(), Name, InsertBefore);
|
||||
}
|
||||
|
||||
BinaryOperator *BinaryOperator::create(BinaryOps Op, Value *S1, Value *S2,
|
||||
@ -1210,14 +1199,8 @@ const Value *BinaryOperator::getNotArgument(const Value *BinOp) {
|
||||
// order dependent (SetLT f.e.) the opcode is changed.
|
||||
//
|
||||
bool BinaryOperator::swapOperands() {
|
||||
if (isCommutative())
|
||||
; // If the instruction is commutative, it is safe to swap the operands
|
||||
else if (SetCondInst *SCI = dyn_cast<SetCondInst>(this))
|
||||
/// FIXME: SetCC instructions shouldn't all have different opcodes.
|
||||
setOpcode(SCI->getSwappedCondition());
|
||||
else
|
||||
return true; // Can't commute operands
|
||||
|
||||
if (!isCommutative())
|
||||
return true; // Can't commute operands
|
||||
std::swap(Ops[0], Ops[1]);
|
||||
return false;
|
||||
}
|
||||
@ -1925,58 +1908,6 @@ BitCastInst::BitCastInst(
|
||||
assert(checkCast(getOpcode(), S, Ty) && "Illegal BitCast");
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SetCondInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
SetCondInst::SetCondInst(BinaryOps Opcode, Value *S1, Value *S2,
|
||||
const std::string &Name, Instruction *InsertBefore)
|
||||
: BinaryOperator(Opcode, S1, S2, Type::BoolTy, Name, InsertBefore) {
|
||||
|
||||
// Make sure it's a valid type... getInverseCondition will assert out if not.
|
||||
assert(getInverseCondition(Opcode));
|
||||
}
|
||||
|
||||
SetCondInst::SetCondInst(BinaryOps Opcode, Value *S1, Value *S2,
|
||||
const std::string &Name, BasicBlock *InsertAtEnd)
|
||||
: BinaryOperator(Opcode, S1, S2, Type::BoolTy, Name, InsertAtEnd) {
|
||||
|
||||
// Make sure it's a valid type... getInverseCondition will assert out if not.
|
||||
assert(getInverseCondition(Opcode));
|
||||
}
|
||||
|
||||
// getInverseCondition - Return the inverse of the current condition opcode.
|
||||
// For example seteq -> setne, setgt -> setle, setlt -> setge, etc...
|
||||
//
|
||||
Instruction::BinaryOps SetCondInst::getInverseCondition(BinaryOps Opcode) {
|
||||
switch (Opcode) {
|
||||
default:
|
||||
assert(0 && "Unknown setcc opcode!");
|
||||
case SetEQ: return SetNE;
|
||||
case SetNE: return SetEQ;
|
||||
case SetGT: return SetLE;
|
||||
case SetLT: return SetGE;
|
||||
case SetGE: return SetLT;
|
||||
case SetLE: return SetGT;
|
||||
}
|
||||
}
|
||||
|
||||
// getSwappedCondition - Return the condition opcode that would be the result
|
||||
// of exchanging the two operands of the setcc instruction without changing
|
||||
// the result produced. Thus, seteq->seteq, setle->setge, setlt->setgt, etc.
|
||||
//
|
||||
Instruction::BinaryOps SetCondInst::getSwappedCondition(BinaryOps Opcode) {
|
||||
switch (Opcode) {
|
||||
default: assert(0 && "Unknown setcc instruction!");
|
||||
case SetEQ: case SetNE: return Opcode;
|
||||
case SetGT: return SetLT;
|
||||
case SetLT: return SetGT;
|
||||
case SetGE: return SetLE;
|
||||
case SetLE: return SetGE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CmpInst Classes
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -2111,7 +2042,7 @@ ICmpInst::Predicate ICmpInst::getInversePredicate(Predicate pred) {
|
||||
|
||||
ICmpInst::Predicate ICmpInst::getSwappedPredicate(Predicate pred) {
|
||||
switch (pred) {
|
||||
default: assert(! "Unknown setcc instruction!");
|
||||
default: assert(! "Unknown icmp predicate!");
|
||||
case ICMP_EQ: case ICMP_NE:
|
||||
return pred;
|
||||
case ICMP_SGT: return ICMP_SLT;
|
||||
@ -2125,6 +2056,30 @@ ICmpInst::Predicate ICmpInst::getSwappedPredicate(Predicate pred) {
|
||||
}
|
||||
}
|
||||
|
||||
ICmpInst::Predicate ICmpInst::getSignedPredicate(Predicate pred) {
|
||||
switch (pred) {
|
||||
default: assert(! "Unknown icmp predicate!");
|
||||
case ICMP_EQ: case ICMP_NE:
|
||||
case ICMP_SGT: case ICMP_SLT: case ICMP_SGE: case ICMP_SLE:
|
||||
return pred;
|
||||
case ICMP_UGT: return ICMP_SGT;
|
||||
case ICMP_ULT: return ICMP_SLT;
|
||||
case ICMP_UGE: return ICMP_SGE;
|
||||
case ICMP_ULE: return ICMP_SLE;
|
||||
}
|
||||
}
|
||||
|
||||
bool ICmpInst::isSignedPredicate(Predicate pred) {
|
||||
switch (pred) {
|
||||
default: assert(! "Unknown icmp predicate!");
|
||||
case ICMP_SGT: case ICMP_SLT: case ICMP_SGE: case ICMP_SLE:
|
||||
return true;
|
||||
case ICMP_EQ: case ICMP_NE: case ICMP_UGT: case ICMP_ULT:
|
||||
case ICMP_UGE: case ICMP_ULE:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
FCmpInst::Predicate FCmpInst::getInversePredicate(Predicate pred) {
|
||||
switch (pred) {
|
||||
default:
|
||||
@ -2150,7 +2105,7 @@ FCmpInst::Predicate FCmpInst::getInversePredicate(Predicate pred) {
|
||||
|
||||
FCmpInst::Predicate FCmpInst::getSwappedPredicate(Predicate pred) {
|
||||
switch (pred) {
|
||||
default: assert(!"Unknown setcc instruction!");
|
||||
default: assert(!"Unknown fcmp predicate!");
|
||||
case FCMP_FALSE: case FCMP_TRUE:
|
||||
case FCMP_OEQ: case FCMP_ONE:
|
||||
case FCMP_UEQ: case FCMP_UNE:
|
||||
@ -2167,6 +2122,40 @@ FCmpInst::Predicate FCmpInst::getSwappedPredicate(Predicate pred) {
|
||||
}
|
||||
}
|
||||
|
||||
bool CmpInst::isUnsigned(unsigned short predicate) {
|
||||
switch (predicate) {
|
||||
default: return false;
|
||||
case ICmpInst::ICMP_ULT: case ICmpInst::ICMP_ULE: case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_UGE: return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CmpInst::isSigned(unsigned short predicate){
|
||||
switch (predicate) {
|
||||
default: return false;
|
||||
case ICmpInst::ICMP_SLT: case ICmpInst::ICMP_SLE: case ICmpInst::ICMP_SGT:
|
||||
case ICmpInst::ICMP_SGE: return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CmpInst::isOrdered(unsigned short predicate) {
|
||||
switch (predicate) {
|
||||
default: return false;
|
||||
case FCmpInst::FCMP_OEQ: case FCmpInst::FCMP_ONE: case FCmpInst::FCMP_OGT:
|
||||
case FCmpInst::FCMP_OLT: case FCmpInst::FCMP_OGE: case FCmpInst::FCMP_OLE:
|
||||
case FCmpInst::FCMP_ORD: return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CmpInst::isUnordered(unsigned short predicate) {
|
||||
switch (predicate) {
|
||||
default: return false;
|
||||
case FCmpInst::FCMP_UEQ: case FCmpInst::FCMP_UNE: case FCmpInst::FCMP_UGT:
|
||||
case FCmpInst::FCMP_ULT: case FCmpInst::FCMP_UGE: case FCmpInst::FCMP_ULE:
|
||||
case FCmpInst::FCMP_UNO: return true;
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SwitchInst Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -230,7 +230,7 @@ void SymbolTable::insertEntry(const std::string &Name, const Type *VTy,
|
||||
}
|
||||
|
||||
|
||||
// insertEntry - Insert a value into the symbol table with the specified
|
||||
// insertEntry - Insert a type into the symbol table with the specified
|
||||
// name...
|
||||
//
|
||||
void SymbolTable::insert(const std::string& Name, const Type* T) {
|
||||
|
@ -719,10 +719,6 @@ void Verifier::visitBinaryOperator(BinaryOperator &B) {
|
||||
Assert1(B.getType() == B.getOperand(0)->getType(),
|
||||
"Logical operators must have same type for operands and result!",
|
||||
&B);
|
||||
} else if (isa<SetCondInst>(B)) {
|
||||
// Check that setcc instructions return bool
|
||||
Assert1(B.getType() == Type::BoolTy,
|
||||
"setcc instructions must return boolean values!", &B);
|
||||
} else {
|
||||
// Arithmetic operators only work on integer or fp values
|
||||
Assert1(B.getType() == B.getOperand(0)->getType(),
|
||||
|
@ -721,7 +721,7 @@ StackerCompiler::handle_if( char* ifTrue, char* ifFalse )
|
||||
LoadInst* cond = cast<LoadInst>( pop_integer(bb) );
|
||||
|
||||
// Compare the condition against 0
|
||||
SetCondInst* cond_inst = new SetCondInst( Instruction::SetNE, cond,
|
||||
ICmpInst* cond_inst = new ICmpInst( ICmpInst::ICMP_NE, cond,
|
||||
ConstantInt::get( Type::LongTy, 0) );
|
||||
bb->getInstList().push_back( cond_inst );
|
||||
|
||||
@ -735,7 +735,7 @@ StackerCompiler::handle_if( char* ifTrue, char* ifFalse )
|
||||
BasicBlock* false_bb = 0;
|
||||
if ( ifFalse ) false_bb = new BasicBlock((echo?"else":""));
|
||||
|
||||
// Create a branch on the SetCond
|
||||
// Create a branch on the ICmp
|
||||
BranchInst* br_inst = new BranchInst( true_bb,
|
||||
( ifFalse ? false_bb : exit_bb ), cond_inst );
|
||||
bb->getInstList().push_back( br_inst );
|
||||
@ -805,8 +805,8 @@ StackerCompiler::handle_while( char* todo )
|
||||
LoadInst* cond = cast<LoadInst>( stack_top(test) );
|
||||
|
||||
// Compare the condition against 0
|
||||
SetCondInst* cond_inst = new SetCondInst(
|
||||
Instruction::SetNE, cond, ConstantInt::get( Type::LongTy, 0));
|
||||
ICmpInst* cond_inst = new ICmpInst(
|
||||
ICmpInst::ICMP_NE, cond, ConstantInt::get( Type::LongTy, 0));
|
||||
test->getInstList().push_back( cond_inst );
|
||||
|
||||
// Add the branch instruction
|
||||
@ -920,8 +920,8 @@ StackerCompiler::handle_word( int tkn )
|
||||
if (echo) bb->setName("LESS");
|
||||
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
|
||||
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
|
||||
SetCondInst* cond_inst =
|
||||
new SetCondInst( Instruction::SetLT, op1, op2 );
|
||||
ICmpInst* cond_inst =
|
||||
new ICmpInst( ICmpInst::ICMP_SLT, op1, op2 );
|
||||
bb->getInstList().push_back( cond_inst );
|
||||
push_value( bb, cond_inst );
|
||||
break;
|
||||
@ -931,8 +931,8 @@ StackerCompiler::handle_word( int tkn )
|
||||
if (echo) bb->setName("MORE");
|
||||
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
|
||||
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
|
||||
SetCondInst* cond_inst =
|
||||
new SetCondInst( Instruction::SetGT, op1, op2 );
|
||||
ICmpInst* cond_inst =
|
||||
new ICmpInst( ICmpInst::ICMP_SGT, op1, op2 );
|
||||
bb->getInstList().push_back( cond_inst );
|
||||
push_value( bb, cond_inst );
|
||||
break;
|
||||
@ -942,8 +942,8 @@ StackerCompiler::handle_word( int tkn )
|
||||
if (echo) bb->setName("LE");
|
||||
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
|
||||
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
|
||||
SetCondInst* cond_inst =
|
||||
new SetCondInst( Instruction::SetLE, op1, op2 );
|
||||
ICmpInst* cond_inst =
|
||||
new ICmpInst( ICmpInst::ICMP_SLE, op1, op2 );
|
||||
bb->getInstList().push_back( cond_inst );
|
||||
push_value( bb, cond_inst );
|
||||
break;
|
||||
@ -953,8 +953,8 @@ StackerCompiler::handle_word( int tkn )
|
||||
if (echo) bb->setName("GE");
|
||||
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
|
||||
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
|
||||
SetCondInst* cond_inst =
|
||||
new SetCondInst( Instruction::SetGE, op1, op2 );
|
||||
ICmpInst* cond_inst =
|
||||
new ICmpInst( ICmpInst::ICMP_SGE, op1, op2 );
|
||||
bb->getInstList().push_back( cond_inst );
|
||||
push_value( bb, cond_inst );
|
||||
break;
|
||||
@ -964,8 +964,8 @@ StackerCompiler::handle_word( int tkn )
|
||||
if (echo) bb->setName("NE");
|
||||
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
|
||||
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
|
||||
SetCondInst* cond_inst =
|
||||
new SetCondInst( Instruction::SetNE, op1, op2 );
|
||||
ICmpInst* cond_inst =
|
||||
new ICmpInst( ICmpInst::ICMP_NE, op1, op2 );
|
||||
bb->getInstList().push_back( cond_inst );
|
||||
push_value( bb, cond_inst );
|
||||
break;
|
||||
@ -975,8 +975,8 @@ StackerCompiler::handle_word( int tkn )
|
||||
if (echo) bb->setName("EQ");
|
||||
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
|
||||
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
|
||||
SetCondInst* cond_inst =
|
||||
new SetCondInst( Instruction::SetEQ, op1, op2 );
|
||||
ICmpInst* cond_inst =
|
||||
new ICmpInst( ICmpInst::ICMP_EQ, op1, op2 );
|
||||
bb->getInstList().push_back( cond_inst );
|
||||
push_value( bb, cond_inst );
|
||||
break;
|
||||
@ -1102,8 +1102,8 @@ StackerCompiler::handle_word( int tkn )
|
||||
LoadInst* op1 = cast<LoadInst>(stack_top(bb));
|
||||
|
||||
// Determine if its negative
|
||||
SetCondInst* cond_inst =
|
||||
new SetCondInst( Instruction::SetLT, op1, Zero );
|
||||
ICmpInst* cond_inst =
|
||||
new ICmpInst( ICmpInst::ICMP_SLT, op1, Zero );
|
||||
bb->getInstList().push_back( cond_inst );
|
||||
|
||||
// Create a block for storing the result
|
||||
@ -1112,7 +1112,7 @@ StackerCompiler::handle_word( int tkn )
|
||||
// Create a block for making it a positive value
|
||||
BasicBlock* pos_bb = new BasicBlock((echo?"neg":""));
|
||||
|
||||
// Create the branch on the SetCond
|
||||
// Create the branch on the ICmp
|
||||
BranchInst* br_inst = new BranchInst( pos_bb, exit_bb, cond_inst );
|
||||
bb->getInstList().push_back( br_inst );
|
||||
|
||||
@ -1143,11 +1143,11 @@ StackerCompiler::handle_word( int tkn )
|
||||
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
|
||||
|
||||
// Compare them
|
||||
SetCondInst* cond_inst =
|
||||
new SetCondInst( Instruction::SetLT, op1, op2);
|
||||
ICmpInst* cond_inst =
|
||||
new ICmpInst( ICmpInst::ICMP_SLT, op1, op2);
|
||||
bb->getInstList().push_back( cond_inst );
|
||||
|
||||
// Create a branch on the SetCond
|
||||
// Create a branch on the ICmp
|
||||
BranchInst* br_inst =
|
||||
new BranchInst( op1_block, op2_block, cond_inst );
|
||||
bb->getInstList().push_back( br_inst );
|
||||
@ -1175,8 +1175,8 @@ StackerCompiler::handle_word( int tkn )
|
||||
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
|
||||
|
||||
// Compare them
|
||||
SetCondInst* cond_inst =
|
||||
new SetCondInst( Instruction::SetGT, op1, op2);
|
||||
ICmpInst* cond_inst =
|
||||
new ICmpInst( ICmpInst::ICMP_SGT, op1, op2);
|
||||
bb->getInstList().push_back( cond_inst );
|
||||
|
||||
// Create an exit block
|
||||
@ -1192,7 +1192,7 @@ StackerCompiler::handle_word( int tkn )
|
||||
push_value(op2_block, op2);
|
||||
op2_block->getInstList().push_back( new BranchInst( exit_bb ) );
|
||||
|
||||
// Create a banch on the SetCond
|
||||
// Create a banch on the ICmp
|
||||
BranchInst* br_inst =
|
||||
new BranchInst( op1_block, op2_block, cond_inst );
|
||||
bb->getInstList().push_back( br_inst );
|
||||
|
@ -1,5 +1,4 @@
|
||||
// RUN: %llvmgcc -O3 -S %s -o - | grep llvm.isunordered &&
|
||||
// RUN: %llvmgcc -O3 -S %s -o - | grep xor
|
||||
// RUN: %llvmgcc -O3 -S %s -o - | grep 'fcmp ord float %X, %Y'
|
||||
|
||||
int test2(float X, float Y) {
|
||||
return !__builtin_isunordered(X, Y);
|
||||
|
@ -1,8 +1,8 @@
|
||||
; These tests have an infinite trip count. We obviously shouldn't remove the
|
||||
; loops! :)
|
||||
;
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -indvars -adce -simplifycfg | llvm-dis | grep set | wc -l > %t2
|
||||
; RUN: llvm-upgrade < %s | llvm-as | llvm-dis | grep set | wc -l > %t1
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -indvars -adce -simplifycfg | llvm-dis | grep icmp | wc -l > %t2
|
||||
; RUN: llvm-upgrade < %s | llvm-as | llvm-dis | grep icmp | wc -l > %t1
|
||||
; RUN: diff %t1 %t2
|
||||
|
||||
int %infinite_linear() { ;; test for (i = 1; i != 100; i += 2)
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -instcombine | llvm-dis | grep 'setlt'
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -instcombine | llvm-dis|grep 'icmp slt'
|
||||
; ModuleID = 'visible.bc'
|
||||
target datalayout = "e-p:32:32"
|
||||
target endian = little
|
||||
|
165
test/Transforms/InstCombine/2006-12-10-ICmp-GEP-GEP.ll
Normal file
165
test/Transforms/InstCombine/2006-12-10-ICmp-GEP-GEP.ll
Normal file
@ -0,0 +1,165 @@
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -instcombine | llvm-dis | \
|
||||
; RUN: grep -v 'icmp ult int'
|
||||
; ModuleID = 'good.bc'
|
||||
target datalayout = "e-p:32:32"
|
||||
target endian = little
|
||||
target pointersize = 32
|
||||
target triple = "i686-pc-linux-gnu"
|
||||
%struct.edgeBox = type { short, short, short, short, short, short }
|
||||
%qsz = external global int ; <int*> [#uses=12]
|
||||
%thresh = external global int ; <int*> [#uses=2]
|
||||
%mthresh = external global int ; <int*> [#uses=1]
|
||||
|
||||
implementation ; Functions:
|
||||
|
||||
int %qsorte(sbyte* %base, int %n, int %size) {
|
||||
entry:
|
||||
%tmp = setgt int %n, 1 ; <bool> [#uses=1]
|
||||
br bool %tmp, label %cond_next, label %return
|
||||
|
||||
cond_next: ; preds = %entry
|
||||
store int %size, int* %qsz
|
||||
%tmp3 = shl int %size, ubyte 2 ; <int> [#uses=1]
|
||||
store int %tmp3, int* %thresh
|
||||
%tmp4 = load int* %qsz ; <int> [#uses=1]
|
||||
%tmp5 = mul int %tmp4, 6 ; <int> [#uses=1]
|
||||
store int %tmp5, int* %mthresh
|
||||
%tmp6 = load int* %qsz ; <int> [#uses=1]
|
||||
%tmp8 = mul int %tmp6, %n ; <int> [#uses=1]
|
||||
%tmp9 = getelementptr sbyte* %base, int %tmp8 ; <sbyte*> [#uses=3]
|
||||
%tmp11 = setgt int %n, 3 ; <bool> [#uses=1]
|
||||
br bool %tmp11, label %cond_true12, label %bb30
|
||||
|
||||
cond_true12: ; preds = %cond_next
|
||||
%tmp156 = call int %qste( sbyte* %base, sbyte* %tmp9 ) ; <int> [#uses=0]
|
||||
%tmp16 = load int* %thresh ; <int> [#uses=1]
|
||||
%tmp18 = getelementptr sbyte* %base, int %tmp16 ; <sbyte*> [#uses=2]
|
||||
%tmp3117 = load int* %qsz ; <int> [#uses=1]
|
||||
%tmp3318 = getelementptr sbyte* %base, int %tmp3117 ; <sbyte*> [#uses=2]
|
||||
%tmp3621 = setlt sbyte* %tmp3318, %tmp18 ; <bool> [#uses=1]
|
||||
br bool %tmp3621, label %bb, label %bb37
|
||||
|
||||
bb: ; preds = %bb30, %cond_true12
|
||||
%hi.0.0 = phi sbyte* [ %tmp18, %cond_true12 ], [ %hi.0, %bb30 ] ; <sbyte*> [#uses=4]
|
||||
%j.1.0 = phi sbyte* [ %base, %cond_true12 ], [ %j.1, %bb30 ] ; <sbyte*> [#uses=4]
|
||||
%tmp33.0 = phi sbyte* [ %tmp3318, %cond_true12 ], [ %tmp33, %bb30 ] ; <sbyte*> [#uses=6]
|
||||
%tmp3 = bitcast sbyte* %j.1.0 to %struct.edgeBox* ; <%struct.edgeBox*> [#uses=1]
|
||||
%tmp4 = bitcast sbyte* %tmp33.0 to %struct.edgeBox* ; <%struct.edgeBox*> [#uses=1]
|
||||
%tmp255 = call int %comparee( %struct.edgeBox* %tmp3, %struct.edgeBox* %tmp4 ) ; <int> [#uses=1]
|
||||
%tmp26 = setgt int %tmp255, 0 ; <bool> [#uses=1]
|
||||
br bool %tmp26, label %cond_true27, label %bb30
|
||||
|
||||
cond_true27: ; preds = %bb
|
||||
br label %bb30
|
||||
|
||||
bb30: ; preds = %cond_true27, %bb, %cond_next
|
||||
%hi.0.3 = phi sbyte* [ %hi.0.0, %cond_true27 ], [ %hi.0.0, %bb ], [ undef, %cond_next ] ; <sbyte*> [#uses=0]
|
||||
%j.1.3 = phi sbyte* [ %j.1.0, %cond_true27 ], [ %j.1.0, %bb ], [ undef, %cond_next ] ; <sbyte*> [#uses=0]
|
||||
%tmp33.3 = phi sbyte* [ %tmp33.0, %cond_true27 ], [ %tmp33.0, %bb ], [ undef, %cond_next ] ; <sbyte*> [#uses=0]
|
||||
%hi.0 = phi sbyte* [ %tmp9, %cond_next ], [ %hi.0.0, %bb ], [ %hi.0.0, %cond_true27 ] ; <sbyte*> [#uses=2]
|
||||
%lo.1 = phi sbyte* [ %tmp33.0, %cond_true27 ], [ %tmp33.0, %bb ], [ %base, %cond_next ] ; <sbyte*> [#uses=1]
|
||||
%j.1 = phi sbyte* [ %tmp33.0, %cond_true27 ], [ %j.1.0, %bb ], [ %base, %cond_next ] ; <sbyte*> [#uses=2]
|
||||
%tmp31 = load int* %qsz ; <int> [#uses=1]
|
||||
%tmp33 = getelementptr sbyte* %lo.1, int %tmp31 ; <sbyte*> [#uses=2]
|
||||
%tmp36 = setlt sbyte* %tmp33, %hi.0 ; <bool> [#uses=1]
|
||||
br bool %tmp36, label %bb, label %bb37
|
||||
|
||||
bb37: ; preds = %bb30, %cond_true12
|
||||
%j.1.1 = phi sbyte* [ %j.1, %bb30 ], [ %base, %cond_true12 ] ; <sbyte*> [#uses=4]
|
||||
%tmp40 = seteq sbyte* %j.1.1, %base ; <bool> [#uses=1]
|
||||
br bool %tmp40, label %bb115, label %cond_true41
|
||||
|
||||
cond_true41: ; preds = %bb37
|
||||
%tmp43 = load int* %qsz ; <int> [#uses=1]
|
||||
%tmp45 = getelementptr sbyte* %base, int %tmp43 ; <sbyte*> [#uses=2]
|
||||
%tmp6030 = setlt sbyte* %base, %tmp45 ; <bool> [#uses=1]
|
||||
br bool %tmp6030, label %bb46, label %bb115
|
||||
|
||||
bb46: ; preds = %bb46, %cond_true41
|
||||
%j.2.0 = phi sbyte* [ %j.1.1, %cond_true41 ], [ %tmp52, %bb46 ] ; <sbyte*> [#uses=3]
|
||||
%i.2.0 = phi sbyte* [ %base, %cond_true41 ], [ %tmp56, %bb46 ] ; <sbyte*> [#uses=3]
|
||||
%tmp = load sbyte* %j.2.0 ; <sbyte> [#uses=2]
|
||||
%tmp49 = load sbyte* %i.2.0 ; <sbyte> [#uses=1]
|
||||
store sbyte %tmp49, sbyte* %j.2.0
|
||||
%tmp52 = getelementptr sbyte* %j.2.0, int 1 ; <sbyte*> [#uses=2]
|
||||
store sbyte %tmp, sbyte* %i.2.0
|
||||
%tmp56 = getelementptr sbyte* %i.2.0, int 1 ; <sbyte*> [#uses=3]
|
||||
%tmp60 = setlt sbyte* %tmp56, %tmp45 ; <bool> [#uses=1]
|
||||
br bool %tmp60, label %bb46, label %bb115
|
||||
|
||||
bb66: ; preds = %bb115, %bb66
|
||||
%hi.3 = phi sbyte* [ %tmp118, %bb115 ], [ %tmp70, %bb66 ] ; <sbyte*> [#uses=2]
|
||||
%tmp67 = load int* %qsz ; <int> [#uses=2]
|
||||
%tmp68 = sub int 0, %tmp67 ; <int> [#uses=1]
|
||||
%tmp70 = getelementptr sbyte* %hi.3, int %tmp68 ; <sbyte*> [#uses=2]
|
||||
%tmp = bitcast sbyte* %tmp70 to %struct.edgeBox* ; <%struct.edgeBox*> [#uses=1]
|
||||
%tmp1 = bitcast sbyte* %tmp118 to %struct.edgeBox* ; <%struct.edgeBox*> [#uses=1]
|
||||
%tmp732 = call int %comparee( %struct.edgeBox* %tmp, %struct.edgeBox* %tmp1 ) ; <int> [#uses=1]
|
||||
%tmp74 = setgt int %tmp732, 0 ; <bool> [#uses=1]
|
||||
br bool %tmp74, label %bb66, label %bb75
|
||||
|
||||
bb75: ; preds = %bb66
|
||||
%tmp76 = load int* %qsz ; <int> [#uses=1]
|
||||
%tmp70.sum = sub int %tmp76, %tmp67 ; <int> [#uses=1]
|
||||
%tmp78 = getelementptr sbyte* %hi.3, int %tmp70.sum ; <sbyte*> [#uses=3]
|
||||
%tmp81 = seteq sbyte* %tmp78, %tmp118 ; <bool> [#uses=1]
|
||||
br bool %tmp81, label %bb115, label %cond_true82
|
||||
|
||||
cond_true82: ; preds = %bb75
|
||||
%tmp83 = load int* %qsz ; <int> [#uses=1]
|
||||
%tmp118.sum = add int %tmp116, %tmp83 ; <int> [#uses=1]
|
||||
%tmp85 = getelementptr sbyte* %min.1, int %tmp118.sum ; <sbyte*> [#uses=1]
|
||||
%tmp10937 = getelementptr sbyte* %tmp85, int -1 ; <sbyte*> [#uses=3]
|
||||
%tmp11239 = setlt sbyte* %tmp10937, %tmp118 ; <bool> [#uses=1]
|
||||
br bool %tmp11239, label %bb115, label %bb86
|
||||
|
||||
bb86: ; preds = %bb104, %cond_true82
|
||||
%tmp109.0 = phi sbyte* [ %tmp10937, %cond_true82 ], [ %tmp109, %bb104 ] ; <sbyte*> [#uses=5]
|
||||
%i.5.2 = phi sbyte* [ %i.5.3, %cond_true82 ], [ %i.5.1, %bb104 ] ; <sbyte*> [#uses=0]
|
||||
%tmp100.2 = phi sbyte* [ %tmp100.3, %cond_true82 ], [ %tmp100.1, %bb104 ] ; <sbyte*> [#uses=0]
|
||||
%tmp88 = load sbyte* %tmp109.0 ; <sbyte> [#uses=2]
|
||||
%tmp9746 = load int* %qsz ; <int> [#uses=1]
|
||||
%tmp9847 = sub int 0, %tmp9746 ; <int> [#uses=1]
|
||||
%tmp10048 = getelementptr sbyte* %tmp109.0, int %tmp9847 ; <sbyte*> [#uses=3]
|
||||
%tmp10350 = setlt sbyte* %tmp10048, %tmp78 ; <bool> [#uses=1]
|
||||
br bool %tmp10350, label %bb104, label %bb91
|
||||
|
||||
bb91: ; preds = %bb91, %bb86
|
||||
%i.5.0 = phi sbyte* [ %tmp109.0, %bb86 ], [ %tmp100.0, %bb91 ] ; <sbyte*> [#uses=1]
|
||||
%tmp100.0 = phi sbyte* [ %tmp10048, %bb86 ], [ %tmp100, %bb91 ] ; <sbyte*> [#uses=4]
|
||||
%tmp93 = load sbyte* %tmp100.0 ; <sbyte> [#uses=1]
|
||||
store sbyte %tmp93, sbyte* %i.5.0
|
||||
%tmp97 = load int* %qsz ; <int> [#uses=1]
|
||||
%tmp98 = sub int 0, %tmp97 ; <int> [#uses=1]
|
||||
%tmp100 = getelementptr sbyte* %tmp100.0, int %tmp98 ; <sbyte*> [#uses=3]
|
||||
%tmp103 = setlt sbyte* %tmp100, %tmp78 ; <bool> [#uses=1]
|
||||
br bool %tmp103, label %bb104, label %bb91
|
||||
|
||||
bb104: ; preds = %bb91, %bb86
|
||||
%i.5.1 = phi sbyte* [ %tmp109.0, %bb86 ], [ %tmp100.0, %bb91 ] ; <sbyte*> [#uses=4]
|
||||
%tmp100.1 = phi sbyte* [ %tmp10048, %bb86 ], [ %tmp100, %bb91 ] ; <sbyte*> [#uses=3]
|
||||
store sbyte %tmp88, sbyte* %i.5.1
|
||||
%tmp109 = getelementptr sbyte* %tmp109.0, int -1 ; <sbyte*> [#uses=3]
|
||||
%tmp112 = setlt sbyte* %tmp109, %tmp118 ; <bool> [#uses=1]
|
||||
br bool %tmp112, label %bb115, label %bb86
|
||||
|
||||
bb115: ; preds = %bb104, %cond_true82, %bb75, %bb46, %cond_true41, %bb37
|
||||
%tmp109.1 = phi sbyte* [ undef, %bb37 ], [ %tmp109.1, %bb75 ], [ %tmp10937, %cond_true82 ], [ %tmp109, %bb104 ], [ undef, %bb46 ], [ undef, %cond_true41 ] ; <sbyte*> [#uses=1]
|
||||
%i.5.3 = phi sbyte* [ undef, %bb37 ], [ %i.5.3, %bb75 ], [ %i.5.3, %cond_true82 ], [ %i.5.1, %bb104 ], [ undef, %bb46 ], [ undef, %cond_true41 ] ; <sbyte*> [#uses=3]
|
||||
%tmp100.3 = phi sbyte* [ undef, %bb37 ], [ %tmp100.3, %bb75 ], [ %tmp100.3, %cond_true82 ], [ %tmp100.1, %bb104 ], [ undef, %bb46 ], [ undef, %cond_true41 ] ; <sbyte*> [#uses=3]
|
||||
%min.1 = phi sbyte* [ %tmp118, %bb104 ], [ %tmp118, %bb75 ], [ %base, %bb37 ], [ %base, %bb46 ], [ %base, %cond_true41 ], [ %tmp118, %cond_true82 ] ; <sbyte*> [#uses=2]
|
||||
%j.5 = phi sbyte* [ %tmp100.1, %bb104 ], [ %j.5, %bb75 ], [ %tmp52, %bb46 ], [ %j.1.1, %bb37 ], [ %j.1.1, %cond_true41 ], [ %j.5, %cond_true82 ] ; <sbyte*> [#uses=2]
|
||||
%i.4 = phi sbyte* [ %i.5.1, %bb104 ], [ %i.4, %bb75 ], [ %tmp56, %bb46 ], [ undef, %bb37 ], [ %base, %cond_true41 ], [ %i.4, %cond_true82 ] ; <sbyte*> [#uses=2]
|
||||
%c.4 = phi sbyte [ %tmp88, %bb104 ], [ %c.4, %bb75 ], [ %tmp, %bb46 ], [ undef, %bb37 ], [ undef, %cond_true41 ], [ %c.4, %cond_true82 ] ; <sbyte> [#uses=2]
|
||||
%tmp116 = load int* %qsz ; <int> [#uses=2]
|
||||
%tmp118 = getelementptr sbyte* %min.1, int %tmp116 ; <sbyte*> [#uses=9]
|
||||
%tmp122 = setlt sbyte* %tmp118, %tmp9 ; <bool> [#uses=1]
|
||||
br bool %tmp122, label %bb66, label %return
|
||||
|
||||
return: ; preds = %bb115, %entry
|
||||
ret int undef
|
||||
}
|
||||
|
||||
declare int %qste(sbyte*, sbyte*)
|
||||
|
||||
declare int %comparee(%struct.edgeBox*, %struct.edgeBox*)
|
32
test/Transforms/InstCombine/2006-12-15-Range-Test.ll
Normal file
32
test/Transforms/InstCombine/2006-12-15-Range-Test.ll
Normal file
@ -0,0 +1,32 @@
|
||||
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep 'icmp' | wc -l | grep 1
|
||||
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep 'icmp ugt' | wc -l | grep 1
|
||||
; ModuleID = 'bugpoint-tooptimize.bc'
|
||||
target datalayout = "e-p:32:32"
|
||||
target endian = little
|
||||
target pointersize = 32
|
||||
target triple = "i686-pc-linux-gnu"
|
||||
%r = external global [17 x int] ; <[17 x int]*> [#uses=1]
|
||||
|
||||
implementation ; Functions:
|
||||
|
||||
bool %print_pgm_cond_true(int %tmp12.reload, int* %tmp16.out) {
|
||||
newFuncRoot:
|
||||
br label %cond_true
|
||||
|
||||
bb27.exitStub: ; preds = %cond_true
|
||||
store int %tmp16, int* %tmp16.out
|
||||
ret bool true
|
||||
|
||||
cond_next23.exitStub: ; preds = %cond_true
|
||||
store int %tmp16, int* %tmp16.out
|
||||
ret bool false
|
||||
|
||||
cond_true: ; preds = %newFuncRoot
|
||||
%tmp15 = getelementptr [17 x int]* %r, int 0, int %tmp12.reload ; <int*> [#uses=1]
|
||||
%tmp16 = load int* %tmp15 ; <int> [#uses=4]
|
||||
%tmp18 = icmp slt int %tmp16, -31 ; <bool> [#uses=1]
|
||||
%tmp21 = icmp sgt int %tmp16, 31 ; <bool> [#uses=1]
|
||||
%bothcond = or bool %tmp18, %tmp21 ; <bool> [#uses=1]
|
||||
br bool %bothcond, label %bb27.exitStub, label %cond_next23.exitStub
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
; This is the sequence of stuff that the Java front-end expands for a single
|
||||
; <= comparison. Check to make sure we turn it into a <= (only)
|
||||
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -instcombine | llvm-dis | grep -v 'setle'| not grep '#uses'
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -instcombine | llvm-dis | grep -v 'icmp sle'| not grep '#uses'
|
||||
|
||||
bool %le(int %A, int %B) {
|
||||
%c1 = setgt int %A, %B;
|
||||
|
@ -93,11 +93,12 @@ bool %test14(sbyte %A) {
|
||||
ret bool %X
|
||||
}
|
||||
|
||||
bool %test15(ubyte %A) {
|
||||
%c = cast ubyte %A to sbyte
|
||||
%X = setlt sbyte %c, 0 ; setgt %A, 127
|
||||
ret bool %X
|
||||
}
|
||||
; This just won't occur when there's no difference between ubyte and sbyte
|
||||
;bool %test15(ubyte %A) {
|
||||
; %c = cast ubyte %A to sbyte
|
||||
; %X = setlt sbyte %c, 0 ; setgt %A, 127
|
||||
; ret bool %X
|
||||
;}
|
||||
|
||||
bool %test16(int* %P) {
|
||||
%c = cast int* %P to bool ;; setne P, null
|
||||
|
@ -1,7 +1,7 @@
|
||||
; This test makes sure that these instructions are properly eliminated.
|
||||
;
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -instcombine -disable-output &&
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -instcombine | llvm-dis | not grep set
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -instcombine | llvm-dis | not grep icmp
|
||||
|
||||
%X = uninitialized global int
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
; into equivalent setne,eq instructions.
|
||||
;
|
||||
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -instcombine | llvm-dis | grep -v seteq | grep -v setne | not grep set
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -instcombine | llvm-dis | grep -v 'icmp eq' | grep -v 'icmp ne' | not grep icmp
|
||||
|
||||
bool %test1(uint %A) {
|
||||
%B = setge uint %A, 1 ; setne %A, 0
|
||||
|
Binary file not shown.
@ -2,7 +2,7 @@
|
||||
; having overlapping live ranges that result in copies. We want the setcc instruction
|
||||
; immediately before the conditional branch.
|
||||
;
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -loop-reduce | llvm-dis | %prcontext 'br bool' 1 | grep set
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -loop-reduce | llvm-dis | %prcontext 'br bool' 1 | grep icmp
|
||||
|
||||
void %foo(float* %D, uint %E) {
|
||||
entry:
|
||||
|
144
test/Transforms/SimplifyCFG/2006-12-08-Ptr-ICmp-Branch.ll
Normal file
144
test/Transforms/SimplifyCFG/2006-12-08-Ptr-ICmp-Branch.ll
Normal file
@ -0,0 +1,144 @@
|
||||
; RUN: llvm-as < %s | opt -simplifycfg | llvm-dis
|
||||
; ModuleID = 'bugpoint-tooptimize.bc'
|
||||
target datalayout = "e-p:32:32"
|
||||
target endian = little
|
||||
target pointersize = 32
|
||||
target triple = "i686-pc-linux-gnu"
|
||||
%struct.FILE = type { int, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, %struct._IO_marker*, %struct.FILE*, int, int, int, ushort, sbyte, [1 x sbyte], sbyte*, long, sbyte*, sbyte*, sbyte*, sbyte*, uint, int, [40 x sbyte] }
|
||||
%struct._IO_FILE = type { int, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, %struct._IO_marker*, %struct.FILE*, int, int, int, ushort, sbyte, [1 x sbyte], sbyte*, long, sbyte*, sbyte*, sbyte*, sbyte*, uint, int, [40 x sbyte] }
|
||||
%struct._IO_marker = type { %struct._IO_marker*, %struct.FILE*, int }
|
||||
%struct.charsequence = type { sbyte*, uint, uint }
|
||||
%struct.trie_s = type { [26 x %struct.trie_s*], int }
|
||||
%str = external global [14 x sbyte] ; <[14 x sbyte]*> [#uses=0]
|
||||
%str = external global [32 x sbyte] ; <[32 x sbyte]*> [#uses=0]
|
||||
%str = external global [12 x sbyte] ; <[12 x sbyte]*> [#uses=0]
|
||||
%C.0.2294 = external global %struct.charsequence ; <%struct.charsequence*> [#uses=3]
|
||||
%t = external global %struct.trie_s* ; <%struct.trie_s**> [#uses=0]
|
||||
%str = external global [3 x sbyte] ; <[3 x sbyte]*> [#uses=0]
|
||||
%str = external global [26 x sbyte] ; <[26 x sbyte]*> [#uses=0]
|
||||
|
||||
implementation ; Functions:
|
||||
|
||||
declare void %charsequence_reset(%struct.charsequence*)
|
||||
declare void %free(sbyte*)
|
||||
declare void %charsequence_push(%struct.charsequence*, sbyte)
|
||||
declare sbyte* %charsequence_val(%struct.charsequence*)
|
||||
declare int %_IO_getc(%struct.FILE*)
|
||||
declare int %tolower(int)
|
||||
declare %struct.trie_s* %trie_insert(%struct.trie_s*, sbyte*)
|
||||
declare int %feof(%struct.FILE*)
|
||||
|
||||
void %addfile(%struct.trie_s* %t, %struct.FILE* %f) {
|
||||
entry:
|
||||
%t_addr = alloca %struct.trie_s* ; <%struct.trie_s**> [#uses=2]
|
||||
%f_addr = alloca %struct.FILE* ; <%struct.FILE**> [#uses=3]
|
||||
%c = alloca sbyte, align 1 ; <sbyte*> [#uses=7]
|
||||
%wstate = alloca int, align 4 ; <int*> [#uses=4]
|
||||
%cs = alloca %struct.charsequence, align 16 ; <%struct.charsequence*> [#uses=7]
|
||||
%str = alloca sbyte*, align 4 ; <sbyte**> [#uses=3]
|
||||
"alloca point" = bitcast int 0 to int ; <int> [#uses=0]
|
||||
store %struct.trie_s* %t, %struct.trie_s** %t_addr
|
||||
store %struct.FILE* %f, %struct.FILE** %f_addr
|
||||
store int 0, int* %wstate
|
||||
%tmp = getelementptr %struct.charsequence* %cs, uint 0, uint 0 ; <sbyte**> [#uses=1]
|
||||
%tmp1 = getelementptr %struct.charsequence* %C.0.2294, uint 0, uint 0 ; <sbyte**> [#uses=1]
|
||||
%tmp = load sbyte** %tmp1 ; <sbyte*> [#uses=1]
|
||||
store sbyte* %tmp, sbyte** %tmp
|
||||
%tmp = getelementptr %struct.charsequence* %cs, uint 0, uint 1 ; <uint*> [#uses=1]
|
||||
%tmp2 = getelementptr %struct.charsequence* %C.0.2294, uint 0, uint 1 ; <uint*> [#uses=1]
|
||||
%tmp = load uint* %tmp2 ; <uint> [#uses=1]
|
||||
store uint %tmp, uint* %tmp
|
||||
%tmp3 = getelementptr %struct.charsequence* %cs, uint 0, uint 2 ; <uint*> [#uses=1]
|
||||
%tmp4 = getelementptr %struct.charsequence* %C.0.2294, uint 0, uint 2 ; <uint*> [#uses=1]
|
||||
%tmp5 = load uint* %tmp4 ; <uint> [#uses=1]
|
||||
store uint %tmp5, uint* %tmp3
|
||||
br label %bb33
|
||||
|
||||
bb: ; preds = %bb33
|
||||
%tmp = load %struct.FILE** %f_addr ; <%struct.FILE*> [#uses=1]
|
||||
%tmp = call int %_IO_getc( %struct.FILE* %tmp ) ; <int> [#uses=1]
|
||||
%tmp6 = call int %tolower( int %tmp ) ; <int> [#uses=1]
|
||||
%tmp6 = trunc int %tmp6 to sbyte ; <sbyte> [#uses=1]
|
||||
store sbyte %tmp6, sbyte* %c
|
||||
%tmp7 = load int* %wstate ; <int> [#uses=1]
|
||||
%tmp = icmp ne int %tmp7, 0 ; <bool> [#uses=1]
|
||||
br bool %tmp, label %cond_true, label %cond_false
|
||||
|
||||
cond_true: ; preds = %bb
|
||||
%tmp = load sbyte* %c ; <sbyte> [#uses=1]
|
||||
%tmp8 = icmp sle sbyte %tmp, 96 ; <bool> [#uses=1]
|
||||
br bool %tmp8, label %cond_true9, label %cond_next
|
||||
|
||||
cond_true9: ; preds = %cond_true
|
||||
br label %bb16
|
||||
|
||||
cond_next: ; preds = %cond_true
|
||||
%tmp10 = load sbyte* %c ; <sbyte> [#uses=1]
|
||||
%tmp11 = icmp sgt sbyte %tmp10, 122 ; <bool> [#uses=1]
|
||||
br bool %tmp11, label %cond_true12, label %cond_next13
|
||||
|
||||
cond_true12: ; preds = %cond_next
|
||||
br label %bb16
|
||||
|
||||
cond_next13: ; preds = %cond_next
|
||||
%tmp14 = load sbyte* %c ; <sbyte> [#uses=1]
|
||||
%tmp14 = sext sbyte %tmp14 to int ; <int> [#uses=1]
|
||||
%tmp1415 = trunc int %tmp14 to sbyte ; <sbyte> [#uses=1]
|
||||
call void %charsequence_push( %struct.charsequence* %cs, sbyte %tmp1415 )
|
||||
br label %bb21
|
||||
|
||||
bb16: ; preds = %cond_true12, %cond_true9
|
||||
%tmp17 = call sbyte* %charsequence_val( %struct.charsequence* %cs ) ; <sbyte*> [#uses=1]
|
||||
store sbyte* %tmp17, sbyte** %str
|
||||
%tmp = load %struct.trie_s** %t_addr ; <%struct.trie_s*> [#uses=1]
|
||||
%tmp18 = load sbyte** %str ; <sbyte*> [#uses=1]
|
||||
%tmp19 = call %struct.trie_s* %trie_insert( %struct.trie_s* %tmp, sbyte* %tmp18 ) ; <%struct.trie_s*> [#uses=0]
|
||||
%tmp20 = load sbyte** %str ; <sbyte*> [#uses=1]
|
||||
call void %free( sbyte* %tmp20 )
|
||||
store int 0, int* %wstate
|
||||
br label %bb21
|
||||
|
||||
bb21: ; preds = %bb16, %cond_next13
|
||||
br label %cond_next32
|
||||
|
||||
cond_false: ; preds = %bb
|
||||
%tmp22 = load sbyte* %c ; <sbyte> [#uses=1]
|
||||
%tmp23 = icmp sgt sbyte %tmp22, 96 ; <bool> [#uses=1]
|
||||
br bool %tmp23, label %cond_true24, label %cond_next31
|
||||
|
||||
cond_true24: ; preds = %cond_false
|
||||
%tmp25 = load sbyte* %c ; <sbyte> [#uses=1]
|
||||
%tmp26 = icmp sle sbyte %tmp25, 122 ; <bool> [#uses=1]
|
||||
br bool %tmp26, label %cond_true27, label %cond_next30
|
||||
|
||||
cond_true27: ; preds = %cond_true24
|
||||
call void %charsequence_reset( %struct.charsequence* %cs )
|
||||
%tmp28 = load sbyte* %c ; <sbyte> [#uses=1]
|
||||
%tmp28 = sext sbyte %tmp28 to int ; <int> [#uses=1]
|
||||
%tmp2829 = trunc int %tmp28 to sbyte ; <sbyte> [#uses=1]
|
||||
call void %charsequence_push( %struct.charsequence* %cs, sbyte %tmp2829 )
|
||||
store int 1, int* %wstate
|
||||
br label %cond_next30
|
||||
|
||||
cond_next30: ; preds = %cond_true27, %cond_true24
|
||||
br label %cond_next31
|
||||
|
||||
cond_next31: ; preds = %cond_next30, %cond_false
|
||||
br label %cond_next32
|
||||
|
||||
cond_next32: ; preds = %cond_next31, %bb21
|
||||
br label %bb33
|
||||
|
||||
bb33: ; preds = %cond_next32, %entry
|
||||
%tmp34 = load %struct.FILE** %f_addr ; <%struct.FILE*> [#uses=1]
|
||||
%tmp35 = call int %feof( %struct.FILE* %tmp34 ) ; <int> [#uses=1]
|
||||
%tmp36 = icmp eq int %tmp35, 0 ; <bool> [#uses=1]
|
||||
br bool %tmp36, label %bb, label %bb37
|
||||
|
||||
bb37: ; preds = %bb33
|
||||
br label %return
|
||||
|
||||
return: ; preds = %bb37
|
||||
ret void
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -simplifycfg | llvm-dis | not grep seteq
|
||||
; RUN: llvm-upgrade < %s | llvm-as | opt -simplifycfg | llvm-dis | not grep 'icmp eq'
|
||||
|
||||
; Check that simplifycfg deletes a dead 'seteq' instruction when it
|
||||
; folds a conditional branch into a switch instruction.
|
||||
|
@ -724,8 +724,8 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
|
||||
|
||||
// Check to see if we already looked up the value.
|
||||
Value *CachedVal = new LoadInst(Cache, "fpcache", EntryBB);
|
||||
Value *IsNull = new SetCondInst(Instruction::SetEQ, CachedVal,
|
||||
NullPtr, "isNull", EntryBB);
|
||||
Value *IsNull = new ICmpInst(ICmpInst::ICMP_EQ, CachedVal,
|
||||
NullPtr, "isNull", EntryBB);
|
||||
new BranchInst(LookupBB, DoCallBB, IsNull, EntryBB);
|
||||
|
||||
// Resolve the call to function F via the JIT API:
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -333,7 +333,7 @@
|
||||
|
||||
|
||||
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
|
||||
#line 285 "/proj/llvm/llvm-1/tools/llvm-upgrade/UpgradeParser.y"
|
||||
#line 275 "/proj/llvm/llvm-3/tools/llvm-upgrade/UpgradeParser.y"
|
||||
typedef union YYSTYPE {
|
||||
std::string* String;
|
||||
TypeInfo Type;
|
||||
|
@ -333,7 +333,7 @@
|
||||
|
||||
|
||||
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
|
||||
#line 285 "/proj/llvm/llvm-1/tools/llvm-upgrade/UpgradeParser.y"
|
||||
#line 275 "/proj/llvm/llvm-3/tools/llvm-upgrade/UpgradeParser.y"
|
||||
typedef union YYSTYPE {
|
||||
std::string* String;
|
||||
TypeInfo Type;
|
||||
|
@ -23,8 +23,6 @@
|
||||
#define YYERROR_VERBOSE 1
|
||||
#define YYINCLUDED_STDLIB_H
|
||||
#define YYDEBUG 1
|
||||
#define UPGRADE_SETCOND_OPS 0
|
||||
#define GENERATE_FCMP_INSTS 0
|
||||
|
||||
int yylex(); // declaration" of xxx warnings.
|
||||
int yyparse();
|
||||
@ -194,11 +192,7 @@ static std::string getCastUpgrade(
|
||||
// the original intent by replace the cast with a setne
|
||||
const char* comparator = SrcTy.isPointer() ? ", null" :
|
||||
(SrcTy.isFloatingPoint() ? ", 0.0" : ", 0");
|
||||
#if UPGRADE_SETCOND_OPS
|
||||
const char* compareOp = SrcTy.isFloatingPoint() ? "setne " : "icmp ne ";
|
||||
#else
|
||||
const char* compareOp = "setne";
|
||||
#endif
|
||||
const char* compareOp = SrcTy.isFloatingPoint() ? "fcmp one " : "icmp ne ";
|
||||
if (isConst) {
|
||||
Result = "(" + Source + comparator + ")";
|
||||
Result = compareOp + Result;
|
||||
@ -254,16 +248,12 @@ getCompareOp(const std::string& setcc, const TypeInfo& TI) {
|
||||
result[6] = cc1;
|
||||
result[7] = cc2;
|
||||
if (TI.isFloatingPoint()) {
|
||||
#if GENERATE_FCMP_INSTS
|
||||
result[0] = 'f';
|
||||
result[5] = 'o'; // FIXME: Always map to ordered comparison ?
|
||||
result[5] = 'o';
|
||||
if (cc1 == 'n')
|
||||
result[5] = 'u'; // NE maps to unordered
|
||||
else
|
||||
result[5] = 'o'; // everything else maps to ordered
|
||||
#else
|
||||
result = setcc;
|
||||
#endif
|
||||
} else if (TI.isIntegral() || TI.isPointer()) {
|
||||
result[0] = 'i';
|
||||
if ((cc1 == 'e' && cc2 == 'q') || (cc1 == 'n' && cc2 == 'e'))
|
||||
@ -679,9 +669,7 @@ ConstExpr: CastOps '(' ConstVal TO Types ')' {
|
||||
$$ = $1;
|
||||
}
|
||||
| SetCondOps '(' ConstVal ',' ConstVal ')' {
|
||||
#if UPGRADE_SETCOND_OPS
|
||||
*$1 = getCompareOp(*$1, $3.type);
|
||||
#endif
|
||||
*$1 += "(" + *$3.cnst + "," + *$5.cnst + ")";
|
||||
$3.destroy(); $5.destroy();
|
||||
$$ = $1;
|
||||
@ -1205,9 +1193,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
$$ = $1;
|
||||
}
|
||||
| SetCondOps Types ValueRef ',' ValueRef {
|
||||
#if UPGRADE_SETCOND_OPS
|
||||
*$1 = getCompareOp(*$1, $2);
|
||||
#endif
|
||||
*$1 += " " + *$2.newTy + " " + *$3.val + ", " + *$5.val;
|
||||
$2.destroy(); $3.destroy(); $5.destroy();
|
||||
$$ = $1;
|
||||
|
@ -23,8 +23,6 @@
|
||||
#define YYERROR_VERBOSE 1
|
||||
#define YYINCLUDED_STDLIB_H
|
||||
#define YYDEBUG 1
|
||||
#define UPGRADE_SETCOND_OPS 0
|
||||
#define GENERATE_FCMP_INSTS 0
|
||||
|
||||
int yylex(); // declaration" of xxx warnings.
|
||||
int yyparse();
|
||||
@ -194,11 +192,7 @@ static std::string getCastUpgrade(
|
||||
// the original intent by replace the cast with a setne
|
||||
const char* comparator = SrcTy.isPointer() ? ", null" :
|
||||
(SrcTy.isFloatingPoint() ? ", 0.0" : ", 0");
|
||||
#if UPGRADE_SETCOND_OPS
|
||||
const char* compareOp = SrcTy.isFloatingPoint() ? "setne " : "icmp ne ";
|
||||
#else
|
||||
const char* compareOp = "setne";
|
||||
#endif
|
||||
const char* compareOp = SrcTy.isFloatingPoint() ? "fcmp one " : "icmp ne ";
|
||||
if (isConst) {
|
||||
Result = "(" + Source + comparator + ")";
|
||||
Result = compareOp + Result;
|
||||
@ -254,16 +248,12 @@ getCompareOp(const std::string& setcc, const TypeInfo& TI) {
|
||||
result[6] = cc1;
|
||||
result[7] = cc2;
|
||||
if (TI.isFloatingPoint()) {
|
||||
#if GENERATE_FCMP_INSTS
|
||||
result[0] = 'f';
|
||||
result[5] = 'o'; // FIXME: Always map to ordered comparison ?
|
||||
result[5] = 'o';
|
||||
if (cc1 == 'n')
|
||||
result[5] = 'u'; // NE maps to unordered
|
||||
else
|
||||
result[5] = 'o'; // everything else maps to ordered
|
||||
#else
|
||||
result = setcc;
|
||||
#endif
|
||||
} else if (TI.isIntegral() || TI.isPointer()) {
|
||||
result[0] = 'i';
|
||||
if ((cc1 == 'e' && cc2 == 'q') || (cc1 == 'n' && cc2 == 'e'))
|
||||
@ -679,9 +669,7 @@ ConstExpr: CastOps '(' ConstVal TO Types ')' {
|
||||
$$ = $1;
|
||||
}
|
||||
| SetCondOps '(' ConstVal ',' ConstVal ')' {
|
||||
#if UPGRADE_SETCOND_OPS
|
||||
*$1 = getCompareOp(*$1, $3.type);
|
||||
#endif
|
||||
*$1 += "(" + *$3.cnst + "," + *$5.cnst + ")";
|
||||
$3.destroy(); $5.destroy();
|
||||
$$ = $1;
|
||||
@ -1205,9 +1193,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
$$ = $1;
|
||||
}
|
||||
| SetCondOps Types ValueRef ',' ValueRef {
|
||||
#if UPGRADE_SETCOND_OPS
|
||||
*$1 = getCompareOp(*$1, $2);
|
||||
#endif
|
||||
*$1 += " " + *$2.newTy + " " + *$3.val + ", " + *$5.val;
|
||||
$2.destroy(); $3.destroy(); $5.destroy();
|
||||
$$ = $1;
|
||||
|
@ -783,31 +783,63 @@ void CppWriter::printConstant(const Constant *CV) {
|
||||
}
|
||||
Out << "Constant* " << constName << " = ConstantExpr::";
|
||||
switch (CE->getOpcode()) {
|
||||
case Instruction::Add: Out << "getAdd"; break;
|
||||
case Instruction::Sub: Out << "getSub"; break;
|
||||
case Instruction::Mul: Out << "getMul"; break;
|
||||
case Instruction::UDiv: Out << "getUDiv"; break;
|
||||
case Instruction::SDiv: Out << "getSDiv"; break;
|
||||
case Instruction::FDiv: Out << "getFDiv"; break;
|
||||
case Instruction::URem: Out << "getURem"; break;
|
||||
case Instruction::SRem: Out << "getSRem"; break;
|
||||
case Instruction::FRem: Out << "getFRem"; break;
|
||||
case Instruction::And: Out << "getAnd"; break;
|
||||
case Instruction::Or: Out << "getOr"; break;
|
||||
case Instruction::Xor: Out << "getXor"; break;
|
||||
case Instruction::SetEQ: Out << "getSetEQ"; break;
|
||||
case Instruction::SetNE: Out << "getSetNE"; break;
|
||||
case Instruction::SetLE: Out << "getSetLE"; break;
|
||||
case Instruction::SetGE: Out << "getSetGE"; break;
|
||||
case Instruction::SetLT: Out << "getSetLT"; break;
|
||||
case Instruction::SetGT: Out << "getSetGT"; break;
|
||||
case Instruction::Shl: Out << "getShl"; break;
|
||||
case Instruction::LShr: Out << "getLShr"; break;
|
||||
case Instruction::AShr: Out << "getAShr"; break;
|
||||
case Instruction::Select: Out << "getSelect"; break;
|
||||
case Instruction::ExtractElement: Out << "getExtractElement"; break;
|
||||
case Instruction::InsertElement: Out << "getInsertElement"; break;
|
||||
case Instruction::ShuffleVector: Out << "getShuffleVector"; break;
|
||||
case Instruction::Add: Out << "getAdd("; break;
|
||||
case Instruction::Sub: Out << "getSub("; break;
|
||||
case Instruction::Mul: Out << "getMul("; break;
|
||||
case Instruction::UDiv: Out << "getUDiv("; break;
|
||||
case Instruction::SDiv: Out << "getSDiv("; break;
|
||||
case Instruction::FDiv: Out << "getFDiv("; break;
|
||||
case Instruction::URem: Out << "getURem("; break;
|
||||
case Instruction::SRem: Out << "getSRem("; break;
|
||||
case Instruction::FRem: Out << "getFRem("; break;
|
||||
case Instruction::And: Out << "getAnd("; break;
|
||||
case Instruction::Or: Out << "getOr("; break;
|
||||
case Instruction::Xor: Out << "getXor("; break;
|
||||
case Instruction::ICmp:
|
||||
Out << "getICmp(ICmpInst::ICMP_";
|
||||
switch (CE->getPredicate()) {
|
||||
case ICmpInst::ICMP_EQ: Out << "EQ"; break;
|
||||
case ICmpInst::ICMP_NE: Out << "NE"; break;
|
||||
case ICmpInst::ICMP_SLT: Out << "SLT"; break;
|
||||
case ICmpInst::ICMP_ULT: Out << "ULT"; break;
|
||||
case ICmpInst::ICMP_SGT: Out << "SGT"; break;
|
||||
case ICmpInst::ICMP_UGT: Out << "UGT"; break;
|
||||
case ICmpInst::ICMP_SLE: Out << "SLE"; break;
|
||||
case ICmpInst::ICMP_ULE: Out << "ULE"; break;
|
||||
case ICmpInst::ICMP_SGE: Out << "SGE"; break;
|
||||
case ICmpInst::ICMP_UGE: Out << "UGE"; break;
|
||||
default: error("Invalid ICmp Predicate");
|
||||
}
|
||||
break;
|
||||
case Instruction::FCmp:
|
||||
Out << "getFCmp(FCmpInst::FCMP_";
|
||||
switch (CE->getPredicate()) {
|
||||
case FCmpInst::FCMP_FALSE: Out << "FALSE"; break;
|
||||
case FCmpInst::FCMP_ORD: Out << "ORD"; break;
|
||||
case FCmpInst::FCMP_UNO: Out << "UNO"; break;
|
||||
case FCmpInst::FCMP_OEQ: Out << "OEQ"; break;
|
||||
case FCmpInst::FCMP_UEQ: Out << "UEQ"; break;
|
||||
case FCmpInst::FCMP_ONE: Out << "ONE"; break;
|
||||
case FCmpInst::FCMP_UNE: Out << "UNE"; break;
|
||||
case FCmpInst::FCMP_OLT: Out << "OLT"; break;
|
||||
case FCmpInst::FCMP_ULT: Out << "ULT"; break;
|
||||
case FCmpInst::FCMP_OGT: Out << "OGT"; break;
|
||||
case FCmpInst::FCMP_UGT: Out << "UGT"; break;
|
||||
case FCmpInst::FCMP_OLE: Out << "OLE"; break;
|
||||
case FCmpInst::FCMP_ULE: Out << "ULE"; break;
|
||||
case FCmpInst::FCMP_OGE: Out << "OGE"; break;
|
||||
case FCmpInst::FCMP_UGE: Out << "UGE"; break;
|
||||
case FCmpInst::FCMP_TRUE: Out << "TRUE"; break;
|
||||
default: error("Invalid FCmp Predicate");
|
||||
}
|
||||
break;
|
||||
case Instruction::Shl: Out << "getShl("; break;
|
||||
case Instruction::LShr: Out << "getLShr("; break;
|
||||
case Instruction::AShr: Out << "getAShr("; break;
|
||||
case Instruction::Select: Out << "getSelect("; break;
|
||||
case Instruction::ExtractElement: Out << "getExtractElement("; break;
|
||||
case Instruction::InsertElement: Out << "getInsertElement("; break;
|
||||
case Instruction::ShuffleVector: Out << "getShuffleVector("; break;
|
||||
default:
|
||||
error("Invalid constant expression");
|
||||
break;
|
||||
@ -1075,21 +1107,46 @@ CppWriter::printInstruction(const Instruction *I, const std::string& bbname) {
|
||||
Out << "\", " << bbname << ");";
|
||||
break;
|
||||
}
|
||||
case Instruction::SetEQ:
|
||||
case Instruction::SetNE:
|
||||
case Instruction::SetLE:
|
||||
case Instruction::SetGE:
|
||||
case Instruction::SetLT:
|
||||
case Instruction::SetGT: {
|
||||
Out << "SetCondInst* " << iName << " = new SetCondInst(";
|
||||
switch (I->getOpcode()) {
|
||||
case Instruction::SetEQ: Out << "Instruction::SetEQ"; break;
|
||||
case Instruction::SetNE: Out << "Instruction::SetNE"; break;
|
||||
case Instruction::SetLE: Out << "Instruction::SetLE"; break;
|
||||
case Instruction::SetGE: Out << "Instruction::SetGE"; break;
|
||||
case Instruction::SetLT: Out << "Instruction::SetLT"; break;
|
||||
case Instruction::SetGT: Out << "Instruction::SetGT"; break;
|
||||
default: Out << "Instruction::BadOpCode"; break;
|
||||
case Instruction::FCmp: {
|
||||
Out << "FCmpInst* " << iName << " = new FCmpInst(";
|
||||
switch (cast<FCmpInst>(I)->getPredicate()) {
|
||||
case FCmpInst::FCMP_FALSE: Out << "FCmpInst::FCMP_FALSE"; break;
|
||||
case FCmpInst::FCMP_OEQ : Out << "FCmpInst::FCMP_OEQ"; break;
|
||||
case FCmpInst::FCMP_OGT : Out << "FCmpInst::FCMP_OGT"; break;
|
||||
case FCmpInst::FCMP_OGE : Out << "FCmpInst::FCMP_OGE"; break;
|
||||
case FCmpInst::FCMP_OLT : Out << "FCmpInst::FCMP_OLT"; break;
|
||||
case FCmpInst::FCMP_OLE : Out << "FCmpInst::FCMP_OLE"; break;
|
||||
case FCmpInst::FCMP_ONE : Out << "FCmpInst::FCMP_ONE"; break;
|
||||
case FCmpInst::FCMP_ORD : Out << "FCmpInst::FCMP_ORD"; break;
|
||||
case FCmpInst::FCMP_UNO : Out << "FCmpInst::FCMP_UNO"; break;
|
||||
case FCmpInst::FCMP_UEQ : Out << "FCmpInst::FCMP_UEQ"; break;
|
||||
case FCmpInst::FCMP_UGT : Out << "FCmpInst::FCMP_UGT"; break;
|
||||
case FCmpInst::FCMP_UGE : Out << "FCmpInst::FCMP_UGE"; break;
|
||||
case FCmpInst::FCMP_ULT : Out << "FCmpInst::FCMP_ULT"; break;
|
||||
case FCmpInst::FCMP_ULE : Out << "FCmpInst::FCMP_ULE"; break;
|
||||
case FCmpInst::FCMP_UNE : Out << "FCmpInst::FCMP_UNE"; break;
|
||||
case FCmpInst::FCMP_TRUE : Out << "FCmpInst::FCMP_TRUE"; break;
|
||||
default: Out << "FCmpInst::BAD_ICMP_PREDICATE"; break;
|
||||
}
|
||||
Out << ", " << opNames[0] << ", " << opNames[1] << ", \"";
|
||||
printEscapedString(I->getName());
|
||||
Out << "\", " << bbname << ");";
|
||||
break;
|
||||
}
|
||||
case Instruction::ICmp: {
|
||||
Out << "ICmpInst* " << iName << " = new ICmpInst(";
|
||||
switch (cast<ICmpInst>(I)->getPredicate()) {
|
||||
case ICmpInst::ICMP_EQ: Out << "ICmpInst::ICMP_EQ"; break;
|
||||
case ICmpInst::ICMP_NE: Out << "ICmpInst::ICMP_NE"; break;
|
||||
case ICmpInst::ICMP_ULE: Out << "ICmpInst::ICMP_ULE"; break;
|
||||
case ICmpInst::ICMP_SLE: Out << "ICmpInst::ICMP_SLE"; break;
|
||||
case ICmpInst::ICMP_UGE: Out << "ICmpInst::ICMP_UGE"; break;
|
||||
case ICmpInst::ICMP_SGE: Out << "ICmpInst::ICMP_SGE"; break;
|
||||
case ICmpInst::ICMP_ULT: Out << "ICmpInst::ICMP_ULT"; break;
|
||||
case ICmpInst::ICMP_SLT: Out << "ICmpInst::ICMP_SLT"; break;
|
||||
case ICmpInst::ICMP_UGT: Out << "ICmpInst::ICMP_UGT"; break;
|
||||
case ICmpInst::ICMP_SGT: Out << "ICmpInst::ICMP_SGT"; break;
|
||||
default: Out << "ICmpInst::BAD_ICMP_PREDICATE"; break;
|
||||
}
|
||||
Out << ", " << opNames[0] << ", " << opNames[1] << ", \"";
|
||||
printEscapedString(I->getName());
|
||||
|
Loading…
x
Reference in New Issue
Block a user