Index: llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -2659,21 +2659,14 @@ const MachineOperand &MOP2) { if (!MOP1.isReg() || !MOP2.isReg()) return false; - MachineInstr *I1 = getDefIgnoringCopies(MOP1.getReg(), MRI); - if (!I1) + auto InstAndDef1 = getDefSrcRegIgnoringCopies(MOP1.getReg(), MRI); + if (!InstAndDef1) return false; - MachineInstr *I2 = getDefIgnoringCopies(MOP2.getReg(), MRI); - if (!I2) + auto InstAndDef2 = getDefSrcRegIgnoringCopies(MOP2.getReg(), MRI); + if (!InstAndDef2) return false; - - // Handle a case like this: - // - // %0:_(s64), %1:_(s64) = G_UNMERGE_VALUES %2:_(<2 x s64>) - // - // Even though %0 and %1 are produced by the same instruction they are not - // the same values. - if (I1 == I2) - return MOP1.getReg() == MOP2.getReg(); + MachineInstr *I1 = InstAndDef1->MI; + MachineInstr *I2 = InstAndDef2->MI; // If we have an instruction which loads or stores, we can't guarantee that // it is identical. @@ -2724,7 +2717,22 @@ // // On the off-chance that there's some target instruction feeding into the // instruction, let's use produceSameValue instead of isIdenticalTo. - return Builder.getTII().produceSameValue(*I1, *I2, &MRI); + if (Builder.getTII().produceSameValue(*I1, *I2, &MRI)) { + // Handle instructions with multiple defs that produce same values. Values + // are same for operands with same index. + // + // %0:_(s64), %1:_(s64) = G_UNMERGE_VALUES %2:_(<2 x s64>) + // Even though %0 and %1 are produced by the same instruction they are not + // the same values. + // + // %0:_(s8), %1:_(s8), %2:_(s8), %3:_(s8) = G_UNMERGE_VALUES %4:_(<4 x s8>) + // %5:_(s8), %6:_(s8), %7:_(s8), %8:_(s8) = G_UNMERGE_VALUES %4:_(<4 x s8>) + // I1 and I2 are different instructions but produce same values, + // %1 and %6 are same, %1 and %7 are not the same value. + return I1->findRegisterDefOperandIdx(InstAndDef1->Reg) == + I2->findRegisterDefOperandIdx(InstAndDef2->Reg); + } + return false; } bool CombinerHelper::matchConstantOp(const MachineOperand &MOP, int64_t C) { Index: llvm/test/CodeGen/AMDGPU/GlobalISel/postlegalizercombiner-select.mir =================================================================== --- llvm/test/CodeGen/AMDGPU/GlobalISel/postlegalizercombiner-select.mir +++ llvm/test/CodeGen/AMDGPU/GlobalISel/postlegalizercombiner-select.mir @@ -50,3 +50,49 @@ SI_RETURN_TO_EPILOG $vgpr0 ... + +--- +name: select_different_result_from_different_unmerge_values_with_the_same_source +tracksRegLiveness: true +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4 + + ; GCN-LABEL: name: select_different_result_from_different_unmerge_values_with_the_same_source + ; GCN: liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4 + ; GCN: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + ; GCN: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr4 + ; GCN: [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[COPY1]](s32) + ; GCN: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<4 x s32>) + ; GCN: [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32), [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<4 x s32>) + ; GCN: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[TRUNC]](s1), [[UV1]], [[UV7]] + ; GCN: $vgpr0 = COPY [[SELECT]](s32) + %0:_(<4 x s32>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + %1:_(s32) = COPY $vgpr4 + %2:_(s1) = G_TRUNC %1:_(s32) + %3:_(s32), %4:_(s32), %5:_(s32), %6:_(s32) = G_UNMERGE_VALUES %0:_(<4 x s32>) + %7:_(s32), %8:_(s32), %9:_(s32), %10:_(s32) = G_UNMERGE_VALUES %0:_(<4 x s32>) + %11:_(s32) = G_SELECT %2:_(s1), %4:_, %10:_ + $vgpr0 = COPY %11 +... + +--- +name: select_same_result_from_different_unmerge_values_with_the_same_source +tracksRegLiveness: true +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4 + + ; GCN-LABEL: name: select_same_result_from_different_unmerge_values_with_the_same_source + ; GCN: liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4 + ; GCN: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + ; GCN: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<4 x s32>) + ; GCN: $vgpr0 = COPY [[UV1]](s32) + %0:_(<4 x s32>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + %1:_(s32) = COPY $vgpr4 + %2:_(s1) = G_TRUNC %1:_(s32) + %3:_(s32), %4:_(s32), %5:_(s32), %6:_(s32) = G_UNMERGE_VALUES %0:_(<4 x s32>) + %7:_(s32), %8:_(s32), %9:_(s32), %10:_(s32) = G_UNMERGE_VALUES %0:_(<4 x s32>) + %11:_(s32) = G_SELECT %2:_(s1), %4:_, %8:_ + $vgpr0 = COPY %11 +...