llvm.org GIT mirror llvm / f78c27b
Fix a hang when lowering __builtin_dynamic_object_size If the ObjectSizeOffsetEvaluator fails to fold the object size call, then it may litter some unused instructions in the function. When done repeatably in InstCombine, this results in an infinite loop. Fix this by tracking the set of instructions that were inserted, then removing them on failure. rdar://49172227 Differential revision: https://reviews.llvm.org/D60298 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@358146 91177308-0d34-0410-b5e6-96231b3b80d8 Erik Pilkington 6 months ago
4 changed file(s) with 55 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
249249 /// May create code to compute the result at run-time.
250250 class ObjectSizeOffsetEvaluator
251251 : public InstVisitor {
252 using BuilderTy = IRBuilder>;
252 using BuilderTy = IRBuilder, IRBuilderCallbackInserter>;
253253 using WeakEvalType = std::pair;
254254 using CacheMapTy = DenseMap;
255255 using PtrSetTy = SmallPtrSet;
263263 CacheMapTy CacheMap;
264264 PtrSetTy SeenVals;
265265 ObjectSizeOpts EvalOpts;
266 SmallPtrSet InsertedInstructions;
266267
267268 SizeOffsetEvalType compute_(Value *V);
268269
764764 ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator(
765765 const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context,
766766 ObjectSizeOpts EvalOpts)
767 : DL(DL), TLI(TLI), Context(Context), Builder(Context, TargetFolder(DL)),
767 : DL(DL), TLI(TLI), Context(Context),
768 Builder(Context, TargetFolder(DL),
769 IRBuilderCallbackInserter(
770 [&](Instruction *I) { InsertedInstructions.insert(I); })),
768771 EvalOpts(EvalOpts) {
769772 // IntTy and Zero must be set for each compute() since the address space may
770773 // be different for later objects.
787790 if (CacheIt != CacheMap.end() && anyKnown(CacheIt->second))
788791 CacheMap.erase(CacheIt);
789792 }
793
794 // Erase any instructions we inserted as part of the traversal.
795 for (Instruction *I : InsertedInstructions) {
796 I->replaceAllUsesWith(UndefValue::get(I->getType()));
797 I->eraseFromParent();
798 }
790799 }
791800
792801 SeenVals.clear();
802 InsertedInstructions.clear();
793803 return Result;
794804 }
795805
933943 if (!bothKnown(EdgeData)) {
934944 OffsetPHI->replaceAllUsesWith(UndefValue::get(IntTy));
935945 OffsetPHI->eraseFromParent();
946 InsertedInstructions.erase(OffsetPHI);
936947 SizePHI->replaceAllUsesWith(UndefValue::get(IntTy));
937948 SizePHI->eraseFromParent();
949 InsertedInstructions.erase(SizePHI);
938950 return unknown();
939951 }
940952 SizePHI->addIncoming(EdgeData.first, PHI.getIncomingBlock(i));
941953 OffsetPHI->addIncoming(EdgeData.second, PHI.getIncomingBlock(i));
942954 }
943955
944 Value *Size = SizePHI, *Offset = OffsetPHI, *Tmp;
945 if ((Tmp = SizePHI->hasConstantValue())) {
956 Value *Size = SizePHI, *Offset = OffsetPHI;
957 if (Value *Tmp = SizePHI->hasConstantValue()) {
946958 Size = Tmp;
947959 SizePHI->replaceAllUsesWith(Size);
948960 SizePHI->eraseFromParent();
949 }
950 if ((Tmp = OffsetPHI->hasConstantValue())) {
961 InsertedInstructions.erase(SizePHI);
962 }
963 if (Value *Tmp = OffsetPHI->hasConstantValue()) {
951964 Offset = Tmp;
952965 OffsetPHI->replaceAllUsesWith(Offset);
953966 OffsetPHI->eraseFromParent();
967 InsertedInstructions.erase(OffsetPHI);
954968 }
955969 return std::make_pair(Size, Offset);
956970 }
5757 ; CHECK: @f1_as1
5858 ; no checks are possible here
5959 ; CHECK-NOT: trap
60 ; CHECK: add i16 undef, -1
61 ; CHECK-NOT: trap
6260 entry:
6361 %0 = load i8, i8 addrspace(1)* %c, align 1
6462 %tobool1 = icmp eq i8 %0, 0
7070
7171 ; CHECK: ret i64 0
7272
73 @d = common global i8 0, align 1
74 @c = common global i32 0, align 4
75
76 ; Function Attrs: nounwind
77 define void @f() {
78 entry:
79 %.pr = load i32, i32* @c, align 4
80 %tobool4 = icmp eq i32 %.pr, 0
81 br i1 %tobool4, label %for.end, label %for.body
82
83 for.body: ; preds = %entry, %for.body
84 %dp.05 = phi i8* [ %add.ptr, %for.body ], [ @d, %entry ]
85 %0 = tail call i64 @llvm.objectsize.i64.p0i8(i8* %dp.05, i1 false, i1 true, i1 true)
86 %conv = trunc i64 %0 to i32
87 tail call void @bury(i32 %conv) #3
88 %1 = load i32, i32* @c, align 4
89 %idx.ext = sext i32 %1 to i64
90 %add.ptr.offs = add i64 %idx.ext, 0
91 %2 = add i64 undef, %add.ptr.offs
92 %add.ptr = getelementptr inbounds i8, i8* %dp.05, i64 %idx.ext
93 %add = shl nsw i32 %1, 1
94 store i32 %add, i32* @c, align 4
95 %tobool = icmp eq i32 %1, 0
96 br i1 %tobool, label %for.end, label %for.body
97
98 for.end: ; preds = %for.body, %entry
99 ret void
100 }
101
102 ; CHECK: define void @f()
103 ; CHECK: call i64 @llvm.objectsize.i64.p0i8(
104
105 declare void @bury(i32) local_unnamed_addr #2
106
73107 ; Function Attrs: nounwind allocsize(0)
74108 declare i8* @malloc(i64)
75109