mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Enhance integer division emulation support to handle types smaller than 32 bits,
enhancement done the trivial way; by extending inputs and truncating outputs which is addequate for targets with little or no support for integer arithmetic on integer types less than 32 bits. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@176139 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
bdc98d3510
commit
b3201c5cf1
@ -43,6 +43,20 @@ namespace llvm {
|
|||||||
/// @brief Replace Div with generated code.
|
/// @brief Replace Div with generated code.
|
||||||
bool expandDivision(BinaryOperator* Div);
|
bool expandDivision(BinaryOperator* Div);
|
||||||
|
|
||||||
|
/// Generate code to calculate the remainder of two integers, replacing Rem
|
||||||
|
/// with the generated code. Uses the above 32bit routine, therefore adequate
|
||||||
|
/// for targets with little or no support for less than 32 bit arithmetic.
|
||||||
|
///
|
||||||
|
/// @brief Replace Rem with generated code.
|
||||||
|
bool expandRemainderUpTo32Bits(BinaryOperator *Rem);
|
||||||
|
|
||||||
|
/// Generate code to divide two integers, replacing Div with the generated
|
||||||
|
/// code. Uses the above 32bit routine, therefore adequate for targets with
|
||||||
|
/// little or no support for less than 32 bit arithmetic.
|
||||||
|
///
|
||||||
|
/// @brief Replace Rem with generated code.
|
||||||
|
bool expandDivisionUpTo32Bits(BinaryOperator *Div);
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -418,3 +418,107 @@ bool llvm::expandDivision(BinaryOperator *Div) {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate code to compute the remainder of two integers of bitwidth up to
|
||||||
|
/// 32 bits. Uses the above routines and extends the inputs/truncates the
|
||||||
|
/// outputs to operate in 32 bits; that is, these routines are good for targets
|
||||||
|
/// that have no or very little suppport for smaller than 32 bit integer
|
||||||
|
/// arithmetic.
|
||||||
|
///
|
||||||
|
/// @brief Replace Rem with emulation code.
|
||||||
|
bool llvm::expandRemainderUpTo32Bits(BinaryOperator *Rem) {
|
||||||
|
assert((Rem->getOpcode() == Instruction::SRem ||
|
||||||
|
Rem->getOpcode() == Instruction::URem) &&
|
||||||
|
"Trying to expand remainder from a non-remainder function");
|
||||||
|
|
||||||
|
Type *RemTy = Rem->getType();
|
||||||
|
if (RemTy->isVectorTy())
|
||||||
|
llvm_unreachable("Div over vectors not supported");
|
||||||
|
|
||||||
|
unsigned RemTyBitWidth = RemTy->getIntegerBitWidth();
|
||||||
|
|
||||||
|
if (RemTyBitWidth > 32)
|
||||||
|
llvm_unreachable("Div of bitwidth greater than 32 not supported");
|
||||||
|
|
||||||
|
if (RemTyBitWidth == 32)
|
||||||
|
return expandRemainder(Rem);
|
||||||
|
|
||||||
|
// If bitwidth smaller than 32 extend inputs, truncate output and proceed
|
||||||
|
// with 32 bit division.
|
||||||
|
IRBuilder<> Builder(Rem);
|
||||||
|
|
||||||
|
Value *ExtDividend;
|
||||||
|
Value *ExtDivisor;
|
||||||
|
Value *ExtRem;
|
||||||
|
Value *Trunc;
|
||||||
|
Type *Int32Ty = Builder.getInt32Ty();
|
||||||
|
|
||||||
|
if (Rem->getOpcode() == Instruction::SRem) {
|
||||||
|
ExtDividend = Builder.CreateSExt(Rem->getOperand(0), Int32Ty);
|
||||||
|
ExtDivisor = Builder.CreateSExt(Rem->getOperand(1), Int32Ty);
|
||||||
|
ExtRem = Builder.CreateSRem(ExtDividend, ExtDivisor);
|
||||||
|
} else {
|
||||||
|
ExtDividend = Builder.CreateZExt(Rem->getOperand(0), Int32Ty);
|
||||||
|
ExtDivisor = Builder.CreateZExt(Rem->getOperand(1), Int32Ty);
|
||||||
|
ExtRem = Builder.CreateURem(ExtDividend, ExtDivisor);
|
||||||
|
}
|
||||||
|
Trunc = Builder.CreateTrunc(ExtRem, RemTy);
|
||||||
|
|
||||||
|
Rem->replaceAllUsesWith(Trunc);
|
||||||
|
Rem->dropAllReferences();
|
||||||
|
Rem->eraseFromParent();
|
||||||
|
|
||||||
|
return expandRemainder(cast<BinaryOperator>(ExtRem));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Generate code to divide two integers of bitwidth up to 32 bits. Uses the
|
||||||
|
/// above routines and extends the inputs/truncates the outputs to operate
|
||||||
|
/// in 32 bits; that is, these routines are good for targets that have no
|
||||||
|
/// or very little support for smaller than 32 bit integer arithmetic.
|
||||||
|
///
|
||||||
|
/// @brief Replace Div with emulation code.
|
||||||
|
bool llvm::expandDivisionUpTo32Bits(BinaryOperator *Div) {
|
||||||
|
assert((Div->getOpcode() == Instruction::SDiv ||
|
||||||
|
Div->getOpcode() == Instruction::UDiv) &&
|
||||||
|
"Trying to expand division from a non-division function");
|
||||||
|
|
||||||
|
Type *DivTy = Div->getType();
|
||||||
|
if (DivTy->isVectorTy())
|
||||||
|
llvm_unreachable("Div over vectors not supported");
|
||||||
|
|
||||||
|
unsigned DivTyBitWidth = DivTy->getIntegerBitWidth();
|
||||||
|
|
||||||
|
if (DivTyBitWidth > 32)
|
||||||
|
llvm_unreachable("Div of bitwidth greater than 32 not supported");
|
||||||
|
|
||||||
|
if (DivTyBitWidth == 32)
|
||||||
|
return expandDivision(Div);
|
||||||
|
|
||||||
|
// If bitwidth smaller than 32 extend inputs, truncate output and proceed
|
||||||
|
// with 32 bit division.
|
||||||
|
IRBuilder<> Builder(Div);
|
||||||
|
|
||||||
|
Value *ExtDividend;
|
||||||
|
Value *ExtDivisor;
|
||||||
|
Value *ExtDiv;
|
||||||
|
Value *Trunc;
|
||||||
|
Type *Int32Ty = Builder.getInt32Ty();
|
||||||
|
|
||||||
|
if (Div->getOpcode() == Instruction::SDiv) {
|
||||||
|
ExtDividend = Builder.CreateSExt(Div->getOperand(0), Int32Ty);
|
||||||
|
ExtDivisor = Builder.CreateSExt(Div->getOperand(1), Int32Ty);
|
||||||
|
ExtDiv = Builder.CreateSDiv(ExtDividend, ExtDivisor);
|
||||||
|
} else {
|
||||||
|
ExtDividend = Builder.CreateZExt(Div->getOperand(0), Int32Ty);
|
||||||
|
ExtDivisor = Builder.CreateZExt(Div->getOperand(1), Int32Ty);
|
||||||
|
ExtDiv = Builder.CreateUDiv(ExtDividend, ExtDivisor);
|
||||||
|
}
|
||||||
|
Trunc = Builder.CreateTrunc(ExtDiv, DivTy);
|
||||||
|
|
||||||
|
Div->replaceAllUsesWith(Trunc);
|
||||||
|
Div->dropAllReferences();
|
||||||
|
Div->eraseFromParent();
|
||||||
|
|
||||||
|
return expandDivision(cast<BinaryOperator>(ExtDiv));
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user