Skip to content

Commit 2d5820c

Browse files
committed
[CVP] Remove a masking operation if range information implies it's a noop
This is really a known bits style transformation, but known bits isn't context sensitive. The particular case which comes up happens to involve a range which allows range based reasoning to eliminate the mask pattern, so handle that case specifically in CVP. InstCombine likes to generate the mask-by-low-bits pattern when widening an arithmetic expression which includes a zext in the middle. Differential Revision: https://reviews.llvm.org/D68811 llvm-svn: 374506
1 parent 32097c2 commit 2d5820c

File tree

4 files changed

+155
-3
lines changed

4 files changed

+155
-3
lines changed

llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ STATISTIC(NumUDivs, "Number of udivs whose width was decreased");
6363
STATISTIC(NumAShrs, "Number of ashr converted to lshr");
6464
STATISTIC(NumSRems, "Number of srem converted to urem");
6565
STATISTIC(NumSExt, "Number of sext converted to zext");
66+
STATISTIC(NumAnd, "Number of ands removed");
6667
STATISTIC(NumOverflows, "Number of overflow checks removed");
6768
STATISTIC(NumSaturating,
6869
"Number of saturating arithmetics converted to normal arithmetics");
@@ -700,6 +701,29 @@ static bool processBinOp(BinaryOperator *BinOp, LazyValueInfo *LVI) {
700701
return Changed;
701702
}
702703

704+
static bool processAnd(BinaryOperator *BinOp, LazyValueInfo *LVI) {
705+
if (BinOp->getType()->isVectorTy())
706+
return false;
707+
708+
// Pattern match (and lhs, C) where C includes a superset of bits which might
709+
// be set in lhs. This is a common truncation idiom created by instcombine.
710+
BasicBlock *BB = BinOp->getParent();
711+
Value *LHS = BinOp->getOperand(0);
712+
ConstantInt *RHS = dyn_cast<ConstantInt>(BinOp->getOperand(1));
713+
if (!RHS || !RHS->getValue().isMask())
714+
return false;
715+
716+
ConstantRange LRange = LVI->getConstantRange(LHS, BB, BinOp);
717+
if (!LRange.getUnsignedMax().ule(RHS->getValue()))
718+
return false;
719+
720+
BinOp->replaceAllUsesWith(LHS);
721+
BinOp->eraseFromParent();
722+
NumAnd++;
723+
return true;
724+
}
725+
726+
703727
static Constant *getConstantAt(Value *V, Instruction *At, LazyValueInfo *LVI) {
704728
if (Constant *C = LVI->getConstant(V, At->getParent(), At))
705729
return C;
@@ -774,6 +798,9 @@ static bool runImpl(Function &F, LazyValueInfo *LVI, DominatorTree *DT,
774798
case Instruction::Sub:
775799
BBChanged |= processBinOp(cast<BinaryOperator>(II), LVI);
776800
break;
801+
case Instruction::And:
802+
BBChanged |= processAnd(cast<BinaryOperator>(II), LVI);
803+
break;
777804
}
778805
}
779806

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt < %s -correlated-propagation -S | FileCheck %s
3+
4+
define i32 @test(i32 %a) {
5+
; CHECK-LABEL: @test(
6+
; CHECK-NEXT: entry:
7+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 128
8+
; CHECK-NEXT: br i1 [[CMP]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
9+
; CHECK: continue:
10+
; CHECK-NEXT: ret i32 [[A]]
11+
; CHECK: exit:
12+
; CHECK-NEXT: ret i32 -1
13+
;
14+
entry:
15+
%cmp = icmp ult i32 %a, 128
16+
br i1 %cmp, label %continue, label %exit
17+
continue:
18+
%and = and i32 %a, 255
19+
ret i32 %and
20+
exit:
21+
ret i32 -1
22+
}
23+
24+
define i32 @test2(i32 %a) {
25+
; CHECK-LABEL: @test2(
26+
; CHECK-NEXT: entry:
27+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 256
28+
; CHECK-NEXT: br i1 [[CMP]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
29+
; CHECK: continue:
30+
; CHECK-NEXT: ret i32 [[A]]
31+
; CHECK: exit:
32+
; CHECK-NEXT: ret i32 -1
33+
;
34+
entry:
35+
%cmp = icmp ult i32 %a, 256
36+
br i1 %cmp, label %continue, label %exit
37+
continue:
38+
%and = and i32 %a, 255
39+
ret i32 %and
40+
exit:
41+
ret i32 -1
42+
}
43+
44+
define i32 @test3(i32 %a) {
45+
; CHECK-LABEL: @test3(
46+
; CHECK-NEXT: entry:
47+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 256
48+
; CHECK-NEXT: br i1 [[CMP]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
49+
; CHECK: continue:
50+
; CHECK-NEXT: ret i32 [[A]]
51+
; CHECK: exit:
52+
; CHECK-NEXT: ret i32 -1
53+
;
54+
entry:
55+
%cmp = icmp ult i32 %a, 256
56+
br i1 %cmp, label %continue, label %exit
57+
continue:
58+
%and = and i32 %a, 1023
59+
ret i32 %and
60+
exit:
61+
ret i32 -1
62+
}
63+
64+
65+
define i32 @neg1(i32 %a) {
66+
; CHECK-LABEL: @neg1(
67+
; CHECK-NEXT: entry:
68+
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[A:%.*]], 256
69+
; CHECK-NEXT: br i1 [[CMP]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
70+
; CHECK: continue:
71+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[A]], 255
72+
; CHECK-NEXT: ret i32 [[AND]]
73+
; CHECK: exit:
74+
; CHECK-NEXT: ret i32 -1
75+
;
76+
entry:
77+
%cmp = icmp ule i32 %a, 256
78+
br i1 %cmp, label %continue, label %exit
79+
continue:
80+
%and = and i32 %a, 255
81+
ret i32 %and
82+
exit:
83+
ret i32 -1
84+
}
85+
86+
define i32 @neg2(i32 %a) {
87+
; CHECK-LABEL: @neg2(
88+
; CHECK-NEXT: entry:
89+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 513
90+
; CHECK-NEXT: br i1 [[CMP]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
91+
; CHECK: continue:
92+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[A]], 255
93+
; CHECK-NEXT: ret i32 [[AND]]
94+
; CHECK: exit:
95+
; CHECK-NEXT: ret i32 -1
96+
;
97+
entry:
98+
%cmp = icmp ult i32 %a, 513
99+
br i1 %cmp, label %continue, label %exit
100+
continue:
101+
%and = and i32 %a, 255
102+
ret i32 %and
103+
exit:
104+
ret i32 -1
105+
}
106+
107+
define i32 @neg3(i32 %a) {
108+
; CHECK-LABEL: @neg3(
109+
; CHECK-NEXT: entry:
110+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 256
111+
; CHECK-NEXT: br i1 [[CMP]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
112+
; CHECK: continue:
113+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[A]], 254
114+
; CHECK-NEXT: ret i32 [[AND]]
115+
; CHECK: exit:
116+
; CHECK-NEXT: ret i32 -1
117+
;
118+
entry:
119+
%cmp = icmp ult i32 %a, 256
120+
br i1 %cmp, label %continue, label %exit
121+
continue:
122+
%and = and i32 %a, 254
123+
ret i32 %and
124+
exit:
125+
ret i32 -1
126+
}
127+

llvm/test/Transforms/CorrelatedValuePropagation/overflows.ll

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,6 @@ define i1 @smul_and_cmp(i32 %x, i32 %y) #0 {
10231023
; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
10241024
; CHECK-NEXT: br label [[CONT3:%.*]]
10251025
; CHECK: cont3:
1026-
; CHECK-NEXT: [[CMP5:%.*]] = and i1 true, true
10271026
; CHECK-NEXT: br label [[OUT]]
10281027
; CHECK: out:
10291028
; CHECK-NEXT: ret i1 true

llvm/test/Transforms/CorrelatedValuePropagation/range.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -745,10 +745,9 @@ target93:
745745
define i1 @test17_i1(i1 %a) {
746746
; CHECK-LABEL: @test17_i1(
747747
; CHECK-NEXT: entry:
748-
; CHECK-NEXT: [[C:%.*]] = and i1 [[A:%.*]], true
749748
; CHECK-NEXT: br label [[DISPATCH:%.*]]
750749
; CHECK: dispatch:
751-
; CHECK-NEXT: br i1 [[A]], label [[TRUE:%.*]], label [[DISPATCH]]
750+
; CHECK-NEXT: br i1 [[A:%.*]], label [[TRUE:%.*]], label [[DISPATCH]]
752751
; CHECK: true:
753752
; CHECK-NEXT: ret i1 true
754753
;

0 commit comments

Comments
 (0)