diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h index 555be8be8885b..8855631859fcf 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -554,6 +554,11 @@ class CombinerHelper { /// Do constant folding when opportunities are exposed after MIR building. bool matchConstantFold(MachineInstr &MI, APInt &MatchInfo); + /// \returns true if it is possible to narrow the width of a scalar binop + /// feeding a G_AND instruction \p MI. + bool matchNarrowBinopFeedingAnd( + MachineInstr &MI, std::function &MatchInfo); + /// Try to transform \p MI by using all of the above /// combine functions. Returns true if changed. bool tryCombine(MachineInstr &MI); diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index d0328b1405afe..07de68fa1bf21 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -30,6 +30,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/DAGCombine.h" #include "llvm/CodeGen/ISDOpcodes.h" +#include "llvm/CodeGen/LowLevelType.h" #include "llvm/CodeGen/RuntimeLibcalls.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" @@ -2509,8 +2510,11 @@ class TargetLoweringBase { return false; } - virtual bool isTruncateFree(EVT FromVT, EVT ToVT) const { - return false; + virtual bool isTruncateFree(EVT FromVT, EVT ToVT) const { return false; } + virtual bool isTruncateFree(LLT FromTy, LLT ToTy, const DataLayout &DL, + LLVMContext &Ctx) const { + return isTruncateFree(getApproximateEVTForLLT(FromTy, DL, Ctx), + getApproximateEVTForLLT(ToTy, DL, Ctx)); } virtual bool isProfitableToHoist(Instruction *I) const { return true; } @@ -2586,8 +2590,11 @@ class TargetLoweringBase { return false; } - virtual bool isZExtFree(EVT FromTy, EVT ToTy) const { - return false; + virtual bool isZExtFree(EVT FromTy, EVT ToTy) const { return false; } + virtual bool isZExtFree(LLT FromTy, LLT ToTy, const DataLayout &DL, + LLVMContext &Ctx) const { + return isZExtFree(getApproximateEVTForLLT(FromTy, DL, Ctx), + getApproximateEVTForLLT(ToTy, DL, Ctx)); } /// Return true if sign-extension from FromTy to ToTy is cheaper than diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td index 13ebc43697c2f..e65073a1d28d0 100644 --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -197,6 +197,12 @@ def reduce_shl_of_extend : GICombineRule< [{ return Helper.matchCombineShlOfExtend(*${mi}, ${matchinfo}); }]), (apply [{ Helper.applyCombineShlOfExtend(*${mi}, ${matchinfo}); }])>; +def narrow_binop_feeding_and : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (wip_match_opcode G_AND):$root, + [{ return Helper.matchNarrowBinopFeedingAnd(*${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; + // [us]itofp(undef) = 0, because the result value is bounded. def undef_to_fp_zero : GICombineRule< (defs root:$root), @@ -698,7 +704,8 @@ def known_bits_simplifications : GICombineGroup<[ redundant_and, redundant_sext_inreg, redundant_or, urem_pow2_to_mask, zext_trunc_fold, icmp_to_true_false_known_bits]>; -def width_reduction_combines : GICombineGroup<[reduce_shl_of_extend]>; +def width_reduction_combines : GICombineGroup<[reduce_shl_of_extend, + narrow_binop_feeding_and]>; def phi_combines : GICombineGroup<[extend_through_phis]>; diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp index 23ff22fe3aa66..732b7ed5dd9d6 100644 --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -4344,6 +4344,97 @@ bool CombinerHelper::matchConstantFold(MachineInstr &MI, APInt &MatchInfo) { return true; } +bool CombinerHelper::matchNarrowBinopFeedingAnd( + MachineInstr &MI, std::function &MatchInfo) { + // Look for a binop feeding into an AND with a mask: + // + // %add = G_ADD %lhs, %rhs + // %and = G_AND %add, 000...11111111 + // + // Check if it's possible to perform the binop at a narrower width and zext + // back to the original width like so: + // + // %narrow_lhs = G_TRUNC %lhs + // %narrow_rhs = G_TRUNC %rhs + // %narrow_add = G_ADD %narrow_lhs, %narrow_rhs + // %new_add = G_ZEXT %narrow_add + // %and = G_AND %new_add, 000...11111111 + // + // This can allow later combines to eliminate the G_AND if it turns out + // that the mask is irrelevant. + assert(MI.getOpcode() == TargetOpcode::G_AND); + Register Dst = MI.getOperand(0).getReg(); + Register AndLHS = MI.getOperand(1).getReg(); + Register AndRHS = MI.getOperand(2).getReg(); + LLT WideTy = MRI.getType(Dst); + + // If the potential binop has more than one use, then it's possible that one + // of those uses will need its full width. + if (!WideTy.isScalar() || !MRI.hasOneNonDBGUse(AndLHS)) + return false; + + // Check if the LHS feeding the AND is impacted by the high bits that we're + // masking out. + // + // e.g. for 64-bit x, y: + // + // add_64(x, y) & 65535 == zext(add_16(trunc(x), trunc(y))) & 65535 + MachineInstr *LHSInst = getDefIgnoringCopies(AndLHS, MRI); + if (!LHSInst) + return false; + unsigned LHSOpc = LHSInst->getOpcode(); + switch (LHSOpc) { + default: + return false; + case TargetOpcode::G_ADD: + case TargetOpcode::G_SUB: + case TargetOpcode::G_MUL: + case TargetOpcode::G_AND: + case TargetOpcode::G_OR: + case TargetOpcode::G_XOR: + break; + } + + // Find the mask on the RHS. + auto Cst = getConstantVRegValWithLookThrough(AndRHS, MRI); + if (!Cst) + return false; + auto Mask = Cst->Value; + if (!Mask.isMask()) + return false; + + // No point in combining if there's nothing to truncate. + unsigned NarrowWidth = Mask.countTrailingOnes(); + if (NarrowWidth == WideTy.getSizeInBits()) + return false; + LLT NarrowTy = LLT::scalar(NarrowWidth); + + // Check if adding the zext + truncates could be harmful. + auto &MF = *MI.getMF(); + const auto &TLI = getTargetLowering(); + LLVMContext &Ctx = MF.getFunction().getContext(); + auto &DL = MF.getDataLayout(); + if (!TLI.isTruncateFree(WideTy, NarrowTy, DL, Ctx) || + !TLI.isZExtFree(NarrowTy, WideTy, DL, Ctx)) + return false; + if (!isLegalOrBeforeLegalizer({TargetOpcode::G_TRUNC, {NarrowTy, WideTy}}) || + !isLegalOrBeforeLegalizer({TargetOpcode::G_ZEXT, {WideTy, NarrowTy}})) + return false; + Register BinOpLHS = LHSInst->getOperand(1).getReg(); + Register BinOpRHS = LHSInst->getOperand(2).getReg(); + MatchInfo = [=, &MI](MachineIRBuilder &B) { + auto NarrowLHS = Builder.buildTrunc(NarrowTy, BinOpLHS); + auto NarrowRHS = Builder.buildTrunc(NarrowTy, BinOpRHS); + auto NarrowBinOp = + Builder.buildInstr(LHSOpc, {NarrowTy}, {NarrowLHS, NarrowRHS}); + auto Ext = Builder.buildZExt(WideTy, NarrowBinOp); + Observer.changingInstr(MI); + MI.getOperand(1).setReg(Ext.getReg(0)); + Observer.changedInstr(MI); + }; + return true; +} + bool CombinerHelper::tryCombine(MachineInstr &MI) { if (tryCombineCopy(MI)) return true; diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-narrow-binop-feeding-add.mir b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-narrow-binop-feeding-add.mir new file mode 100644 index 0000000000000..fb19cda303d36 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-narrow-binop-feeding-add.mir @@ -0,0 +1,332 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple aarch64 -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s + +... +--- +name: add_64_mask_32 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1 + ; CHECK-LABEL: name: add_64_mask_32 + ; CHECK: liveins: $x0, $x1 + ; CHECK: %binop_lhs:_(s64) = COPY $x0 + ; CHECK: %binop_rhs:_(s64) = COPY $x1 + ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC %binop_lhs(s64) + ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC %binop_rhs(s64) + ; CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[TRUNC]], [[TRUNC1]] + ; CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[ADD]](s32) + ; CHECK: $x0 = COPY [[ZEXT]](s64) + ; CHECK: RET_ReallyLR implicit $x0 + %binop_lhs:_(s64) = COPY $x0 + %binop_rhs:_(s64) = COPY $x1 + %mask_32:_(s64) = G_CONSTANT i64 4294967295 + %binop:_(s64) = G_ADD %binop_lhs, %binop_rhs + %and:_(s64) = G_AND %binop, %mask_32 + $x0 = COPY %and(s64) + RET_ReallyLR implicit $x0 +... +--- +name: sub_64_mask_32 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1 + ; CHECK-LABEL: name: sub_64_mask_32 + ; CHECK: liveins: $x0, $x1 + ; CHECK: %binop_lhs:_(s64) = COPY $x0 + ; CHECK: %binop_rhs:_(s64) = COPY $x1 + ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC %binop_lhs(s64) + ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC %binop_rhs(s64) + ; CHECK: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[TRUNC]], [[TRUNC1]] + ; CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[SUB]](s32) + ; CHECK: $x0 = COPY [[ZEXT]](s64) + ; CHECK: RET_ReallyLR implicit $x0 + %binop_lhs:_(s64) = COPY $x0 + %binop_rhs:_(s64) = COPY $x1 + %mask_32:_(s64) = G_CONSTANT i64 4294967295 + %binop:_(s64) = G_SUB %binop_lhs, %binop_rhs + %and:_(s64) = G_AND %binop, %mask_32 + $x0 = COPY %and(s64) + RET_ReallyLR implicit $x0 +... +--- +name: mul_64_mask_32 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1 + ; CHECK-LABEL: name: mul_64_mask_32 + ; CHECK: liveins: $x0, $x1 + ; CHECK: %binop_lhs:_(s64) = COPY $x0 + ; CHECK: %binop_rhs:_(s64) = COPY $x1 + ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC %binop_lhs(s64) + ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC %binop_rhs(s64) + ; CHECK: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[TRUNC]], [[TRUNC1]] + ; CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[MUL]](s32) + ; CHECK: $x0 = COPY [[ZEXT]](s64) + ; CHECK: RET_ReallyLR implicit $x0 + %binop_lhs:_(s64) = COPY $x0 + %binop_rhs:_(s64) = COPY $x1 + %mask_32:_(s64) = G_CONSTANT i64 4294967295 + %binop:_(s64) = G_MUL %binop_lhs, %binop_rhs + %and:_(s64) = G_AND %binop, %mask_32 + $x0 = COPY %and(s64) + RET_ReallyLR implicit $x0 +... +--- +name: and_64_mask_32 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1 + ; CHECK-LABEL: name: and_64_mask_32 + ; CHECK: liveins: $x0, $x1 + ; CHECK: %binop_lhs:_(s64) = COPY $x0 + ; CHECK: %binop_rhs:_(s64) = COPY $x1 + ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC %binop_lhs(s64) + ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC %binop_rhs(s64) + ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[TRUNC]], [[TRUNC1]] + ; CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[AND]](s32) + ; CHECK: $x0 = COPY [[ZEXT]](s64) + ; CHECK: RET_ReallyLR implicit $x0 + %binop_lhs:_(s64) = COPY $x0 + %binop_rhs:_(s64) = COPY $x1 + %mask_32:_(s64) = G_CONSTANT i64 4294967295 + %binop:_(s64) = G_AND %binop_lhs, %binop_rhs + %and:_(s64) = G_AND %binop, %mask_32 + $x0 = COPY %and(s64) + RET_ReallyLR implicit $x0 +... +--- +name: or_64_mask_32 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1 + ; CHECK-LABEL: name: or_64_mask_32 + ; CHECK: liveins: $x0, $x1 + ; CHECK: %binop_lhs:_(s64) = COPY $x0 + ; CHECK: %binop_rhs:_(s64) = COPY $x1 + ; CHECK: %mask_32:_(s64) = G_CONSTANT i64 4294967295 + ; CHECK: %binop:_(s64) = G_SUB %binop_lhs, %binop_rhs + ; CHECK: %and:_(s64) = G_OR %binop, %mask_32 + ; CHECK: $x0 = COPY %and(s64) + ; CHECK: RET_ReallyLR implicit $x0 + %binop_lhs:_(s64) = COPY $x0 + %binop_rhs:_(s64) = COPY $x1 + %mask_32:_(s64) = G_CONSTANT i64 4294967295 + %binop:_(s64) = G_SUB %binop_lhs, %binop_rhs + %and:_(s64) = G_OR %binop, %mask_32 + $x0 = COPY %and(s64) + RET_ReallyLR implicit $x0 +... +--- +name: xor_64_mask_32 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1 + ; CHECK-LABEL: name: xor_64_mask_32 + ; CHECK: liveins: $x0, $x1 + ; CHECK: %binop_lhs:_(s64) = COPY $x0 + ; CHECK: %binop_rhs:_(s64) = COPY $x1 + ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC %binop_lhs(s64) + ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC %binop_rhs(s64) + ; CHECK: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[TRUNC]], [[TRUNC1]] + ; CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[XOR]](s32) + ; CHECK: $x0 = COPY [[ZEXT]](s64) + ; CHECK: RET_ReallyLR implicit $x0 + %binop_lhs:_(s64) = COPY $x0 + %binop_rhs:_(s64) = COPY $x1 + %mask_32:_(s64) = G_CONSTANT i64 4294967295 + %binop:_(s64) = G_XOR %binop_lhs, %binop_rhs + %and:_(s64) = G_AND %binop, %mask_32 + $x0 = COPY %and(s64) + RET_ReallyLR implicit $x0 +... +--- +name: walk_thru_copy +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1 + ; CHECK-LABEL: name: walk_thru_copy + ; CHECK: liveins: $x0, $x1 + ; CHECK: %binop_lhs:_(s64) = COPY $x0 + ; CHECK: %binop_rhs:_(s64) = COPY $x1 + ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC %binop_lhs(s64) + ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC %binop_rhs(s64) + ; CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[TRUNC]], [[TRUNC1]] + ; CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[ADD]](s32) + ; CHECK: $x0 = COPY [[ZEXT]](s64) + ; CHECK: RET_ReallyLR implicit $x0 + %binop_lhs:_(s64) = COPY $x0 + %binop_rhs:_(s64) = COPY $x1 + %mask_32:_(s64) = G_CONSTANT i64 4294967295 + %binop:_(s64) = G_ADD %binop_lhs, %binop_rhs + %copy:_(s64) = COPY %binop + %and:_(s64) = G_AND %copy, %mask_32 + $x0 = COPY %and(s64) + RET_ReallyLR implicit $x0 +... +--- +name: dont_combine_zext_not_free_add_64_mask_16 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1 + ; CHECK-LABEL: name: dont_combine_zext_not_free_add_64_mask_16 + ; CHECK: liveins: $x0, $x1 + ; CHECK: %binop_lhs:_(s64) = COPY $x0 + ; CHECK: %binop_rhs:_(s64) = COPY $x1 + ; CHECK: %mask_16:_(s64) = G_CONSTANT i64 65535 + ; CHECK: %binop:_(s64) = G_ADD %binop_lhs, %binop_rhs + ; CHECK: %and:_(s64) = G_AND %binop, %mask_16 + ; CHECK: $x0 = COPY %and(s64) + ; CHECK: RET_ReallyLR implicit $x0 + %binop_lhs:_(s64) = COPY $x0 + %binop_rhs:_(s64) = COPY $x1 + %mask_16:_(s64) = G_CONSTANT i64 65535 + %binop:_(s64) = G_ADD %binop_lhs, %binop_rhs + %and:_(s64) = G_AND %binop, %mask_16 + $x0 = COPY %and(s64) + RET_ReallyLR implicit $x0 +... +--- +name: dont_combine_zext_not_free_add_64_mask_8 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1 + ; CHECK-LABEL: name: dont_combine_zext_not_free_add_64_mask_8 + ; CHECK: liveins: $x0, $x1 + ; CHECK: %binop_lhs:_(s64) = COPY $x0 + ; CHECK: %binop_rhs:_(s64) = COPY $x1 + ; CHECK: %mask_8:_(s64) = G_CONSTANT i64 255 + ; CHECK: %binop:_(s64) = G_ADD %binop_lhs, %binop_rhs + ; CHECK: %and:_(s64) = G_AND %binop, %mask_8 + ; CHECK: $x0 = COPY %and(s64) + ; CHECK: RET_ReallyLR implicit $x0 + %binop_lhs:_(s64) = COPY $x0 + %binop_rhs:_(s64) = COPY $x1 + %mask_8:_(s64) = G_CONSTANT i64 255 + %binop:_(s64) = G_ADD %binop_lhs, %binop_rhs + %and:_(s64) = G_AND %binop, %mask_8 + $x0 = COPY %and(s64) + RET_ReallyLR implicit $x0 +... +--- +name: dont_combine_not_a_mask +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1 + ; CHECK-LABEL: name: dont_combine_not_a_mask + ; CHECK: liveins: $x0, $x1 + ; CHECK: %binop_lhs:_(s64) = COPY $x0 + ; CHECK: %binop_rhs:_(s64) = COPY $x1 + ; CHECK: %not_a_mask:_(s64) = G_CONSTANT i64 26 + ; CHECK: %binop:_(s64) = G_ADD %binop_lhs, %binop_rhs + ; CHECK: %and:_(s64) = G_AND %binop, %not_a_mask + ; CHECK: $x0 = COPY %and(s64) + ; CHECK: RET_ReallyLR implicit $x0 + %binop_lhs:_(s64) = COPY $x0 + %binop_rhs:_(s64) = COPY $x1 + %not_a_mask:_(s64) = G_CONSTANT i64 26 + %binop:_(s64) = G_ADD %binop_lhs, %binop_rhs + %and:_(s64) = G_AND %binop, %not_a_mask + $x0 = COPY %and(s64) + RET_ReallyLR implicit $x0 +... +--- +name: dont_combine_more_than_one_use +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1 + ; CHECK-LABEL: name: dont_combine_more_than_one_use + ; CHECK: liveins: $x0, $x1 + ; CHECK: %binop_lhs:_(s64) = COPY $x0 + ; CHECK: %binop_rhs:_(s64) = COPY $x1 + ; CHECK: %not_a_mask:_(s64) = G_CONSTANT i64 26 + ; CHECK: %binop:_(s64) = G_ADD %binop_lhs, %binop_rhs + ; CHECK: %and:_(s64) = G_AND %binop, %not_a_mask + ; CHECK: %or:_(s64) = G_OR %and, %binop + ; CHECK: $x0 = COPY %or(s64) + ; CHECK: RET_ReallyLR implicit $x0 + %binop_lhs:_(s64) = COPY $x0 + %binop_rhs:_(s64) = COPY $x1 + %not_a_mask:_(s64) = G_CONSTANT i64 26 + %binop:_(s64) = G_ADD %binop_lhs, %binop_rhs + %and:_(s64) = G_AND %binop, %not_a_mask + %or:_(s64) = G_OR %and, %binop + $x0 = COPY %or(s64) + RET_ReallyLR implicit $x0 +... +--- +name: dont_combine_vector +tracksRegLiveness: true +body: | + bb.0: + liveins: $q0, $q1 + ; CHECK-LABEL: name: dont_combine_vector + ; CHECK: liveins: $q0, $q1 + ; CHECK: %binop_lhs:_(<2 x s64>) = COPY $q0 + ; CHECK: %binop_rhs:_(<2 x s64>) = COPY $q1 + ; CHECK: %mask_elt:_(s64) = G_CONSTANT i64 4294967295 + ; CHECK: %mask:_(<2 x s64>) = G_BUILD_VECTOR %mask_elt(s64), %mask_elt(s64) + ; CHECK: %binop:_(<2 x s64>) = G_ADD %binop_lhs, %binop_rhs + ; CHECK: %and:_(<2 x s64>) = G_AND %binop, %mask + ; CHECK: $q0 = COPY %and(<2 x s64>) + ; CHECK: RET_ReallyLR implicit $q0 + %binop_lhs:_(<2 x s64>) = COPY $q0 + %binop_rhs:_(<2 x s64>) = COPY $q1 + %mask_elt:_(s64) = G_CONSTANT i64 4294967295 + %mask:_(<2 x s64>) = G_BUILD_VECTOR %mask_elt, %mask_elt + %binop:_(<2 x s64>) = G_ADD %binop_lhs, %binop_rhs + %and:_(<2 x s64>) = G_AND %binop, %mask + $q0 = COPY %and(<2 x s64>) + RET_ReallyLR implicit $q0 +... +--- +name: dont_combine_add_64_mask_64 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1 + ; CHECK-LABEL: name: dont_combine_add_64_mask_64 + ; CHECK: liveins: $x0, $x1 + ; CHECK: %binop_lhs:_(s64) = COPY $x0 + ; CHECK: %binop_rhs:_(s64) = COPY $x1 + ; CHECK: %binop:_(s64) = G_ADD %binop_lhs, %binop_rhs + ; CHECK: $x0 = COPY %binop(s64) + ; CHECK: RET_ReallyLR implicit $x0 + %binop_lhs:_(s64) = COPY $x0 + %binop_rhs:_(s64) = COPY $x1 + %mask_64:_(s64) = G_CONSTANT i64 18446744073709551615 + %binop:_(s64) = G_ADD %binop_lhs, %binop_rhs + %and:_(s64) = G_AND %binop, %mask_64 + $x0 = COPY %and(s64) + RET_ReallyLR implicit $x0 +... +--- +name: dont_combine_copy_from_physreg +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1 + ; CHECK-LABEL: name: dont_combine_copy_from_physreg + ; CHECK: liveins: $x0, $x1 + ; CHECK: %copy_from_physreg:_(s64) = COPY $x0 + ; CHECK: %mask_32:_(s64) = G_CONSTANT i64 4294967295 + ; CHECK: %and:_(s64) = G_AND %copy_from_physreg, %mask_32 + ; CHECK: $x0 = COPY %and(s64) + ; CHECK: RET_ReallyLR implicit $x0 + %copy_from_physreg:_(s64) = COPY $x0 + %binop_rhs:_(s64) = COPY $x1 + %mask_32:_(s64) = G_CONSTANT i64 4294967295 + %copy:_(s64) = COPY %copy_from_physreg + %and:_(s64) = G_AND %copy, %mask_32 + $x0 = COPY %and(s64) + RET_ReallyLR implicit $x0