diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -1682,10 +1682,11 @@ TheUse = InsertedShift; } - // If we removed all uses, nuke the shift. + // If we removed all uses, or there are none, nuke the shift. if (ShiftI->use_empty()) { salvageDebugInfo(*ShiftI); ShiftI->eraseFromParent(); + MadeChange = true; } return MadeChange; diff --git a/llvm/test/Transforms/CodeGenPrepare/sink-shift-and-trunc.ll b/llvm/test/Transforms/CodeGenPrepare/sink-shift-and-trunc.ll --- a/llvm/test/Transforms/CodeGenPrepare/sink-shift-and-trunc.ll +++ b/llvm/test/Transforms/CodeGenPrepare/sink-shift-and-trunc.ll @@ -1,5 +1,5 @@ ; REQUIRES: aarch64-registered-target -; RUN: opt -codegenprepare -mtriple=arm64-apple=ios -S -o - %s | FileCheck %s +; RUN: opt -codegenprepare -mtriple=arm64-apple-ios -S -o - %s | FileCheck %s @first_ones = external global [65536 x i8] @@ -58,6 +58,23 @@ ret i32 %retval.0, !dbg !63 } +define i32 @shift_unused(i32 %a) { +; CHECK-LABEL: @shift_unused + + %as = lshr i32 %a, 3 + br label %BB2 + +; CHECK-NEXT: BB2: +BB2: + ; CodeGenPrepare was erasing the unused lshr instruction, but then further + ; processing the instruction after it was freed. If this bug is still present, + ; this test will always crash in an LLVM built with ASAN enabled, and may + ; crash even if ASAN is not enabled. + +; CHECK-NEXT: ret i32 + ret i32 %a +} + ; CHECK: [[shift1_loc]] = !DILocation(line: 1 ; CHECK: [[trunc1_loc]] = !DILocation(line: 2 ; CHECK: [[shift2_loc]] = !DILocation(line: 3