diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -74,12 +74,35 @@ return false; Register DstReg = MI.getOperand(0).getReg(); Register SrcReg = MI.getOperand(1).getReg(); + + // Give up if either DstReg or SrcReg is a physical register. + if (Register::isPhysicalRegister(DstReg) || + Register::isPhysicalRegister(SrcReg)) + return false; + + // Give up the types don't match. LLT DstTy = MRI.getType(DstReg); LLT SrcTy = MRI.getType(SrcReg); - // Simple Copy Propagation. - // a(sx) = COPY b(sx) -> Replace all uses of a with b. - if (DstTy.isValid() && SrcTy.isValid() && DstTy == SrcTy) + // Give up if one has a valid LLT, but the other doesn't. + if (DstTy.isValid() != SrcTy.isValid()) + return false; + // Give up if the types don't match. + if (DstTy.isValid() && SrcTy.isValid() && DstTy != SrcTy) + return false; + + // Get the register banks and classes. + const RegisterBank *DstBank = MRI.getRegBankOrNull(DstReg); + const RegisterBank *SrcBank = MRI.getRegBankOrNull(SrcReg); + const TargetRegisterClass *DstRC = MRI.getRegClassOrNull(DstReg); + const TargetRegisterClass *SrcRC = MRI.getRegClassOrNull(SrcReg); + + // Replace if the register constraints match. + if ((SrcRC == DstRC) && (SrcBank == DstBank)) return true; + // Replace if DstReg has no constraints. + if (!DstBank && !DstRC) + return true; + return false; } void CombinerHelper::applyCombineCopy(MachineInstr &MI) { diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-copy.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-copy.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-copy.mir @@ -0,0 +1,86 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -o - -march=aarch64 -run-pass=aarch64-prelegalizer-combiner %s | FileCheck %s + +# Make sure we don't lose the register bank constraints when +# combining COPY instructions. +--- +name: test_none_none +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_none_none + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK: $x0 = COPY [[COPY]](s64) + %0:_(s64) = COPY $x0 + %1:_(s64) = COPY %0(s64) + $x0 = COPY %1(s64) +... +--- +name: test_gpr_none +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_gpr_none + ; CHECK: [[COPY:%[0-9]+]]:gpr(s64) = COPY $x0 + ; CHECK: $x0 = COPY [[COPY]](s64) + %0:gpr(s64) = COPY $x0 + %1:_(s64) = COPY %0(s64) + $x0 = COPY %1(s64) +... +--- +name: test_none_gpr +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_none_gpr + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK: [[COPY1:%[0-9]+]]:gpr(s64) = COPY [[COPY]](s64) + ; CHECK: $x0 = COPY [[COPY1]](s64) + %0:_(s64) = COPY $x0 + %1:gpr(s64) = COPY %0(s64) + $x0 = COPY %1(s64) +... +--- +name: test_fpr_gpr +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_fpr_gpr + ; CHECK: [[COPY:%[0-9]+]]:fpr(s64) = COPY $x0 + ; CHECK: [[COPY1:%[0-9]+]]:gpr(s64) = COPY [[COPY]](s64) + ; CHECK: $x0 = COPY [[COPY1]](s64) + %0:fpr(s64) = COPY $x0 + %1:gpr(s64) = COPY %0(s64) + $x0 = COPY %1(s64) +... +--- +name: test_gpr64_gpr64_dst_no_llt +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_gpr64_gpr64_dst_no_llt + ; CHECK: [[COPY:%[0-9]+]]:gpr64(s64) = COPY $x0 + ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY [[COPY]](s64) + ; CHECK: $x0 = COPY [[COPY1]] + %0:gpr64(s64) = COPY $x0 + %1:gpr64 = COPY %0(s64) + $x0 = COPY %1 +... +--- +name: test_gpr64_gpr64_src_no_llt +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_gpr64_gpr64_src_no_llt + ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK: [[COPY1:%[0-9]+]]:gpr64(s64) = COPY [[COPY]] + ; CHECK: $x0 = COPY [[COPY1]](s64) + %0:gpr64 = COPY $x0 + %1:gpr64(s64) = COPY %0 + $x0 = COPY %1(s64) +... +--- +name: test_gpr64_gpr64_both_no_llt +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_gpr64_gpr64_both_no_llt + ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK: $x0 = COPY [[COPY]] + %0:gpr64 = COPY $x0 + %1:gpr64 = COPY %0 + $x0 = COPY %1 +...