LLC crash in ImplicitNullChecks Pass

LLC crashed in ImplicitNullChecks Pass when compiling an LLVM IR file. An implicit null check metadata triggers the crash, without the “make.implicit” metadata, compile ended successfully.

Crash stack trace:

#10 0x0000555557b47a15 getParent(llvm::Value const*)
#11 0x0000555557b41f76 notDifferentParent(llvm::Value const*, llvm::Value const*)
#12 0x0000555557b41ec7 llvm::BasicAAResult::alias(llvm::MemoryLocation const&, llvm::MemoryLocation const&, llvm::AAQueryInfo&, llvm::Instruction const*)
#13 0x0000555557b3e429 llvm::AAResults::Model< llvm::BasicAAResult>::alias(llvm::MemoryLocation const&, llvm::MemoryLocation const&, llvm::AAQueryInfo&, llvm::Instruction const*)
#14 0x0000555557b34f42 llvm::AAResults::alias(llvm::MemoryLocation const&, llvm::MemoryLocation const&, llvm::AAQueryInfo&, llvm::Instruction const*)
#15 0x0000555557b34d6e llvm::AAResults::alias(llvm::MemoryLocation const&, llvm::MemoryLocation const&)
#16 0x00005555579dad95 llvm::AAResults::isNoAlias(llvm::MemoryLocation const&, llvm::MemoryLocation const&)
#17 0x00005555581da867 (anonymous namespace)::ImplicitNullChecks::areMemoryOpsAliased(llvm::MachineInstr const&, llvm::MachineInstr const*) const
#18 0x00005555581d9d23 (anonymous namespace)::ImplicitNullChecks::isSuitableMemoryOp(llvm::MachineInstr const&, unsigned int, llvm::ArrayRef< llvm::MachineInstr*>)
#19 0x00005555581d8fa4 (anonymous namespace)::ImplicitNullChecks::analyzeBlockForNullChecks(llvm::MachineBasicBlock&, llvm::SmallVectorImpl<(anonymous namespace)::ImplicitNullChecks::NullCheck>&)
#20 0x00005555581d8ab2 (anonymous namespace)::ImplicitNullChecks::runOnMachineFunction(llvm::MachineFunction&)

344 for (MachineMemOperand *MMO1 : MI.memoperands()) {
345 // MMO1 should have a value due it comes from operation we’d like to use
346 // as implicit null check.
347 assert(MMO1->getValue() && “MMO1 should have a Value!”);
348 for (MachineMemOperand *MMO2 : PrevMI->memoperands()) {
349 if (const PseudoSourceValue *PSV = MMO2->getPseudoValue()) {
350 if (PSV->mayAlias(MFI))
351 return AR_MayAlias;
352 continue;
353 }
354 if (!AA->isNoAlias(
355 MemoryLocation::getAfter(MMO1->getValue(), MMO1->getAAInfo()),
356 MemoryLocation::getAfter(MMO2->getValue(), MMO2->getAAInfo())))
357 return AR_MayAlias;
358 }
359 }
360 return AR_NoAlias;
361 }

In lib/CodeGen/ImplicitNullChecks.cpp line 356 (17.0.6),
MMO2->getValue() returns NULL pointer, and MMO2->getValue()->getParent() is invoked without checking the pointer value. I can see there is an assertion in line 347 to make sure MMO1->getValue() is not NULL, but no check for MMO2->getValue().

I am not able to share the full IR due to our policy. And I don’t have a small reproducer currently.
I can only share IR snippet and some information dumped from gdb.

IR snippet:

label_28:
%405 = phi %struct_type_1* [ null, %not_null70 ], [ %404, %397 ]
%406 = load i8*, i8** %24
%407 = load i8*, i8** @ _global_data
%408 = tail call i32 @ library_function_1(i8* %406, i8* %407, i32 0)
%409 = trunc i32 %408 to i1
%410 = getelementptr inbounds i8, i8* %0, i32 989
%411 = zext i1 %409 to i8
store i8 %411, i8* %410
%412 = load i32, i32* %49
%413 = load i32, i32* %54
%414 = select i1 %409, i32 %412, i32 %413
%415 = icmp eq %struct_type_1* %405, null
br i1 %415, label %is_null73, label %not_null72, !make.implicit !10

not_null72:
%416 = getelementptr inbounds %struct_type_1, %struct_type_1* %405, i64 0, i32 80
store i32 %414, i32* %416
%417 = load i32, i32* %i20
%418 = load %struct_type_2*, %struct_type_2** %285
%419 = getelementptr inbounds %struct_type_2, %struct_type_2* %418, i64 0, i32 2
%420 = load i32, i32* %419
%421 = icmp ult i32 %417, %420
br i1 %421, label %label_30, label %label_31

is_null73:
call void @ library_function_2(i8* %4, i8* %0, i32 2439845, i32 0)
unreachable

GDB

MI.dump()
MOV32mr killed renamable $rbp, 1, $noreg, 288, $noreg, killed renamable $eax :: (store (s32) into %ir.416)

PrevMI->dump()
renamable $eax = MOV32rm killed renamable $rax, 1, $noreg, 0, $noreg :: (load (s32))
$8 = void

MMO1->getValue()->dump()
%416 = getelementptr inbounds %struct_type_1, %struct_type_1* %405, i64 0, i32 80

MMO2->getValue()
NULL

Although I can add a check in line 354 to check the return of MMO2->getValue() and make the compilation pass. But I am not sure whether this is a proper fix since I don’t know if MMO2->getValue() is expected to be NULL.

The “areMemoryOpsAliased” function is introduced by commit eef785c1a5eef982428be5c1c7a2fc8d7bdf1c84. I would really appreciate your thoughts and feed back on this @serguei-katkov @sanjoyd