diff --git a/llvm/lib/Target/AArch64/AArch64ExpandImm.cpp b/llvm/lib/Target/AArch64/AArch64ExpandImm.cpp index a7d72b59b1d5a..98016271a9d00 100644 --- a/llvm/lib/Target/AArch64/AArch64ExpandImm.cpp +++ b/llvm/lib/Target/AArch64/AArch64ExpandImm.cpp @@ -518,6 +518,14 @@ static inline void expandMOVImmSimple(uint64_t Imm, unsigned BitSize, Insn.push_back({ Opc, Imm16, AArch64_AM::getShifterImm(AArch64_AM::LSL, Shift) }); } + + // Now, we get 16-bit divided Imm. If high and low bits are same in + // 32-bit, there is an opportunity to reduce instruction. + if (Insn.size() > 2 && (Imm >> 32) == (Imm & 0xffffffffULL)) { + for (int Size = Insn.size(); Size > 2; Size--) + Insn.pop_back(); + Insn.push_back({AArch64::ORRXrs, 0, 32}); + } } /// Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more diff --git a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp index 03f0778bae59d..36957bb0f5a05 100644 --- a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +++ b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp @@ -168,6 +168,19 @@ bool AArch64ExpandPseudo::expandMOVImm(MachineBasicBlock &MBB, .addImm(I->Op2)); } break; + case AArch64::ORRWrs: + case AArch64::ORRXrs: { + Register DstReg = MI.getOperand(0).getReg(); + bool DstIsDead = MI.getOperand(0).isDead(); + MIBS.push_back( + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode)) + .addReg(DstReg, RegState::Define | + getDeadRegState(DstIsDead && LastItem) | + RenamableState) + .addReg(DstReg) + .addReg(DstReg) + .addImm(I->Op2)); + } break; case AArch64::ANDXri: case AArch64::EORXri: if (I->Op1 == 0) { diff --git a/llvm/test/CodeGen/AArch64/movimm-expand-ldst.ll b/llvm/test/CodeGen/AArch64/movimm-expand-ldst.ll new file mode 100644 index 0000000000000..b25ac96f97c7d --- /dev/null +++ b/llvm/test/CodeGen/AArch64/movimm-expand-ldst.ll @@ -0,0 +1,95 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=aarch64 %s -o - | FileCheck %s + +define i64 @test0x1234567812345678() { +; CHECK-LABEL: test0x1234567812345678: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #22136 // =0x5678 +; CHECK-NEXT: movk x0, #4660, lsl #16 +; CHECK-NEXT: orr x0, x0, x0, lsl #32 +; CHECK-NEXT: ret + ret i64 u0x1234567812345678 +} + +define i64 @test0xff3456ffff3456ff() { +; CHECK-LABEL: test0xff3456ffff3456ff: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #22271 // =0x56ff +; CHECK-NEXT: movk x0, #65332, lsl #16 +; CHECK-NEXT: orr x0, x0, x0, lsl #32 +; CHECK-NEXT: ret + ret i64 u0xff3456ffff3456ff +} + +define i64 @test0x00345600345600() { +; CHECK-LABEL: test0x00345600345600: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #22016 // =0x5600 +; CHECK-NEXT: movk x0, #52, lsl #16 +; CHECK-NEXT: movk x0, #13398, lsl #32 +; CHECK-NEXT: ret + ret i64 u0x00345600345600 +} + +define i64 @test0x5555555555555555() { +; CHECK-LABEL: test0x5555555555555555: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #6148914691236517205 // =0x5555555555555555 +; CHECK-NEXT: ret + ret i64 u0x5555555555555555 +} + +define i64 @test0x5055555550555555() { +; CHECK-LABEL: test0x5055555550555555: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #6148914691236517205 // =0x5555555555555555 +; CHECK-NEXT: and x0, x0, #0xf0fffffff0ffffff +; CHECK-NEXT: ret + ret i64 u0x5055555550555555 +} + +define i64 @test0x0000555555555555() { +; CHECK-LABEL: test0x0000555555555555: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #6148914691236517205 // =0x5555555555555555 +; CHECK-NEXT: movk x0, #0, lsl #48 +; CHECK-NEXT: ret + ret i64 u0x0000555555555555 +} + +define i64 @test0x0000555500005555() { +; CHECK-LABEL: test0x0000555500005555: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #21845 // =0x5555 +; CHECK-NEXT: movk x0, #21845, lsl #32 +; CHECK-NEXT: ret + ret i64 u0x0000555500005555 +} + +define i64 @testu0xffff5555ffff5555() { +; CHECK-LABEL: testu0xffff5555ffff5555: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #-43691 // =0xffffffffffff5555 +; CHECK-NEXT: movk x0, #21845, lsl #32 +; CHECK-NEXT: ret + ret i64 u0xffff5555ffff5555 +} + +define i64 @testuu0xfffff555f555f555() { +; CHECK-LABEL: testuu0xfffff555f555f555: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #-2731 // =0xfffffffffffff555 +; CHECK-NEXT: movk x0, #62805, lsl #16 +; CHECK-NEXT: movk x0, #62805, lsl #32 +; CHECK-NEXT: ret + ret i64 u0xfffff555f555f555 +} + +define i64 @testuu0xf555f555f555f555() { +; CHECK-LABEL: testuu0xf555f555f555f555: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #6148914691236517205 // =0x5555555555555555 +; CHECK-NEXT: orr x0, x0, #0xe001e001e001e001 +; CHECK-NEXT: ret + ret i64 u0xf555f555f555f555 +} diff --git a/llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir b/llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir new file mode 100644 index 0000000000000..1ec2a00f67690 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir @@ -0,0 +1,33 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 +# RUN: llc -mtriple=aarch64 -verify-machineinstrs -run-pass=aarch64-expand-pseudo -run-pass=aarch64-ldst-opt -debug-only=aarch64-ldst-opt %s -o - | FileCheck %s +--- +name: test_fold_repeating_constant_load +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0 + ; CHECK-LABEL: name: test_fold_repeating_constant_load + ; CHECK: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x0 = MOVZXi 49370, 0 + ; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 320, 16 + ; CHECK-NEXT: renamable $x0 = ORRXrs $x0, $x0, 32 + ; CHECK-NEXT: RET undef $lr, implicit $x0 + renamable $x0 = MOVi64imm 90284035103834330 + RET_ReallyLR implicit $x0 +... +--- +name: test_fold_repeating_constant_load_neg +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0 + ; CHECK-LABEL: name: test_fold_repeating_constant_load_neg + ; CHECK: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x0 = MOVZXi 320, 0 + ; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 49370, 16 + ; CHECK-NEXT: renamable $x0 = ORRXrs $x0, $x0, 32 + ; CHECK-NEXT: RET undef $lr, implicit $x0 + renamable $x0 = MOVi64imm -4550323095879417536 + RET_ReallyLR implicit $x0