Skip to content

Commit 15e19a2

Browse files
committed
Revert "[instcombine] Exploit UB implied by nofree attributes"
This change effectively reverts 8666463, but since there have been some changes on top and I wanted to leave the tests in, it's not a mechanical revert. Why revert this now? Two main reasons: 1) There are continuing discussion around what the semantics of nofree. I am getting increasing uncomfortable with the seeming possibility we might redefine nofree in a way incompatible with these changes. 2) There was a reported miscompile triggered by this change (emscripten-core/emscripten#9443). At first, I was making good progress on tracking down the issues exposed and those issues appeared to be unrelated latent bugs. Now that we've found at least one bug in the original change, and the investigation has stalled, I'm no longer comfortable leaving this in tree. In retrospect, I probably should have reverted this earlier and investigated the issues once the triggering change was out of tree.
1 parent e01c419 commit 15e19a2

File tree

2 files changed

+12
-30
lines changed

2 files changed

+12
-30
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2799,25 +2799,6 @@ Instruction *InstCombinerImpl::visitFree(CallInst &FI) {
27992799
if (isa<ConstantPointerNull>(Op))
28002800
return eraseInstFromFunction(FI);
28012801

2802-
2803-
// If we free a non-null pointer we've been explicitly told won't be freed,
2804-
// this would be full UB and thus we can conclude that the argument must
2805-
// be null at the point of the free. Cases:
2806-
// 1) freeing a pointer which is explicitly nofree
2807-
// 2) calling free from a call site marked nofree (TODO: can generalize
2808-
// for non-arguments)
2809-
// 3) calling free in a function scope marked nofree (when we can prove
2810-
// the allocation existed before the start of the function scope)
2811-
if (auto *A = dyn_cast<Argument>(Op->stripPointerCasts()))
2812-
if (A->hasAttribute(Attribute::NoFree) ||
2813-
FI.hasFnAttr(Attribute::NoFree) ||
2814-
FI.getFunction()->hasFnAttribute(Attribute::NoFree)) {
2815-
Value *Null = ConstantPointerNull::get(cast<PointerType>(A->getType()));
2816-
Value *Cond = Builder.CreateICmpEQ(A, Null);
2817-
Builder.CreateAssumption(Cond);
2818-
return eraseInstFromFunction(FI);
2819-
}
2820-
28212802
// If we optimize for code size, try to move the call to free before the null
28222803
// test so that simplify cfg can remove the empty block and dead code
28232804
// elimination the branch. I.e., helps to turn something like:

llvm/test/Transforms/InstCombine/malloc-free-delete.ll

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -391,43 +391,44 @@ if.end: ; preds = %entry, %if.then
391391
ret void
392392
}
393393

394-
; Freeing a no-free pointer -> %foo must be null
394+
; The next four tests cover the semantics of the nofree attributes. These
395+
; are thought to be legal transforms, but an implementation thereof has
396+
; been reverted once due to difficult to isolate fallout.
397+
398+
; TODO: Freeing a no-free pointer -> %foo must be null
395399
define void @test13(i8* nofree %foo) {
396400
; CHECK-LABEL: @test13(
397-
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* [[FOO:%.*]], null
398-
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
401+
; CHECK-NEXT: call void @free(i8* [[FOO:%.*]])
399402
; CHECK-NEXT: ret void
400403
;
401404
call void @free(i8* %foo)
402405
ret void
403406
}
404407

405-
; Freeing a no-free pointer -> %foo must be null
408+
; TODO: Freeing a no-free pointer -> %foo must be null
406409
define void @test14(i8* %foo) nofree {
407410
; CHECK-LABEL: @test14(
408-
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* [[FOO:%.*]], null
409-
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
411+
; CHECK-NEXT: call void @free(i8* [[FOO:%.*]])
410412
; CHECK-NEXT: ret void
411413
;
412414
call void @free(i8* %foo)
413415
ret void
414416
}
415417

416-
; free call marked no-free -> %foo must be null
418+
; TODO: free call marked no-free -> %foo must be null
417419
define void @test15(i8* %foo) {
418420
; CHECK-LABEL: @test15(
419-
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* [[FOO:%.*]], null
420-
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
421+
; CHECK-NEXT: call void @free(i8* [[FOO:%.*]]) #[[ATTR6:[0-9]+]]
421422
; CHECK-NEXT: ret void
422423
;
423424
call void @free(i8* %foo) nofree
424425
ret void
425426
}
426427

427-
; freeing a nonnull nofree pointer -> full UB
428+
; TODO: freeing a nonnull nofree pointer -> full UB
428429
define void @test16(i8* nonnull nofree %foo) {
429430
; CHECK-LABEL: @test16(
430-
; CHECK-NEXT: call void @llvm.assume(i1 false)
431+
; CHECK-NEXT: call void @free(i8* [[FOO:%.*]])
431432
; CHECK-NEXT: ret void
432433
;
433434
call void @free(i8* %foo)

0 commit comments

Comments
 (0)