Skip to content

Commit fe79061

Browse files
committed
[LVI][CVP] Use block value when simplifying icmps
Add a flag to getPredicateAt() that allows making use of the block value. This allows us to take into account range information from the current block, rather than only information that is threaded over edges, making the icmp simplification in CVP a lot more powerful. I'm not changing getPredicateAt() to use the block value unconditionally to avoid any impact on the JumpThreading pass, which is somewhat picky about LVI query order. Most test changes here are just icmps that now get dropped (while previously only a result used in a return was replaced). The three tests in icmp.ll show some representative improvements. Some of the folds this enables have been covered by IPSCCP in the meantime, but LVI can reason about some cases which are hard to support in IPSCCP, such as in test_br_cmp_with_offset. The compile-time time cost of doing this is fairly minimal, with a ~0.05% CTMark regression for ReleaseThinLTO: https://llvm-compile-time-tracker.com/compare.php?from=709d03f8af4da4204849a70f01798e7cebba2e32&to=6236fd503761f43c99f4537121e057a01056f185&stat=instructions This is because the block values will typically already be queried and cached by other CVP optimizations anyway. Differential Revision: https://reviews.llvm.org/D69686
1 parent 50bd71e commit fe79061

File tree

6 files changed

+14
-49
lines changed

6 files changed

+14
-49
lines changed

llvm/include/llvm/Analysis/LazyValueInfo.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,11 @@ class LazyValueInfo {
7171
Instruction *CxtI = nullptr);
7272

7373
/// Determine whether the specified value comparison with a constant is known
74-
/// to be true or false at the specified instruction
75-
/// (from an assume intrinsic). Pred is a CmpInst predicate.
74+
/// to be true or false at the specified instruction.
75+
/// \p Pred is a CmpInst predicate. If \p UseBlockValue is true, the block
76+
/// value is also taken into account.
7677
Tristate getPredicateAt(unsigned Pred, Value *V, Constant *C,
77-
Instruction *CxtI);
78+
Instruction *CxtI, bool UseBlockValue = false);
7879

7980
/// Determine whether the specified value is known to be a constant at the
8081
/// specified instruction. Return null if not.

llvm/lib/Analysis/LazyValueInfo.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -1744,7 +1744,7 @@ LazyValueInfo::getPredicateOnEdge(unsigned Pred, Value *V, Constant *C,
17441744

17451745
LazyValueInfo::Tristate
17461746
LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C,
1747-
Instruction *CxtI) {
1747+
Instruction *CxtI, bool UseBlockValue) {
17481748
// Is or is not NonNull are common predicates being queried. If
17491749
// isKnownNonZero can tell us the result of the predicate, we can
17501750
// return it quickly. But this is only a fastpath, and falling
@@ -1758,7 +1758,10 @@ LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C,
17581758
else if (Pred == ICmpInst::ICMP_NE)
17591759
return LazyValueInfo::True;
17601760
}
1761-
ValueLatticeElement Result = getImpl(PImpl, AC, M).getValueAt(V, CxtI);
1761+
1762+
ValueLatticeElement Result = UseBlockValue
1763+
? getImpl(PImpl, AC, M).getValueInBlock(V, CxtI->getParent(), CxtI)
1764+
: getImpl(PImpl, AC, M).getValueAt(V, CxtI);
17621765
Tristate Ret = getPredicateResult(Pred, C, Result, DL, TLI);
17631766
if (Ret != Unknown)
17641767
return Ret;

llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp

+2-11
Original file line numberDiff line numberDiff line change
@@ -304,18 +304,9 @@ static bool processCmp(CmpInst *Cmp, LazyValueInfo *LVI) {
304304
if (!C)
305305
return false;
306306

307-
// As a policy choice, we choose not to waste compile time on anything where
308-
// the comparison is testing local values. While LVI can sometimes reason
309-
// about such cases, it's not its primary purpose. We do make sure to do
310-
// the block local query for uses from terminator instructions, but that's
311-
// handled in the code for each terminator. As an exception, we allow phi
312-
// nodes, for which LVI can thread the condition into predecessors.
313-
auto *I = dyn_cast<Instruction>(Op0);
314-
if (I && I->getParent() == Cmp->getParent() && !isa<PHINode>(I))
315-
return false;
316-
317307
LazyValueInfo::Tristate Result =
318-
LVI->getPredicateAt(Cmp->getPredicate(), Op0, C, Cmp);
308+
LVI->getPredicateAt(Cmp->getPredicate(), Op0, C, Cmp,
309+
/*UseBlockValue=*/true);
319310
if (Result == LazyValueInfo::Unknown)
320311
return false;
321312

llvm/test/Transforms/CorrelatedValuePropagation/basic.ll

-23
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,6 @@ declare nonnull i8* @return_nonnull()
295295
define i1 @call_attribute() {
296296
; CHECK-LABEL: @call_attribute(
297297
; CHECK-NEXT: [[A:%.*]] = call i8* @return_nonnull()
298-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8* [[A]], null
299298
; CHECK-NEXT: br label [[EXIT:%.*]]
300299
; CHECK: exit:
301300
; CHECK-NEXT: ret i1 false
@@ -319,7 +318,6 @@ define i1 @umin(i32 %a, i32 %b) {
319318
; CHECK: b_guard:
320319
; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ult i32 [[A]], [[B]]
321320
; CHECK-NEXT: [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
322-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[MIN]], 7
323321
; CHECK-NEXT: br label [[NEXT:%.*]]
324322
; CHECK: next:
325323
; CHECK-NEXT: ret i1 false
@@ -356,7 +354,6 @@ define i1 @smin(i32 %a, i32 %b) {
356354
; CHECK: b_guard:
357355
; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp sle i32 [[A]], [[B]]
358356
; CHECK-NEXT: [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
359-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[MIN]], 7
360357
; CHECK-NEXT: br label [[NEXT:%.*]]
361358
; CHECK: next:
362359
; CHECK-NEXT: ret i1 false
@@ -393,7 +390,6 @@ define i1 @smax(i32 %a, i32 %b) {
393390
; CHECK: b_guard:
394391
; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp sge i32 [[A]], [[B]]
395392
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
396-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[MAX]], 7
397393
; CHECK-NEXT: br label [[NEXT:%.*]]
398394
; CHECK: next:
399395
; CHECK-NEXT: ret i1 false
@@ -430,7 +426,6 @@ define i1 @umax(i32 %a, i32 %b) {
430426
; CHECK: b_guard:
431427
; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp uge i32 [[A]], [[B]]
432428
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
433-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[MAX]], 7
434429
; CHECK-NEXT: br label [[NEXT:%.*]]
435430
; CHECK: next:
436431
; CHECK-NEXT: ret i1 false
@@ -465,7 +460,6 @@ define i1 @clamp_low1(i32 %a) {
465460
; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5
466461
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], -1
467462
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[A]]
468-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 4
469463
; CHECK-NEXT: br label [[NEXT:%.*]]
470464
; CHECK: next:
471465
; CHECK-NEXT: ret i1 false
@@ -497,7 +491,6 @@ define i1 @clamp_low2(i32 %a) {
497491
; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5
498492
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], -1
499493
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 5
500-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 4
501494
; CHECK-NEXT: br label [[NEXT:%.*]]
502495
; CHECK: next:
503496
; CHECK-NEXT: ret i1 false
@@ -529,7 +522,6 @@ define i1 @clamp_high1(i32 %a) {
529522
; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5
530523
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1
531524
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[A]]
532-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 6
533525
; CHECK-NEXT: br label [[NEXT:%.*]]
534526
; CHECK: next:
535527
; CHECK-NEXT: ret i1 false
@@ -561,7 +553,6 @@ define i1 @clamp_high2(i32 %a) {
561553
; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5
562554
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1
563555
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 5
564-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 6
565556
; CHECK-NEXT: br label [[NEXT:%.*]]
566557
; CHECK: next:
567558
; CHECK-NEXT: ret i1 false
@@ -594,7 +585,6 @@ define i1 @clamp_high3(i32 %a) {
594585
; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5
595586
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 100
596587
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 5
597-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 105
598588
; CHECK-NEXT: br label [[NEXT:%.*]]
599589
; CHECK: next:
600590
; CHECK-NEXT: ret i1 false
@@ -821,7 +811,6 @@ define i1 @zext_unknown(i8 %a) {
821811
; CHECK-LABEL: @zext_unknown(
822812
; CHECK-NEXT: entry:
823813
; CHECK-NEXT: [[A32:%.*]] = zext i8 [[A:%.*]] to i32
824-
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A32]], 256
825814
; CHECK-NEXT: br label [[EXIT:%.*]]
826815
; CHECK: exit:
827816
; CHECK-NEXT: ret i1 true
@@ -839,7 +828,6 @@ define i1 @trunc_unknown(i32 %a) {
839828
; CHECK-NEXT: entry:
840829
; CHECK-NEXT: [[A8:%.*]] = trunc i32 [[A:%.*]] to i8
841830
; CHECK-NEXT: [[A32:%.*]] = sext i8 [[A8]] to i32
842-
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A32]], 128
843831
; CHECK-NEXT: br label [[EXIT:%.*]]
844832
; CHECK: exit:
845833
; CHECK-NEXT: ret i1 true
@@ -894,7 +882,6 @@ define i1 @and_unknown(i32 %a) {
894882
; CHECK-LABEL: @and_unknown(
895883
; CHECK-NEXT: entry:
896884
; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], 128
897-
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[AND]], 128
898885
; CHECK-NEXT: br label [[EXIT:%.*]]
899886
; CHECK: exit:
900887
; CHECK-NEXT: ret i1 true
@@ -911,7 +898,6 @@ define i1 @lshr_unknown(i32 %a) {
911898
; CHECK-LABEL: @lshr_unknown(
912899
; CHECK-NEXT: entry:
913900
; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[A:%.*]], 30
914-
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[AND]], 128
915901
; CHECK-NEXT: br label [[EXIT:%.*]]
916902
; CHECK: exit:
917903
; CHECK-NEXT: ret i1 true
@@ -928,7 +914,6 @@ define i1 @urem_unknown(i32 %a) {
928914
; CHECK-LABEL: @urem_unknown(
929915
; CHECK-NEXT: entry:
930916
; CHECK-NEXT: [[UREM:%.*]] = urem i32 [[A:%.*]], 30
931-
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[UREM]], 30
932917
; CHECK-NEXT: br label [[EXIT:%.*]]
933918
; CHECK: exit:
934919
; CHECK-NEXT: ret i1 true
@@ -945,8 +930,6 @@ define i1 @srem_unknown(i32 %a) {
945930
; CHECK-LABEL: @srem_unknown(
946931
; CHECK-NEXT: entry:
947932
; CHECK-NEXT: [[SREM:%.*]] = srem i32 [[A:%.*]], 30
948-
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[SREM]], 30
949-
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[SREM]], -30
950933
; CHECK-NEXT: br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]]
951934
; CHECK: exit1:
952935
; CHECK-NEXT: ret i1 true
@@ -968,8 +951,6 @@ define i1 @sdiv_unknown(i32 %a) {
968951
; CHECK-LABEL: @sdiv_unknown(
969952
; CHECK-NEXT: entry:
970953
; CHECK-NEXT: [[SREM:%.*]] = sdiv i32 [[A:%.*]], 123
971-
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[SREM]], 17459217
972-
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[SREM]], -17459217
973954
; CHECK-NEXT: br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]]
974955
; CHECK: exit1:
975956
; CHECK-NEXT: ret i1 true
@@ -991,7 +972,6 @@ define i1 @uadd_sat_unknown(i32 %a) {
991972
; CHECK-LABEL: @uadd_sat_unknown(
992973
; CHECK-NEXT: entry:
993974
; CHECK-NEXT: [[VAL:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[A:%.*]], i32 100)
994-
; CHECK-NEXT: [[CMP1:%.*]] = icmp uge i32 [[VAL]], 100
995975
; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[VAL]], 100
996976
; CHECK-NEXT: br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]]
997977
; CHECK: exit1:
@@ -1014,7 +994,6 @@ define i1 @usub_sat_unknown(i32 %a) {
1014994
; CHECK-LABEL: @usub_sat_unknown(
1015995
; CHECK-NEXT: entry:
1016996
; CHECK-NEXT: [[VAL:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 100)
1017-
; CHECK-NEXT: [[CMP1:%.*]] = icmp ule i32 [[VAL]], -101
1018997
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[VAL]], -101
1019998
; CHECK-NEXT: br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]]
1020999
; CHECK: exit1:
@@ -1037,7 +1016,6 @@ define i1 @sadd_sat_unknown(i32 %a) {
10371016
; CHECK-LABEL: @sadd_sat_unknown(
10381017
; CHECK-NEXT: entry:
10391018
; CHECK-NEXT: [[VAL:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[A:%.*]], i32 100)
1040-
; CHECK-NEXT: [[CMP1:%.*]] = icmp sge i32 [[VAL]], -2147483548
10411019
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[VAL]], -2147483548
10421020
; CHECK-NEXT: br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]]
10431021
; CHECK: exit1:
@@ -1060,7 +1038,6 @@ define i1 @ssub_sat_unknown(i32 %a) {
10601038
; CHECK-LABEL: @ssub_sat_unknown(
10611039
; CHECK-NEXT: entry:
10621040
; CHECK-NEXT: [[VAL:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[A:%.*]], i32 100)
1063-
; CHECK-NEXT: [[CMP1:%.*]] = icmp sle i32 [[VAL]], 2147483547
10641041
; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[VAL]], 2147483547
10651042
; CHECK-NEXT: br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]]
10661043
; CHECK: exit1:

llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll

+3-6
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,7 @@ define i1 @test12(i32 %x) {
381381
; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i64 [[ZEXT]], 7
382382
; CHECK-NEXT: [[SHR:%.*]] = lshr i64 [[MUL]], 32
383383
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[SHR]] to i32
384-
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TRUNC]], 7
385-
; CHECK-NEXT: ret i1 [[CMP]]
384+
; CHECK-NEXT: ret i1 true
386385
;
387386
%zext = zext i32 %x to i64
388387
%mul = mul nuw i64 %zext, 7
@@ -396,9 +395,8 @@ define i1 @test13(i8 %x, i64* %p) {
396395
; CHECK-LABEL: @test13(
397396
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[X:%.*]] to i64
398397
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i64 [[ZEXT]], 128
399-
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[ADD]], 384
400398
; CHECK-NEXT: store i64 [[ADD]], i64* [[P:%.*]], align 8
401-
; CHECK-NEXT: ret i1 [[CMP]]
399+
; CHECK-NEXT: ret i1 true
402400
;
403401
%zext = zext i8 %x to i64
404402
%add = add nuw nsw i64 %zext, 128
@@ -627,8 +625,7 @@ define i1 @test_br_cmp_with_offset(i64 %idx) {
627625
; CHECK-NEXT: br i1 [[CMP1]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
628626
; CHECK: if.true:
629627
; CHECK-NEXT: [[IDX_OFF2:%.*]] = add nsw i64 [[IDX]], -1
630-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[IDX_OFF2]], 10
631-
; CHECK-NEXT: ret i1 [[CMP2]]
628+
; CHECK-NEXT: ret i1 true
632629
; CHECK: if.false:
633630
; CHECK-NEXT: ret i1 undef
634631
;

llvm/test/Transforms/CorrelatedValuePropagation/range.ll

-4
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,6 @@ sw.default:
241241
define i1 @test8(i64* %p) {
242242
; CHECK-LABEL: @test8(
243243
; CHECK-NEXT: [[A:%.*]] = load i64, i64* [[P:%.*]], align 4, [[RNG0:!range !.*]]
244-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i64 [[A]], 0
245244
; CHECK-NEXT: ret i1 false
246245
;
247246
%a = load i64, i64* %p, !range !{i64 4, i64 255}
@@ -252,7 +251,6 @@ define i1 @test8(i64* %p) {
252251
define i1 @test9(i64* %p) {
253252
; CHECK-LABEL: @test9(
254253
; CHECK-NEXT: [[A:%.*]] = load i64, i64* [[P:%.*]], align 4, [[RNG1:!range !.*]]
255-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i64 [[A]], 0
256254
; CHECK-NEXT: ret i1 true
257255
;
258256
%a = load i64, i64* %p, !range !{i64 0, i64 1}
@@ -263,7 +261,6 @@ define i1 @test9(i64* %p) {
263261
define i1 @test10(i64* %p) {
264262
; CHECK-LABEL: @test10(
265263
; CHECK-NEXT: [[A:%.*]] = load i64, i64* [[P:%.*]], align 4, [[RNG2:!range !.*]]
266-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i64 [[A]], 0
267264
; CHECK-NEXT: ret i1 false
268265
;
269266
%a = load i64, i64* %p, !range !{i64 4, i64 8, i64 15, i64 20}
@@ -277,7 +274,6 @@ define i1 @test11() {
277274
; CHECK-LABEL: @test11(
278275
; CHECK-NEXT: [[POSITIVE:%.*]] = load i32, i32* @g, align 4, [[RNG3:!range !.*]]
279276
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[POSITIVE]], 1
280-
; CHECK-NEXT: [[TEST:%.*]] = icmp sgt i32 [[ADD]], 0
281277
; CHECK-NEXT: br label [[NEXT:%.*]]
282278
; CHECK: next:
283279
; CHECK-NEXT: ret i1 true

0 commit comments

Comments
 (0)