Index: llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -1598,6 +1598,12 @@ Register Shift1 = Builder.buildInstr(Opcode, {DestType}, {Shift1Base, Const}).getReg(0); + // If LogicNonShiftReg is the same to Shift1Base, and shift1 const is the same + // to MatchInfo.Shift2 const, CSEMIRBuilder will reuse the old shift1 when build + // shift2. So, if we erase MatchInfo.Shift2 at the end, actually we remove old + // shift1. And it will cause crash later. So erase it ealier to avoid the crash. + MatchInfo.Shift2->eraseFromParent(); + Register Shift2Const = MI.getOperand(2).getReg(); Register Shift2 = Builder .buildInstr(Opcode, {DestType}, @@ -1607,8 +1613,7 @@ Register Dest = MI.getOperand(0).getReg(); Builder.buildInstr(MatchInfo.Logic->getOpcode(), {Dest}, {Shift1, Shift2}); - // These were one use so it's safe to remove them. - MatchInfo.Shift2->eraseFromParent(); + // This was one use so it's safe to remove it. MatchInfo.Logic->eraseFromParent(); MI.eraseFromParent(); Index: llvm/test/CodeGen/AArch64/pr58432.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/pr58432.ll @@ -0,0 +1,15 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -global-isel -global-isel-abort=0 | FileCheck %s + +; this used to crash +define i32 @f(i32 %0) { +; CHECK-LABEL: f: +; CHECK: // %bb.0: +; CHECK-NEXT: lsl w8, w0, #8 +; CHECK-NEXT: orr w0, w8, w0, lsl #16 +; CHECK-NEXT: ret + %2 = shl i32 %0, 8 + %3 = or i32 %0, %2 + %4 = shl i32 %3, 8 + ret i32 %4 +}