forked from OSchip/llvm-project
Reapply [FastISel] Let the target decide first if it wants to materialize a constant (215588).
Note: This was originally reverted to track down a buildbot error. This commit exposed a latent bug that was fixed in r215753. Therefore it is reapplied without any modifications. I run it through SPEC2k and SPEC2k6 for AArch64 and it didn't introduce any new regeressions. Original commit message: This changes the order in which FastISel tries to materialize a constant. Originally it would try to use a simple target-independent approach, which can lead to the generation of inefficient code. On X86 this would result in the use of movabsq to materialize any 64bit integer constant - even for simple and small values such as 0 and 1. Also some very funny floating-point materialization could be observed too. On AArch64 it would materialize the constant 0 in a register even the architecture has an actual "zero" register. On ARM it would generate unnecessary mov instructions or not use mvn. This change simply changes the order and always asks the target first if it likes to materialize the constant. This doesn't fix all the issues mentioned above, but it enables the targets to implement such optimizations. Related to <rdar://problem/17420988>. llvm-svn: 216006
This commit is contained in:
parent
113ba3e6c0
commit
4bf6c01cdb
|
@ -575,6 +575,10 @@ private:
|
|||
/// correspond to a different MBB than the end.
|
||||
bool HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB);
|
||||
|
||||
/// \brief Helper for materializeRegForValue to materialize a constant in a
|
||||
/// target-independent way.
|
||||
unsigned MaterializeConstant(const Value *V, MVT VT);
|
||||
|
||||
/// Helper for getRegForVale. This function is called when the value isn't
|
||||
/// already available in a register and must be materialized with new
|
||||
/// instructions.
|
||||
|
|
|
@ -198,29 +198,24 @@ unsigned FastISel::getRegForValue(const Value *V) {
|
|||
return Reg;
|
||||
}
|
||||
|
||||
/// materializeRegForValue - Helper for getRegForValue. This function is
|
||||
/// called when the value isn't already available in a register and must
|
||||
/// be materialized with new instructions.
|
||||
unsigned FastISel::materializeRegForValue(const Value *V, MVT VT) {
|
||||
unsigned FastISel::MaterializeConstant(const Value *V, MVT VT) {
|
||||
unsigned Reg = 0;
|
||||
|
||||
if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
|
||||
if (CI->getValue().getActiveBits() <= 64)
|
||||
Reg = FastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue());
|
||||
} else if (isa<AllocaInst>(V)) {
|
||||
} else if (isa<AllocaInst>(V))
|
||||
Reg = TargetMaterializeAlloca(cast<AllocaInst>(V));
|
||||
} else if (isa<ConstantPointerNull>(V)) {
|
||||
else if (isa<ConstantPointerNull>(V))
|
||||
// Translate this as an integer zero so that it can be
|
||||
// local-CSE'd with actual integer zeros.
|
||||
Reg =
|
||||
getRegForValue(Constant::getNullValue(DL.getIntPtrType(V->getContext())));
|
||||
} else if (const ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
|
||||
if (CF->isNullValue()) {
|
||||
else if (const ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
|
||||
if (CF->isNullValue())
|
||||
Reg = TargetMaterializeFloatZero(CF);
|
||||
} else {
|
||||
else
|
||||
// Try to emit the constant directly.
|
||||
Reg = FastEmit_f(VT, VT, ISD::ConstantFP, CF);
|
||||
}
|
||||
|
||||
if (!Reg) {
|
||||
// Try to emit the constant by using an integer constant with a cast.
|
||||
|
@ -253,15 +248,26 @@ unsigned FastISel::materializeRegForValue(const Value *V, MVT VT) {
|
|||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||
TII.get(TargetOpcode::IMPLICIT_DEF), Reg);
|
||||
}
|
||||
return Reg;
|
||||
}
|
||||
|
||||
// If target-independent code couldn't handle the value, give target-specific
|
||||
// code a try.
|
||||
if (!Reg && isa<Constant>(V))
|
||||
/// materializeRegForValue - Helper for getRegForValue. This function is
|
||||
/// called when the value isn't already available in a register and must
|
||||
/// be materialized with new instructions.
|
||||
unsigned FastISel::materializeRegForValue(const Value *V, MVT VT) {
|
||||
unsigned Reg = 0;
|
||||
// Give the target-specific code a try first.
|
||||
if (isa<Constant>(V))
|
||||
Reg = TargetMaterializeConstant(cast<Constant>(V));
|
||||
|
||||
// If target-specific code couldn't or didn't want to handle the value, then
|
||||
// give target-independent code a try.
|
||||
if (!Reg)
|
||||
Reg = MaterializeConstant(V, VT);
|
||||
|
||||
// Don't cache constant materializations in the general ValueMap.
|
||||
// To do so would require tracking what uses they dominate.
|
||||
if (Reg != 0) {
|
||||
if (Reg) {
|
||||
LocalValueMap[V] = Reg;
|
||||
LastLocalValue = MRI.getVRegDef(Reg);
|
||||
}
|
||||
|
|
|
@ -117,17 +117,11 @@ entry:
|
|||
; ARM-LONG: blx [[R]]
|
||||
; THUMB: @t10
|
||||
; THUMB: movs [[R0:l?r[0-9]*]], #0
|
||||
; THUMB: movt [[R0]], #0
|
||||
; THUMB: movs [[R1:l?r[0-9]*]], #248
|
||||
; THUMB: movt [[R1]], #0
|
||||
; THUMB: movs [[R2:l?r[0-9]*]], #187
|
||||
; THUMB: movt [[R2]], #0
|
||||
; THUMB: movs [[R3:l?r[0-9]*]], #28
|
||||
; THUMB: movt [[R3]], #0
|
||||
; THUMB: movw [[R4:l?r[0-9]*]], #40
|
||||
; THUMB: movt [[R4]], #0
|
||||
; THUMB: movw [[R5:l?r[0-9]*]], #186
|
||||
; THUMB: movt [[R5]], #0
|
||||
; THUMB: and [[R0]], [[R0]], #255
|
||||
; THUMB: and [[R1]], [[R1]], #255
|
||||
; THUMB: and [[R2]], [[R2]], #255
|
||||
|
|
|
@ -14,7 +14,6 @@ entry:
|
|||
; THUMB-NOT: ldr
|
||||
; THUMB-NOT: sxtb
|
||||
; THUMB: movs r0, #0
|
||||
; THUMB: movt r0, #0
|
||||
; THUMB: pop
|
||||
ret i32 0
|
||||
}
|
||||
|
|
|
@ -31,9 +31,7 @@ define void @t1() nounwind ssp {
|
|||
; THUMB: {{(movt r0, :upper16:_?message1)|(ldr r0, \[r0\])}}
|
||||
; THUMB: adds r0, #5
|
||||
; THUMB: movs r1, #64
|
||||
; THUMB: movt r1, #0
|
||||
; THUMB: movs r2, #10
|
||||
; THUMB: movt r2, #0
|
||||
; THUMB: and r1, r1, #255
|
||||
; THUMB: bl {{_?}}memset
|
||||
; THUMB-LONG-LABEL: t1:
|
||||
|
@ -71,7 +69,6 @@ define void @t2() nounwind ssp {
|
|||
; THUMB: adds r1, r0, #4
|
||||
; THUMB: adds r0, #16
|
||||
; THUMB: movs r2, #17
|
||||
; THUMB: movt r2, #0
|
||||
; THUMB: str r0, [sp[[SLOT:[, #0-9]*]]] @ 4-byte Spill
|
||||
; THUMB: mov r0, r1
|
||||
; THUMB: ldr r1, [sp[[SLOT]]] @ 4-byte Reload
|
||||
|
@ -109,7 +106,6 @@ define void @t3() nounwind ssp {
|
|||
; THUMB: adds r1, r0, #4
|
||||
; THUMB: adds r0, #16
|
||||
; THUMB: movs r2, #10
|
||||
; THUMB: movt r2, #0
|
||||
; THUMB: str r0, [sp[[SLOT:[, #0-9]*]]] @ 4-byte Spill
|
||||
; THUMB: mov r0, r1
|
||||
; THUMB: ldr r1, [sp[[SLOT]]] @ 4-byte Reload
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
; RUN: llc -O0 -verify-machineinstrs -fast-isel-abort -relocation-model=dynamic-no-pic -arm-use-movt=false -mtriple=armv7-apple-ios < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM
|
||||
; RUN: llc -O0 -verify-machineinstrs -fast-isel-abort -relocation-model=dynamic-no-pic -arm-use-movt=false -mtriple=armv7-linux-gnueabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM
|
||||
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios | FileCheck %s --check-prefix=THUMB
|
||||
; RUN: llc -O0 -verify-machineinstrs -fast-isel-abort -relocation-model=dynamic-no-pic -arm-use-movt=true -mtriple=armv7-apple-ios < %s | FileCheck %s --check-prefix=MOVT
|
||||
; RUN: llc -O0 -verify-machineinstrs -fast-isel-abort -relocation-model=dynamic-no-pic -arm-use-movt=false -mtriple=thumbv7-apple-ios < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM
|
||||
; RUN: llc -O0 -verify-machineinstrs -fast-isel-abort -relocation-model=dynamic-no-pic -arm-use-movt=true -mtriple=thumbv7-apple-ios < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB
|
||||
; RUN: llc -O0 -verify-machineinstrs -fast-isel-abort -relocation-model=dynamic-no-pic -arm-use-movt=true -mtriple=armv7-apple-ios < %s | FileCheck %s --check-prefix=MOVT
|
||||
; rdar://10412592
|
||||
|
||||
; Note: The Thumb code is being generated by the target-independent selector.
|
||||
|
||||
define void @t1() nounwind {
|
||||
entry:
|
||||
; ARM: t1
|
||||
; THUMB: t1
|
||||
; ARM: mvn r0, #0
|
||||
; THUMB: movw r0, #65535
|
||||
; THUMB: movt r0, #65535
|
||||
; CHECK-LABEL: t1
|
||||
; CHECK: mvn r0, #0
|
||||
call void @foo(i32 -1)
|
||||
ret void
|
||||
}
|
||||
|
@ -21,22 +17,16 @@ declare void @foo(i32)
|
|||
|
||||
define void @t2() nounwind {
|
||||
entry:
|
||||
; ARM: t2
|
||||
; THUMB: t2
|
||||
; ARM: mvn r0, #233
|
||||
; THUMB: movw r0, #65302
|
||||
; THUMB: movt r0, #65535
|
||||
; CHECK-LABEL: t2
|
||||
; CHECK: mvn r0, #233
|
||||
call void @foo(i32 -234)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @t3() nounwind {
|
||||
entry:
|
||||
; ARM: t3
|
||||
; THUMB: t3
|
||||
; ARM: mvn r0, #256
|
||||
; THUMB: movw r0, #65279
|
||||
; THUMB: movt r0, #65535
|
||||
; CHECK-LABEL: t3
|
||||
; CHECK: mvn r0, #256
|
||||
call void @foo(i32 -257)
|
||||
ret void
|
||||
}
|
||||
|
@ -44,66 +34,51 @@ entry:
|
|||
; Load from constant pool
|
||||
define void @t4() nounwind {
|
||||
entry:
|
||||
; ARM: t4
|
||||
; THUMB: t4
|
||||
; ARM: ldr r0
|
||||
; THUMB: movw r0, #65278
|
||||
; THUMB: movt r0, #65535
|
||||
; ARM-LABEL: t4
|
||||
; ARM: ldr r0
|
||||
; THUMB-LABEL: t4
|
||||
; THUMB: movw r0, #65278
|
||||
; THUMB: movt r0, #65535
|
||||
call void @foo(i32 -258)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @t5() nounwind {
|
||||
entry:
|
||||
; ARM: t5
|
||||
; THUMB: t5
|
||||
; ARM: mvn r0, #65280
|
||||
; THUMB: movs r0, #255
|
||||
; THUMB: movt r0, #65535
|
||||
; CHECK-LABEL: t5
|
||||
; CHECK: mvn r0, #65280
|
||||
call void @foo(i32 -65281)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @t6() nounwind {
|
||||
entry:
|
||||
; ARM: t6
|
||||
; THUMB: t6
|
||||
; ARM: mvn r0, #978944
|
||||
; THUMB: movw r0, #4095
|
||||
; THUMB: movt r0, #65521
|
||||
; CHECK-LABEL: t6
|
||||
; CHECK: mvn r0, #978944
|
||||
call void @foo(i32 -978945)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @t7() nounwind {
|
||||
entry:
|
||||
; ARM: t7
|
||||
; THUMB: t7
|
||||
; ARM: mvn r0, #267386880
|
||||
; THUMB: movw r0, #65535
|
||||
; THUMB: movt r0, #61455
|
||||
; CHECK-LABEL: t7
|
||||
; CHECK: mvn r0, #267386880
|
||||
call void @foo(i32 -267386881)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @t8() nounwind {
|
||||
entry:
|
||||
; ARM: t8
|
||||
; THUMB: t8
|
||||
; ARM: mvn r0, #65280
|
||||
; THUMB: movs r0, #255
|
||||
; THUMB: movt r0, #65535
|
||||
; CHECK-LABEL: t8
|
||||
; CHECK: mvn r0, #65280
|
||||
call void @foo(i32 -65281)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @t9() nounwind {
|
||||
entry:
|
||||
; ARM: t9
|
||||
; THUMB: t9
|
||||
; ARM: mvn r0, #2130706432
|
||||
; THUMB: movw r0, #65535
|
||||
; THUMB: movt r0, #33023
|
||||
; CHECK-LABEL: t9
|
||||
; CHECK: mvn r0, #2130706432
|
||||
call void @foo(i32 -2130706433)
|
||||
ret void
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ entry:
|
|||
; ARM: mov r0, r{{[1-9]}}
|
||||
; THUMB: t1
|
||||
; THUMB: movs r{{[1-9]}}, #10
|
||||
; THUMB: movt r{{[1-9]}}, #0
|
||||
; THUMB: cmp r0, #0
|
||||
; THUMB: it eq
|
||||
; THUMB: moveq r{{[1-9]}}, #20
|
||||
|
@ -59,13 +58,12 @@ entry:
|
|||
; ARM: cmp r0, #0
|
||||
; ARM: mvneq r{{[1-9]}}, #0
|
||||
; ARM: mov r0, r{{[1-9]}}
|
||||
; THUMB: t4
|
||||
; THUMB: movw r{{[1-9]}}, #65526
|
||||
; THUMB: movt r{{[1-9]}}, #65535
|
||||
; THUMB-LABEL: t4
|
||||
; THUMB: mvn [[REG:r[1-9]+]], #9
|
||||
; THUMB: cmp r0, #0
|
||||
; THUMB: it eq
|
||||
; THUMB: mvneq r{{[1-9]}}, #0
|
||||
; THUMB: mov r0, r{{[1-9]}}
|
||||
; THUMB: mvneq [[REG]], #0
|
||||
; THUMB: mov r0, [[REG]]
|
||||
%0 = select i1 %c, i32 -10, i32 -1
|
||||
ret i32 %0
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ entry:
|
|||
; ARM: bl {{_?CallVariadic}}
|
||||
; THUMB: sub sp, #32
|
||||
; THUMB: movs r0, #5
|
||||
; THUMB: movt r0, #0
|
||||
; THUMB: ldr r1, [sp, #28]
|
||||
; THUMB: ldr r2, [sp, #24]
|
||||
; THUMB: ldr r3, [sp, #20]
|
||||
|
|
|
@ -57,11 +57,11 @@ entry:
|
|||
; ELF64: t10
|
||||
%call = call i32 @bar(i8 zeroext 0, i8 zeroext -8, i8 zeroext -69, i8 zeroext 28, i8 zeroext 40, i8 zeroext -70)
|
||||
; ELF64: li 3, 0
|
||||
; ELF64: li 4, 248
|
||||
; ELF64: li 5, 187
|
||||
; ELF64: li 4, -8
|
||||
; ELF64: li 5, -69
|
||||
; ELF64: li 6, 28
|
||||
; ELF64: li 7, 40
|
||||
; ELF64: li 8, 186
|
||||
; ELF64: li 8, -70
|
||||
; ELF64: rldicl 3, 3, 0, 56
|
||||
; ELF64: rldicl 4, 4, 0, 56
|
||||
; ELF64: rldicl 5, 5, 0, 56
|
||||
|
|
|
@ -194,12 +194,10 @@ define void @test16() nounwind {
|
|||
br label %block2
|
||||
|
||||
block2:
|
||||
; CHECK: movabsq $1
|
||||
; CHECK: cvtsi2sdq {{.*}} %xmm0
|
||||
; CHECK: movsd LCP{{.*}}_{{.*}}(%rip), %xmm0
|
||||
; CHECK: movb $1, %al
|
||||
; CHECK: callq _test16callee
|
||||
|
||||
; AVX: movabsq $1
|
||||
; AVX: vmovsd LCP{{.*}}_{{.*}}(%rip), %xmm0
|
||||
; AVX: movb $1, %al
|
||||
; AVX: callq _test16callee
|
||||
|
|
Loading…
Reference in New Issue