Skip to content

Commit c228140

Browse files
serge-sans-paillellvmbot
authored andcommitted
[llvm] Fix __builtin_object_size interaction between Negative Offset … (#111827)
…and Select/Phi When picking a SizeOffsetAPInt through combineSizeOffset, the behavior differs if we're going to apply a constant offset that's positive or negative: If it's positive, then we need to compare the remaining bytes (i.e. Size - Offset), but if it's negative, we need to compare the preceding bytes (i.e. Offset). Fix #111709 (cherry picked from commit 01a103b)
1 parent ab51ecc commit c228140

File tree

4 files changed

+405
-89
lines changed

4 files changed

+405
-89
lines changed

llvm/include/llvm/Analysis/MemoryBuiltins.h

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -222,21 +222,43 @@ struct SizeOffsetAPInt : public SizeOffsetType<APInt, SizeOffsetAPInt> {
222222
static bool known(const APInt &V) { return V.getBitWidth() > 1; }
223223
};
224224

225+
/// OffsetSpan - Used internally by \p ObjectSizeOffsetVisitor. Represents a
226+
/// point in memory as a pair of allocated bytes before and after it.
227+
struct OffsetSpan {
228+
APInt Before; /// Number of allocated bytes before this point.
229+
APInt After; /// Number of allocated bytes after this point.
230+
231+
OffsetSpan() = default;
232+
OffsetSpan(APInt Before, APInt After) : Before(Before), After(After) {}
233+
234+
bool knownBefore() const { return known(Before); }
235+
bool knownAfter() const { return known(After); }
236+
bool anyKnown() const { return knownBefore() || knownAfter(); }
237+
bool bothKnown() const { return knownBefore() && knownAfter(); }
238+
239+
bool operator==(const OffsetSpan &RHS) const {
240+
return Before == RHS.Before && After == RHS.After;
241+
}
242+
bool operator!=(const OffsetSpan &RHS) const { return !(*this == RHS); }
243+
244+
static bool known(const APInt &V) { return V.getBitWidth() > 1; }
245+
};
246+
225247
/// Evaluate the size and offset of an object pointed to by a Value*
226248
/// statically. Fails if size or offset are not known at compile time.
227249
class ObjectSizeOffsetVisitor
228-
: public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetAPInt> {
250+
: public InstVisitor<ObjectSizeOffsetVisitor, OffsetSpan> {
229251
const DataLayout &DL;
230252
const TargetLibraryInfo *TLI;
231253
ObjectSizeOpts Options;
232254
unsigned IntTyBits;
233255
APInt Zero;
234-
SmallDenseMap<Instruction *, SizeOffsetAPInt, 8> SeenInsts;
256+
SmallDenseMap<Instruction *, OffsetSpan, 8> SeenInsts;
235257
unsigned InstructionsVisited;
236258

237259
APInt align(APInt Size, MaybeAlign Align);
238260

239-
static SizeOffsetAPInt unknown() { return SizeOffsetAPInt(); }
261+
static OffsetSpan unknown() { return OffsetSpan(); }
240262

241263
public:
242264
ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI,
@@ -246,29 +268,30 @@ class ObjectSizeOffsetVisitor
246268

247269
// These are "private", except they can't actually be made private. Only
248270
// compute() should be used by external users.
249-
SizeOffsetAPInt visitAllocaInst(AllocaInst &I);
250-
SizeOffsetAPInt visitArgument(Argument &A);
251-
SizeOffsetAPInt visitCallBase(CallBase &CB);
252-
SizeOffsetAPInt visitConstantPointerNull(ConstantPointerNull &);
253-
SizeOffsetAPInt visitExtractElementInst(ExtractElementInst &I);
254-
SizeOffsetAPInt visitExtractValueInst(ExtractValueInst &I);
255-
SizeOffsetAPInt visitGlobalAlias(GlobalAlias &GA);
256-
SizeOffsetAPInt visitGlobalVariable(GlobalVariable &GV);
257-
SizeOffsetAPInt visitIntToPtrInst(IntToPtrInst &);
258-
SizeOffsetAPInt visitLoadInst(LoadInst &I);
259-
SizeOffsetAPInt visitPHINode(PHINode &);
260-
SizeOffsetAPInt visitSelectInst(SelectInst &I);
261-
SizeOffsetAPInt visitUndefValue(UndefValue &);
262-
SizeOffsetAPInt visitInstruction(Instruction &I);
271+
OffsetSpan visitAllocaInst(AllocaInst &I);
272+
OffsetSpan visitArgument(Argument &A);
273+
OffsetSpan visitCallBase(CallBase &CB);
274+
OffsetSpan visitConstantPointerNull(ConstantPointerNull &);
275+
OffsetSpan visitExtractElementInst(ExtractElementInst &I);
276+
OffsetSpan visitExtractValueInst(ExtractValueInst &I);
277+
OffsetSpan visitGlobalAlias(GlobalAlias &GA);
278+
OffsetSpan visitGlobalVariable(GlobalVariable &GV);
279+
OffsetSpan visitIntToPtrInst(IntToPtrInst &);
280+
OffsetSpan visitLoadInst(LoadInst &I);
281+
OffsetSpan visitPHINode(PHINode &);
282+
OffsetSpan visitSelectInst(SelectInst &I);
283+
OffsetSpan visitUndefValue(UndefValue &);
284+
OffsetSpan visitInstruction(Instruction &I);
263285

264286
private:
265-
SizeOffsetAPInt findLoadSizeOffset(
266-
LoadInst &LoadFrom, BasicBlock &BB, BasicBlock::iterator From,
267-
SmallDenseMap<BasicBlock *, SizeOffsetAPInt, 8> &VisitedBlocks,
268-
unsigned &ScannedInstCount);
269-
SizeOffsetAPInt combineSizeOffset(SizeOffsetAPInt LHS, SizeOffsetAPInt RHS);
270-
SizeOffsetAPInt computeImpl(Value *V);
271-
SizeOffsetAPInt computeValue(Value *V);
287+
OffsetSpan
288+
findLoadOffsetRange(LoadInst &LoadFrom, BasicBlock &BB,
289+
BasicBlock::iterator From,
290+
SmallDenseMap<BasicBlock *, OffsetSpan, 8> &VisitedBlocks,
291+
unsigned &ScannedInstCount);
292+
OffsetSpan combineOffsetRange(OffsetSpan LHS, OffsetSpan RHS);
293+
OffsetSpan computeImpl(Value *V);
294+
OffsetSpan computeValue(Value *V);
272295
bool CheckedZextOrTrunc(APInt &I);
273296
};
274297

0 commit comments

Comments
 (0)