summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetar Avramovic <Petar.Avramovic@amd.com>2021-08-05 13:59:37 +0200
committerPetar Avramovic <Petar.Avramovic@amd.com>2021-08-05 15:05:45 +0200
commit66de26b1f9ecf22193aea2edfac03db03f138feb (patch)
tree9a5b0d6391f7a0eec663d2e50cfdce2871b89006
parent7b73ca3043fecfc5fa6bbf5b28edfee61a83ff9f (diff)
downloadllvm-66de26b1f9ecf22193aea2edfac03db03f138feb.tar.gz
GlobalISel: Fix matchEqualDefs for instructions with multiple defs
Instructions that produceSameValue produce same values for operands with same index. matchEqualDefs used to return true for any two values from different instructions that produce same values. Fix this by checking if values are defined by operands with the same index. Differential Revision: https://reviews.llvm.org/D107362
-rw-r--r--llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp22
-rw-r--r--llvm/test/CodeGen/AMDGPU/GlobalISel/postlegalizercombiner-select.mir46
2 files changed, 63 insertions, 5 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index c816f5b71b3d..f0d97e573645 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -2659,12 +2659,14 @@ bool CombinerHelper::matchEqualDefs(const MachineOperand &MOP1,
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;
+ MachineInstr *I1 = InstAndDef1->MI;
+ MachineInstr *I2 = InstAndDef2->MI;
// Handle a case like this:
//
@@ -2724,7 +2726,17 @@ bool CombinerHelper::matchEqualDefs(const MachineOperand &MOP1,
//
// 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:_(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) {
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/postlegalizercombiner-select.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/postlegalizercombiner-select.mir
index 1941ad593f96..75840bfda563 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/postlegalizercombiner-select.mir
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/postlegalizercombiner-select.mir
@@ -50,3 +50,49 @@ body: |
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
+...