1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

GlobalISel: legalize 1-bit load/store and mark 8/16 bit variants legal on AArch64.

llvm-svn: 279548
This commit is contained in:
Tim Northover 2016-08-23 18:20:09 +00:00
parent 3b30fbd4c0
commit 685dd8eded
3 changed files with 113 additions and 7 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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)
...