summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAhmed Bougacha <ahmed.bougacha@gmail.com>2016-07-29 16:56:16 +0000
committerAhmed Bougacha <ahmed.bougacha@gmail.com>2016-07-29 16:56:16 +0000
commit7adfac56b3345f9815663f24c6ca5e5a68bfae4e (patch)
tree3ad1520812a84046f28fcccf526b99ebd802d16c
parent5c98b60ecc5580e53e191cbe6c7a11bf139687cb (diff)
downloadbcm5719-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
-rw-r--r--llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp8
-rw-r--r--llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp56
-rw-r--r--llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir106
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)
+
+...
OpenPOWER on IntegriCloud