Index: lib/Target/AArch64/AArch64RedundantCopyElimination.cpp =================================================================== --- lib/Target/AArch64/AArch64RedundantCopyElimination.cpp +++ lib/Target/AArch64/AArch64RedundantCopyElimination.cpp @@ -154,14 +154,20 @@ // Track clobbered registers. trackRegDefs(PredI, ClobberedRegs, TRI); + bool IsCMN = false; switch (PredI.getOpcode()) { default: break; + // CMN is an alias for ADDS with a dead destination register. + case AArch64::ADDSWri: + case AArch64::ADDSXri: + IsCMN = true; // CMP is an alias for SUBS with a dead destination register. case AArch64::SUBSWri: case AArch64::SUBSXri: { - unsigned SrcReg = PredI.getOperand(1).getReg(); + MCPhysReg SrcReg = PredI.getOperand(1).getReg(); + // Must not be a symbolic immediate. if (!PredI.getOperand(2).isImm()) return None; @@ -176,8 +182,11 @@ return None; // We've found the Cmp that sets NZCV. + int32_t KnownImm = PredI.getOperand(2).getImm(); + if (IsCMN) + KnownImm = -KnownImm; FirstUse = PredI; - return RegImm(PredI.getOperand(1).getReg(), PredI.getOperand(2).getImm()); + return RegImm(SrcReg, KnownImm); } } Index: test/CodeGen/AArch64/machine-copy-remove.mir =================================================================== --- test/CodeGen/AArch64/machine-copy-remove.mir +++ test/CodeGen/AArch64/machine-copy-remove.mir @@ -535,3 +535,114 @@ bb.2: RET_ReallyLR +... +# Eliminate redundant MOVi32imm -1 in bb.1 +# Note: 32-bit compare/32-bit move imm +# Kill marker should be removed from compare. +# CHECK-LABEL: name: test19 +# CHECK: ADDSWri %w0, 1, 0, implicit-def %nzcv +# CHECK: bb.1: +# CHECK-NOT: MOVi32imm +name: test19 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %w0, %x1 + + dead %wzr = ADDSWri killed %w0, 1, 0, implicit-def %nzcv + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %w0 = MOVi32imm -1 + STRWui killed %w0, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# Eliminate redundant MOVi64imm -1 in bb.1 +# Note: 64-bit compare/64-bit move imm +# Kill marker should be removed from compare. +# CHECK-LABEL: name: test20 +# CHECK: ADDSXri %x0, 1, 0, implicit-def %nzcv +# CHECK: bb.1: +# CHECK-NOT: MOVi64imm +name: test20 +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1, %bb.2 + liveins: %x0, %x1 + + dead %xzr = ADDSXri killed %x0, 1, 0, implicit-def %nzcv + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %x0 = MOVi64imm -1 + STRXui killed %x0, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# Eliminate redundant MOVi32imm -1 in bb.1 +# Note: 64-bit compare/32-bit move imm +# Kill marker should be removed from compare. +# CHECK-LABEL: name: test21 +# CHECK: ADDSXri %x0, 1, 0, implicit-def %nzcv +# CHECK: bb.1: +# CHECK-NOT: MOVi32imm +name: test21 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %x0, %x1 + + dead %xzr = ADDSXri killed %x0, 1, 0, implicit-def %nzcv + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %w0 = MOVi32imm -1 + STRWui killed %w0, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# Don't eliminate MOVi64imm -1 in bb.1 as we don't necessarily know the upper 32-bits. +# Note: 32-bit compare/64-bit move imm +# CHECK-LABEL: name: test22 +# CHECK: bb.1: +# CHECK: MOVi64imm +name: test22 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %w0, %x1 + + dead %wzr = ADDSWri killed %w0, 1, 0, implicit-def %nzcv + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %x0 = MOVi64imm -1 + STRXui killed %x0, killed %x1, 0 + + bb.2: + RET_ReallyLR +...