Index: llvm/trunk/include/llvm/CodeGen/MachineInstr.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineInstr.h +++ llvm/trunk/include/llvm/CodeGen/MachineInstr.h @@ -322,6 +322,11 @@ return Operands[i]; } + /// Returns the total number of definitions. + unsigned getNumDefs() const { + return getNumExplicitDefs() + MCID->getNumImplicitDefs(); + } + /// Return true if operand \p OpIdx is a subregister index. bool isOperandSubregIdx(unsigned OpIdx) const { assert(getOperand(OpIdx).getType() == MachineOperand::MO_Immediate && @@ -340,6 +345,9 @@ /// Returns the number of non-implicit operands. unsigned getNumExplicitOperands() const; + /// Returns the number of non-implicit definitions. + unsigned getNumExplicitDefs() const; + /// iterator/begin/end - Iterate over all operands of a machine instruction. using mop_iterator = MachineOperand *; using const_mop_iterator = const MachineOperand *; @@ -374,31 +382,29 @@ /// Implicit definition are not included! iterator_range defs() { return make_range(operands_begin(), - operands_begin() + getDesc().getNumDefs()); + operands_begin() + getNumExplicitDefs()); } /// \copydoc defs() iterator_range defs() const { return make_range(operands_begin(), - operands_begin() + getDesc().getNumDefs()); + operands_begin() + getNumExplicitDefs()); } /// Returns a range that includes all operands that are register uses. /// This may include unrelated operands which are not register uses. iterator_range uses() { - return make_range(operands_begin() + getDesc().getNumDefs(), - operands_end()); + return make_range(operands_begin() + getNumExplicitDefs(), operands_end()); } /// \copydoc uses() iterator_range uses() const { - return make_range(operands_begin() + getDesc().getNumDefs(), - operands_end()); + return make_range(operands_begin() + getNumExplicitDefs(), operands_end()); } iterator_range explicit_uses() { - return make_range(operands_begin() + getDesc().getNumDefs(), - operands_begin() + getNumExplicitOperands() ); + return make_range(operands_begin() + getNumExplicitDefs(), + operands_begin() + getNumExplicitOperands()); } iterator_range explicit_uses() const { - return make_range(operands_begin() + getDesc().getNumDefs(), - operands_begin() + getNumExplicitOperands() ); + return make_range(operands_begin() + getNumExplicitDefs(), + operands_begin() + getNumExplicitOperands()); } /// Returns the number of the operand iterator \p I points to. Index: llvm/trunk/lib/CodeGen/MachineCSE.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MachineCSE.cpp +++ llvm/trunk/lib/CodeGen/MachineCSE.cpp @@ -550,8 +550,7 @@ // Check if it's profitable to perform this CSE. bool DoCSE = true; - unsigned NumDefs = MI->getDesc().getNumDefs() + - MI->getDesc().getNumImplicitDefs(); + unsigned NumDefs = MI->getNumDefs(); for (unsigned i = 0, e = MI->getNumOperands(); NumDefs && i != e; ++i) { MachineOperand &MO = MI->getOperand(i); Index: llvm/trunk/lib/CodeGen/MachineInstr.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MachineInstr.cpp +++ llvm/trunk/lib/CodeGen/MachineInstr.cpp @@ -519,21 +519,39 @@ getParent()->erase_instr(this); } -/// getNumExplicitOperands - Returns the number of non-implicit operands. -/// unsigned MachineInstr::getNumExplicitOperands() const { unsigned NumOperands = MCID->getNumOperands(); if (!MCID->isVariadic()) return NumOperands; - for (unsigned i = NumOperands, e = getNumOperands(); i != e; ++i) { - const MachineOperand &MO = getOperand(i); - if (!MO.isReg() || !MO.isImplicit()) - NumOperands++; + for (unsigned I = NumOperands, E = getNumOperands(); I != E; ++I) { + const MachineOperand &MO = getOperand(I); + // The operands must always be in the following order: + // - explicit reg defs, + // - other explicit operands (reg uses, immediates, etc.), + // - implicit reg defs + // - implicit reg uses + if (MO.isReg() && MO.isImplicit()) + break; + ++NumOperands; } return NumOperands; } +unsigned MachineInstr::getNumExplicitDefs() const { + unsigned NumDefs = MCID->getNumDefs(); + if (!MCID->isVariadic()) + return NumDefs; + + for (unsigned I = NumDefs, E = getNumOperands(); I != E; ++I) { + const MachineOperand &MO = getOperand(I); + if (!MO.isReg() || !MO.isDef() || MO.isImplicit()) + break; + ++NumDefs; + } + return NumDefs; +} + void MachineInstr::bundleWithPred() { assert(!isBundledWithPred() && "MI is already bundled with its predecessor"); setFlag(BundledPred); Index: llvm/trunk/test/CodeGen/AArch64/GlobalISel/machine-cse-mid-pipeline.mir =================================================================== --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/machine-cse-mid-pipeline.mir +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/machine-cse-mid-pipeline.mir @@ -179,3 +179,102 @@ $w0 = COPY %4 RET_ReallyLR implicit $w0 ... +--- +name: variadic_defs_unmerge_vector +legalized: true +regBankSelected: false +selected: false +body: | + ; CHECK-LABEL: name: variadic_defs_unmerge_vector + ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $d0 + ; CHECK-NEXT: [[UV0:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; CHECK-NEXT: [[ANYEXT0:%[0-9]+]]:_(s32) = G_ANYEXT [[UV0]](s16) + ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[UV1]](s16) + ; CHECK-NEXT: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[UV2]](s16) + ; CHECK-NEXT: [[ANYEXT3:%[0-9]+]]:_(s32) = G_ANYEXT [[UV3]](s16) + ; CHECK-NEXT: [[ADD0:%[0-9]+]]:_(s32) = G_ADD [[ANYEXT0]], [[ANYEXT1]] + ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ANYEXT2]], [[ANYEXT3]] + ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD0]], [[ADD1]] + ; CHECK-NEXT: $w0 = COPY [[ADD2]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 + bb.0: + %0 :_(<4 x s16>) = COPY $d0 + %1 :_(s16), %2 :_(s16), %3 :_(s16), %4 :_(s16) = G_UNMERGE_VALUES %0(<4 x s16>) + %5 :_(s16), %6 :_(s16), %7 :_(s16), %8 :_(s16) = G_UNMERGE_VALUES %0(<4 x s16>) + %9 :_(s16), %10:_(s16), %11:_(s16), %12:_(s16) = G_UNMERGE_VALUES %0(<4 x s16>) + %13:_(s16), %14:_(s16), %15:_(s16), %16:_(s16) = G_UNMERGE_VALUES %0(<4 x s16>) + %17:_(s32) = G_ANYEXT %1 (s16) + %18:_(s32) = G_ANYEXT %6 (s16) + %19:_(s32) = G_ANYEXT %11(s16) + %20:_(s32) = G_ANYEXT %16(s16) + %21:_(s32) = G_ADD %17, %18 + %22:_(s32) = G_ADD %19, %20 + %23:_(s32) = G_ADD %21, %22 + $w0 = COPY %23(s32) + RET_ReallyLR implicit $w0 +... +--- +name: variadic_defs_unmerge_scalar +legalized: true +regBankSelected: false +selected: false +body: | + ; CHECK-LABEL: name: variadic_defs_unmerge_scalar + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $d0 + ; CHECK-NEXT: [[UV0:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](s64) + ; CHECK-NEXT: [[ANYEXT0:%[0-9]+]]:_(s32) = G_ANYEXT [[UV0]](s16) + ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[UV1]](s16) + ; CHECK-NEXT: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[UV2]](s16) + ; CHECK-NEXT: [[ANYEXT3:%[0-9]+]]:_(s32) = G_ANYEXT [[UV3]](s16) + ; CHECK-NEXT: [[ADD0:%[0-9]+]]:_(s32) = G_ADD [[ANYEXT0]], [[ANYEXT1]] + ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ANYEXT2]], [[ANYEXT3]] + ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD0]], [[ADD1]] + ; CHECK-NEXT: $w0 = COPY [[ADD2]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 + bb.0: + %0 :_(s64) = COPY $d0 + %1 :_(s16), %2 :_(s16), %3 :_(s16), %4 :_(s16) = G_UNMERGE_VALUES %0(s64) + %5 :_(s16), %6 :_(s16), %7 :_(s16), %8 :_(s16) = G_UNMERGE_VALUES %0(s64) + %9 :_(s16), %10:_(s16), %11:_(s16), %12:_(s16) = G_UNMERGE_VALUES %0(s64) + %13:_(s16), %14:_(s16), %15:_(s16), %16:_(s16) = G_UNMERGE_VALUES %0(s64) + %17:_(s32) = G_ANYEXT %1 (s16) + %18:_(s32) = G_ANYEXT %6 (s16) + %19:_(s32) = G_ANYEXT %11(s16) + %20:_(s32) = G_ANYEXT %16(s16) + %21:_(s32) = G_ADD %17, %18 + %22:_(s32) = G_ADD %19, %20 + %23:_(s32) = G_ADD %21, %22 + $w0 = COPY %23(s32) + RET_ReallyLR implicit $w0 +... +--- +name: variadic_defs_unmerge_scalar_asym +legalized: true +regBankSelected: false +selected: false +body: | + ; CHECK-LABEL: name: variadic_defs_unmerge_scalar_asym + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $d0 + ; CHECK-NEXT: [[UV0:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](s64) + ; CHECK-NEXT: [[UV01:%[0-9]+]]:_(s32), [[UV23:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](s64) + ; CHECK-NEXT: [[ANYEXT0:%[0-9]+]]:_(s32) = G_ANYEXT [[UV0]](s16) + ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[UV1]](s16) + ; CHECK-NEXT: [[ADD0:%[0-9]+]]:_(s32) = G_ADD [[ANYEXT0]], [[ANYEXT1]] + ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[UV01]], [[UV23]] + ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD0]], [[ADD1]] + ; CHECK-NEXT: $w0 = COPY [[ADD2]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 + bb.0: + %0 :_(s64) = COPY $d0 + %1 :_(s16), %2 :_(s16), %3 :_(s16), %4 :_(s16) = G_UNMERGE_VALUES %0(s64) + %9 :_(s32), %10:_(s32) = G_UNMERGE_VALUES %0(s64) + %5 :_(s16), %6 :_(s16), %7 :_(s16), %8 :_(s16) = G_UNMERGE_VALUES %0(s64) + %11:_(s32), %12:_(s32) = G_UNMERGE_VALUES %0(s64) + %17:_(s32) = G_ANYEXT %1 (s16) + %18:_(s32) = G_ANYEXT %6 (s16) + %21:_(s32) = G_ADD %17, %18 + %22:_(s32) = G_ADD %9, %12 + %23:_(s32) = G_ADD %21, %22 + $w0 = COPY %23(s32) + RET_ReallyLR implicit $w0 +...