From 254b11a0fd864ab42eef2d6cf781330959c58567 Mon Sep 17 00:00:00 2001 From: Diana Picus Date: Mon, 25 Mar 2019 08:54:29 +0000 Subject: [PATCH] [ARM GlobalISel] 64-bit memops should be aligned We currently use only VLDR/VSTR for all 64-bit loads/stores, so the memory operands must be word-aligned. Mark aligned operations as legal and narrow non-aligned ones to 32 bits. While we're here, also mark non-power-of-2 loads/stores as unsupported. llvm-svn: 356872 --- llvm/lib/Target/ARM/ARMLegalizerInfo.cpp | 19 ++--- .../ARM/GlobalISel/arm-legalize-load-store.mir | 90 +++++++++++++++++++++- llvm/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir | 30 -------- 3 files changed, 99 insertions(+), 40 deletions(-) diff --git a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp index 82817d3..5ab211b 100644 --- a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp +++ b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp @@ -129,14 +129,13 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) { // We're keeping these builders around because we'll want to add support for // floating point to them. - auto &LoadStoreBuilder = - getActionDefinitionsBuilder({G_LOAD, G_STORE}) - .legalForTypesWithMemDesc({ - {s1, p0, 8, 8}, - {s8, p0, 8, 8}, - {s16, p0, 16, 8}, - {s32, p0, 32, 8}, - {p0, p0, 32, 8}}); + auto &LoadStoreBuilder = getActionDefinitionsBuilder({G_LOAD, G_STORE}) + .legalForTypesWithMemDesc({{s1, p0, 8, 8}, + {s8, p0, 8, 8}, + {s16, p0, 16, 8}, + {s32, p0, 32, 8}, + {p0, p0, 32, 8}}) + .unsupportedIfMemSizeNotPow2(); getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0}); getActionDefinitionsBuilder(G_GLOBAL_VALUE).legalFor({p0}); @@ -155,7 +154,9 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) { {G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FCONSTANT, G_FNEG}) .legalFor({s32, s64}); - LoadStoreBuilder.legalFor({{s64, p0}}); + LoadStoreBuilder + .legalForTypesWithMemDesc({{s64, p0, 64, 32}}) + .maxScalar(0, s32); PhiBuilder.legalFor({s64}); getActionDefinitionsBuilder(G_FCMP).legalForCartesianProduct({s1}, diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-load-store.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-load-store.mir index 34ed8b8..a7d83d5 100644 --- a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-load-store.mir +++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-load-store.mir @@ -1,10 +1,16 @@ # RUN: llc -mtriple arm-- -run-pass=legalizer %s -o - | FileCheck %s -# RUN: llc -mtriple thumb-- -mattr=+v6t2 -run-pass=legalizer %s -o - | FileCheck %s +# RUN: llc -mtriple thumbv7-- -run-pass=legalizer %s -o - | FileCheck %s --- | define void @test_legal_loads_stores() { ret void } define void @test_load_from_stack() { ret void } + define void @test_load_store_64_vfp() #0 { ret void } + define void @test_load_store_64_novfp() #1 { ret void } + define void @test_gep() { ret void } + + attributes #0 = { "target-features"="+vfp2" } + attributes #1 = { "target-features"="-vfp2" } ... --- name: test_legal_loads_stores @@ -81,6 +87,88 @@ body: | BX_RET 14, $noreg, implicit $r0 ... --- +name: test_load_store_64_vfp +# CHECK-LABEL: name: test_load_store_64_vfp +legalized: false +# CHECK: legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.0: + liveins: $r0 + + ; Can't use the VFP support for unaligned operations, we need to use 32-bits + ; operations instead. + ; CHECK: [[ADDR1:%[0-9]+]]:_(p0) = COPY $r0 + ; CHECK-NEXT: [[V1:%[0-9]+]]:_(s32) = G_LOAD [[ADDR1]](p0) :: (load 4, align 1) + ; CHECK-NEXT: [[OFF:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; CHECK-NEXT: [[OFFCOPY:%[0-9]+]]:_(s32) = COPY [[OFF]] + ; CHECK-NEXT: [[ADDR2:%[0-9]+]]:_(p0) = G_GEP [[ADDR1]], [[OFFCOPY]] + ; CHECK-NEXT: [[V2:%[0-9]+]]:_(s32) = G_LOAD [[ADDR2]](p0) :: (load 4, align 1) + ; CHECK-NEXT: G_STORE [[V1]](s32), [[ADDR1]](p0) :: (store 4, align 1) + ; CHECK-NEXT: [[ADDR2:%[0-9]+]]:_(p0) = G_GEP [[ADDR1]], [[OFF]] + ; CHECK-NEXT: G_STORE [[V2]](s32), [[ADDR2]](p0) :: (store 4, align 1) + %0(p0) = COPY $r0 + %1(s64) = G_LOAD %0(p0) :: (load 8, align 1) + G_STORE %1(s64), %0(p0) :: (store 8, align 1) + + ; For word-aligned we can use VFP operations. + ; CHECK: [[V:%[0-9]+]]:_(s64) = G_LOAD %0(p0) :: (load 8, align 4) + ; CHECK: G_STORE [[V]](s64), %0(p0) :: (store 8, align 4) + %2(s64) = G_LOAD %0(p0) :: (load 8, align 4) + G_STORE %2(s64), %0(p0) :: (store 8, align 4) + + BX_RET 14, $noreg +... +--- +name: test_load_store_64_novfp +# CHECK-LABEL: name: test_load_store_64_novfp +legalized: false +# CHECK: legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.0: + liveins: $r0 + + ; When we don't have VFP support, we need to use 32-bit operations. + ; CHECK: [[ADDR1:%[0-9]+]]:_(p0) = COPY $r0 + ; CHECK-NEXT: [[V1:%[0-9]+]]:_(s32) = G_LOAD [[ADDR1]](p0) :: (load 4, align 1) + ; CHECK-NEXT: [[OFF:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; CHECK-NEXT: [[OFFCOPY:%[0-9]+]]:_(s32) = COPY [[OFF]] + ; CHECK-NEXT: [[ADDR2:%[0-9]+]]:_(p0) = G_GEP [[ADDR1]], [[OFFCOPY]] + ; CHECK-NEXT: [[V2:%[0-9]+]]:_(s32) = G_LOAD [[ADDR2]](p0) :: (load 4, align 1) + ; CHECK-NEXT: G_STORE [[V1]](s32), [[ADDR1]](p0) :: (store 4, align 1) + ; CHECK-NEXT: [[OFFCOPY:%[0-9]+]]:_(s32) = COPY [[OFF]] + ; CHECK-NEXT: [[ADDR2:%[0-9]+]]:_(p0) = G_GEP [[ADDR1]], [[OFFCOPY]] + ; CHECK-NEXT: G_STORE [[V2]](s32), [[ADDR2]](p0) :: (store 4, align 1) + %0(p0) = COPY $r0 + %1(s64) = G_LOAD %0(p0) :: (load 8, align 1) + G_STORE %1(s64), %0(p0) :: (store 8, align 1) + + ; CHECK: [[V1:%[0-9]+]]:_(s32) = G_LOAD [[ADDR1]](p0) :: (load 4) + ; CHECK-NEXT: [[OFFCOPY:%[0-9]+]]:_(s32) = COPY [[OFF]] + ; CHECK-NEXT: [[ADDR2:%[0-9]+]]:_(p0) = G_GEP [[ADDR1]], [[OFFCOPY]] + ; CHECK-NEXT: [[V2:%[0-9]+]]:_(s32) = G_LOAD [[ADDR2]](p0) :: (load 4) + ; CHECK-NEXT: G_STORE [[V1]](s32), [[ADDR1]](p0) :: (store 4) + ; CHECK-NEXT: [[ADDR2:%[0-9]+]]:_(p0) = G_GEP [[ADDR1]], [[OFF]] + ; CHECK-NEXT: G_STORE [[V2]](s32), [[ADDR2]](p0) :: (store 4) + %2(s64) = G_LOAD %0(p0) :: (load 8, align 4) + G_STORE %2(s64), %0(p0) :: (store 8, align 4) + + BX_RET 14, $noreg +... +--- name: test_gep # CHECK-LABEL: name: test_gep legalized: false diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir index ae4e949..f4408ad 100644 --- a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir +++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir @@ -1,7 +1,5 @@ # RUN: llc -mtriple arm-- -run-pass=legalizer %s -o - | FileCheck %s --- | - define void @test_load_store_64() #0 { ret void } - define void @test_constants_s64() { ret void } define void @test_phi_s64() #0 { ret void } @@ -9,34 +7,6 @@ attributes #0 = { "target-features"="+vfp2" } ... --- -name: test_load_store_64 -# CHECK-LABEL: name: test_load_store_64 -legalized: false -# CHECK: legalized: true -regBankSelected: false -selected: false -tracksRegLiveness: true -registers: - - { id: 0, class: _ } - - { id: 1, class: _ } - - { id: 2, class: _ } - - { id: 3, class: _ } - - { id: 4, class: _ } - - { id: 5, class: _ } - - { id: 6, class: _ } -body: | - bb.0: - liveins: $r0 - - ; These are legal, so we should find them unchanged in the output - ; CHECK-DAG: G_STORE {{%[0-9]+}}(s64), %0(p0) - ; CHECK-DAG: {{%[0-9]+}}:_(s64) = G_LOAD %0(p0) - %0(p0) = COPY $r0 - %1(s64) = G_LOAD %0(p0) :: (load 8) - G_STORE %1(s64), %0(p0) :: (store 8) - BX_RET 14, $noreg -... ---- name: test_constants_s64 # CHECK-LABEL: name: test_constants_s64 legalized: false -- 2.7.4