mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-21 18:29:46 +00:00
Revert r164614 to appease the buildbots.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@164627 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
fe4a778f6e
commit
442ffc346f
@ -23,16 +23,6 @@ namespace llvm {
|
|||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
/// Generate code to calculate the remainder of two integers, replacing Rem
|
|
||||||
/// with the generated code. This currently generates code using the udiv
|
|
||||||
/// expansion, but future work includes generating more specialized code,
|
|
||||||
/// e.g. when more information about the operands are known. Currently only
|
|
||||||
/// implements 32bit scalar division (due to udiv's limitation), but future
|
|
||||||
/// work is removing this limitation.
|
|
||||||
///
|
|
||||||
/// @brief Replace Rem with generated code.
|
|
||||||
bool expandRemainder(BinaryOperator *Rem);
|
|
||||||
|
|
||||||
/// Generate code to divide two integers, replacing Div with the generated
|
/// Generate code to divide two integers, replacing Div with the generated
|
||||||
/// code. This currently generates code similarly to compiler-rt's
|
/// code. This currently generates code similarly to compiler-rt's
|
||||||
/// implementations, but future work includes generating more specialized code
|
/// implementations, but future work includes generating more specialized code
|
||||||
|
@ -23,69 +23,11 @@
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
/// Generate code to compute the remainder of two signed integers. Returns the
|
|
||||||
/// remainder, which will have the sign of the dividend. Builder's insert point
|
|
||||||
/// should be pointing where the caller wants code generated, e.g. at the srem
|
|
||||||
/// instruction. This will generate a urem in the process, and Builder's insert
|
|
||||||
/// point will be pointing at the uren (if present, i.e. not folded), ready to
|
|
||||||
/// be expanded if the user wishes
|
|
||||||
static Value *generateSignedRemainderCode(Value *Dividend, Value *Divisor,
|
|
||||||
IRBuilder<> &Builder) {
|
|
||||||
ConstantInt *ThirtyOne = Builder.getInt32(31);
|
|
||||||
|
|
||||||
// ; %dividend_sgn = ashr i32 %dividend, 31
|
|
||||||
// ; %divisor_sgn = ashr i32 %divisor, 31
|
|
||||||
// ; %dvd_xor = xor i32 %dividend, %dividend_sgn
|
|
||||||
// ; %dvs_xor = xor i32 %divisor, %divisor_sgn
|
|
||||||
// ; %u_dividend = sub i32 %dvd_xor, %dividend_sgn
|
|
||||||
// ; %u_divisor = sub i32 %dvs_xor, %divisor_sgn
|
|
||||||
// ; %urem = urem i32 %dividend, %divisor
|
|
||||||
// ; %xored = xor i32 %urem, %dividend_sgn
|
|
||||||
// ; %srem = sub i32 %xored, %dividend_sgn
|
|
||||||
Value *DividendSign = Builder.CreateAShr(Dividend, ThirtyOne);
|
|
||||||
Value *DivisorSign = Builder.CreateAShr(Divisor, ThirtyOne);
|
|
||||||
Value *DvdXor = Builder.CreateXor(Dividend, DividendSign);
|
|
||||||
Value *DvsXor = Builder.CreateXor(Divisor, DivisorSign);
|
|
||||||
Value *UDividend = Builder.CreateSub(DvdXor, DividendSign);
|
|
||||||
Value *UDivisor = Builder.CreateSub(DvsXor, DivisorSign);
|
|
||||||
Value *URem = Builder.CreateURem(UDividend, UDivisor);
|
|
||||||
Value *Xored = Builder.CreateXor(URem, DividendSign);
|
|
||||||
Value *SRem = Builder.CreateSub(Xored, DividendSign);
|
|
||||||
|
|
||||||
if (Instruction *URem = dyn_cast<Instruction>(URem))
|
|
||||||
Builder.SetInsertPoint(URem);
|
|
||||||
|
|
||||||
return SRem;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Generate code to compute the remainder of two unsigned integers. Returns the
|
|
||||||
/// remainder. Builder's insert point should be pointing where the caller wants
|
|
||||||
/// code generated, e.g. at the urem instruction. This will generate a udiv in
|
|
||||||
/// the process, and Builder's insert point will be pointing at the udiv (if
|
|
||||||
/// present, i.e. not folded), ready to be expanded if the user wishes
|
|
||||||
static Value *generatedUnsignedRemainderCode(Value *Dividend, Value *Divisor,
|
|
||||||
IRBuilder<> &Builder) {
|
|
||||||
// Remainder = Dividend - Quotient*Divisor
|
|
||||||
|
|
||||||
// ; %quotient = udiv i32 %dividend, %divisor
|
|
||||||
// ; %product = mul i32 %divisor, %quotient
|
|
||||||
// ; %remainder = sub i32 %dividend, %product
|
|
||||||
Value *Quotient = Builder.CreateUDiv(Dividend, Divisor);
|
|
||||||
Value *Product = Builder.CreateMul(Divisor, Quotient);
|
|
||||||
Value *Remainder = Builder.CreateSub(Dividend, Product);
|
|
||||||
|
|
||||||
if (Instruction *UDiv = dyn_cast<Instruction>(Quotient))
|
|
||||||
Builder.SetInsertPoint(UDiv);
|
|
||||||
|
|
||||||
return Remainder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate code to divide two signed integers. Returns the quotient, rounded
|
/// Generate code to divide two signed integers. Returns the quotient, rounded
|
||||||
/// towards 0. Builder's insert point should be pointing where the caller wants
|
/// towards 0. Builder's insert point should be pointing at the sdiv
|
||||||
/// code generated, e.g. at the sdiv instruction. This will generate a udiv in
|
/// instruction. This will generate a udiv in the process, and Builder's insert
|
||||||
/// the process, and Builder's insert point will be pointing at the udiv (if
|
/// point will be pointing at the udiv (if present, i.e. not folded), ready to
|
||||||
/// present, i.e. not folded), ready to be expanded if the user wishes.
|
/// be expanded if the user wishes.
|
||||||
static Value *generateSignedDivisionCode(Value *Dividend, Value *Divisor,
|
static Value *generateSignedDivisionCode(Value *Dividend, Value *Divisor,
|
||||||
IRBuilder<> &Builder) {
|
IRBuilder<> &Builder) {
|
||||||
// Implementation taken from compiler-rt's __divsi3
|
// Implementation taken from compiler-rt's __divsi3
|
||||||
@ -120,8 +62,8 @@ static Value *generateSignedDivisionCode(Value *Dividend, Value *Divisor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generates code to divide two unsigned scalar 32-bit integers. Returns the
|
/// Generates code to divide two unsigned scalar 32-bit integers. Returns the
|
||||||
/// quotient, rounded towards 0. Builder's insert point should be pointing where
|
/// quotient, rounded towards 0. Builder's insert point should be pointing at
|
||||||
/// the caller wants code generated, e.g. at the udiv instruction.
|
/// the udiv instruction.
|
||||||
static Value *generateUnsignedDivisionCode(Value *Dividend, Value *Divisor,
|
static Value *generateUnsignedDivisionCode(Value *Dividend, Value *Divisor,
|
||||||
IRBuilder<> &Builder) {
|
IRBuilder<> &Builder) {
|
||||||
// The basic algorithm can be found in the compiler-rt project's
|
// The basic algorithm can be found in the compiler-rt project's
|
||||||
@ -323,56 +265,6 @@ static Value *generateUnsignedDivisionCode(Value *Dividend, Value *Divisor,
|
|||||||
return Q_5;
|
return Q_5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate code to calculate the remainder of two integers, replacing Rem with
|
|
||||||
/// the generated code. This currently generates code using the udiv expansion,
|
|
||||||
/// but future work includes generating more specialized code, e.g. when more
|
|
||||||
/// information about the operands are known. Currently only implements 32bit
|
|
||||||
/// scalar division (due to udiv's limitation), but future work is removing this
|
|
||||||
/// limitation.
|
|
||||||
///
|
|
||||||
/// @brief Replace Rem with generated code.
|
|
||||||
bool llvm::expandRemainder(BinaryOperator *Rem) {
|
|
||||||
assert((Rem->getOpcode() == Instruction::SRem ||
|
|
||||||
Rem->getOpcode() == Instruction::URem) &&
|
|
||||||
"Trying to expand remainder from a non-remainder function");
|
|
||||||
|
|
||||||
IRBuilder<> Builder(Rem);
|
|
||||||
|
|
||||||
// First prepare the sign if it's a signed remainder
|
|
||||||
if (Rem->getOpcode() == Instruction::SRem) {
|
|
||||||
Value *Remainder = generateSignedRemainderCode(Rem->getOperand(0),
|
|
||||||
Rem->getOperand(1), Builder);
|
|
||||||
|
|
||||||
Rem->replaceAllUsesWith(Remainder);
|
|
||||||
Rem->dropAllReferences();
|
|
||||||
Rem->eraseFromParent();
|
|
||||||
|
|
||||||
// If we didn't actually generate a udiv instruction, we're done
|
|
||||||
BinaryOperator *BO = dyn_cast<BinaryOperator>(Builder.GetInsertPoint());
|
|
||||||
if (!BO || BO->getOpcode() != Instruction::URem)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
Rem = BO;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value *Remainder = generatedUnsignedRemainderCode(Rem->getOperand(0),
|
|
||||||
Rem->getOperand(1),
|
|
||||||
Builder);
|
|
||||||
|
|
||||||
Rem->replaceAllUsesWith(Remainder);
|
|
||||||
Rem->dropAllReferences();
|
|
||||||
Rem->eraseFromParent();
|
|
||||||
|
|
||||||
// Expand the udiv
|
|
||||||
if (BinaryOperator *UDiv = dyn_cast<BinaryOperator>(Builder.GetInsertPoint())) {
|
|
||||||
assert(UDiv->getOpcode() == Instruction::UDiv && "Non-udiv in expansion?");
|
|
||||||
expandDivision(UDiv);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Generate code to divide two integers, replacing Div with the generated
|
/// Generate code to divide two integers, replacing Div with the generated
|
||||||
/// code. This currently generates code similarly to compiler-rt's
|
/// code. This currently generates code similarly to compiler-rt's
|
||||||
/// implementations, but future work includes generating more specialized code
|
/// implementations, but future work includes generating more specialized code
|
||||||
@ -395,7 +287,7 @@ bool llvm::expandDivision(BinaryOperator *Div) {
|
|||||||
if (Div->getOpcode() == Instruction::SDiv) {
|
if (Div->getOpcode() == Instruction::SDiv) {
|
||||||
// Lower the code to unsigned division, and reset Div to point to the udiv.
|
// Lower the code to unsigned division, and reset Div to point to the udiv.
|
||||||
Value *Quotient = generateSignedDivisionCode(Div->getOperand(0),
|
Value *Quotient = generateSignedDivisionCode(Div->getOperand(0),
|
||||||
Div->getOperand(1), Builder);
|
Div->getOperand(1), Builder);
|
||||||
Div->replaceAllUsesWith(Quotient);
|
Div->replaceAllUsesWith(Quotient);
|
||||||
Div->dropAllReferences();
|
Div->dropAllReferences();
|
||||||
Div->eraseFromParent();
|
Div->eraseFromParent();
|
||||||
|
@ -51,101 +51,4 @@ TEST(IntegerDivision, SDiv) {
|
|||||||
Builder.SetInsertPoint(BB->end());
|
Builder.SetInsertPoint(BB->end());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(IntegerDivision, UDiv) {
|
|
||||||
LLVMContext &C(getGlobalContext());
|
|
||||||
Module M("test division", C);
|
|
||||||
IRBuilder<> Builder(C);
|
|
||||||
|
|
||||||
SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
|
|
||||||
Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
|
|
||||||
ArgTys, false),
|
|
||||||
GlobalValue::ExternalLinkage, "F", &M);
|
|
||||||
assert(F->getArgumentList().size() == 2);
|
|
||||||
|
|
||||||
BasicBlock *BB = BasicBlock::Create(C, "", F);
|
|
||||||
Builder.SetInsertPoint(BB);
|
|
||||||
|
|
||||||
Function::arg_iterator AI = F->arg_begin();
|
|
||||||
Value *A = AI++;
|
|
||||||
Value *B = AI++;
|
|
||||||
|
|
||||||
Value *Div = Builder.CreateUDiv(A, B);
|
|
||||||
EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv);
|
|
||||||
|
|
||||||
Value *Ret = Builder.CreateRet(Div);
|
|
||||||
|
|
||||||
expandDivision(cast<BinaryOperator>(Div));
|
|
||||||
EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
|
|
||||||
|
|
||||||
Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
|
|
||||||
EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI);
|
|
||||||
|
|
||||||
Builder.SetInsertPoint(BB->end());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TEST(IntegerDivision, SRem) {
|
|
||||||
LLVMContext &C(getGlobalContext());
|
|
||||||
Module M("test remainder", C);
|
|
||||||
IRBuilder<> Builder(C);
|
|
||||||
|
|
||||||
SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
|
|
||||||
Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
|
|
||||||
ArgTys, false),
|
|
||||||
GlobalValue::ExternalLinkage, "F", &M);
|
|
||||||
assert(F->getArgumentList().size() == 2);
|
|
||||||
|
|
||||||
BasicBlock *BB = BasicBlock::Create(C, "", F);
|
|
||||||
Builder.SetInsertPoint(BB);
|
|
||||||
|
|
||||||
Function::arg_iterator AI = F->arg_begin();
|
|
||||||
Value *A = AI++;
|
|
||||||
Value *B = AI++;
|
|
||||||
|
|
||||||
Value *Rem = Builder.CreateSRem(A, B);
|
|
||||||
EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem);
|
|
||||||
|
|
||||||
Value *Ret = Builder.CreateRet(Rem);
|
|
||||||
|
|
||||||
expandRemainder(cast<BinaryOperator>(Rem));
|
|
||||||
EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
|
|
||||||
|
|
||||||
Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
|
|
||||||
EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
|
|
||||||
|
|
||||||
Builder.SetInsertPoint(BB->end());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(IntegerDivision, URem) {
|
|
||||||
LLVMContext &C(getGlobalContext());
|
|
||||||
Module M("test remainder", C);
|
|
||||||
IRBuilder<> Builder(C);
|
|
||||||
|
|
||||||
SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
|
|
||||||
Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
|
|
||||||
ArgTys, false),
|
|
||||||
GlobalValue::ExternalLinkage, "F", &M);
|
|
||||||
assert(F->getArgumentList().size() == 2);
|
|
||||||
|
|
||||||
BasicBlock *BB = BasicBlock::Create(C, "", F);
|
|
||||||
Builder.SetInsertPoint(BB);
|
|
||||||
|
|
||||||
Function::arg_iterator AI = F->arg_begin();
|
|
||||||
Value *A = AI++;
|
|
||||||
Value *B = AI++;
|
|
||||||
|
|
||||||
Value *Rem = Builder.CreateURem(A, B);
|
|
||||||
EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem);
|
|
||||||
|
|
||||||
Value *Ret = Builder.CreateRet(Rem);
|
|
||||||
|
|
||||||
expandRemainder(cast<BinaryOperator>(Rem));
|
|
||||||
EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
|
|
||||||
|
|
||||||
Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
|
|
||||||
EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
|
|
||||||
|
|
||||||
Builder.SetInsertPoint(BB->end());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user