Skip to content

Commit 43a59be

Browse files
committed
[CVP] Expand bound udiv's, symmetrically with urem's
Symmetrical with the `urem` case, added in 66efb98. Simple case: https://alive2.llvm.org/ce/z/gRumLd / https://alive2.llvm.org/ce/z/rxEeC5 Second variant of precondition: https://alive2.llvm.org/ce/z/cAm9TD
1 parent 51da0dc commit 43a59be

File tree

2 files changed

+58
-36
lines changed

2 files changed

+58
-36
lines changed

llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ STATISTIC(NumSaturating,
9494
"Number of saturating arithmetics converted to normal arithmetics");
9595
STATISTIC(NumNonNull, "Number of function pointer arguments marked non-null");
9696
STATISTIC(NumMinMax, "Number of llvm.[us]{min,max} intrinsics removed");
97-
STATISTIC(NumURemExpanded, "Number of bound urem's expanded");
97+
STATISTIC(NumUDivURemsNarrowedExpanded,
98+
"Number of bound udiv's/urem's expanded");
9899

99100
namespace {
100101

@@ -752,19 +753,23 @@ static bool narrowSDivOrSRem(BinaryOperator *Instr, const ConstantRange &LCR,
752753
return true;
753754
}
754755

755-
static bool processURem(BinaryOperator *Instr, const ConstantRange &XCR,
756-
const ConstantRange &YCR) {
757-
assert(Instr->getOpcode() == Instruction::URem);
758-
assert(!Instr->getType()->isVectorTy());
756+
static bool expandUDivOrURem(BinaryOperator *Instr, const ConstantRange &XCR,
757+
const ConstantRange &YCR) {
758+
Type *Ty = Instr->getType();
759+
assert(Instr->getOpcode() == Instruction::UDiv ||
760+
Instr->getOpcode() == Instruction::URem);
761+
assert(!Ty->isVectorTy());
762+
bool IsRem = Instr->getOpcode() == Instruction::URem;
759763

760764
Value *X = Instr->getOperand(0);
761765
Value *Y = Instr->getOperand(1);
762766

767+
// X u/ Y -> 0 iff X u< Y
763768
// X u% Y -> X iff X u< Y
764769
if (XCR.icmp(ICmpInst::ICMP_ULT, YCR)) {
765-
Instr->replaceAllUsesWith(X);
770+
Instr->replaceAllUsesWith(IsRem ? X : Constant::getNullValue(Ty));
766771
Instr->eraseFromParent();
767-
++NumURemExpanded;
772+
++NumUDivURemsNarrowedExpanded;
768773
return true;
769774
}
770775

@@ -798,17 +803,24 @@ static bool processURem(BinaryOperator *Instr, const ConstantRange &XCR,
798803
return false;
799804

800805
IRBuilder<> B(Instr);
801-
// NOTE: this transformation introduces two uses of X,
802-
// but it may be undef so we must freeze it first.
803-
Value *FrozenX = B.CreateFreeze(X, X->getName() + ".frozen");
804-
auto *AdjX = B.CreateNUWSub(FrozenX, Y, Instr->getName() + ".urem");
805-
auto *Cmp =
806-
B.CreateICmp(ICmpInst::ICMP_ULT, FrozenX, Y, Instr->getName() + ".cmp");
807-
auto *ExpandedURem = B.CreateSelect(Cmp, FrozenX, AdjX);
808-
ExpandedURem->takeName(Instr);
809-
Instr->replaceAllUsesWith(ExpandedURem);
806+
Value *ExpandedOp;
807+
if (IsRem) {
808+
// NOTE: this transformation introduces two uses of X,
809+
// but it may be undef so we must freeze it first.
810+
Value *FrozenX = B.CreateFreeze(X, X->getName() + ".frozen");
811+
auto *AdjX = B.CreateNUWSub(FrozenX, Y, Instr->getName() + ".urem");
812+
auto *Cmp =
813+
B.CreateICmp(ICmpInst::ICMP_ULT, FrozenX, Y, Instr->getName() + ".cmp");
814+
ExpandedOp = B.CreateSelect(Cmp, FrozenX, AdjX);
815+
} else {
816+
auto *Cmp =
817+
B.CreateICmp(ICmpInst::ICMP_UGE, X, Y, Instr->getName() + ".cmp");
818+
ExpandedOp = B.CreateZExt(Cmp, Ty, Instr->getName() + ".udiv");
819+
}
820+
ExpandedOp->takeName(Instr);
821+
Instr->replaceAllUsesWith(ExpandedOp);
810822
Instr->eraseFromParent();
811-
++NumURemExpanded;
823+
++NumUDivURemsNarrowedExpanded;
812824
return true;
813825
}
814826

@@ -860,7 +872,7 @@ static bool processUDivOrURem(BinaryOperator *Instr, LazyValueInfo *LVI) {
860872

861873
ConstantRange XCR = LVI->getConstantRangeAtUse(Instr->getOperandUse(0));
862874
ConstantRange YCR = LVI->getConstantRangeAtUse(Instr->getOperandUse(1));
863-
if (Instr->getOpcode() == Instruction::URem && processURem(Instr, XCR, YCR))
875+
if (expandUDivOrURem(Instr, XCR, YCR))
864876
return true;
865877

866878
return narrowUDivOrURem(Instr, XCR, YCR);

llvm/test/Transforms/CorrelatedValuePropagation/udiv-expansion.ll

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ define i8 @constant.divisor.v3(i8 %x) {
99
; CHECK-LABEL: @constant.divisor.v3(
1010
; CHECK-NEXT: [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], 3
1111
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_X_UPPER]])
12-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], 3
1312
; CHECK-NEXT: ret i8 0
1413
;
1514
%cmp.x.upper = icmp ult i8 %x, 3
@@ -21,7 +20,8 @@ define i8 @constant.divisor.v4(i8 %x) {
2120
; CHECK-LABEL: @constant.divisor.v4(
2221
; CHECK-NEXT: [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], 4
2322
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_X_UPPER]])
24-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], 3
23+
; CHECK-NEXT: [[DIV_CMP:%.*]] = icmp uge i8 [[X]], 3
24+
; CHECK-NEXT: [[DIV:%.*]] = zext i1 [[DIV_CMP]] to i8
2525
; CHECK-NEXT: ret i8 [[DIV]]
2626
;
2727
%cmp.x.upper = icmp ult i8 %x, 4
@@ -32,7 +32,8 @@ define i8 @constant.divisor.v4(i8 %x) {
3232
define i8 @constant.divisor.x.range.v4(ptr %x.ptr) {
3333
; CHECK-LABEL: @constant.divisor.x.range.v4(
3434
; CHECK-NEXT: [[X:%.*]] = load i8, ptr [[X_PTR:%.*]], align 1, !range [[RNG0:![0-9]+]]
35-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], 3
35+
; CHECK-NEXT: [[DIV_CMP:%.*]] = icmp uge i8 [[X]], 3
36+
; CHECK-NEXT: [[DIV:%.*]] = zext i1 [[DIV_CMP]] to i8
3637
; CHECK-NEXT: ret i8 [[DIV]]
3738
;
3839
%x = load i8, ptr %x.ptr, !range !{ i8 0, i8 4 }
@@ -42,7 +43,8 @@ define i8 @constant.divisor.x.range.v4(ptr %x.ptr) {
4243
define i8 @constant.divisor.x.mask.v4(i8 %x) {
4344
; CHECK-LABEL: @constant.divisor.x.mask.v4(
4445
; CHECK-NEXT: [[X_MASKED:%.*]] = and i8 [[X:%.*]], 3
45-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X_MASKED]], 3
46+
; CHECK-NEXT: [[DIV_CMP:%.*]] = icmp uge i8 [[X_MASKED]], 3
47+
; CHECK-NEXT: [[DIV:%.*]] = zext i1 [[DIV_CMP]] to i8
4648
; CHECK-NEXT: ret i8 [[DIV]]
4749
;
4850
%x.masked = and i8 %x, 3
@@ -53,7 +55,8 @@ define i8 @constant.divisor.v5(i8 %x) {
5355
; CHECK-LABEL: @constant.divisor.v5(
5456
; CHECK-NEXT: [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], 5
5557
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_X_UPPER]])
56-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], 3
58+
; CHECK-NEXT: [[DIV_CMP:%.*]] = icmp uge i8 [[X]], 3
59+
; CHECK-NEXT: [[DIV:%.*]] = zext i1 [[DIV_CMP]] to i8
5760
; CHECK-NEXT: ret i8 [[DIV]]
5861
;
5962
%cmp.x.upper = icmp ult i8 %x, 5
@@ -65,7 +68,8 @@ define i8 @constant.divisor.v6(i8 %x) {
6568
; CHECK-LABEL: @constant.divisor.v6(
6669
; CHECK-NEXT: [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], 6
6770
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_X_UPPER]])
68-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], 3
71+
; CHECK-NEXT: [[DIV_CMP:%.*]] = icmp uge i8 [[X]], 3
72+
; CHECK-NEXT: [[DIV:%.*]] = zext i1 [[DIV_CMP]] to i8
6973
; CHECK-NEXT: ret i8 [[DIV]]
7074
;
7175
%cmp.x.upper = icmp ult i8 %x, 6
@@ -96,7 +100,6 @@ define i8 @variable.v3(i8 %x, i8 %y) {
96100
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_Y_LOWER]])
97101
; CHECK-NEXT: [[CMP_Y_UPPER:%.*]] = icmp ule i8 [[Y]], 4
98102
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_Y_UPPER]])
99-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], [[Y]]
100103
; CHECK-NEXT: ret i8 0
101104
;
102105
%cmp.x = icmp ult i8 %x, 3
@@ -116,7 +119,8 @@ define i8 @variable.v4(i8 %x, i8 %y) {
116119
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_Y_LOWER]])
117120
; CHECK-NEXT: [[CMP_Y_UPPER:%.*]] = icmp ule i8 [[Y]], 4
118121
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_Y_UPPER]])
119-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], [[Y]]
122+
; CHECK-NEXT: [[DIV_CMP:%.*]] = icmp uge i8 [[X]], [[Y]]
123+
; CHECK-NEXT: [[DIV:%.*]] = zext i1 [[DIV_CMP]] to i8
120124
; CHECK-NEXT: ret i8 [[DIV]]
121125
;
122126
%cmp.x = icmp ult i8 %x, 4
@@ -132,7 +136,8 @@ define i8 @variable.v4.range(ptr %x.ptr, ptr %y.ptr) {
132136
; CHECK-LABEL: @variable.v4.range(
133137
; CHECK-NEXT: [[X:%.*]] = load i8, ptr [[X_PTR:%.*]], align 1, !range [[RNG0]]
134138
; CHECK-NEXT: [[Y:%.*]] = load i8, ptr [[Y_PTR:%.*]], align 1, !range [[RNG1:![0-9]+]]
135-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], [[Y]]
139+
; CHECK-NEXT: [[DIV_CMP:%.*]] = icmp uge i8 [[X]], [[Y]]
140+
; CHECK-NEXT: [[DIV:%.*]] = zext i1 [[DIV_CMP]] to i8
136141
; CHECK-NEXT: ret i8 [[DIV]]
137142
;
138143
%x = load i8, ptr %x.ptr, !range !{ i8 0, i8 4 }
@@ -148,7 +153,8 @@ define i8 @variable.v5(i8 %x, i8 %y) {
148153
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_Y_LOWER]])
149154
; CHECK-NEXT: [[CMP_Y_UPPER:%.*]] = icmp ule i8 [[Y]], 4
150155
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_Y_UPPER]])
151-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], [[Y]]
156+
; CHECK-NEXT: [[DIV_CMP:%.*]] = icmp uge i8 [[X]], [[Y]]
157+
; CHECK-NEXT: [[DIV:%.*]] = zext i1 [[DIV_CMP]] to i8
152158
; CHECK-NEXT: ret i8 [[DIV]]
153159
;
154160
%cmp.x = icmp ult i8 %x, 5
@@ -168,7 +174,8 @@ define i8 @variable.v6(i8 %x, i8 %y) {
168174
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_Y_LOWER]])
169175
; CHECK-NEXT: [[CMP_Y_UPPER:%.*]] = icmp ule i8 [[Y]], 4
170176
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_Y_UPPER]])
171-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], [[Y]]
177+
; CHECK-NEXT: [[DIV_CMP:%.*]] = icmp uge i8 [[X]], [[Y]]
178+
; CHECK-NEXT: [[DIV:%.*]] = zext i1 [[DIV_CMP]] to i8
172179
; CHECK-NEXT: ret i8 [[DIV]]
173180
;
174181
%cmp.x = icmp ult i8 %x, 6
@@ -207,7 +214,6 @@ define i8 @large.divisor.v0(i8 %x) {
207214
; CHECK-LABEL: @large.divisor.v0(
208215
; CHECK-NEXT: [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], 127
209216
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_X_UPPER]])
210-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], 127
211217
; CHECK-NEXT: ret i8 0
212218
;
213219
%cmp.x.upper = icmp ult i8 %x, 127
@@ -219,7 +225,8 @@ define i8 @large.divisor.v1(i8 %x) {
219225
; CHECK-LABEL: @large.divisor.v1(
220226
; CHECK-NEXT: [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], -128
221227
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_X_UPPER]])
222-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], 127
228+
; CHECK-NEXT: [[DIV_CMP:%.*]] = icmp uge i8 [[X]], 127
229+
; CHECK-NEXT: [[DIV:%.*]] = zext i1 [[DIV_CMP]] to i8
223230
; CHECK-NEXT: ret i8 [[DIV]]
224231
;
225232
%cmp.x.upper = icmp ult i8 %x, 128
@@ -230,7 +237,8 @@ define i8 @large.divisor.v1(i8 %x) {
230237
define i8 @large.divisor.v1.range(ptr %x.ptr) {
231238
; CHECK-LABEL: @large.divisor.v1.range(
232239
; CHECK-NEXT: [[X:%.*]] = load i8, ptr [[X_PTR:%.*]], align 1, !range [[RNG2:![0-9]+]]
233-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], 127
240+
; CHECK-NEXT: [[DIV_CMP:%.*]] = icmp uge i8 [[X]], 127
241+
; CHECK-NEXT: [[DIV:%.*]] = zext i1 [[DIV_CMP]] to i8
234242
; CHECK-NEXT: ret i8 [[DIV]]
235243
;
236244
%x = load i8, ptr %x.ptr, !range !{ i8 0, i8 128 }
@@ -250,7 +258,6 @@ define i8 @large.divisor.with.overflow.v0(i8 %x) {
250258
; CHECK-LABEL: @large.divisor.with.overflow.v0(
251259
; CHECK-NEXT: [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], -128
252260
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_X_UPPER]])
253-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], -128
254261
; CHECK-NEXT: ret i8 0
255262
;
256263
%cmp.x.upper = icmp ult i8 %x, 128
@@ -262,7 +269,8 @@ define i8 @large.divisor.with.overflow.v1(i8 %x) {
262269
; CHECK-LABEL: @large.divisor.with.overflow.v1(
263270
; CHECK-NEXT: [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], -127
264271
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_X_UPPER]])
265-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], -128
272+
; CHECK-NEXT: [[DIV_CMP:%.*]] = icmp uge i8 [[X]], -128
273+
; CHECK-NEXT: [[DIV:%.*]] = zext i1 [[DIV_CMP]] to i8
266274
; CHECK-NEXT: ret i8 [[DIV]]
267275
;
268276
%cmp.x.upper = icmp ult i8 %x, 129
@@ -273,7 +281,8 @@ define i8 @large.divisor.with.overflow.v1(i8 %x) {
273281
define i8 @large.divisor.with.overflow.v1.range(ptr %x.ptr) {
274282
; CHECK-LABEL: @large.divisor.with.overflow.v1.range(
275283
; CHECK-NEXT: [[X:%.*]] = load i8, ptr [[X_PTR:%.*]], align 1, !range [[RNG3:![0-9]+]]
276-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X]], -128
284+
; CHECK-NEXT: [[DIV_CMP:%.*]] = icmp uge i8 [[X]], -128
285+
; CHECK-NEXT: [[DIV:%.*]] = zext i1 [[DIV_CMP]] to i8
277286
; CHECK-NEXT: ret i8 [[DIV]]
278287
;
279288
%x = load i8, ptr %x.ptr, !range !{ i8 0, i8 129 }
@@ -282,7 +291,8 @@ define i8 @large.divisor.with.overflow.v1.range(ptr %x.ptr) {
282291
}
283292
define i8 @large.divisor.with.overflow.v2.unbound.x(i8 %x) {
284293
; CHECK-LABEL: @large.divisor.with.overflow.v2.unbound.x(
285-
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[X:%.*]], -128
294+
; CHECK-NEXT: [[DIV_CMP:%.*]] = icmp uge i8 [[X:%.*]], -128
295+
; CHECK-NEXT: [[DIV:%.*]] = zext i1 [[DIV_CMP]] to i8
286296
; CHECK-NEXT: ret i8 [[DIV]]
287297
;
288298
%div = udiv i8 %x, 128

0 commit comments

Comments
 (0)