https://github.com/vtjnash updated https://github.com/llvm/llvm-project/pull/143958
>From 0d309ccbde665a033976a9eaa9f84c284765825c Mon Sep 17 00:00:00 2001 From: Jameson Nash <vtjn...@gmail.com> Date: Thu, 12 Jun 2025 18:48:00 +0000 Subject: [PATCH 1/9] [instcombine] remove dead loads, such as memcpy from undef --- .../InstCombine/InstructionCombining.cpp | 66 +++++++++++++++++-- .../Transforms/InstCombine/malloc-free.ll | 6 +- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index dc2a8cb0115e7..aa7119b005013 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3217,10 +3217,12 @@ static bool isRemovableWrite(CallBase &CB, Value *UsedV, static bool isAllocSiteRemovable(Instruction *AI, SmallVectorImpl<WeakTrackingVH> &Users, - const TargetLibraryInfo &TLI) { + const TargetLibraryInfo &TLI, + bool KnowInit) { SmallVector<Instruction*, 4> Worklist; const std::optional<StringRef> Family = getAllocationFamily(AI, &TLI); Worklist.push_back(AI); + ModRefInfo Access = KnowInit ? ModRefInfo::NoModRef : ModRefInfo::Mod; do { Instruction *PI = Worklist.pop_back_val(); @@ -3283,10 +3285,15 @@ static bool isAllocSiteRemovable(Instruction *AI, case Intrinsic::memcpy: case Intrinsic::memset: { MemIntrinsic *MI = cast<MemIntrinsic>(II); - if (MI->isVolatile() || MI->getRawDest() != PI) + if (MI->isVolatile()) return false; + // Note: this could also be ModRef, but we can still interpret that as just Mod in that case. + ModRefInfo NewAccess = MI->getRawDest() == PI ? ModRefInfo::Mod : ModRefInfo::Ref; + if ((Access & ~NewAccess) != ModRefInfo::NoModRef) + return false; + Access |= NewAccess; + } [[fallthrough]]; - } case Intrinsic::assume: case Intrinsic::invariant_start: case Intrinsic::invariant_end: @@ -3327,6 +3334,20 @@ static bool isAllocSiteRemovable(Instruction *AI, StoreInst *SI = cast<StoreInst>(I); if (SI->isVolatile() || SI->getPointerOperand() != PI) return false; + if (isRefSet(Access)) + return false; + Access |= ModRefInfo::Mod; + Users.emplace_back(I); + continue; + } + + case Instruction::Load: { + LoadInst *LI = cast<LoadInst>(I); + if (LI->isVolatile() || LI->getPointerOperand() != LI) + return false; + if (isModSet(Access)) + return false; + Access |= ModRefInfo::Ref; Users.emplace_back(I); continue; } @@ -3334,6 +3355,7 @@ static bool isAllocSiteRemovable(Instruction *AI, llvm_unreachable("missing a return?"); } } while (!Worklist.empty()); + return true; } @@ -3362,10 +3384,23 @@ Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) { DIB.reset(new DIBuilder(*MI.getModule(), /*AllowUnresolved=*/false)); } - if (isAllocSiteRemovable(&MI, Users, TLI)) { + // Determine what getInitialValueOfAllocation would return without actually allocating the result. + bool KnowInitUndef = isa<AllocaInst>(MI); + bool KnowInitZero = false; + if (!KnowInitUndef) { + Constant *Init = getInitialValueOfAllocation(&MI, &TLI, Type::getInt8Ty(MI.getContext())); + if (Init) { + if (isa<UndefValue>(Init)) + KnowInitUndef = true; + else if (Init->isNullValue()) + KnowInitZero = true; + } + } + + if (isAllocSiteRemovable(&MI, Users, TLI, KnowInitZero | KnowInitUndef)) { for (unsigned i = 0, e = Users.size(); i != e; ++i) { - // Lowering all @llvm.objectsize calls first because they may - // use a bitcast/GEP of the alloca we are removing. + // Lowering all @llvm.objectsize and MTI calls first because they may use + // a bitcast/GEP of the alloca we are removing. if (!Users[i]) continue; @@ -3382,6 +3417,17 @@ Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) { eraseInstFromFunction(*I); Users[i] = nullptr; // Skip examining in the next loop. } + if (auto *MTI = dyn_cast<MemTransferInst>(I)) { + if (KnowInitZero && getUnderlyingObject(MTI->getRawDest()) != &MI) { + IRBuilderBase::InsertPointGuard Guard(Builder); + Builder.SetInsertPoint(MTI); + auto *M = Builder.CreateMemSet(MTI->getRawDest(), + ConstantInt::get(Type::getInt8Ty(MI.getContext()), 0), + MTI->getLength(), + MTI->getDestAlign()); + M->copyMetadata(*MTI, LLVMContext::MD_DIAssignID); + } + } } } for (unsigned i = 0, e = Users.size(); i != e; ++i) { @@ -3404,7 +3450,13 @@ Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) { } else { // Casts, GEP, or anything else: we're about to delete this instruction, // so it can not have any valid uses. - replaceInstUsesWith(*I, PoisonValue::get(I->getType())); + Constant *Replace; + if (isa<LoadInst>(I)) { + assert(KnowInitZero || KnowInitUndef); + Replace = KnowInitUndef ? UndefValue::get(I->getType()) : Constant::getNullValue(I->getType()); + } else + Replace = PoisonValue::get(I->getType()); + replaceInstUsesWith(*I, Replace); } eraseInstFromFunction(*I); } diff --git a/llvm/test/Transforms/InstCombine/malloc-free.ll b/llvm/test/Transforms/InstCombine/malloc-free.ll index 1f556821270a2..989074f97aaf6 100644 --- a/llvm/test/Transforms/InstCombine/malloc-free.ll +++ b/llvm/test/Transforms/InstCombine/malloc-free.ll @@ -133,17 +133,13 @@ define void @test4() { define void @test5(ptr %ptr, ptr %esc) { ; CHECK-LABEL: @test5( -; CHECK-NEXT: [[A:%.*]] = call dereferenceable_or_null(700) ptr @malloc(i32 700) -; CHECK-NEXT: [[B:%.*]] = call dereferenceable_or_null(700) ptr @malloc(i32 700) ; CHECK-NEXT: [[C:%.*]] = call dereferenceable_or_null(700) ptr @malloc(i32 700) ; CHECK-NEXT: [[D:%.*]] = call dereferenceable_or_null(700) ptr @malloc(i32 700) ; CHECK-NEXT: [[E:%.*]] = call dereferenceable_or_null(700) ptr @malloc(i32 700) ; CHECK-NEXT: [[F:%.*]] = call dereferenceable_or_null(700) ptr @malloc(i32 700) ; CHECK-NEXT: [[G:%.*]] = call dereferenceable_or_null(700) ptr @malloc(i32 700) -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(32) [[PTR:%.*]], ptr noundef nonnull align 1 dereferenceable(32) [[A]], i32 32, i1 false) -; CHECK-NEXT: call void @llvm.memmove.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(32) [[PTR]], ptr noundef nonnull align 1 dereferenceable(32) [[B]], i32 32, i1 false) ; CHECK-NEXT: store ptr [[C]], ptr [[ESC:%.*]], align 4 -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[D]], ptr [[PTR]], i32 32, i1 true) +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[D]], ptr [[PTR:%.*]], i32 32, i1 true) ; CHECK-NEXT: call void @llvm.memmove.p0.p0.i32(ptr [[E]], ptr [[PTR]], i32 32, i1 true) ; CHECK-NEXT: call void @llvm.memset.p0.i32(ptr [[F]], i8 5, i32 32, i1 true) ; CHECK-NEXT: store volatile i8 4, ptr [[G]], align 1 >From 5acfa4e5fb7ec248807da001f51e6624edc079bb Mon Sep 17 00:00:00 2001 From: Jameson Nash <vtjn...@gmail.com> Date: Thu, 12 Jun 2025 14:54:29 -0400 Subject: [PATCH 2/9] add tests and bugfixes, with help from Claude --- clang/test/Misc/loop-opt-setup.c | 2 +- .../InstCombine/InstructionCombining.cpp | 13 +- .../Transforms/InstCombine/and-or-icmps.ll | 16 +- .../Transforms/InstCombine/apint-shift.ll | 2 +- .../InstCombine/call-cast-target.ll | 6 +- .../Transforms/InstCombine/dead-alloc-elim.ll | 140 ++++++++++++++++++ .../Transforms/InstCombine/fp-ret-bitcast.ll | 4 +- .../Transforms/InstCombine/getelementptr.ll | 16 +- .../multiple-uses-load-bitcast-select.ll | 16 -- llvm/test/Transforms/InstCombine/objsize.ll | 6 +- .../Transforms/InstCombine/select-load.ll | 14 +- .../InstCombine/shift-amount-reassociation.ll | 2 +- .../test/Transforms/InstCombine/vscale_gep.ll | 13 +- 13 files changed, 163 insertions(+), 87 deletions(-) create mode 100644 llvm/test/Transforms/InstCombine/dead-alloc-elim.ll diff --git a/clang/test/Misc/loop-opt-setup.c b/clang/test/Misc/loop-opt-setup.c index 01643e6073b56..c1c620e52200d 100644 --- a/clang/test/Misc/loop-opt-setup.c +++ b/clang/test/Misc/loop-opt-setup.c @@ -15,7 +15,7 @@ int foo(void) { // CHECK-NOT: br i1 void Helper(void) { - const int *nodes[5]; + const int *nodes[5] = {0}; int num_active = 5; while (num_active) diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index aa7119b005013..83ebf9e402c06 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3310,11 +3310,6 @@ static bool isAllocSiteRemovable(Instruction *AI, } } - if (isRemovableWrite(*cast<CallBase>(I), PI, TLI)) { - Users.emplace_back(I); - continue; - } - if (Family && getFreedOperand(cast<CallBase>(I), &TLI) == PI && getAllocationFamily(I, &TLI) == Family) { Users.emplace_back(I); @@ -3328,6 +3323,12 @@ static bool isAllocSiteRemovable(Instruction *AI, continue; } + if (!isRefSet(Access) && isRemovableWrite(*cast<CallBase>(I), PI, TLI)) { + Access |= ModRefInfo::Mod; + Users.emplace_back(I); + continue; + } + return false; case Instruction::Store: { @@ -3343,7 +3344,7 @@ static bool isAllocSiteRemovable(Instruction *AI, case Instruction::Load: { LoadInst *LI = cast<LoadInst>(I); - if (LI->isVolatile() || LI->getPointerOperand() != LI) + if (LI->isVolatile() || LI->getPointerOperand() != PI) return false; if (isModSet(Access)) return false; diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll index 8824ae48417b0..26e0552886814 100644 --- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -364,20 +364,8 @@ define <2 x i1> @and_ne_with_diff_one_splatvec(<2 x i32> %x) { define void @simplify_before_foldAndOfICmps(ptr %p) { ; CHECK-LABEL: @simplify_before_foldAndOfICmps( -; CHECK-NEXT: [[A8:%.*]] = alloca i16, align 2 -; CHECK-NEXT: [[L7:%.*]] = load i16, ptr [[A8]], align 2 -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i16 [[L7]], -1 -; CHECK-NEXT: [[B11:%.*]] = zext i1 [[TMP1]] to i16 -; CHECK-NEXT: [[C10:%.*]] = icmp ugt i16 [[L7]], [[B11]] -; CHECK-NEXT: [[C7:%.*]] = icmp slt i16 [[L7]], 0 -; CHECK-NEXT: [[C3:%.*]] = and i1 [[C7]], [[C10]] -; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[C10]], true -; CHECK-NEXT: [[C18:%.*]] = or i1 [[C7]], [[TMP2]] -; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[C3]] to i64 -; CHECK-NEXT: [[G26:%.*]] = getelementptr i1, ptr null, i64 [[TMP3]] -; CHECK-NEXT: store i16 [[L7]], ptr [[P:%.*]], align 2 -; CHECK-NEXT: store i1 [[C18]], ptr [[P]], align 1 -; CHECK-NEXT: store ptr [[G26]], ptr [[P]], align 8 +; CHECK-NEXT: store i1 true, ptr [[P:%.*]], align 1 +; CHECK-NEXT: store ptr null, ptr [[P]], align 8 ; CHECK-NEXT: ret void ; %A8 = alloca i16 diff --git a/llvm/test/Transforms/InstCombine/apint-shift.ll b/llvm/test/Transforms/InstCombine/apint-shift.ll index 3cc530bdbd021..d81f14a30cd99 100644 --- a/llvm/test/Transforms/InstCombine/apint-shift.ll +++ b/llvm/test/Transforms/InstCombine/apint-shift.ll @@ -564,7 +564,7 @@ define i40 @test26(i40 %A) { ; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9880 define i177 @ossfuzz_9880(i177 %X) { ; CHECK-LABEL: @ossfuzz_9880( -; CHECK-NEXT: ret i177 0 +; CHECK-NEXT: ret i177 poison ; %A = alloca i177 %L1 = load i177, ptr %A diff --git a/llvm/test/Transforms/InstCombine/call-cast-target.ll b/llvm/test/Transforms/InstCombine/call-cast-target.ll index 2cedc6c81d735..d18b70ff5ce9b 100644 --- a/llvm/test/Transforms/InstCombine/call-cast-target.ll +++ b/llvm/test/Transforms/InstCombine/call-cast-target.ll @@ -112,11 +112,7 @@ declare i1 @fn5(ptr byval({ i32, i32 }) align 4 %r) define i1 @test5() { ; CHECK-LABEL: define i1 @test5() { -; CHECK-NEXT: [[TMP1:%.*]] = alloca { i32, i32 }, align 4 -; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4 -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP1]], i32 4 -; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 -; CHECK-NEXT: [[TMP5:%.*]] = call i1 @fn5(i32 [[TMP2]], i32 [[TMP4]]) +; CHECK-NEXT: [[TMP5:%.*]] = call i1 @fn5(i32 undef, i32 undef) ; CHECK-NEXT: ret i1 [[TMP5]] ; %1 = alloca { i32, i32 }, align 4 diff --git a/llvm/test/Transforms/InstCombine/dead-alloc-elim.ll b/llvm/test/Transforms/InstCombine/dead-alloc-elim.ll new file mode 100644 index 0000000000000..b135f76f709f1 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/dead-alloc-elim.ll @@ -0,0 +1,140 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +declare noalias ptr @calloc(i32, i32) nounwind allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" +declare void @free(ptr) allockind("free") "alloc-family"="malloc" + +; Test load from uninitialized alloca - should be removed and replaced with undef +define i32 @test_load_uninitialized_alloca() { +; CHECK-LABEL: @test_load_uninitialized_alloca( +; CHECK-NEXT: ret i32 undef +; + %a = alloca i32 + %v = load i32, ptr %a + ret i32 %v +} + +; Test load from zero-initialized malloc - should be removed and replaced with zero +define i32 @test_load_zero_initialized_malloc() { +; CHECK-LABEL: @test_load_zero_initialized_malloc( +; CHECK-NEXT: ret i32 0 +; + %a = call ptr @calloc(i32 1, i32 4) + %v = load i32, ptr %a + call void @free(ptr %a) + ret i32 %v +} + +; Test memcpy from uninitialized source - should be removed +define void @test_memcpy_from_uninitialized_alloca(ptr %dest) { +; CHECK-LABEL: @test_memcpy_from_uninitialized_alloca( +; CHECK-NEXT: ret void +; + %src = alloca i32, align 1 + call void @llvm.memcpy.p0.p0.i32(ptr %src, ptr %src, i32 4, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr %dest, ptr %src, i32 4, i1 false) + ret void +} + +; Test memcpy from zeroed source - should transform to memset with zero +define void @test_memcpy_from_uninitialized_calloc(ptr %dest) { +; CHECK-LABEL: @test_memcpy_from_uninitialized_calloc( +; CHECK-NEXT: call void @llvm.memset.p0.i32(ptr noundef nonnull align 1 dereferenceable(16) [[DEST:%.*]], i8 0, i32 16, i1 false) +; CHECK-NEXT: ret void +; + %src = call ptr @calloc(i32 1, i32 16) + call void @llvm.memcpy.p0.p0.i32(ptr %dest, ptr %src, i32 16, i1 false) + call void @free(ptr %src) + ret void +} + +; Test mixed read/write pattern - should not be removable due to write before read +define i32 @test_write_then_read_alloca() { +; CHECK-LABEL: @test_write_then_read_alloca( +; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 +; CHECK-NEXT: store i8 42, ptr [[A]], align 1 +; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[A]], align 4 +; CHECK-NEXT: ret i32 [[V]] +; + %a = alloca i32 + store i8 42, ptr %a + %v = load i32, ptr %a + ret i32 %v +} + +; Test read then write pattern - should not be removable due to conflicting access +define void @test_read_then_write_alloca() { +; CHECK-LABEL: @test_read_then_write_alloca( +; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[A]], align 4 +; CHECK-NEXT: [[V8:%.*]] = trunc i32 [[V]] to i8 +; CHECK-NEXT: store i8 [[V8]], ptr [[A]], align 1 +; CHECK-NEXT: ret void +; + %a = alloca i32 + %v = load i32, ptr %a + %v8 = trunc i32 %v to i8 + store i8 %v8, ptr %a + ret void +} + +; Test load through GEP from uninitialized alloca +define i8 @test_load_gep_uninitialized_alloca() { +; CHECK-LABEL: @test_load_gep_uninitialized_alloca( +; CHECK-NEXT: ret i8 undef +; + %a = alloca [4 x i8] + %gep = getelementptr [4 x i8], ptr %a, i32 0, i32 2 + %v = load i8, ptr %gep + ret i8 %v +} + +; Test load through bitcast from uninitialized alloca +define i16 @test_load_bitcast_uninitialized_alloca() { +; CHECK-LABEL: @test_load_bitcast_uninitialized_alloca( +; CHECK-NEXT: ret i16 undef +; + %a = alloca i32 + %bc = bitcast ptr %a to ptr + %v = load i16, ptr %bc + ret i16 %v +} + +; Test memmove from zero-initialized malloc +define void @test_memmove_from_zero_initialized_malloc(ptr %dest) { +; CHECK-LABEL: @test_memmove_from_zero_initialized_malloc( +; CHECK-NEXT: call void @llvm.memset.p0.i32(ptr noundef nonnull align 1 dereferenceable(32) [[DEST:%.*]], i8 0, i32 32, i1 false) +; CHECK-NEXT: ret void +; + %src = call ptr @calloc(i32 8, i32 4) + call void @llvm.memmove.p0.p0.i32(ptr %dest, ptr %src, i32 32, i1 false) + call void @free(ptr %src) + ret void +} + +; Test multiple loads from same uninitialized alloca +define { i32, i32 } @test_multiple_loads_uninitialized_alloca() { +; CHECK-LABEL: @test_multiple_loads_uninitialized_alloca( +; CHECK-NEXT: ret { i32, i32 } undef +; + %a = alloca [2 x i32] + %gep1 = getelementptr [2 x i32], ptr %a, i32 0, i32 0 + %gep2 = getelementptr [2 x i32], ptr %a, i32 0, i32 1 + %v1 = load i32, ptr %gep1 + %v2 = load i32, ptr %gep2 + %ret = insertvalue { i32, i32 } { i32 undef, i32 poison }, i32 %v1, 0 + %ret2 = insertvalue { i32, i32 } %ret, i32 %v2, 1 + ret { i32, i32 } %ret2 +} + +; Test that volatile operations prevent removal +define i32 @test_volatile_load_prevents_removal() { +; CHECK-LABEL: @test_volatile_load_prevents_removal( +; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[V:%.*]] = load volatile i32, ptr [[A]], align 4 +; CHECK-NEXT: ret i32 [[V]] +; + %a = alloca i32 + %v = load volatile i32, ptr %a + ret i32 %v +} diff --git a/llvm/test/Transforms/InstCombine/fp-ret-bitcast.ll b/llvm/test/Transforms/InstCombine/fp-ret-bitcast.ll index 15eb3e15ea44a..12a554081ca79 100644 --- a/llvm/test/Transforms/InstCombine/fp-ret-bitcast.ll +++ b/llvm/test/Transforms/InstCombine/fp-ret-bitcast.ll @@ -15,10 +15,8 @@ target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:1 define void @bork() nounwind { ; CHECK-LABEL: @bork( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[COLOR:%.*]] = alloca ptr, align 8 -; CHECK-NEXT: [[TMP103:%.*]] = load ptr, ptr [[COLOR]], align 4 ; CHECK-NEXT: [[TMP105:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_81", align 4 -; CHECK-NEXT: [[TMP107:%.*]] = call float @objc_msgSend_fpret(ptr [[TMP103]], ptr [[TMP105]]) #[[ATTR0:[0-9]+]] +; CHECK-NEXT: [[TMP107:%.*]] = call float @objc_msgSend_fpret(ptr undef, ptr [[TMP105]]) #[[ATTR0:[0-9]+]] ; CHECK-NEXT: br label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/InstCombine/getelementptr.ll b/llvm/test/Transforms/InstCombine/getelementptr.ll index 61236df80bfa6..19466e48fb73c 100644 --- a/llvm/test/Transforms/InstCombine/getelementptr.ll +++ b/llvm/test/Transforms/InstCombine/getelementptr.ll @@ -582,9 +582,7 @@ define i32 @test20_as1(ptr addrspace(1) %P, i32 %A, i32 %B) { define i32 @test21() { ; CHECK-LABEL: @test21( -; CHECK-NEXT: [[PBOB1:%.*]] = alloca [[INTSTRUCT:%.*]], align 8 -; CHECK-NEXT: [[RVAL:%.*]] = load i32, ptr [[PBOB1]], align 4 -; CHECK-NEXT: ret i32 [[RVAL]] +; CHECK-NEXT: ret i32 undef ; %pbob1 = alloca %intstruct %pbob2 = getelementptr %intstruct, ptr %pbob1 @@ -657,11 +655,6 @@ define i1 @test26(ptr %arr) { define i32 @test27(ptr %to, ptr %from) { ; CHECK-LABEL: @test27( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[FROM_ADDR:%.*]] = alloca ptr, align 8 -; CHECK-NEXT: [[T344:%.*]] = load ptr, ptr [[FROM_ADDR]], align 8 -; CHECK-NEXT: [[T348:%.*]] = getelementptr i8, ptr [[T344]], i64 24 -; CHECK-NEXT: [[T351:%.*]] = load i32, ptr [[T348]], align 8 -; CHECK-NEXT: [[T360:%.*]] = call i32 asm sideeffect "...", "=r,ir,*m,i,0,~{dirflag},~{fpsr},~{flags}"(i32 [[T351]], ptr elementtype([[STRUCT___LARGE_STRUCT:%.*]]) null, i32 -14, i32 0) #[[ATTR0:[0-9]+]] ; CHECK-NEXT: unreachable ; entry: @@ -685,7 +678,7 @@ define i32 @test28() nounwind { ; CHECK-LABEL: @test28( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[ORIENTATIONS:%.*]] = alloca [1 x [1 x %struct.x]], align 8 -; CHECK-NEXT: [[T3:%.*]] = call i32 @puts(ptr noundef nonnull dereferenceable(1) @.str) #[[ATTR0]] +; CHECK-NEXT: [[T3:%.*]] = call i32 @puts(ptr noundef nonnull dereferenceable(1) @.str) #[[ATTR0:[0-9]+]] ; CHECK-NEXT: [[T45:%.*]] = getelementptr inbounds nuw i8, ptr [[ORIENTATIONS]], i64 1 ; CHECK-NEXT: br label [[BB10:%.*]] ; CHECK: bb10: @@ -1345,10 +1338,7 @@ declare noalias ptr @malloc(i64) nounwind allockind("alloc,uninitialized") alloc define i32 @test_gep_bitcast_malloc(ptr %a) { ; CHECK-LABEL: @test_gep_bitcast_malloc( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = call noalias dereferenceable_or_null(16) ptr @malloc(i64 16) -; CHECK-NEXT: [[G3:%.*]] = getelementptr i8, ptr [[CALL]], i64 12 -; CHECK-NEXT: [[A_C:%.*]] = load i32, ptr [[G3]], align 4 -; CHECK-NEXT: ret i32 [[A_C]] +; CHECK-NEXT: ret i32 undef ; entry: %call = call noalias ptr @malloc(i64 16) #2 diff --git a/llvm/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll b/llvm/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll index 38fca0314ae11..a0f4f571a4b93 100644 --- a/llvm/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll +++ b/llvm/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll @@ -3,14 +3,6 @@ define void @PR35618(ptr %st1, ptr %st2) { ; CHECK-LABEL: @PR35618( -; CHECK-NEXT: [[Y1:%.*]] = alloca double, align 8 -; CHECK-NEXT: [[Z1:%.*]] = alloca double, align 8 -; CHECK-NEXT: [[LD1:%.*]] = load double, ptr [[Y1]], align 8 -; CHECK-NEXT: [[LD2:%.*]] = load double, ptr [[Z1]], align 8 -; CHECK-NEXT: [[TMP:%.*]] = fcmp olt double [[LD1]], [[LD2]] -; CHECK-NEXT: [[TMP12_V:%.*]] = select i1 [[TMP]], double [[LD1]], double [[LD2]] -; CHECK-NEXT: store double [[TMP12_V]], ptr [[ST1:%.*]], align 8 -; CHECK-NEXT: store double [[TMP12_V]], ptr [[ST2:%.*]], align 8 ; CHECK-NEXT: ret void ; %y1 = alloca double @@ -27,14 +19,6 @@ define void @PR35618(ptr %st1, ptr %st2) { define void @PR35618_asan(ptr %st1, ptr %st2) sanitize_address { ; CHECK-LABEL: @PR35618_asan( -; CHECK-NEXT: [[Y1:%.*]] = alloca double, align 8 -; CHECK-NEXT: [[Z1:%.*]] = alloca double, align 8 -; CHECK-NEXT: [[LD1:%.*]] = load double, ptr [[Y1]], align 8 -; CHECK-NEXT: [[LD2:%.*]] = load double, ptr [[Z1]], align 8 -; CHECK-NEXT: [[TMP:%.*]] = fcmp olt double [[LD1]], [[LD2]] -; CHECK-NEXT: [[TMP12_V:%.*]] = select i1 [[TMP]], double [[LD1]], double [[LD2]] -; CHECK-NEXT: store double [[TMP12_V]], ptr [[ST1:%.*]], align 8 -; CHECK-NEXT: store double [[TMP12_V]], ptr [[ST2:%.*]], align 8 ; CHECK-NEXT: ret void ; %y1 = alloca double diff --git a/llvm/test/Transforms/InstCombine/objsize.ll b/llvm/test/Transforms/InstCombine/objsize.ll index 1c33412303c19..f113616a478ab 100644 --- a/llvm/test/Transforms/InstCombine/objsize.ll +++ b/llvm/test/Transforms/InstCombine/objsize.ll @@ -17,13 +17,11 @@ define i32 @foo() nounwind { define ptr @bar() nounwind { ; CHECK-LABEL: @bar( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[RETVAL:%.*]] = alloca ptr, align 4 ; CHECK-NEXT: br i1 true, label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] ; CHECK: cond.true: -; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[RETVAL]], align 4 -; CHECK-NEXT: ret ptr [[TMP0]] +; CHECK-NEXT: ret ptr undef ; CHECK: cond.false: -; CHECK-NEXT: ret ptr poison +; CHECK-NEXT: ret ptr undef ; entry: %retval = alloca ptr diff --git a/llvm/test/Transforms/InstCombine/select-load.ll b/llvm/test/Transforms/InstCombine/select-load.ll index 36883423aea36..6012452a48da9 100644 --- a/llvm/test/Transforms/InstCombine/select-load.ll +++ b/llvm/test/Transforms/InstCombine/select-load.ll @@ -7,12 +7,7 @@ target triple = "x86_64-grtev4-linux-gnu" define i32 @test_plain(i1 %f) { ; CHECK-LABEL: @test_plain( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[A:%.*]] = alloca i32, align 8 -; CHECK-NEXT: [[B:%.*]] = alloca i32, align 8 -; CHECK-NEXT: [[A_VAL:%.*]] = load i32, ptr [[A]], align 8 -; CHECK-NEXT: [[B_VAL:%.*]] = load i32, ptr [[B]], align 8 -; CHECK-NEXT: [[L:%.*]] = select i1 [[F:%.*]], i32 [[A_VAL]], i32 [[B_VAL]] -; CHECK-NEXT: ret i32 [[L]] +; CHECK-NEXT: ret i32 undef ; entry: %a = alloca i32, align 8 @@ -85,12 +80,7 @@ entry: define i32 @test_msan(i1 %f) sanitize_memory { ; CHECK-LABEL: @test_msan( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[A:%.*]] = alloca i32, align 8 -; CHECK-NEXT: [[B:%.*]] = alloca i32, align 8 -; CHECK-NEXT: [[A_VAL:%.*]] = load i32, ptr [[A]], align 8 -; CHECK-NEXT: [[B_VAL:%.*]] = load i32, ptr [[B]], align 8 -; CHECK-NEXT: [[L:%.*]] = select i1 [[F:%.*]], i32 [[A_VAL]], i32 [[B_VAL]] -; CHECK-NEXT: ret i32 [[L]] +; CHECK-NEXT: ret i32 undef ; entry: %a = alloca i32, align 8 diff --git a/llvm/test/Transforms/InstCombine/shift-amount-reassociation.ll b/llvm/test/Transforms/InstCombine/shift-amount-reassociation.ll index b4c606f037d56..f251dc282f4ca 100644 --- a/llvm/test/Transforms/InstCombine/shift-amount-reassociation.ll +++ b/llvm/test/Transforms/InstCombine/shift-amount-reassociation.ll @@ -158,7 +158,7 @@ define i32 @t11_shl_nsw_flag_preservation(i32 %x, i32 %y) { @X = external global i32 define i64 @constantexpr() { ; CHECK-LABEL: @constantexpr( -; CHECK-NEXT: ret i64 0 +; CHECK-NEXT: ret i64 poison ; %A = alloca i64 %L = load i64, ptr %A diff --git a/llvm/test/Transforms/InstCombine/vscale_gep.ll b/llvm/test/Transforms/InstCombine/vscale_gep.ll index 371ee71e45f23..2f5e2a074ea5f 100644 --- a/llvm/test/Transforms/InstCombine/vscale_gep.ll +++ b/llvm/test/Transforms/InstCombine/vscale_gep.ll @@ -43,10 +43,7 @@ define void @gep_bitcast(ptr %p) { ; This test is to verify 'inbounds' is added when it's valid to accumulate constant offset. define i32 @gep_alloca_inbounds_vscale_zero() { ; CHECK-LABEL: @gep_alloca_inbounds_vscale_zero( -; CHECK-NEXT: [[A:%.*]] = alloca <vscale x 4 x i32>, align 16 -; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 8 -; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[TMP]], align 4 -; CHECK-NEXT: ret i32 [[LOAD]] +; CHECK-NEXT: ret i32 undef ; %a = alloca <vscale x 4 x i32> %tmp = getelementptr <vscale x 4 x i32>, ptr %a, i32 0, i32 2 @@ -57,13 +54,7 @@ define i32 @gep_alloca_inbounds_vscale_zero() { ; This test is to verify 'inbounds' is not added when a constant offset can not be determined at compile-time. define i32 @gep_alloca_inbounds_vscale_nonzero() { ; CHECK-LABEL: @gep_alloca_inbounds_vscale_nonzero( -; CHECK-NEXT: [[A:%.*]] = alloca <vscale x 4 x i32>, align 16 -; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP2:%.*]] = shl i64 [[TMP1]], 4 -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP2]] -; CHECK-NEXT: [[TMP:%.*]] = getelementptr i8, ptr [[TMP3]], i64 8 -; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[TMP]], align 4 -; CHECK-NEXT: ret i32 [[LOAD]] +; CHECK-NEXT: ret i32 undef ; %a = alloca <vscale x 4 x i32> %tmp = getelementptr <vscale x 4 x i32>, ptr %a, i32 1, i32 2 >From c088c0c52080348c0c5cb6fdb52f3e9bfcb3e816 Mon Sep 17 00:00:00 2001 From: Jameson Nash <vtjn...@gmail.com> Date: Thu, 12 Jun 2025 20:43:27 +0000 Subject: [PATCH 3/9] clang-format --- .../InstCombine/InstructionCombining.cpp | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 83ebf9e402c06..f75e76f80cb0e 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3217,8 +3217,7 @@ static bool isRemovableWrite(CallBase &CB, Value *UsedV, static bool isAllocSiteRemovable(Instruction *AI, SmallVectorImpl<WeakTrackingVH> &Users, - const TargetLibraryInfo &TLI, - bool KnowInit) { + const TargetLibraryInfo &TLI, bool KnowInit) { SmallVector<Instruction*, 4> Worklist; const std::optional<StringRef> Family = getAllocationFamily(AI, &TLI); Worklist.push_back(AI); @@ -3287,12 +3286,14 @@ static bool isAllocSiteRemovable(Instruction *AI, MemIntrinsic *MI = cast<MemIntrinsic>(II); if (MI->isVolatile()) return false; - // Note: this could also be ModRef, but we can still interpret that as just Mod in that case. - ModRefInfo NewAccess = MI->getRawDest() == PI ? ModRefInfo::Mod : ModRefInfo::Ref; + // Note: this could also be ModRef, but we can still interpret that + // as just Mod in that case. + ModRefInfo NewAccess = + MI->getRawDest() == PI ? ModRefInfo::Mod : ModRefInfo::Ref; if ((Access & ~NewAccess) != ModRefInfo::NoModRef) return false; Access |= NewAccess; - } + } [[fallthrough]]; case Intrinsic::assume: case Intrinsic::invariant_start: @@ -3323,7 +3324,8 @@ static bool isAllocSiteRemovable(Instruction *AI, continue; } - if (!isRefSet(Access) && isRemovableWrite(*cast<CallBase>(I), PI, TLI)) { + if (!isRefSet(Access) && + isRemovableWrite(*cast<CallBase>(I), PI, TLI)) { Access |= ModRefInfo::Mod; Users.emplace_back(I); continue; @@ -3385,11 +3387,13 @@ Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) { DIB.reset(new DIBuilder(*MI.getModule(), /*AllowUnresolved=*/false)); } - // Determine what getInitialValueOfAllocation would return without actually allocating the result. + // Determine what getInitialValueOfAllocation would return without actually + // allocating the result. bool KnowInitUndef = isa<AllocaInst>(MI); bool KnowInitZero = false; if (!KnowInitUndef) { - Constant *Init = getInitialValueOfAllocation(&MI, &TLI, Type::getInt8Ty(MI.getContext())); + Constant *Init = getInitialValueOfAllocation( + &MI, &TLI, Type::getInt8Ty(MI.getContext())); if (Init) { if (isa<UndefValue>(Init)) KnowInitUndef = true; @@ -3422,10 +3426,10 @@ Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) { if (KnowInitZero && getUnderlyingObject(MTI->getRawDest()) != &MI) { IRBuilderBase::InsertPointGuard Guard(Builder); Builder.SetInsertPoint(MTI); - auto *M = Builder.CreateMemSet(MTI->getRawDest(), - ConstantInt::get(Type::getInt8Ty(MI.getContext()), 0), - MTI->getLength(), - MTI->getDestAlign()); + auto *M = Builder.CreateMemSet( + MTI->getRawDest(), + ConstantInt::get(Type::getInt8Ty(MI.getContext()), 0), + MTI->getLength(), MTI->getDestAlign()); M->copyMetadata(*MTI, LLVMContext::MD_DIAssignID); } } @@ -3454,7 +3458,8 @@ Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) { Constant *Replace; if (isa<LoadInst>(I)) { assert(KnowInitZero || KnowInitUndef); - Replace = KnowInitUndef ? UndefValue::get(I->getType()) : Constant::getNullValue(I->getType()); + Replace = KnowInitUndef ? UndefValue::get(I->getType()) + : Constant::getNullValue(I->getType()); } else Replace = PoisonValue::get(I->getType()); replaceInstUsesWith(*I, Replace); >From 7e5c60428c2f3caf099c9f02162203305adea6d8 Mon Sep 17 00:00:00 2001 From: Jameson Nash <vtjn...@gmail.com> Date: Thu, 12 Jun 2025 17:15:49 -0400 Subject: [PATCH 4/9] fix tests (thanks Claude) --- .../Transforms/InstCombine/and-or-icmps.ll | 18 ++++++++++++---- .../Transforms/InstCombine/apint-shift.ll | 5 ++--- .../InstCombine/call-cast-target.ll | 14 +++++++------ .../Transforms/InstCombine/fp-ret-bitcast.ll | 9 ++++---- .../Transforms/InstCombine/getelementptr.ll | 20 +++++++++++------- .../multiple-uses-load-bitcast-select.ll | 21 +++++++++++++------ llvm/test/Transforms/InstCombine/objsize.ll | 9 ++++---- .../Transforms/InstCombine/select-load.ll | 18 +++++++++------- .../InstCombine/shift-amount-reassociation.ll | 7 +++---- .../test/Transforms/InstCombine/vscale_gep.ll | 21 ++++++++++++------- 10 files changed, 86 insertions(+), 56 deletions(-) diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll index 26e0552886814..6fb94a648f368 100644 --- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -362,13 +362,23 @@ define <2 x i1> @and_ne_with_diff_one_splatvec(<2 x i32> %x) { ; on an 'and' that should have been killed. It's not obvious ; why, but removing anything hides the bug, hence the long test. -define void @simplify_before_foldAndOfICmps(ptr %p) { +define void @simplify_before_foldAndOfICmps(ptr %p, ptr %A8) { ; CHECK-LABEL: @simplify_before_foldAndOfICmps( -; CHECK-NEXT: store i1 true, ptr [[P:%.*]], align 1 -; CHECK-NEXT: store ptr null, ptr [[P]], align 8 +; CHECK-NEXT: [[L7:%.*]] = load i16, ptr [[A8:%.*]], align 2 +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i16 [[L7]], -1 +; CHECK-NEXT: [[B11:%.*]] = zext i1 [[TMP1]] to i16 +; CHECK-NEXT: [[C10:%.*]] = icmp ugt i16 [[L7]], [[B11]] +; CHECK-NEXT: [[C7:%.*]] = icmp slt i16 [[L7]], 0 +; CHECK-NEXT: [[C3:%.*]] = and i1 [[C7]], [[C10]] +; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[C10]], true +; CHECK-NEXT: [[C18:%.*]] = or i1 [[C7]], [[TMP2]] +; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[C3]] to i64 +; CHECK-NEXT: [[G26:%.*]] = getelementptr i1, ptr null, i64 [[TMP3]] +; CHECK-NEXT: store i16 [[L7]], ptr [[P:%.*]], align 2 +; CHECK-NEXT: store i1 [[C18]], ptr [[P]], align 1 +; CHECK-NEXT: store ptr [[G26]], ptr [[P]], align 8 ; CHECK-NEXT: ret void ; - %A8 = alloca i16 %L7 = load i16, ptr %A8 %G21 = getelementptr i16, ptr %A8, i8 -1 %B11 = udiv i16 %L7, -1 diff --git a/llvm/test/Transforms/InstCombine/apint-shift.ll b/llvm/test/Transforms/InstCombine/apint-shift.ll index d81f14a30cd99..4dd0811bb7ecb 100644 --- a/llvm/test/Transforms/InstCombine/apint-shift.ll +++ b/llvm/test/Transforms/InstCombine/apint-shift.ll @@ -562,11 +562,10 @@ define i40 @test26(i40 %A) { ; OSS-Fuzz #9880 ; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9880 -define i177 @ossfuzz_9880(i177 %X) { +define i177 @ossfuzz_9880(i177 %X, ptr %A) { ; CHECK-LABEL: @ossfuzz_9880( -; CHECK-NEXT: ret i177 poison +; CHECK-NEXT: ret i177 0 ; - %A = alloca i177 %L1 = load i177, ptr %A %B = or i177 0, -1 %B5 = udiv i177 %L1, %B diff --git a/llvm/test/Transforms/InstCombine/call-cast-target.ll b/llvm/test/Transforms/InstCombine/call-cast-target.ll index d18b70ff5ce9b..2f4b4ad2409e6 100644 --- a/llvm/test/Transforms/InstCombine/call-cast-target.ll +++ b/llvm/test/Transforms/InstCombine/call-cast-target.ll @@ -110,15 +110,17 @@ entry: declare i1 @fn5(ptr byval({ i32, i32 }) align 4 %r) -define i1 @test5() { -; CHECK-LABEL: define i1 @test5() { -; CHECK-NEXT: [[TMP5:%.*]] = call i1 @fn5(i32 undef, i32 undef) +define i1 @test5(ptr %ptr) { +; CHECK-LABEL: define i1 @test5(ptr %ptr) { +; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[PTR:%.*]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR]], i32 4 +; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 +; CHECK-NEXT: [[TMP5:%.*]] = call i1 @fn5(i32 [[TMP2]], i32 [[TMP4]]) ; CHECK-NEXT: ret i1 [[TMP5]] ; - %1 = alloca { i32, i32 }, align 4 - %2 = getelementptr inbounds { i32, i32 }, ptr %1, i32 0, i32 0 + %2 = getelementptr inbounds { i32, i32 }, ptr %ptr, i32 0, i32 0 %3 = load i32, ptr %2, align 4 - %4 = getelementptr inbounds { i32, i32 }, ptr %1, i32 0, i32 1 + %4 = getelementptr inbounds { i32, i32 }, ptr %ptr, i32 0, i32 1 %5 = load i32, ptr %4, align 4 %6 = call i1 @fn5(i32 %3, i32 %5) ret i1 %6 diff --git a/llvm/test/Transforms/InstCombine/fp-ret-bitcast.ll b/llvm/test/Transforms/InstCombine/fp-ret-bitcast.ll index 12a554081ca79..3daee254227ec 100644 --- a/llvm/test/Transforms/InstCombine/fp-ret-bitcast.ll +++ b/llvm/test/Transforms/InstCombine/fp-ret-bitcast.ll @@ -12,18 +12,17 @@ target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:1 @"\01L_OBJC_METH_VAR_NAME_112" = internal global [15 x i8] c"whiteComponent\00", section "__TEXT,__cstring,cstring_literals" @"\01L_OBJC_SELECTOR_REFERENCES_81" = internal global ptr @"\01L_OBJC_METH_VAR_NAME_112", section "__OBJC,__message_refs,literal_pointers,no_dead_strip" -define void @bork() nounwind { -; CHECK-LABEL: @bork( +define void @bork(ptr %color, ptr %color.466) nounwind { +; CHECK-LABEL: @bork(ptr %color, ptr %color.466) { ; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP103:%.*]] = load ptr, ptr [[COLOR:%.*]], align 4 ; CHECK-NEXT: [[TMP105:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_81", align 4 -; CHECK-NEXT: [[TMP107:%.*]] = call float @objc_msgSend_fpret(ptr undef, ptr [[TMP105]]) #[[ATTR0:[0-9]+]] +; CHECK-NEXT: [[TMP107:%.*]] = call float @objc_msgSend_fpret(ptr [[TMP103]], ptr [[TMP105]]) #[[ATTR0:[0-9]+]] ; CHECK-NEXT: br label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: ret void ; entry: - %color = alloca ptr - %color.466 = alloca ptr %tmp103 = load ptr, ptr %color, align 4 store ptr %tmp103, ptr %color.466, align 4 %tmp105 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_81", align 4 diff --git a/llvm/test/Transforms/InstCombine/getelementptr.ll b/llvm/test/Transforms/InstCombine/getelementptr.ll index 19466e48fb73c..c90ba7f43f50f 100644 --- a/llvm/test/Transforms/InstCombine/getelementptr.ll +++ b/llvm/test/Transforms/InstCombine/getelementptr.ll @@ -580,11 +580,11 @@ define i32 @test20_as1(ptr addrspace(1) %P, i32 %A, i32 %B) { } -define i32 @test21() { +define i32 @test21(ptr %pbob1) { ; CHECK-LABEL: @test21( -; CHECK-NEXT: ret i32 undef +; CHECK-NEXT: [[RVAL:%.*]] = load i32, ptr [[PBOB1:%.*]], align 4 +; CHECK-NEXT: ret i32 [[RVAL]] ; - %pbob1 = alloca %intstruct %pbob2 = getelementptr %intstruct, ptr %pbob1 %rval = load i32, ptr %pbob2 ret i32 %rval @@ -652,13 +652,16 @@ define i1 @test26(ptr %arr) { %struct.siginfo_t = type { i32, i32, i32, { { i32, i32, [0 x i8], %struct.sigval_t, i32 }, [88 x i8] } } %struct.sigval_t = type { ptr } -define i32 @test27(ptr %to, ptr %from) { +define i32 @test27(ptr %to, ptr %from, ptr %from_addr) { ; CHECK-LABEL: @test27( ; CHECK-NEXT: entry: +; CHECK-NEXT: [[T344:%.*]] = load ptr, ptr [[FROM_ADDR:%.*]], align 8 +; CHECK-NEXT: [[T348:%.*]] = getelementptr i8, ptr [[T344]], i64 24 +; CHECK-NEXT: [[T351:%.*]] = load i32, ptr [[T348]], align 8 +; CHECK-NEXT: [[T360:%.*]] = call i32 asm sideeffect "...", "=r,ir,*m,i,0,~{dirflag},~{fpsr},~{flags}"(i32 [[T351]], ptr elementtype([[STRUCT___LARGE_STRUCT:%.*]]) null, i32 -14, i32 0) #[[ATTR0:[0-9]+]] ; CHECK-NEXT: unreachable ; entry: - %from_addr = alloca ptr %t344 = load ptr, ptr %from_addr, align 8 %t345 = getelementptr %struct.siginfo_t, ptr %t344, i32 0, i32 3 %t346 = getelementptr { { i32, i32, [0 x i8], %struct.sigval_t, i32 }, [88 x i8] }, ptr %t345, i32 0, i32 0 @@ -1335,13 +1338,14 @@ define ptr @D98588(ptr %c1, i64 %offset) { declare noalias ptr @malloc(i64) nounwind allockind("alloc,uninitialized") allocsize(0) -define i32 @test_gep_bitcast_malloc(ptr %a) { +define i32 @test_gep_bitcast_malloc(ptr %a, ptr %call) { ; CHECK-LABEL: @test_gep_bitcast_malloc( ; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32 undef +; CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds i8, ptr [[CALL:%.*]], i64 12 +; CHECK-NEXT: [[A_C:%.*]] = load i32, ptr [[G3]], align 4 +; CHECK-NEXT: ret i32 [[A_C]] ; entry: - %call = call noalias ptr @malloc(i64 16) #2 %g3 = getelementptr %struct.A, ptr %call, i32 0, i32 2 %a_c = load i32, ptr %g3, align 4 ret i32 %a_c diff --git a/llvm/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll b/llvm/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll index a0f4f571a4b93..594ff091f5651 100644 --- a/llvm/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll +++ b/llvm/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll @@ -1,12 +1,16 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -S -data-layout="E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64" | FileCheck %s -define void @PR35618(ptr %st1, ptr %st2) { +define void @PR35618(ptr %st1, ptr %st2, ptr %y1, ptr %z1) { ; CHECK-LABEL: @PR35618( +; CHECK-NEXT: [[LD1:%.*]] = load double, ptr [[Y1:%.*]], align 8 +; CHECK-NEXT: [[LD2:%.*]] = load double, ptr [[Z1:%.*]], align 8 +; CHECK-NEXT: [[TMP:%.*]] = fcmp olt double [[LD1]], [[LD2]] +; CHECK-NEXT: [[TMP12_V:%.*]] = select i1 [[TMP]], double [[LD1]], double [[LD2]] +; CHECK-NEXT: store double [[TMP12_V]], ptr [[ST1:%.*]], align 8 +; CHECK-NEXT: store double [[TMP12_V]], ptr [[ST2:%.*]], align 8 ; CHECK-NEXT: ret void ; - %y1 = alloca double - %z1 = alloca double %ld1 = load double, ptr %y1 %ld2 = load double, ptr %z1 %tmp = fcmp olt double %ld1, %ld2 @@ -17,12 +21,17 @@ define void @PR35618(ptr %st1, ptr %st2) { ret void } -define void @PR35618_asan(ptr %st1, ptr %st2) sanitize_address { +define void @PR35618_asan(ptr %st1, ptr %st2, ptr %y1, ptr %z1) sanitize_address { ; CHECK-LABEL: @PR35618_asan( +; CHECK-NEXT: [[LD1:%.*]] = load double, ptr [[Y1:%.*]], align 8 +; CHECK-NEXT: [[LD2:%.*]] = load double, ptr [[Z1:%.*]], align 8 +; CHECK-NEXT: [[TMP:%.*]] = fcmp olt double [[LD1]], [[LD2]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP]], ptr [[Y1]], ptr [[Z1]] +; CHECK-NEXT: [[TMP12:%.*]] = load i64, ptr [[SEL]], align 8 +; CHECK-NEXT: store i64 [[TMP12]], ptr [[ST1:%.*]], align 8 +; CHECK-NEXT: store i64 [[TMP12]], ptr [[ST2:%.*]], align 8 ; CHECK-NEXT: ret void ; - %y1 = alloca double - %z1 = alloca double %ld1 = load double, ptr %y1 %ld2 = load double, ptr %z1 %tmp = fcmp olt double %ld1, %ld2 diff --git a/llvm/test/Transforms/InstCombine/objsize.ll b/llvm/test/Transforms/InstCombine/objsize.ll index f113616a478ab..7ef1e9bb9275f 100644 --- a/llvm/test/Transforms/InstCombine/objsize.ll +++ b/llvm/test/Transforms/InstCombine/objsize.ll @@ -14,17 +14,18 @@ define i32 @foo() nounwind { ret i32 %1 } -define ptr @bar() nounwind { +define ptr @bar(ptr %retval) nounwind { ; CHECK-LABEL: @bar( ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 true, label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] ; CHECK: cond.true: -; CHECK-NEXT: ret ptr undef +; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[RETVAL:%.*]], align 8 +; CHECK-NEXT: ret ptr [[TMP1]] ; CHECK: cond.false: -; CHECK-NEXT: ret ptr undef +; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[RETVAL]], align 8 +; CHECK-NEXT: ret ptr [[TMP2]] ; entry: - %retval = alloca ptr %0 = call i32 @llvm.objectsize.i32.p0(ptr @a, i1 false, i1 false, i1 false) %cmp = icmp ne i32 %0, -1 br i1 %cmp, label %cond.true, label %cond.false diff --git a/llvm/test/Transforms/InstCombine/select-load.ll b/llvm/test/Transforms/InstCombine/select-load.ll index 6012452a48da9..5e3182614e9cf 100644 --- a/llvm/test/Transforms/InstCombine/select-load.ll +++ b/llvm/test/Transforms/InstCombine/select-load.ll @@ -4,14 +4,15 @@ target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" target triple = "x86_64-grtev4-linux-gnu" -define i32 @test_plain(i1 %f) { +define i32 @test_plain(i1 %f, ptr %a, ptr %b) { ; CHECK-LABEL: @test_plain( ; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32 undef +; CHECK-NEXT: [[A_VAL:%.*]] = load i32, ptr [[A:%.*]], align 8 +; CHECK-NEXT: [[B_VAL:%.*]] = load i32, ptr [[B:%.*]], align 8 +; CHECK-NEXT: [[L:%.*]] = select i1 [[F:%.*]], i32 [[A_VAL]], i32 [[B_VAL]] +; CHECK-NEXT: ret i32 [[L]] ; entry: - %a = alloca i32, align 8 - %b = alloca i32, align 8 %sel = select i1 %f, ptr %a, ptr %b %l = load i32, ptr %sel, align 8 ret i32 %l @@ -77,14 +78,15 @@ entry: ; Msan just propagates shadow, even if speculated load accesses uninitialized ; value, instrumentation will select shadow of the desired value anyway. -define i32 @test_msan(i1 %f) sanitize_memory { +define i32 @test_msan(i1 %f, ptr %a, ptr %b) sanitize_memory { ; CHECK-LABEL: @test_msan( ; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32 undef +; CHECK-NEXT: [[A_VAL:%.*]] = load i32, ptr [[A:%.*]], align 8 +; CHECK-NEXT: [[B_VAL:%.*]] = load i32, ptr [[B:%.*]], align 8 +; CHECK-NEXT: [[L:%.*]] = select i1 [[F:%.*]], i32 [[A_VAL]], i32 [[B_VAL]] +; CHECK-NEXT: ret i32 [[L]] ; entry: - %a = alloca i32, align 8 - %b = alloca i32, align 8 %sel = select i1 %f, ptr %a, ptr %b %l = load i32, ptr %sel, align 8 ret i32 %l diff --git a/llvm/test/Transforms/InstCombine/shift-amount-reassociation.ll b/llvm/test/Transforms/InstCombine/shift-amount-reassociation.ll index f251dc282f4ca..abae2c6b9ab8e 100644 --- a/llvm/test/Transforms/InstCombine/shift-amount-reassociation.ll +++ b/llvm/test/Transforms/InstCombine/shift-amount-reassociation.ll @@ -156,11 +156,10 @@ define i32 @t11_shl_nsw_flag_preservation(i32 %x, i32 %y) { ; Reduced from https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=15587 @X = external global i32 -define i64 @constantexpr() { -; CHECK-LABEL: @constantexpr( -; CHECK-NEXT: ret i64 poison +define i64 @constantexpr(ptr %A) { +; CHECK-LABEL: @constantexpr(ptr %A) { +; CHECK-NEXT: ret i64 0 ; - %A = alloca i64 %L = load i64, ptr %A %V = add i64 ptrtoint (ptr @X to i64), 0 %B2 = shl i64 %V, 0 diff --git a/llvm/test/Transforms/InstCombine/vscale_gep.ll b/llvm/test/Transforms/InstCombine/vscale_gep.ll index 2f5e2a074ea5f..ff63e8d04cc53 100644 --- a/llvm/test/Transforms/InstCombine/vscale_gep.ll +++ b/llvm/test/Transforms/InstCombine/vscale_gep.ll @@ -41,22 +41,27 @@ define void @gep_bitcast(ptr %p) { ; These tests serve to verify code changes when underlying gep ptr is alloca. ; This test is to verify 'inbounds' is added when it's valid to accumulate constant offset. -define i32 @gep_alloca_inbounds_vscale_zero() { -; CHECK-LABEL: @gep_alloca_inbounds_vscale_zero( -; CHECK-NEXT: ret i32 undef +define i32 @gep_alloca_inbounds_vscale_zero(ptr %a) { +; CHECK-LABEL: @gep_alloca_inbounds_vscale_zero(ptr %a) { +; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds nuw i8, ptr [[A:%.*]], i64 8 +; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[TMP]], align 4 +; CHECK-NEXT: ret i32 [[LOAD]] ; - %a = alloca <vscale x 4 x i32> %tmp = getelementptr <vscale x 4 x i32>, ptr %a, i32 0, i32 2 %load = load i32, ptr %tmp ret i32 %load } ; This test is to verify 'inbounds' is not added when a constant offset can not be determined at compile-time. -define i32 @gep_alloca_inbounds_vscale_nonzero() { -; CHECK-LABEL: @gep_alloca_inbounds_vscale_nonzero( -; CHECK-NEXT: ret i32 undef +define i32 @gep_alloca_inbounds_vscale_nonzero(ptr %a) { +; CHECK-LABEL: @gep_alloca_inbounds_vscale_nonzero(ptr %a) { +; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP2:%.*]] = shl i64 [[TMP1]], 4 +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 [[TMP2]] +; CHECK-NEXT: [[TMP:%.*]] = getelementptr i8, ptr [[TMP3]], i64 8 +; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[TMP]], align 4 +; CHECK-NEXT: ret i32 [[LOAD]] ; - %a = alloca <vscale x 4 x i32> %tmp = getelementptr <vscale x 4 x i32>, ptr %a, i32 1, i32 2 %load = load i32, ptr %tmp ret i32 %load >From dbb71d3bedc67c23bc6cc9aa0ea3431d2fc3b780 Mon Sep 17 00:00:00 2001 From: Jameson Nash <vtjn...@gmail.com> Date: Thu, 12 Jun 2025 21:20:12 +0000 Subject: [PATCH 5/9] fix claude --- llvm/test/Transforms/InstCombine/fp-ret-bitcast.ll | 3 ++- llvm/test/Transforms/InstCombine/getelementptr.ll | 4 ++-- .../multiple-uses-load-bitcast-select.ll | 7 +++---- llvm/test/Transforms/InstCombine/objsize.ll | 5 ++--- llvm/test/Transforms/InstCombine/select-load.ll | 14 ++++++-------- llvm/test/Transforms/InstCombine/vscale_gep.ll | 6 +++--- 6 files changed, 18 insertions(+), 21 deletions(-) diff --git a/llvm/test/Transforms/InstCombine/fp-ret-bitcast.ll b/llvm/test/Transforms/InstCombine/fp-ret-bitcast.ll index 3daee254227ec..af18a427ee372 100644 --- a/llvm/test/Transforms/InstCombine/fp-ret-bitcast.ll +++ b/llvm/test/Transforms/InstCombine/fp-ret-bitcast.ll @@ -13,9 +13,10 @@ target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:1 @"\01L_OBJC_SELECTOR_REFERENCES_81" = internal global ptr @"\01L_OBJC_METH_VAR_NAME_112", section "__OBJC,__message_refs,literal_pointers,no_dead_strip" define void @bork(ptr %color, ptr %color.466) nounwind { -; CHECK-LABEL: @bork(ptr %color, ptr %color.466) { +; CHECK-LABEL: @bork( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP103:%.*]] = load ptr, ptr [[COLOR:%.*]], align 4 +; CHECK-NEXT: store ptr [[TMP103]], ptr [[COLOR_466:%.*]], align 4 ; CHECK-NEXT: [[TMP105:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_81", align 4 ; CHECK-NEXT: [[TMP107:%.*]] = call float @objc_msgSend_fpret(ptr [[TMP103]], ptr [[TMP105]]) #[[ATTR0:[0-9]+]] ; CHECK-NEXT: br label [[EXIT:%.*]] diff --git a/llvm/test/Transforms/InstCombine/getelementptr.ll b/llvm/test/Transforms/InstCombine/getelementptr.ll index c90ba7f43f50f..11046d1e45de0 100644 --- a/llvm/test/Transforms/InstCombine/getelementptr.ll +++ b/llvm/test/Transforms/InstCombine/getelementptr.ll @@ -681,7 +681,7 @@ define i32 @test28() nounwind { ; CHECK-LABEL: @test28( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[ORIENTATIONS:%.*]] = alloca [1 x [1 x %struct.x]], align 8 -; CHECK-NEXT: [[T3:%.*]] = call i32 @puts(ptr noundef nonnull dereferenceable(1) @.str) #[[ATTR0:[0-9]+]] +; CHECK-NEXT: [[T3:%.*]] = call i32 @puts(ptr noundef nonnull dereferenceable(1) @.str) #[[ATTR0]] ; CHECK-NEXT: [[T45:%.*]] = getelementptr inbounds nuw i8, ptr [[ORIENTATIONS]], i64 1 ; CHECK-NEXT: br label [[BB10:%.*]] ; CHECK: bb10: @@ -1341,7 +1341,7 @@ declare noalias ptr @malloc(i64) nounwind allockind("alloc,uninitialized") alloc define i32 @test_gep_bitcast_malloc(ptr %a, ptr %call) { ; CHECK-LABEL: @test_gep_bitcast_malloc( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds i8, ptr [[CALL:%.*]], i64 12 +; CHECK-NEXT: [[G3:%.*]] = getelementptr i8, ptr [[CALL:%.*]], i64 12 ; CHECK-NEXT: [[A_C:%.*]] = load i32, ptr [[G3]], align 4 ; CHECK-NEXT: ret i32 [[A_C]] ; diff --git a/llvm/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll b/llvm/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll index 594ff091f5651..5d3512e10f418 100644 --- a/llvm/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll +++ b/llvm/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll @@ -26,10 +26,9 @@ define void @PR35618_asan(ptr %st1, ptr %st2, ptr %y1, ptr %z1) sanitize_address ; CHECK-NEXT: [[LD1:%.*]] = load double, ptr [[Y1:%.*]], align 8 ; CHECK-NEXT: [[LD2:%.*]] = load double, ptr [[Z1:%.*]], align 8 ; CHECK-NEXT: [[TMP:%.*]] = fcmp olt double [[LD1]], [[LD2]] -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP]], ptr [[Y1]], ptr [[Z1]] -; CHECK-NEXT: [[TMP12:%.*]] = load i64, ptr [[SEL]], align 8 -; CHECK-NEXT: store i64 [[TMP12]], ptr [[ST1:%.*]], align 8 -; CHECK-NEXT: store i64 [[TMP12]], ptr [[ST2:%.*]], align 8 +; CHECK-NEXT: [[TMP12_V:%.*]] = select i1 [[TMP]], double [[LD1]], double [[LD2]] +; CHECK-NEXT: store double [[TMP12_V]], ptr [[ST1:%.*]], align 8 +; CHECK-NEXT: store double [[TMP12_V]], ptr [[ST2:%.*]], align 8 ; CHECK-NEXT: ret void ; %ld1 = load double, ptr %y1 diff --git a/llvm/test/Transforms/InstCombine/objsize.ll b/llvm/test/Transforms/InstCombine/objsize.ll index 7ef1e9bb9275f..39f6f493782d2 100644 --- a/llvm/test/Transforms/InstCombine/objsize.ll +++ b/llvm/test/Transforms/InstCombine/objsize.ll @@ -19,11 +19,10 @@ define ptr @bar(ptr %retval) nounwind { ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 true, label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] ; CHECK: cond.true: -; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[RETVAL:%.*]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[RETVAL:%.*]], align 4 ; CHECK-NEXT: ret ptr [[TMP1]] ; CHECK: cond.false: -; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[RETVAL]], align 8 -; CHECK-NEXT: ret ptr [[TMP2]] +; CHECK-NEXT: ret ptr poison ; entry: %0 = call i32 @llvm.objectsize.i32.p0(ptr @a, i1 false, i1 false, i1 false) diff --git a/llvm/test/Transforms/InstCombine/select-load.ll b/llvm/test/Transforms/InstCombine/select-load.ll index 5e3182614e9cf..308dc25bf780c 100644 --- a/llvm/test/Transforms/InstCombine/select-load.ll +++ b/llvm/test/Transforms/InstCombine/select-load.ll @@ -7,10 +7,9 @@ target triple = "x86_64-grtev4-linux-gnu" define i32 @test_plain(i1 %f, ptr %a, ptr %b) { ; CHECK-LABEL: @test_plain( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[A_VAL:%.*]] = load i32, ptr [[A:%.*]], align 8 -; CHECK-NEXT: [[B_VAL:%.*]] = load i32, ptr [[B:%.*]], align 8 -; CHECK-NEXT: [[L:%.*]] = select i1 [[F:%.*]], i32 [[A_VAL]], i32 [[B_VAL]] -; CHECK-NEXT: ret i32 [[L]] +; CHECK-NEXT: [[B:%.*]] = select i1 [[F:%.*]], ptr [[A:%.*]], ptr [[B1:%.*]] +; CHECK-NEXT: [[B_VAL:%.*]] = load i32, ptr [[B]], align 8 +; CHECK-NEXT: ret i32 [[B_VAL]] ; entry: %sel = select i1 %f, ptr %a, ptr %b @@ -81,10 +80,9 @@ entry: define i32 @test_msan(i1 %f, ptr %a, ptr %b) sanitize_memory { ; CHECK-LABEL: @test_msan( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[A_VAL:%.*]] = load i32, ptr [[A:%.*]], align 8 -; CHECK-NEXT: [[B_VAL:%.*]] = load i32, ptr [[B:%.*]], align 8 -; CHECK-NEXT: [[L:%.*]] = select i1 [[F:%.*]], i32 [[A_VAL]], i32 [[B_VAL]] -; CHECK-NEXT: ret i32 [[L]] +; CHECK-NEXT: [[B:%.*]] = select i1 [[F:%.*]], ptr [[A:%.*]], ptr [[B1:%.*]] +; CHECK-NEXT: [[B_VAL:%.*]] = load i32, ptr [[B]], align 8 +; CHECK-NEXT: ret i32 [[B_VAL]] ; entry: %sel = select i1 %f, ptr %a, ptr %b diff --git a/llvm/test/Transforms/InstCombine/vscale_gep.ll b/llvm/test/Transforms/InstCombine/vscale_gep.ll index ff63e8d04cc53..705a1ed13dead 100644 --- a/llvm/test/Transforms/InstCombine/vscale_gep.ll +++ b/llvm/test/Transforms/InstCombine/vscale_gep.ll @@ -42,8 +42,8 @@ define void @gep_bitcast(ptr %p) { ; These tests serve to verify code changes when underlying gep ptr is alloca. ; This test is to verify 'inbounds' is added when it's valid to accumulate constant offset. define i32 @gep_alloca_inbounds_vscale_zero(ptr %a) { -; CHECK-LABEL: @gep_alloca_inbounds_vscale_zero(ptr %a) { -; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds nuw i8, ptr [[A:%.*]], i64 8 +; CHECK-LABEL: @gep_alloca_inbounds_vscale_zero( +; CHECK-NEXT: [[TMP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 8 ; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[TMP]], align 4 ; CHECK-NEXT: ret i32 [[LOAD]] ; @@ -54,7 +54,7 @@ define i32 @gep_alloca_inbounds_vscale_zero(ptr %a) { ; This test is to verify 'inbounds' is not added when a constant offset can not be determined at compile-time. define i32 @gep_alloca_inbounds_vscale_nonzero(ptr %a) { -; CHECK-LABEL: @gep_alloca_inbounds_vscale_nonzero(ptr %a) { +; CHECK-LABEL: @gep_alloca_inbounds_vscale_nonzero( ; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-NEXT: [[TMP2:%.*]] = shl i64 [[TMP1]], 4 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 [[TMP2]] >From 1fcc3238985d5a8d83a8066540b7460ec32fe952 Mon Sep 17 00:00:00 2001 From: Jameson Nash <vtjn...@gmail.com> Date: Fri, 13 Jun 2025 13:27:55 +0000 Subject: [PATCH 6/9] more fixes, add xfail for pre-existing failure --- .../Transforms/InstCombine/and-or-icmps.ll | 18 ++---- .../InstCombine/fixedpoint-and-or-icmps.ll | 58 +++++++++++++++++++ .../Transforms/InstCombine/getelementptr.ll | 7 +-- 3 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll index 6fb94a648f368..26e0552886814 100644 --- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -362,23 +362,13 @@ define <2 x i1> @and_ne_with_diff_one_splatvec(<2 x i32> %x) { ; on an 'and' that should have been killed. It's not obvious ; why, but removing anything hides the bug, hence the long test. -define void @simplify_before_foldAndOfICmps(ptr %p, ptr %A8) { +define void @simplify_before_foldAndOfICmps(ptr %p) { ; CHECK-LABEL: @simplify_before_foldAndOfICmps( -; CHECK-NEXT: [[L7:%.*]] = load i16, ptr [[A8:%.*]], align 2 -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i16 [[L7]], -1 -; CHECK-NEXT: [[B11:%.*]] = zext i1 [[TMP1]] to i16 -; CHECK-NEXT: [[C10:%.*]] = icmp ugt i16 [[L7]], [[B11]] -; CHECK-NEXT: [[C7:%.*]] = icmp slt i16 [[L7]], 0 -; CHECK-NEXT: [[C3:%.*]] = and i1 [[C7]], [[C10]] -; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[C10]], true -; CHECK-NEXT: [[C18:%.*]] = or i1 [[C7]], [[TMP2]] -; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[C3]] to i64 -; CHECK-NEXT: [[G26:%.*]] = getelementptr i1, ptr null, i64 [[TMP3]] -; CHECK-NEXT: store i16 [[L7]], ptr [[P:%.*]], align 2 -; CHECK-NEXT: store i1 [[C18]], ptr [[P]], align 1 -; CHECK-NEXT: store ptr [[G26]], ptr [[P]], align 8 +; CHECK-NEXT: store i1 true, ptr [[P:%.*]], align 1 +; CHECK-NEXT: store ptr null, ptr [[P]], align 8 ; CHECK-NEXT: ret void ; + %A8 = alloca i16 %L7 = load i16, ptr %A8 %G21 = getelementptr i16, ptr %A8, i8 -1 %B11 = udiv i16 %L7, -1 diff --git a/llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll b/llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll new file mode 100644 index 0000000000000..d4115603e3a0a --- /dev/null +++ b/llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll @@ -0,0 +1,58 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instcombine -S | FileCheck %s +; XFAIL: * + +; This is a fuzzer-generated test that would assert because +; we'd get into foldAndOfICmps() without running InstSimplify +; on an 'and' that should have been killed. It's not obvious +; why, but removing anything hides the bug, hence the long test. + +define void @simplify_before_foldAndOfICmps(ptr %p, ptr %A8) { +; CHECK-LABEL: @simplify_before_foldAndOfICmps( +; CHECK-NEXT: [[L7:%.*]] = load i16, ptr [[A8:%.*]], align 2 +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i16 [[L7]], -1 +; CHECK-NEXT: [[B11:%.*]] = zext i1 [[TMP1]] to i16 +; CHECK-NEXT: [[C10:%.*]] = icmp ugt i16 [[L7]], [[B11]] +; CHECK-NEXT: [[C7:%.*]] = icmp slt i16 [[L7]], 0 +; CHECK-NEXT: [[C3:%.*]] = and i1 [[C7]], [[C10]] +; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[C10]], true +; CHECK-NEXT: [[C18:%.*]] = or i1 [[C7]], [[TMP2]] +; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[C3]] to i64 +; CHECK-NEXT: [[G26:%.*]] = getelementptr i1, ptr null, i64 [[TMP3]] +; CHECK-NEXT: store i16 [[L7]], ptr [[P:%.*]], align 2 +; CHECK-NEXT: store i1 [[C18]], ptr [[P]], align 1 +; CHECK-NEXT: store ptr [[G26]], ptr [[P]], align 8 +; CHECK-NEXT: ret void +; + %L7 = load i16, ptr %A8 + %G21 = getelementptr i16, ptr %A8, i8 -1 + %B11 = udiv i16 %L7, -1 + %G4 = getelementptr i16, ptr %A8, i16 %B11 + %L2 = load i16, ptr %G4 + %L = load i16, ptr %G4 + %B23 = mul i16 %B11, %B11 + %L4 = load i16, ptr %A8 + %B21 = sdiv i16 %L7, %L4 + %B7 = sub i16 0, %B21 + %B18 = mul i16 %B23, %B7 + %C10 = icmp ugt i16 %L, %B11 + %B20 = and i16 %L7, %L2 + %B1 = mul i1 %C10, true + %C5 = icmp sle i16 %B21, %L + %C11 = icmp ule i16 %B21, %L + %C7 = icmp slt i16 %B20, 0 + %B29 = srem i16 %L4, %B18 + %B15 = add i1 %C7, %C10 + %B19 = add i1 %C11, %B15 + %C6 = icmp sge i1 %C11, %B19 + %B33 = or i16 %B29, %L4 + %C13 = icmp uge i1 %C5, %B1 + %C3 = icmp ult i1 %C13, %C6 + store i16 undef, ptr %G21 + %C18 = icmp ule i1 %C10, %C7 + %G26 = getelementptr i1, ptr null, i1 %C3 + store i16 %B33, ptr %p + store i1 %C18, ptr %p + store ptr %G26, ptr %p + ret void +} diff --git a/llvm/test/Transforms/InstCombine/getelementptr.ll b/llvm/test/Transforms/InstCombine/getelementptr.ll index 11046d1e45de0..61a2c57347d95 100644 --- a/llvm/test/Transforms/InstCombine/getelementptr.ll +++ b/llvm/test/Transforms/InstCombine/getelementptr.ll @@ -1338,14 +1338,13 @@ define ptr @D98588(ptr %c1, i64 %offset) { declare noalias ptr @malloc(i64) nounwind allockind("alloc,uninitialized") allocsize(0) -define i32 @test_gep_bitcast_malloc(ptr %a, ptr %call) { +define i32 @test_gep_bitcast_malloc(ptr %a) { ; CHECK-LABEL: @test_gep_bitcast_malloc( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[G3:%.*]] = getelementptr i8, ptr [[CALL:%.*]], i64 12 -; CHECK-NEXT: [[A_C:%.*]] = load i32, ptr [[G3]], align 4 -; CHECK-NEXT: ret i32 [[A_C]] +; CHECK-NEXT: ret i32 undef ; entry: + %call = call noalias ptr @malloc(i64 16) #2 %g3 = getelementptr %struct.A, ptr %call, i32 0, i32 2 %a_c = load i32, ptr %g3, align 4 ret i32 %a_c >From a2a38208d7f13818104a36ba975c1bcbe3baa2e4 Mon Sep 17 00:00:00 2001 From: Jameson Nash <vtjn...@gmail.com> Date: Fri, 13 Jun 2025 10:31:20 -0400 Subject: [PATCH 7/9] not actually an xfail, just intended behavior for this test to crash when run with an explicit passes pipeline Per 41895843b5915bb78e9d02aa711fa10f7174db43 --- llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll b/llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll index d4115603e3a0a..60e4bc57b1053 100644 --- a/llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll +++ b/llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll @@ -1,6 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -passes=instcombine -S | FileCheck %s -; XFAIL: * +; RUN: opt < %s -passes='instcombine<max-iterations=5>' -S | FileCheck %s ; This is a fuzzer-generated test that would assert because ; we'd get into foldAndOfICmps() without running InstSimplify >From 75849491536710653d6e166a37dbfceb6bba77ac Mon Sep 17 00:00:00 2001 From: Jameson Nash <vtjn...@gmail.com> Date: Fri, 13 Jun 2025 11:03:15 -0400 Subject: [PATCH 8/9] oops, forgot to commit updated test checks --- .../InstCombine/fixedpoint-and-or-icmps.ll | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll b/llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll index 60e4bc57b1053..61e0989af497f 100644 --- a/llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll +++ b/llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -passes='instcombine<max-iterations=5>' -S | FileCheck %s +; RUN: opt < %s -passes='instcombine<no-verify-fixpoint>' -S | FileCheck %s ; This is a fuzzer-generated test that would assert because ; we'd get into foldAndOfICmps() without running InstSimplify @@ -11,14 +11,30 @@ define void @simplify_before_foldAndOfICmps(ptr %p, ptr %A8) { ; CHECK-NEXT: [[L7:%.*]] = load i16, ptr [[A8:%.*]], align 2 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i16 [[L7]], -1 ; CHECK-NEXT: [[B11:%.*]] = zext i1 [[TMP1]] to i16 -; CHECK-NEXT: [[C10:%.*]] = icmp ugt i16 [[L7]], [[B11]] -; CHECK-NEXT: [[C7:%.*]] = icmp slt i16 [[L7]], 0 -; CHECK-NEXT: [[C3:%.*]] = and i1 [[C7]], [[C10]] -; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[C10]], true -; CHECK-NEXT: [[C18:%.*]] = or i1 [[C7]], [[TMP2]] -; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[C3]] to i64 +; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP1]] to i64 +; CHECK-NEXT: [[G4:%.*]] = getelementptr i16, ptr [[A8]], i64 [[TMP2]] +; CHECK-NEXT: [[L2:%.*]] = load i16, ptr [[G4]], align 2 +; CHECK-NEXT: [[L4:%.*]] = load i16, ptr [[A8]], align 2 +; CHECK-NEXT: [[B21:%.*]] = sdiv i16 [[L7]], [[L4]] +; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP1]], i16 [[B21]], i16 0 +; CHECK-NEXT: [[B18:%.*]] = sub i16 0, [[TMP5]] +; CHECK-NEXT: [[C11:%.*]] = icmp ugt i16 [[L2]], [[B11]] +; CHECK-NEXT: [[B20:%.*]] = and i16 [[L7]], [[L2]] +; CHECK-NEXT: [[C5:%.*]] = icmp sgt i16 [[B21]], [[L2]] +; CHECK-NEXT: [[C12:%.*]] = icmp ule i16 [[B21]], [[L2]] +; CHECK-NEXT: [[C10:%.*]] = icmp slt i16 [[B20]], 0 +; CHECK-NEXT: [[B29:%.*]] = srem i16 [[L4]], [[B18]] +; CHECK-NEXT: [[B15:%.*]] = xor i1 [[C10]], [[C11]] +; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[C12]], [[B15]] +; CHECK-NEXT: [[C6:%.*]] = xor i1 [[TMP6]], true +; CHECK-NEXT: [[B33:%.*]] = or i16 [[B29]], [[L4]] +; CHECK-NEXT: [[C3:%.*]] = and i1 [[C5]], [[C6]] +; CHECK-NEXT: [[C4:%.*]] = and i1 [[C3]], [[C11]] +; CHECK-NEXT: [[TMP4:%.*]] = xor i1 [[C11]], true +; CHECK-NEXT: [[C18:%.*]] = or i1 [[C10]], [[TMP4]] +; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[C4]] to i64 ; CHECK-NEXT: [[G26:%.*]] = getelementptr i1, ptr null, i64 [[TMP3]] -; CHECK-NEXT: store i16 [[L7]], ptr [[P:%.*]], align 2 +; CHECK-NEXT: store i16 [[B33]], ptr [[P:%.*]], align 2 ; CHECK-NEXT: store i1 [[C18]], ptr [[P]], align 1 ; CHECK-NEXT: store ptr [[G26]], ptr [[P]], align 8 ; CHECK-NEXT: ret void >From d158fbbc7dc63106b669be1aeeaba252537de271 Mon Sep 17 00:00:00 2001 From: Jameson Nash <vtjn...@gmail.com> Date: Fri, 13 Jun 2025 11:03:42 -0400 Subject: [PATCH 9/9] run iterations --- .../InstCombine/fixedpoint-and-or-icmps.ll | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll b/llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll index 61e0989af497f..d0475177f629b 100644 --- a/llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll +++ b/llvm/test/Transforms/InstCombine/fixedpoint-and-or-icmps.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -passes='instcombine<no-verify-fixpoint>' -S | FileCheck %s +; RUN: opt < %s -passes='instcombine<max-iterations=5>' -S | FileCheck %s ; This is a fuzzer-generated test that would assert because ; we'd get into foldAndOfICmps() without running InstSimplify @@ -14,27 +14,17 @@ define void @simplify_before_foldAndOfICmps(ptr %p, ptr %A8) { ; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP1]] to i64 ; CHECK-NEXT: [[G4:%.*]] = getelementptr i16, ptr [[A8]], i64 [[TMP2]] ; CHECK-NEXT: [[L2:%.*]] = load i16, ptr [[G4]], align 2 -; CHECK-NEXT: [[L4:%.*]] = load i16, ptr [[A8]], align 2 -; CHECK-NEXT: [[B21:%.*]] = sdiv i16 [[L7]], [[L4]] -; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP1]], i16 [[B21]], i16 0 -; CHECK-NEXT: [[B18:%.*]] = sub i16 0, [[TMP5]] ; CHECK-NEXT: [[C11:%.*]] = icmp ugt i16 [[L2]], [[B11]] ; CHECK-NEXT: [[B20:%.*]] = and i16 [[L7]], [[L2]] -; CHECK-NEXT: [[C5:%.*]] = icmp sgt i16 [[B21]], [[L2]] -; CHECK-NEXT: [[C12:%.*]] = icmp ule i16 [[B21]], [[L2]] +; CHECK-NEXT: [[C5:%.*]] = icmp slt i16 [[L2]], 1 ; CHECK-NEXT: [[C10:%.*]] = icmp slt i16 [[B20]], 0 -; CHECK-NEXT: [[B29:%.*]] = srem i16 [[L4]], [[B18]] -; CHECK-NEXT: [[B15:%.*]] = xor i1 [[C10]], [[C11]] -; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[C12]], [[B15]] -; CHECK-NEXT: [[C6:%.*]] = xor i1 [[TMP6]], true -; CHECK-NEXT: [[B33:%.*]] = or i16 [[B29]], [[L4]] -; CHECK-NEXT: [[C3:%.*]] = and i1 [[C5]], [[C6]] +; CHECK-NEXT: [[C3:%.*]] = and i1 [[C5]], [[C10]] ; CHECK-NEXT: [[C4:%.*]] = and i1 [[C3]], [[C11]] ; CHECK-NEXT: [[TMP4:%.*]] = xor i1 [[C11]], true ; CHECK-NEXT: [[C18:%.*]] = or i1 [[C10]], [[TMP4]] ; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[C4]] to i64 ; CHECK-NEXT: [[G26:%.*]] = getelementptr i1, ptr null, i64 [[TMP3]] -; CHECK-NEXT: store i16 [[B33]], ptr [[P:%.*]], align 2 +; CHECK-NEXT: store i16 [[L7]], ptr [[P:%.*]], align 2 ; CHECK-NEXT: store i1 [[C18]], ptr [[P]], align 1 ; CHECK-NEXT: store ptr [[G26]], ptr [[P]], align 8 ; CHECK-NEXT: ret void _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits