mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
[FastISel][AArch64] Use the zero register for stores.
Use the zero register directly when possible to avoid an unnecessary register copy and a wasted register at -O0. This also uses integer stores to store a positive floating-point zero. This saves us from materializing the positive zero in a register and then storing it. llvm-svn: 216617
This commit is contained in:
parent
aa5b60a6f9
commit
8c8c692bd7
@ -1419,7 +1419,7 @@ bool AArch64FastISel::EmitStore(MVT VT, unsigned SrcReg, Address Addr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Storing an i1 requires special handling.
|
// Storing an i1 requires special handling.
|
||||||
if (VTIsi1) {
|
if (VTIsi1 && SrcReg != AArch64::WZR) {
|
||||||
unsigned ANDReg = emitAND_ri(MVT::i32, SrcReg, /*TODO:IsKill=*/false, 1);
|
unsigned ANDReg = emitAND_ri(MVT::i32, SrcReg, /*TODO:IsKill=*/false, 1);
|
||||||
assert(ANDReg && "Unexpected AND instruction emission failure.");
|
assert(ANDReg && "Unexpected AND instruction emission failure.");
|
||||||
SrcReg = ANDReg;
|
SrcReg = ANDReg;
|
||||||
@ -1436,7 +1436,7 @@ bool AArch64FastISel::EmitStore(MVT VT, unsigned SrcReg, Address Addr,
|
|||||||
|
|
||||||
bool AArch64FastISel::SelectStore(const Instruction *I) {
|
bool AArch64FastISel::SelectStore(const Instruction *I) {
|
||||||
MVT VT;
|
MVT VT;
|
||||||
Value *Op0 = I->getOperand(0);
|
const Value *Op0 = I->getOperand(0);
|
||||||
// Verify we have a legal type before going any further. Currently, we handle
|
// Verify we have a legal type before going any further. Currently, we handle
|
||||||
// simple types that will directly fit in a register (i32/f32/i64/f64) or
|
// simple types that will directly fit in a register (i32/f32/i64/f64) or
|
||||||
// those that can be sign or zero-extended to a basic operation (i1/i8/i16).
|
// those that can be sign or zero-extended to a basic operation (i1/i8/i16).
|
||||||
@ -1444,9 +1444,23 @@ bool AArch64FastISel::SelectStore(const Instruction *I) {
|
|||||||
cast<StoreInst>(I)->isAtomic())
|
cast<StoreInst>(I)->isAtomic())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Get the value to be stored into a register.
|
// Get the value to be stored into a register. Use the zero register directly
|
||||||
unsigned SrcReg = getRegForValue(Op0);
|
// when possible to avoid an unnecessary copy and a wasted register at -O0.
|
||||||
if (SrcReg == 0)
|
unsigned SrcReg = 0;
|
||||||
|
if (const auto *CI = dyn_cast<ConstantInt>(Op0)) {
|
||||||
|
if (CI->isZero())
|
||||||
|
SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
|
||||||
|
} else if (const auto *CF = dyn_cast<ConstantFP>(Op0)) {
|
||||||
|
if (CF->isZero() && !CF->isNegative()) {
|
||||||
|
VT = MVT::getIntegerVT(VT.getSizeInBits());
|
||||||
|
SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SrcReg)
|
||||||
|
SrcReg = getRegForValue(Op0);
|
||||||
|
|
||||||
|
if (!SrcReg)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// See if we can handle this address.
|
// See if we can handle this address.
|
||||||
|
@ -66,8 +66,7 @@ entry:
|
|||||||
define void @t4(i32 *%ptr) nounwind {
|
define void @t4(i32 *%ptr) nounwind {
|
||||||
entry:
|
entry:
|
||||||
; CHECK-LABEL: t4:
|
; CHECK-LABEL: t4:
|
||||||
; CHECK: mov w8, wzr
|
; CHECK: stur wzr, [x0, #-4]
|
||||||
; CHECK: stur w8, [x0, #-4]
|
|
||||||
; CHECK: ret
|
; CHECK: ret
|
||||||
%0 = getelementptr i32 *%ptr, i32 -1
|
%0 = getelementptr i32 *%ptr, i32 -1
|
||||||
store i32 0, i32* %0, align 4
|
store i32 0, i32* %0, align 4
|
||||||
@ -77,8 +76,7 @@ entry:
|
|||||||
define void @t5(i32 *%ptr) nounwind {
|
define void @t5(i32 *%ptr) nounwind {
|
||||||
entry:
|
entry:
|
||||||
; CHECK-LABEL: t5:
|
; CHECK-LABEL: t5:
|
||||||
; CHECK: mov w8, wzr
|
; CHECK: stur wzr, [x0, #-256]
|
||||||
; CHECK: stur w8, [x0, #-256]
|
|
||||||
; CHECK: ret
|
; CHECK: ret
|
||||||
%0 = getelementptr i32 *%ptr, i32 -64
|
%0 = getelementptr i32 *%ptr, i32 -64
|
||||||
store i32 0, i32* %0, align 4
|
store i32 0, i32* %0, align 4
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
; RUN: llc -mtriple=aarch64-apple-darwin -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=SDAG
|
; RUN: llc -mtriple=aarch64-apple-darwin -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=SDAG
|
||||||
; RUN: llc -mtriple=aarch64-apple-darwin -fast-isel -fast-isel-abort -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=FAST
|
; RUN: llc -mtriple=aarch64-apple-darwin -O0 -fast-isel-abort -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=FAST
|
||||||
|
|
||||||
; Load / Store Base Register only
|
; Load / Store Base Register only
|
||||||
define zeroext i1 @load_breg_i1(i1* %a) {
|
define zeroext i1 @load_breg_i1(i1* %a) {
|
||||||
@ -53,11 +53,18 @@ define double @load_breg_f64(double* %a) {
|
|||||||
|
|
||||||
define void @store_breg_i1(i1* %a) {
|
define void @store_breg_i1(i1* %a) {
|
||||||
; CHECK-LABEL: store_breg_i1
|
; CHECK-LABEL: store_breg_i1
|
||||||
; CHECK: strb {{wzr|w[0-9]+}}, [x0]
|
; CHECK: strb wzr, [x0]
|
||||||
store i1 0, i1* %a
|
store i1 0, i1* %a
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define void @store_breg_i1_2(i1* %a) {
|
||||||
|
; CHECK-LABEL: store_breg_i1_2
|
||||||
|
; CHECK: strb {{w[0-9]+}}, [x0]
|
||||||
|
store i1 true, i1* %a
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
define void @store_breg_i8(i8* %a) {
|
define void @store_breg_i8(i8* %a) {
|
||||||
; CHECK-LABEL: store_breg_i8
|
; CHECK-LABEL: store_breg_i8
|
||||||
; CHECK: strb wzr, [x0]
|
; CHECK: strb wzr, [x0]
|
||||||
@ -88,14 +95,14 @@ define void @store_breg_i64(i64* %a) {
|
|||||||
|
|
||||||
define void @store_breg_f32(float* %a) {
|
define void @store_breg_f32(float* %a) {
|
||||||
; CHECK-LABEL: store_breg_f32
|
; CHECK-LABEL: store_breg_f32
|
||||||
; CHECK: str {{wzr|s[0-9]+}}, [x0]
|
; CHECK: str wzr, [x0]
|
||||||
store float 0.0, float* %a
|
store float 0.0, float* %a
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @store_breg_f64(double* %a) {
|
define void @store_breg_f64(double* %a) {
|
||||||
; CHECK-LABEL: store_breg_f64
|
; CHECK-LABEL: store_breg_f64
|
||||||
; CHECK: str {{xzr|d[0-9]+}}, [x0]
|
; CHECK: str xzr, [x0]
|
||||||
store double 0.0, double* %a
|
store double 0.0, double* %a
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
@ -426,7 +433,7 @@ define i32 @load_breg_sext_shift_offreg_2(i32 %a, i64 %b) {
|
|||||||
; Load Scaled Register Offset + Immediate Offset + Sign/Zero extension
|
; Load Scaled Register Offset + Immediate Offset + Sign/Zero extension
|
||||||
define i64 @load_sext_shift_offreg_imm1(i32 %a) {
|
define i64 @load_sext_shift_offreg_imm1(i32 %a) {
|
||||||
; CHECK-LABEL: load_sext_shift_offreg_imm1
|
; CHECK-LABEL: load_sext_shift_offreg_imm1
|
||||||
; CHECK: sbfiz [[REG:x[0-9]+]], x0, #3, #32
|
; CHECK: sbfiz [[REG:x[0-9]+]], {{x[0-9]+}}, #3, #32
|
||||||
; CHECK-NEXT: ldr {{x[0-9]+}}, {{\[}}[[REG]], #8{{\]}}
|
; CHECK-NEXT: ldr {{x[0-9]+}}, {{\[}}[[REG]], #8{{\]}}
|
||||||
%1 = sext i32 %a to i64
|
%1 = sext i32 %a to i64
|
||||||
%2 = shl i64 %1, 3
|
%2 = shl i64 %1, 3
|
||||||
|
Loading…
Reference in New Issue
Block a user