From 3c73e367c03dbf3e03911cffaaf465a0ce1688f6 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Tue, 23 Aug 2016 18:20:09 +0000 Subject: [PATCH] GlobalISel: legalize 1-bit load/store and mark 8/16 bit variants legal on AArch64. llvm-svn: 279548 --- .../CodeGen/GlobalISel/MachineLegalizeHelper.cpp | 29 ++++++-- .../lib/Target/AArch64/AArch64MachineLegalizer.cpp | 7 +- .../AArch64/GlobalISel/legalize-load-store.mir | 84 ++++++++++++++++++++++ 3 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir diff --git a/llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp b/llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp index 9dc2bf8..7c3253d 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp @@ -105,6 +105,8 @@ MachineLegalizeHelper::narrowScalar(MachineInstr &MI, LLT NarrowTy) { MachineLegalizeHelper::LegalizeResult MachineLegalizeHelper::widenScalar(MachineInstr &MI, LLT WideTy) { unsigned WideSize = WideTy.getSizeInBits(); + MIRBuilder.setInstr(MI); + switch (MI.getOpcode()) { default: return UnableToLegalize; @@ -117,9 +119,6 @@ MachineLegalizeHelper::widenScalar(MachineInstr &MI, LLT WideTy) { // Perform operation at larger width (any extension is fine here, high bits // don't affect the result) and then truncate the result back to the // original type. - - MIRBuilder.setInstr(MI); - unsigned Src1Ext = MRI.createGenericVirtualRegister(WideSize); unsigned Src2Ext = MRI.createGenericVirtualRegister(WideSize); MIRBuilder.buildAnyExtend(WideTy, Src1Ext, MI.getOperand(1).getReg()); @@ -133,8 +132,29 @@ MachineLegalizeHelper::widenScalar(MachineInstr &MI, LLT WideTy) { MI.eraseFromParent(); return Legalized; } + case TargetOpcode::G_LOAD: { + assert(alignTo(MI.getType().getSizeInBits(), 8) == WideSize && + "illegal to increase number of bytes loaded"); + + unsigned DstExt = MRI.createGenericVirtualRegister(WideSize); + MIRBuilder.buildLoad(WideTy, MI.getType(1), DstExt, + MI.getOperand(1).getReg(), **MI.memoperands_begin()); + MIRBuilder.buildTrunc(MI.getType(), MI.getOperand(0).getReg(), DstExt); + MI.eraseFromParent(); + return Legalized; + } + case TargetOpcode::G_STORE: { + assert(alignTo(MI.getType().getSizeInBits(), 8) == WideSize && + "illegal to increase number of bytes modified by a store"); + + unsigned SrcExt = MRI.createGenericVirtualRegister(WideSize); + MIRBuilder.buildAnyExtend(WideTy, SrcExt, MI.getOperand(0).getReg()); + MIRBuilder.buildStore(WideTy, MI.getType(1), SrcExt, + MI.getOperand(1).getReg(), **MI.memoperands_begin()); + MI.eraseFromParent(); + return Legalized; + } case TargetOpcode::G_CONSTANT: { - MIRBuilder.setInstr(MI); unsigned DstExt = MRI.createGenericVirtualRegister(WideSize); MIRBuilder.buildConstant(WideTy, DstExt, MI.getOperand(1).getImm()); MIRBuilder.buildTrunc(MI.getType(), MI.getOperand(0).getReg(), DstExt); @@ -142,7 +162,6 @@ MachineLegalizeHelper::widenScalar(MachineInstr &MI, LLT WideTy) { return Legalized; } case TargetOpcode::G_FCONSTANT: { - MIRBuilder.setInstr(MI); unsigned DstExt = MRI.createGenericVirtualRegister(WideSize); MIRBuilder.buildFConstant(WideTy, DstExt, *MI.getOperand(1).getFPImm()); MIRBuilder.buildFPTrunc(MI.getType(), MI.getOperand(0).getReg(), DstExt); diff --git a/llvm/lib/Target/AArch64/AArch64MachineLegalizer.cpp b/llvm/lib/Target/AArch64/AArch64MachineLegalizer.cpp index b91d604..d5bf1db 100644 --- a/llvm/lib/Target/AArch64/AArch64MachineLegalizer.cpp +++ b/llvm/lib/Target/AArch64/AArch64MachineLegalizer.cpp @@ -51,10 +51,13 @@ AArch64MachineLegalizer::AArch64MachineLegalizer() { for (auto Ty : {s32, s64}) setAction(BinOp, Ty, Legal); - for (auto MemOp : {G_LOAD, G_STORE}) - for (auto Ty : {s32, s64}) + for (auto MemOp : {G_LOAD, G_STORE}) { + for (auto Ty : {s8, s16, s32, s64}) setAction(MemOp, Ty, Legal); + setAction(MemOp, s1, WidenScalar); + } + for (auto Ty : {s32, s64}) { setAction(TargetOpcode::G_CONSTANT, Ty, Legal); setAction(TargetOpcode::G_FCONSTANT, Ty, Legal); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir new file mode 100644 index 0000000..30ec0a2 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir @@ -0,0 +1,84 @@ +# RUN: llc -O0 -run-pass=legalize-mir -global-isel %s -o - 2>&1 | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "aarch64-apple-ios" + define void @test_load(i8* %addr) { + entry: + ret void + } + define void @test_store(i8* %addr) { + entry: + ret void + } +... + +--- +name: test_load +isSSA: true +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } + - { id: 3, class: _ } + - { id: 4, class: _ } + - { id: 5, class: _ } +body: | + bb.0.entry: + liveins: %x0, %x1, %x2, %x3 + ; CHECK-LABEL: name: test_load + %0(64) = COPY %x0 + + ; CHECK: [[BIT8:%[0-9]+]](8) = G_LOAD { s8, p0 } %0 :: (load 1 from %ir.addr) + ; CHECK: %1(1) = G_TRUNC s1 [[BIT8]] + %1(1) = G_LOAD { s1, p0 } %0 :: (load 1 from %ir.addr) + + ; CHECK: %2(8) = G_LOAD { s8, p0 } %0 :: (load 1 from %ir.addr) + %2(8) = G_LOAD { s8, p0 } %0 :: (load 1 from %ir.addr) + + ; CHECK: %3(16) = G_LOAD { s16, p0 } %0 :: (load 2 from %ir.addr) + %3(16) = G_LOAD { s16, p0 } %0 :: (load 2 from %ir.addr) + + ; CHECK: %4(32) = G_LOAD { s32, p0 } %0 :: (load 4 from %ir.addr) + %4(32) = G_LOAD { s32, p0 } %0 :: (load 4 from %ir.addr) + + ; CHECK: %5(64) = G_LOAD { s64, p0 } %0 :: (load 8 from %ir.addr) + %5(64) = G_LOAD { s64, p0 } %0 :: (load 8 from %ir.addr) +... + +--- +name: test_store +isSSA: true +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } + - { id: 3, class: _ } + - { id: 4, class: _ } +body: | + bb.0.entry: + liveins: %x0, %x1, %x2, %x3 + ; CHECK-LABEL: name: test_store + + %0(64) = COPY %x0 + %1(32) = COPY %w1 + + ; CHECK: [[BIT8:%[0-9]+]](8) = G_ANYEXTEND s8 %2 + ; CHECK: G_STORE { s8, p0 } [[BIT8]], %0 :: (store 1 into %ir.addr) + %2(1) = G_TRUNC s1 %1 + G_STORE { s1, p0 } %2, %0 :: (store 1 into %ir.addr) + + ; CHECK: G_STORE { s8, p0 } %3, %0 :: (store 1 into %ir.addr) + %3(8) = G_TRUNC s8 %1 + G_STORE { s8, p0 } %3, %0 :: (store 1 into %ir.addr) + + ; CHECK: G_STORE { s16, p0 } %4, %0 :: (store 2 into %ir.addr) + %4(16) = G_TRUNC s16 %1 + G_STORE { s16, p0 } %4, %0 :: (store 2 into %ir.addr) + + ; CHECK: G_STORE { s32, p0 } %1, %0 :: (store 4 into %ir.addr) + G_STORE { s32, p0 } %1, %0 :: (store 4 into %ir.addr) + + ; CHECK: G_STORE { s64, p0 } %0, %0 :: (store 8 into %ir.addr) + G_STORE { s64, p0 } %0, %0 :: (store 8 into %ir.addr) +... -- 2.7.4