diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index 1423dc4996c2ed..e6900190f59dbf 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -4521,7 +4521,20 @@ AArch64InstrInfo::getLdStAmountOp(const MachineInstr &MI) { switch (MI.getOpcode()) { default: llvm_unreachable("Unexpected opcode"); + case AArch64::LDRBroX: case AArch64::LDRBBroX: + case AArch64::LDRSBXroX: + case AArch64::LDRSBWroX: + case AArch64::LDRHroX: + case AArch64::LDRHHroX: + case AArch64::LDRSHXroX: + case AArch64::LDRSHWroX: + case AArch64::LDRWroX: + case AArch64::LDRSroX: + case AArch64::LDRSWroX: + case AArch64::LDRDroX: + case AArch64::LDRXroX: + case AArch64::LDRQroX: return MI.getOperand(4); } } diff --git a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp index 8de3f8db84ae2b..eec97c45aff0a3 100644 --- a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp +++ b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp @@ -509,12 +509,38 @@ static unsigned getPreIndexedOpcode(unsigned Opc) { } static unsigned getBaseAddressOpcode(unsigned Opc) { - // TODO: Add more index address loads/stores. + // TODO: Add more index address stores. switch (Opc) { default: llvm_unreachable("Opcode has no base address equivalent!"); + case AArch64::LDRBroX: + return AArch64::LDRBui; case AArch64::LDRBBroX: return AArch64::LDRBBui; + case AArch64::LDRSBXroX: + return AArch64::LDRSBXui; + case AArch64::LDRSBWroX: + return AArch64::LDRSBWui; + case AArch64::LDRHroX: + return AArch64::LDRHui; + case AArch64::LDRHHroX: + return AArch64::LDRHHui; + case AArch64::LDRSHXroX: + return AArch64::LDRSHXui; + case AArch64::LDRSHWroX: + return AArch64::LDRSHWui; + case AArch64::LDRWroX: + return AArch64::LDRWui; + case AArch64::LDRSroX: + return AArch64::LDRSui; + case AArch64::LDRSWroX: + return AArch64::LDRSWui; + case AArch64::LDRDroX: + return AArch64::LDRDui; + case AArch64::LDRXroX: + return AArch64::LDRXui; + case AArch64::LDRQroX: + return AArch64::LDRQui; } } @@ -766,10 +792,31 @@ static bool isMergeableIndexLdSt(MachineInstr &MI, int &Scale) { default: return false; // Scaled instructions. - // TODO: Add more index address loads/stores. + // TODO: Add more index address stores. + case AArch64::LDRBroX: case AArch64::LDRBBroX: + case AArch64::LDRSBXroX: + case AArch64::LDRSBWroX: Scale = 1; return true; + case AArch64::LDRHroX: + case AArch64::LDRHHroX: + case AArch64::LDRSHXroX: + case AArch64::LDRSHWroX: + Scale = 2; + return true; + case AArch64::LDRWroX: + case AArch64::LDRSroX: + case AArch64::LDRSWroX: + Scale = 4; + return true; + case AArch64::LDRDroX: + case AArch64::LDRXroX: + Scale = 8; + return true; + case AArch64::LDRQroX: + Scale = 16; + return true; } } @@ -2223,7 +2270,9 @@ bool AArch64LoadStoreOpt::isMatchingMovConstInsn(MachineInstr &MemMI, return false; MBBI = prev_nodbg(MBBI, B); MachineInstr &MovzMI = *MBBI; - if (MovzMI.getOpcode() == AArch64::MOVZWi) { + // Make sure the MOVKWi and MOVZWi set the same register. + if (MovzMI.getOpcode() == AArch64::MOVZWi && + MovzMI.getOperand(0).getReg() == MI.getOperand(0).getReg()) { unsigned Low = MovzMI.getOperand(1).getImm(); unsigned High = MI.getOperand(2).getImm() << MI.getOperand(3).getImm(); Offset = High + Low; diff --git a/llvm/test/CodeGen/AArch64/arm64-addrmode.ll b/llvm/test/CodeGen/AArch64/arm64-addrmode.ll index 2181eaaee7db68..bfef61abd8c129 100644 --- a/llvm/test/CodeGen/AArch64/arm64-addrmode.ll +++ b/llvm/test/CodeGen/AArch64/arm64-addrmode.ll @@ -239,9 +239,8 @@ define i32 @LdOffset_i8_zext32(ptr %a) { define i32 @LdOffset_i8_sext32(ptr %a) { ; CHECK-LABEL: LdOffset_i8_sext32: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #56952 // =0xde78 -; CHECK-NEXT: movk w8, #15, lsl #16 -; CHECK-NEXT: ldrsb w0, [x0, x8] +; CHECK-NEXT: add x8, x0, #253, lsl #12 // =1036288 +; CHECK-NEXT: ldrsb w0, [x8, #3704] ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds i8, ptr %a, i64 1039992 %val = load i8, ptr %arrayidx, align 1 @@ -266,9 +265,8 @@ define i64 @LdOffset_i8_zext64(ptr %a) { define i64 @LdOffset_i8_sext64(ptr %a) { ; CHECK-LABEL: LdOffset_i8_sext64: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #56952 // =0xde78 -; CHECK-NEXT: movk w8, #15, lsl #16 -; CHECK-NEXT: ldrsb x0, [x0, x8] +; CHECK-NEXT: add x8, x0, #253, lsl #12 // =1036288 +; CHECK-NEXT: ldrsb x0, [x8, #3704] ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds i8, ptr %a, i64 1039992 %val = load i8, ptr %arrayidx, align 1 @@ -280,9 +278,8 @@ define i64 @LdOffset_i8_sext64(ptr %a) { define i16 @LdOffset_i16(ptr %a) { ; CHECK-LABEL: LdOffset_i16: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #48368 // =0xbcf0 -; CHECK-NEXT: movk w8, #31, lsl #16 -; CHECK-NEXT: ldrh w0, [x0, x8] +; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576 +; CHECK-NEXT: ldrh w0, [x8, #7408] ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992 %val = load i16, ptr %arrayidx, align 2 @@ -293,9 +290,8 @@ define i16 @LdOffset_i16(ptr %a) { define i32 @LdOffset_i16_zext32(ptr %a) { ; CHECK-LABEL: LdOffset_i16_zext32: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #48368 // =0xbcf0 -; CHECK-NEXT: movk w8, #31, lsl #16 -; CHECK-NEXT: ldrh w0, [x0, x8] +; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576 +; CHECK-NEXT: ldrh w0, [x8, #7408] ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992 %val = load i16, ptr %arrayidx, align 2 @@ -307,9 +303,8 @@ define i32 @LdOffset_i16_zext32(ptr %a) { define i32 @LdOffset_i16_sext32(ptr %a) { ; CHECK-LABEL: LdOffset_i16_sext32: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #48368 // =0xbcf0 -; CHECK-NEXT: movk w8, #31, lsl #16 -; CHECK-NEXT: ldrsh w0, [x0, x8] +; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576 +; CHECK-NEXT: ldrsh w0, [x8, #7408] ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992 %val = load i16, ptr %arrayidx, align 2 @@ -321,9 +316,8 @@ define i32 @LdOffset_i16_sext32(ptr %a) { define i64 @LdOffset_i16_zext64(ptr %a) { ; CHECK-LABEL: LdOffset_i16_zext64: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #48368 // =0xbcf0 -; CHECK-NEXT: movk w8, #31, lsl #16 -; CHECK-NEXT: ldrh w0, [x0, x8] +; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576 +; CHECK-NEXT: ldrh w0, [x8, #7408] ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992 %val = load i16, ptr %arrayidx, align 2 @@ -335,9 +329,8 @@ define i64 @LdOffset_i16_zext64(ptr %a) { define i64 @LdOffset_i16_sext64(ptr %a) { ; CHECK-LABEL: LdOffset_i16_sext64: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #48368 // =0xbcf0 -; CHECK-NEXT: movk w8, #31, lsl #16 -; CHECK-NEXT: ldrsh x0, [x0, x8] +; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576 +; CHECK-NEXT: ldrsh x0, [x8, #7408] ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992 %val = load i16, ptr %arrayidx, align 2 @@ -349,9 +342,8 @@ define i64 @LdOffset_i16_sext64(ptr %a) { define i32 @LdOffset_i32(ptr %a) { ; CHECK-LABEL: LdOffset_i32: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #31200 // =0x79e0 -; CHECK-NEXT: movk w8, #63, lsl #16 -; CHECK-NEXT: ldr w0, [x0, x8] +; CHECK-NEXT: add x8, x0, #1012, lsl #12 // =4145152 +; CHECK-NEXT: ldr w0, [x8, #14816] ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds i32, ptr %a, i64 1039992 %val = load i32, ptr %arrayidx, align 4 @@ -362,9 +354,8 @@ define i32 @LdOffset_i32(ptr %a) { define i64 @LdOffset_i32_zext64(ptr %a) { ; CHECK-LABEL: LdOffset_i32_zext64: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #31200 // =0x79e0 -; CHECK-NEXT: movk w8, #63, lsl #16 -; CHECK-NEXT: ldr w0, [x0, x8] +; CHECK-NEXT: add x8, x0, #1012, lsl #12 // =4145152 +; CHECK-NEXT: ldr w0, [x8, #14816] ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds i32, ptr %a, i64 1039992 %val = load i32, ptr %arrayidx, align 2 @@ -376,9 +367,8 @@ define i64 @LdOffset_i32_zext64(ptr %a) { define i64 @LdOffset_i32_sext64(ptr %a) { ; CHECK-LABEL: LdOffset_i32_sext64: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #31200 // =0x79e0 -; CHECK-NEXT: movk w8, #63, lsl #16 -; CHECK-NEXT: ldrsw x0, [x0, x8] +; CHECK-NEXT: add x8, x0, #1012, lsl #12 // =4145152 +; CHECK-NEXT: ldrsw x0, [x8, #14816] ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds i32, ptr %a, i64 1039992 %val = load i32, ptr %arrayidx, align 2 @@ -390,9 +380,8 @@ define i64 @LdOffset_i32_sext64(ptr %a) { define i64 @LdOffset_i64(ptr %a) { ; CHECK-LABEL: LdOffset_i64: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #62400 // =0xf3c0 -; CHECK-NEXT: movk w8, #126, lsl #16 -; CHECK-NEXT: ldr x0, [x0, x8] +; CHECK-NEXT: add x8, x0, #2024, lsl #12 // =8290304 +; CHECK-NEXT: ldr x0, [x8, #29632] ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds i64, ptr %a, i64 1039992 %val = load i64, ptr %arrayidx, align 4 @@ -403,9 +392,8 @@ define i64 @LdOffset_i64(ptr %a) { define <2 x i32> @LdOffset_v2i32(ptr %a) { ; CHECK-LABEL: LdOffset_v2i32: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #62400 // =0xf3c0 -; CHECK-NEXT: movk w8, #126, lsl #16 -; CHECK-NEXT: ldr d0, [x0, x8] +; CHECK-NEXT: add x8, x0, #2024, lsl #12 // =8290304 +; CHECK-NEXT: ldr d0, [x8, #29632] ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds <2 x i32>, ptr %a, i64 1039992 %val = load <2 x i32>, ptr %arrayidx, align 4 @@ -416,9 +404,8 @@ define <2 x i32> @LdOffset_v2i32(ptr %a) { define <2 x i64> @LdOffset_v2i64(ptr %a) { ; CHECK-LABEL: LdOffset_v2i64: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #59264 // =0xe780 -; CHECK-NEXT: movk w8, #253, lsl #16 -; CHECK-NEXT: ldr q0, [x0, x8] +; CHECK-NEXT: add x8, x0, #4048, lsl #12 // =16580608 +; CHECK-NEXT: ldr q0, [x8, #59264] ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds <2 x i64>, ptr %a, i64 1039992 %val = load <2 x i64>, ptr %arrayidx, align 4 @@ -429,9 +416,8 @@ define <2 x i64> @LdOffset_v2i64(ptr %a) { define double @LdOffset_i8_f64(ptr %a) { ; CHECK-LABEL: LdOffset_i8_f64: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #56952 // =0xde78 -; CHECK-NEXT: movk w8, #15, lsl #16 -; CHECK-NEXT: ldrsb w8, [x0, x8] +; CHECK-NEXT: add x8, x0, #253, lsl #12 // =1036288 +; CHECK-NEXT: ldrsb w8, [x8, #3704] ; CHECK-NEXT: scvtf d0, w8 ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds i8, ptr %a, i64 1039992 @@ -444,9 +430,8 @@ define double @LdOffset_i8_f64(ptr %a) { define double @LdOffset_i16_f64(ptr %a) { ; CHECK-LABEL: LdOffset_i16_f64: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #48368 // =0xbcf0 -; CHECK-NEXT: movk w8, #31, lsl #16 -; CHECK-NEXT: ldrsh w8, [x0, x8] +; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576 +; CHECK-NEXT: ldrsh w8, [x8, #7408] ; CHECK-NEXT: scvtf d0, w8 ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992 @@ -459,9 +444,8 @@ define double @LdOffset_i16_f64(ptr %a) { define double @LdOffset_i32_f64(ptr %a) { ; CHECK-LABEL: LdOffset_i32_f64: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #31200 // =0x79e0 -; CHECK-NEXT: movk w8, #63, lsl #16 -; CHECK-NEXT: ldr s0, [x0, x8] +; CHECK-NEXT: add x8, x0, #1012, lsl #12 // =4145152 +; CHECK-NEXT: ldr s0, [x8, #14816] ; CHECK-NEXT: ucvtf d0, d0 ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds i32, ptr %a, i64 1039992 @@ -474,9 +458,8 @@ define double @LdOffset_i32_f64(ptr %a) { define double @LdOffset_i64_f64(ptr %a) { ; CHECK-LABEL: LdOffset_i64_f64: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #62400 // =0xf3c0 -; CHECK-NEXT: movk w8, #126, lsl #16 -; CHECK-NEXT: ldr d0, [x0, x8] +; CHECK-NEXT: add x8, x0, #2024, lsl #12 // =8290304 +; CHECK-NEXT: ldr d0, [x8, #29632] ; CHECK-NEXT: scvtf d0, d0 ; CHECK-NEXT: ret %arrayidx = getelementptr inbounds i64, ptr %a, i64 1039992 diff --git a/llvm/test/CodeGen/AArch64/large-offset-ldr-merge.mir b/llvm/test/CodeGen/AArch64/large-offset-ldr-merge.mir index 473c74323d9399..5c7dc13d051744 100644 --- a/llvm/test/CodeGen/AArch64/large-offset-ldr-merge.mir +++ b/llvm/test/CodeGen/AArch64/large-offset-ldr-merge.mir @@ -65,3 +65,26 @@ body: | renamable $w8 = MOVKWi $w8, 15, 16, implicit-def $x8 renamable $w0 = LDRBBroX killed renamable $x0, killed renamable $x8, 0, 0 RET undef $lr, implicit $w0 +... + +# Negative test: MOVZWi and MOVKWi don't set the same register +--- +name: LdOffset_different_register_MOVZ_MOVK +tracksRegLiveness: true +liveins: + - { reg: '$x0', virtual-reg: '' } +body: | + bb.0.entry: + liveins: $x0 + + ; CHECK-LABEL: name: LdOffset_different_register_MOVZ_MOVK + ; CHECK: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $w7 = MOVZWi 56952, 0 + ; CHECK-NEXT: renamable $w8 = MOVKWi $w8, 15, 16, implicit-def $x8 + ; CHECK-NEXT: renamable $w0 = LDRBBroX killed renamable $x0, killed renamable $x8, 0, 0 + ; CHECK-NEXT: RET undef $lr, implicit $w0 + renamable $w7 = MOVZWi 56952, 0 + renamable $w8 = MOVKWi $w8, 15, 16, implicit-def $x8 + renamable $w0 = LDRBBroX killed renamable $x0, killed renamable $x8, 0, 0 + RET undef $lr, implicit $w0