diff options
| author | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2016-07-29 16:56:16 +0000 |
|---|---|---|
| committer | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2016-07-29 16:56:16 +0000 |
| commit | 7adfac56b3345f9815663f24c6ca5e5a68bfae4e (patch) | |
| tree | 3ad1520812a84046f28fcccf526b99ebd802d16c | |
| parent | 5c98b60ecc5580e53e191cbe6c7a11bf139687cb (diff) | |
| download | bcm5719-llvm-7adfac56b3345f9815663f24c6ca5e5a68bfae4e.tar.gz bcm5719-llvm-7adfac56b3345f9815663f24c6ca5e5a68bfae4e.zip | |
[AArch64][GlobalISel] Select G_LOAD/G_STORE.
Mostly straightforward as we ignore addressing modes and just
use the base + unsigned immediate offset (always 0) variants.
This currently fails to select extloads because we have yet to
agree on a representation.
llvm-svn: 277171
3 files changed, 168 insertions, 2 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp index 07a4b3d7170..5cb7e184a6c 100644 --- a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp +++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp @@ -31,9 +31,13 @@ bool InstructionSelector::constrainSelectedInstRegOperands( for (unsigned OpI = 0, OpE = I.getNumExplicitOperands(); OpI != OpE; ++OpI) { MachineOperand &MO = I.getOperand(OpI); - DEBUG(dbgs() << "Converting operand: " << MO << '\n'); - assert(MO.isReg() && "Unsupported binop non-reg operand"); + // There's nothing to be done on immediates. + if (MO.isImm()) + continue; + + DEBUG(dbgs() << "Converting operand: " << MO << '\n'); + assert(MO.isReg() && "Unsupported non-reg operand"); const TargetRegisterClass *RC = TII.getRegClass(I.getDesc(), OpI, &TRI, MF); assert(RC && "Selected inst should have regclass operand"); diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp index 492024ecd1a..9c48d32897f 100644 --- a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -79,6 +79,26 @@ static unsigned selectBinaryOp(unsigned GenericOpc, unsigned RegBankID, return GenericOpc; } +/// Select the AArch64 opcode for the G_LOAD or G_STORE operation \p GenericOpc, +/// appropriate for the (value) register bank \p RegBankID and of memory access +/// size \p OpSize. This returns the variant with the base+unsigned-immediate +/// addressing mode (e.g., LDRXui). +/// \returns \p GenericOpc if the combination is unsupported. +static unsigned selectLoadStoreUIOp(unsigned GenericOpc, unsigned RegBankID, + unsigned OpSize) { + const bool isStore = GenericOpc == TargetOpcode::G_STORE; + switch (RegBankID) { + case AArch64::GPRRegBankID: + switch (OpSize) { + case 32: + return isStore ? AArch64::STRWui : AArch64::LDRWui; + case 64: + return isStore ? AArch64::STRXui : AArch64::LDRXui; + } + }; + return GenericOpc; +} + bool AArch64InstructionSelector::select(MachineInstr &I) const { assert(I.getParent() && "Instruction should be in a basic block!"); assert(I.getParent()->getParent() && "Instruction should be in a function!"); @@ -109,6 +129,42 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const { return true; } + case TargetOpcode::G_LOAD: + case TargetOpcode::G_STORE: { + LLT MemTy = I.getType(0); + LLT PtrTy = I.getType(1); + + if (PtrTy != LLT::pointer(0)) { + DEBUG(dbgs() << "Load/Store pointer has type: " << PtrTy + << ", expected: " << LLT::pointer(0) << '\n'); + return false; + } + +#ifndef NDEBUG + // Sanity-check the pointer register. + const unsigned PtrReg = I.getOperand(1).getReg(); + const RegisterBank &PtrRB = *RBI.getRegBank(PtrReg, MRI, TRI); + assert(PtrRB.getID() == AArch64::GPRRegBankID && + "Load/Store pointer operand isn't a GPR"); + assert(MRI.getSize(PtrReg) == 64 && + "Load/Store pointer operand isn't 64-bit"); +#endif + + const unsigned ValReg = I.getOperand(0).getReg(); + const RegisterBank &RB = *RBI.getRegBank(ValReg, MRI, TRI); + + const unsigned NewOpc = + selectLoadStoreUIOp(I.getOpcode(), RB.getID(), MemTy.getSizeInBits()); + if (NewOpc == I.getOpcode()) + return false; + + I.setDesc(TII.get(NewOpc)); + I.removeTypes(); + + I.addOperand(MachineOperand::CreateImm(0)); + return constrainSelectedInstRegOperands(I, TII, TRI, RBI); + } + case TargetOpcode::G_OR: case TargetOpcode::G_AND: case TargetOpcode::G_ADD: diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir index 555956c9745..28a42460c3f 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir @@ -22,6 +22,12 @@ define void @unconditional_br() { ret void } + define void @load_s64_gpr(i64* %addr) { ret void } + define void @load_s32_gpr(i32* %addr) { ret void } + + define void @store_s64_gpr(i64* %addr) { ret void } + define void @store_s32_gpr(i32* %addr) { ret void } + ... --- @@ -232,3 +238,103 @@ body: | G_BR unsized %bb.0 ... + +--- +# CHECK-LABEL: name: load_s64_gpr +name: load_s64_gpr +isSSA: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = LDRXui %0, 0 :: (load 8 from %ir.addr) +body: | + bb.0: + liveins: %x0 + + %0(64) = COPY %x0 + %1(64) = G_LOAD { s64, p0 } %0 :: (load 8 from %ir.addr) + +... + +--- +# CHECK-LABEL: name: load_s32_gpr +name: load_s32_gpr +isSSA: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = LDRWui %0, 0 :: (load 4 from %ir.addr) +body: | + bb.0: + liveins: %x0 + + %0(64) = COPY %x0 + %1(32) = G_LOAD { s32, p0 } %0 :: (load 4 from %ir.addr) + +... + +--- +# CHECK-LABEL: name: store_s64_gpr +name: store_s64_gpr +isSSA: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: STRXui %1, %0, 0 :: (store 8 into %ir.addr) +body: | + bb.0: + liveins: %x0, %x1 + + %0(64) = COPY %x0 + %1(64) = COPY %x1 + G_STORE { s64, p0 } %1, %0 :: (store 8 into %ir.addr) + +... + +--- +# CHECK-LABEL: name: store_s32_gpr +name: store_s32_gpr +isSSA: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %w1 +# CHECK: STRWui %1, %0, 0 :: (store 4 into %ir.addr) +body: | + bb.0: + liveins: %x0, %w1 + + %0(64) = COPY %x0 + %1(32) = COPY %w1 + G_STORE { s32, p0 } %1, %0 :: (store 4 into %ir.addr) + +... |

