implement .ll and .bc support for nsw/nuw on shl and exact on lshr/ashr.

Factor some code better.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125006 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2011-02-07 16:40:21 +00:00
parent 163a84bbce
commit f067d584a8
8 changed files with 239 additions and 211 deletions

View File

@ -3684,7 +3684,10 @@ Instruction</a> </div>
<h5>Syntax:</h5>
<pre>
&lt;result&gt; = shl &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt; <i>; yields {ty}:result</i>
&lt;result&gt; = shl &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt; <i>; yields {ty}:result</i>
&lt;result&gt; = shl nuw &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt; <i>; yields {ty}:result</i>
&lt;result&gt; = shl nsw &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt; <i>; yields {ty}:result</i>
&lt;result&gt; = shl nuw nsw &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt; <i>; yields {ty}:result</i>
</pre>
<h5>Overview:</h5>
@ -3704,6 +3707,14 @@ Instruction</a> </div>
vectors, each vector element of <tt>op1</tt> is shifted by the corresponding
shift amount in <tt>op2</tt>.</p>
<p>If the <tt>nuw</tt> keyword is present, then the shift produces a
<a href="#trapvalues">trap value</a> if it shifts out any non-zero bits. If
the <tt>nsw</tt> keywrod is present, then the shift produces a
<a href="#trapvalues">trap value</a> if it shifts out any bits that disagree
with the resultant sign bit. As such, NUW/NSW have the same semantics as
they would if the shift were expressed as a mul instruction with the same
nsw/nuw bits in (mul %op1, (shl 1, %op2)).</p>
<h5>Example:</h5>
<pre>
&lt;result&gt; = shl i32 4, %var <i>; yields {i32}: 4 &lt;&lt; %var</i>
@ -3723,7 +3734,8 @@ Instruction</a> </div>
<h5>Syntax:</h5>
<pre>
&lt;result&gt; = lshr &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt; <i>; yields {ty}:result</i>
&lt;result&gt; = lshr &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt; <i>; yields {ty}:result</i>
&lt;result&gt; = lshr exact &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt; <i>; yields {ty}:result</i>
</pre>
<h5>Overview:</h5>
@ -3743,6 +3755,11 @@ Instruction</a> </div>
vectors, each vector element of <tt>op1</tt> is shifted by the corresponding
shift amount in <tt>op2</tt>.</p>
<p>If the <tt>exact</tt> keyword is present, the result value of the
<tt>lshr</tt> is a <a href="#trapvalues">trap value</a> if any of the bits
shifted out are non-zero.</p>
<h5>Example:</h5>
<pre>
&lt;result&gt; = lshr i32 4, 1 <i>; yields {i32}:result = 2</i>
@ -3762,7 +3779,8 @@ Instruction</a> </div>
<h5>Syntax:</h5>
<pre>
&lt;result&gt; = ashr &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt; <i>; yields {ty}:result</i>
&lt;result&gt; = ashr &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt; <i>; yields {ty}:result</i>
&lt;result&gt; = ashr exact &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt; <i>; yields {ty}:result</i>
</pre>
<h5>Overview:</h5>
@ -3783,6 +3801,10 @@ Instruction</a> </div>
the arguments are vectors, each vector element of <tt>op1</tt> is shifted by
the corresponding shift amount in <tt>op2</tt>.</p>
<p>If the <tt>exact</tt> keyword is present, the result value of the
<tt>ashr</tt> is a <a href="#trapvalues">trap value</a> if any of the bits
shifted out are non-zero.</p>
<h5>Example:</h5>
<pre>
&lt;result&gt; = ashr i32 4, 1 <i>; yields {i32}:result = 2</i>

View File

@ -724,8 +724,12 @@ public:
static Constant *getNUWSub(Constant *C1, Constant *C2);
static Constant *getNSWMul(Constant *C1, Constant *C2);
static Constant *getNUWMul(Constant *C1, Constant *C2);
static Constant *getNSWShl(Constant *C1, Constant *C2);
static Constant *getNUWShl(Constant *C1, Constant *C2);
static Constant *getExactSDiv(Constant *C1, Constant *C2);
static Constant *getExactUDiv(Constant *C1, Constant *C2);
static Constant *getExactAShr(Constant *C1, Constant *C2);
static Constant *getExactLShr(Constant *C1, Constant *C2);
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);

View File

@ -106,66 +106,14 @@ public:
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::Add ||
I->getOpcode() == Instruction::Sub ||
I->getOpcode() == Instruction::Mul;
I->getOpcode() == Instruction::Mul ||
I->getOpcode() == Instruction::Shl;
}
static inline bool classof(const ConstantExpr *CE) {
return CE->getOpcode() == Instruction::Add ||
CE->getOpcode() == Instruction::Sub ||
CE->getOpcode() == Instruction::Mul;
}
static inline bool classof(const Value *V) {
return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
(isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
}
};
/// AddOperator - Utility class for integer addition operators.
///
class AddOperator : public OverflowingBinaryOperator {
~AddOperator(); // do not implement
public:
static inline bool classof(const AddOperator *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::Add;
}
static inline bool classof(const ConstantExpr *CE) {
return CE->getOpcode() == Instruction::Add;
}
static inline bool classof(const Value *V) {
return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
(isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
}
};
/// SubOperator - Utility class for integer subtraction operators.
///
class SubOperator : public OverflowingBinaryOperator {
~SubOperator(); // do not implement
public:
static inline bool classof(const SubOperator *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::Sub;
}
static inline bool classof(const ConstantExpr *CE) {
return CE->getOpcode() == Instruction::Sub;
}
static inline bool classof(const Value *V) {
return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
(isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
}
};
/// MulOperator - Utility class for integer multiplication operators.
///
class MulOperator : public OverflowingBinaryOperator {
~MulOperator(); // do not implement
public:
static inline bool classof(const MulOperator *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::Mul;
}
static inline bool classof(const ConstantExpr *CE) {
return CE->getOpcode() == Instruction::Mul;
CE->getOpcode() == Instruction::Mul ||
CE->getOpcode() == Instruction::Shl;
}
static inline bool classof(const Value *V) {
return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
@ -196,31 +144,40 @@ public:
return SubclassOptionalData & IsExact;
}
static bool isPossiblyExactOpcode(unsigned OpC) {
return OpC == Instruction::SDiv ||
OpC == Instruction::UDiv ||
OpC == Instruction::AShr ||
OpC == Instruction::LShr;
}
static inline bool classof(const ConstantExpr *CE) {
return CE->getOpcode() == Instruction::SDiv ||
CE->getOpcode() == Instruction::UDiv;
return isPossiblyExactOpcode(CE->getOpcode());
}
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::SDiv ||
I->getOpcode() == Instruction::UDiv;
return isPossiblyExactOpcode(I->getOpcode());
}
static inline bool classof(const Value *V) {
return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
(isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
(isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
}
};
/// SDivOperator - An Operator with opcode Instruction::SDiv.
///
class SDivOperator : public PossiblyExactOperator {
/// ConcreteOperator - A helper template for defining operators for individual
/// opcodes.
template<typename SuperClass, unsigned Opc>
class ConcreteOperator : public SuperClass {
~ConcreteOperator(); // DO NOT IMPLEMENT
public:
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SDivOperator *) { return true; }
static inline bool classof(const ConstantExpr *CE) {
return CE->getOpcode() == Instruction::SDiv;
static inline bool classof(const ConcreteOperator<SuperClass, Opc> *) {
return true;
}
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::SDiv;
return I->getOpcode() == Opc;
}
static inline bool classof(const ConstantExpr *CE) {
return CE->getOpcode() == Opc;
}
static inline bool classof(const Value *V) {
return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
@ -228,31 +185,33 @@ public:
}
};
/// UDivOperator - An Operator with opcode Instruction::UDiv.
///
class UDivOperator : public PossiblyExactOperator {
public:
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const UDivOperator *) { return true; }
static inline bool classof(const ConstantExpr *CE) {
return CE->getOpcode() == Instruction::UDiv;
}
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::UDiv;
}
static inline bool classof(const Value *V) {
return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
(isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
}
};
class AddOperator
: public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> {};
class SubOperator
: public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> {};
class MulOperator
: public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> {};
class ShlOperator
: public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> {};
class GEPOperator : public Operator {
class SDivOperator
: public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> {};
class UDivOperator
: public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> {};
class AShrOperator
: public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> {};
class LShrOperator
: public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> {};
class GEPOperator
: public ConcreteOperator<Operator, Instruction::GetElementPtr> {
enum {
IsInBounds = (1 << 0)
};
~GEPOperator(); // do not implement
friend class GetElementPtrInst;
friend class ConstantExpr;
void setIsInBounds(bool B) {
@ -301,8 +260,8 @@ public:
/// value, just potentially different types.
bool hasAllZeroIndices() const {
for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) {
if (Constant *C = dyn_cast<Constant>(I))
if (C->isNullValue())
if (ConstantInt *C = dyn_cast<ConstantInt>(I))
if (C->isZero())
continue;
return false;
}
@ -319,21 +278,6 @@ public:
}
return true;
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const GEPOperator *) { return true; }
static inline bool classof(const GetElementPtrInst *) { return true; }
static inline bool classof(const ConstantExpr *CE) {
return CE->getOpcode() == Instruction::GetElementPtr;
}
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::GetElementPtr;
}
static inline bool classof(const Value *V) {
return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
(isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
}
};
} // End llvm namespace

View File

@ -2286,7 +2286,10 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
case lltok::kw_fdiv:
case lltok::kw_urem:
case lltok::kw_srem:
case lltok::kw_frem: {
case lltok::kw_frem:
case lltok::kw_shl:
case lltok::kw_lshr:
case lltok::kw_ashr: {
bool NUW = false;
bool NSW = false;
bool Exact = false;
@ -2294,9 +2297,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
Constant *Val0, *Val1;
Lex.Lex();
LocTy ModifierLoc = Lex.getLoc();
if (Opc == Instruction::Add ||
Opc == Instruction::Sub ||
Opc == Instruction::Mul) {
if (Opc == Instruction::Add || Opc == Instruction::Sub ||
Opc == Instruction::Mul || Opc == Instruction::Shl) {
if (EatIfPresent(lltok::kw_nuw))
NUW = true;
if (EatIfPresent(lltok::kw_nsw)) {
@ -2304,7 +2306,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
if (EatIfPresent(lltok::kw_nuw))
NUW = true;
}
} else if (Opc == Instruction::SDiv || Opc == Instruction::UDiv) {
} else if (Opc == Instruction::SDiv || Opc == Instruction::UDiv ||
Opc == Instruction::LShr || Opc == Instruction::AShr) {
if (EatIfPresent(lltok::kw_exact))
Exact = true;
}
@ -2331,6 +2334,9 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
case Instruction::SDiv:
case Instruction::URem:
case Instruction::SRem:
case Instruction::Shl:
case Instruction::AShr:
case Instruction::LShr:
if (!Val0->getType()->isIntOrIntVectorTy())
return Error(ID.Loc, "constexpr requires integer operands");
break;
@ -2355,9 +2361,6 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
}
// Logical Operations
case lltok::kw_shl:
case lltok::kw_lshr:
case lltok::kw_ashr:
case lltok::kw_and:
case lltok::kw_or:
case lltok::kw_xor: {
@ -3002,55 +3005,38 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
// Binary Operators.
case lltok::kw_add:
case lltok::kw_sub:
case lltok::kw_mul: {
bool NUW = false;
bool NSW = false;
case lltok::kw_mul:
case lltok::kw_shl: {
LocTy ModifierLoc = Lex.getLoc();
if (EatIfPresent(lltok::kw_nuw))
NUW = true;
if (EatIfPresent(lltok::kw_nsw)) {
NSW = true;
if (EatIfPresent(lltok::kw_nuw))
NUW = true;
}
bool Result = ParseArithmetic(Inst, PFS, KeywordVal, 1);
if (!Result) {
if (!Inst->getType()->isIntOrIntVectorTy()) {
if (NUW)
return Error(ModifierLoc, "nuw only applies to integer operations");
if (NSW)
return Error(ModifierLoc, "nsw only applies to integer operations");
}
if (NUW)
cast<BinaryOperator>(Inst)->setHasNoUnsignedWrap(true);
if (NSW)
cast<BinaryOperator>(Inst)->setHasNoSignedWrap(true);
}
return Result;
bool NUW = EatIfPresent(lltok::kw_nuw);
bool NSW = EatIfPresent(lltok::kw_nsw);
if (!NUW) NUW = EatIfPresent(lltok::kw_nuw);
if (ParseArithmetic(Inst, PFS, KeywordVal, 1)) return true;
if (NUW) cast<BinaryOperator>(Inst)->setHasNoUnsignedWrap(true);
if (NSW) cast<BinaryOperator>(Inst)->setHasNoSignedWrap(true);
return false;
}
case lltok::kw_fadd:
case lltok::kw_fsub:
case lltok::kw_fmul: return ParseArithmetic(Inst, PFS, KeywordVal, 2);
case lltok::kw_sdiv:
case lltok::kw_udiv: {
bool Exact = false;
if (EatIfPresent(lltok::kw_exact))
Exact = true;
bool Result = ParseArithmetic(Inst, PFS, KeywordVal, 1);
if (!Result)
if (Exact)
cast<BinaryOperator>(Inst)->setIsExact(true);
return Result;
case lltok::kw_udiv:
case lltok::kw_lshr:
case lltok::kw_ashr: {
bool Exact = EatIfPresent(lltok::kw_exact);
if (ParseArithmetic(Inst, PFS, KeywordVal, 1)) return true;
if (Exact) cast<BinaryOperator>(Inst)->setIsExact(true);
return false;
}
case lltok::kw_urem:
case lltok::kw_srem: return ParseArithmetic(Inst, PFS, KeywordVal, 1);
case lltok::kw_fdiv:
case lltok::kw_frem: return ParseArithmetic(Inst, PFS, KeywordVal, 2);
case lltok::kw_shl:
case lltok::kw_lshr:
case lltok::kw_ashr:
case lltok::kw_and:
case lltok::kw_or:
case lltok::kw_xor: return ParseLogical(Inst, PFS, KeywordVal);

View File

@ -1085,13 +1085,16 @@ bool BitcodeReader::ParseConstants() {
if (Record.size() >= 4) {
if (Opc == Instruction::Add ||
Opc == Instruction::Sub ||
Opc == Instruction::Mul) {
Opc == Instruction::Mul ||
Opc == Instruction::Shl) {
if (Record[3] & (1 << bitc::OBO_NO_SIGNED_WRAP))
Flags |= OverflowingBinaryOperator::NoSignedWrap;
if (Record[3] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
} else if (Opc == Instruction::SDiv ||
Opc == Instruction::UDiv) {
Opc == Instruction::UDiv ||
Opc == Instruction::LShr ||
Opc == Instruction::AShr) {
if (Record[3] & (1 << bitc::PEO_EXACT))
Flags |= SDivOperator::IsExact;
}
@ -1901,13 +1904,16 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
if (OpNum < Record.size()) {
if (Opc == Instruction::Add ||
Opc == Instruction::Sub ||
Opc == Instruction::Mul) {
Opc == Instruction::Mul ||
Opc == Instruction::Shl) {
if (Record[OpNum] & (1 << bitc::OBO_NO_SIGNED_WRAP))
cast<BinaryOperator>(I)->setHasNoSignedWrap(true);
if (Record[OpNum] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
cast<BinaryOperator>(I)->setHasNoUnsignedWrap(true);
} else if (Opc == Instruction::SDiv ||
Opc == Instruction::UDiv) {
Opc == Instruction::UDiv ||
Opc == Instruction::LShr ||
Opc == Instruction::AShr) {
if (Record[OpNum] & (1 << bitc::PEO_EXACT))
cast<BinaryOperator>(I)->setIsExact(true);
}

View File

@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
// This file implements the Constant* classes.
// This file implements the Constant *classes.
//
//===----------------------------------------------------------------------===//
@ -72,7 +72,7 @@ Constant *Constant::getNullValue(const Type *Ty) {
}
}
Constant* Constant::getIntegerValue(const Type *Ty, const APInt &V) {
Constant *Constant::getIntegerValue(const Type *Ty, const APInt &V) {
const Type *ScalarTy = Ty->getScalarType();
// Create the base integer constant.
@ -89,7 +89,7 @@ Constant* Constant::getIntegerValue(const Type *Ty, const APInt &V) {
return C;
}
Constant* Constant::getAllOnesValue(const Type *Ty) {
Constant *Constant::getAllOnesValue(const Type *Ty) {
if (const IntegerType *ITy = dyn_cast<IntegerType>(Ty))
return ConstantInt::get(Ty->getContext(),
APInt::getAllOnesValue(ITy->getBitWidth()));
@ -296,7 +296,7 @@ ConstantInt *ConstantInt::get(LLVMContext &Context, const APInt& V) {
return Slot;
}
Constant* ConstantInt::get(const Type* Ty, uint64_t V, bool isSigned) {
Constant *ConstantInt::get(const Type* Ty, uint64_t V, bool isSigned) {
Constant *C = get(cast<IntegerType>(Ty->getScalarType()),
V, isSigned);
@ -321,7 +321,7 @@ Constant *ConstantInt::getSigned(const Type *Ty, int64_t V) {
return get(Ty, V, true);
}
Constant* ConstantInt::get(const Type* Ty, const APInt& V) {
Constant *ConstantInt::get(const Type* Ty, const APInt& V) {
ConstantInt *C = get(Ty->getContext(), V);
assert(C->getType() == Ty->getScalarType() &&
"ConstantInt type doesn't match the type implied by its value!");
@ -360,7 +360,7 @@ static const fltSemantics *TypeToFloatSemantics(const Type *Ty) {
/// get() - This returns a constant fp for the specified value in the
/// specified type. This should only be used for simple constant values like
/// 2.0/1.0 etc, that are known-valid both as double and as the target format.
Constant* ConstantFP::get(const Type* Ty, double V) {
Constant *ConstantFP::get(const Type* Ty, double V) {
LLVMContext &Context = Ty->getContext();
APFloat FV(V);
@ -378,7 +378,7 @@ Constant* ConstantFP::get(const Type* Ty, double V) {
}
Constant* ConstantFP::get(const Type* Ty, StringRef Str) {
Constant *ConstantFP::get(const Type* Ty, StringRef Str) {
LLVMContext &Context = Ty->getContext();
APFloat FV(*TypeToFloatSemantics(Ty->getScalarType()), Str);
@ -401,7 +401,7 @@ ConstantFP* ConstantFP::getNegativeZero(const Type* Ty) {
}
Constant* ConstantFP::getZeroValueForNegation(const Type* Ty) {
Constant *ConstantFP::getZeroValueForNegation(const Type* Ty) {
if (const VectorType *PTy = dyn_cast<VectorType>(Ty))
if (PTy->getElementType()->isFloatingPointTy()) {
std::vector<Constant*> zeros(PTy->getNumElements(),
@ -509,7 +509,7 @@ Constant *ConstantArray::get(const ArrayType *Ty,
}
Constant* ConstantArray::get(const ArrayType* T, Constant* const* Vals,
Constant *ConstantArray::get(const ArrayType* T, Constant *const* Vals,
unsigned NumVals) {
// FIXME: make this the primary ctor method.
return get(T, std::vector<Constant*>(Vals, Vals+NumVals));
@ -521,7 +521,7 @@ Constant* ConstantArray::get(const ArrayType* T, Constant* const* Vals,
/// Otherwise, the length parameter specifies how much of the string to use
/// and it won't be null terminated.
///
Constant* ConstantArray::get(LLVMContext &Context, StringRef Str,
Constant *ConstantArray::get(LLVMContext &Context, StringRef Str,
bool AddNull) {
std::vector<Constant*> ElementVals;
ElementVals.reserve(Str.size() + size_t(AddNull));
@ -557,7 +557,7 @@ ConstantStruct::ConstantStruct(const StructType *T,
}
// ConstantStruct accessors.
Constant* ConstantStruct::get(const StructType* T,
Constant *ConstantStruct::get(const StructType* T,
const std::vector<Constant*>& V) {
LLVMContextImpl* pImpl = T->getContext().pImpl;
@ -569,7 +569,7 @@ Constant* ConstantStruct::get(const StructType* T,
return ConstantAggregateZero::get(T);
}
Constant* ConstantStruct::get(LLVMContext &Context,
Constant *ConstantStruct::get(LLVMContext &Context,
const std::vector<Constant*>& V, bool packed) {
std::vector<const Type*> StructEls;
StructEls.reserve(V.size());
@ -578,8 +578,8 @@ Constant* ConstantStruct::get(LLVMContext &Context,
return get(StructType::get(Context, StructEls, packed), V);
}
Constant* ConstantStruct::get(LLVMContext &Context,
Constant* const *Vals, unsigned NumVals,
Constant *ConstantStruct::get(LLVMContext &Context,
Constant *const *Vals, unsigned NumVals,
bool Packed) {
// FIXME: make this the primary ctor method.
return get(Context, std::vector<Constant*>(Vals, Vals+NumVals), Packed);
@ -601,7 +601,7 @@ ConstantVector::ConstantVector(const VectorType *T,
}
// ConstantVector accessors.
Constant* ConstantVector::get(const VectorType* T,
Constant *ConstantVector::get(const VectorType* T,
const std::vector<Constant*>& V) {
assert(!V.empty() && "Vectors can't be empty");
LLVMContext &Context = T->getContext();
@ -629,68 +629,89 @@ Constant* ConstantVector::get(const VectorType* T,
return pImpl->VectorConstants.getOrCreate(T, V);
}
Constant* ConstantVector::get(const std::vector<Constant*>& V) {
Constant *ConstantVector::get(const std::vector<Constant*>& V) {
assert(!V.empty() && "Cannot infer type if V is empty");
return get(VectorType::get(V.front()->getType(),V.size()), V);
}
Constant* ConstantVector::get(Constant* const* Vals, unsigned NumVals) {
Constant *ConstantVector::get(Constant *const* Vals, unsigned NumVals) {
// FIXME: make this the primary ctor method.
return get(std::vector<Constant*>(Vals, Vals+NumVals));
}
Constant* ConstantExpr::getNSWNeg(Constant* C) {
Constant *ConstantExpr::getNSWNeg(Constant *C) {
assert(C->getType()->isIntOrIntVectorTy() &&
"Cannot NEG a nonintegral value!");
return getNSWSub(ConstantFP::getZeroValueForNegation(C->getType()), C);
}
Constant* ConstantExpr::getNUWNeg(Constant* C) {
Constant *ConstantExpr::getNUWNeg(Constant *C) {
assert(C->getType()->isIntOrIntVectorTy() &&
"Cannot NEG a nonintegral value!");
return getNUWSub(ConstantFP::getZeroValueForNegation(C->getType()), C);
}
Constant* ConstantExpr::getNSWAdd(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getNSWAdd(Constant *C1, Constant *C2) {
return getTy(C1->getType(), Instruction::Add, C1, C2,
OverflowingBinaryOperator::NoSignedWrap);
}
Constant* ConstantExpr::getNUWAdd(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getNUWAdd(Constant *C1, Constant *C2) {
return getTy(C1->getType(), Instruction::Add, C1, C2,
OverflowingBinaryOperator::NoUnsignedWrap);
}
Constant* ConstantExpr::getNSWSub(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getNSWSub(Constant *C1, Constant *C2) {
return getTy(C1->getType(), Instruction::Sub, C1, C2,
OverflowingBinaryOperator::NoSignedWrap);
}
Constant* ConstantExpr::getNUWSub(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getNUWSub(Constant *C1, Constant *C2) {
return getTy(C1->getType(), Instruction::Sub, C1, C2,
OverflowingBinaryOperator::NoUnsignedWrap);
}
Constant* ConstantExpr::getNSWMul(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getNSWMul(Constant *C1, Constant *C2) {
return getTy(C1->getType(), Instruction::Mul, C1, C2,
OverflowingBinaryOperator::NoSignedWrap);
}
Constant* ConstantExpr::getNUWMul(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getNUWMul(Constant *C1, Constant *C2) {
return getTy(C1->getType(), Instruction::Mul, C1, C2,
OverflowingBinaryOperator::NoUnsignedWrap);
}
Constant* ConstantExpr::getExactSDiv(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getNSWShl(Constant *C1, Constant *C2) {
return getTy(C1->getType(), Instruction::Shl, C1, C2,
OverflowingBinaryOperator::NoSignedWrap);
}
Constant *ConstantExpr::getNUWShl(Constant *C1, Constant *C2) {
return getTy(C1->getType(), Instruction::Shl, C1, C2,
OverflowingBinaryOperator::NoUnsignedWrap);
}
Constant *ConstantExpr::getExactSDiv(Constant *C1, Constant *C2) {
return getTy(C1->getType(), Instruction::SDiv, C1, C2,
PossiblyExactOperator::IsExact);
}
Constant* ConstantExpr::getExactUDiv(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getExactUDiv(Constant *C1, Constant *C2) {
return getTy(C1->getType(), Instruction::UDiv, C1, C2,
PossiblyExactOperator::IsExact);
}
Constant *ConstantExpr::getExactAShr(Constant *C1, Constant *C2) {
return getTy(C1->getType(), Instruction::AShr, C1, C2,
PossiblyExactOperator::IsExact);
}
Constant *ConstantExpr::getExactLShr(Constant *C1, Constant *C2) {
return getTy(C1->getType(), Instruction::LShr, C1, C2,
PossiblyExactOperator::IsExact);
}
// Utility function for determining if a ConstantExpr is a CastOp or not. This
// can't be inline because we don't want to #include Instruction.h into
// Constant.h
@ -816,7 +837,7 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const {
/// operands replaced with the specified values. The specified operands must
/// match count and type with the existing ones.
Constant *ConstantExpr::
getWithOperands(Constant* const *Ops, unsigned NumOps) const {
getWithOperands(Constant *const *Ops, unsigned NumOps) const {
assert(NumOps == getNumOperands() && "Operand count mismatch!");
bool AnyChange = false;
for (unsigned i = 0; i != NumOps; ++i) {
@ -1486,7 +1507,7 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
return getTy(C1->getType(), Opcode, C1, C2, Flags);
}
Constant* ConstantExpr::getSizeOf(const Type* Ty) {
Constant *ConstantExpr::getSizeOf(const Type* Ty) {
// sizeof is implemented as: (i64) gep (Ty*)null, 1
// Note that a non-inbounds gep is used, as null isn't within any object.
Constant *GEPIdx = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 1);
@ -1496,7 +1517,7 @@ Constant* ConstantExpr::getSizeOf(const Type* Ty) {
Type::getInt64Ty(Ty->getContext()));
}
Constant* ConstantExpr::getAlignOf(const Type* Ty) {
Constant *ConstantExpr::getAlignOf(const Type* Ty) {
// alignof is implemented as: (i64) gep ({i1,Ty}*)null, 0, 1
// Note that a non-inbounds gep is used, as null isn't within any object.
const Type *AligningTy = StructType::get(Ty->getContext(),
@ -1510,12 +1531,12 @@ Constant* ConstantExpr::getAlignOf(const Type* Ty) {
Type::getInt64Ty(Ty->getContext()));
}
Constant* ConstantExpr::getOffsetOf(const StructType* STy, unsigned FieldNo) {
Constant *ConstantExpr::getOffsetOf(const StructType* STy, unsigned FieldNo) {
return getOffsetOf(STy, ConstantInt::get(Type::getInt32Ty(STy->getContext()),
FieldNo));
}
Constant* ConstantExpr::getOffsetOf(const Type* Ty, Constant *FieldNo) {
Constant *ConstantExpr::getOffsetOf(const Type* Ty, Constant *FieldNo) {
// offsetof is implemented as: (i64) gep (Ty*)null, 0, FieldNo
// Note that a non-inbounds gep is used, as null isn't within any object.
Constant *GEPIdx[] = {
@ -1823,7 +1844,7 @@ Constant *ConstantExpr::getExtractValue(Constant *Agg,
return getExtractValueTy(ReqTy, Agg, IdxList, NumIdx);
}
Constant* ConstantExpr::getNeg(Constant* C) {
Constant *ConstantExpr::getNeg(Constant *C) {
assert(C->getType()->isIntOrIntVectorTy() &&
"Cannot NEG a nonintegral value!");
return get(Instruction::Sub,
@ -1831,7 +1852,7 @@ Constant* ConstantExpr::getNeg(Constant* C) {
C);
}
Constant* ConstantExpr::getFNeg(Constant* C) {
Constant *ConstantExpr::getFNeg(Constant *C) {
assert(C->getType()->isFPOrFPVectorTy() &&
"Cannot FNEG a non-floating-point value!");
return get(Instruction::FSub,
@ -1839,81 +1860,81 @@ Constant* ConstantExpr::getFNeg(Constant* C) {
C);
}
Constant* ConstantExpr::getNot(Constant* C) {
Constant *ConstantExpr::getNot(Constant *C) {
assert(C->getType()->isIntOrIntVectorTy() &&
"Cannot NOT a nonintegral value!");
return get(Instruction::Xor, C, Constant::getAllOnesValue(C->getType()));
}
Constant* ConstantExpr::getAdd(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getAdd(Constant *C1, Constant *C2) {
return get(Instruction::Add, C1, C2);
}
Constant* ConstantExpr::getFAdd(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getFAdd(Constant *C1, Constant *C2) {
return get(Instruction::FAdd, C1, C2);
}
Constant* ConstantExpr::getSub(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getSub(Constant *C1, Constant *C2) {
return get(Instruction::Sub, C1, C2);
}
Constant* ConstantExpr::getFSub(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getFSub(Constant *C1, Constant *C2) {
return get(Instruction::FSub, C1, C2);
}
Constant* ConstantExpr::getMul(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getMul(Constant *C1, Constant *C2) {
return get(Instruction::Mul, C1, C2);
}
Constant* ConstantExpr::getFMul(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getFMul(Constant *C1, Constant *C2) {
return get(Instruction::FMul, C1, C2);
}
Constant* ConstantExpr::getUDiv(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getUDiv(Constant *C1, Constant *C2) {
return get(Instruction::UDiv, C1, C2);
}
Constant* ConstantExpr::getSDiv(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getSDiv(Constant *C1, Constant *C2) {
return get(Instruction::SDiv, C1, C2);
}
Constant* ConstantExpr::getFDiv(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getFDiv(Constant *C1, Constant *C2) {
return get(Instruction::FDiv, C1, C2);
}
Constant* ConstantExpr::getURem(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getURem(Constant *C1, Constant *C2) {
return get(Instruction::URem, C1, C2);
}
Constant* ConstantExpr::getSRem(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getSRem(Constant *C1, Constant *C2) {
return get(Instruction::SRem, C1, C2);
}
Constant* ConstantExpr::getFRem(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getFRem(Constant *C1, Constant *C2) {
return get(Instruction::FRem, C1, C2);
}
Constant* ConstantExpr::getAnd(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getAnd(Constant *C1, Constant *C2) {
return get(Instruction::And, C1, C2);
}
Constant* ConstantExpr::getOr(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getOr(Constant *C1, Constant *C2) {
return get(Instruction::Or, C1, C2);
}
Constant* ConstantExpr::getXor(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getXor(Constant *C1, Constant *C2) {
return get(Instruction::Xor, C1, C2);
}
Constant* ConstantExpr::getShl(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getShl(Constant *C1, Constant *C2) {
return get(Instruction::Shl, C1, C2);
}
Constant* ConstantExpr::getLShr(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getLShr(Constant *C1, Constant *C2) {
return get(Instruction::LShr, C1, C2);
}
Constant* ConstantExpr::getAShr(Constant* C1, Constant* C2) {
Constant *ConstantExpr::getAShr(Constant *C1, Constant *C2) {
return get(Instruction::AShr, C1, C2);
}

View File

@ -1,4 +1,4 @@
; Found by inspection of the code
; RUN: not llvm-as < %s > /dev/null |& grep {constexpr requires integer or integer vector operands}
; RUN: not llvm-as < %s > /dev/null |& grep {constexpr requires integer operands}
global i32 ashr (float 1.0, float 2.0)

View File

@ -92,6 +92,12 @@ define i64 @mul_both_reversed(i64 %x, i64 %y) {
ret i64 %z
}
define i64 @shl_both(i64 %x, i64 %y) {
; CHECK: %z = shl nuw nsw i64 %x, %y
%z = shl nuw nsw i64 %x, %y
ret i64 %z
}
define i64 @sdiv_exact(i64 %x, i64 %y) {
; CHECK: %z = sdiv exact i64 %x, %y
%z = sdiv exact i64 %x, %y
@ -116,6 +122,29 @@ define i64 @udiv_plain(i64 %x, i64 %y) {
ret i64 %z
}
define i64 @ashr_plain(i64 %x, i64 %y) {
; CHECK: %z = ashr i64 %x, %y
%z = ashr i64 %x, %y
ret i64 %z
}
define i64 @ashr_exact(i64 %x, i64 %y) {
; CHECK: %z = ashr exact i64 %x, %y
%z = ashr exact i64 %x, %y
ret i64 %z
}
define i64 @lshr_plain(i64 %x, i64 %y) {
; CHECK: %z = lshr i64 %x, %y
%z = lshr i64 %x, %y
ret i64 %z
}
define i64 @lshr_exact(i64 %x, i64 %y) {
; CHECK: %z = lshr exact i64 %x, %y
%z = lshr exact i64 %x, %y
ret i64 %z
}
define i64* @gep_nw(i64* %p, i64 %x) {
; CHECK: %z = getelementptr inbounds i64* %p, i64 %x
@ -154,6 +183,16 @@ define i64 @udiv_exact_ce() {
ret i64 udiv exact (i64 ptrtoint (i64* @addr to i64), i64 91)
}
define i64 @ashr_exact_ce() {
; CHECK: ret i64 ashr exact (i64 ptrtoint (i64* @addr to i64), i64 9)
ret i64 ashr exact (i64 ptrtoint (i64* @addr to i64), i64 9)
}
define i64 @lshr_exact_ce() {
; CHECK: ret i64 lshr exact (i64 ptrtoint (i64* @addr to i64), i64 9)
ret i64 lshr exact (i64 ptrtoint (i64* @addr to i64), i64 9)
}
define i64* @gep_nw_ce() {
; CHECK: ret i64* getelementptr inbounds (i64* @addr, i64 171)
ret i64* getelementptr inbounds (i64* @addr, i64 171)
@ -214,6 +253,12 @@ define i64 @mul_signed_ce() {
ret i64 mul nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
}
define i64 @shl_signed_ce() {
; CHECK: ret i64 shl nsw (i64 ptrtoint (i64* @addr to i64), i64 17)
ret i64 shl nsw (i64 ptrtoint (i64* @addr to i64), i64 17)
}
define i64 @add_unsigned_ce() {
; CHECK: ret i64 add nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
ret i64 add nuw (i64 ptrtoint (i64* @addr to i64), i64 91)