mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
enhance vmcore to know that udiv's can be exact, and add a trivial
instcombine xform to exercise this. Nothing forms exact udivs yet though. This is progress on PR8862 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@124992 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
bd75021465
commit
35bda8914c
@ -3441,7 +3441,8 @@ Instruction</a> </div>
|
||||
|
||||
<h5>Syntax:</h5>
|
||||
<pre>
|
||||
<result> = udiv <ty> <op1>, <op2> <i>; yields {ty}:result</i>
|
||||
<result> = udiv <ty> <op1>, <op2> <i>; yields {ty}:result</i>
|
||||
<result> = udiv exact <ty> <op1>, <op2> <i>; yields {ty}:result</i>
|
||||
</pre>
|
||||
|
||||
<h5>Overview:</h5>
|
||||
@ -3460,6 +3461,11 @@ Instruction</a> </div>
|
||||
|
||||
<p>Division by zero leads to undefined behavior.</p>
|
||||
|
||||
<p>If the <tt>exact</tt> keyword is present, the result value of the
|
||||
<tt>udiv</tt> is a <a href="#trapvalues">trap value</a> if %op1 is not a
|
||||
multiple of %op2 (as such, "((a udiv exact b) mul b) == a").</p>
|
||||
|
||||
|
||||
<h5>Example:</h5>
|
||||
<pre>
|
||||
<result> = udiv i32 4, %var <i>; yields {i32}:result = 4 / %var</i>
|
||||
|
@ -199,10 +199,10 @@ namespace bitc {
|
||||
OBO_NO_SIGNED_WRAP = 1
|
||||
};
|
||||
|
||||
/// SDivOperatorOptionalFlags - Flags for serializing SDivOperator's
|
||||
/// SubclassOptionalData contents.
|
||||
enum SDivOperatorOptionalFlags {
|
||||
SDIV_EXACT = 0
|
||||
/// PossiblyExactOperatorOptionalFlags - Flags for serializing
|
||||
/// PossiblyExactOperator's SubclassOptionalData contents.
|
||||
enum PossiblyExactOperatorOptionalFlags {
|
||||
PEO_EXACT = 0
|
||||
};
|
||||
|
||||
// The function body block (FUNCTION_BLOCK_ID) describes function bodies. It
|
||||
|
@ -725,6 +725,7 @@ public:
|
||||
static Constant *getNSWMul(Constant *C1, Constant *C2);
|
||||
static Constant *getNUWMul(Constant *C1, Constant *C2);
|
||||
static Constant *getExactSDiv(Constant *C1, Constant *C2);
|
||||
static Constant *getExactUDiv(Constant *C1, Constant *C2);
|
||||
|
||||
/// Transparently provide more efficient getOperand methods.
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
|
||||
|
@ -341,7 +341,7 @@ public:
|
||||
BO->setIsExact(true);
|
||||
return BO;
|
||||
}
|
||||
|
||||
|
||||
/// Helper functions to construct and inspect unary operations (NEG and NOT)
|
||||
/// via binary operators SUB and XOR:
|
||||
///
|
||||
|
@ -173,30 +173,47 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// SDivOperator - An Operator with opcode Instruction::SDiv.
|
||||
///
|
||||
class SDivOperator : public Operator {
|
||||
/// PossiblyExactOperator - A udiv or sdiv instruction, which can be marked as
|
||||
/// "exact", indicating that no bits are destroyed.
|
||||
class PossiblyExactOperator : public Operator {
|
||||
public:
|
||||
enum {
|
||||
IsExact = (1 << 0)
|
||||
};
|
||||
|
||||
private:
|
||||
~SDivOperator(); // do not implement
|
||||
|
||||
|
||||
friend class BinaryOperator;
|
||||
friend class ConstantExpr;
|
||||
void setIsExact(bool B) {
|
||||
SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
~PossiblyExactOperator(); // do not implement
|
||||
public:
|
||||
/// isExact - Test whether this division is known to be exact, with
|
||||
/// zero remainder.
|
||||
bool isExact() const {
|
||||
return SubclassOptionalData & IsExact;
|
||||
}
|
||||
|
||||
|
||||
static inline bool classof(const ConstantExpr *CE) {
|
||||
return CE->getOpcode() == Instruction::SDiv ||
|
||||
CE->getOpcode() == Instruction::UDiv;
|
||||
}
|
||||
static inline bool classof(const Instruction *I) {
|
||||
return I->getOpcode() == Instruction::SDiv ||
|
||||
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)));
|
||||
}
|
||||
};
|
||||
|
||||
/// SDivOperator - An Operator with opcode Instruction::SDiv.
|
||||
///
|
||||
class SDivOperator : public PossiblyExactOperator {
|
||||
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) {
|
||||
@ -211,6 +228,24 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// UDivOperator - An Operator with opcode Instruction::SDiv.
|
||||
///
|
||||
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 GEPOperator : public Operator {
|
||||
enum {
|
||||
IsInBounds = (1 << 0)
|
||||
|
@ -2304,7 +2304,7 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
|
||||
if (EatIfPresent(lltok::kw_nuw))
|
||||
NUW = true;
|
||||
}
|
||||
} else if (Opc == Instruction::SDiv) {
|
||||
} else if (Opc == Instruction::SDiv || Opc == Instruction::UDiv) {
|
||||
if (EatIfPresent(lltok::kw_exact))
|
||||
Exact = true;
|
||||
}
|
||||
@ -2347,7 +2347,7 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
|
||||
unsigned Flags = 0;
|
||||
if (NUW) Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
|
||||
if (NSW) Flags |= OverflowingBinaryOperator::NoSignedWrap;
|
||||
if (Exact) Flags |= SDivOperator::IsExact;
|
||||
if (Exact) Flags |= PossiblyExactOperator::IsExact;
|
||||
Constant *C = ConstantExpr::get(Opc, Val0, Val1, Flags);
|
||||
ID.ConstantVal = C;
|
||||
ID.Kind = ValID::t_Constant;
|
||||
@ -3032,7 +3032,8 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
|
||||
case lltok::kw_fsub:
|
||||
case lltok::kw_fmul: return ParseArithmetic(Inst, PFS, KeywordVal, 2);
|
||||
|
||||
case lltok::kw_sdiv: {
|
||||
case lltok::kw_sdiv:
|
||||
case lltok::kw_udiv: {
|
||||
bool Exact = false;
|
||||
if (EatIfPresent(lltok::kw_exact))
|
||||
Exact = true;
|
||||
@ -3043,7 +3044,6 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
|
||||
return Result;
|
||||
}
|
||||
|
||||
case lltok::kw_udiv:
|
||||
case lltok::kw_urem:
|
||||
case lltok::kw_srem: return ParseArithmetic(Inst, PFS, KeywordVal, 1);
|
||||
case lltok::kw_fdiv:
|
||||
|
@ -1090,8 +1090,9 @@ bool BitcodeReader::ParseConstants() {
|
||||
Flags |= OverflowingBinaryOperator::NoSignedWrap;
|
||||
if (Record[3] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
|
||||
Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
|
||||
} else if (Opc == Instruction::SDiv) {
|
||||
if (Record[3] & (1 << bitc::SDIV_EXACT))
|
||||
} else if (Opc == Instruction::SDiv ||
|
||||
Opc == Instruction::UDiv) {
|
||||
if (Record[3] & (1 << bitc::PEO_EXACT))
|
||||
Flags |= SDivOperator::IsExact;
|
||||
}
|
||||
}
|
||||
@ -1905,8 +1906,9 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
|
||||
cast<BinaryOperator>(I)->setHasNoSignedWrap(true);
|
||||
if (Record[OpNum] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
|
||||
cast<BinaryOperator>(I)->setHasNoUnsignedWrap(true);
|
||||
} else if (Opc == Instruction::SDiv) {
|
||||
if (Record[OpNum] & (1 << bitc::SDIV_EXACT))
|
||||
} else if (Opc == Instruction::SDiv ||
|
||||
Opc == Instruction::UDiv) {
|
||||
if (Record[OpNum] & (1 << bitc::PEO_EXACT))
|
||||
cast<BinaryOperator>(I)->setIsExact(true);
|
||||
}
|
||||
}
|
||||
|
@ -470,9 +470,10 @@ static uint64_t GetOptimizationFlags(const Value *V) {
|
||||
Flags |= 1 << bitc::OBO_NO_SIGNED_WRAP;
|
||||
if (OBO->hasNoUnsignedWrap())
|
||||
Flags |= 1 << bitc::OBO_NO_UNSIGNED_WRAP;
|
||||
} else if (const SDivOperator *Div = dyn_cast<SDivOperator>(V)) {
|
||||
if (Div->isExact())
|
||||
Flags |= 1 << bitc::SDIV_EXACT;
|
||||
} else if (const PossiblyExactOperator *PEO =
|
||||
dyn_cast<PossiblyExactOperator>(V)) {
|
||||
if (PEO->isExact())
|
||||
Flags |= 1 << bitc::PEO_EXACT;
|
||||
}
|
||||
|
||||
return Flags;
|
||||
|
@ -135,8 +135,8 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
||||
BO->getOpcode() == Instruction::SDiv)) {
|
||||
Value *Op0BO = BO->getOperand(0), *Op1BO = BO->getOperand(1);
|
||||
|
||||
// If the division is exact, X % Y is zero.
|
||||
if (SDivOperator *SDiv = dyn_cast<SDivOperator>(BO))
|
||||
// If the division is exact, X % Y is zero, so we end up with X or -X.
|
||||
if (PossiblyExactOperator *SDiv = dyn_cast<PossiblyExactOperator>(BO))
|
||||
if (SDiv->isExact()) {
|
||||
if (Op1BO == Op1C)
|
||||
return ReplaceInstUsesWith(I, Op0BO);
|
||||
|
@ -831,7 +831,8 @@ static void WriteOptimizationInfo(raw_ostream &Out, const User *U) {
|
||||
Out << " nuw";
|
||||
if (OBO->hasNoSignedWrap())
|
||||
Out << " nsw";
|
||||
} else if (const SDivOperator *Div = dyn_cast<SDivOperator>(U)) {
|
||||
} else if (const PossiblyExactOperator *Div =
|
||||
dyn_cast<PossiblyExactOperator>(U)) {
|
||||
if (Div->isExact())
|
||||
Out << " exact";
|
||||
} else if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
|
||||
|
@ -683,7 +683,12 @@ Constant* ConstantExpr::getNUWMul(Constant* C1, Constant* C2) {
|
||||
|
||||
Constant* ConstantExpr::getExactSDiv(Constant* C1, Constant* C2) {
|
||||
return getTy(C1->getType(), Instruction::SDiv, C1, C2,
|
||||
SDivOperator::IsExact);
|
||||
PossiblyExactOperator::IsExact);
|
||||
}
|
||||
|
||||
Constant* ConstantExpr::getExactUDiv(Constant* C1, Constant* C2) {
|
||||
return getTy(C1->getType(), Instruction::UDiv, C1, C2,
|
||||
PossiblyExactOperator::IsExact);
|
||||
}
|
||||
|
||||
// Utility function for determining if a ConstantExpr is a CastOp or not. This
|
||||
|
@ -1822,7 +1822,7 @@ void BinaryOperator::setHasNoSignedWrap(bool b) {
|
||||
}
|
||||
|
||||
void BinaryOperator::setIsExact(bool b) {
|
||||
cast<SDivOperator>(this)->setIsExact(b);
|
||||
cast<PossiblyExactOperator>(this)->setIsExact(b);
|
||||
}
|
||||
|
||||
bool BinaryOperator::hasNoUnsignedWrap() const {
|
||||
@ -1834,7 +1834,7 @@ bool BinaryOperator::hasNoSignedWrap() const {
|
||||
}
|
||||
|
||||
bool BinaryOperator::isExact() const {
|
||||
return cast<SDivOperator>(this)->isExact();
|
||||
return cast<PossiblyExactOperator>(this)->isExact();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -104,6 +104,19 @@ define i64 @sdiv_plain(i64 %x, i64 %y) {
|
||||
ret i64 %z
|
||||
}
|
||||
|
||||
define i64 @udiv_exact(i64 %x, i64 %y) {
|
||||
; CHECK: %z = udiv exact i64 %x, %y
|
||||
%z = udiv exact i64 %x, %y
|
||||
ret i64 %z
|
||||
}
|
||||
|
||||
define i64 @udiv_plain(i64 %x, i64 %y) {
|
||||
; CHECK: %z = udiv i64 %x, %y
|
||||
%z = udiv i64 %x, %y
|
||||
ret i64 %z
|
||||
}
|
||||
|
||||
|
||||
define i64* @gep_nw(i64* %p, i64 %x) {
|
||||
; CHECK: %z = getelementptr inbounds i64* %p, i64 %x
|
||||
%z = getelementptr inbounds i64* %p, i64 %x
|
||||
@ -136,6 +149,11 @@ define i64 @sdiv_exact_ce() {
|
||||
ret i64 sdiv exact (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||
}
|
||||
|
||||
define i64 @udiv_exact_ce() {
|
||||
; CHECK: ret i64 udiv exact (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||
ret i64 udiv exact (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||
}
|
||||
|
||||
define i64* @gep_nw_ce() {
|
||||
; CHECK: ret i64* getelementptr inbounds (i64* @addr, i64 171)
|
||||
ret i64* getelementptr inbounds (i64* @addr, i64 171)
|
||||
@ -210,3 +228,4 @@ define i64 @mul_unsigned_ce() {
|
||||
; CHECK: ret i64 mul nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||
ret i64 mul nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||
}
|
||||
|
||||
|
@ -50,3 +50,11 @@ define i32 @b1(i32 %x) {
|
||||
%z = mul i32 %y, -3
|
||||
ret i32 %z
|
||||
}
|
||||
|
||||
; CHECK: i32 @b2
|
||||
; CHECK: ret i32 %x
|
||||
define i32 @b2(i32 %x, i32 %w) {
|
||||
%y = udiv exact i32 %x, %w
|
||||
%z = mul i32 %y, %w
|
||||
ret i32 %z
|
||||
}
|
Loading…
Reference in New Issue
Block a user