Index: lib/Target/AArch64/AArch64InstrInfo.cpp =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.cpp +++ lib/Target/AArch64/AArch64InstrInfo.cpp @@ -533,6 +533,14 @@ CC); } +/// Returns true if a MOVi32imm or MOVi64imm can be expanded to an ORRxx. +static bool canBeExpandedToORR(const MachineInstr *MI, unsigned BitSize) { + uint64_t Imm = MI->getOperand(1).getImm(); + uint64_t UImm = Imm << (64 - BitSize) >> (64 - BitSize); + uint64_t Encoding; + return AArch64_AM::processLogicalImmediate(UImm, BitSize, Encoding); +} + // FIXME: this implementation should be micro-architecture dependent, so a // micro-architecture target hook should be introduced here in future. bool AArch64InstrInfo::isAsCheapAsAMove(const MachineInstr *MI) const { @@ -573,6 +581,12 @@ case AArch64::ORRWrr: case AArch64::ORRXrr: return true; + // If MOVi32imm or MOVi64imm can be expanded into ORRWri or + // ORRXri, it is as cheap as MOV + case AArch64::MOVi32imm: + return canBeExpandedToORR(MI, 32); + case AArch64::MOVi64imm: + return canBeExpandedToORR(MI, 64); } llvm_unreachable("Unknown opcode to check as cheap as a move!"); Index: test/CodeGen/AArch64/arm64-coalescing-MOVi32imm.ll =================================================================== --- /dev/null +++ test/CodeGen/AArch64/arm64-coalescing-MOVi32imm.ll @@ -0,0 +1,18 @@ +; RUN: llc < %s | FileCheck %s + +; CHECK: orr w0, wzr, #0x1 +; CHECK-NEXT : bl foo +; CHECK-NEXT : orr w0, wzr, #0x1 +; CHECK-NEXT : bl foo + +target triple = "aarch64--linux-android" +declare i32 @foo(i32) + +; Function Attrs: nounwind uwtable +define i32 @main() { +entry: + %call = tail call i32 @foo(i32 1) + %call1 = tail call i32 @foo(i32 1) + ret i32 0 +} +