mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 00:32:55 +00:00
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:
parent
7043d00750
commit
1628cec4d7
@ -77,7 +77,9 @@
|
||||
<li><a href="#i_add">'<tt>add</tt>' Instruction</a></li>
|
||||
<li><a href="#i_sub">'<tt>sub</tt>' Instruction</a></li>
|
||||
<li><a href="#i_mul">'<tt>mul</tt>' Instruction</a></li>
|
||||
<li><a href="#i_div">'<tt>div</tt>' Instruction</a></li>
|
||||
<li><a href="#i_udiv">'<tt>udiv</tt>' Instruction</a></li>
|
||||
<li><a href="#i_sdiv">'<tt>sdiv</tt>' Instruction</a></li>
|
||||
<li><a href="#i_fdiv">'<tt>fdiv</tt>' Instruction</a></li>
|
||||
<li><a href="#i_rem">'<tt>rem</tt>' Instruction</a></li>
|
||||
<li><a href="#i_setcc">'<tt>set<i>cc</i></tt>' Instructions</a></li>
|
||||
</ol>
|
||||
@ -1630,26 +1632,70 @@ action is taken based on the type of the operand.</p>
|
||||
</pre>
|
||||
</div>
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<div class="doc_subsubsection"> <a name="i_div">'<tt>div</tt>'
|
||||
<div class="doc_subsubsection"> <a name="i_udiv">'<tt>udiv</tt>' Instruction
|
||||
</a></div>
|
||||
<div class="doc_text">
|
||||
<h5>Syntax:</h5>
|
||||
<pre> <result> = udiv <ty> <var1>, <var2> <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> <result> = 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> <result> = sdiv <ty> <var1>, <var2> <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> <result> = sdiv int 4, %var <i>; yields {int}:result = 4 / %var</i>
|
||||
</pre>
|
||||
</div>
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<div class="doc_subsubsection"> <a name="i_fdiv">'<tt>fdiv</tt>'
|
||||
Instruction</a> </div>
|
||||
<div class="doc_text">
|
||||
<h5>Syntax:</h5>
|
||||
<pre> <result> = div <ty> <var1>, <var2> <i>; yields {ty}:result</i>
|
||||
<pre> <result> = fdiv <ty> <var1>, <var2> <i>; yields {ty}:result</i>
|
||||
</pre>
|
||||
<h5>Overview:</h5>
|
||||
<p>The '<tt>div</tt>' instruction returns the quotient of its two
|
||||
<p>The '<tt>fdiv</tt>' instruction returns the quotient of its two
|
||||
operands.</p>
|
||||
<h5>Arguments:</h5>
|
||||
<p>The two arguments to the '<tt>div</tt>' instruction must be either <a
|
||||
href="#t_integer">integer</a> or <a href="#t_floating">floating point</a>
|
||||
values.
|
||||
This instruction can also take <a href="#t_packed">packed</a> versions of the values.
|
||||
Both arguments must have identical types.</p>
|
||||
<p>The two arguments to the '<tt>div</tt>' instruction must be
|
||||
<a href="#t_floating">floating point</a> values. Both arguments must have
|
||||
identical types. This instruction can also take <a href="#t_packed">packed</a>
|
||||
versions of the values in which case the elements must be floating point.</p>
|
||||
<h5>Semantics:</h5>
|
||||
<p>The value produced is the integer or floating point quotient of the
|
||||
two operands.</p>
|
||||
<p>The value produced is the floating point quotient of the two operands.</p>
|
||||
<h5>Example:</h5>
|
||||
<pre> <result> = div int 4, %var <i>; yields {int}:result = 4 / %var</i>
|
||||
<pre> <result> = fdiv float 4.0, %var <i>; yields {float}:result = 4.0 / %var</i>
|
||||
</pre>
|
||||
</div>
|
||||
<!-- _______________________________________________________________________ -->
|
||||
|
@ -140,7 +140,7 @@ namespace llvm {
|
||||
const Type *Ty = S->getType();
|
||||
Value *LHS = expandInTy(S->getLHS(), Ty);
|
||||
Value *RHS = expandInTy(S->getRHS(), Ty);
|
||||
return BinaryOperator::createDiv(LHS, RHS, "tmp.", InsertPt);
|
||||
return BinaryOperator::createSDiv(LHS, RHS, "tmp.", InsertPt);
|
||||
}
|
||||
|
||||
Value *visitAddRecExpr(SCEVAddRecExpr *S);
|
||||
|
@ -293,7 +293,7 @@ namespace llvm {
|
||||
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SCEVSDivExpr - This class represents a binary unsigned division operation.
|
||||
/// SCEVSDivExpr - This class represents a binary signed division operation.
|
||||
///
|
||||
class SCEVSDivExpr : public SCEV {
|
||||
SCEVHandle LHS, RHS;
|
||||
|
@ -543,7 +543,9 @@ public:
|
||||
static Constant *getAdd(Constant *C1, Constant *C2);
|
||||
static Constant *getSub(Constant *C1, Constant *C2);
|
||||
static Constant *getMul(Constant *C1, Constant *C2);
|
||||
static Constant *getDiv(Constant *C1, Constant *C2);
|
||||
static Constant *getUDiv(Constant *C1, Constant *C2);
|
||||
static Constant *getSDiv(Constant *C1, Constant *C2);
|
||||
static Constant *getFDiv(Constant *C1, Constant *C2);
|
||||
static Constant *getRem(Constant *C1, Constant *C2);
|
||||
static Constant *getAnd(Constant *C1, Constant *C2);
|
||||
static Constant *getOr(Constant *C1, Constant *C2);
|
||||
|
@ -93,45 +93,43 @@ HANDLE_TERM_INST ( 6, Unreachable, UnreachableInst)
|
||||
HANDLE_BINARY_INST( 7, Add , BinaryOperator)
|
||||
HANDLE_BINARY_INST( 8, Sub , BinaryOperator)
|
||||
HANDLE_BINARY_INST( 9, Mul , BinaryOperator)
|
||||
HANDLE_BINARY_INST(10, Div , BinaryOperator)
|
||||
HANDLE_BINARY_INST(11, Rem , BinaryOperator)
|
||||
HANDLE_BINARY_INST(10, UDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(11, SDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(12, FDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(13, Rem , BinaryOperator)
|
||||
|
||||
// Logical operators...
|
||||
HANDLE_BINARY_INST(12, And , BinaryOperator)
|
||||
HANDLE_BINARY_INST(13, Or , BinaryOperator)
|
||||
HANDLE_BINARY_INST(14, Xor , BinaryOperator)
|
||||
HANDLE_BINARY_INST(14, And , BinaryOperator)
|
||||
HANDLE_BINARY_INST(15, Or , BinaryOperator)
|
||||
HANDLE_BINARY_INST(16, Xor , BinaryOperator)
|
||||
|
||||
// Binary comparison operators...
|
||||
HANDLE_BINARY_INST(15, SetEQ , SetCondInst)
|
||||
HANDLE_BINARY_INST(16, SetNE , SetCondInst)
|
||||
HANDLE_BINARY_INST(17, SetLE , SetCondInst)
|
||||
HANDLE_BINARY_INST(18, SetGE , SetCondInst)
|
||||
HANDLE_BINARY_INST(19, SetLT , SetCondInst)
|
||||
HANDLE_BINARY_INST(20, SetGT , SetCondInst)
|
||||
LAST_BINARY_INST(20)
|
||||
HANDLE_BINARY_INST(17, SetEQ , SetCondInst)
|
||||
HANDLE_BINARY_INST(18, SetNE , SetCondInst)
|
||||
HANDLE_BINARY_INST(19, SetLE , SetCondInst)
|
||||
HANDLE_BINARY_INST(20, SetGE , SetCondInst)
|
||||
HANDLE_BINARY_INST(21, SetLT , SetCondInst)
|
||||
HANDLE_BINARY_INST(22, SetGT , SetCondInst)
|
||||
LAST_BINARY_INST(22)
|
||||
|
||||
// Memory operators...
|
||||
FIRST_MEMORY_INST(21)
|
||||
HANDLE_MEMORY_INST(21, Malloc, MallocInst) // Heap management instructions
|
||||
HANDLE_MEMORY_INST(22, Free , FreeInst )
|
||||
HANDLE_MEMORY_INST(23, Alloca, AllocaInst) // Stack management
|
||||
HANDLE_MEMORY_INST(24, Load , LoadInst ) // Memory manipulation instrs
|
||||
HANDLE_MEMORY_INST(25, Store , StoreInst )
|
||||
HANDLE_MEMORY_INST(26, GetElementPtr, GetElementPtrInst)
|
||||
LAST_MEMORY_INST(26)
|
||||
FIRST_MEMORY_INST(23)
|
||||
HANDLE_MEMORY_INST(23, Malloc, MallocInst) // Heap management instructions
|
||||
HANDLE_MEMORY_INST(24, Free , FreeInst )
|
||||
HANDLE_MEMORY_INST(25, Alloca, AllocaInst) // Stack management
|
||||
HANDLE_MEMORY_INST(26, Load , LoadInst ) // Memory manipulation instrs
|
||||
HANDLE_MEMORY_INST(27, Store , StoreInst )
|
||||
HANDLE_MEMORY_INST(28, GetElementPtr, GetElementPtrInst)
|
||||
LAST_MEMORY_INST(28)
|
||||
|
||||
// Other operators...
|
||||
FIRST_OTHER_INST(27)
|
||||
HANDLE_OTHER_INST(27, PHI , PHINode ) // PHI node instruction
|
||||
HANDLE_OTHER_INST(28, Cast , CastInst ) // Type cast
|
||||
HANDLE_OTHER_INST(29, Call , CallInst ) // Call a function
|
||||
|
||||
HANDLE_OTHER_INST(30, Shl , ShiftInst ) // Shift operations
|
||||
HANDLE_OTHER_INST(31, Shr , ShiftInst )
|
||||
// 32 -> Empty slot used to be used for vanext in llvm 1.5 and before.
|
||||
// 33 -> Empty slot used to be used for vaarg in llvm 1.5 and before.
|
||||
FIRST_OTHER_INST(29)
|
||||
HANDLE_OTHER_INST(29, PHI , PHINode ) // PHI node instruction
|
||||
HANDLE_OTHER_INST(30, Cast , CastInst ) // Type cast
|
||||
HANDLE_OTHER_INST(31, Call , CallInst ) // Call a function
|
||||
HANDLE_OTHER_INST(32, Shl , ShiftInst ) // Shift operations
|
||||
HANDLE_OTHER_INST(33, Shr , ShiftInst )
|
||||
HANDLE_OTHER_INST(34, Select , SelectInst ) // select instruction
|
||||
|
||||
HANDLE_OTHER_INST(35, UserOp1, Instruction) // May be used internally in a pass
|
||||
HANDLE_OTHER_INST(36, UserOp2, Instruction)
|
||||
HANDLE_OTHER_INST(37, VAArg , VAArgInst ) // vaarg instruction
|
||||
|
@ -112,9 +112,21 @@ inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS &L,
|
||||
}
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
inline BinaryOp_match<LHS, RHS, Instruction::Div> m_Div(const LHS &L,
|
||||
inline BinaryOp_match<LHS, RHS, Instruction::UDiv> m_UDiv(const LHS &L,
|
||||
const RHS &R) {
|
||||
return BinaryOp_match<LHS, RHS, Instruction::Div>(L, R);
|
||||
return BinaryOp_match<LHS, RHS, Instruction::UDiv>(L, R);
|
||||
}
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
inline BinaryOp_match<LHS, RHS, Instruction::SDiv> m_SDiv(const LHS &L,
|
||||
const RHS &R) {
|
||||
return BinaryOp_match<LHS, RHS, Instruction::SDiv>(L, R);
|
||||
}
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
inline BinaryOp_match<LHS, RHS, Instruction::FDiv> m_FDiv(const LHS &L,
|
||||
const RHS &R) {
|
||||
return BinaryOp_match<LHS, RHS, Instruction::FDiv>(L, R);
|
||||
}
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
|
@ -989,9 +989,9 @@ SCEVHandle SCEVMulExpr::get(std::vector<SCEVHandle> &Ops) {
|
||||
SCEVHandle SCEVSDivExpr::get(const SCEVHandle &LHS, const SCEVHandle &RHS) {
|
||||
if (SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS)) {
|
||||
if (RHSC->getValue()->equalsInt(1))
|
||||
return LHS; // X /s 1 --> x
|
||||
return LHS; // X sdiv 1 --> x
|
||||
if (RHSC->getValue()->isAllOnesValue())
|
||||
return SCEV::getNegativeSCEV(LHS); // X /s -1 --> -x
|
||||
return SCEV::getNegativeSCEV(LHS); // X sdiv -1 --> -x
|
||||
|
||||
if (SCEVConstant *LHSC = dyn_cast<SCEVConstant>(LHS)) {
|
||||
Constant *LHSCV = LHSC->getValue();
|
||||
@ -1001,7 +1001,7 @@ SCEVHandle SCEVSDivExpr::get(const SCEVHandle &LHS, const SCEVHandle &RHS) {
|
||||
LHSCV->getType()->getSignedVersion());
|
||||
if (RHSCV->getType()->isUnsigned())
|
||||
RHSCV = ConstantExpr::getCast(RHSCV, LHSCV->getType());
|
||||
return SCEVUnknown::get(ConstantExpr::getDiv(LHSCV, RHSCV));
|
||||
return SCEVUnknown::get(ConstantExpr::getSDiv(LHSCV, RHSCV));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1384,10 +1384,9 @@ SCEVHandle ScalarEvolutionsImpl::createSCEV(Value *V) {
|
||||
case Instruction::Mul:
|
||||
return SCEVMulExpr::get(getSCEV(I->getOperand(0)),
|
||||
getSCEV(I->getOperand(1)));
|
||||
case Instruction::Div:
|
||||
if (V->getType()->isInteger() && V->getType()->isSigned())
|
||||
return SCEVSDivExpr::get(getSCEV(I->getOperand(0)),
|
||||
getSCEV(I->getOperand(1)));
|
||||
case Instruction::SDiv:
|
||||
return SCEVSDivExpr::get(getSCEV(I->getOperand(0)),
|
||||
getSCEV(I->getOperand(1)));
|
||||
break;
|
||||
|
||||
case Instruction::Sub:
|
||||
@ -2058,16 +2057,16 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec) {
|
||||
return std::make_pair(CNC, CNC);
|
||||
}
|
||||
|
||||
Constant *Two = ConstantInt::get(L->getValue()->getType(), 2);
|
||||
Constant *C = L->getValue();
|
||||
Constant *Two = ConstantInt::get(C->getType(), 2);
|
||||
|
||||
// Convert from chrec coefficients to polynomial coefficients AX^2+BX+C
|
||||
Constant *C = L->getValue();
|
||||
// The B coefficient is M-N/2
|
||||
Constant *B = ConstantExpr::getSub(M->getValue(),
|
||||
ConstantExpr::getDiv(N->getValue(),
|
||||
ConstantExpr::getSDiv(N->getValue(),
|
||||
Two));
|
||||
// The A coefficient is N/2
|
||||
Constant *A = ConstantExpr::getDiv(N->getValue(), Two);
|
||||
Constant *A = ConstantExpr::getSDiv(N->getValue(), Two);
|
||||
|
||||
// Compute the B^2-4ac term.
|
||||
Constant *SqrtTerm =
|
||||
@ -2102,9 +2101,9 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec) {
|
||||
SqrtTerm = ConstantExpr::getCast(SqrtTerm, SignedTy);
|
||||
|
||||
Constant *Solution1 =
|
||||
ConstantExpr::getDiv(ConstantExpr::getAdd(NegB, SqrtTerm), TwoA);
|
||||
ConstantExpr::getSDiv(ConstantExpr::getAdd(NegB, SqrtTerm), TwoA);
|
||||
Constant *Solution2 =
|
||||
ConstantExpr::getDiv(ConstantExpr::getSub(NegB, SqrtTerm), TwoA);
|
||||
ConstantExpr::getSDiv(ConstantExpr::getSub(NegB, SqrtTerm), TwoA);
|
||||
return std::make_pair(SCEVUnknown::get(Solution1),
|
||||
SCEVUnknown::get(Solution2));
|
||||
}
|
||||
@ -2150,7 +2149,7 @@ SCEVHandle ScalarEvolutionsImpl::HowFarToZero(SCEV *V, const Loop *L) {
|
||||
Constant *StartNegC = ConstantExpr::getNeg(StartCC);
|
||||
Constant *Rem = ConstantExpr::getRem(StartNegC, StepC->getValue());
|
||||
if (Rem->isNullValue()) {
|
||||
Constant *Result =ConstantExpr::getDiv(StartNegC,StepC->getValue());
|
||||
Constant *Result =ConstantExpr::getSDiv(StartNegC,StepC->getValue());
|
||||
return SCEVUnknown::get(Result);
|
||||
}
|
||||
}
|
||||
@ -2352,7 +2351,7 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
|
||||
Constant *ExitValue = Upper;
|
||||
if (A != One) {
|
||||
ExitValue = ConstantExpr::getSub(ConstantExpr::getAdd(Upper, A), One);
|
||||
ExitValue = ConstantExpr::getDiv(ExitValue, A);
|
||||
ExitValue = ConstantExpr::getSDiv(ExitValue, A);
|
||||
}
|
||||
assert(isa<ConstantInt>(ExitValue) &&
|
||||
"Constant folding of integers not implemented?");
|
||||
|
@ -39,8 +39,18 @@ void set_scan_string (const char * str) {
|
||||
yy_scan_string (str);
|
||||
}
|
||||
|
||||
// Construct a token value for a non-obsolete token
|
||||
#define RET_TOK(type, Enum, sym) \
|
||||
llvmAsmlval.type = Instruction::Enum; return sym
|
||||
llvmAsmlval.type.opcode = Instruction::Enum; \
|
||||
llvmAsmlval.type.obsolete = false; \
|
||||
return sym
|
||||
|
||||
// Construct a token value for an obsolete token
|
||||
#define RET_TOK_OBSOLETE(type, Enum, sym) \
|
||||
llvmAsmlval.type.opcode = Instruction::Enum; \
|
||||
llvmAsmlval.type.obsolete = true; \
|
||||
return sym
|
||||
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -247,7 +257,10 @@ opaque { return OPAQUE; }
|
||||
add { RET_TOK(BinaryOpVal, Add, ADD); }
|
||||
sub { RET_TOK(BinaryOpVal, Sub, SUB); }
|
||||
mul { RET_TOK(BinaryOpVal, Mul, MUL); }
|
||||
div { RET_TOK(BinaryOpVal, Div, DIV); }
|
||||
div { RET_TOK_OBSOLETE(BinaryOpVal, UDiv, UDIV); }
|
||||
udiv { RET_TOK(BinaryOpVal, UDiv, UDIV); }
|
||||
sdiv { RET_TOK(BinaryOpVal, SDiv, SDIV); }
|
||||
fdiv { RET_TOK(BinaryOpVal, FDiv, FDIV); }
|
||||
rem { RET_TOK(BinaryOpVal, Rem, REM); }
|
||||
and { RET_TOK(BinaryOpVal, And, AND); }
|
||||
or { RET_TOK(BinaryOpVal, Or , OR ); }
|
||||
|
@ -201,4 +201,20 @@ struct ValID {
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
// This structure is used to keep track of obsolete opcodes. The lexer will
|
||||
// retain the ability to parse obsolete opcode mnemonics. In this case it will
|
||||
// set "obsolete" to true and the opcode will be the replacement opcode. For
|
||||
// example if "rem" is encountered then opcode will be set to "urem" and the
|
||||
// "obsolete" flag will be true. If the opcode is not obsolete then "obsolete"
|
||||
// will be false.
|
||||
template <class Enum>
|
||||
struct OpcodeInfo {
|
||||
Enum opcode;
|
||||
bool obsolete;
|
||||
};
|
||||
typedef OpcodeInfo<llvm::Instruction::BinaryOps> BinaryOpInfo;
|
||||
typedef OpcodeInfo<llvm::Instruction::TermOps> TermOpInfo;
|
||||
typedef OpcodeInfo<llvm::Instruction::MemoryOps> MemOpInfo;
|
||||
typedef OpcodeInfo<llvm::Instruction::OtherOps> OtherOpInfo;
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -107,34 +107,36 @@
|
||||
ADD = 333,
|
||||
SUB = 334,
|
||||
MUL = 335,
|
||||
DIV = 336,
|
||||
REM = 337,
|
||||
AND = 338,
|
||||
OR = 339,
|
||||
XOR = 340,
|
||||
SETLE = 341,
|
||||
SETGE = 342,
|
||||
SETLT = 343,
|
||||
SETGT = 344,
|
||||
SETEQ = 345,
|
||||
SETNE = 346,
|
||||
MALLOC = 347,
|
||||
ALLOCA = 348,
|
||||
FREE = 349,
|
||||
LOAD = 350,
|
||||
STORE = 351,
|
||||
GETELEMENTPTR = 352,
|
||||
PHI_TOK = 353,
|
||||
CAST = 354,
|
||||
SELECT = 355,
|
||||
SHL = 356,
|
||||
SHR = 357,
|
||||
VAARG = 358,
|
||||
EXTRACTELEMENT = 359,
|
||||
INSERTELEMENT = 360,
|
||||
SHUFFLEVECTOR = 361,
|
||||
VAARG_old = 362,
|
||||
VANEXT_old = 363
|
||||
UDIV = 336,
|
||||
SDIV = 337,
|
||||
FDIV = 338,
|
||||
REM = 339,
|
||||
AND = 340,
|
||||
OR = 341,
|
||||
XOR = 342,
|
||||
SETLE = 343,
|
||||
SETGE = 344,
|
||||
SETLT = 345,
|
||||
SETGT = 346,
|
||||
SETEQ = 347,
|
||||
SETNE = 348,
|
||||
MALLOC = 349,
|
||||
ALLOCA = 350,
|
||||
FREE = 351,
|
||||
LOAD = 352,
|
||||
STORE = 353,
|
||||
GETELEMENTPTR = 354,
|
||||
PHI_TOK = 355,
|
||||
CAST = 356,
|
||||
SELECT = 357,
|
||||
SHL = 358,
|
||||
SHR = 359,
|
||||
VAARG = 360,
|
||||
EXTRACTELEMENT = 361,
|
||||
INSERTELEMENT = 362,
|
||||
SHUFFLEVECTOR = 363,
|
||||
VAARG_old = 364,
|
||||
VANEXT_old = 365
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
@ -216,40 +218,42 @@
|
||||
#define ADD 333
|
||||
#define SUB 334
|
||||
#define MUL 335
|
||||
#define DIV 336
|
||||
#define REM 337
|
||||
#define AND 338
|
||||
#define OR 339
|
||||
#define XOR 340
|
||||
#define SETLE 341
|
||||
#define SETGE 342
|
||||
#define SETLT 343
|
||||
#define SETGT 344
|
||||
#define SETEQ 345
|
||||
#define SETNE 346
|
||||
#define MALLOC 347
|
||||
#define ALLOCA 348
|
||||
#define FREE 349
|
||||
#define LOAD 350
|
||||
#define STORE 351
|
||||
#define GETELEMENTPTR 352
|
||||
#define PHI_TOK 353
|
||||
#define CAST 354
|
||||
#define SELECT 355
|
||||
#define SHL 356
|
||||
#define SHR 357
|
||||
#define VAARG 358
|
||||
#define EXTRACTELEMENT 359
|
||||
#define INSERTELEMENT 360
|
||||
#define SHUFFLEVECTOR 361
|
||||
#define VAARG_old 362
|
||||
#define VANEXT_old 363
|
||||
#define UDIV 336
|
||||
#define SDIV 337
|
||||
#define FDIV 338
|
||||
#define REM 339
|
||||
#define AND 340
|
||||
#define OR 341
|
||||
#define XOR 342
|
||||
#define SETLE 343
|
||||
#define SETGE 344
|
||||
#define SETLT 345
|
||||
#define SETGT 346
|
||||
#define SETEQ 347
|
||||
#define SETNE 348
|
||||
#define MALLOC 349
|
||||
#define ALLOCA 350
|
||||
#define FREE 351
|
||||
#define LOAD 352
|
||||
#define STORE 353
|
||||
#define GETELEMENTPTR 354
|
||||
#define PHI_TOK 355
|
||||
#define CAST 356
|
||||
#define SELECT 357
|
||||
#define SHL 358
|
||||
#define SHR 359
|
||||
#define VAARG 360
|
||||
#define EXTRACTELEMENT 361
|
||||
#define INSERTELEMENT 362
|
||||
#define SHUFFLEVECTOR 363
|
||||
#define VAARG_old 364
|
||||
#define VANEXT_old 365
|
||||
|
||||
|
||||
|
||||
|
||||
#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 {
|
||||
llvm::Module *ModuleVal;
|
||||
llvm::Function *FunctionVal;
|
||||
@ -281,16 +285,16 @@ typedef union YYSTYPE {
|
||||
bool BoolVal;
|
||||
|
||||
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;
|
||||
llvm::Instruction::TermOps TermOpVal;
|
||||
llvm::Instruction::MemoryOps MemOpVal;
|
||||
llvm::Instruction::OtherOps OtherOpVal;
|
||||
llvm::Module::Endianness Endianness;
|
||||
BinaryOpInfo BinaryOpVal;
|
||||
TermOpInfo TermOpVal;
|
||||
MemOpInfo MemOpVal;
|
||||
OtherOpInfo OtherOpVal;
|
||||
llvm::Module::Endianness Endianness;
|
||||
} YYSTYPE;
|
||||
/* Line 1447 of yacc.c. */
|
||||
#line 294 "llvmAsmParser.tab.h"
|
||||
#line 298 "llvmAsmParser.tab.h"
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
|
@ -813,6 +813,43 @@ static PATypeHolder HandleUpRefs(const Type *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
|
||||
static Module* RunParser(Module * M) {
|
||||
@ -1002,13 +1039,13 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
|
||||
bool BoolVal;
|
||||
|
||||
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;
|
||||
llvm::Instruction::TermOps TermOpVal;
|
||||
llvm::Instruction::MemoryOps MemOpVal;
|
||||
llvm::Instruction::OtherOps OtherOpVal;
|
||||
llvm::Module::Endianness Endianness;
|
||||
BinaryOpInfo BinaryOpVal;
|
||||
TermOpInfo TermOpVal;
|
||||
MemOpInfo MemOpVal;
|
||||
OtherOpInfo OtherOpVal;
|
||||
llvm::Module::Endianness Endianness;
|
||||
}
|
||||
|
||||
%type <ModuleVal> Module FunctionList
|
||||
@ -1076,8 +1113,8 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
|
||||
|
||||
// Binary Operators
|
||||
%type <BinaryOpVal> ArithmeticOps LogicalOps SetCondOps // Binops Subcatagories
|
||||
%token <BinaryOpVal> ADD SUB MUL DIV REM AND OR XOR
|
||||
%token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comarators
|
||||
%token <BinaryOpVal> ADD SUB MUL UDIV SDIV FDIV REM AND OR XOR
|
||||
%token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comparators
|
||||
|
||||
// Memory Instructions
|
||||
%token <MemOpVal> MALLOC ALLOCA FREE LOAD STORE GETELEMENTPTR
|
||||
@ -1114,7 +1151,7 @@ EINT64VAL : EUINT64VAL {
|
||||
// Operations that are notably excluded from this list include:
|
||||
// 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;
|
||||
SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
|
||||
|
||||
@ -1642,12 +1679,17 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
|
||||
| ArithmeticOps '(' ConstVal ',' ConstVal ')' {
|
||||
if ($3->getType() != $5->getType())
|
||||
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.
|
||||
// To retain backward compatibility with these early compilers, we emit a
|
||||
// cast to the appropriate integer type automatically if we are in the
|
||||
// broken case. See PR424 for more information.
|
||||
if (!isa<PointerType>($3->getType())) {
|
||||
$$ = ConstantExpr::get($1, $3, $5);
|
||||
$$ = ConstantExpr::get($1.opcode, $3, $5);
|
||||
} else {
|
||||
const Type *IntPtrTy = 0;
|
||||
switch (CurModule.CurrentModule->getPointerSize()) {
|
||||
@ -1655,7 +1697,7 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
|
||||
case Module::Pointer64: IntPtrTy = Type::LongTy; break;
|
||||
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($$, $3->getType());
|
||||
}
|
||||
@ -1669,13 +1711,13 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
|
||||
!cast<PackedType>($3->getType())->getElementType()->isIntegral())
|
||||
GEN_ERROR("Logical operator requires integral operands!");
|
||||
}
|
||||
$$ = ConstantExpr::get($1, $3, $5);
|
||||
$$ = ConstantExpr::get($1.opcode, $3, $5);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| SetCondOps '(' ConstVal ',' ConstVal ')' {
|
||||
if ($3->getType() != $5->getType())
|
||||
GEN_ERROR("setcc operand types must match!");
|
||||
$$ = ConstantExpr::get($1, $3, $5);
|
||||
$$ = ConstantExpr::get($1.opcode, $3, $5);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| ShiftOps '(' ConstVal ',' ConstVal ')' {
|
||||
@ -1683,7 +1725,7 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
|
||||
GEN_ERROR("Shift count for shift constant must be unsigned byte!");
|
||||
if (!$3->getType()->isInteger())
|
||||
GEN_ERROR("Shift constant expression requires integer operand!");
|
||||
$$ = ConstantExpr::get($1, $3, $5);
|
||||
$$ = ConstantExpr::get($1.opcode, $3, $5);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| EXTRACTELEMENT '(' ConstVal ',' ConstVal ')' {
|
||||
@ -2423,13 +2465,16 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
!isa<PackedType>((*$2).get()))
|
||||
GEN_ERROR(
|
||||
"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!");
|
||||
// Upgrade the opcode from obsolete versions before we do anything with it.
|
||||
sanitizeOpCode($1,*$2);
|
||||
CHECK_FOR_ERROR;
|
||||
Value* val1 = getVal(*$2, $3);
|
||||
CHECK_FOR_ERROR
|
||||
Value* val2 = getVal(*$2, $5);
|
||||
CHECK_FOR_ERROR
|
||||
$$ = BinaryOperator::create($1, val1, val2);
|
||||
$$ = BinaryOperator::create($1.opcode, val1, val2);
|
||||
if ($$ == 0)
|
||||
GEN_ERROR("binary operator returned null!");
|
||||
delete $2;
|
||||
@ -2444,7 +2489,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
CHECK_FOR_ERROR
|
||||
Value* tmpVal2 = getVal(*$2, $5);
|
||||
CHECK_FOR_ERROR
|
||||
$$ = BinaryOperator::create($1, tmpVal1, tmpVal2);
|
||||
$$ = BinaryOperator::create($1.opcode, tmpVal1, tmpVal2);
|
||||
if ($$ == 0)
|
||||
GEN_ERROR("binary operator returned null!");
|
||||
delete $2;
|
||||
@ -2458,7 +2503,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
CHECK_FOR_ERROR
|
||||
Value* tmpVal2 = getVal(*$2, $5);
|
||||
CHECK_FOR_ERROR
|
||||
$$ = new SetCondInst($1, tmpVal1, tmpVal2);
|
||||
$$ = new SetCondInst($1.opcode, tmpVal1, tmpVal2);
|
||||
if ($$ == 0)
|
||||
GEN_ERROR("binary operator returned null!");
|
||||
delete $2;
|
||||
@ -2481,7 +2526,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
GEN_ERROR("Shift amount must be ubyte!");
|
||||
if (!$2->getType()->isInteger())
|
||||
GEN_ERROR("Shift constant expression requires integer operand!");
|
||||
$$ = new ShiftInst($1, $2, $4);
|
||||
$$ = new ShiftInst($1.opcode, $2, $4);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| CAST ResolvedVal TO Types {
|
||||
|
@ -813,6 +813,43 @@ static PATypeHolder HandleUpRefs(const Type *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
|
||||
static Module* RunParser(Module * M) {
|
||||
@ -1002,13 +1039,13 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
|
||||
bool BoolVal;
|
||||
|
||||
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;
|
||||
llvm::Instruction::TermOps TermOpVal;
|
||||
llvm::Instruction::MemoryOps MemOpVal;
|
||||
llvm::Instruction::OtherOps OtherOpVal;
|
||||
llvm::Module::Endianness Endianness;
|
||||
BinaryOpInfo BinaryOpVal;
|
||||
TermOpInfo TermOpVal;
|
||||
MemOpInfo MemOpVal;
|
||||
OtherOpInfo OtherOpVal;
|
||||
llvm::Module::Endianness Endianness;
|
||||
}
|
||||
|
||||
%type <ModuleVal> Module FunctionList
|
||||
@ -1076,8 +1113,8 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
|
||||
|
||||
// Binary Operators
|
||||
%type <BinaryOpVal> ArithmeticOps LogicalOps SetCondOps // Binops Subcatagories
|
||||
%token <BinaryOpVal> ADD SUB MUL DIV REM AND OR XOR
|
||||
%token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comarators
|
||||
%token <BinaryOpVal> ADD SUB MUL UDIV SDIV FDIV REM AND OR XOR
|
||||
%token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comparators
|
||||
|
||||
// Memory Instructions
|
||||
%token <MemOpVal> MALLOC ALLOCA FREE LOAD STORE GETELEMENTPTR
|
||||
@ -1114,7 +1151,7 @@ EINT64VAL : EUINT64VAL {
|
||||
// Operations that are notably excluded from this list include:
|
||||
// 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;
|
||||
SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
|
||||
|
||||
@ -1642,12 +1679,17 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
|
||||
| ArithmeticOps '(' ConstVal ',' ConstVal ')' {
|
||||
if ($3->getType() != $5->getType())
|
||||
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.
|
||||
// To retain backward compatibility with these early compilers, we emit a
|
||||
// cast to the appropriate integer type automatically if we are in the
|
||||
// broken case. See PR424 for more information.
|
||||
if (!isa<PointerType>($3->getType())) {
|
||||
$$ = ConstantExpr::get($1, $3, $5);
|
||||
$$ = ConstantExpr::get($1.opcode, $3, $5);
|
||||
} else {
|
||||
const Type *IntPtrTy = 0;
|
||||
switch (CurModule.CurrentModule->getPointerSize()) {
|
||||
@ -1655,7 +1697,7 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
|
||||
case Module::Pointer64: IntPtrTy = Type::LongTy; break;
|
||||
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($$, $3->getType());
|
||||
}
|
||||
@ -1669,13 +1711,13 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
|
||||
!cast<PackedType>($3->getType())->getElementType()->isIntegral())
|
||||
GEN_ERROR("Logical operator requires integral operands!");
|
||||
}
|
||||
$$ = ConstantExpr::get($1, $3, $5);
|
||||
$$ = ConstantExpr::get($1.opcode, $3, $5);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| SetCondOps '(' ConstVal ',' ConstVal ')' {
|
||||
if ($3->getType() != $5->getType())
|
||||
GEN_ERROR("setcc operand types must match!");
|
||||
$$ = ConstantExpr::get($1, $3, $5);
|
||||
$$ = ConstantExpr::get($1.opcode, $3, $5);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| ShiftOps '(' ConstVal ',' ConstVal ')' {
|
||||
@ -1683,7 +1725,7 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
|
||||
GEN_ERROR("Shift count for shift constant must be unsigned byte!");
|
||||
if (!$3->getType()->isInteger())
|
||||
GEN_ERROR("Shift constant expression requires integer operand!");
|
||||
$$ = ConstantExpr::get($1, $3, $5);
|
||||
$$ = ConstantExpr::get($1.opcode, $3, $5);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| EXTRACTELEMENT '(' ConstVal ',' ConstVal ')' {
|
||||
@ -2423,13 +2465,16 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
!isa<PackedType>((*$2).get()))
|
||||
GEN_ERROR(
|
||||
"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!");
|
||||
// Upgrade the opcode from obsolete versions before we do anything with it.
|
||||
sanitizeOpCode($1,*$2);
|
||||
CHECK_FOR_ERROR;
|
||||
Value* val1 = getVal(*$2, $3);
|
||||
CHECK_FOR_ERROR
|
||||
Value* val2 = getVal(*$2, $5);
|
||||
CHECK_FOR_ERROR
|
||||
$$ = BinaryOperator::create($1, val1, val2);
|
||||
$$ = BinaryOperator::create($1.opcode, val1, val2);
|
||||
if ($$ == 0)
|
||||
GEN_ERROR("binary operator returned null!");
|
||||
delete $2;
|
||||
@ -2444,7 +2489,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
CHECK_FOR_ERROR
|
||||
Value* tmpVal2 = getVal(*$2, $5);
|
||||
CHECK_FOR_ERROR
|
||||
$$ = BinaryOperator::create($1, tmpVal1, tmpVal2);
|
||||
$$ = BinaryOperator::create($1.opcode, tmpVal1, tmpVal2);
|
||||
if ($$ == 0)
|
||||
GEN_ERROR("binary operator returned null!");
|
||||
delete $2;
|
||||
@ -2458,7 +2503,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
CHECK_FOR_ERROR
|
||||
Value* tmpVal2 = getVal(*$2, $5);
|
||||
CHECK_FOR_ERROR
|
||||
$$ = new SetCondInst($1, tmpVal1, tmpVal2);
|
||||
$$ = new SetCondInst($1.opcode, tmpVal1, tmpVal2);
|
||||
if ($$ == 0)
|
||||
GEN_ERROR("binary operator returned null!");
|
||||
delete $2;
|
||||
@ -2481,7 +2526,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
GEN_ERROR("Shift amount must be ubyte!");
|
||||
if (!$2->getType()->isInteger())
|
||||
GEN_ERROR("Shift constant expression requires integer operand!");
|
||||
$$ = new ShiftInst($1, $2, $4);
|
||||
$$ = new ShiftInst($1.opcode, $2, $4);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
| CAST ResolvedVal TO Types {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -226,6 +226,18 @@ protected:
|
||||
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.
|
||||
void ParseInstruction(
|
||||
std::vector<unsigned>& Args, ///< The arguments to be filled in
|
||||
@ -336,6 +348,13 @@ private:
|
||||
// unreachable instruction.
|
||||
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
|
||||
/// 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
|
||||
|
@ -40,7 +40,7 @@ using namespace llvm;
|
||||
/// so that the reader can distinguish which format of the bytecode file has
|
||||
/// been written.
|
||||
/// @brief The bytecode version number
|
||||
const unsigned BCVersionNum = 5;
|
||||
const unsigned BCVersionNum = 6;
|
||||
|
||||
static RegisterPass<WriteBytecodePass> X("emitbytecode", "Bytecode Writer");
|
||||
|
||||
|
@ -499,28 +499,35 @@ public:
|
||||
void visitInvoke(InvokeInst &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 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 visitMul(User &I) {
|
||||
visitBinary(I, ISD::MUL, ISD::FMUL, ISD::VMUL);
|
||||
}
|
||||
void visitDiv(User &I) {
|
||||
const Type *Ty = I.getType();
|
||||
visitBinary(I,
|
||||
Ty->isSigned() ? ISD::SDIV : ISD::UDIV, ISD::FDIV,
|
||||
Ty->isSigned() ? ISD::VSDIV : ISD::VUDIV);
|
||||
void visitMul(User &I) {
|
||||
if (I.getType()->isFloatingPoint())
|
||||
visitFPBinary(I, ISD::FMUL, ISD::VMUL);
|
||||
else
|
||||
visitIntBinary(I, ISD::MUL, ISD::VMUL);
|
||||
}
|
||||
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) {
|
||||
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 visitOr (User &I) { visitBinary(I, ISD::OR, 0, ISD::VOR); }
|
||||
void visitXor(User &I) { visitBinary(I, ISD::XOR, 0, ISD::VXOR); }
|
||||
void visitAnd(User &I) { visitIntBinary(I, ISD::AND, ISD::VAND); }
|
||||
void visitOr (User &I) { visitIntBinary(I, ISD::OR, ISD::VOR); }
|
||||
void visitXor(User &I) { visitIntBinary(I, ISD::XOR, ISD::VXOR); }
|
||||
void visitShl(User &I) { visitShift(I, ISD::SHL); }
|
||||
void visitShr(User &I) {
|
||||
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));
|
||||
return;
|
||||
}
|
||||
}
|
||||
visitBinary(I, ISD::SUB, ISD::FSUB, ISD::VSUB);
|
||||
visitFPBinary(I, ISD::FSUB, ISD::VSUB);
|
||||
} else
|
||||
visitIntBinary(I, ISD::SUB, ISD::VSUB);
|
||||
}
|
||||
|
||||
void SelectionDAGLowering::visitBinary(User &I, unsigned IntOp, unsigned FPOp,
|
||||
unsigned VecOp) {
|
||||
void
|
||||
SelectionDAGLowering::visitIntBinary(User &I, unsigned IntOp, unsigned VecOp) {
|
||||
const Type *Ty = I.getType();
|
||||
SDOperand Op1 = getValue(I.getOperand(0));
|
||||
SDOperand Op2 = getValue(I.getOperand(1));
|
||||
|
||||
if (Ty->isIntegral()) {
|
||||
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);
|
||||
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(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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,8 +42,12 @@ static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeRemInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeDivInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
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);
|
||||
static GenericValue executeAndInst(GenericValue Src1, GenericValue Src2,
|
||||
const Type *Ty);
|
||||
static GenericValue executeOrInst(GenericValue Src1, GenericValue Src2,
|
||||
@ -89,10 +93,18 @@ GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE,
|
||||
return executeMulInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::Div:
|
||||
return executeDivInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::SDiv:
|
||||
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),
|
||||
CE->getOperand(0)->getType());
|
||||
case Instruction::Rem:
|
||||
return executeRemInst(getOperandValue(CE->getOperand(0), SF),
|
||||
getOperandValue(CE->getOperand(1), SF),
|
||||
@ -242,18 +254,44 @@ static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2,
|
||||
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) {
|
||||
GenericValue Dest;
|
||||
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(/, Double);
|
||||
default:
|
||||
@ -504,7 +542,9 @@ void Interpreter::visitBinaryOperator(BinaryOperator &I) {
|
||||
case Instruction::Add: R = executeAddInst (Src1, Src2, Ty); break;
|
||||
case Instruction::Sub: R = executeSubInst (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::And: R = executeAndInst (Src1, Src2, Ty); break;
|
||||
case Instruction::Or: R = executeOrInst (Src1, Src2, Ty); break;
|
||||
|
@ -121,6 +121,8 @@ namespace {
|
||||
|
||||
void writeOperand(Value *Operand);
|
||||
void writeOperandInternal(Value *Operand);
|
||||
void writeOperandWithCast(Value* Operand, unsigned Opcode);
|
||||
bool writeInstructionCast(const Instruction &I);
|
||||
|
||||
private :
|
||||
void lowerIntrinsics(Function &F);
|
||||
@ -136,6 +138,8 @@ namespace {
|
||||
void printLoop(Loop *L);
|
||||
|
||||
void printConstant(Constant *CPV);
|
||||
void printConstantWithCast(Constant *CPV, unsigned Opcode);
|
||||
bool printConstExprCast(const ConstantExpr *CE);
|
||||
void printConstantArray(ConstantArray *CPA);
|
||||
void printConstantPacked(ConstantPacked *CP);
|
||||
|
||||
@ -586,7 +590,9 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
case Instruction::Add:
|
||||
case Instruction::Sub:
|
||||
case Instruction::Mul:
|
||||
case Instruction::Div:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::FDiv:
|
||||
case Instruction::Rem:
|
||||
case Instruction::And:
|
||||
case Instruction::Or:
|
||||
@ -600,12 +606,15 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
case Instruction::Shl:
|
||||
case Instruction::Shr:
|
||||
Out << '(';
|
||||
printConstant(CE->getOperand(0));
|
||||
bool NeedsClosingParens = printConstExprCast(CE);
|
||||
printConstantWithCast(CE->getOperand(0), CE->getOpcode());
|
||||
switch (CE->getOpcode()) {
|
||||
case Instruction::Add: Out << " + "; break;
|
||||
case Instruction::Sub: 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::And: Out << " & "; break;
|
||||
case Instruction::Or: Out << " | "; break;
|
||||
@ -620,7 +629,9 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
case Instruction::Shr: Out << " >> "; break;
|
||||
default: assert(0 && "Illegal opcode here!");
|
||||
}
|
||||
printConstant(CE->getOperand(1));
|
||||
printConstantWithCast(CE->getOperand(1), CE->getOpcode());
|
||||
if (NeedsClosingParens)
|
||||
Out << "))";
|
||||
Out << ')';
|
||||
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) {
|
||||
if (Instruction *I = dyn_cast<Instruction>(Operand))
|
||||
if (isInlinableInst(*I) && !isDirectAlloca(I)) {
|
||||
@ -833,6 +909,72 @@ void CWriter::writeOperand(Value *Operand) {
|
||||
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
|
||||
// directives to cater to specific compilers as need be.
|
||||
//
|
||||
@ -1642,13 +1784,23 @@ void CWriter::visitBinaryOperator(Instruction &I) {
|
||||
writeOperand(I.getOperand(1));
|
||||
Out << ")";
|
||||
} 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()) {
|
||||
case Instruction::Add: Out << " + "; break;
|
||||
case Instruction::Sub: 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::And: Out << " & "; break;
|
||||
case Instruction::Or: Out << " | "; break;
|
||||
@ -1664,7 +1816,9 @@ void CWriter::visitBinaryOperator(Instruction &I) {
|
||||
default: std::cerr << "Invalid operator type!" << I; abort();
|
||||
}
|
||||
|
||||
writeOperand(I.getOperand(1));
|
||||
writeOperandWithCast(I.getOperand(1), I.getOpcode());
|
||||
if (NeedsClosingParens)
|
||||
Out << "))";
|
||||
}
|
||||
|
||||
if (needsCast) {
|
||||
|
@ -121,6 +121,8 @@ namespace {
|
||||
|
||||
void writeOperand(Value *Operand);
|
||||
void writeOperandInternal(Value *Operand);
|
||||
void writeOperandWithCast(Value* Operand, unsigned Opcode);
|
||||
bool writeInstructionCast(const Instruction &I);
|
||||
|
||||
private :
|
||||
void lowerIntrinsics(Function &F);
|
||||
@ -136,6 +138,8 @@ namespace {
|
||||
void printLoop(Loop *L);
|
||||
|
||||
void printConstant(Constant *CPV);
|
||||
void printConstantWithCast(Constant *CPV, unsigned Opcode);
|
||||
bool printConstExprCast(const ConstantExpr *CE);
|
||||
void printConstantArray(ConstantArray *CPA);
|
||||
void printConstantPacked(ConstantPacked *CP);
|
||||
|
||||
@ -586,7 +590,9 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
case Instruction::Add:
|
||||
case Instruction::Sub:
|
||||
case Instruction::Mul:
|
||||
case Instruction::Div:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::FDiv:
|
||||
case Instruction::Rem:
|
||||
case Instruction::And:
|
||||
case Instruction::Or:
|
||||
@ -600,12 +606,15 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
case Instruction::Shl:
|
||||
case Instruction::Shr:
|
||||
Out << '(';
|
||||
printConstant(CE->getOperand(0));
|
||||
bool NeedsClosingParens = printConstExprCast(CE);
|
||||
printConstantWithCast(CE->getOperand(0), CE->getOpcode());
|
||||
switch (CE->getOpcode()) {
|
||||
case Instruction::Add: Out << " + "; break;
|
||||
case Instruction::Sub: 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::And: Out << " & "; break;
|
||||
case Instruction::Or: Out << " | "; break;
|
||||
@ -620,7 +629,9 @@ void CWriter::printConstant(Constant *CPV) {
|
||||
case Instruction::Shr: Out << " >> "; break;
|
||||
default: assert(0 && "Illegal opcode here!");
|
||||
}
|
||||
printConstant(CE->getOperand(1));
|
||||
printConstantWithCast(CE->getOperand(1), CE->getOpcode());
|
||||
if (NeedsClosingParens)
|
||||
Out << "))";
|
||||
Out << ')';
|
||||
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) {
|
||||
if (Instruction *I = dyn_cast<Instruction>(Operand))
|
||||
if (isInlinableInst(*I) && !isDirectAlloca(I)) {
|
||||
@ -833,6 +909,72 @@ void CWriter::writeOperand(Value *Operand) {
|
||||
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
|
||||
// directives to cater to specific compilers as need be.
|
||||
//
|
||||
@ -1642,13 +1784,23 @@ void CWriter::visitBinaryOperator(Instruction &I) {
|
||||
writeOperand(I.getOperand(1));
|
||||
Out << ")";
|
||||
} 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()) {
|
||||
case Instruction::Add: Out << " + "; break;
|
||||
case Instruction::Sub: 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::And: Out << " & "; break;
|
||||
case Instruction::Or: Out << " | "; break;
|
||||
@ -1664,7 +1816,9 @@ void CWriter::visitBinaryOperator(Instruction &I) {
|
||||
default: std::cerr << "Invalid operator type!" << I; abort();
|
||||
}
|
||||
|
||||
writeOperand(I.getOperand(1));
|
||||
writeOperandWithCast(I.getOperand(1), I.getOpcode());
|
||||
if (NeedsClosingParens)
|
||||
Out << "))";
|
||||
}
|
||||
|
||||
if (needsCast) {
|
||||
|
@ -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.
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
@ -1275,7 +1275,7 @@ public:
|
||||
return true;
|
||||
} else if (Op2V == -1.0) {
|
||||
// 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);
|
||||
ci->replaceAllUsesWith(div_inst);
|
||||
ci->eraseFromParent();
|
||||
|
@ -131,7 +131,11 @@ namespace {
|
||||
Instruction *visitAdd(BinaryOperator &I);
|
||||
Instruction *visitSub(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 *visitAnd(BinaryOperator &I);
|
||||
Instruction *visitOr (BinaryOperator &I);
|
||||
@ -1822,7 +1826,9 @@ FoundSExt:
|
||||
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);
|
||||
Value* Other = RHS;
|
||||
@ -1975,11 +1981,11 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
||||
}
|
||||
|
||||
// 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 (CSI->getType()->isSigned() && CSI->isNullValue())
|
||||
if (CSI->isNullValue())
|
||||
if (Constant *DivRHS = dyn_cast<Constant>(Op1I->getOperand(1)))
|
||||
return BinaryOperator::createDiv(Op1I->getOperand(0),
|
||||
return BinaryOperator::createSDiv(Op1I->getOperand(0),
|
||||
ConstantExpr::getNeg(DivRHS));
|
||||
|
||||
// X - X*C --> X * (1-C)
|
||||
@ -2156,64 +2162,28 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
||||
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);
|
||||
|
||||
if (isa<UndefValue>(Op0)) // undef / X -> 0
|
||||
// undef / X -> 0
|
||||
if (isa<UndefValue>(Op0))
|
||||
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
||||
|
||||
// X / undef -> undef
|
||||
if (isa<UndefValue>(Op1))
|
||||
return ReplaceInstUsesWith(I, Op1); // X / undef -> undef
|
||||
return ReplaceInstUsesWith(I, Op1);
|
||||
|
||||
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
|
||||
// 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
|
||||
// Handle cases involving: div X, (select Cond, Y, Z)
|
||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) {
|
||||
// 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
|
||||
// the select with false (if the cond value is in the same BB). If the
|
||||
// same basic block, then we replace the select with Y, and the condition
|
||||
// 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
|
||||
// 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 (ST->isNullValue()) {
|
||||
Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0));
|
||||
@ -2225,6 +2195,7 @@ Instruction *InstCombiner::visitDiv(BinaryOperator &I) {
|
||||
UpdateValueUsesWith(SI, SI->getOperand(2));
|
||||
return &I;
|
||||
}
|
||||
|
||||
// Likewise for: div X, (Cond ? Y : 0) -> div X, Y
|
||||
if (Constant *ST = dyn_cast<Constant>(SI->getOperand(2)))
|
||||
if (ST->isNullValue()) {
|
||||
@ -2237,28 +2208,42 @@ Instruction *InstCombiner::visitDiv(BinaryOperator &I) {
|
||||
UpdateValueUsesWith(SI, SI->getOperand(1));
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
/// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// 0 / X == 0, we don't need to preserve faults!
|
||||
@ -2266,48 +2251,137 @@ Instruction *InstCombiner::visitDiv(BinaryOperator &I) {
|
||||
if (LHS->equalsInt(0))
|
||||
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
||||
|
||||
if (I.getType()->isSigned()) {
|
||||
// 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.
|
||||
if (Instruction *RHSI = dyn_cast<Instruction>(I.getOperand(1))) {
|
||||
// Turn A / (C1 << N), where C1 is "1<<C2" into A >> (N+C2) [udiv only].
|
||||
if (RHSI->getOpcode() == Instruction::Shl &&
|
||||
isa<ConstantInt>(RHSI->getOperand(0)) &&
|
||||
RHSI->getOperand(0)->getType()->isUnsigned()) {
|
||||
uint64_t C1 = cast<ConstantInt>(RHSI->getOperand(0))->getZExtValue();
|
||||
if (isPowerOf2_64(C1)) {
|
||||
uint64_t C2 = Log2_64(C1);
|
||||
Value *Add = RHSI->getOperand(1);
|
||||
if (C2) {
|
||||
Constant *C2V = ConstantInt::get(Add->getType(), C2);
|
||||
Add = InsertNewInstBefore(BinaryOperator::createAdd(Add, C2V,
|
||||
"tmp"), I);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
|
||||
// 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 &&
|
||||
isa<ConstantInt>(RHSI->getOperand(0))) {
|
||||
uint64_t C1 = cast<ConstantInt>(RHSI->getOperand(0))->getZExtValue();
|
||||
if (isPowerOf2_64(C1)) {
|
||||
Value *N = RHSI->getOperand(1);
|
||||
const Type* NTy = N->getType();
|
||||
bool isSigned = NTy->isSigned();
|
||||
if (uint64_t C2 = Log2_64(C1)) {
|
||||
if (isSigned) {
|
||||
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;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
|
||||
return commonDivTransforms(I);
|
||||
}
|
||||
|
||||
/// GetFactor - If we can prove that the specified value is at least a multiple
|
||||
/// of some factor, return that factor.
|
||||
@ -2376,13 +2450,12 @@ Instruction *InstCombiner::visitRem(BinaryOperator &I) {
|
||||
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 *LHS = InsertCastBefore(Op0, NTy, 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);
|
||||
RHS = InsertCastBefore(Op1, NTy, I);
|
||||
Instruction *Rem = BinaryOperator::createRem(LHS, RHS, I.getName());
|
||||
InsertNewInstBefore(Rem, I);
|
||||
return new CastInst(Rem, I.getType());
|
||||
@ -3717,14 +3790,6 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
||||
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) {
|
||||
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))
|
||||
switch (LHSI->getOpcode()) {
|
||||
case Instruction::And:
|
||||
@ -4379,27 +4446,60 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
|
||||
}
|
||||
break;
|
||||
|
||||
case Instruction::Div:
|
||||
// Fold: (div X, C1) op C2 -> range check
|
||||
case Instruction::SDiv:
|
||||
case Instruction::UDiv:
|
||||
// Fold: setcc ([us]div X, C1), C2 -> range test
|
||||
// Fold this div into the comparison, producing a range check.
|
||||
// Determine, based on the divide type, what the range is being
|
||||
// checked. If there is an overflow on the low or high side, remember
|
||||
// it, otherwise compute the range [low, hi) bounding the new value.
|
||||
// See: InsertRangeTest above for the kinds of replacements possible.
|
||||
if (ConstantInt *DivRHS = dyn_cast<ConstantInt>(LHSI->getOperand(1))) {
|
||||
// Fold this div into the comparison, producing a range check.
|
||||
// Determine, based on the divide type, what the range is being
|
||||
// checked. If there is an overflow on the low or high side, remember
|
||||
// it, otherwise compute the range [low, hi) bounding the new value.
|
||||
bool LoOverflow = false, HiOverflow = 0;
|
||||
// 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 *Prod;
|
||||
bool ProdOV = MulWithOverflow(Prod, CI, DivRHS);
|
||||
// Compute Prod = CI * DivRHS. We are essentially solving an equation
|
||||
// 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();
|
||||
|
||||
if (DivRHS->isNullValue()) { // Don't hack on divide by zeros.
|
||||
} else if (LHSI->getType()->isUnsigned()) { // udiv
|
||||
if (DivRHS->isNullValue()) {
|
||||
// Don't hack on divide by zeros!
|
||||
} else if (DivOpCode == Instruction::UDiv) { // udiv
|
||||
LoBound = Prod;
|
||||
LoOverflow = ProdOV;
|
||||
HiOverflow = ProdOV || AddWithOverflow(HiBound, LoBound, DivRHS);
|
||||
} else if (isPositive(DivRHS)) { // Divisor is > 0.
|
||||
} else if (isPositive(DivRHS)) { // Divisor is > 0.
|
||||
if (CI->isNullValue()) { // (X / pos) op 0
|
||||
// Can't overflow.
|
||||
LoBound = cast<ConstantInt>(ConstantExpr::getNeg(SubOne(DivRHS)));
|
||||
@ -4415,12 +4515,12 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
|
||||
HiBound = Prod;
|
||||
HiOverflow = ProdOV;
|
||||
}
|
||||
} else { // Divisor is < 0.
|
||||
} else { // Divisor is < 0.
|
||||
if (CI->isNullValue()) { // (X / neg) op 0
|
||||
LoBound = AddOne(DivRHS);
|
||||
HiBound = cast<ConstantInt>(ConstantExpr::getNeg(DivRHS));
|
||||
if (HiBound == DivRHS)
|
||||
LoBound = 0; // - INTMIN = INTMIN
|
||||
LoBound = 0; // - INTMIN = INTMIN
|
||||
} else if (isPositive(CI)) { // (X / neg) op pos
|
||||
HiOverflow = LoOverflow = ProdOV;
|
||||
if (!LoOverflow)
|
||||
@ -5679,6 +5779,23 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) {
|
||||
ConstantInt::get(CI.getType(), 1));
|
||||
}
|
||||
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:
|
||||
// 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
|
||||
|
@ -788,7 +788,9 @@ void PredicateSimplifier::Forwards::visitBinaryOperator(BinaryOperator &BO) {
|
||||
Instruction::BinaryOps ops = BO.getOpcode();
|
||||
|
||||
switch (ops) {
|
||||
case Instruction::Div:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::FDiv:
|
||||
case Instruction::Rem: {
|
||||
Value *Divisor = BO.getOperand(1);
|
||||
KP.addNotEqual(Constant::getNullValue(Divisor->getType()), Divisor);
|
||||
|
@ -113,7 +113,9 @@ static bool isUnmovableInstruction(Instruction *I) {
|
||||
I->getOpcode() == Instruction::Malloc ||
|
||||
I->getOpcode() == Instruction::Invoke ||
|
||||
I->getOpcode() == Instruction::Call ||
|
||||
I->getOpcode() == Instruction::Div ||
|
||||
I->getOpcode() == Instruction::UDiv ||
|
||||
I->getOpcode() == Instruction::SDiv ||
|
||||
I->getOpcode() == Instruction::FDiv ||
|
||||
I->getOpcode() == Instruction::Rem)
|
||||
return true;
|
||||
return false;
|
||||
|
@ -40,7 +40,9 @@ namespace {
|
||||
virtual Constant *add(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 *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 *op_and(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 {
|
||||
return SubClassName::Mul((const ArgType *)V1, (const ArgType *)V2);
|
||||
}
|
||||
virtual Constant *div(const Constant *V1, const Constant *V2) const {
|
||||
return SubClassName::Div((const ArgType *)V1, (const ArgType *)V2);
|
||||
virtual Constant *udiv(const Constant *V1, const Constant *V2) const {
|
||||
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 {
|
||||
return SubClassName::Rem((const ArgType *)V1, (const ArgType *)V2);
|
||||
@ -178,16 +186,18 @@ class VISIBILITY_HIDDEN TemplateRules : public ConstRules {
|
||||
// Default "noop" implementations
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
static Constant *Add(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 *Div(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 *Or (const ArgType *V1, const ArgType *V2) { return 0; }
|
||||
static Constant *Xor(const ArgType *V1, const ArgType *V2) { return 0; }
|
||||
static Constant *Shl(const ArgType *V1, const ArgType *V2) { return 0; }
|
||||
static Constant *Shr(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 *Mul (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 *And (const ArgType *V1, const ArgType *V2) { return 0; }
|
||||
static Constant *Or (const ArgType *V1, const ArgType *V2) { return 0; }
|
||||
static Constant *Xor (const ArgType *V1, const ArgType *V2) { return 0; }
|
||||
static Constant *Shl (const ArgType *V1, const ArgType *V2) { return 0; }
|
||||
static Constant *Shr (const ArgType *V1, const ArgType *V2) { return 0; }
|
||||
static Constant *LessThan(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) {
|
||||
return EvalVectorOp(V1, V2, ConstantExpr::getMul);
|
||||
}
|
||||
static Constant *Div(const ConstantPacked *V1, const ConstantPacked *V2) {
|
||||
return EvalVectorOp(V1, V2, ConstantExpr::getDiv);
|
||||
static Constant *UDiv(const ConstantPacked *V1, const ConstantPacked *V2) {
|
||||
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) {
|
||||
return EvalVectorOp(V1, V2, ConstantExpr::getRem);
|
||||
@ -493,18 +509,25 @@ struct VISIBILITY_HIDDEN DirectIntRules
|
||||
DEF_CAST(Double, ConstantFP , double)
|
||||
#undef DEF_CAST
|
||||
|
||||
static Constant *Div(const ConstantInt *V1, const ConstantInt *V2) {
|
||||
if (V2->isNullValue()) return 0;
|
||||
if (V2->isAllOnesValue() && // MIN_INT / -1
|
||||
(BuiltinType)V1->getZExtValue() == -(BuiltinType)V1->getZExtValue())
|
||||
static Constant *UDiv(const ConstantInt *V1, const ConstantInt *V2) {
|
||||
if (V2->isNullValue())
|
||||
return 0;
|
||||
BuiltinType R =
|
||||
(BuiltinType)V1->getZExtValue() / (BuiltinType)V2->getZExtValue();
|
||||
BuiltinType R = (BuiltinType)(V1->getZExtValue() / V2->getZExtValue());
|
||||
return ConstantInt::get(*Ty, R);
|
||||
}
|
||||
|
||||
static Constant *Rem(const ConstantInt *V1,
|
||||
const ConstantInt *V2) {
|
||||
static Constant *SDiv(const ConstantInt *V1, 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->isAllOnesValue() && // MIN_INT / -1
|
||||
(BuiltinType)V1->getZExtValue() == -(BuiltinType)V1->getZExtValue())
|
||||
@ -615,7 +638,7 @@ struct VISIBILITY_HIDDEN DirectFPRules
|
||||
(BuiltinType)V2->getValue());
|
||||
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();
|
||||
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::Sub: C = ConstRules::get(V1, V2).sub(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::And: C = ConstRules::get(V1, V2).op_and(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::And:
|
||||
return Constant::getNullValue(V1->getType());
|
||||
case Instruction::Div:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::FDiv:
|
||||
case Instruction::Rem:
|
||||
if (!isa<UndefValue>(V2)) // undef/X -> 0
|
||||
return Constant::getNullValue(V1->getType());
|
||||
@ -1358,7 +1385,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
|
||||
if (CI->getZExtValue() == 1)
|
||||
return const_cast<Constant*>(V1); // X * 1 == X
|
||||
break;
|
||||
case Instruction::Div:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::SDiv:
|
||||
if (const ConstantInt *CI = dyn_cast<ConstantInt>(V2))
|
||||
if (CI->getZExtValue() == 1)
|
||||
return const_cast<Constant*>(V1); // X / 1 == X
|
||||
@ -1419,7 +1447,9 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
|
||||
case Instruction::Shl:
|
||||
case Instruction::Shr:
|
||||
case Instruction::Sub:
|
||||
case Instruction::Div:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::FDiv:
|
||||
case Instruction::Rem:
|
||||
default: // These instructions cannot be flopped around.
|
||||
break;
|
||||
|
@ -75,7 +75,9 @@ bool Constant::canTrap() const {
|
||||
switch (CE->getOpcode()) {
|
||||
default:
|
||||
return false;
|
||||
case Instruction::Div:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::FDiv:
|
||||
case Instruction::Rem:
|
||||
// Div and rem can trap if the RHS is not known to be non-zero.
|
||||
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) {
|
||||
return get(Instruction::Mul, C1, C2);
|
||||
}
|
||||
Constant *ConstantExpr::getDiv(Constant *C1, Constant *C2) {
|
||||
return get(Instruction::Div, C1, C2);
|
||||
Constant *ConstantExpr::getUDiv(Constant *C1, Constant *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) {
|
||||
return get(Instruction::Rem, C1, C2);
|
||||
@ -1437,13 +1445,27 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
|
||||
#ifndef NDEBUG
|
||||
switch (Opcode) {
|
||||
case Instruction::Add: case Instruction::Sub:
|
||||
case Instruction::Mul: case Instruction::Div:
|
||||
case Instruction::Mul:
|
||||
case Instruction::Rem:
|
||||
assert(C1->getType() == C2->getType() && "Op types should be identical!");
|
||||
assert((C1->getType()->isInteger() || C1->getType()->isFloatingPoint() ||
|
||||
isa<PackedType>(C1->getType())) &&
|
||||
"Tried to create an arithmetic operation on a non-arithmetic type!");
|
||||
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::Or:
|
||||
case Instruction::Xor:
|
||||
|
@ -94,7 +94,9 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
|
||||
case Add: return "add";
|
||||
case Sub: return "sub";
|
||||
case Mul: return "mul";
|
||||
case Div: return "div";
|
||||
case UDiv: return "udiv";
|
||||
case SDiv: return "sdiv";
|
||||
case FDiv: return "fdiv";
|
||||
case Rem: return "rem";
|
||||
|
||||
// Logical operators...
|
||||
@ -221,7 +223,9 @@ bool Instruction::isComparison(unsigned op) {
|
||||
///
|
||||
bool Instruction::isTrapping(unsigned op) {
|
||||
switch(op) {
|
||||
case Div:
|
||||
case UDiv:
|
||||
case SDiv:
|
||||
case FDiv:
|
||||
case Rem:
|
||||
case Load:
|
||||
case Store:
|
||||
|
@ -1022,7 +1022,7 @@ void BinaryOperator::init(BinaryOps iType)
|
||||
#ifndef NDEBUG
|
||||
switch (iType) {
|
||||
case Add: case Sub:
|
||||
case Mul: case Div:
|
||||
case Mul:
|
||||
case Rem:
|
||||
assert(getType() == LHS->getType() &&
|
||||
"Arithmetic operation should return same type as operands!");
|
||||
@ -1030,6 +1030,22 @@ void BinaryOperator::init(BinaryOps iType)
|
||||
isa<PackedType>(getType())) &&
|
||||
"Tried to create an arithmetic operation on a non-arithmetic type!");
|
||||
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 Xor:
|
||||
assert(getType() == LHS->getType() &&
|
||||
|
@ -1041,7 +1041,7 @@ StackerCompiler::handle_word( int tkn )
|
||||
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
|
||||
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
|
||||
BinaryOperator* divop =
|
||||
BinaryOperator::create( Instruction::Div, op1, op2);
|
||||
BinaryOperator::create( Instruction::SDiv, op1, op2);
|
||||
bb->getInstList().push_back( divop );
|
||||
push_value( bb, divop );
|
||||
break;
|
||||
@ -1072,7 +1072,7 @@ StackerCompiler::handle_word( int tkn )
|
||||
|
||||
// Divide by the third operand
|
||||
BinaryOperator* divop =
|
||||
BinaryOperator::create( Instruction::Div, multop, op3);
|
||||
BinaryOperator::create( Instruction::SDiv, multop, op3);
|
||||
bb->getInstList().push_back( divop );
|
||||
|
||||
// Push the result
|
||||
|
@ -57,13 +57,12 @@ bool %test9(ubyte %A) {
|
||||
|
||||
uint %test10(uint %X, bool %C) {
|
||||
%V = select bool %C, uint 64, uint 8
|
||||
%R = div uint %X, %V
|
||||
%R = udiv uint %X, %V
|
||||
ret uint %R
|
||||
}
|
||||
|
||||
uint %test10(uint %X, ubyte %B) {
|
||||
%Amt = shl uint 32, ubyte %B
|
||||
%V = div uint %X, %Amt
|
||||
ret uint %V
|
||||
int %test11(int %X, bool %C) {
|
||||
%A = select bool %C, int 1024, int 32
|
||||
%B = udiv int %X, %A
|
||||
ret int %B
|
||||
}
|
||||
|
||||
|
@ -773,7 +773,9 @@ void CppWriter::printConstant(const Constant *CV) {
|
||||
case Instruction::Add: Out << "getAdd"; break;
|
||||
case Instruction::Sub: Out << "getSub"; 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::And: Out << "getAnd"; 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::Sub:
|
||||
case Instruction::Mul:
|
||||
case Instruction::Div:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::FDiv:
|
||||
case Instruction::Rem:
|
||||
case Instruction::And:
|
||||
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::Sub: Out << "Instruction::Sub"; 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::And: Out << "Instruction::And"; break;
|
||||
case Instruction::Or: Out << "Instruction::Or"; break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user