这是indexloc提供的服务,不要输入任何密码
Skip to content

Commit 8dbcc58

Browse files
committed
Use SCEV to avoid inserting some bounds checks.
This patch uses SCEV to avoid inserting some bounds checks when they are not needed. This slightly improves the performance of code compiled with the bounds check sanitizer. Differential Revision: https://reviews.llvm.org/D49602 llvm-svn: 337830
1 parent 3241724 commit 8dbcc58

File tree

2 files changed

+386
-12
lines changed

2 files changed

+386
-12
lines changed

llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "llvm/ADT/Statistic.h"
1212
#include "llvm/ADT/Twine.h"
1313
#include "llvm/Analysis/MemoryBuiltins.h"
14+
#include "llvm/Analysis/ScalarEvolution.h"
1415
#include "llvm/Analysis/TargetFolder.h"
1516
#include "llvm/Analysis/TargetLibraryInfo.h"
1617
#include "llvm/IR/BasicBlock.h"
@@ -59,8 +60,8 @@ template <typename GetTrapBBT>
5960
static bool instrumentMemAccess(Value *Ptr, Value *InstVal,
6061
const DataLayout &DL, TargetLibraryInfo &TLI,
6162
ObjectSizeOffsetEvaluator &ObjSizeEval,
62-
BuilderTy &IRB,
63-
GetTrapBBT GetTrapBB) {
63+
BuilderTy &IRB, GetTrapBBT GetTrapBB,
64+
ScalarEvolution &SE) {
6465
uint64_t NeededSize = DL.getTypeStoreSize(InstVal->getType());
6566
LLVM_DEBUG(dbgs() << "Instrument " << *Ptr << " for " << Twine(NeededSize)
6667
<< " bytes\n");
@@ -79,6 +80,10 @@ static bool instrumentMemAccess(Value *Ptr, Value *InstVal,
7980
Type *IntTy = DL.getIntPtrType(Ptr->getType());
8081
Value *NeededSizeVal = ConstantInt::get(IntTy, NeededSize);
8182

83+
auto SizeRange = SE.getUnsignedRange(SE.getSCEV(Size));
84+
auto OffsetRange = SE.getUnsignedRange(SE.getSCEV(Offset));
85+
auto NeededSizeRange = SE.getUnsignedRange(SE.getSCEV(NeededSizeVal));
86+
8287
// three checks are required to ensure safety:
8388
// . Offset >= 0 (since the offset is given from the base ptr)
8489
// . Size >= Offset (unsigned)
@@ -87,10 +92,17 @@ static bool instrumentMemAccess(Value *Ptr, Value *InstVal,
8792
// optimization: if Size >= 0 (signed), skip 1st check
8893
// FIXME: add NSW/NUW here? -- we dont care if the subtraction overflows
8994
Value *ObjSize = IRB.CreateSub(Size, Offset);
90-
Value *Cmp2 = IRB.CreateICmpULT(Size, Offset);
91-
Value *Cmp3 = IRB.CreateICmpULT(ObjSize, NeededSizeVal);
95+
Value *Cmp2 = SizeRange.getUnsignedMin().uge(OffsetRange.getUnsignedMax())
96+
? ConstantInt::getFalse(Ptr->getContext())
97+
: IRB.CreateICmpULT(Size, Offset);
98+
Value *Cmp3 = SizeRange.sub(OffsetRange)
99+
.getUnsignedMin()
100+
.uge(NeededSizeRange.getUnsignedMax())
101+
? ConstantInt::getFalse(Ptr->getContext())
102+
: IRB.CreateICmpULT(ObjSize, NeededSizeVal);
92103
Value *Or = IRB.CreateOr(Cmp2, Cmp3);
93-
if (!SizeCI || SizeCI->getValue().slt(0)) {
104+
if ((!SizeCI || SizeCI->getValue().slt(0)) &&
105+
!SizeRange.getSignedMin().isNonNegative()) {
94106
Value *Cmp1 = IRB.CreateICmpSLT(Offset, ConstantInt::get(IntTy, 0));
95107
Or = IRB.CreateOr(Cmp1, Or);
96108
}
@@ -123,7 +135,8 @@ static bool instrumentMemAccess(Value *Ptr, Value *InstVal,
123135
return true;
124136
}
125137

126-
static bool addBoundsChecking(Function &F, TargetLibraryInfo &TLI) {
138+
static bool addBoundsChecking(Function &F, TargetLibraryInfo &TLI,
139+
ScalarEvolution &SE) {
127140
const DataLayout &DL = F.getParent()->getDataLayout();
128141
ObjectSizeOffsetEvaluator ObjSizeEval(DL, &TLI, F.getContext(),
129142
/*RoundToAlign=*/true);
@@ -168,19 +181,19 @@ static bool addBoundsChecking(Function &F, TargetLibraryInfo &TLI) {
168181
BuilderTy IRB(Inst->getParent(), BasicBlock::iterator(Inst), TargetFolder(DL));
169182
if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
170183
MadeChange |= instrumentMemAccess(LI->getPointerOperand(), LI, DL, TLI,
171-
ObjSizeEval, IRB, GetTrapBB);
184+
ObjSizeEval, IRB, GetTrapBB, SE);
172185
} else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
173186
MadeChange |=
174187
instrumentMemAccess(SI->getPointerOperand(), SI->getValueOperand(),
175-
DL, TLI, ObjSizeEval, IRB, GetTrapBB);
188+
DL, TLI, ObjSizeEval, IRB, GetTrapBB, SE);
176189
} else if (AtomicCmpXchgInst *AI = dyn_cast<AtomicCmpXchgInst>(Inst)) {
177190
MadeChange |=
178191
instrumentMemAccess(AI->getPointerOperand(), AI->getCompareOperand(),
179-
DL, TLI, ObjSizeEval, IRB, GetTrapBB);
192+
DL, TLI, ObjSizeEval, IRB, GetTrapBB, SE);
180193
} else if (AtomicRMWInst *AI = dyn_cast<AtomicRMWInst>(Inst)) {
181194
MadeChange |=
182195
instrumentMemAccess(AI->getPointerOperand(), AI->getValOperand(), DL,
183-
TLI, ObjSizeEval, IRB, GetTrapBB);
196+
TLI, ObjSizeEval, IRB, GetTrapBB, SE);
184197
} else {
185198
llvm_unreachable("unknown Instruction type");
186199
}
@@ -190,8 +203,9 @@ static bool addBoundsChecking(Function &F, TargetLibraryInfo &TLI) {
190203

191204
PreservedAnalyses BoundsCheckingPass::run(Function &F, FunctionAnalysisManager &AM) {
192205
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
206+
auto &SE = AM.getResult<ScalarEvolutionAnalysis>(F);
193207

194-
if (!addBoundsChecking(F, TLI))
208+
if (!addBoundsChecking(F, TLI, SE))
195209
return PreservedAnalyses::all();
196210

197211
return PreservedAnalyses::none();
@@ -207,11 +221,13 @@ struct BoundsCheckingLegacyPass : public FunctionPass {
207221

208222
bool runOnFunction(Function &F) override {
209223
auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
210-
return addBoundsChecking(F, TLI);
224+
auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
225+
return addBoundsChecking(F, TLI, SE);
211226
}
212227

213228
void getAnalysisUsage(AnalysisUsage &AU) const override {
214229
AU.addRequired<TargetLibraryInfoWrapperPass>();
230+
AU.addRequired<ScalarEvolutionWrapperPass>();
215231
}
216232
};
217233
} // namespace

0 commit comments

Comments
 (0)