Skip to content

Commit 2213168

Browse files
dtcxzywrorth
authored andcommitted

File tree

4 files changed

+91
-38
lines changed

4 files changed

+91
-38
lines changed

llvm/lib/Transforms/Utils/SCCPSolver.cpp

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "llvm/Analysis/ValueLatticeUtils.h"
2121
#include "llvm/Analysis/ValueTracking.h"
2222
#include "llvm/IR/InstVisitor.h"
23+
#include "llvm/IR/PatternMatch.h"
2324
#include "llvm/Support/Casting.h"
2425
#include "llvm/Support/Debug.h"
2526
#include "llvm/Support/ErrorHandling.h"
@@ -30,6 +31,7 @@
3031
#include <vector>
3132

3233
using namespace llvm;
34+
using namespace PatternMatch;
3335

3436
#define DEBUG_TYPE "sccp"
3537

@@ -83,20 +85,28 @@ bool SCCPSolver::tryToReplaceWithConstant(Value *V) {
8385
return true;
8486
}
8587

88+
/// Helper for getting ranges from \p Solver. Instructions inserted during
89+
/// simplification are unavailable in the solver, so we return a full range for
90+
/// them.
91+
static ConstantRange getRange(Value *Op, SCCPSolver &Solver,
92+
const SmallPtrSetImpl<Value *> &InsertedValues) {
93+
if (auto *Const = dyn_cast<Constant>(Op))
94+
return Const->toConstantRange();
95+
if (InsertedValues.contains(Op)) {
96+
unsigned Bitwidth = Op->getType()->getScalarSizeInBits();
97+
return ConstantRange::getFull(Bitwidth);
98+
}
99+
return Solver.getLatticeValueFor(Op).asConstantRange(Op->getType(),
100+
/*UndefAllowed=*/false);
101+
}
102+
86103
/// Try to use \p Inst's value range from \p Solver to infer the NUW flag.
87104
static bool refineInstruction(SCCPSolver &Solver,
88105
const SmallPtrSetImpl<Value *> &InsertedValues,
89106
Instruction &Inst) {
90107
bool Changed = false;
91108
auto GetRange = [&Solver, &InsertedValues](Value *Op) {
92-
if (auto *Const = dyn_cast<Constant>(Op))
93-
return Const->toConstantRange();
94-
if (InsertedValues.contains(Op)) {
95-
unsigned Bitwidth = Op->getType()->getScalarSizeInBits();
96-
return ConstantRange::getFull(Bitwidth);
97-
}
98-
return Solver.getLatticeValueFor(Op).asConstantRange(
99-
Op->getType(), /*UndefAllowed=*/false);
109+
return getRange(Op, Solver, InsertedValues);
100110
};
101111

102112
if (isa<OverflowingBinaryOperator>(Inst)) {
@@ -167,16 +177,8 @@ static bool replaceSignedInst(SCCPSolver &Solver,
167177
SmallPtrSetImpl<Value *> &InsertedValues,
168178
Instruction &Inst) {
169179
// Determine if a signed value is known to be >= 0.
170-
auto isNonNegative = [&Solver](Value *V) {
171-
// If this value was constant-folded, it may not have a solver entry.
172-
// Handle integers. Otherwise, return false.
173-
if (auto *C = dyn_cast<Constant>(V)) {
174-
auto *CInt = dyn_cast<ConstantInt>(C);
175-
return CInt && !CInt->isNegative();
176-
}
177-
const ValueLatticeElement &IV = Solver.getLatticeValueFor(V);
178-
return IV.isConstantRange(/*UndefAllowed=*/false) &&
179-
IV.getConstantRange().isAllNonNegative();
180+
auto isNonNegative = [&Solver, &InsertedValues](Value *V) {
181+
return getRange(V, Solver, InsertedValues).isAllNonNegative();
180182
};
181183

182184
Instruction *NewInst = nullptr;
@@ -185,7 +187,7 @@ static bool replaceSignedInst(SCCPSolver &Solver,
185187
case Instruction::SExt: {
186188
// If the source value is not negative, this is a zext/uitofp.
187189
Value *Op0 = Inst.getOperand(0);
188-
if (InsertedValues.count(Op0) || !isNonNegative(Op0))
190+
if (!isNonNegative(Op0))
189191
return false;
190192
NewInst = CastInst::Create(Inst.getOpcode() == Instruction::SExt
191193
? Instruction::ZExt
@@ -197,7 +199,7 @@ static bool replaceSignedInst(SCCPSolver &Solver,
197199
case Instruction::AShr: {
198200
// If the shifted value is not negative, this is a logical shift right.
199201
Value *Op0 = Inst.getOperand(0);
200-
if (InsertedValues.count(Op0) || !isNonNegative(Op0))
202+
if (!isNonNegative(Op0))
201203
return false;
202204
NewInst = BinaryOperator::CreateLShr(Op0, Inst.getOperand(1), "", Inst.getIterator());
203205
NewInst->setIsExact(Inst.isExact());
@@ -207,8 +209,7 @@ static bool replaceSignedInst(SCCPSolver &Solver,
207209
case Instruction::SRem: {
208210
// If both operands are not negative, this is the same as udiv/urem.
209211
Value *Op0 = Inst.getOperand(0), *Op1 = Inst.getOperand(1);
210-
if (InsertedValues.count(Op0) || InsertedValues.count(Op1) ||
211-
!isNonNegative(Op0) || !isNonNegative(Op1))
212+
if (!isNonNegative(Op0) || !isNonNegative(Op1))
212213
return false;
213214
auto NewOpcode = Inst.getOpcode() == Instruction::SDiv ? Instruction::UDiv
214215
: Instruction::URem;
@@ -232,6 +233,26 @@ static bool replaceSignedInst(SCCPSolver &Solver,
232233
return true;
233234
}
234235

236+
/// Try to use \p Inst's value range from \p Solver to simplify it.
237+
static Value *simplifyInstruction(SCCPSolver &Solver,
238+
SmallPtrSetImpl<Value *> &InsertedValues,
239+
Instruction &Inst) {
240+
auto GetRange = [&Solver, &InsertedValues](Value *Op) {
241+
return getRange(Op, Solver, InsertedValues);
242+
};
243+
244+
Value *X;
245+
const APInt *RHSC;
246+
// Remove masking operations.
247+
if (match(&Inst, m_And(m_Value(X), m_LowBitMask(RHSC)))) {
248+
ConstantRange LRange = GetRange(Inst.getOperand(0));
249+
if (LRange.getUnsignedMax().ule(*RHSC))
250+
return X;
251+
}
252+
253+
return nullptr;
254+
}
255+
235256
bool SCCPSolver::simplifyInstsInBlock(BasicBlock &BB,
236257
SmallPtrSetImpl<Value *> &InsertedValues,
237258
Statistic &InstRemovedStat,
@@ -251,6 +272,11 @@ bool SCCPSolver::simplifyInstsInBlock(BasicBlock &BB,
251272
++InstReplacedStat;
252273
} else if (refineInstruction(*this, InsertedValues, Inst)) {
253274
MadeChanges = true;
275+
} else if (auto *V = simplifyInstruction(*this, InsertedValues, Inst)) {
276+
Inst.replaceAllUsesWith(V);
277+
Inst.eraseFromParent();
278+
++InstRemovedStat;
279+
MadeChanges = true;
254280
}
255281
}
256282
return MadeChanges;

llvm/test/Transforms/SCCP/conditions-ranges-with-undef.ll

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ false:
3636

3737
declare void @use.i32(i32)
3838

39-
; It is not allowed to use the range information from the condition to remove
40-
; %a.127 = and ... in the true block, as %a could be undef.
4139
define void @val_undef_range() {
4240
; CHECK-LABEL: @val_undef_range(
4341
; CHECK-NEXT: entry:
@@ -46,8 +44,7 @@ define void @val_undef_range() {
4644
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
4745
; CHECK: true:
4846
; CHECK-NEXT: call void @use(i1 false)
49-
; CHECK-NEXT: [[A_127:%.*]] = and i32 [[A]], 127
50-
; CHECK-NEXT: call void @use.i32(i32 [[A_127]])
47+
; CHECK-NEXT: call void @use.i32(i32 [[A]])
5148
; CHECK-NEXT: ret void
5249
; CHECK: false:
5350
; CHECK-NEXT: ret void
@@ -82,8 +79,7 @@ define void @val_singlecrfromundef_range(i1 %cond) {
8279
; CHECK-NEXT: br label [[TRUE:%.*]]
8380
; CHECK: true:
8481
; CHECK-NEXT: call void @use(i1 false)
85-
; CHECK-NEXT: [[P_127:%.*]] = and i32 10, 127
86-
; CHECK-NEXT: call void @use.i32(i32 [[P_127]])
82+
; CHECK-NEXT: call void @use.i32(i32 10)
8783
; CHECK-NEXT: ret void
8884
;
8985
entry:
@@ -113,9 +109,6 @@ false:
113109
ret void
114110
}
115111

116-
117-
; It is not allowed to use the information from the condition ([0, 128))
118-
; to remove a.127.2 = and i32 %p, 127, as %p might be undef.
119112
define void @val_undef_to_cr_to_overdef_range(i32 %a, i1 %cond) {
120113
; CHECK-LABEL: @val_undef_to_cr_to_overdef_range(
121114
; CHECK-NEXT: entry:
@@ -131,8 +124,7 @@ define void @val_undef_to_cr_to_overdef_range(i32 %a, i1 %cond) {
131124
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
132125
; CHECK: true:
133126
; CHECK-NEXT: call void @use(i1 false)
134-
; CHECK-NEXT: [[P_127:%.*]] = and i32 [[P]], 127
135-
; CHECK-NEXT: call void @use.i32(i32 [[P_127]])
127+
; CHECK-NEXT: call void @use.i32(i32 [[P]])
136128
; CHECK-NEXT: ret void
137129
; CHECK: false:
138130
; CHECK-NEXT: ret void
@@ -164,6 +156,43 @@ false:
164156
ret void
165157
}
166158

159+
; It is not allowed to use the range information from the condition to remove
160+
; %p.127 = and i32 %p, 127, as %p could be undef.
161+
define void @masked_incoming_val_with_undef(i32 %a, i1 %cond) {
162+
; CHECK-LABEL: @masked_incoming_val_with_undef(
163+
; CHECK-NEXT: entry:
164+
; CHECK-NEXT: [[A_127:%.*]] = and i32 [[A:%.*]], 127
165+
; CHECK-NEXT: br i1 [[COND:%.*]], label [[INC1:%.*]], label [[INC2:%.*]]
166+
; CHECK: inc1:
167+
; CHECK-NEXT: br label [[IF:%.*]]
168+
; CHECK: inc2:
169+
; CHECK-NEXT: br label [[IF]]
170+
; CHECK: if:
171+
; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[A_127]], [[INC1]] ], [ undef, [[INC2]] ]
172+
; CHECK-NEXT: [[P_127:%.*]] = and i32 [[P]], 127
173+
; CHECK-NEXT: call void @use.i32(i32 [[P_127]])
174+
; CHECK-NEXT: ret void
175+
;
176+
entry:
177+
%a.127 = and i32 %a, 127
178+
br i1 %cond, label %inc1, label %inc2
179+
180+
inc1:
181+
br label %if
182+
183+
inc2:
184+
br label %if
185+
186+
if:
187+
%p = phi i32 [ %a.127, %inc1 ], [ undef, %inc2 ]
188+
%p.127 = and i32 %p, 127
189+
call void @use.i32(i32 %p.127)
190+
ret void
191+
192+
false:
193+
ret void
194+
}
195+
167196
; All uses of %p can be replaced by a constant (10), we are allowed to use it
168197
; as a bound too.
169198
define void @bound_singlecrfromundef(i32 %a, i1 %cond) {

llvm/test/Transforms/SCCP/range-and.ll

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --verbose
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
22
; RUN: opt -S -passes=sccp %s | FileCheck %s
33

44
declare void @use(i1)
@@ -140,9 +140,8 @@ define i64 @constant_range_and_255_100(i1 %cond, i64 %a) {
140140
; CHECK-NEXT: br label [[BB3]]
141141
; CHECK: bb3:
142142
; CHECK-NEXT: [[P:%.*]] = phi i64 [ [[R_1]], [[BB1]] ], [ [[R_2]], [[BB2]] ]
143-
; CHECK-NEXT: [[P_AND:%.*]] = and i64 [[P]], 255
144143
; CHECK-NEXT: call void @use(i1 true)
145-
; CHECK-NEXT: ret i64 [[P_AND]]
144+
; CHECK-NEXT: ret i64 [[P]]
146145
;
147146
entry:
148147
br i1 %cond, label %bb1, label %bb2

llvm/test/Transforms/SCCP/range-with-undef.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ define i8 @test_binop(i1 %cond, i8 %a) {
1212
; CHECK-NEXT: [[A_EXT:%.*]] = zext i8 [[A]] to i16
1313
; CHECK-NEXT: br label %[[JOIN]]
1414
; CHECK: [[JOIN]]:
15-
; CHECK-NEXT: [[PHI:%.*]] = phi i16 [ undef, %[[ENTRY]] ], [ [[A_EXT]], %[[IF]] ]
16-
; CHECK-NEXT: [[AND:%.*]] = and i16 [[PHI]], -1
15+
; CHECK-NEXT: [[AND:%.*]] = phi i16 [ undef, %[[ENTRY]] ], [ [[A_EXT]], %[[IF]] ]
1716
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i16 [[AND]] to i8
1817
; CHECK-NEXT: ret i8 [[TRUNC]]
1918
;

0 commit comments

Comments
 (0)