mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-11 11:34:02 +00:00
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:
parent
163a84bbce
commit
f067d584a8
@ -3684,7 +3684,10 @@ Instruction</a> </div>
|
||||
|
||||
<h5>Syntax:</h5>
|
||||
<pre>
|
||||
<result> = shl <ty> <op1>, <op2> <i>; yields {ty}:result</i>
|
||||
<result> = shl <ty> <op1>, <op2> <i>; yields {ty}:result</i>
|
||||
<result> = shl nuw <ty> <op1>, <op2> <i>; yields {ty}:result</i>
|
||||
<result> = shl nsw <ty> <op1>, <op2> <i>; yields {ty}:result</i>
|
||||
<result> = shl nuw nsw <ty> <op1>, <op2> <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>
|
||||
<result> = shl i32 4, %var <i>; yields {i32}: 4 << %var</i>
|
||||
@ -3723,7 +3734,8 @@ Instruction</a> </div>
|
||||
|
||||
<h5>Syntax:</h5>
|
||||
<pre>
|
||||
<result> = lshr <ty> <op1>, <op2> <i>; yields {ty}:result</i>
|
||||
<result> = lshr <ty> <op1>, <op2> <i>; yields {ty}:result</i>
|
||||
<result> = lshr exact <ty> <op1>, <op2> <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>
|
||||
<result> = lshr i32 4, 1 <i>; yields {i32}:result = 2</i>
|
||||
@ -3762,7 +3779,8 @@ Instruction</a> </div>
|
||||
|
||||
<h5>Syntax:</h5>
|
||||
<pre>
|
||||
<result> = ashr <ty> <op1>, <op2> <i>; yields {ty}:result</i>
|
||||
<result> = ashr <ty> <op1>, <op2> <i>; yields {ty}:result</i>
|
||||
<result> = ashr exact <ty> <op1>, <op2> <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>
|
||||
<result> = ashr i32 4, 1 <i>; yields {i32}:result = 2</i>
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user