Index: llvm/include/llvm/CodeGen/GlobalISel/Utils.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/Utils.h +++ llvm/include/llvm/CodeGen/GlobalISel/Utils.h @@ -171,11 +171,15 @@ /// Find the def instruction for \p Reg, and underlying value Register folding /// away any copies. +/// +/// Also walks through hints such as G_ASSERT_ZEXT. Optional getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI); /// Find the def instruction for \p Reg, folding away any trivial copies. May /// return nullptr if \p Reg is not a generic virtual register. +/// +/// Also walks through hints such as G_ASSERT_ZEXT. MachineInstr *getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI); @@ -183,8 +187,9 @@ /// will be an output register of the instruction that getDefIgnoringCopies /// returns. May return an invalid register if \p Reg is not a generic virtual /// register. -Register getSrcRegIgnoringCopies(Register Reg, - const MachineRegisterInfo &MRI); +/// +/// Also walks through hints such as G_ASSERT_ZEXT. +Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI); /// Returns an APFloat from Val converted to the appropriate size. APFloat getAPFloatFromSize(double Val, unsigned Size); Index: llvm/lib/CodeGen/GlobalISel/Utils.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/Utils.cpp +++ llvm/lib/CodeGen/GlobalISel/Utils.cpp @@ -375,11 +375,13 @@ auto DstTy = MRI.getType(DefMI->getOperand(0).getReg()); if (!DstTy.isValid()) return None; - while (DefMI->getOpcode() == TargetOpcode::COPY) { + unsigned Opc = DefMI->getOpcode(); + while (Opc == TargetOpcode::COPY || isPreISelGenericOptimizationHint(Opc)) { Register SrcReg = DefMI->getOperand(1).getReg(); auto SrcTy = MRI.getType(SrcReg); if (!SrcTy.isValid()) break; + Opc = DefMI->getOpcode(); DefMI = MRI.getVRegDef(SrcReg); DefSrcReg = SrcReg; } Index: llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-select.mir =================================================================== --- llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-select.mir +++ llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-select.mir @@ -7,6 +7,7 @@ define void @self_not_equivalent_overwrite_w0() { ret void } define void @self_not_equivalent_overwrite_w0_implicit() { ret void } define void @self_not_equivalent_different_copies() { ret void } + define void @self_with_assert_zext() { ret void } ... --- name: self @@ -140,3 +141,26 @@ RET_ReallyLR implicit $w0 ... +--- +name: self_with_assert_zext +tracksRegLiveness: true +body: | + bb.0: + liveins: $w0, $w1 + ; We should walk through G_ASSERT_ZEXT as if it's a copy, and remove the + ; G_SELECT. + ; + ; CHECK-LABEL: name: self_with_assert_zext + ; CHECK: liveins: $w0, $w1 + ; CHECK: %a:_(s32) = COPY $w0 + ; CHECK: %a_assert_zext:_(s32) = G_ASSERT_ZEXT %a, 16 + ; CHECK: $w0 = COPY %a_assert_zext(s32) + ; CHECK: RET_ReallyLR implicit $w0 + %a:_(s32) = COPY $w0 + %a_assert_zext:_(s32) = G_ASSERT_ZEXT %a, 16 + %b:_(s32) = COPY %a_assert_zext + %cond_wide:gpr(s32) = COPY $w1 + %cond:gpr(s1) = G_TRUNC %cond_wide(s32) + %select:_(s32) = G_SELECT %cond(s1), %a_assert_zext, %b + $w0 = COPY %select(s32) + RET_ReallyLR implicit $w0