This is an archive of the discontinued LLVM Phabricator instance.

[CodeGenPrepare] Fix isIVIncrement (PR49466)
ClosedPublic

Authored by TaWeiTu on Mar 7 2021, 7:55 AM.

Details

Summary

In the NFC commit 8d835f42a57f15c0b9053bd7c41ea95821a40e5f, the check for !L is
moved to a separate function getIVIncrement which, instead of using BO->getParent(),
uses PN->getParent(). However, these two basic blocks are not necessarily the same.

https://bugs.llvm.org/show_bug.cgi?id=49466 demonstrates a case where PN is contained in
a loop while BO is not, causing the null-pointer dereference in L->getLoopLatch().

This patch checks whether both BO and PN belong to the same loop before entering getIVIncrement.

Diff Detail

Event Timeline

TaWeiTu created this revision.Mar 7 2021, 7:55 AM
TaWeiTu requested review of this revision.Mar 7 2021, 7:55 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 7 2021, 7:55 AM
TaWeiTu updated this revision to Diff 328921.Mar 7 2021, 7:23 PM
  • Add testcase
TaWeiTu updated this revision to Diff 328963.Mar 8 2021, 3:24 AM
  • Fix typo
mkazantsev accepted this revision.Mar 8 2021, 8:17 PM

Thanks for catching this. Indeed, this fact was checked before my patch and was lost during the refactoring. LGTM with nits.

llvm/lib/CodeGen/CodeGenPrepare.cpp
1350

nit: \n not needed.

llvm/test/CodeGen/X86/pr49466.ll
2

If the test is expected to pass, it doesn't really need REQUIRES: asserts

3

| Filecheck %s + ; CHECK-LABEL: @m( if all you want to check is a no-crash.

This revision is now accepted and ready to land.Mar 8 2021, 8:17 PM
TaWeiTu updated this revision to Diff 329196.Mar 8 2021, 8:26 PM
  • Fix nits
TaWeiTu marked 3 inline comments as done.Mar 8 2021, 8:26 PM

Thanks for the review!

TaWeiTu updated this revision to Diff 329206.Mar 8 2021, 9:30 PM
  • Fix test
This revision was landed with ongoing or failed builds.Mar 8 2021, 9:32 PM
This revision was automatically updated to reflect the committed changes.

Reverted in 8d20f2c2c66eb486ff23cc3d55a53bd840b36971. Although this fixes a crash, it also introduces a compile timeout (haven't checked if it's a true infinite loop or just _really_ slow) on other code. The reproducer is in the commit message.

Reverted in 8d20f2c2c66eb486ff23cc3d55a53bd840b36971. Although this fixes a crash, it also introduces a compile timeout (haven't checked if it's a true infinite loop or just _really_ slow) on other code. The reproducer is in the commit message.

Thanks for the report!
There seems to be an infinite loop here but I don't know the reason yet.
Will investigate the cause later.

Here's an IR reproducer, derived from the C++ one I provided in the reverting commit (as before, it reproduces with "clang -O2", although it doesn't with "opt -O2"):

; ModuleID = '/tmp/repro.cc'
source_filename = "/tmp/repro.cc"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%class.D = type { i64 }
%class.a = type { %class.g }
%class.g = type { i32*, i32* }

$_ZNK1aIliEixEl = comdat any

$_ZNK1aIliE1jEv = comdat any

@o = dso_local local_unnamed_addr global i32 0, align 4
@p = dso_local local_unnamed_addr global i32 0, align 4
@.str = private unnamed_addr constant [1 x i8] zeroinitializer, align 1

; Function Attrs: uwtable mustprogress
define dso_local void @_ZN1D1qERK1aIliE(%class.D* nocapture nonnull dereferenceable(8) %0, %class.a* nonnull align 8 dereferenceable(16) %1) local_unnamed_addr #0 align 2 {
  %3 = call i64 @_ZNK1aIliEixEl(%class.a* nonnull dereferenceable(16) %1, i64 0) #3
  %4 = icmp eq i64 %3, 0
  br i1 %4, label %26, label %5

5:                                                ; preds = %2
  %6 = call i64 @_ZNK1aIliE1jEv(%class.a* nonnull dereferenceable(16) %1)
  %7 = icmp eq i64 %6, 0
  br i1 %7, label %26, label %8

8:                                                ; preds = %5
  %9 = getelementptr inbounds %class.D, %class.D* %0, i64 0, i32 0
  br label %10

10:                                               ; preds = %8, %18
  %11 = phi i64 [ 0, %8 ], [ %23, %18 ]
  %12 = call i64 @_ZNK1aIliEixEl(%class.a* nonnull dereferenceable(16) %1, i64 %11) #3
  %13 = icmp eq i64 %12, 0
  br i1 %13, label %18, label %14

14:                                               ; preds = %10, %14
  %15 = load i32, i32* @o, align 4, !tbaa !2
  %16 = call i32 @_Z3fn1IiiEiT_T0_PKc(i32 %15, i32 0, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i64 0, i64 0))
  %17 = icmp eq i32 %16, 0
  br i1 %17, label %18, label %14, !llvm.loop !6

18:                                               ; preds = %14, %10
  %19 = call i64 @_ZNK1aIliEixEl(%class.a* nonnull dereferenceable(16) %1, i64 %11) #3
  %20 = load i32, i32* @p, align 4, !tbaa !2
  %21 = sext i32 %20 to i64
  %22 = sdiv i64 %19, %21
  store i64 %22, i64* %9, align 8, !tbaa !9
  %23 = add i64 %11, 1
  %24 = call i64 @_ZNK1aIliE1jEv(%class.a* nonnull dereferenceable(16) %1)
  %25 = icmp eq i64 %24, 0
  br i1 %25, label %26, label %10, !llvm.loop !12

26:                                               ; preds = %18, %5, %2
  ret void
}

; Function Attrs: nounwind uwtable willreturn mustprogress
define linkonce_odr dso_local i64 @_ZNK1aIliEixEl(%class.a* nonnull dereferenceable(16) %0, i64 %1) local_unnamed_addr #1 comdat align 2 {
  %3 = getelementptr inbounds %class.a, %class.a* %0, i64 0, i32 0, i32 0
  %4 = load i32*, i32** %3, align 8, !tbaa !13
  %5 = getelementptr inbounds i32, i32* %4, i64 %1
  %6 = load i32, i32* %5, align 4, !tbaa !2
  %7 = sext i32 %6 to i64
  ret i64 %7
}

; Function Attrs: nounwind uwtable willreturn mustprogress
define linkonce_odr dso_local i64 @_ZNK1aIliE1jEv(%class.a* nonnull dereferenceable(16) %0) local_unnamed_addr #1 comdat align 2 {
  %2 = getelementptr inbounds %class.a, %class.a* %0, i64 0, i32 0, i32 1
  %3 = load i32*, i32** %2, align 8, !tbaa !16
  %4 = getelementptr inbounds %class.a, %class.a* %0, i64 0, i32 0, i32 0
  %5 = load i32*, i32** %4, align 8, !tbaa !13
  %6 = ptrtoint i32* %3 to i64
  %7 = ptrtoint i32* %5 to i64
  %8 = sub i64 %6, %7
  %9 = ashr exact i64 %8, 2
  ret i64 %9
}

declare dso_local i32 @_Z3fn1IiiEiT_T0_PKc(i32, i32, i8*) local_unnamed_addr #2

attributes #0 = { uwtable mustprogress "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { nounwind uwtable willreturn mustprogress "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #2 = { "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #3 = { nounwind }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git dfd27ebbd0eb137c9a439b7c537bb87ba903efd3)"}
!2 = !{!3, !3, i64 0}
!3 = !{!"int", !4, i64 0}
!4 = !{!"omnipotent char", !5, i64 0}
!5 = !{!"Simple C++ TBAA"}
!6 = distinct !{!6, !7, !8}
!7 = !{!"llvm.loop.mustprogress"}
!8 = !{!"llvm.loop.unroll.disable"}
!9 = !{!10, !11, i64 0}
!10 = !{!"_ZTS1D", !11, i64 0}
!11 = !{!"long", !4, i64 0}
!12 = distinct !{!12, !7, !8}
!13 = !{!14, !15, i64 0}
!14 = !{!"_ZTS1g", !15, i64 0, !15, i64 8}
!15 = !{!"any pointer", !4, i64 0}
!16 = !{!14, !15, i64 8}