Skip to content

Commit 506150a

Browse files
committed
Expansions for u/srem, using the udiv expansion. More unit tests for udiv and u/srem.
llvm-svn: 164614
1 parent 165f0a2 commit 506150a

File tree

3 files changed

+222
-7
lines changed

3 files changed

+222
-7
lines changed

llvm/include/llvm/Transforms/Utils/IntegerDivision.h

+10
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ namespace llvm {
2323

2424
namespace llvm {
2525

26+
/// Generate code to calculate the remainder of two integers, replacing Rem
27+
/// with the generated code. This currently generates code using the udiv
28+
/// expansion, but future work includes generating more specialized code,
29+
/// e.g. when more information about the operands are known. Currently only
30+
/// implements 32bit scalar division (due to udiv's limitation), but future
31+
/// work is removing this limitation.
32+
///
33+
/// @brief Replace Rem with generated code.
34+
bool expandRemainder(BinaryOperator *Rem);
35+
2636
/// Generate code to divide two integers, replacing Div with the generated
2737
/// code. This currently generates code similarly to compiler-rt's
2838
/// implementations, but future work includes generating more specialized code

llvm/lib/Transforms/Utils/IntegerDivision.cpp

+115-7
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,69 @@
2323

2424
using namespace llvm;
2525

26+
/// Generate code to compute the remainder of two signed integers. Returns the
27+
/// remainder, which will have the sign of the dividend. Builder's insert point
28+
/// should be pointing where the caller wants code generated, e.g. at the srem
29+
/// instruction. This will generate a urem in the process, and Builder's insert
30+
/// point will be pointing at the uren (if present, i.e. not folded), ready to
31+
/// be expanded if the user wishes
32+
static Value *generateSignedRemainderCode(Value *Dividend, Value *Divisor,
33+
IRBuilder<> &Builder) {
34+
ConstantInt *ThirtyOne = Builder.getInt32(31);
35+
36+
// ; %dividend_sgn = ashr i32 %dividend, 31
37+
// ; %divisor_sgn = ashr i32 %divisor, 31
38+
// ; %dvd_xor = xor i32 %dividend, %dividend_sgn
39+
// ; %dvs_xor = xor i32 %divisor, %divisor_sgn
40+
// ; %u_dividend = sub i32 %dvd_xor, %dividend_sgn
41+
// ; %u_divisor = sub i32 %dvs_xor, %divisor_sgn
42+
// ; %urem = urem i32 %dividend, %divisor
43+
// ; %xored = xor i32 %urem, %dividend_sgn
44+
// ; %srem = sub i32 %xored, %dividend_sgn
45+
Value *DividendSign = Builder.CreateAShr(Dividend, ThirtyOne);
46+
Value *DivisorSign = Builder.CreateAShr(Divisor, ThirtyOne);
47+
Value *DvdXor = Builder.CreateXor(Dividend, DividendSign);
48+
Value *DvsXor = Builder.CreateXor(Divisor, DivisorSign);
49+
Value *UDividend = Builder.CreateSub(DvdXor, DividendSign);
50+
Value *UDivisor = Builder.CreateSub(DvsXor, DivisorSign);
51+
Value *URem = Builder.CreateURem(UDividend, UDivisor);
52+
Value *Xored = Builder.CreateXor(URem, DividendSign);
53+
Value *SRem = Builder.CreateSub(Xored, DividendSign);
54+
55+
if (Instruction *URem = dyn_cast<Instruction>(URem))
56+
Builder.SetInsertPoint(URem);
57+
58+
return SRem;
59+
}
60+
61+
62+
/// Generate code to compute the remainder of two unsigned integers. Returns the
63+
/// remainder. Builder's insert point should be pointing where the caller wants
64+
/// code generated, e.g. at the urem instruction. This will generate a udiv in
65+
/// the process, and Builder's insert point will be pointing at the udiv (if
66+
/// present, i.e. not folded), ready to be expanded if the user wishes
67+
static Value *generatedUnsignedRemainderCode(Value *Dividend, Value *Divisor,
68+
IRBuilder<> &Builder) {
69+
// Remainder = Dividend - Quotient*Divisor
70+
71+
// ; %quotient = udiv i32 %dividend, %divisor
72+
// ; %product = mul i32 %divisor, %quotient
73+
// ; %remainder = sub i32 %dividend, %product
74+
Value *Quotient = Builder.CreateUDiv(Dividend, Divisor);
75+
Value *Product = Builder.CreateMul(Divisor, Quotient);
76+
Value *Remainder = Builder.CreateSub(Dividend, Product);
77+
78+
if (Instruction *UDiv = dyn_cast<Instruction>(Quotient))
79+
Builder.SetInsertPoint(UDiv);
80+
81+
return Remainder;
82+
}
83+
2684
/// Generate code to divide two signed integers. Returns the quotient, rounded
27-
/// towards 0. Builder's insert point should be pointing at the sdiv
28-
/// instruction. This will generate a udiv in the process, and Builder's insert
29-
/// point will be pointing at the udiv (if present, i.e. not folded), ready to
30-
/// be expanded if the user wishes.
85+
/// towards 0. Builder's insert point should be pointing where the caller wants
86+
/// code generated, e.g. at the sdiv instruction. This will generate a udiv in
87+
/// the process, and Builder's insert point will be pointing at the udiv (if
88+
/// present, i.e. not folded), ready to be expanded if the user wishes.
3189
static Value *generateSignedDivisionCode(Value *Dividend, Value *Divisor,
3290
IRBuilder<> &Builder) {
3391
// Implementation taken from compiler-rt's __divsi3
@@ -62,8 +120,8 @@ static Value *generateSignedDivisionCode(Value *Dividend, Value *Divisor,
62120
}
63121

64122
/// Generates code to divide two unsigned scalar 32-bit integers. Returns the
65-
/// quotient, rounded towards 0. Builder's insert point should be pointing at
66-
/// the udiv instruction.
123+
/// quotient, rounded towards 0. Builder's insert point should be pointing where
124+
/// the caller wants code generated, e.g. at the udiv instruction.
67125
static Value *generateUnsignedDivisionCode(Value *Dividend, Value *Divisor,
68126
IRBuilder<> &Builder) {
69127
// The basic algorithm can be found in the compiler-rt project's
@@ -265,6 +323,56 @@ static Value *generateUnsignedDivisionCode(Value *Dividend, Value *Divisor,
265323
return Q_5;
266324
}
267325

326+
/// Generate code to calculate the remainder of two integers, replacing Rem with
327+
/// the generated code. This currently generates code using the udiv expansion,
328+
/// but future work includes generating more specialized code, e.g. when more
329+
/// information about the operands are known. Currently only implements 32bit
330+
/// scalar division (due to udiv's limitation), but future work is removing this
331+
/// limitation.
332+
///
333+
/// @brief Replace Rem with generated code.
334+
bool llvm::expandRemainder(BinaryOperator *Rem) {
335+
assert((Rem->getOpcode() == Instruction::SRem ||
336+
Rem->getOpcode() == Instruction::URem) &&
337+
"Trying to expand remainder from a non-remainder function");
338+
339+
IRBuilder<> Builder(Rem);
340+
341+
// First prepare the sign if it's a signed remainder
342+
if (Rem->getOpcode() == Instruction::SRem) {
343+
Value *Remainder = generateSignedRemainderCode(Rem->getOperand(0),
344+
Rem->getOperand(1), Builder);
345+
346+
Rem->replaceAllUsesWith(Remainder);
347+
Rem->dropAllReferences();
348+
Rem->eraseFromParent();
349+
350+
// If we didn't actually generate a udiv instruction, we're done
351+
BinaryOperator *BO = dyn_cast<BinaryOperator>(Builder.GetInsertPoint());
352+
if (!BO || BO->getOpcode() != Instruction::URem)
353+
return true;
354+
355+
Rem = BO;
356+
}
357+
358+
Value *Remainder = generatedUnsignedRemainderCode(Rem->getOperand(0),
359+
Rem->getOperand(1),
360+
Builder);
361+
362+
Rem->replaceAllUsesWith(Remainder);
363+
Rem->dropAllReferences();
364+
Rem->eraseFromParent();
365+
366+
// Expand the udiv
367+
if (BinaryOperator *UDiv = dyn_cast<BinaryOperator>(Builder.GetInsertPoint())) {
368+
assert(UDiv->getOpcode() == Instruction::UDiv && "Non-udiv in expansion?");
369+
expandDivision(UDiv);
370+
}
371+
372+
return true;
373+
}
374+
375+
268376
/// Generate code to divide two integers, replacing Div with the generated
269377
/// code. This currently generates code similarly to compiler-rt's
270378
/// implementations, but future work includes generating more specialized code
@@ -287,7 +395,7 @@ bool llvm::expandDivision(BinaryOperator *Div) {
287395
if (Div->getOpcode() == Instruction::SDiv) {
288396
// Lower the code to unsigned division, and reset Div to point to the udiv.
289397
Value *Quotient = generateSignedDivisionCode(Div->getOperand(0),
290-
Div->getOperand(1), Builder);
398+
Div->getOperand(1), Builder);
291399
Div->replaceAllUsesWith(Quotient);
292400
Div->dropAllReferences();
293401
Div->eraseFromParent();

llvm/unittests/Transforms/Utils/IntegerDivision.cpp

+97
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,101 @@ TEST(IntegerDivision, SDiv) {
5151
Builder.SetInsertPoint(BB->end());
5252
}
5353

54+
TEST(IntegerDivision, UDiv) {
55+
LLVMContext &C(getGlobalContext());
56+
Module M("test division", C);
57+
IRBuilder<> Builder(C);
58+
59+
SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
60+
Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
61+
ArgTys, false),
62+
GlobalValue::ExternalLinkage, "F", &M);
63+
assert(F->getArgumentList().size() == 2);
64+
65+
BasicBlock *BB = BasicBlock::Create(C, "", F);
66+
Builder.SetInsertPoint(BB);
67+
68+
Function::arg_iterator AI = F->arg_begin();
69+
Value *A = AI++;
70+
Value *B = AI++;
71+
72+
Value *Div = Builder.CreateUDiv(A, B);
73+
EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv);
74+
75+
Value *Ret = Builder.CreateRet(Div);
76+
77+
expandDivision(cast<BinaryOperator>(Div));
78+
EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
79+
80+
Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
81+
EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI);
82+
83+
Builder.SetInsertPoint(BB->end());
84+
}
85+
86+
87+
TEST(IntegerDivision, SRem) {
88+
LLVMContext &C(getGlobalContext());
89+
Module M("test remainder", C);
90+
IRBuilder<> Builder(C);
91+
92+
SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
93+
Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
94+
ArgTys, false),
95+
GlobalValue::ExternalLinkage, "F", &M);
96+
assert(F->getArgumentList().size() == 2);
97+
98+
BasicBlock *BB = BasicBlock::Create(C, "", F);
99+
Builder.SetInsertPoint(BB);
100+
101+
Function::arg_iterator AI = F->arg_begin();
102+
Value *A = AI++;
103+
Value *B = AI++;
104+
105+
Value *Rem = Builder.CreateSRem(A, B);
106+
EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem);
107+
108+
Value *Ret = Builder.CreateRet(Rem);
109+
110+
expandRemainder(cast<BinaryOperator>(Rem));
111+
EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
112+
113+
Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
114+
EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
115+
116+
Builder.SetInsertPoint(BB->end());
117+
}
118+
119+
TEST(IntegerDivision, URem) {
120+
LLVMContext &C(getGlobalContext());
121+
Module M("test remainder", C);
122+
IRBuilder<> Builder(C);
123+
124+
SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
125+
Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
126+
ArgTys, false),
127+
GlobalValue::ExternalLinkage, "F", &M);
128+
assert(F->getArgumentList().size() == 2);
129+
130+
BasicBlock *BB = BasicBlock::Create(C, "", F);
131+
Builder.SetInsertPoint(BB);
132+
133+
Function::arg_iterator AI = F->arg_begin();
134+
Value *A = AI++;
135+
Value *B = AI++;
136+
137+
Value *Rem = Builder.CreateURem(A, B);
138+
EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem);
139+
140+
Value *Ret = Builder.CreateRet(Rem);
141+
142+
expandRemainder(cast<BinaryOperator>(Rem));
143+
EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
144+
145+
Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
146+
EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
147+
148+
Builder.SetInsertPoint(BB->end());
149+
}
150+
54151
}

0 commit comments

Comments
 (0)