[FastISel] Let the target decide first if it wants to materialize a constant.
authorJuergen Ributzka <juergen@apple.com>
Wed, 13 Aug 2014 22:08:02 +0000 (22:08 +0000)
committerJuergen Ributzka <juergen@apple.com>
Wed, 13 Aug 2014 22:08:02 +0000 (22:08 +0000)
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>.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215588 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/FastISel.h
lib/CodeGen/SelectionDAG/FastISel.cpp
test/CodeGen/ARM/fast-isel-call.ll
test/CodeGen/ARM/fast-isel-deadcode.ll
test/CodeGen/ARM/fast-isel-intrinsic.ll
test/CodeGen/ARM/fast-isel-mvn.ll
test/CodeGen/ARM/fast-isel-select.ll
test/CodeGen/ARM/fast-isel-vararg.ll
test/CodeGen/PowerPC/fast-isel-call.ll
test/CodeGen/X86/fast-isel-x86-64.ll

index 7af25db904794b7b9bcc186ce02b67e02206741b..b0503f0391fedc4f7422a17486857d78e26b8dac 100644 (file)
@@ -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.
index 1c2cee29a797d4b63e4abbbecbcfba9caf3d41e5..93a366a85460fd9920ed382e9a1815c8d46d24f8 100644 (file)
@@ -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);
   }
index 9d9e341647abf49b72f9a21ecc972662248162d3..74b31bd9e67fdce14b781f212865e160d9bba92e 100644 (file)
@@ -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
index 5e6666c47d3ed7ea12a03174f9aea8d892c2a3b9..c3eed30692b81ea90842f08fdcd69bfdd300a14b 100644 (file)
@@ -14,7 +14,6 @@ entry:
 ; THUMB-NOT: ldr
 ; THUMB-NOT: sxtb
 ; THUMB: movs r0, #0
-; THUMB: movt r0, #0
 ; THUMB: pop
   ret i32 0
 }
index 089209e45fc3d15c073bf597cd05d83c13b3bd78..b09931dc4e2f7ff71c27851b7056e9858acdaaaa 100644 (file)
@@ -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
index 9cb56ea9ae13c0d31d241a852501d6d1b1f55678..7ec7f3ce32d8ea0200bc499618340671daf39300 100644 (file)
@@ -1,17 +1,13 @@
 ; 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=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
 ; 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
 }
@@ -20,22 +16,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
 }
@@ -43,66 +33,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
 }
index 40f88075039e054d99740db2040f4f9fa5b1b0f3..549c97e24dcd99322d3b6ce7b7ac81401bdd216b 100644 (file)
@@ -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
 }
index 0b7b0bd1c6f0ad17c3db7d2e4153b94a4cb4a779..3ff2b151ab5fed448dfec813516fb4806b72ccdd 100644 (file)
@@ -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]
index 33a8ba903e3d60590dac00bd2b076d3ba74c60c7..223090523c4d187c00da72d3cbbe6323cb956804 100644 (file)
@@ -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
index f7d2750b5b815ed98ca0281504cc61c3b631cde4..29f1f264a72990deaa512d462e054d2d3508aaba 100644 (file)
@@ -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