Index: llvm/lib/CodeGen/BranchFolding.cpp =================================================================== --- llvm/lib/CodeGen/BranchFolding.cpp +++ llvm/lib/CodeGen/BranchFolding.cpp @@ -837,7 +837,8 @@ // Merge MMOs from memory operations in the common block. if (MBBICommon->mayLoad() || MBBICommon->mayStore()) MBBICommon->cloneMergedMemRefs(*MBB->getParent(), {&*MBBICommon, &*MBBI}); - // Drop undef flags if they aren't present in all merged instructions. + // Drop undef/kill/dead flags if they aren't present in all merged + // instructions. for (unsigned I = 0, E = MBBICommon->getNumOperands(); I != E; ++I) { MachineOperand &MO = MBBICommon->getOperand(I); if (MO.isReg() && MO.isUndef()) { @@ -845,6 +846,26 @@ if (!OtherMO.isUndef()) MO.setIsUndef(false); } + if (MO.isReg() && MO.isKill()) { + const MachineOperand &OtherMO = MBBI->getOperand(I); + // An exception to the clearing of the kill flag is if we merge + // something like: + // undef $r0 + // $r0 = + // and + // killed $r0 + // $r0 = + // Here we should keep the kill flag even if it's only set in one of the + // merged paths since it's undef in the other. So the only real value + // in $r0 that actually reaches will indeed be killed there. + if (!OtherMO.isKill() && !OtherMO.isUndef()) + MO.setIsKill(false); + } + if (MO.isReg() && MO.isDead()) { + const MachineOperand &OtherMO = MBBI->getOperand(I); + if (!OtherMO.isDead()) + MO.setIsDead(false); + } } ++MBBI; Index: llvm/test/CodeGen/Hexagon/branchfolder-clear-kill-dead.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/Hexagon/branchfolder-clear-kill-dead.mir @@ -0,0 +1,90 @@ +# RUN: llc -march=hexagon -run-pass branch-folder %s -o - -verify-machineinstrs | FileCheck %s + +# When the branchfolder merges common tails, it needs to clear both kill and +# dead flags if they differ between the merged blocks. + +# In the below example, if the killed flag is not cleared we will be left with +# A2_nop 0, killed $r0 +# A2_nop 0, $r0 +# and then the verifier will complain about use of an undefined physical +# register. + +--- +# CHECK-LABEL: name: func0 +# CHECK-LABEL: bb.0: +# CHECK: liveins: $r0, $r31 +# CHECK: A2_nop implicit $r0 +# CHECK: A2_nop implicit $r0 +# CHECK: PS_jmpret + +name: func0 +tracksRegLiveness: true + +body: | + bb.0: + liveins: $r0, $r31 + successors: %bb.1, %bb.2 + J2_jumpt undef $p0, %bb.2, implicit-def $pc + J2_jump %bb.1, implicit-def $pc + + bb.1: + liveins: $r0, $r31 + successors: %bb.3 + A2_nop implicit $r0 + A2_nop implicit killed $r0 + J2_jump %bb.3, implicit-def $pc + + bb.2: + liveins: $r0, $r31 + successors: %bb.3 + A2_nop implicit killed $r0 + A2_nop implicit undef $r0 + J2_jump %bb.3, implicit-def $pc + + bb.3: + liveins: $r31 + PS_jmpret killed $r31, implicit-def $pc +... +--- +# In the below example, if the dead flag is not cleared we will be left with +# A2_nop 0, dead $r0 +# A2_nop 0, $r0 +# and then the verifier will complain about use of an undefined physical +# register. + +# CHECK-LABEL: name: func1 +# CHECK-NOT: PS_jmpret +# CHECK-LABEL: bb.2: +# CHECK-NOT: PS_jmpret +# CHECK: A2_nop +# CHECK-NEXT: A2_nop implicit-def $r0 +# CHECK-NEXT: A2_nop implicit $r0 +# CHECK-NEXT: PS_jmpret undef $r31, implicit-def $pc +# CHECK-NOT: PS_jmpret + +name: func1 +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1(0x40000000), %bb.2(0x40000000) + + J2_jumpt undef $p0, %bb.2, implicit-def $pc + + bb.1: + successors: + + A2_nop implicit-def $r2 + A2_nop + A2_nop implicit-def dead $r0 + A2_nop implicit undef $r0 + PS_jmpret undef $r31, implicit-def $pc + + bb.2: + successors: + + A2_nop implicit-def $r1 + A2_nop + A2_nop implicit-def $r0 + A2_nop implicit killed $r0 + PS_jmpret undef $r31, implicit-def $pc +...