diff --git a/llvm/lib/CodeGen/MachineLICM.cpp b/llvm/lib/CodeGen/MachineLICM.cpp index c9079170ca575..1544298ec587d 100644 --- a/llvm/lib/CodeGen/MachineLICM.cpp +++ b/llvm/lib/CodeGen/MachineLICM.cpp @@ -554,23 +554,18 @@ void MachineLICMImpl::ProcessMI(MachineInstr *MI, BitVector &RUDefs, } if (MO.isImplicit()) { - for (MCRegUnit Unit : TRI->regunits(Reg)) - RUClobbers.set(Unit); if (!MO.isDead()) // Non-dead implicit def? This cannot be hoisted. RuledOut = true; - // No need to check if a dead implicit def is also defined by - // another instruction. - continue; + } else { + // FIXME: For now, avoid instructions with multiple defs, unless + // it's a dead implicit def. + if (Def) + RuledOut = true; + else + Def = Reg; } - // FIXME: For now, avoid instructions with multiple defs, unless - // it's a dead implicit def. - if (Def) - RuledOut = true; - else - Def = Reg; - // If we have already seen another instruction that defines the same // register, then this is not safe. Two defs is indicated by setting a // PhysRegClobbers bit. diff --git a/llvm/test/CodeGen/AArch64/mlicm-implicit-defs.mir b/llvm/test/CodeGen/AArch64/mlicm-implicit-defs.mir new file mode 100644 index 0000000000000..2c5a70288cfad --- /dev/null +++ b/llvm/test/CodeGen/AArch64/mlicm-implicit-defs.mir @@ -0,0 +1,103 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 +# RUN: llc -mtriple=aarch64 -run-pass machinelicm -verify-machineinstrs -o - %s | FileCheck %s +# RUN: llc -mtriple=aarch64 -passes machinelicm -o - %s | FileCheck %s + +--- +name: unsafe_to_move +tracksRegLiveness: true +body: | + ; CHECK-LABEL: name: unsafe_to_move + ; CHECK: bb.0: + ; CHECK-NEXT: successors: %bb.1(0x80000000) + ; CHECK-NEXT: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x16 = COPY killed $x0 + ; CHECK-NEXT: B %bb.1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.1: + ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000) + ; CHECK-NEXT: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x1 = COPY killed $x16 + ; CHECK-NEXT: $x2 = MOVi64imm 1024, implicit-def dead $x16 + ; CHECK-NEXT: $x16 = LDRXroX killed $x1, killed $x2, 0, 0 + ; CHECK-NEXT: $xzr = SUBSXri $x16, 0, 0, implicit-def $nzcv + ; CHECK-NEXT: Bcc 1, %bb.1, implicit $nzcv + ; CHECK-NEXT: B %bb.2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.2: + ; CHECK-NEXT: liveins: $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x0 = COPY killed $x1 + ; CHECK-NEXT: RET_ReallyLR + bb.0: + liveins: $x0 + $x16 = COPY killed $x0 + B %bb.1 + + bb.1: + liveins: $x16 + $x1 = COPY killed $x16 + /* MOVi64imm below mimics a pseudo instruction that doesn't have any */ + /* unmodelled side effects, but uses x16 as a scratch register. */ + $x2 = MOVi64imm 1024, implicit-def dead $x16 + $x16 = LDRXroX killed $x1, killed $x2, 0, 0 + $xzr = SUBSXri $x16, 0, 0, implicit-def $nzcv + Bcc 1, %bb.1, implicit $nzcv + B %bb.2 + + bb.2: + liveins: $x1 + $x0 = COPY killed $x1 + RET_ReallyLR +... + +--- +name: dead_implicit_def +tracksRegLiveness: true +body: | + ; CHECK-LABEL: name: dead_implicit_def + ; CHECK: bb.0: + ; CHECK-NEXT: successors: %bb.1(0x80000000) + ; CHECK-NEXT: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x12 = COPY killed $x0 + ; CHECK-NEXT: $x2 = MOVi64imm 1024, implicit-def dead $x16 + ; CHECK-NEXT: B %bb.1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.1: + ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000) + ; CHECK-NEXT: liveins: $x12, $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x1 = COPY killed $x12 + ; CHECK-NEXT: $x16 = LDRXroX killed $x1, $x2, 0, 0 + ; CHECK-NEXT: $xzr = SUBSXri $x16, 0, 0, implicit-def $nzcv + ; CHECK-NEXT: Bcc 1, %bb.1, implicit $nzcv + ; CHECK-NEXT: B %bb.2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.2: + ; CHECK-NEXT: liveins: $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x0 = COPY killed $x1 + ; CHECK-NEXT: RET_ReallyLR + bb.0: + liveins: $x0 + $x12 = COPY killed $x0 + B %bb.1 + + bb.1: + liveins: $x12 + $x1 = COPY killed $x12 + /* MOVi64imm below mimics a pseudo instruction that doesn't have any */ + /* unmodelled side effects, but uses x16 as a scratch register. */ + $x2 = MOVi64imm 1024, implicit-def dead $x16 + $x16 = LDRXroX killed $x1, killed $x2, 0, 0 + $xzr = SUBSXri $x16, 0, 0, implicit-def $nzcv + Bcc 1, %bb.1, implicit $nzcv + B %bb.2 + + bb.2: + liveins: $x1 + $x0 = COPY killed $x1 + RET_ReallyLR +...