For PR950:

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
This commit is contained in:
Reid Spencer 2006-10-26 06:15:43 +00:00
parent 7043d00750
commit 1628cec4d7
32 changed files with 3086 additions and 1944 deletions

View File

@ -77,7 +77,9 @@
<li><a href="#i_add">'<tt>add</tt>' Instruction</a></li> <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_sub">'<tt>sub</tt>' Instruction</a></li>
<li><a href="#i_mul">'<tt>mul</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_rem">'<tt>rem</tt>' Instruction</a></li>
<li><a href="#i_setcc">'<tt>set<i>cc</i></tt>' Instructions</a></li> <li><a href="#i_setcc">'<tt>set<i>cc</i></tt>' Instructions</a></li>
</ol> </ol>
@ -1630,26 +1632,70 @@ action is taken based on the type of the operand.</p>
</pre> </pre>
</div> </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> Instruction</a> </div>
<div class="doc_text"> <div class="doc_text">
<h5>Syntax:</h5> <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> </pre>
<h5>Overview:</h5> <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> operands.</p>
<h5>Arguments:</h5> <h5>Arguments:</h5>
<p>The two arguments to the '<tt>div</tt>' instruction must be either <a <p>The two arguments to the '<tt>div</tt>' instruction must be
href="#t_integer">integer</a> or <a href="#t_floating">floating point</a> <a href="#t_floating">floating point</a> values. Both arguments must have
values. identical types. This instruction can also take <a href="#t_packed">packed</a>
This instruction can also take <a href="#t_packed">packed</a> versions of the values. versions of the values in which case the elements must be floating point.</p>
Both arguments must have identical types.</p>
<h5>Semantics:</h5> <h5>Semantics:</h5>
<p>The value produced is the integer or floating point quotient of the <p>The value produced is the floating point quotient of the two operands.</p>
two operands.</p>
<h5>Example:</h5> <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> </pre>
</div> </div>
<!-- _______________________________________________________________________ --> <!-- _______________________________________________________________________ -->

View File

@ -140,7 +140,7 @@ namespace llvm {
const Type *Ty = S->getType(); const Type *Ty = S->getType();
Value *LHS = expandInTy(S->getLHS(), Ty); Value *LHS = expandInTy(S->getLHS(), Ty);
Value *RHS = expandInTy(S->getRHS(), 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); Value *visitAddRecExpr(SCEVAddRecExpr *S);

View File

@ -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 { class SCEVSDivExpr : public SCEV {
SCEVHandle LHS, RHS; SCEVHandle LHS, RHS;

View File

@ -543,7 +543,9 @@ public:
static Constant *getAdd(Constant *C1, Constant *C2); static Constant *getAdd(Constant *C1, Constant *C2);
static Constant *getSub(Constant *C1, Constant *C2); static Constant *getSub(Constant *C1, Constant *C2);
static Constant *getMul(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 *getRem(Constant *C1, Constant *C2);
static Constant *getAnd(Constant *C1, Constant *C2); static Constant *getAnd(Constant *C1, Constant *C2);
static Constant *getOr(Constant *C1, Constant *C2); static Constant *getOr(Constant *C1, Constant *C2);

View File

@ -93,45 +93,43 @@ HANDLE_TERM_INST ( 6, Unreachable, UnreachableInst)
HANDLE_BINARY_INST( 7, Add , BinaryOperator) HANDLE_BINARY_INST( 7, Add , BinaryOperator)
HANDLE_BINARY_INST( 8, Sub , BinaryOperator) HANDLE_BINARY_INST( 8, Sub , BinaryOperator)
HANDLE_BINARY_INST( 9, Mul , BinaryOperator) HANDLE_BINARY_INST( 9, Mul , BinaryOperator)
HANDLE_BINARY_INST(10, Div , BinaryOperator) HANDLE_BINARY_INST(10, UDiv , BinaryOperator)
HANDLE_BINARY_INST(11, Rem , BinaryOperator) HANDLE_BINARY_INST(11, SDiv , BinaryOperator)
HANDLE_BINARY_INST(12, FDiv , BinaryOperator)
HANDLE_BINARY_INST(13, Rem , BinaryOperator)
// Logical operators... // Logical operators...
HANDLE_BINARY_INST(12, And , BinaryOperator) HANDLE_BINARY_INST(14, And , BinaryOperator)
HANDLE_BINARY_INST(13, Or , BinaryOperator) HANDLE_BINARY_INST(15, Or , BinaryOperator)
HANDLE_BINARY_INST(14, Xor , BinaryOperator) HANDLE_BINARY_INST(16, Xor , BinaryOperator)
// Binary comparison operators... // Binary comparison operators...
HANDLE_BINARY_INST(15, SetEQ , SetCondInst) HANDLE_BINARY_INST(17, SetEQ , SetCondInst)
HANDLE_BINARY_INST(16, SetNE , SetCondInst) HANDLE_BINARY_INST(18, SetNE , SetCondInst)
HANDLE_BINARY_INST(17, SetLE , SetCondInst) HANDLE_BINARY_INST(19, SetLE , SetCondInst)
HANDLE_BINARY_INST(18, SetGE , SetCondInst) HANDLE_BINARY_INST(20, SetGE , SetCondInst)
HANDLE_BINARY_INST(19, SetLT , SetCondInst) HANDLE_BINARY_INST(21, SetLT , SetCondInst)
HANDLE_BINARY_INST(20, SetGT , SetCondInst) HANDLE_BINARY_INST(22, SetGT , SetCondInst)
LAST_BINARY_INST(20) LAST_BINARY_INST(22)
// Memory operators... // Memory operators...
FIRST_MEMORY_INST(21) FIRST_MEMORY_INST(23)
HANDLE_MEMORY_INST(21, Malloc, MallocInst) // Heap management instructions HANDLE_MEMORY_INST(23, Malloc, MallocInst) // Heap management instructions
HANDLE_MEMORY_INST(22, Free , FreeInst ) HANDLE_MEMORY_INST(24, Free , FreeInst )
HANDLE_MEMORY_INST(23, Alloca, AllocaInst) // Stack management HANDLE_MEMORY_INST(25, Alloca, AllocaInst) // Stack management
HANDLE_MEMORY_INST(24, Load , LoadInst ) // Memory manipulation instrs HANDLE_MEMORY_INST(26, Load , LoadInst ) // Memory manipulation instrs
HANDLE_MEMORY_INST(25, Store , StoreInst ) HANDLE_MEMORY_INST(27, Store , StoreInst )
HANDLE_MEMORY_INST(26, GetElementPtr, GetElementPtrInst) HANDLE_MEMORY_INST(28, GetElementPtr, GetElementPtrInst)
LAST_MEMORY_INST(26) LAST_MEMORY_INST(28)
// Other operators... // Other operators...
FIRST_OTHER_INST(27) FIRST_OTHER_INST(29)
HANDLE_OTHER_INST(27, PHI , PHINode ) // PHI node instruction HANDLE_OTHER_INST(29, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(28, Cast , CastInst ) // Type cast HANDLE_OTHER_INST(30, Cast , CastInst ) // Type cast
HANDLE_OTHER_INST(29, Call , CallInst ) // Call a function HANDLE_OTHER_INST(31, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(32, Shl , ShiftInst ) // Shift operations
HANDLE_OTHER_INST(30, Shl , ShiftInst ) // Shift operations HANDLE_OTHER_INST(33, Shr , ShiftInst )
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.
HANDLE_OTHER_INST(34, Select , SelectInst ) // select instruction HANDLE_OTHER_INST(34, Select , SelectInst ) // select instruction
HANDLE_OTHER_INST(35, UserOp1, Instruction) // May be used internally in a pass HANDLE_OTHER_INST(35, UserOp1, Instruction) // May be used internally in a pass
HANDLE_OTHER_INST(36, UserOp2, Instruction) HANDLE_OTHER_INST(36, UserOp2, Instruction)
HANDLE_OTHER_INST(37, VAArg , VAArgInst ) // vaarg instruction HANDLE_OTHER_INST(37, VAArg , VAArgInst ) // vaarg instruction

View File

@ -112,9 +112,21 @@ inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS &L,
} }
template<typename LHS, typename RHS> 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) { 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> template<typename LHS, typename RHS>

View File

@ -989,9 +989,9 @@ SCEVHandle SCEVMulExpr::get(std::vector<SCEVHandle> &Ops) {
SCEVHandle SCEVSDivExpr::get(const SCEVHandle &LHS, const SCEVHandle &RHS) { SCEVHandle SCEVSDivExpr::get(const SCEVHandle &LHS, const SCEVHandle &RHS) {
if (SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS)) { if (SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS)) {
if (RHSC->getValue()->equalsInt(1)) if (RHSC->getValue()->equalsInt(1))
return LHS; // X /s 1 --> x return LHS; // X sdiv 1 --> x
if (RHSC->getValue()->isAllOnesValue()) 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)) { if (SCEVConstant *LHSC = dyn_cast<SCEVConstant>(LHS)) {
Constant *LHSCV = LHSC->getValue(); Constant *LHSCV = LHSC->getValue();
@ -1001,7 +1001,7 @@ SCEVHandle SCEVSDivExpr::get(const SCEVHandle &LHS, const SCEVHandle &RHS) {
LHSCV->getType()->getSignedVersion()); LHSCV->getType()->getSignedVersion());
if (RHSCV->getType()->isUnsigned()) if (RHSCV->getType()->isUnsigned())
RHSCV = ConstantExpr::getCast(RHSCV, LHSCV->getType()); RHSCV = ConstantExpr::getCast(RHSCV, LHSCV->getType());
return SCEVUnknown::get(ConstantExpr::getDiv(LHSCV, RHSCV)); return SCEVUnknown::get(ConstantExpr::getSDiv(LHSCV, RHSCV));
} }
} }
@ -1384,8 +1384,7 @@ SCEVHandle ScalarEvolutionsImpl::createSCEV(Value *V) {
case Instruction::Mul: case Instruction::Mul:
return SCEVMulExpr::get(getSCEV(I->getOperand(0)), return SCEVMulExpr::get(getSCEV(I->getOperand(0)),
getSCEV(I->getOperand(1))); getSCEV(I->getOperand(1)));
case Instruction::Div: case Instruction::SDiv:
if (V->getType()->isInteger() && V->getType()->isSigned())
return SCEVSDivExpr::get(getSCEV(I->getOperand(0)), return SCEVSDivExpr::get(getSCEV(I->getOperand(0)),
getSCEV(I->getOperand(1))); getSCEV(I->getOperand(1)));
break; break;
@ -2058,16 +2057,16 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec) {
return std::make_pair(CNC, CNC); 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 // Convert from chrec coefficients to polynomial coefficients AX^2+BX+C
Constant *C = L->getValue();
// The B coefficient is M-N/2 // The B coefficient is M-N/2
Constant *B = ConstantExpr::getSub(M->getValue(), Constant *B = ConstantExpr::getSub(M->getValue(),
ConstantExpr::getDiv(N->getValue(), ConstantExpr::getSDiv(N->getValue(),
Two)); Two));
// The A coefficient is N/2 // 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. // Compute the B^2-4ac term.
Constant *SqrtTerm = Constant *SqrtTerm =
@ -2102,9 +2101,9 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec) {
SqrtTerm = ConstantExpr::getCast(SqrtTerm, SignedTy); SqrtTerm = ConstantExpr::getCast(SqrtTerm, SignedTy);
Constant *Solution1 = Constant *Solution1 =
ConstantExpr::getDiv(ConstantExpr::getAdd(NegB, SqrtTerm), TwoA); ConstantExpr::getSDiv(ConstantExpr::getAdd(NegB, SqrtTerm), TwoA);
Constant *Solution2 = Constant *Solution2 =
ConstantExpr::getDiv(ConstantExpr::getSub(NegB, SqrtTerm), TwoA); ConstantExpr::getSDiv(ConstantExpr::getSub(NegB, SqrtTerm), TwoA);
return std::make_pair(SCEVUnknown::get(Solution1), return std::make_pair(SCEVUnknown::get(Solution1),
SCEVUnknown::get(Solution2)); SCEVUnknown::get(Solution2));
} }
@ -2150,7 +2149,7 @@ SCEVHandle ScalarEvolutionsImpl::HowFarToZero(SCEV *V, const Loop *L) {
Constant *StartNegC = ConstantExpr::getNeg(StartCC); Constant *StartNegC = ConstantExpr::getNeg(StartCC);
Constant *Rem = ConstantExpr::getRem(StartNegC, StepC->getValue()); Constant *Rem = ConstantExpr::getRem(StartNegC, StepC->getValue());
if (Rem->isNullValue()) { if (Rem->isNullValue()) {
Constant *Result =ConstantExpr::getDiv(StartNegC,StepC->getValue()); Constant *Result =ConstantExpr::getSDiv(StartNegC,StepC->getValue());
return SCEVUnknown::get(Result); return SCEVUnknown::get(Result);
} }
} }
@ -2352,7 +2351,7 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
Constant *ExitValue = Upper; Constant *ExitValue = Upper;
if (A != One) { if (A != One) {
ExitValue = ConstantExpr::getSub(ConstantExpr::getAdd(Upper, A), One); ExitValue = ConstantExpr::getSub(ConstantExpr::getAdd(Upper, A), One);
ExitValue = ConstantExpr::getDiv(ExitValue, A); ExitValue = ConstantExpr::getSDiv(ExitValue, A);
} }
assert(isa<ConstantInt>(ExitValue) && assert(isa<ConstantInt>(ExitValue) &&
"Constant folding of integers not implemented?"); "Constant folding of integers not implemented?");

View File

@ -39,8 +39,18 @@ void set_scan_string (const char * str) {
yy_scan_string (str); yy_scan_string (str);
} }
// Construct a token value for a non-obsolete token
#define RET_TOK(type, Enum, sym) \ #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 { namespace llvm {
@ -247,7 +257,10 @@ opaque { return OPAQUE; }
add { RET_TOK(BinaryOpVal, Add, ADD); } add { RET_TOK(BinaryOpVal, Add, ADD); }
sub { RET_TOK(BinaryOpVal, Sub, SUB); } sub { RET_TOK(BinaryOpVal, Sub, SUB); }
mul { RET_TOK(BinaryOpVal, Mul, MUL); } 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); } rem { RET_TOK(BinaryOpVal, Rem, REM); }
and { RET_TOK(BinaryOpVal, And, AND); } and { RET_TOK(BinaryOpVal, And, AND); }
or { RET_TOK(BinaryOpVal, Or , OR ); } or { RET_TOK(BinaryOpVal, Or , OR ); }

View File

@ -201,4 +201,20 @@ struct ValID {
} // End llvm namespace } // 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 #endif

File diff suppressed because it is too large Load Diff

View File

@ -107,34 +107,36 @@
ADD = 333, ADD = 333,
SUB = 334, SUB = 334,
MUL = 335, MUL = 335,
DIV = 336, UDIV = 336,
REM = 337, SDIV = 337,
AND = 338, FDIV = 338,
OR = 339, REM = 339,
XOR = 340, AND = 340,
SETLE = 341, OR = 341,
SETGE = 342, XOR = 342,
SETLT = 343, SETLE = 343,
SETGT = 344, SETGE = 344,
SETEQ = 345, SETLT = 345,
SETNE = 346, SETGT = 346,
MALLOC = 347, SETEQ = 347,
ALLOCA = 348, SETNE = 348,
FREE = 349, MALLOC = 349,
LOAD = 350, ALLOCA = 350,
STORE = 351, FREE = 351,
GETELEMENTPTR = 352, LOAD = 352,
PHI_TOK = 353, STORE = 353,
CAST = 354, GETELEMENTPTR = 354,
SELECT = 355, PHI_TOK = 355,
SHL = 356, CAST = 356,
SHR = 357, SELECT = 357,
VAARG = 358, SHL = 358,
EXTRACTELEMENT = 359, SHR = 359,
INSERTELEMENT = 360, VAARG = 360,
SHUFFLEVECTOR = 361, EXTRACTELEMENT = 361,
VAARG_old = 362, INSERTELEMENT = 362,
VANEXT_old = 363 SHUFFLEVECTOR = 363,
VAARG_old = 364,
VANEXT_old = 365
}; };
#endif #endif
/* Tokens. */ /* Tokens. */
@ -216,40 +218,42 @@
#define ADD 333 #define ADD 333
#define SUB 334 #define SUB 334
#define MUL 335 #define MUL 335
#define DIV 336 #define UDIV 336
#define REM 337 #define SDIV 337
#define AND 338 #define FDIV 338
#define OR 339 #define REM 339
#define XOR 340 #define AND 340
#define SETLE 341 #define OR 341
#define SETGE 342 #define XOR 342
#define SETLT 343 #define SETLE 343
#define SETGT 344 #define SETGE 344
#define SETEQ 345 #define SETLT 345
#define SETNE 346 #define SETGT 346
#define MALLOC 347 #define SETEQ 347
#define ALLOCA 348 #define SETNE 348
#define FREE 349 #define MALLOC 349
#define LOAD 350 #define ALLOCA 350
#define STORE 351 #define FREE 351
#define GETELEMENTPTR 352 #define LOAD 352
#define PHI_TOK 353 #define STORE 353
#define CAST 354 #define GETELEMENTPTR 354
#define SELECT 355 #define PHI_TOK 355
#define SHL 356 #define CAST 356
#define SHR 357 #define SELECT 357
#define VAARG 358 #define SHL 358
#define EXTRACTELEMENT 359 #define SHR 359
#define INSERTELEMENT 360 #define VAARG 360
#define SHUFFLEVECTOR 361 #define EXTRACTELEMENT 361
#define VAARG_old 362 #define INSERTELEMENT 362
#define VANEXT_old 363 #define SHUFFLEVECTOR 363
#define VAARG_old 364
#define VANEXT_old 365
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
#line 974 "/proj/llvm/llvm_nc/lib/AsmParser/llvmAsmParser.y" #line 1011 "/proj/llvm/llvm/lib/AsmParser/llvmAsmParser.y"
typedef union YYSTYPE { typedef union YYSTYPE {
llvm::Module *ModuleVal; llvm::Module *ModuleVal;
llvm::Function *FunctionVal; llvm::Function *FunctionVal;
@ -283,14 +287,14 @@ typedef union YYSTYPE {
char *StrVal; // This memory is strdup'd! char *StrVal; // This memory is strdup'd!
llvm::ValID ValIDVal; // strdup'd memory maybe! llvm::ValID ValIDVal; // strdup'd memory maybe!
llvm::Instruction::BinaryOps BinaryOpVal; BinaryOpInfo BinaryOpVal;
llvm::Instruction::TermOps TermOpVal; TermOpInfo TermOpVal;
llvm::Instruction::MemoryOps MemOpVal; MemOpInfo MemOpVal;
llvm::Instruction::OtherOps OtherOpVal; OtherOpInfo OtherOpVal;
llvm::Module::Endianness Endianness; llvm::Module::Endianness Endianness;
} YYSTYPE; } YYSTYPE;
/* Line 1447 of yacc.c. */ /* Line 1447 of yacc.c. */
#line 294 "llvmAsmParser.tab.h" #line 298 "llvmAsmParser.tab.h"
# define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_TRIVIAL 1

View File

@ -813,6 +813,43 @@ static PATypeHolder HandleUpRefs(const Type *ty) {
return Ty; return Ty;
} }
/// This function is used to obtain the correct opcode for an instruction when
/// an obsolete opcode is encountered. The OI parameter (OpcodeInfo) has both
/// an opcode and an "obsolete" flag. These are generated by the lexer and
/// the "obsolete" member will be true when the lexer encounters the token for
/// an obsolete opcode. For example, "div" was replaced by [usf]div but we need
/// to maintain backwards compatibility for asm files that still have the "div"
/// instruction. This function handles converting div -> [usf]div appropriately.
/// @brief Convert obsolete opcodes to new values
static void
sanitizeOpCode(OpcodeInfo<Instruction::BinaryOps> &OI, const PATypeHolder& PATy)
{
// If its not obsolete, don't do anything
if (!OI.obsolete)
return;
// If its a packed type we want to use the element type
const Type* Ty = PATy;
if (const PackedType* PTy = dyn_cast<PackedType>(Ty))
Ty = PTy->getElementType();
// Depending on the opcode ..
switch (OI.opcode) {
default:
GenerateError("Invalid Obsolete OpCode");
break;
case Instruction::UDiv:
// Handle cases where the opcode needs to change
if (Ty->isFloatingPoint())
OI.opcode = Instruction::FDiv;
else if (Ty->isSigned())
OI.opcode = Instruction::SDiv;
break;
}
// Its not obsolete any more, we fixed it.
OI.obsolete = false;
}
// common code from the two 'RunVMAsmParser' functions // common code from the two 'RunVMAsmParser' functions
static Module* RunParser(Module * M) { static Module* RunParser(Module * M) {
@ -1004,10 +1041,10 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
char *StrVal; // This memory is strdup'd! char *StrVal; // This memory is strdup'd!
llvm::ValID ValIDVal; // strdup'd memory maybe! llvm::ValID ValIDVal; // strdup'd memory maybe!
llvm::Instruction::BinaryOps BinaryOpVal; BinaryOpInfo BinaryOpVal;
llvm::Instruction::TermOps TermOpVal; TermOpInfo TermOpVal;
llvm::Instruction::MemoryOps MemOpVal; MemOpInfo MemOpVal;
llvm::Instruction::OtherOps OtherOpVal; OtherOpInfo OtherOpVal;
llvm::Module::Endianness Endianness; llvm::Module::Endianness Endianness;
} }
@ -1076,8 +1113,8 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
// Binary Operators // Binary Operators
%type <BinaryOpVal> ArithmeticOps LogicalOps SetCondOps // Binops Subcatagories %type <BinaryOpVal> ArithmeticOps LogicalOps SetCondOps // Binops Subcatagories
%token <BinaryOpVal> ADD SUB MUL DIV REM AND OR XOR %token <BinaryOpVal> ADD SUB MUL UDIV SDIV FDIV REM AND OR XOR
%token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comarators %token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comparators
// Memory Instructions // Memory Instructions
%token <MemOpVal> MALLOC ALLOCA FREE LOAD STORE GETELEMENTPTR %token <MemOpVal> MALLOC ALLOCA FREE LOAD STORE GETELEMENTPTR
@ -1114,7 +1151,7 @@ EINT64VAL : EUINT64VAL {
// Operations that are notably excluded from this list include: // Operations that are notably excluded from this list include:
// RET, BR, & SWITCH because they end basic blocks and are treated specially. // RET, BR, & SWITCH because they end basic blocks and are treated specially.
// //
ArithmeticOps: ADD | SUB | MUL | DIV | REM; ArithmeticOps: ADD | SUB | MUL | UDIV | SDIV | FDIV | REM ;
LogicalOps : AND | OR | XOR; LogicalOps : AND | OR | XOR;
SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE; SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
@ -1642,12 +1679,17 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
| ArithmeticOps '(' ConstVal ',' ConstVal ')' { | ArithmeticOps '(' ConstVal ',' ConstVal ')' {
if ($3->getType() != $5->getType()) if ($3->getType() != $5->getType())
GEN_ERROR("Binary operator types must match!"); GEN_ERROR("Binary operator types must match!");
// First, make sure we're dealing with the right opcode by upgrading from
// obsolete versions.
sanitizeOpCode($1,$3->getType());
CHECK_FOR_ERROR;
// HACK: llvm 1.3 and earlier used to emit invalid pointer constant exprs. // HACK: llvm 1.3 and earlier used to emit invalid pointer constant exprs.
// To retain backward compatibility with these early compilers, we emit a // To retain backward compatibility with these early compilers, we emit a
// cast to the appropriate integer type automatically if we are in the // cast to the appropriate integer type automatically if we are in the
// broken case. See PR424 for more information. // broken case. See PR424 for more information.
if (!isa<PointerType>($3->getType())) { if (!isa<PointerType>($3->getType())) {
$$ = ConstantExpr::get($1, $3, $5); $$ = ConstantExpr::get($1.opcode, $3, $5);
} else { } else {
const Type *IntPtrTy = 0; const Type *IntPtrTy = 0;
switch (CurModule.CurrentModule->getPointerSize()) { switch (CurModule.CurrentModule->getPointerSize()) {
@ -1655,7 +1697,7 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
case Module::Pointer64: IntPtrTy = Type::LongTy; break; case Module::Pointer64: IntPtrTy = Type::LongTy; break;
default: GEN_ERROR("invalid pointer binary constant expr!"); default: GEN_ERROR("invalid pointer binary constant expr!");
} }
$$ = ConstantExpr::get($1, ConstantExpr::getCast($3, IntPtrTy), $$ = ConstantExpr::get($1.opcode, ConstantExpr::getCast($3, IntPtrTy),
ConstantExpr::getCast($5, IntPtrTy)); ConstantExpr::getCast($5, IntPtrTy));
$$ = ConstantExpr::getCast($$, $3->getType()); $$ = ConstantExpr::getCast($$, $3->getType());
} }
@ -1669,13 +1711,13 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
!cast<PackedType>($3->getType())->getElementType()->isIntegral()) !cast<PackedType>($3->getType())->getElementType()->isIntegral())
GEN_ERROR("Logical operator requires integral operands!"); GEN_ERROR("Logical operator requires integral operands!");
} }
$$ = ConstantExpr::get($1, $3, $5); $$ = ConstantExpr::get($1.opcode, $3, $5);
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| SetCondOps '(' ConstVal ',' ConstVal ')' { | SetCondOps '(' ConstVal ',' ConstVal ')' {
if ($3->getType() != $5->getType()) if ($3->getType() != $5->getType())
GEN_ERROR("setcc operand types must match!"); GEN_ERROR("setcc operand types must match!");
$$ = ConstantExpr::get($1, $3, $5); $$ = ConstantExpr::get($1.opcode, $3, $5);
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| ShiftOps '(' ConstVal ',' ConstVal ')' { | ShiftOps '(' ConstVal ',' ConstVal ')' {
@ -1683,7 +1725,7 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
GEN_ERROR("Shift count for shift constant must be unsigned byte!"); GEN_ERROR("Shift count for shift constant must be unsigned byte!");
if (!$3->getType()->isInteger()) if (!$3->getType()->isInteger())
GEN_ERROR("Shift constant expression requires integer operand!"); GEN_ERROR("Shift constant expression requires integer operand!");
$$ = ConstantExpr::get($1, $3, $5); $$ = ConstantExpr::get($1.opcode, $3, $5);
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| EXTRACTELEMENT '(' ConstVal ',' ConstVal ')' { | EXTRACTELEMENT '(' ConstVal ',' ConstVal ')' {
@ -2423,13 +2465,16 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
!isa<PackedType>((*$2).get())) !isa<PackedType>((*$2).get()))
GEN_ERROR( GEN_ERROR(
"Arithmetic operator requires integer, FP, or packed operands!"); "Arithmetic operator requires integer, FP, or packed operands!");
if (isa<PackedType>((*$2).get()) && $1 == Instruction::Rem) if (isa<PackedType>((*$2).get()) && $1.opcode == Instruction::Rem)
GEN_ERROR("Rem not supported on packed types!"); GEN_ERROR("Rem not supported on packed types!");
// Upgrade the opcode from obsolete versions before we do anything with it.
sanitizeOpCode($1,*$2);
CHECK_FOR_ERROR;
Value* val1 = getVal(*$2, $3); Value* val1 = getVal(*$2, $3);
CHECK_FOR_ERROR CHECK_FOR_ERROR
Value* val2 = getVal(*$2, $5); Value* val2 = getVal(*$2, $5);
CHECK_FOR_ERROR CHECK_FOR_ERROR
$$ = BinaryOperator::create($1, val1, val2); $$ = BinaryOperator::create($1.opcode, val1, val2);
if ($$ == 0) if ($$ == 0)
GEN_ERROR("binary operator returned null!"); GEN_ERROR("binary operator returned null!");
delete $2; delete $2;
@ -2444,7 +2489,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
CHECK_FOR_ERROR CHECK_FOR_ERROR
Value* tmpVal2 = getVal(*$2, $5); Value* tmpVal2 = getVal(*$2, $5);
CHECK_FOR_ERROR CHECK_FOR_ERROR
$$ = BinaryOperator::create($1, tmpVal1, tmpVal2); $$ = BinaryOperator::create($1.opcode, tmpVal1, tmpVal2);
if ($$ == 0) if ($$ == 0)
GEN_ERROR("binary operator returned null!"); GEN_ERROR("binary operator returned null!");
delete $2; delete $2;
@ -2458,7 +2503,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
CHECK_FOR_ERROR CHECK_FOR_ERROR
Value* tmpVal2 = getVal(*$2, $5); Value* tmpVal2 = getVal(*$2, $5);
CHECK_FOR_ERROR CHECK_FOR_ERROR
$$ = new SetCondInst($1, tmpVal1, tmpVal2); $$ = new SetCondInst($1.opcode, tmpVal1, tmpVal2);
if ($$ == 0) if ($$ == 0)
GEN_ERROR("binary operator returned null!"); GEN_ERROR("binary operator returned null!");
delete $2; delete $2;
@ -2481,7 +2526,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
GEN_ERROR("Shift amount must be ubyte!"); GEN_ERROR("Shift amount must be ubyte!");
if (!$2->getType()->isInteger()) if (!$2->getType()->isInteger())
GEN_ERROR("Shift constant expression requires integer operand!"); GEN_ERROR("Shift constant expression requires integer operand!");
$$ = new ShiftInst($1, $2, $4); $$ = new ShiftInst($1.opcode, $2, $4);
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| CAST ResolvedVal TO Types { | CAST ResolvedVal TO Types {

View File

@ -813,6 +813,43 @@ static PATypeHolder HandleUpRefs(const Type *ty) {
return Ty; return Ty;
} }
/// This function is used to obtain the correct opcode for an instruction when
/// an obsolete opcode is encountered. The OI parameter (OpcodeInfo) has both
/// an opcode and an "obsolete" flag. These are generated by the lexer and
/// the "obsolete" member will be true when the lexer encounters the token for
/// an obsolete opcode. For example, "div" was replaced by [usf]div but we need
/// to maintain backwards compatibility for asm files that still have the "div"
/// instruction. This function handles converting div -> [usf]div appropriately.
/// @brief Convert obsolete opcodes to new values
static void
sanitizeOpCode(OpcodeInfo<Instruction::BinaryOps> &OI, const PATypeHolder& PATy)
{
// If its not obsolete, don't do anything
if (!OI.obsolete)
return;
// If its a packed type we want to use the element type
const Type* Ty = PATy;
if (const PackedType* PTy = dyn_cast<PackedType>(Ty))
Ty = PTy->getElementType();
// Depending on the opcode ..
switch (OI.opcode) {
default:
GenerateError("Invalid Obsolete OpCode");
break;
case Instruction::UDiv:
// Handle cases where the opcode needs to change
if (Ty->isFloatingPoint())
OI.opcode = Instruction::FDiv;
else if (Ty->isSigned())
OI.opcode = Instruction::SDiv;
break;
}
// Its not obsolete any more, we fixed it.
OI.obsolete = false;
}
// common code from the two 'RunVMAsmParser' functions // common code from the two 'RunVMAsmParser' functions
static Module* RunParser(Module * M) { static Module* RunParser(Module * M) {
@ -1004,10 +1041,10 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
char *StrVal; // This memory is strdup'd! char *StrVal; // This memory is strdup'd!
llvm::ValID ValIDVal; // strdup'd memory maybe! llvm::ValID ValIDVal; // strdup'd memory maybe!
llvm::Instruction::BinaryOps BinaryOpVal; BinaryOpInfo BinaryOpVal;
llvm::Instruction::TermOps TermOpVal; TermOpInfo TermOpVal;
llvm::Instruction::MemoryOps MemOpVal; MemOpInfo MemOpVal;
llvm::Instruction::OtherOps OtherOpVal; OtherOpInfo OtherOpVal;
llvm::Module::Endianness Endianness; llvm::Module::Endianness Endianness;
} }
@ -1076,8 +1113,8 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
// Binary Operators // Binary Operators
%type <BinaryOpVal> ArithmeticOps LogicalOps SetCondOps // Binops Subcatagories %type <BinaryOpVal> ArithmeticOps LogicalOps SetCondOps // Binops Subcatagories
%token <BinaryOpVal> ADD SUB MUL DIV REM AND OR XOR %token <BinaryOpVal> ADD SUB MUL UDIV SDIV FDIV REM AND OR XOR
%token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comarators %token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comparators
// Memory Instructions // Memory Instructions
%token <MemOpVal> MALLOC ALLOCA FREE LOAD STORE GETELEMENTPTR %token <MemOpVal> MALLOC ALLOCA FREE LOAD STORE GETELEMENTPTR
@ -1114,7 +1151,7 @@ EINT64VAL : EUINT64VAL {
// Operations that are notably excluded from this list include: // Operations that are notably excluded from this list include:
// RET, BR, & SWITCH because they end basic blocks and are treated specially. // RET, BR, & SWITCH because they end basic blocks and are treated specially.
// //
ArithmeticOps: ADD | SUB | MUL | DIV | REM; ArithmeticOps: ADD | SUB | MUL | UDIV | SDIV | FDIV | REM ;
LogicalOps : AND | OR | XOR; LogicalOps : AND | OR | XOR;
SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE; SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
@ -1642,12 +1679,17 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
| ArithmeticOps '(' ConstVal ',' ConstVal ')' { | ArithmeticOps '(' ConstVal ',' ConstVal ')' {
if ($3->getType() != $5->getType()) if ($3->getType() != $5->getType())
GEN_ERROR("Binary operator types must match!"); GEN_ERROR("Binary operator types must match!");
// First, make sure we're dealing with the right opcode by upgrading from
// obsolete versions.
sanitizeOpCode($1,$3->getType());
CHECK_FOR_ERROR;
// HACK: llvm 1.3 and earlier used to emit invalid pointer constant exprs. // HACK: llvm 1.3 and earlier used to emit invalid pointer constant exprs.
// To retain backward compatibility with these early compilers, we emit a // To retain backward compatibility with these early compilers, we emit a
// cast to the appropriate integer type automatically if we are in the // cast to the appropriate integer type automatically if we are in the
// broken case. See PR424 for more information. // broken case. See PR424 for more information.
if (!isa<PointerType>($3->getType())) { if (!isa<PointerType>($3->getType())) {
$$ = ConstantExpr::get($1, $3, $5); $$ = ConstantExpr::get($1.opcode, $3, $5);
} else { } else {
const Type *IntPtrTy = 0; const Type *IntPtrTy = 0;
switch (CurModule.CurrentModule->getPointerSize()) { switch (CurModule.CurrentModule->getPointerSize()) {
@ -1655,7 +1697,7 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
case Module::Pointer64: IntPtrTy = Type::LongTy; break; case Module::Pointer64: IntPtrTy = Type::LongTy; break;
default: GEN_ERROR("invalid pointer binary constant expr!"); default: GEN_ERROR("invalid pointer binary constant expr!");
} }
$$ = ConstantExpr::get($1, ConstantExpr::getCast($3, IntPtrTy), $$ = ConstantExpr::get($1.opcode, ConstantExpr::getCast($3, IntPtrTy),
ConstantExpr::getCast($5, IntPtrTy)); ConstantExpr::getCast($5, IntPtrTy));
$$ = ConstantExpr::getCast($$, $3->getType()); $$ = ConstantExpr::getCast($$, $3->getType());
} }
@ -1669,13 +1711,13 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
!cast<PackedType>($3->getType())->getElementType()->isIntegral()) !cast<PackedType>($3->getType())->getElementType()->isIntegral())
GEN_ERROR("Logical operator requires integral operands!"); GEN_ERROR("Logical operator requires integral operands!");
} }
$$ = ConstantExpr::get($1, $3, $5); $$ = ConstantExpr::get($1.opcode, $3, $5);
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| SetCondOps '(' ConstVal ',' ConstVal ')' { | SetCondOps '(' ConstVal ',' ConstVal ')' {
if ($3->getType() != $5->getType()) if ($3->getType() != $5->getType())
GEN_ERROR("setcc operand types must match!"); GEN_ERROR("setcc operand types must match!");
$$ = ConstantExpr::get($1, $3, $5); $$ = ConstantExpr::get($1.opcode, $3, $5);
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| ShiftOps '(' ConstVal ',' ConstVal ')' { | ShiftOps '(' ConstVal ',' ConstVal ')' {
@ -1683,7 +1725,7 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
GEN_ERROR("Shift count for shift constant must be unsigned byte!"); GEN_ERROR("Shift count for shift constant must be unsigned byte!");
if (!$3->getType()->isInteger()) if (!$3->getType()->isInteger())
GEN_ERROR("Shift constant expression requires integer operand!"); GEN_ERROR("Shift constant expression requires integer operand!");
$$ = ConstantExpr::get($1, $3, $5); $$ = ConstantExpr::get($1.opcode, $3, $5);
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| EXTRACTELEMENT '(' ConstVal ',' ConstVal ')' { | EXTRACTELEMENT '(' ConstVal ',' ConstVal ')' {
@ -2423,13 +2465,16 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
!isa<PackedType>((*$2).get())) !isa<PackedType>((*$2).get()))
GEN_ERROR( GEN_ERROR(
"Arithmetic operator requires integer, FP, or packed operands!"); "Arithmetic operator requires integer, FP, or packed operands!");
if (isa<PackedType>((*$2).get()) && $1 == Instruction::Rem) if (isa<PackedType>((*$2).get()) && $1.opcode == Instruction::Rem)
GEN_ERROR("Rem not supported on packed types!"); GEN_ERROR("Rem not supported on packed types!");
// Upgrade the opcode from obsolete versions before we do anything with it.
sanitizeOpCode($1,*$2);
CHECK_FOR_ERROR;
Value* val1 = getVal(*$2, $3); Value* val1 = getVal(*$2, $3);
CHECK_FOR_ERROR CHECK_FOR_ERROR
Value* val2 = getVal(*$2, $5); Value* val2 = getVal(*$2, $5);
CHECK_FOR_ERROR CHECK_FOR_ERROR
$$ = BinaryOperator::create($1, val1, val2); $$ = BinaryOperator::create($1.opcode, val1, val2);
if ($$ == 0) if ($$ == 0)
GEN_ERROR("binary operator returned null!"); GEN_ERROR("binary operator returned null!");
delete $2; delete $2;
@ -2444,7 +2489,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
CHECK_FOR_ERROR CHECK_FOR_ERROR
Value* tmpVal2 = getVal(*$2, $5); Value* tmpVal2 = getVal(*$2, $5);
CHECK_FOR_ERROR CHECK_FOR_ERROR
$$ = BinaryOperator::create($1, tmpVal1, tmpVal2); $$ = BinaryOperator::create($1.opcode, tmpVal1, tmpVal2);
if ($$ == 0) if ($$ == 0)
GEN_ERROR("binary operator returned null!"); GEN_ERROR("binary operator returned null!");
delete $2; delete $2;
@ -2458,7 +2503,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
CHECK_FOR_ERROR CHECK_FOR_ERROR
Value* tmpVal2 = getVal(*$2, $5); Value* tmpVal2 = getVal(*$2, $5);
CHECK_FOR_ERROR CHECK_FOR_ERROR
$$ = new SetCondInst($1, tmpVal1, tmpVal2); $$ = new SetCondInst($1.opcode, tmpVal1, tmpVal2);
if ($$ == 0) if ($$ == 0)
GEN_ERROR("binary operator returned null!"); GEN_ERROR("binary operator returned null!");
delete $2; delete $2;
@ -2481,7 +2526,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
GEN_ERROR("Shift amount must be ubyte!"); GEN_ERROR("Shift amount must be ubyte!");
if (!$2->getType()->isInteger()) if (!$2->getType()->isInteger())
GEN_ERROR("Shift constant expression requires integer operand!"); GEN_ERROR("Shift constant expression requires integer operand!");
$$ = new ShiftInst($1, $2, $4); $$ = new ShiftInst($1.opcode, $2, $4);
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| CAST ResolvedVal TO Types { | CAST ResolvedVal TO Types {

View File

@ -562,6 +562,244 @@ void BytecodeReader::insertArguments(Function* F) {
insertValue(AI, getTypeSlot(AI->getType()), FunctionValues); insertValue(AI, getTypeSlot(AI->getType()), FunctionValues);
} }
// Convert previous opcode values into the current value and/or construct
// the instruction. This function handles all *abnormal* cases for instruction
// generation based on obsolete opcode values. The normal cases are handled
// in ParseInstruction below. Generally this function just produces a new
// Opcode value (first argument). In a few cases (VAArg, VANext) the upgrade
// path requies that the instruction (sequence) be generated differently from
// the normal case in order to preserve the original semantics. In these
// cases the result of the function will be a non-zero Instruction pointer. In
// all other cases, zero will be returned indicating that the *normal*
// instruction generation should be used, but with the new Opcode value.
//
Instruction*
BytecodeReader::handleObsoleteOpcodes(
unsigned &Opcode, ///< The old opcode, possibly updated by this function
std::vector<unsigned> &Oprnds, ///< The operands to the instruction
unsigned &iType, ///< The type code from the bytecode file
const Type* InstTy, ///< The type of the instruction
BasicBlock* BB ///< The basic block to insert into, if we need to
) {
// First, short circuit this if no conversion is required. When signless
// instructions were implemented the entire opcode sequence was revised so
// we key on this first which means that the opcode value read is the one
// we should use.
if (!hasSignlessInstructions)
return 0; // The opcode is fine the way it is.
// Declare the resulting instruction we might build. In general we just
// change the Opcode argument but in a few cases we need to generate the
// Instruction here because the upgrade case is significantly different from
// the normal case.
Instruction *Result = 0;
// If this is a bytecode format that did not include the unreachable
// instruction, bump up the opcode number to adjust it.
if (hasNoUnreachableInst)
if (Opcode >= Instruction::Unreachable && Opcode < 62)
++Opcode;
// We're dealing with an upgrade situation. For each of the opcode values,
// perform the necessary conversion.
switch (Opcode) {
default: // Error
// This switch statement provides cases for all known opcodes prior to
// version 6 bytecode format. We know we're in an upgrade situation so
// if there isn't a match in this switch, then something is horribly
// wrong.
error("Unknown obsolete opcode encountered.");
break;
case 1: // Ret
Opcode = Instruction::Ret;
break;
case 2: // Br
Opcode = Instruction::Br;
break;
case 3: // Switch
Opcode = Instruction::Switch;
break;
case 4: // Invoke
Opcode = Instruction::Invoke;
break;
case 5: // Unwind
Opcode = Instruction::Unwind;
break;
case 6: // Unreachable
Opcode = Instruction::Unreachable;
break;
case 7: // Add
Opcode = Instruction::Add;
break;
case 8: // Sub
Opcode = Instruction::Sub;
break;
case 9: // Mul
Opcode = Instruction::Mul;
break;
case 10: // Div
// The type of the instruction is based on the operands. We need to select
// fdiv, udiv or sdiv based on that type. The iType values are hardcoded
// to the values used in bytecode version 5 (and prior) because it is
// likely these codes will change in future versions of LLVM.
if (iType == 10 || iType == 11 )
Opcode = Instruction::FDiv;
else if (iType >= 2 && iType <= 9 && iType % 2 != 0)
Opcode = Instruction::SDiv;
else
Opcode = Instruction::UDiv;
break;
case 11: // Rem
Opcode = Instruction::Rem;
break;
case 12: // And
Opcode = Instruction::And;
break;
case 13: // Or
Opcode = Instruction::Or;
break;
case 14: // Xor
Opcode = Instruction::Xor;
break;
case 15: // SetEQ
Opcode = Instruction::SetEQ;
break;
case 16: // SetNE
Opcode = Instruction::SetNE;
break;
case 17: // SetLE
Opcode = Instruction::SetLE;
break;
case 18: // SetGE
Opcode = Instruction::SetGE;
break;
case 19: // SetLT
Opcode = Instruction::SetLT;
break;
case 20: // SetGT
Opcode = Instruction::SetGT;
break;
case 21: // Malloc
Opcode = Instruction::Malloc;
break;
case 22: // Free
Opcode = Instruction::Free;
break;
case 23: // Alloca
Opcode = Instruction::Alloca;
break;
case 24: // Load
Opcode = Instruction::Load;
break;
case 25: // Store
Opcode = Instruction::Store;
break;
case 26: // GetElementPtr
Opcode = Instruction::GetElementPtr;
break;
case 27: // PHI
Opcode = Instruction::PHI;
break;
case 28: // Cast
Opcode = Instruction::Cast;
break;
case 29: // Call
Opcode = Instruction::Call;
break;
case 30: // Shl
Opcode = Instruction::Shl;
break;
case 31: // Shr
Opcode = Instruction::Shr;
break;
case 32: { //VANext_old ( <= llvm 1.5 )
const Type* ArgTy = getValue(iType, Oprnds[0])->getType();
Function* NF = TheModule->getOrInsertFunction(
"llvm.va_copy", ArgTy, ArgTy, (Type *)0);
// In llvm 1.6 the VANext instruction was dropped because it was only
// necessary to have a VAArg instruction. The code below transforms an
// old vanext instruction into the equivalent code given only the
// availability of the new vaarg instruction. Essentially, the transform
// is as follows:
// b = vanext a, t ->
// foo = alloca 1 of t
// bar = vacopy a
// store bar -> foo
// tmp = vaarg foo, t
// b = load foo
AllocaInst* foo = new AllocaInst(ArgTy, 0, "vanext.fix");
BB->getInstList().push_back(foo);
CallInst* bar = new CallInst(NF, getValue(iType, Oprnds[0]));
BB->getInstList().push_back(bar);
BB->getInstList().push_back(new StoreInst(bar, foo));
Instruction* tmp = new VAArgInst(foo, getSanitizedType(Oprnds[1]));
BB->getInstList().push_back(tmp);
Result = new LoadInst(foo);
break;
}
case 33: { //VAArg_old
const Type* ArgTy = getValue(iType, Oprnds[0])->getType();
Function* NF = TheModule->getOrInsertFunction(
"llvm.va_copy", ArgTy, ArgTy, (Type *)0);
// In llvm 1.6 the VAArg's instruction semantics were changed. The code
// below transforms an old vaarg instruction into the equivalent code
// given only the availability of the new vaarg instruction. Essentially,
// the transform is as follows:
// b = vaarg a, t ->
// foo = alloca 1 of t
// bar = vacopy a
// store bar -> foo
// b = vaarg foo, t
AllocaInst* foo = new AllocaInst(ArgTy, 0, "vaarg.fix");
BB->getInstList().push_back(foo);
CallInst* bar = new CallInst(NF, getValue(iType, Oprnds[0]));
BB->getInstList().push_back(bar);
BB->getInstList().push_back(new StoreInst(bar, foo));
Result = new VAArgInst(foo, getSanitizedType(Oprnds[1]));
break;
}
case 34: // Select
Opcode = Instruction::Select;
break;
case 35: // UserOp1
Opcode = Instruction::UserOp1;
break;
case 36: // UserOp2
Opcode = Instruction::UserOp2;
break;
case 37: // VAArg
Opcode = Instruction::VAArg;
break;
case 38: // ExtractElement
Opcode = Instruction::ExtractElement;
break;
case 39: // InsertElement
Opcode = Instruction::InsertElement;
break;
case 40: // ShuffleVector
Opcode = Instruction::ShuffleVector;
break;
case 56: // Invoke with encoded CC
case 57: // Invoke Fast CC
case 58: // Call with extra operand for calling conv
case 59: // tail call, Fast CC
case 60: // normal call, Fast CC
case 61: // tail call, C Calling Conv
case 62: // volatile load
case 63: // volatile store
// In all these cases, we pass the opcode through. The new version uses
// the same code (for now, this might change in 2.0). These are listed
// here to document the opcodes in use in vers 5 bytecode and to make it
// easier to migrate these opcodes in the future.
break;
}
return Result;
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Bytecode Parsing Methods // Bytecode Parsing Methods
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -643,77 +881,38 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
const Type *InstTy = getSanitizedType(iType); const Type *InstTy = getSanitizedType(iType);
// Make the necessary adjustments for dealing with backwards compatibility
// of opcodes.
Instruction* Result =
handleObsoleteOpcodes(Opcode, Oprnds, iType, InstTy, BB);
// We have enough info to inform the handler now. // We have enough info to inform the handler now.
if (Handler) Handler->handleInstruction(Opcode, InstTy, Oprnds, At-SaveAt); if (Handler)
Handler->handleInstruction(Opcode, InstTy, Oprnds, At-SaveAt);
// Declare the resulting instruction we'll build. // If the backwards compatibility code didn't produce an instruction then
Instruction *Result = 0; // we do the *normal* thing ..
if (!Result) {
// If this is a bytecode format that did not include the unreachable // First, handle the easy binary operators case
// instruction, bump up all opcodes numbers to make space.
if (hasNoUnreachableInst) {
if (Opcode >= Instruction::Unreachable &&
Opcode < 62) {
++Opcode;
}
}
// Handle binary operators
if (Opcode >= Instruction::BinaryOpsBegin && if (Opcode >= Instruction::BinaryOpsBegin &&
Opcode < Instruction::BinaryOpsEnd && Oprnds.size() == 2) Opcode < Instruction::BinaryOpsEnd && Oprnds.size() == 2)
Result = BinaryOperator::create((Instruction::BinaryOps)Opcode, Result = BinaryOperator::create(Instruction::BinaryOps(Opcode),
getValue(iType, Oprnds[0]), getValue(iType, Oprnds[0]),
getValue(iType, Oprnds[1])); getValue(iType, Oprnds[1]));
bool isCall = false; // Indicate that we don't think this is a call instruction (yet).
// Process based on the Opcode read
switch (Opcode) { switch (Opcode) {
default: default: // There was an error, this shouldn't happen.
if (Result == 0) if (Result == 0)
error("Illegal instruction read!"); error("Illegal instruction read!");
break; break;
case Instruction::VAArg: case Instruction::VAArg:
if (Oprnds.size() != 2)
error("Invalid VAArg instruction!");
Result = new VAArgInst(getValue(iType, Oprnds[0]), Result = new VAArgInst(getValue(iType, Oprnds[0]),
getSanitizedType(Oprnds[1])); getSanitizedType(Oprnds[1]));
break; break;
case 32: { //VANext_old
const Type* ArgTy = getValue(iType, Oprnds[0])->getType();
Function* NF = TheModule->getOrInsertFunction("llvm.va_copy", ArgTy, ArgTy,
(Type *)0);
//b = vanext a, t ->
//foo = alloca 1 of t
//bar = vacopy a
//store bar -> foo
//tmp = vaarg foo, t
//b = load foo
AllocaInst* foo = new AllocaInst(ArgTy, 0, "vanext.fix");
BB->getInstList().push_back(foo);
CallInst* bar = new CallInst(NF, getValue(iType, Oprnds[0]));
BB->getInstList().push_back(bar);
BB->getInstList().push_back(new StoreInst(bar, foo));
Instruction* tmp = new VAArgInst(foo, getSanitizedType(Oprnds[1]));
BB->getInstList().push_back(tmp);
Result = new LoadInst(foo);
break;
}
case 33: { //VAArg_old
const Type* ArgTy = getValue(iType, Oprnds[0])->getType();
Function* NF = TheModule->getOrInsertFunction("llvm.va_copy", ArgTy, ArgTy,
(Type *)0);
//b = vaarg a, t ->
//foo = alloca 1 of t
//bar = vacopy a
//store bar -> foo
//b = vaarg foo, t
AllocaInst* foo = new AllocaInst(ArgTy, 0, "vaarg.fix");
BB->getInstList().push_back(foo);
CallInst* bar = new CallInst(NF, getValue(iType, Oprnds[0]));
BB->getInstList().push_back(bar);
BB->getInstList().push_back(new StoreInst(bar, foo));
Result = new VAArgInst(foo, getSanitizedType(Oprnds[1]));
break;
}
case Instruction::ExtractElement: { case Instruction::ExtractElement: {
if (Oprnds.size() != 2) if (Oprnds.size() != 2)
error("Invalid extractelement instruction!"); error("Invalid extractelement instruction!");
@ -755,10 +954,14 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
break; break;
} }
case Instruction::Cast: case Instruction::Cast:
if (Oprnds.size() != 2)
error("Invalid Cast instruction!");
Result = new CastInst(getValue(iType, Oprnds[0]), Result = new CastInst(getValue(iType, Oprnds[0]),
getSanitizedType(Oprnds[1])); getSanitizedType(Oprnds[1]));
break; break;
case Instruction::Select: case Instruction::Select:
if (Oprnds.size() != 3)
error("Invalid Select instruction!");
Result = new SelectInst(getValue(Type::BoolTyID, Oprnds[0]), Result = new SelectInst(getValue(Type::BoolTyID, Oprnds[0]),
getValue(iType, Oprnds[1]), getValue(iType, Oprnds[1]),
getValue(iType, Oprnds[2])); getValue(iType, Oprnds[2]));
@ -770,14 +973,15 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
PHINode *PN = new PHINode(InstTy); PHINode *PN = new PHINode(InstTy);
PN->reserveOperandSpace(Oprnds.size()); PN->reserveOperandSpace(Oprnds.size());
for (unsigned i = 0, e = Oprnds.size(); i != e; i += 2) for (unsigned i = 0, e = Oprnds.size(); i != e; i += 2)
PN->addIncoming(getValue(iType, Oprnds[i]), getBasicBlock(Oprnds[i+1])); PN->addIncoming(
getValue(iType, Oprnds[i]), getBasicBlock(Oprnds[i+1]));
Result = PN; Result = PN;
break; break;
} }
case Instruction::Shl: case Instruction::Shl:
case Instruction::Shr: case Instruction::Shr:
Result = new ShiftInst((Instruction::OtherOps)Opcode, Result = new ShiftInst(Instruction::OtherOps(Opcode),
getValue(iType, Oprnds[0]), getValue(iType, Oprnds[0]),
getValue(Type::UByteTyID, Oprnds[1])); getValue(Type::UByteTyID, Oprnds[1]));
break; break;
@ -812,7 +1016,6 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
Result = I; Result = I;
break; break;
} }
case 58: // Call with extra operand for calling conv case 58: // Call with extra operand for calling conv
case 59: // tail call, Fast CC case 59: // tail call, Fast CC
case 60: // normal call, Fast CC case 60: // normal call, Fast CC
@ -863,7 +1066,8 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
// Read all of the fixed arguments // Read all of the fixed arguments
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
Params.push_back(getValue(getTypeSlot(FTy->getParamType(i)),Oprnds[i])); Params.push_back(
getValue(getTypeSlot(FTy->getParamType(i)),Oprnds[i]));
FirstVariableOperand = FTy->getNumParams(); FirstVariableOperand = FTy->getNumParams();
@ -929,7 +1133,8 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
Params.push_back(getValue(getTypeSlot(FTy->getParamType(i-2)), Params.push_back(getValue(getTypeSlot(FTy->getParamType(i-2)),
Oprnds[i])); Oprnds[i]));
if (Oprnds.size()-FirstVariableArgument & 1) // Must be type/value pairs // Must be type/value pairs. If not, error out.
if (Oprnds.size()-FirstVariableArgument & 1)
error("Invalid invoke instruction!"); error("Invalid invoke instruction!");
for (unsigned i = FirstVariableArgument; i < Oprnds.size(); i += 2) for (unsigned i = FirstVariableArgument; i < Oprnds.size(); i += 2)
@ -953,7 +1158,6 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
getValue(Type::UIntTyID, Oprnds[0]), Align); getValue(Type::UIntTyID, Oprnds[0]), Align);
break; break;
} }
case Instruction::Alloca: { case Instruction::Alloca: {
unsigned Align = 0; unsigned Align = 0;
if (Oprnds.size() == 2) if (Oprnds.size() == 2)
@ -987,9 +1191,9 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
unsigned ValIdx = Oprnds[i]; unsigned ValIdx = Oprnds[i];
unsigned IdxTy = 0; unsigned IdxTy = 0;
if (!hasRestrictedGEPTypes) { if (!hasRestrictedGEPTypes) {
// Struct indices are always uints, sequential type indices can be any // Struct indices are always uints, sequential type indices can be
// of the 32 or 64-bit integer types. The actual choice of type is // any of the 32 or 64-bit integer types. The actual choice of
// encoded in the low two bits of the slot number. // type is encoded in the low two bits of the slot number.
if (isa<StructType>(TopTy)) if (isa<StructType>(TopTy))
IdxTy = Type::UIntTyID; IdxTy = Type::UIntTyID;
else { else {
@ -1020,14 +1224,12 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
Result = new GetElementPtrInst(getValue(iType, Oprnds[0]), Idx); Result = new GetElementPtrInst(getValue(iType, Oprnds[0]), Idx);
break; break;
} }
case 62: // volatile load case 62: // volatile load
case Instruction::Load: case Instruction::Load:
if (Oprnds.size() != 1 || !isa<PointerType>(InstTy)) if (Oprnds.size() != 1 || !isa<PointerType>(InstTy))
error("Invalid load instruction!"); error("Invalid load instruction!");
Result = new LoadInst(getValue(iType, Oprnds[0]), "", Opcode == 62); Result = new LoadInst(getValue(iType, Oprnds[0]), "", Opcode == 62);
break; break;
case 63: // volatile store case 63: // volatile store
case Instruction::Store: { case Instruction::Store: {
if (!isa<PointerType>(InstTy) || Oprnds.size() != 2) if (!isa<PointerType>(InstTy) || Oprnds.size() != 2)
@ -1048,6 +1250,7 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
Result = new UnreachableInst(); Result = new UnreachableInst();
break; break;
} // end switch(Opcode) } // end switch(Opcode)
} // end if *normal*
BB->getInstList().push_back(Result); BB->getInstList().push_back(Result);
@ -1414,6 +1617,110 @@ void BytecodeReader::ParseTypes(TypeListTy &Tab, unsigned NumEntries){
} }
} }
// Upgrade obsolete constant expression opcodes (ver. 5 and prior) to the new
// values used after ver 6. bytecode format. The operands are provided to the
// function so that decisions based on the operand type can be made when
// auto-upgrading obsolete opcodes to the new ones.
// NOTE: This code needs to be kept synchronized with handleObsoleteOpcodes.
// We can't use that function because of that functions argument requirements.
// This function only deals with the subset of opcodes that are applicable to
// constant expressions and is therefore simpler than handleObsoleteOpcodes.
inline unsigned fixCEOpcodes(
unsigned Opcode, const std::vector<Constant*> &ArgVec
) {
switch (Opcode) {
default: // Pass Through
// If we don't match any of the cases here then the opcode is fine the
// way it is.
break;
case 7: // Add
Opcode = Instruction::Add;
break;
case 8: // Sub
Opcode = Instruction::Sub;
break;
case 9: // Mul
Opcode = Instruction::Mul;
break;
case 10: // Div
// The type of the instruction is based on the operands. We need to select
// either udiv or sdiv based on that type. This expression selects the
// cases where the type is floating point or signed in which case we
// generated an sdiv instruction.
if (ArgVec[0]->getType()->isFloatingPoint())
Opcode = Instruction::FDiv;
else if (ArgVec[0]->getType()->isSigned())
Opcode = Instruction::SDiv;
else
Opcode = Instruction::UDiv;
break;
case 11: // Rem
// As with "Div", make the signed/unsigned Rem instruction choice based
// on the type of the instruction.
if (ArgVec[0]->getType()->isFloatingPoint())
Opcode = Instruction::Rem;
else if (ArgVec[0]->getType()->isSigned())
Opcode = Instruction::Rem;
else
Opcode = Instruction::Rem;
break;
case 12: // And
Opcode = Instruction::And;
break;
case 13: // Or
Opcode = Instruction::Or;
break;
case 14: // Xor
Opcode = Instruction::Xor;
break;
case 15: // SetEQ
Opcode = Instruction::SetEQ;
break;
case 16: // SetNE
Opcode = Instruction::SetNE;
break;
case 17: // SetLE
Opcode = Instruction::SetLE;
break;
case 18: // SetGE
Opcode = Instruction::SetGE;
break;
case 19: // SetLT
Opcode = Instruction::SetLT;
break;
case 20: // SetGT
Opcode = Instruction::SetGT;
break;
case 26: // GetElementPtr
Opcode = Instruction::GetElementPtr;
break;
case 28: // Cast
Opcode = Instruction::Cast;
break;
case 30: // Shl
Opcode = Instruction::Shl;
break;
case 31: // Shr
Opcode = Instruction::Shr;
break;
case 34: // Select
Opcode = Instruction::Select;
break;
case 38: // ExtractElement
Opcode = Instruction::ExtractElement;
break;
case 39: // InsertElement
Opcode = Instruction::InsertElement;
break;
case 40: // ShuffleVector
Opcode = Instruction::ShuffleVector;
break;
}
return Opcode;
}
/// Parse a single constant value /// Parse a single constant value
Value *BytecodeReader::ParseConstantPoolValue(unsigned TypeID) { Value *BytecodeReader::ParseConstantPoolValue(unsigned TypeID) {
// We must check for a ConstantExpr before switching by type because // We must check for a ConstantExpr before switching by type because
@ -1468,6 +1775,10 @@ Value *BytecodeReader::ParseConstantPoolValue(unsigned TypeID) {
ArgVec.push_back(getConstantValue(ArgTypeSlot, ArgValSlot)); ArgVec.push_back(getConstantValue(ArgTypeSlot, ArgValSlot));
} }
// Handle backwards compatibility for the opcode numbers
if (hasSignlessInstructions)
Opcode = fixCEOpcodes(Opcode, ArgVec);
// Construct a ConstantExpr of the appropriate kind // Construct a ConstantExpr of the appropriate kind
if (isExprNumArgs == 1) { // All one-operand expressions if (isExprNumArgs == 1) { // All one-operand expressions
if (Opcode != Instruction::Cast) if (Opcode != Instruction::Cast)
@ -2240,7 +2551,10 @@ void BytecodeReader::ParseVersionInfo() {
hasNoUndefValue = false; hasNoUndefValue = false;
hasNoFlagsForFunctions = false; hasNoFlagsForFunctions = false;
hasNoUnreachableInst = false; hasNoUnreachableInst = false;
hasSignlessInstructions = false;
// Determine which backwards compatibility flags to set based on the
// bytecode file's version number
switch (RevisionNum) { switch (RevisionNum) {
case 0: // LLVM 1.0, 1.1 (Released) case 0: // LLVM 1.0, 1.1 (Released)
// Base LLVM 1.0 bytecode format. // Base LLVM 1.0 bytecode format.
@ -2311,11 +2625,21 @@ void BytecodeReader::ParseVersionInfo() {
// In version 4 and above, we did not include the 'unreachable' instruction // In version 4 and above, we did not include the 'unreachable' instruction
// in the opcode numbering in the bytecode file. // in the opcode numbering in the bytecode file.
hasNoUnreachableInst = true; hasNoUnreachableInst = true;
break;
// FALL THROUGH // FALL THROUGH
case 5: // 1.4 (Released) case 5: // 1.4 (Released)
// In version 5 and prior, instructions were signless while integer types
// were signed. In version 6, instructions became signed and types became
// signless. For example in version 5 we have the DIV instruction but in
// version 6 we have FDIV, SDIV and UDIV to replace it. This caused a
// renumbering of the instruction codes in version 6 that must be dealt with
// when reading old bytecode files.
hasSignlessInstructions = true;
// FALL THROUGH
case 6: // SignlessTypes Implementation (1.9 release)
break; break;
default: default:

View File

@ -226,6 +226,18 @@ protected:
Function* F ///< The function into which BBs will be inserted Function* F ///< The function into which BBs will be inserted
); );
/// Convert previous opcode values into the current value and/or construct
/// the instruction. This function handles all *abnormal* cases for
/// instruction generation based on obsolete opcode values. The normal cases
/// are handled by the ParseInstruction function.
Instruction* handleObsoleteOpcodes(
unsigned &opcode, ///< The old opcode, possibly updated by this function
std::vector<unsigned> &Oprnds, ///< The operands to the instruction
unsigned &iType, ///< The type code from the bytecode file
const Type* InstTy, ///< The type of the instruction
BasicBlock* BB ///< The basic block to insert into, if we need to
);
/// @brief Parse a single instruction. /// @brief Parse a single instruction.
void ParseInstruction( void ParseInstruction(
std::vector<unsigned>& Args, ///< The arguments to be filled in std::vector<unsigned>& Args, ///< The arguments to be filled in
@ -336,6 +348,13 @@ private:
// unreachable instruction. // unreachable instruction.
bool hasNoUnreachableInst; bool hasNoUnreachableInst;
// In version 5 and prior, instructions were signless. In version 6,
// instructions became signed. For example in version 5 we have the DIV
// instruction but in version 6 we have FDIV, SDIV and UDIV to replace it.
// This causes a renumbering of the instruction codes in version 6 that must
// be dealt with when reading old bytecode files.
bool hasSignlessInstructions;
/// In release 1.7 we changed intrinsic functions to not be overloaded. There /// In release 1.7 we changed intrinsic functions to not be overloaded. There
/// is no bytecode change for this, but to optimize the auto-upgrade of calls /// is no bytecode change for this, but to optimize the auto-upgrade of calls
/// to intrinsic functions, we save a mapping of old function definitions to /// to intrinsic functions, we save a mapping of old function definitions to

View File

@ -40,7 +40,7 @@ using namespace llvm;
/// so that the reader can distinguish which format of the bytecode file has /// so that the reader can distinguish which format of the bytecode file has
/// been written. /// been written.
/// @brief The bytecode version number /// @brief The bytecode version number
const unsigned BCVersionNum = 5; const unsigned BCVersionNum = 6;
static RegisterPass<WriteBytecodePass> X("emitbytecode", "Bytecode Writer"); static RegisterPass<WriteBytecodePass> X("emitbytecode", "Bytecode Writer");

View File

@ -499,28 +499,35 @@ public:
void visitInvoke(InvokeInst &I) { assert(0 && "TODO"); } void visitInvoke(InvokeInst &I) { assert(0 && "TODO"); }
void visitUnwind(UnwindInst &I) { assert(0 && "TODO"); } void visitUnwind(UnwindInst &I) { assert(0 && "TODO"); }
void visitBinary(User &I, unsigned IntOp, unsigned FPOp, unsigned VecOp); void visitIntBinary(User &I, unsigned IntOp, unsigned VecOp);
void visitFPBinary(User &I, unsigned FPOp, unsigned VecOp);
void visitShift(User &I, unsigned Opcode); void visitShift(User &I, unsigned Opcode);
void visitAdd(User &I) { void visitAdd(User &I) {
visitBinary(I, ISD::ADD, ISD::FADD, ISD::VADD); if (I.getType()->isFloatingPoint())
visitFPBinary(I, ISD::FADD, ISD::VADD);
else
visitIntBinary(I, ISD::ADD, ISD::VADD);
} }
void visitSub(User &I); void visitSub(User &I);
void visitMul(User &I) { void visitMul(User &I) {
visitBinary(I, ISD::MUL, ISD::FMUL, ISD::VMUL); if (I.getType()->isFloatingPoint())
} visitFPBinary(I, ISD::FMUL, ISD::VMUL);
void visitDiv(User &I) { else
const Type *Ty = I.getType(); visitIntBinary(I, ISD::MUL, ISD::VMUL);
visitBinary(I,
Ty->isSigned() ? ISD::SDIV : ISD::UDIV, ISD::FDIV,
Ty->isSigned() ? ISD::VSDIV : ISD::VUDIV);
} }
void visitUDiv(User &I) { visitIntBinary(I, ISD::UDIV, ISD::VUDIV); }
void visitSDiv(User &I) { visitIntBinary(I, ISD::SDIV, ISD::VSDIV); }
void visitFDiv(User &I) { visitFPBinary(I, ISD::FDIV, ISD::VSDIV); }
void visitRem(User &I) { void visitRem(User &I) {
const Type *Ty = I.getType(); const Type *Ty = I.getType();
visitBinary(I, Ty->isSigned() ? ISD::SREM : ISD::UREM, ISD::FREM, 0); if (Ty->isFloatingPoint())
visitFPBinary(I, ISD::FREM, 0);
else
visitIntBinary(I, Ty->isSigned() ? ISD::SREM : ISD::UREM, 0);
} }
void visitAnd(User &I) { visitBinary(I, ISD::AND, 0, ISD::VAND); } void visitAnd(User &I) { visitIntBinary(I, ISD::AND, ISD::VAND); }
void visitOr (User &I) { visitBinary(I, ISD::OR, 0, ISD::VOR); } void visitOr (User &I) { visitIntBinary(I, ISD::OR, ISD::VOR); }
void visitXor(User &I) { visitBinary(I, ISD::XOR, 0, ISD::VXOR); } void visitXor(User &I) { visitIntBinary(I, ISD::XOR, ISD::VXOR); }
void visitShl(User &I) { visitShift(I, ISD::SHL); } void visitShl(User &I) { visitShift(I, ISD::SHL); }
void visitShr(User &I) { void visitShr(User &I) {
visitShift(I, I.getType()->isUnsigned() ? ISD::SRL : ISD::SRA); visitShift(I, I.getType()->isUnsigned() ? ISD::SRL : ISD::SRA);
@ -1142,25 +1149,38 @@ void SelectionDAGLowering::visitSub(User &I) {
setValue(&I, DAG.getNode(ISD::FNEG, Op2.getValueType(), Op2)); setValue(&I, DAG.getNode(ISD::FNEG, Op2.getValueType(), Op2));
return; return;
} }
} visitFPBinary(I, ISD::FSUB, ISD::VSUB);
visitBinary(I, ISD::SUB, ISD::FSUB, ISD::VSUB); } else
visitIntBinary(I, ISD::SUB, ISD::VSUB);
} }
void SelectionDAGLowering::visitBinary(User &I, unsigned IntOp, unsigned FPOp, void
unsigned VecOp) { SelectionDAGLowering::visitIntBinary(User &I, unsigned IntOp, unsigned VecOp) {
const Type *Ty = I.getType(); const Type *Ty = I.getType();
SDOperand Op1 = getValue(I.getOperand(0)); SDOperand Op1 = getValue(I.getOperand(0));
SDOperand Op2 = getValue(I.getOperand(1)); SDOperand Op2 = getValue(I.getOperand(1));
if (Ty->isIntegral()) { if (const PackedType *PTy = dyn_cast<PackedType>(Ty)) {
setValue(&I, DAG.getNode(IntOp, Op1.getValueType(), Op1, Op2));
} else if (Ty->isFloatingPoint()) {
setValue(&I, DAG.getNode(FPOp, Op1.getValueType(), Op1, Op2));
} else {
const PackedType *PTy = cast<PackedType>(Ty);
SDOperand Num = DAG.getConstant(PTy->getNumElements(), MVT::i32); SDOperand Num = DAG.getConstant(PTy->getNumElements(), MVT::i32);
SDOperand Typ = DAG.getValueType(TLI.getValueType(PTy->getElementType())); SDOperand Typ = DAG.getValueType(TLI.getValueType(PTy->getElementType()));
setValue(&I, DAG.getNode(VecOp, MVT::Vector, Op1, Op2, Num, Typ)); setValue(&I, DAG.getNode(VecOp, MVT::Vector, Op1, Op2, Num, Typ));
} else {
setValue(&I, DAG.getNode(IntOp, Op1.getValueType(), Op1, Op2));
}
}
void
SelectionDAGLowering::visitFPBinary(User &I, unsigned FPOp, unsigned VecOp) {
const Type *Ty = I.getType();
SDOperand Op1 = getValue(I.getOperand(0));
SDOperand Op2 = getValue(I.getOperand(1));
if (const PackedType *PTy = dyn_cast<PackedType>(Ty)) {
SDOperand Num = DAG.getConstant(PTy->getNumElements(), MVT::i32);
SDOperand Typ = DAG.getValueType(TLI.getValueType(PTy->getElementType()));
setValue(&I, DAG.getNode(VecOp, MVT::Vector, Op1, Op2, Num, Typ));
} else {
setValue(&I, DAG.getNode(FPOp, Op1.getValueType(), Op1, Op2));
} }
} }

View File

@ -42,7 +42,11 @@ static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2,
const Type *Ty); const Type *Ty);
static GenericValue executeRemInst(GenericValue Src1, GenericValue Src2, static GenericValue executeRemInst(GenericValue Src1, GenericValue Src2,
const Type *Ty); const Type *Ty);
static GenericValue executeDivInst(GenericValue Src1, GenericValue Src2, static GenericValue executeUDivInst(GenericValue Src1, GenericValue Src2,
const Type *Ty);
static GenericValue executeSDivInst(GenericValue Src1, GenericValue Src2,
const Type *Ty);
static GenericValue executeFDivInst(GenericValue Src1, GenericValue Src2,
const Type *Ty); const Type *Ty);
static GenericValue executeAndInst(GenericValue Src1, GenericValue Src2, static GenericValue executeAndInst(GenericValue Src1, GenericValue Src2,
const Type *Ty); const Type *Ty);
@ -89,8 +93,16 @@ GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE,
return executeMulInst(getOperandValue(CE->getOperand(0), SF), return executeMulInst(getOperandValue(CE->getOperand(0), SF),
getOperandValue(CE->getOperand(1), SF), getOperandValue(CE->getOperand(1), SF),
CE->getOperand(0)->getType()); CE->getOperand(0)->getType());
case Instruction::Div: case Instruction::SDiv:
return executeDivInst(getOperandValue(CE->getOperand(0), SF), return executeSDivInst(getOperandValue(CE->getOperand(0), SF),
getOperandValue(CE->getOperand(1), SF),
CE->getOperand(0)->getType());
case Instruction::UDiv:
return executeUDivInst(getOperandValue(CE->getOperand(0), SF),
getOperandValue(CE->getOperand(1), SF),
CE->getOperand(0)->getType());
case Instruction::FDiv:
return executeFDivInst(getOperandValue(CE->getOperand(0), SF),
getOperandValue(CE->getOperand(1), SF), getOperandValue(CE->getOperand(1), SF),
CE->getOperand(0)->getType()); CE->getOperand(0)->getType());
case Instruction::Rem: case Instruction::Rem:
@ -242,18 +254,44 @@ static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2,
return Dest; return Dest;
} }
static GenericValue executeDivInst(GenericValue Src1, GenericValue Src2, static GenericValue executeUDivInst(GenericValue Src1, GenericValue Src2,
const Type *Ty) {
GenericValue Dest;
if (Ty->isSigned())
Ty = Ty->getUnsignedVersion();
switch (Ty->getTypeID()) {
IMPLEMENT_BINARY_OPERATOR(/, UByte);
IMPLEMENT_BINARY_OPERATOR(/, UShort);
IMPLEMENT_BINARY_OPERATOR(/, UInt);
IMPLEMENT_BINARY_OPERATOR(/, ULong);
default:
std::cout << "Unhandled type for UDiv instruction: " << *Ty << "\n";
abort();
}
return Dest;
}
static GenericValue executeSDivInst(GenericValue Src1, GenericValue Src2,
const Type *Ty) {
GenericValue Dest;
if (Ty->isUnsigned())
Ty = Ty->getSignedVersion();
switch (Ty->getTypeID()) {
IMPLEMENT_BINARY_OPERATOR(/, SByte);
IMPLEMENT_BINARY_OPERATOR(/, Short);
IMPLEMENT_BINARY_OPERATOR(/, Int);
IMPLEMENT_BINARY_OPERATOR(/, Long);
default:
std::cout << "Unhandled type for SDiv instruction: " << *Ty << "\n";
abort();
}
return Dest;
}
static GenericValue executeFDivInst(GenericValue Src1, GenericValue Src2,
const Type *Ty) { const Type *Ty) {
GenericValue Dest; GenericValue Dest;
switch (Ty->getTypeID()) { switch (Ty->getTypeID()) {
IMPLEMENT_BINARY_OPERATOR(/, UByte);
IMPLEMENT_BINARY_OPERATOR(/, SByte);
IMPLEMENT_BINARY_OPERATOR(/, UShort);
IMPLEMENT_BINARY_OPERATOR(/, Short);
IMPLEMENT_BINARY_OPERATOR(/, UInt);
IMPLEMENT_BINARY_OPERATOR(/, Int);
IMPLEMENT_BINARY_OPERATOR(/, ULong);
IMPLEMENT_BINARY_OPERATOR(/, Long);
IMPLEMENT_BINARY_OPERATOR(/, Float); IMPLEMENT_BINARY_OPERATOR(/, Float);
IMPLEMENT_BINARY_OPERATOR(/, Double); IMPLEMENT_BINARY_OPERATOR(/, Double);
default: default:
@ -504,7 +542,9 @@ void Interpreter::visitBinaryOperator(BinaryOperator &I) {
case Instruction::Add: R = executeAddInst (Src1, Src2, Ty); break; case Instruction::Add: R = executeAddInst (Src1, Src2, Ty); break;
case Instruction::Sub: R = executeSubInst (Src1, Src2, Ty); break; case Instruction::Sub: R = executeSubInst (Src1, Src2, Ty); break;
case Instruction::Mul: R = executeMulInst (Src1, Src2, Ty); break; case Instruction::Mul: R = executeMulInst (Src1, Src2, Ty); break;
case Instruction::Div: R = executeDivInst (Src1, Src2, Ty); break; case Instruction::UDiv: R = executeUDivInst (Src1, Src2, Ty); break;
case Instruction::SDiv: R = executeSDivInst (Src1, Src2, Ty); break;
case Instruction::FDiv: R = executeFDivInst (Src1, Src2, Ty); break;
case Instruction::Rem: R = executeRemInst (Src1, Src2, Ty); break; case Instruction::Rem: R = executeRemInst (Src1, Src2, Ty); break;
case Instruction::And: R = executeAndInst (Src1, Src2, Ty); break; case Instruction::And: R = executeAndInst (Src1, Src2, Ty); break;
case Instruction::Or: R = executeOrInst (Src1, Src2, Ty); break; case Instruction::Or: R = executeOrInst (Src1, Src2, Ty); break;

View File

@ -121,6 +121,8 @@ namespace {
void writeOperand(Value *Operand); void writeOperand(Value *Operand);
void writeOperandInternal(Value *Operand); void writeOperandInternal(Value *Operand);
void writeOperandWithCast(Value* Operand, unsigned Opcode);
bool writeInstructionCast(const Instruction &I);
private : private :
void lowerIntrinsics(Function &F); void lowerIntrinsics(Function &F);
@ -136,6 +138,8 @@ namespace {
void printLoop(Loop *L); void printLoop(Loop *L);
void printConstant(Constant *CPV); void printConstant(Constant *CPV);
void printConstantWithCast(Constant *CPV, unsigned Opcode);
bool printConstExprCast(const ConstantExpr *CE);
void printConstantArray(ConstantArray *CPA); void printConstantArray(ConstantArray *CPA);
void printConstantPacked(ConstantPacked *CP); void printConstantPacked(ConstantPacked *CP);
@ -586,7 +590,9 @@ void CWriter::printConstant(Constant *CPV) {
case Instruction::Add: case Instruction::Add:
case Instruction::Sub: case Instruction::Sub:
case Instruction::Mul: case Instruction::Mul:
case Instruction::Div: case Instruction::SDiv:
case Instruction::UDiv:
case Instruction::FDiv:
case Instruction::Rem: case Instruction::Rem:
case Instruction::And: case Instruction::And:
case Instruction::Or: case Instruction::Or:
@ -600,12 +606,15 @@ void CWriter::printConstant(Constant *CPV) {
case Instruction::Shl: case Instruction::Shl:
case Instruction::Shr: case Instruction::Shr:
Out << '('; Out << '(';
printConstant(CE->getOperand(0)); bool NeedsClosingParens = printConstExprCast(CE);
printConstantWithCast(CE->getOperand(0), CE->getOpcode());
switch (CE->getOpcode()) { switch (CE->getOpcode()) {
case Instruction::Add: Out << " + "; break; case Instruction::Add: Out << " + "; break;
case Instruction::Sub: Out << " - "; break; case Instruction::Sub: Out << " - "; break;
case Instruction::Mul: Out << " * "; break; case Instruction::Mul: Out << " * "; break;
case Instruction::Div: Out << " / "; break; case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::FDiv: Out << " / "; break;
case Instruction::Rem: Out << " % "; break; case Instruction::Rem: Out << " % "; break;
case Instruction::And: Out << " & "; break; case Instruction::And: Out << " & "; break;
case Instruction::Or: Out << " | "; break; case Instruction::Or: Out << " | "; break;
@ -620,7 +629,9 @@ void CWriter::printConstant(Constant *CPV) {
case Instruction::Shr: Out << " >> "; break; case Instruction::Shr: Out << " >> "; break;
default: assert(0 && "Illegal opcode here!"); default: assert(0 && "Illegal opcode here!");
} }
printConstant(CE->getOperand(1)); printConstantWithCast(CE->getOperand(1), CE->getOpcode());
if (NeedsClosingParens)
Out << "))";
Out << ')'; Out << ')';
return; return;
@ -805,6 +816,71 @@ void CWriter::printConstant(Constant *CPV) {
} }
} }
// Some constant expressions need to be casted back to the original types
// because their operands were casted to the expected type. This function takes
// care of detecting that case and printing the cast for the ConstantExpr.
bool CWriter::printConstExprCast(const ConstantExpr* CE) {
bool Result = false;
const Type* Ty = CE->getOperand(0)->getType();
switch (CE->getOpcode()) {
case Instruction::UDiv: Result = Ty->isSigned(); break;
case Instruction::SDiv: Result = Ty->isUnsigned(); break;
default: break;
}
if (Result) {
Out << "((";
printType(Out, Ty);
Out << ")(";
}
return Result;
}
// Print a constant assuming that it is the operand for a given Opcode. The
// opcodes that care about sign need to cast their operands to the expected
// type before the operation proceeds. This function does the casting.
void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
// Extract the operand's type, we'll need it.
const Type* OpTy = CPV->getType();
// Indicate whether to do the cast or not.
bool shouldCast = false;
// Based on the Opcode for which this Constant is being written, determine
// the new type to which the operand should be casted by setting the value
// of OpTy. If we change OpTy, also set shouldCast to true.
switch (Opcode) {
default:
// for most instructions, it doesn't matter
break;
case Instruction::UDiv:
// For UDiv to have unsigned operands
if (OpTy->isSigned()) {
OpTy = OpTy->getUnsignedVersion();
shouldCast = true;
}
break;
case Instruction::SDiv:
if (OpTy->isUnsigned()) {
OpTy = OpTy->getSignedVersion();
shouldCast = true;
}
break;
}
// Write out the casted constnat if we should, otherwise just write the
// operand.
if (shouldCast) {
Out << "((";
printType(Out, OpTy);
Out << ")";
printConstant(CPV);
Out << ")";
} else
writeOperand(CPV);
}
void CWriter::writeOperandInternal(Value *Operand) { void CWriter::writeOperandInternal(Value *Operand) {
if (Instruction *I = dyn_cast<Instruction>(Operand)) if (Instruction *I = dyn_cast<Instruction>(Operand))
if (isInlinableInst(*I) && !isDirectAlloca(I)) { if (isInlinableInst(*I) && !isDirectAlloca(I)) {
@ -833,6 +909,72 @@ void CWriter::writeOperand(Value *Operand) {
Out << ')'; Out << ')';
} }
// Some instructions need to have their result value casted back to the
// original types because their operands were casted to the expected type.
// This function takes care of detecting that case and printing the cast
// for the Instruction.
bool CWriter::writeInstructionCast(const Instruction &I) {
bool Result = false;
const Type* Ty = I.getOperand(0)->getType();
switch (I.getOpcode()) {
case Instruction::UDiv: Result = Ty->isSigned(); break;
case Instruction::SDiv: Result = Ty->isUnsigned(); break;
default: break;
}
if (Result) {
Out << "((";
printType(Out, Ty);
Out << ")(";
}
return Result;
}
// Write the operand with a cast to another type based on the Opcode being used.
// This will be used in cases where an instruction has specific type
// requirements (usually signedness) for its operands.
void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
// Extract the operand's type, we'll need it.
const Type* OpTy = Operand->getType();
// Indicate whether to do the cast or not.
bool shouldCast = false;
// Based on the Opcode for which this Operand is being written, determine
// the new type to which the operand should be casted by setting the value
// of OpTy. If we change OpTy, also set shouldCast to true.
switch (Opcode) {
default:
// for most instructions, it doesn't matter
break;
case Instruction::UDiv:
// For UDiv to have unsigned operands
if (OpTy->isSigned()) {
OpTy = OpTy->getUnsignedVersion();
shouldCast = true;
}
break;
case Instruction::SDiv:
if (OpTy->isUnsigned()) {
OpTy = OpTy->getSignedVersion();
shouldCast = true;
}
break;
}
// Write out the casted operand if we should, otherwise just write the
// operand.
if (shouldCast) {
Out << "((";
printType(Out, OpTy);
Out << ")";
writeOperand(Operand);
Out << ")";
} else
writeOperand(Operand);
}
// generateCompilerSpecificCode - This is where we add conditional compilation // generateCompilerSpecificCode - This is where we add conditional compilation
// directives to cater to specific compilers as need be. // directives to cater to specific compilers as need be.
// //
@ -1642,13 +1784,23 @@ void CWriter::visitBinaryOperator(Instruction &I) {
writeOperand(I.getOperand(1)); writeOperand(I.getOperand(1));
Out << ")"; Out << ")";
} else { } else {
writeOperand(I.getOperand(0));
// Write out the cast of the instruction's value back to the proper type
// if necessary.
bool NeedsClosingParens = writeInstructionCast(I);
// Certain instructions require the operand to be forced to a specific type
// so we use writeOperandWithCast here instead of writeOperand. Similarly
// below for operand 1
writeOperandWithCast(I.getOperand(0), I.getOpcode());
switch (I.getOpcode()) { switch (I.getOpcode()) {
case Instruction::Add: Out << " + "; break; case Instruction::Add: Out << " + "; break;
case Instruction::Sub: Out << " - "; break; case Instruction::Sub: Out << " - "; break;
case Instruction::Mul: Out << '*'; break; case Instruction::Mul: Out << '*'; break;
case Instruction::Div: Out << '/'; break; case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::FDiv: Out << '/'; break;
case Instruction::Rem: Out << '%'; break; case Instruction::Rem: Out << '%'; break;
case Instruction::And: Out << " & "; break; case Instruction::And: Out << " & "; break;
case Instruction::Or: Out << " | "; break; case Instruction::Or: Out << " | "; break;
@ -1664,7 +1816,9 @@ void CWriter::visitBinaryOperator(Instruction &I) {
default: std::cerr << "Invalid operator type!" << I; abort(); default: std::cerr << "Invalid operator type!" << I; abort();
} }
writeOperand(I.getOperand(1)); writeOperandWithCast(I.getOperand(1), I.getOpcode());
if (NeedsClosingParens)
Out << "))";
} }
if (needsCast) { if (needsCast) {

View File

@ -121,6 +121,8 @@ namespace {
void writeOperand(Value *Operand); void writeOperand(Value *Operand);
void writeOperandInternal(Value *Operand); void writeOperandInternal(Value *Operand);
void writeOperandWithCast(Value* Operand, unsigned Opcode);
bool writeInstructionCast(const Instruction &I);
private : private :
void lowerIntrinsics(Function &F); void lowerIntrinsics(Function &F);
@ -136,6 +138,8 @@ namespace {
void printLoop(Loop *L); void printLoop(Loop *L);
void printConstant(Constant *CPV); void printConstant(Constant *CPV);
void printConstantWithCast(Constant *CPV, unsigned Opcode);
bool printConstExprCast(const ConstantExpr *CE);
void printConstantArray(ConstantArray *CPA); void printConstantArray(ConstantArray *CPA);
void printConstantPacked(ConstantPacked *CP); void printConstantPacked(ConstantPacked *CP);
@ -586,7 +590,9 @@ void CWriter::printConstant(Constant *CPV) {
case Instruction::Add: case Instruction::Add:
case Instruction::Sub: case Instruction::Sub:
case Instruction::Mul: case Instruction::Mul:
case Instruction::Div: case Instruction::SDiv:
case Instruction::UDiv:
case Instruction::FDiv:
case Instruction::Rem: case Instruction::Rem:
case Instruction::And: case Instruction::And:
case Instruction::Or: case Instruction::Or:
@ -600,12 +606,15 @@ void CWriter::printConstant(Constant *CPV) {
case Instruction::Shl: case Instruction::Shl:
case Instruction::Shr: case Instruction::Shr:
Out << '('; Out << '(';
printConstant(CE->getOperand(0)); bool NeedsClosingParens = printConstExprCast(CE);
printConstantWithCast(CE->getOperand(0), CE->getOpcode());
switch (CE->getOpcode()) { switch (CE->getOpcode()) {
case Instruction::Add: Out << " + "; break; case Instruction::Add: Out << " + "; break;
case Instruction::Sub: Out << " - "; break; case Instruction::Sub: Out << " - "; break;
case Instruction::Mul: Out << " * "; break; case Instruction::Mul: Out << " * "; break;
case Instruction::Div: Out << " / "; break; case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::FDiv: Out << " / "; break;
case Instruction::Rem: Out << " % "; break; case Instruction::Rem: Out << " % "; break;
case Instruction::And: Out << " & "; break; case Instruction::And: Out << " & "; break;
case Instruction::Or: Out << " | "; break; case Instruction::Or: Out << " | "; break;
@ -620,7 +629,9 @@ void CWriter::printConstant(Constant *CPV) {
case Instruction::Shr: Out << " >> "; break; case Instruction::Shr: Out << " >> "; break;
default: assert(0 && "Illegal opcode here!"); default: assert(0 && "Illegal opcode here!");
} }
printConstant(CE->getOperand(1)); printConstantWithCast(CE->getOperand(1), CE->getOpcode());
if (NeedsClosingParens)
Out << "))";
Out << ')'; Out << ')';
return; return;
@ -805,6 +816,71 @@ void CWriter::printConstant(Constant *CPV) {
} }
} }
// Some constant expressions need to be casted back to the original types
// because their operands were casted to the expected type. This function takes
// care of detecting that case and printing the cast for the ConstantExpr.
bool CWriter::printConstExprCast(const ConstantExpr* CE) {
bool Result = false;
const Type* Ty = CE->getOperand(0)->getType();
switch (CE->getOpcode()) {
case Instruction::UDiv: Result = Ty->isSigned(); break;
case Instruction::SDiv: Result = Ty->isUnsigned(); break;
default: break;
}
if (Result) {
Out << "((";
printType(Out, Ty);
Out << ")(";
}
return Result;
}
// Print a constant assuming that it is the operand for a given Opcode. The
// opcodes that care about sign need to cast their operands to the expected
// type before the operation proceeds. This function does the casting.
void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
// Extract the operand's type, we'll need it.
const Type* OpTy = CPV->getType();
// Indicate whether to do the cast or not.
bool shouldCast = false;
// Based on the Opcode for which this Constant is being written, determine
// the new type to which the operand should be casted by setting the value
// of OpTy. If we change OpTy, also set shouldCast to true.
switch (Opcode) {
default:
// for most instructions, it doesn't matter
break;
case Instruction::UDiv:
// For UDiv to have unsigned operands
if (OpTy->isSigned()) {
OpTy = OpTy->getUnsignedVersion();
shouldCast = true;
}
break;
case Instruction::SDiv:
if (OpTy->isUnsigned()) {
OpTy = OpTy->getSignedVersion();
shouldCast = true;
}
break;
}
// Write out the casted constnat if we should, otherwise just write the
// operand.
if (shouldCast) {
Out << "((";
printType(Out, OpTy);
Out << ")";
printConstant(CPV);
Out << ")";
} else
writeOperand(CPV);
}
void CWriter::writeOperandInternal(Value *Operand) { void CWriter::writeOperandInternal(Value *Operand) {
if (Instruction *I = dyn_cast<Instruction>(Operand)) if (Instruction *I = dyn_cast<Instruction>(Operand))
if (isInlinableInst(*I) && !isDirectAlloca(I)) { if (isInlinableInst(*I) && !isDirectAlloca(I)) {
@ -833,6 +909,72 @@ void CWriter::writeOperand(Value *Operand) {
Out << ')'; Out << ')';
} }
// Some instructions need to have their result value casted back to the
// original types because their operands were casted to the expected type.
// This function takes care of detecting that case and printing the cast
// for the Instruction.
bool CWriter::writeInstructionCast(const Instruction &I) {
bool Result = false;
const Type* Ty = I.getOperand(0)->getType();
switch (I.getOpcode()) {
case Instruction::UDiv: Result = Ty->isSigned(); break;
case Instruction::SDiv: Result = Ty->isUnsigned(); break;
default: break;
}
if (Result) {
Out << "((";
printType(Out, Ty);
Out << ")(";
}
return Result;
}
// Write the operand with a cast to another type based on the Opcode being used.
// This will be used in cases where an instruction has specific type
// requirements (usually signedness) for its operands.
void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
// Extract the operand's type, we'll need it.
const Type* OpTy = Operand->getType();
// Indicate whether to do the cast or not.
bool shouldCast = false;
// Based on the Opcode for which this Operand is being written, determine
// the new type to which the operand should be casted by setting the value
// of OpTy. If we change OpTy, also set shouldCast to true.
switch (Opcode) {
default:
// for most instructions, it doesn't matter
break;
case Instruction::UDiv:
// For UDiv to have unsigned operands
if (OpTy->isSigned()) {
OpTy = OpTy->getUnsignedVersion();
shouldCast = true;
}
break;
case Instruction::SDiv:
if (OpTy->isUnsigned()) {
OpTy = OpTy->getSignedVersion();
shouldCast = true;
}
break;
}
// Write out the casted operand if we should, otherwise just write the
// operand.
if (shouldCast) {
Out << "((";
printType(Out, OpTy);
Out << ")";
writeOperand(Operand);
Out << ")";
} else
writeOperand(Operand);
}
// generateCompilerSpecificCode - This is where we add conditional compilation // generateCompilerSpecificCode - This is where we add conditional compilation
// directives to cater to specific compilers as need be. // directives to cater to specific compilers as need be.
// //
@ -1642,13 +1784,23 @@ void CWriter::visitBinaryOperator(Instruction &I) {
writeOperand(I.getOperand(1)); writeOperand(I.getOperand(1));
Out << ")"; Out << ")";
} else { } else {
writeOperand(I.getOperand(0));
// Write out the cast of the instruction's value back to the proper type
// if necessary.
bool NeedsClosingParens = writeInstructionCast(I);
// Certain instructions require the operand to be forced to a specific type
// so we use writeOperandWithCast here instead of writeOperand. Similarly
// below for operand 1
writeOperandWithCast(I.getOperand(0), I.getOpcode());
switch (I.getOpcode()) { switch (I.getOpcode()) {
case Instruction::Add: Out << " + "; break; case Instruction::Add: Out << " + "; break;
case Instruction::Sub: Out << " - "; break; case Instruction::Sub: Out << " - "; break;
case Instruction::Mul: Out << '*'; break; case Instruction::Mul: Out << '*'; break;
case Instruction::Div: Out << '/'; break; case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::FDiv: Out << '/'; break;
case Instruction::Rem: Out << '%'; break; case Instruction::Rem: Out << '%'; break;
case Instruction::And: Out << " & "; break; case Instruction::And: Out << " & "; break;
case Instruction::Or: Out << " | "; break; case Instruction::Or: Out << " | "; break;
@ -1664,7 +1816,9 @@ void CWriter::visitBinaryOperator(Instruction &I) {
default: std::cerr << "Invalid operator type!" << I; abort(); default: std::cerr << "Invalid operator type!" << I; abort();
} }
writeOperand(I.getOperand(1)); writeOperandWithCast(I.getOperand(1), I.getOpcode());
if (NeedsClosingParens)
Out << "))";
} }
if (needsCast) { if (needsCast) {

View File

@ -319,3 +319,16 @@ entry:
} }
//===---------------------------------------------------------------------===// //===---------------------------------------------------------------------===//
-instcombine should handle this transform:
setcc (sdiv X / C1 ), C2
when X, C1, and C2 are unsigned. Similarly for udiv and signed operands.
Currently InstCombine avoids this transform but will do it when the signs of
the operands and the sign of the divide match. See the FIXME in
InstructionCombining.cpp in the visitSetCondInst method after the switch case
for Instruction::UDiv (around line 4447) for more details.
The SingleSource/Benchmarks/Shootout-C++/hash and hash2 tests have examples of
this construct.
//===---------------------------------------------------------------------===//

View File

@ -1275,7 +1275,7 @@ public:
return true; return true;
} else if (Op2V == -1.0) { } else if (Op2V == -1.0) {
// pow(x,-1.0) -> 1.0/x // pow(x,-1.0) -> 1.0/x
BinaryOperator* div_inst= BinaryOperator::createDiv( BinaryOperator* div_inst= BinaryOperator::createFDiv(
ConstantFP::get(Ty,1.0), base, ci->getName()+".pow", ci); ConstantFP::get(Ty,1.0), base, ci->getName()+".pow", ci);
ci->replaceAllUsesWith(div_inst); ci->replaceAllUsesWith(div_inst);
ci->eraseFromParent(); ci->eraseFromParent();

View File

@ -131,7 +131,11 @@ namespace {
Instruction *visitAdd(BinaryOperator &I); Instruction *visitAdd(BinaryOperator &I);
Instruction *visitSub(BinaryOperator &I); Instruction *visitSub(BinaryOperator &I);
Instruction *visitMul(BinaryOperator &I); Instruction *visitMul(BinaryOperator &I);
Instruction *visitDiv(BinaryOperator &I); Instruction *commonDivTransforms(BinaryOperator &I);
Instruction *commonIDivTransforms(BinaryOperator &I);
Instruction *visitUDiv(BinaryOperator &I);
Instruction *visitSDiv(BinaryOperator &I);
Instruction *visitFDiv(BinaryOperator &I);
Instruction *visitRem(BinaryOperator &I); Instruction *visitRem(BinaryOperator &I);
Instruction *visitAnd(BinaryOperator &I); Instruction *visitAnd(BinaryOperator &I);
Instruction *visitOr (BinaryOperator &I); Instruction *visitOr (BinaryOperator &I);
@ -1822,7 +1826,9 @@ FoundSExt:
return R; return R;
} }
// add (cast *A to intptrtype) B -> cast (GEP (cast *A to sbyte*) B) -> intptrtype // add (cast *A to intptrtype) B ->
// cast (GEP (cast *A to sbyte*) B) ->
// intptrtype
{ {
CastInst* CI = dyn_cast<CastInst>(LHS); CastInst* CI = dyn_cast<CastInst>(LHS);
Value* Other = RHS; Value* Other = RHS;
@ -1975,11 +1981,11 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
} }
// 0 - (X sdiv C) -> (X sdiv -C) // 0 - (X sdiv C) -> (X sdiv -C)
if (Op1I->getOpcode() == Instruction::Div) if (Op1I->getOpcode() == Instruction::SDiv)
if (ConstantInt *CSI = dyn_cast<ConstantInt>(Op0)) if (ConstantInt *CSI = dyn_cast<ConstantInt>(Op0))
if (CSI->getType()->isSigned() && CSI->isNullValue()) if (CSI->isNullValue())
if (Constant *DivRHS = dyn_cast<Constant>(Op1I->getOperand(1))) if (Constant *DivRHS = dyn_cast<Constant>(Op1I->getOperand(1)))
return BinaryOperator::createDiv(Op1I->getOperand(0), return BinaryOperator::createSDiv(Op1I->getOperand(0),
ConstantExpr::getNeg(DivRHS)); ConstantExpr::getNeg(DivRHS));
// X - X*C --> X * (1-C) // X - X*C --> X * (1-C)
@ -2156,64 +2162,28 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
return Changed ? &I : 0; return Changed ? &I : 0;
} }
Instruction *InstCombiner::visitDiv(BinaryOperator &I) { /// This function implements the transforms on div instructions that work
/// regardless of the kind of div instruction it is (udiv, sdiv, or fdiv). It is
/// used by the visitors to those instructions.
/// @brief Transforms common to all three div instructions
Instruction* InstCombiner::commonDivTransforms(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
if (isa<UndefValue>(Op0)) // undef / X -> 0 // undef / X -> 0
if (isa<UndefValue>(Op0))
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
// X / undef -> undef
if (isa<UndefValue>(Op1)) if (isa<UndefValue>(Op1))
return ReplaceInstUsesWith(I, Op1); // X / undef -> undef return ReplaceInstUsesWith(I, Op1);
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) { // Handle cases involving: div X, (select Cond, Y, Z)
// div X, 1 == X
if (RHS->equalsInt(1))
return ReplaceInstUsesWith(I, Op0);
// div X, -1 == -X
if (RHS->isAllOnesValue())
return BinaryOperator::createNeg(Op0);
if (Instruction *LHS = dyn_cast<Instruction>(Op0))
if (LHS->getOpcode() == Instruction::Div)
if (ConstantInt *LHSRHS = dyn_cast<ConstantInt>(LHS->getOperand(1))) {
// (X / C1) / C2 -> X / (C1*C2)
return BinaryOperator::createDiv(LHS->getOperand(0),
ConstantExpr::getMul(RHS, LHSRHS));
}
// Check to see if this is an unsigned division with an exact power of 2,
// if so, convert to a right shift.
if (ConstantInt *C = dyn_cast<ConstantInt>(RHS))
if (C->getType()->isUnsigned())
if (uint64_t Val = C->getZExtValue()) // Don't break X / 0
if (isPowerOf2_64(Val)) {
uint64_t C = Log2_64(Val);
return new ShiftInst(Instruction::Shr, Op0,
ConstantInt::get(Type::UByteTy, C));
}
// -X/C -> X/-C
if (RHS->getType()->isSigned())
if (Value *LHSNeg = dyn_castNegVal(Op0))
return BinaryOperator::createDiv(LHSNeg, ConstantExpr::getNeg(RHS));
if (!RHS->isNullValue()) {
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
return R;
if (isa<PHINode>(Op0))
if (Instruction *NV = FoldOpIntoPhi(I))
return NV;
}
}
// Handle div X, Cond?Y:Z
if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) { if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) {
// div X, (Cond ? 0 : Y) -> div X, Y. If the div and the select are in the // div X, (Cond ? 0 : Y) -> div X, Y. If the div and the select are in the
// same basic block, then we replace the select with Y, and the condition of // same basic block, then we replace the select with Y, and the condition
// the select with false (if the cond value is in the same BB). If the // of the select with false (if the cond value is in the same BB). If the
// select has uses other than the div, this allows them to be simplified // select has uses other than the div, this allows them to be simplified
// also. // also. Note that div X, Y is just as good as div X, 0 (undef)
if (Constant *ST = dyn_cast<Constant>(SI->getOperand(1))) if (Constant *ST = dyn_cast<Constant>(SI->getOperand(1)))
if (ST->isNullValue()) { if (ST->isNullValue()) {
Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0)); Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0));
@ -2225,6 +2195,7 @@ Instruction *InstCombiner::visitDiv(BinaryOperator &I) {
UpdateValueUsesWith(SI, SI->getOperand(2)); UpdateValueUsesWith(SI, SI->getOperand(2));
return &I; return &I;
} }
// Likewise for: div X, (Cond ? Y : 0) -> div X, Y // Likewise for: div X, (Cond ? Y : 0) -> div X, Y
if (Constant *ST = dyn_cast<Constant>(SI->getOperand(2))) if (Constant *ST = dyn_cast<Constant>(SI->getOperand(2)))
if (ST->isNullValue()) { if (ST->isNullValue()) {
@ -2237,27 +2208,41 @@ Instruction *InstCombiner::visitDiv(BinaryOperator &I) {
UpdateValueUsesWith(SI, SI->getOperand(1)); UpdateValueUsesWith(SI, SI->getOperand(1));
return &I; return &I;
} }
// If this is 'udiv X, (Cond ? C1, C2)' where C1&C2 are powers of two,
// transform this into: '(Cond ? (udiv X, C1) : (udiv X, C2))'.
if (ConstantInt *STO = dyn_cast<ConstantInt>(SI->getOperand(1)))
if (ConstantInt *SFO = dyn_cast<ConstantInt>(SI->getOperand(2)))
if (STO->getType()->isUnsigned() && SFO->getType()->isUnsigned()) {
// STO == 0 and SFO == 0 handled above.
uint64_t TVA = STO->getZExtValue(), FVA = SFO->getZExtValue();
if (isPowerOf2_64(TVA) && isPowerOf2_64(FVA)) {
unsigned TSA = Log2_64(TVA), FSA = Log2_64(FVA);
Constant *TC = ConstantInt::get(Type::UByteTy, TSA);
Instruction *TSI = new ShiftInst(Instruction::Shr, Op0,
TC, SI->getName()+".t");
TSI = InsertNewInstBefore(TSI, I);
Constant *FC = ConstantInt::get(Type::UByteTy, FSA);
Instruction *FSI = new ShiftInst(Instruction::Shr, Op0,
FC, SI->getName()+".f");
FSI = InsertNewInstBefore(FSI, I);
return new SelectInst(SI->getOperand(0), TSI, FSI);
} }
return 0;
}
/// This function implements the transforms common to both integer division
/// instructions (udiv and sdiv). It is called by the visitors to those integer
/// division instructions.
/// @brief Common integer divide transforms
Instruction* InstCombiner::commonIDivTransforms(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
if (Instruction *Common = commonDivTransforms(I))
return Common;
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
// div X, 1 == X
if (RHS->equalsInt(1))
return ReplaceInstUsesWith(I, Op0);
// (X / C1) / C2 -> X / (C1*C2)
if (Instruction *LHS = dyn_cast<Instruction>(Op0))
if (Instruction::BinaryOps(LHS->getOpcode()) == I.getOpcode())
if (ConstantInt *LHSRHS = dyn_cast<ConstantInt>(LHS->getOperand(1))) {
return BinaryOperator::create(I.getOpcode(), LHS->getOperand(0),
ConstantExpr::getMul(RHS, LHSRHS));
}
if (!RHS->isNullValue()) { // avoid X udiv 0
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
return R;
if (isa<PHINode>(Op0))
if (Instruction *NV = FoldOpIntoPhi(I))
return NV;
} }
} }
@ -2266,48 +2251,137 @@ Instruction *InstCombiner::visitDiv(BinaryOperator &I) {
if (LHS->equalsInt(0)) if (LHS->equalsInt(0))
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
if (I.getType()->isSigned()) { return 0;
// If the sign bits of both operands are zero (i.e. we can prove they are
// unsigned inputs), turn this into a udiv.
uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1);
if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) {
const Type *NTy = Op0->getType()->getUnsignedVersion();
Instruction *LHS = new CastInst(Op0, NTy, Op0->getName());
InsertNewInstBefore(LHS, I);
Value *RHS;
if (Constant *R = dyn_cast<Constant>(Op1))
RHS = ConstantExpr::getCast(R, NTy);
else
RHS = InsertNewInstBefore(new CastInst(Op1, NTy, Op1->getName()), I);
Instruction *Div = BinaryOperator::createDiv(LHS, RHS, I.getName());
InsertNewInstBefore(Div, I);
return new CastInst(Div, I.getType());
} }
} else {
// Known to be an unsigned division. Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
if (Instruction *RHSI = dyn_cast<Instruction>(I.getOperand(1))) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
// Turn A / (C1 << N), where C1 is "1<<C2" into A >> (N+C2) [udiv only].
// Handle the integer div common cases
if (Instruction *Common = commonIDivTransforms(I))
return Common;
// X udiv C^2 -> X >> C
// Check to see if this is an unsigned division with an exact power of 2,
// if so, convert to a right shift.
if (ConstantInt *C = dyn_cast<ConstantInt>(Op1)) {
if (uint64_t Val = C->getZExtValue()) // Don't break X / 0
if (isPowerOf2_64(Val)) {
uint64_t ShiftAmt = Log2_64(Val);
Value* X = Op0;
const Type* XTy = X->getType();
bool isSigned = XTy->isSigned();
if (isSigned)
X = InsertCastBefore(X, XTy->getUnsignedVersion(), I);
Instruction* Result =
new ShiftInst(Instruction::Shr, X,
ConstantInt::get(Type::UByteTy, ShiftAmt));
if (!isSigned)
return Result;
InsertNewInstBefore(Result, I);
return new CastInst(Result, XTy->getSignedVersion(), I.getName());
}
}
// X udiv (C1 << N), where C1 is "1<<C2" --> X >> (N+C2)
if (ShiftInst *RHSI = dyn_cast<ShiftInst>(I.getOperand(1))) {
if (RHSI->getOpcode() == Instruction::Shl && if (RHSI->getOpcode() == Instruction::Shl &&
isa<ConstantInt>(RHSI->getOperand(0)) && isa<ConstantInt>(RHSI->getOperand(0))) {
RHSI->getOperand(0)->getType()->isUnsigned()) {
uint64_t C1 = cast<ConstantInt>(RHSI->getOperand(0))->getZExtValue(); uint64_t C1 = cast<ConstantInt>(RHSI->getOperand(0))->getZExtValue();
if (isPowerOf2_64(C1)) { if (isPowerOf2_64(C1)) {
uint64_t C2 = Log2_64(C1); Value *N = RHSI->getOperand(1);
Value *Add = RHSI->getOperand(1); const Type* NTy = N->getType();
if (C2) { bool isSigned = NTy->isSigned();
Constant *C2V = ConstantInt::get(Add->getType(), C2); if (uint64_t C2 = Log2_64(C1)) {
Add = InsertNewInstBefore(BinaryOperator::createAdd(Add, C2V, if (isSigned) {
"tmp"), I); NTy = NTy->getUnsignedVersion();
N = InsertCastBefore(N, NTy, I);
} }
return new ShiftInst(Instruction::Shr, Op0, Add); Constant *C2V = ConstantInt::get(NTy, C2);
N = InsertNewInstBefore(BinaryOperator::createAdd(N, C2V, "tmp"), I);
}
Instruction* Result = new ShiftInst(Instruction::Shr, Op0, N);
if (!isSigned)
return Result;
InsertNewInstBefore(Result, I);
return new CastInst(Result, NTy->getSignedVersion(), I.getName());
} }
} }
} }
// udiv X, (Select Cond, C1, C2) --> Select Cond, (shr X, C1), (shr X, C2)
// where C1&C2 are powers of two.
if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) {
if (ConstantInt *STO = dyn_cast<ConstantInt>(SI->getOperand(1)))
if (ConstantInt *SFO = dyn_cast<ConstantInt>(SI->getOperand(2)))
if (!STO->isNullValue() && !STO->isNullValue()) {
uint64_t TVA = STO->getZExtValue(), FVA = SFO->getZExtValue();
if (isPowerOf2_64(TVA) && isPowerOf2_64(FVA)) {
// Compute the shift amounts
unsigned TSA = Log2_64(TVA), FSA = Log2_64(FVA);
// Make sure we get the unsigned version of X
Value* X = Op0;
const Type* origXTy = X->getType();
bool isSigned = origXTy->isSigned();
if (isSigned)
X = InsertCastBefore(X, X->getType()->getUnsignedVersion(), I);
// Construct the "on true" case of the select
Constant *TC = ConstantInt::get(Type::UByteTy, TSA);
Instruction *TSI =
new ShiftInst(Instruction::Shr, X, TC, SI->getName()+".t");
TSI = InsertNewInstBefore(TSI, I);
// Construct the "on false" case of the select
Constant *FC = ConstantInt::get(Type::UByteTy, FSA);
Instruction *FSI =
new ShiftInst(Instruction::Shr, X, FC, SI->getName()+".f");
FSI = InsertNewInstBefore(FSI, I);
// construct the select instruction and return it.
SelectInst* NewSI =
new SelectInst(SI->getOperand(0), TSI, FSI, SI->getName());
if (!isSigned)
return NewSI;
InsertNewInstBefore(NewSI, I);
return new CastInst(NewSI, origXTy, NewSI->getName());
}
}
}
return 0;
}
Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
// Handle the integer div common cases
if (Instruction *Common = commonIDivTransforms(I))
return Common;
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
// sdiv X, -1 == -X
if (RHS->isAllOnesValue())
return BinaryOperator::createNeg(Op0);
// -X/C -> X/-C
if (Value *LHSNeg = dyn_castNegVal(Op0))
return BinaryOperator::createSDiv(LHSNeg, ConstantExpr::getNeg(RHS));
}
// If the sign bits of both operands are zero (i.e. we can prove they are
// unsigned inputs), turn this into a udiv.
if (I.getType()->isInteger()) {
uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1);
if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) {
return BinaryOperator::createUDiv(Op0, Op1, I.getName());
}
} }
return 0; return 0;
} }
Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
return commonDivTransforms(I);
}
/// GetFactor - If we can prove that the specified value is at least a multiple /// GetFactor - If we can prove that the specified value is at least a multiple
/// of some factor, return that factor. /// of some factor, return that factor.
@ -2376,13 +2450,12 @@ Instruction *InstCombiner::visitRem(BinaryOperator &I) {
uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1); uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1);
if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) { if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) {
const Type *NTy = Op0->getType()->getUnsignedVersion(); const Type *NTy = Op0->getType()->getUnsignedVersion();
Instruction *LHS = new CastInst(Op0, NTy, Op0->getName()); Value *LHS = InsertCastBefore(Op0, NTy, I);
InsertNewInstBefore(LHS, I);
Value *RHS; Value *RHS;
if (Constant *R = dyn_cast<Constant>(Op1)) if (Constant *R = dyn_cast<Constant>(Op1))
RHS = ConstantExpr::getCast(R, NTy); RHS = ConstantExpr::getCast(R, NTy);
else else
RHS = InsertNewInstBefore(new CastInst(Op1, NTy, Op1->getName()), I); RHS = InsertCastBefore(Op1, NTy, I);
Instruction *Rem = BinaryOperator::createRem(LHS, RHS, I.getName()); Instruction *Rem = BinaryOperator::createRem(LHS, RHS, I.getName());
InsertNewInstBefore(Rem, I); InsertNewInstBefore(Rem, I);
return new CastInst(Rem, I.getType()); return new CastInst(Rem, I.getType());
@ -3717,14 +3790,6 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
return Changed ? &I : 0; return Changed ? &I : 0;
} }
/// MulWithOverflow - Compute Result = In1*In2, returning true if the result
/// overflowed for this type.
static bool MulWithOverflow(ConstantInt *&Result, ConstantInt *In1,
ConstantInt *In2) {
Result = cast<ConstantInt>(ConstantExpr::getMul(In1, In2));
return !In2->isNullValue() && ConstantExpr::getDiv(Result, In2) != In1;
}
static bool isPositive(ConstantInt *C) { static bool isPositive(ConstantInt *C) {
return C->getSExtValue() >= 0; return C->getSExtValue() >= 0;
} }
@ -4126,7 +4191,9 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
} }
} }
// Since the RHS is a constantInt (CI), if the left hand side is an
// instruction, see if that instruction also has constants so that the
// instruction can be folded into the setcc
if (Instruction *LHSI = dyn_cast<Instruction>(Op0)) if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
switch (LHSI->getOpcode()) { switch (LHSI->getOpcode()) {
case Instruction::And: case Instruction::And:
@ -4379,23 +4446,56 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
} }
break; break;
case Instruction::Div: case Instruction::SDiv:
// Fold: (div X, C1) op C2 -> range check case Instruction::UDiv:
if (ConstantInt *DivRHS = dyn_cast<ConstantInt>(LHSI->getOperand(1))) { // Fold: setcc ([us]div X, C1), C2 -> range test
// Fold this div into the comparison, producing a range check. // Fold this div into the comparison, producing a range check.
// Determine, based on the divide type, what the range is being // Determine, based on the divide type, what the range is being
// checked. If there is an overflow on the low or high side, remember // checked. If there is an overflow on the low or high side, remember
// it, otherwise compute the range [low, hi) bounding the new value. // it, otherwise compute the range [low, hi) bounding the new value.
bool LoOverflow = false, HiOverflow = 0; // See: InsertRangeTest above for the kinds of replacements possible.
if (ConstantInt *DivRHS = dyn_cast<ConstantInt>(LHSI->getOperand(1))) {
// FIXME: If the operand types don't match the type of the divide
// then don't attempt this transform. The code below doesn't have the
// logic to deal with a signed divide and an unsigned compare (and
// vice versa). This is because (x /s C1) <s C2 produces different
// results than (x /s C1) <u C2 or (x /u C1) <s C2 or even
// (x /u C1) <u C2. Simply casting the operands and result won't
// work. :( The if statement below tests that condition and bails
// if it finds it.
const Type* DivRHSTy = DivRHS->getType();
unsigned DivOpCode = LHSI->getOpcode();
if (I.isEquality() &&
((DivOpCode == Instruction::SDiv && DivRHSTy->isUnsigned()) ||
(DivOpCode == Instruction::UDiv && DivRHSTy->isSigned())))
break;
// Initialize the variables that will indicate the nature of the
// range check.
bool LoOverflow = false, HiOverflow = false;
ConstantInt *LoBound = 0, *HiBound = 0; ConstantInt *LoBound = 0, *HiBound = 0;
ConstantInt *Prod; // Compute Prod = CI * DivRHS. We are essentially solving an equation
bool ProdOV = MulWithOverflow(Prod, CI, DivRHS); // of form X/C1=C2. We solve for X by multiplying C1 (DivRHS) and
// C2 (CI). By solving for X we can turn this into a range check
// instead of computing a divide.
ConstantInt *Prod =
cast<ConstantInt>(ConstantExpr::getMul(CI, DivRHS));
// Determine if the product overflows by seeing if the product is
// not equal to the divide. Make sure we do the same kind of divide
// as in the LHS instruction that we're folding.
bool ProdOV = !DivRHS->isNullValue() &&
(DivOpCode == Instruction::SDiv ?
ConstantExpr::getSDiv(Prod, DivRHS) :
ConstantExpr::getUDiv(Prod, DivRHS)) != CI;
// Get the SetCC opcode
Instruction::BinaryOps Opcode = I.getOpcode(); Instruction::BinaryOps Opcode = I.getOpcode();
if (DivRHS->isNullValue()) { // Don't hack on divide by zeros. if (DivRHS->isNullValue()) {
} else if (LHSI->getType()->isUnsigned()) { // udiv // Don't hack on divide by zeros!
} else if (DivOpCode == Instruction::UDiv) { // udiv
LoBound = Prod; LoBound = Prod;
LoOverflow = ProdOV; LoOverflow = ProdOV;
HiOverflow = ProdOV || AddWithOverflow(HiBound, LoBound, DivRHS); HiOverflow = ProdOV || AddWithOverflow(HiBound, LoBound, DivRHS);
@ -5679,6 +5779,23 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) {
ConstantInt::get(CI.getType(), 1)); ConstantInt::get(CI.getType(), 1));
} }
break; break;
case Instruction::SDiv:
case Instruction::UDiv:
// If we are just changing the sign, rewrite.
if (DestBitSize == SrcBitSize) {
// Don't insert two casts if they cannot be eliminated. We allow two
// casts to be inserted if the sizes are the same. This could only be
// converting signedness, which is a noop.
if (!ValueRequiresCast(Op1, DestTy,TD) ||
!ValueRequiresCast(Op0, DestTy, TD)) {
Value *Op0c = InsertOperandCastBefore(Op0, DestTy, SrcI);
Value *Op1c = InsertOperandCastBefore(Op1, DestTy, SrcI);
return BinaryOperator::create(
cast<BinaryOperator>(SrcI)->getOpcode(), Op0c, Op1c);
}
}
break;
case Instruction::Shl: case Instruction::Shl:
// Allow changing the sign of the source operand. Do not allow changing // Allow changing the sign of the source operand. Do not allow changing
// the size of the shift, UNLESS the shift amount is a constant. We // the size of the shift, UNLESS the shift amount is a constant. We

View File

@ -788,7 +788,9 @@ void PredicateSimplifier::Forwards::visitBinaryOperator(BinaryOperator &BO) {
Instruction::BinaryOps ops = BO.getOpcode(); Instruction::BinaryOps ops = BO.getOpcode();
switch (ops) { switch (ops) {
case Instruction::Div: case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::FDiv:
case Instruction::Rem: { case Instruction::Rem: {
Value *Divisor = BO.getOperand(1); Value *Divisor = BO.getOperand(1);
KP.addNotEqual(Constant::getNullValue(Divisor->getType()), Divisor); KP.addNotEqual(Constant::getNullValue(Divisor->getType()), Divisor);

View File

@ -113,7 +113,9 @@ static bool isUnmovableInstruction(Instruction *I) {
I->getOpcode() == Instruction::Malloc || I->getOpcode() == Instruction::Malloc ||
I->getOpcode() == Instruction::Invoke || I->getOpcode() == Instruction::Invoke ||
I->getOpcode() == Instruction::Call || I->getOpcode() == Instruction::Call ||
I->getOpcode() == Instruction::Div || I->getOpcode() == Instruction::UDiv ||
I->getOpcode() == Instruction::SDiv ||
I->getOpcode() == Instruction::FDiv ||
I->getOpcode() == Instruction::Rem) I->getOpcode() == Instruction::Rem)
return true; return true;
return false; return false;

View File

@ -40,7 +40,9 @@ namespace {
virtual Constant *add(const Constant *V1, const Constant *V2) const = 0; virtual Constant *add(const Constant *V1, const Constant *V2) const = 0;
virtual Constant *sub(const Constant *V1, const Constant *V2) const = 0; virtual Constant *sub(const Constant *V1, const Constant *V2) const = 0;
virtual Constant *mul(const Constant *V1, const Constant *V2) const = 0; virtual Constant *mul(const Constant *V1, const Constant *V2) const = 0;
virtual Constant *div(const Constant *V1, const Constant *V2) const = 0; virtual Constant *udiv(const Constant *V1, const Constant *V2) const = 0;
virtual Constant *sdiv(const Constant *V1, const Constant *V2) const = 0;
virtual Constant *fdiv(const Constant *V1, const Constant *V2) const = 0;
virtual Constant *rem(const Constant *V1, const Constant *V2) const = 0; virtual Constant *rem(const Constant *V1, const Constant *V2) const = 0;
virtual Constant *op_and(const Constant *V1, const Constant *V2) const = 0; virtual Constant *op_and(const Constant *V1, const Constant *V2) const = 0;
virtual Constant *op_or (const Constant *V1, const Constant *V2) const = 0; virtual Constant *op_or (const Constant *V1, const Constant *V2) const = 0;
@ -106,8 +108,14 @@ class VISIBILITY_HIDDEN TemplateRules : public ConstRules {
virtual Constant *mul(const Constant *V1, const Constant *V2) const { virtual Constant *mul(const Constant *V1, const Constant *V2) const {
return SubClassName::Mul((const ArgType *)V1, (const ArgType *)V2); return SubClassName::Mul((const ArgType *)V1, (const ArgType *)V2);
} }
virtual Constant *div(const Constant *V1, const Constant *V2) const { virtual Constant *udiv(const Constant *V1, const Constant *V2) const {
return SubClassName::Div((const ArgType *)V1, (const ArgType *)V2); return SubClassName::UDiv((const ArgType *)V1, (const ArgType *)V2);
}
virtual Constant *sdiv(const Constant *V1, const Constant *V2) const {
return SubClassName::SDiv((const ArgType *)V1, (const ArgType *)V2);
}
virtual Constant *fdiv(const Constant *V1, const Constant *V2) const {
return SubClassName::FDiv((const ArgType *)V1, (const ArgType *)V2);
} }
virtual Constant *rem(const Constant *V1, const Constant *V2) const { virtual Constant *rem(const Constant *V1, const Constant *V2) const {
return SubClassName::Rem((const ArgType *)V1, (const ArgType *)V2); return SubClassName::Rem((const ArgType *)V1, (const ArgType *)V2);
@ -181,7 +189,9 @@ class VISIBILITY_HIDDEN TemplateRules : public ConstRules {
static Constant *Add (const ArgType *V1, const ArgType *V2) { return 0; } static Constant *Add (const ArgType *V1, const ArgType *V2) { return 0; }
static Constant *Sub (const ArgType *V1, const ArgType *V2) { return 0; } static Constant *Sub (const ArgType *V1, const ArgType *V2) { return 0; }
static Constant *Mul (const ArgType *V1, const ArgType *V2) { return 0; } static Constant *Mul (const ArgType *V1, const ArgType *V2) { return 0; }
static Constant *Div(const ArgType *V1, const ArgType *V2) { return 0; } static Constant *SDiv(const ArgType *V1, const ArgType *V2) { return 0; }
static Constant *UDiv(const ArgType *V1, const ArgType *V2) { return 0; }
static Constant *FDiv(const ArgType *V1, const ArgType *V2) { return 0; }
static Constant *Rem (const ArgType *V1, const ArgType *V2) { return 0; } static Constant *Rem (const ArgType *V1, const ArgType *V2) { return 0; }
static Constant *And (const ArgType *V1, const ArgType *V2) { return 0; } static Constant *And (const ArgType *V1, const ArgType *V2) { return 0; }
static Constant *Or (const ArgType *V1, const ArgType *V2) { return 0; } static Constant *Or (const ArgType *V1, const ArgType *V2) { return 0; }
@ -373,8 +383,14 @@ struct VISIBILITY_HIDDEN ConstantPackedRules
static Constant *Mul(const ConstantPacked *V1, const ConstantPacked *V2) { static Constant *Mul(const ConstantPacked *V1, const ConstantPacked *V2) {
return EvalVectorOp(V1, V2, ConstantExpr::getMul); return EvalVectorOp(V1, V2, ConstantExpr::getMul);
} }
static Constant *Div(const ConstantPacked *V1, const ConstantPacked *V2) { static Constant *UDiv(const ConstantPacked *V1, const ConstantPacked *V2) {
return EvalVectorOp(V1, V2, ConstantExpr::getDiv); return EvalVectorOp(V1, V2, ConstantExpr::getUDiv);
}
static Constant *SDiv(const ConstantPacked *V1, const ConstantPacked *V2) {
return EvalVectorOp(V1, V2, ConstantExpr::getSDiv);
}
static Constant *FDiv(const ConstantPacked *V1, const ConstantPacked *V2) {
return EvalVectorOp(V1, V2, ConstantExpr::getFDiv);
} }
static Constant *Rem(const ConstantPacked *V1, const ConstantPacked *V2) { static Constant *Rem(const ConstantPacked *V1, const ConstantPacked *V2) {
return EvalVectorOp(V1, V2, ConstantExpr::getRem); return EvalVectorOp(V1, V2, ConstantExpr::getRem);
@ -493,18 +509,25 @@ struct VISIBILITY_HIDDEN DirectIntRules
DEF_CAST(Double, ConstantFP , double) DEF_CAST(Double, ConstantFP , double)
#undef DEF_CAST #undef DEF_CAST
static Constant *Div(const ConstantInt *V1, const ConstantInt *V2) { static Constant *UDiv(const ConstantInt *V1, const ConstantInt *V2) {
if (V2->isNullValue()) return 0; if (V2->isNullValue())
if (V2->isAllOnesValue() && // MIN_INT / -1
(BuiltinType)V1->getZExtValue() == -(BuiltinType)V1->getZExtValue())
return 0; return 0;
BuiltinType R = BuiltinType R = (BuiltinType)(V1->getZExtValue() / V2->getZExtValue());
(BuiltinType)V1->getZExtValue() / (BuiltinType)V2->getZExtValue();
return ConstantInt::get(*Ty, R); return ConstantInt::get(*Ty, R);
} }
static Constant *Rem(const ConstantInt *V1, static Constant *SDiv(const ConstantInt *V1, const ConstantInt *V2) {
const ConstantInt *V2) { if (V2->isNullValue())
return 0;
if (V2->isAllOnesValue() && // MIN_INT / -1
(BuiltinType)V1->getSExtValue() == -(BuiltinType)V1->getSExtValue())
return 0;
BuiltinType R =
(BuiltinType)(V1->getSExtValue() / V2->getSExtValue());
return ConstantInt::get(*Ty, R);
}
static Constant *Rem(const ConstantInt *V1, const ConstantInt *V2) {
if (V2->isNullValue()) return 0; // X / 0 if (V2->isNullValue()) return 0; // X / 0
if (V2->isAllOnesValue() && // MIN_INT / -1 if (V2->isAllOnesValue() && // MIN_INT / -1
(BuiltinType)V1->getZExtValue() == -(BuiltinType)V1->getZExtValue()) (BuiltinType)V1->getZExtValue() == -(BuiltinType)V1->getZExtValue())
@ -615,7 +638,7 @@ struct VISIBILITY_HIDDEN DirectFPRules
(BuiltinType)V2->getValue()); (BuiltinType)V2->getValue());
return ConstantFP::get(*Ty, Result); return ConstantFP::get(*Ty, Result);
} }
static Constant *Div(const ConstantFP *V1, const ConstantFP *V2) { static Constant *FDiv(const ConstantFP *V1, const ConstantFP *V2) {
BuiltinType inf = std::numeric_limits<BuiltinType>::infinity(); BuiltinType inf = std::numeric_limits<BuiltinType>::infinity();
if (V2->isExactlyValue(0.0)) return ConstantFP::get(*Ty, inf); if (V2->isExactlyValue(0.0)) return ConstantFP::get(*Ty, inf);
if (V2->isExactlyValue(-0.0)) return ConstantFP::get(*Ty, -inf); if (V2->isExactlyValue(-0.0)) return ConstantFP::get(*Ty, -inf);
@ -1224,7 +1247,9 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
case Instruction::Add: C = ConstRules::get(V1, V2).add(V1, V2); break; case Instruction::Add: C = ConstRules::get(V1, V2).add(V1, V2); break;
case Instruction::Sub: C = ConstRules::get(V1, V2).sub(V1, V2); break; case Instruction::Sub: C = ConstRules::get(V1, V2).sub(V1, V2); break;
case Instruction::Mul: C = ConstRules::get(V1, V2).mul(V1, V2); break; case Instruction::Mul: C = ConstRules::get(V1, V2).mul(V1, V2); break;
case Instruction::Div: C = ConstRules::get(V1, V2).div(V1, V2); break; case Instruction::UDiv: C = ConstRules::get(V1, V2).udiv(V1, V2); break;
case Instruction::SDiv: C = ConstRules::get(V1, V2).sdiv(V1, V2); break;
case Instruction::FDiv: C = ConstRules::get(V1, V2).fdiv(V1, V2); break;
case Instruction::Rem: C = ConstRules::get(V1, V2).rem(V1, V2); break; case Instruction::Rem: C = ConstRules::get(V1, V2).rem(V1, V2); break;
case Instruction::And: C = ConstRules::get(V1, V2).op_and(V1, V2); break; case Instruction::And: C = ConstRules::get(V1, V2).op_and(V1, V2); break;
case Instruction::Or: C = ConstRules::get(V1, V2).op_or (V1, V2); break; case Instruction::Or: C = ConstRules::get(V1, V2).op_or (V1, V2); break;
@ -1307,7 +1332,9 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
case Instruction::Mul: case Instruction::Mul:
case Instruction::And: case Instruction::And:
return Constant::getNullValue(V1->getType()); return Constant::getNullValue(V1->getType());
case Instruction::Div: case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::FDiv:
case Instruction::Rem: case Instruction::Rem:
if (!isa<UndefValue>(V2)) // undef/X -> 0 if (!isa<UndefValue>(V2)) // undef/X -> 0
return Constant::getNullValue(V1->getType()); return Constant::getNullValue(V1->getType());
@ -1358,7 +1385,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
if (CI->getZExtValue() == 1) if (CI->getZExtValue() == 1)
return const_cast<Constant*>(V1); // X * 1 == X return const_cast<Constant*>(V1); // X * 1 == X
break; break;
case Instruction::Div: case Instruction::UDiv:
case Instruction::SDiv:
if (const ConstantInt *CI = dyn_cast<ConstantInt>(V2)) if (const ConstantInt *CI = dyn_cast<ConstantInt>(V2))
if (CI->getZExtValue() == 1) if (CI->getZExtValue() == 1)
return const_cast<Constant*>(V1); // X / 1 == X return const_cast<Constant*>(V1); // X / 1 == X
@ -1419,7 +1447,9 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
case Instruction::Shl: case Instruction::Shl:
case Instruction::Shr: case Instruction::Shr:
case Instruction::Sub: case Instruction::Sub:
case Instruction::Div: case Instruction::SDiv:
case Instruction::UDiv:
case Instruction::FDiv:
case Instruction::Rem: case Instruction::Rem:
default: // These instructions cannot be flopped around. default: // These instructions cannot be flopped around.
break; break;

View File

@ -75,7 +75,9 @@ bool Constant::canTrap() const {
switch (CE->getOpcode()) { switch (CE->getOpcode()) {
default: default:
return false; return false;
case Instruction::Div: case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::FDiv:
case Instruction::Rem: case Instruction::Rem:
// Div and rem can trap if the RHS is not known to be non-zero. // Div and rem can trap if the RHS is not known to be non-zero.
if (!isa<ConstantInt>(getOperand(1)) || getOperand(1)->isNullValue()) if (!isa<ConstantInt>(getOperand(1)) || getOperand(1)->isNullValue())
@ -446,8 +448,14 @@ Constant *ConstantExpr::getSub(Constant *C1, Constant *C2) {
Constant *ConstantExpr::getMul(Constant *C1, Constant *C2) { Constant *ConstantExpr::getMul(Constant *C1, Constant *C2) {
return get(Instruction::Mul, C1, C2); return get(Instruction::Mul, C1, C2);
} }
Constant *ConstantExpr::getDiv(Constant *C1, Constant *C2) { Constant *ConstantExpr::getUDiv(Constant *C1, Constant *C2) {
return get(Instruction::Div, C1, C2); return get(Instruction::UDiv, C1, C2);
}
Constant *ConstantExpr::getSDiv(Constant *C1, Constant *C2) {
return get(Instruction::SDiv, C1, C2);
}
Constant *ConstantExpr::getFDiv(Constant *C1, Constant *C2) {
return get(Instruction::FDiv, C1, C2);
} }
Constant *ConstantExpr::getRem(Constant *C1, Constant *C2) { Constant *ConstantExpr::getRem(Constant *C1, Constant *C2) {
return get(Instruction::Rem, C1, C2); return get(Instruction::Rem, C1, C2);
@ -1437,13 +1445,27 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
#ifndef NDEBUG #ifndef NDEBUG
switch (Opcode) { switch (Opcode) {
case Instruction::Add: case Instruction::Sub: case Instruction::Add: case Instruction::Sub:
case Instruction::Mul: case Instruction::Div: case Instruction::Mul:
case Instruction::Rem: case Instruction::Rem:
assert(C1->getType() == C2->getType() && "Op types should be identical!"); assert(C1->getType() == C2->getType() && "Op types should be identical!");
assert((C1->getType()->isInteger() || C1->getType()->isFloatingPoint() || assert((C1->getType()->isInteger() || C1->getType()->isFloatingPoint() ||
isa<PackedType>(C1->getType())) && isa<PackedType>(C1->getType())) &&
"Tried to create an arithmetic operation on a non-arithmetic type!"); "Tried to create an arithmetic operation on a non-arithmetic type!");
break; break;
case Instruction::UDiv:
case Instruction::SDiv:
assert(C1->getType() == C2->getType() && "Op types should be identical!");
assert((C1->getType()->isInteger() || (isa<PackedType>(C1->getType()) &&
cast<PackedType>(C1->getType())->getElementType()->isInteger())) &&
"Tried to create an arithmetic operation on a non-arithmetic type!");
break;
case Instruction::FDiv:
assert(C1->getType() == C2->getType() && "Op types should be identical!");
assert((C1->getType()->isFloatingPoint() || (isa<PackedType>(C1->getType())
&& cast<PackedType>(C1->getType())->getElementType()->isFloatingPoint()))
&& "Tried to create an arithmetic operation on a non-arithmetic type!");
break;
case Instruction::And: case Instruction::And:
case Instruction::Or: case Instruction::Or:
case Instruction::Xor: case Instruction::Xor:

View File

@ -94,7 +94,9 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case Add: return "add"; case Add: return "add";
case Sub: return "sub"; case Sub: return "sub";
case Mul: return "mul"; case Mul: return "mul";
case Div: return "div"; case UDiv: return "udiv";
case SDiv: return "sdiv";
case FDiv: return "fdiv";
case Rem: return "rem"; case Rem: return "rem";
// Logical operators... // Logical operators...
@ -221,7 +223,9 @@ bool Instruction::isComparison(unsigned op) {
/// ///
bool Instruction::isTrapping(unsigned op) { bool Instruction::isTrapping(unsigned op) {
switch(op) { switch(op) {
case Div: case UDiv:
case SDiv:
case FDiv:
case Rem: case Rem:
case Load: case Load:
case Store: case Store:

View File

@ -1022,7 +1022,7 @@ void BinaryOperator::init(BinaryOps iType)
#ifndef NDEBUG #ifndef NDEBUG
switch (iType) { switch (iType) {
case Add: case Sub: case Add: case Sub:
case Mul: case Div: case Mul:
case Rem: case Rem:
assert(getType() == LHS->getType() && assert(getType() == LHS->getType() &&
"Arithmetic operation should return same type as operands!"); "Arithmetic operation should return same type as operands!");
@ -1030,6 +1030,22 @@ void BinaryOperator::init(BinaryOps iType)
isa<PackedType>(getType())) && isa<PackedType>(getType())) &&
"Tried to create an arithmetic operation on a non-arithmetic type!"); "Tried to create an arithmetic operation on a non-arithmetic type!");
break; break;
case UDiv:
case SDiv:
assert(getType() == LHS->getType() &&
"Arithmetic operation should return same type as operands!");
assert((getType()->isInteger() || (isa<PackedType>(getType()) &&
cast<PackedType>(getType())->getElementType()->isInteger())) &&
"Incorrect operand type (not integer) for S/UDIV");
break;
case FDiv:
assert(getType() == LHS->getType() &&
"Arithmetic operation should return same type as operands!");
assert((getType()->isFloatingPoint() || (isa<PackedType>(getType()) &&
cast<PackedType>(getType())->getElementType()->isFloatingPoint()))
&& "Incorrect operand type (not floating point) for FDIV");
break;
case And: case Or: case And: case Or:
case Xor: case Xor:
assert(getType() == LHS->getType() && assert(getType() == LHS->getType() &&

View File

@ -1041,7 +1041,7 @@ StackerCompiler::handle_word( int tkn )
LoadInst* op1 = cast<LoadInst>(pop_integer(bb)); LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb)); LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
BinaryOperator* divop = BinaryOperator* divop =
BinaryOperator::create( Instruction::Div, op1, op2); BinaryOperator::create( Instruction::SDiv, op1, op2);
bb->getInstList().push_back( divop ); bb->getInstList().push_back( divop );
push_value( bb, divop ); push_value( bb, divop );
break; break;
@ -1072,7 +1072,7 @@ StackerCompiler::handle_word( int tkn )
// Divide by the third operand // Divide by the third operand
BinaryOperator* divop = BinaryOperator* divop =
BinaryOperator::create( Instruction::Div, multop, op3); BinaryOperator::create( Instruction::SDiv, multop, op3);
bb->getInstList().push_back( divop ); bb->getInstList().push_back( divop );
// Push the result // Push the result

View File

@ -57,13 +57,12 @@ bool %test9(ubyte %A) {
uint %test10(uint %X, bool %C) { uint %test10(uint %X, bool %C) {
%V = select bool %C, uint 64, uint 8 %V = select bool %C, uint 64, uint 8
%R = div uint %X, %V %R = udiv uint %X, %V
ret uint %R ret uint %R
} }
uint %test10(uint %X, ubyte %B) { int %test11(int %X, bool %C) {
%Amt = shl uint 32, ubyte %B %A = select bool %C, int 1024, int 32
%V = div uint %X, %Amt %B = udiv int %X, %A
ret uint %V ret int %B
} }

View File

@ -773,7 +773,9 @@ void CppWriter::printConstant(const Constant *CV) {
case Instruction::Add: Out << "getAdd"; break; case Instruction::Add: Out << "getAdd"; break;
case Instruction::Sub: Out << "getSub"; break; case Instruction::Sub: Out << "getSub"; break;
case Instruction::Mul: Out << "getMul"; break; case Instruction::Mul: Out << "getMul"; break;
case Instruction::Div: Out << "getDiv"; break; case Instruction::UDiv: Out << "getUDiv"; break;
case Instruction::SDiv: Out << "getSDiv"; break;
case Instruction::FDiv: Out << "getFDiv"; break;
case Instruction::Rem: Out << "getRem"; break; case Instruction::Rem: Out << "getRem"; break;
case Instruction::And: Out << "getAnd"; break; case Instruction::And: Out << "getAnd"; break;
case Instruction::Or: Out << "getOr"; break; case Instruction::Or: Out << "getOr"; break;
@ -1021,7 +1023,9 @@ CppWriter::printInstruction(const Instruction *I, const std::string& bbname) {
case Instruction::Add: case Instruction::Add:
case Instruction::Sub: case Instruction::Sub:
case Instruction::Mul: case Instruction::Mul:
case Instruction::Div: case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::FDiv:
case Instruction::Rem: case Instruction::Rem:
case Instruction::And: case Instruction::And:
case Instruction::Or: case Instruction::Or:
@ -1033,7 +1037,9 @@ CppWriter::printInstruction(const Instruction *I, const std::string& bbname) {
case Instruction::Add: Out << "Instruction::Add"; break; case Instruction::Add: Out << "Instruction::Add"; break;
case Instruction::Sub: Out << "Instruction::Sub"; break; case Instruction::Sub: Out << "Instruction::Sub"; break;
case Instruction::Mul: Out << "Instruction::Mul"; break; case Instruction::Mul: Out << "Instruction::Mul"; break;
case Instruction::Div: Out << "Instruction::Div"; break; case Instruction::UDiv:Out << "Instruction::UDiv"; break;
case Instruction::SDiv:Out << "Instruction::SDiv"; break;
case Instruction::FDiv:Out << "Instruction::FDiv"; break;
case Instruction::Rem: Out << "Instruction::Rem"; break; case Instruction::Rem: Out << "Instruction::Rem"; break;
case Instruction::And: Out << "Instruction::And"; break; case Instruction::And: Out << "Instruction::And"; break;
case Instruction::Or: Out << "Instruction::Or"; break; case Instruction::Or: Out << "Instruction::Or"; break;