Skip to content

Commit

Permalink
For PR950:
Browse files Browse the repository at this point in the history
Make necessary changes to support DIV -> [SUF]Div. This changes llvm to
have three division instructions: signed, unsigned, floating point. The
bytecode and assembler are bacwards compatible, however.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31195 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Reid Spencer committed Oct 26, 2006
1 parent 7043d00 commit 1628cec
Show file tree
Hide file tree
Showing 32 changed files with 3,002 additions and 1,860 deletions.
70 changes: 58 additions & 12 deletions docs/LangRef.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@
<li><a href="#i_add">'<tt>add</tt>' Instruction</a></li>
<li><a href="#i_sub">'<tt>sub</tt>' Instruction</a></li>
<li><a href="#i_mul">'<tt>mul</tt>' Instruction</a></li>
<li><a href="#i_div">'<tt>div</tt>' Instruction</a></li>
<li><a href="#i_udiv">'<tt>udiv</tt>' Instruction</a></li>
<li><a href="#i_sdiv">'<tt>sdiv</tt>' Instruction</a></li>
<li><a href="#i_fdiv">'<tt>fdiv</tt>' Instruction</a></li>
<li><a href="#i_rem">'<tt>rem</tt>' Instruction</a></li>
<li><a href="#i_setcc">'<tt>set<i>cc</i></tt>' Instructions</a></li>
</ol>
Expand Down Expand Up @@ -1630,26 +1632,70 @@ <h5>Example:</h5>
</pre>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection"> <a name="i_div">'<tt>div</tt>'
<div class="doc_subsubsection"> <a name="i_udiv">'<tt>udiv</tt>' Instruction
</a></div>
<div class="doc_text">
<h5>Syntax:</h5>
<pre> &lt;result&gt; = udiv &lt;ty&gt; &lt;var1&gt;, &lt;var2&gt; <i>; yields {ty}:result</i>
</pre>
<h5>Overview:</h5>
<p>The '<tt>udiv</tt>' instruction returns the quotient of its two
operands.</p>
<h5>Arguments:</h5>
<p>The two arguments to the '<tt>udiv</tt>' instruction must be
<a href="#t_integer">integer</a> values. Both arguments must have identical
types. This instruction can also take <a href="#t_packed">packed</a> versions
of the values in which case the elements must be integers.</p>
<h5>Semantics:</h5>
<p>The value produced is the unsigned integer quotient of the two operands. This
instruction always performs an unsigned division operation, regardless of
whether the arguments are unsigned or not.</p>
<h5>Example:</h5>
<pre> &lt;result&gt; = udiv uint 4, %var <i>; yields {uint}:result = 4 / %var</i>
</pre>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection"> <a name="i_sdiv">'<tt>sdiv</tt>' Instruction
</a> </div>
<div class="doc_text">
<h5>Syntax:</h5>
<pre> &lt;result&gt; = sdiv &lt;ty&gt; &lt;var1&gt;, &lt;var2&gt; <i>; yields {ty}:result</i>
</pre>
<h5>Overview:</h5>
<p>The '<tt>sdiv</tt>' instruction returns the quotient of its two
operands.</p>
<h5>Arguments:</h5>
<p>The two arguments to the '<tt>sdiv</tt>' instruction must be
<a href="#t_integer">integer</a> values. Both arguments must have identical
types. This instruction can also take <a href="#t_packed">packed</a> versions
of the values in which case the elements must be integers.</p>
<h5>Semantics:</h5>
<p>The value produced is the signed integer quotient of the two operands. This
instruction always performs a signed division operation, regardless of whether
the arguments are signed or not.</p>
<h5>Example:</h5>
<pre> &lt;result&gt; = sdiv int 4, %var <i>; yields {int}:result = 4 / %var</i>
</pre>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection"> <a name="i_fdiv">'<tt>fdiv</tt>'
Instruction</a> </div>
<div class="doc_text">
<h5>Syntax:</h5>
<pre> &lt;result&gt; = div &lt;ty&gt; &lt;var1&gt;, &lt;var2&gt; <i>; yields {ty}:result</i>
<pre> &lt;result&gt; = fdiv &lt;ty&gt; &lt;var1&gt;, &lt;var2&gt; <i>; yields {ty}:result</i>
</pre>
<h5>Overview:</h5>
<p>The '<tt>div</tt>' instruction returns the quotient of its two
<p>The '<tt>fdiv</tt>' instruction returns the quotient of its two
operands.</p>
<h5>Arguments:</h5>
<p>The two arguments to the '<tt>div</tt>' instruction must be either <a
href="#t_integer">integer</a> or <a href="#t_floating">floating point</a>
values.
This instruction can also take <a href="#t_packed">packed</a> versions of the values.
Both arguments must have identical types.</p>
<p>The two arguments to the '<tt>div</tt>' instruction must be
<a href="#t_floating">floating point</a> values. Both arguments must have
identical types. This instruction can also take <a href="#t_packed">packed</a>
versions of the values in which case the elements must be floating point.</p>
<h5>Semantics:</h5>
<p>The value produced is the integer or floating point quotient of the
two operands.</p>
<p>The value produced is the floating point quotient of the two operands.</p>
<h5>Example:</h5>
<pre> &lt;result&gt; = div int 4, %var <i>; yields {int}:result = 4 / %var</i>
<pre> &lt;result&gt; = fdiv float 4.0, %var <i>; yields {float}:result = 4.0 / %var</i>
</pre>
</div>
<!-- _______________________________________________________________________ -->
Expand Down
2 changes: 1 addition & 1 deletion include/llvm/Analysis/ScalarEvolutionExpander.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ namespace llvm {
const Type *Ty = S->getType();
Value *LHS = expandInTy(S->getLHS(), Ty);
Value *RHS = expandInTy(S->getRHS(), Ty);
return BinaryOperator::createDiv(LHS, RHS, "tmp.", InsertPt);
return BinaryOperator::createSDiv(LHS, RHS, "tmp.", InsertPt);
}

Value *visitAddRecExpr(SCEVAddRecExpr *S);
Expand Down
2 changes: 1 addition & 1 deletion include/llvm/Analysis/ScalarEvolutionExpressions.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ namespace llvm {


//===--------------------------------------------------------------------===//
/// SCEVSDivExpr - This class represents a binary unsigned division operation.
/// SCEVSDivExpr - This class represents a binary signed division operation.
///
class SCEVSDivExpr : public SCEV {
SCEVHandle LHS, RHS;
Expand Down
4 changes: 3 additions & 1 deletion include/llvm/Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,9 @@ class ConstantExpr : public Constant {
static Constant *getAdd(Constant *C1, Constant *C2);
static Constant *getSub(Constant *C1, Constant *C2);
static Constant *getMul(Constant *C1, Constant *C2);
static Constant *getDiv(Constant *C1, Constant *C2);
static Constant *getUDiv(Constant *C1, Constant *C2);
static Constant *getSDiv(Constant *C1, Constant *C2);
static Constant *getFDiv(Constant *C1, Constant *C2);
static Constant *getRem(Constant *C1, Constant *C2);
static Constant *getAnd(Constant *C1, Constant *C2);
static Constant *getOr(Constant *C1, Constant *C2);
Expand Down
58 changes: 28 additions & 30 deletions include/llvm/Instruction.def
Original file line number Diff line number Diff line change
Expand Up @@ -93,45 +93,43 @@ HANDLE_TERM_INST ( 6, Unreachable, UnreachableInst)
HANDLE_BINARY_INST( 7, Add , BinaryOperator)
HANDLE_BINARY_INST( 8, Sub , BinaryOperator)
HANDLE_BINARY_INST( 9, Mul , BinaryOperator)
HANDLE_BINARY_INST(10, Div , BinaryOperator)
HANDLE_BINARY_INST(11, Rem , BinaryOperator)
HANDLE_BINARY_INST(10, UDiv , BinaryOperator)
HANDLE_BINARY_INST(11, SDiv , BinaryOperator)
HANDLE_BINARY_INST(12, FDiv , BinaryOperator)
HANDLE_BINARY_INST(13, Rem , BinaryOperator)

// Logical operators...
HANDLE_BINARY_INST(12, And , BinaryOperator)
HANDLE_BINARY_INST(13, Or , BinaryOperator)
HANDLE_BINARY_INST(14, Xor , BinaryOperator)
HANDLE_BINARY_INST(14, And , BinaryOperator)
HANDLE_BINARY_INST(15, Or , BinaryOperator)
HANDLE_BINARY_INST(16, Xor , BinaryOperator)

// Binary comparison operators...
HANDLE_BINARY_INST(15, SetEQ , SetCondInst)
HANDLE_BINARY_INST(16, SetNE , SetCondInst)
HANDLE_BINARY_INST(17, SetLE , SetCondInst)
HANDLE_BINARY_INST(18, SetGE , SetCondInst)
HANDLE_BINARY_INST(19, SetLT , SetCondInst)
HANDLE_BINARY_INST(20, SetGT , SetCondInst)
LAST_BINARY_INST(20)
HANDLE_BINARY_INST(17, SetEQ , SetCondInst)
HANDLE_BINARY_INST(18, SetNE , SetCondInst)
HANDLE_BINARY_INST(19, SetLE , SetCondInst)
HANDLE_BINARY_INST(20, SetGE , SetCondInst)
HANDLE_BINARY_INST(21, SetLT , SetCondInst)
HANDLE_BINARY_INST(22, SetGT , SetCondInst)
LAST_BINARY_INST(22)

// Memory operators...
FIRST_MEMORY_INST(21)
HANDLE_MEMORY_INST(21, Malloc, MallocInst) // Heap management instructions
HANDLE_MEMORY_INST(22, Free , FreeInst )
HANDLE_MEMORY_INST(23, Alloca, AllocaInst) // Stack management
HANDLE_MEMORY_INST(24, Load , LoadInst ) // Memory manipulation instrs
HANDLE_MEMORY_INST(25, Store , StoreInst )
HANDLE_MEMORY_INST(26, GetElementPtr, GetElementPtrInst)
LAST_MEMORY_INST(26)
FIRST_MEMORY_INST(23)
HANDLE_MEMORY_INST(23, Malloc, MallocInst) // Heap management instructions
HANDLE_MEMORY_INST(24, Free , FreeInst )
HANDLE_MEMORY_INST(25, Alloca, AllocaInst) // Stack management
HANDLE_MEMORY_INST(26, Load , LoadInst ) // Memory manipulation instrs
HANDLE_MEMORY_INST(27, Store , StoreInst )
HANDLE_MEMORY_INST(28, GetElementPtr, GetElementPtrInst)
LAST_MEMORY_INST(28)

// Other operators...
FIRST_OTHER_INST(27)
HANDLE_OTHER_INST(27, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(28, Cast , CastInst ) // Type cast
HANDLE_OTHER_INST(29, Call , CallInst ) // Call a function

HANDLE_OTHER_INST(30, Shl , ShiftInst ) // Shift operations
HANDLE_OTHER_INST(31, Shr , ShiftInst )
// 32 -> Empty slot used to be used for vanext in llvm 1.5 and before.
// 33 -> Empty slot used to be used for vaarg in llvm 1.5 and before.
FIRST_OTHER_INST(29)
HANDLE_OTHER_INST(29, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(30, Cast , CastInst ) // Type cast
HANDLE_OTHER_INST(31, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(32, Shl , ShiftInst ) // Shift operations
HANDLE_OTHER_INST(33, Shr , ShiftInst )
HANDLE_OTHER_INST(34, Select , SelectInst ) // select instruction

HANDLE_OTHER_INST(35, UserOp1, Instruction) // May be used internally in a pass
HANDLE_OTHER_INST(36, UserOp2, Instruction)
HANDLE_OTHER_INST(37, VAArg , VAArgInst ) // vaarg instruction
Expand Down
16 changes: 14 additions & 2 deletions include/llvm/Support/PatternMatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,21 @@ inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS &L,
}

template<typename LHS, typename RHS>
inline BinaryOp_match<LHS, RHS, Instruction::Div> m_Div(const LHS &L,
inline BinaryOp_match<LHS, RHS, Instruction::UDiv> m_UDiv(const LHS &L,
const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Div>(L, R);
return BinaryOp_match<LHS, RHS, Instruction::UDiv>(L, R);
}

template<typename LHS, typename RHS>
inline BinaryOp_match<LHS, RHS, Instruction::SDiv> m_SDiv(const LHS &L,
const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::SDiv>(L, R);
}

template<typename LHS, typename RHS>
inline BinaryOp_match<LHS, RHS, Instruction::FDiv> m_FDiv(const LHS &L,
const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FDiv>(L, R);
}

template<typename LHS, typename RHS>
Expand Down
29 changes: 14 additions & 15 deletions lib/Analysis/ScalarEvolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -989,9 +989,9 @@ SCEVHandle SCEVMulExpr::get(std::vector<SCEVHandle> &Ops) {
SCEVHandle SCEVSDivExpr::get(const SCEVHandle &LHS, const SCEVHandle &RHS) {
if (SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS)) {
if (RHSC->getValue()->equalsInt(1))
return LHS; // X /s 1 --> x
return LHS; // X sdiv 1 --> x
if (RHSC->getValue()->isAllOnesValue())
return SCEV::getNegativeSCEV(LHS); // X /s -1 --> -x
return SCEV::getNegativeSCEV(LHS); // X sdiv -1 --> -x

if (SCEVConstant *LHSC = dyn_cast<SCEVConstant>(LHS)) {
Constant *LHSCV = LHSC->getValue();
Expand All @@ -1001,7 +1001,7 @@ SCEVHandle SCEVSDivExpr::get(const SCEVHandle &LHS, const SCEVHandle &RHS) {
LHSCV->getType()->getSignedVersion());
if (RHSCV->getType()->isUnsigned())
RHSCV = ConstantExpr::getCast(RHSCV, LHSCV->getType());
return SCEVUnknown::get(ConstantExpr::getDiv(LHSCV, RHSCV));
return SCEVUnknown::get(ConstantExpr::getSDiv(LHSCV, RHSCV));
}
}

Expand Down Expand Up @@ -1384,10 +1384,9 @@ SCEVHandle ScalarEvolutionsImpl::createSCEV(Value *V) {
case Instruction::Mul:
return SCEVMulExpr::get(getSCEV(I->getOperand(0)),
getSCEV(I->getOperand(1)));
case Instruction::Div:
if (V->getType()->isInteger() && V->getType()->isSigned())
return SCEVSDivExpr::get(getSCEV(I->getOperand(0)),
getSCEV(I->getOperand(1)));
case Instruction::SDiv:
return SCEVSDivExpr::get(getSCEV(I->getOperand(0)),
getSCEV(I->getOperand(1)));
break;

case Instruction::Sub:
Expand Down Expand Up @@ -2058,16 +2057,16 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec) {
return std::make_pair(CNC, CNC);
}

Constant *Two = ConstantInt::get(L->getValue()->getType(), 2);
Constant *C = L->getValue();
Constant *Two = ConstantInt::get(C->getType(), 2);

// Convert from chrec coefficients to polynomial coefficients AX^2+BX+C
Constant *C = L->getValue();
// The B coefficient is M-N/2
Constant *B = ConstantExpr::getSub(M->getValue(),
ConstantExpr::getDiv(N->getValue(),
ConstantExpr::getSDiv(N->getValue(),
Two));
// The A coefficient is N/2
Constant *A = ConstantExpr::getDiv(N->getValue(), Two);
Constant *A = ConstantExpr::getSDiv(N->getValue(), Two);

// Compute the B^2-4ac term.
Constant *SqrtTerm =
Expand Down Expand Up @@ -2102,9 +2101,9 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec) {
SqrtTerm = ConstantExpr::getCast(SqrtTerm, SignedTy);

Constant *Solution1 =
ConstantExpr::getDiv(ConstantExpr::getAdd(NegB, SqrtTerm), TwoA);
ConstantExpr::getSDiv(ConstantExpr::getAdd(NegB, SqrtTerm), TwoA);
Constant *Solution2 =
ConstantExpr::getDiv(ConstantExpr::getSub(NegB, SqrtTerm), TwoA);
ConstantExpr::getSDiv(ConstantExpr::getSub(NegB, SqrtTerm), TwoA);
return std::make_pair(SCEVUnknown::get(Solution1),
SCEVUnknown::get(Solution2));
}
Expand Down Expand Up @@ -2150,7 +2149,7 @@ SCEVHandle ScalarEvolutionsImpl::HowFarToZero(SCEV *V, const Loop *L) {
Constant *StartNegC = ConstantExpr::getNeg(StartCC);
Constant *Rem = ConstantExpr::getRem(StartNegC, StepC->getValue());
if (Rem->isNullValue()) {
Constant *Result =ConstantExpr::getDiv(StartNegC,StepC->getValue());
Constant *Result =ConstantExpr::getSDiv(StartNegC,StepC->getValue());
return SCEVUnknown::get(Result);
}
}
Expand Down Expand Up @@ -2352,7 +2351,7 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
Constant *ExitValue = Upper;
if (A != One) {
ExitValue = ConstantExpr::getSub(ConstantExpr::getAdd(Upper, A), One);
ExitValue = ConstantExpr::getDiv(ExitValue, A);
ExitValue = ConstantExpr::getSDiv(ExitValue, A);
}
assert(isa<ConstantInt>(ExitValue) &&
"Constant folding of integers not implemented?");
Expand Down
17 changes: 15 additions & 2 deletions lib/AsmParser/Lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,18 @@ void set_scan_string (const char * str) {
yy_scan_string (str);
}

// Construct a token value for a non-obsolete token
#define RET_TOK(type, Enum, sym) \
llvmAsmlval.type = Instruction::Enum; return sym
llvmAsmlval.type.opcode = Instruction::Enum; \
llvmAsmlval.type.obsolete = false; \
return sym

// Construct a token value for an obsolete token
#define RET_TOK_OBSOLETE(type, Enum, sym) \
llvmAsmlval.type.opcode = Instruction::Enum; \
llvmAsmlval.type.obsolete = true; \
return sym


namespace llvm {

Expand Down Expand Up @@ -247,7 +257,10 @@ opaque { return OPAQUE; }
add { RET_TOK(BinaryOpVal, Add, ADD); }
sub { RET_TOK(BinaryOpVal, Sub, SUB); }
mul { RET_TOK(BinaryOpVal, Mul, MUL); }
div { RET_TOK(BinaryOpVal, Div, DIV); }
div { RET_TOK_OBSOLETE(BinaryOpVal, UDiv, UDIV); }
udiv { RET_TOK(BinaryOpVal, UDiv, UDIV); }
sdiv { RET_TOK(BinaryOpVal, SDiv, SDIV); }
fdiv { RET_TOK(BinaryOpVal, FDiv, FDIV); }
rem { RET_TOK(BinaryOpVal, Rem, REM); }
and { RET_TOK(BinaryOpVal, And, AND); }
or { RET_TOK(BinaryOpVal, Or , OR ); }
Expand Down
16 changes: 16 additions & 0 deletions lib/AsmParser/ParserInternals.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,20 @@ struct ValID {

} // End llvm namespace

// This structure is used to keep track of obsolete opcodes. The lexer will
// retain the ability to parse obsolete opcode mnemonics. In this case it will
// set "obsolete" to true and the opcode will be the replacement opcode. For
// example if "rem" is encountered then opcode will be set to "urem" and the
// "obsolete" flag will be true. If the opcode is not obsolete then "obsolete"
// will be false.
template <class Enum>
struct OpcodeInfo {
Enum opcode;
bool obsolete;
};
typedef OpcodeInfo<llvm::Instruction::BinaryOps> BinaryOpInfo;
typedef OpcodeInfo<llvm::Instruction::TermOps> TermOpInfo;
typedef OpcodeInfo<llvm::Instruction::MemoryOps> MemOpInfo;
typedef OpcodeInfo<llvm::Instruction::OtherOps> OtherOpInfo;

#endif
Loading

0 comments on commit 1628cec

Please sign in to comment.