[FastISel]
authorJuergen Ributzka <juergen@apple.com>
Thu, 28 Aug 2014 00:09:46 +0000 (00:09 +0000)
committerJuergen Ributzka <juergen@apple.com>
Thu, 28 Aug 2014 00:09:46 +0000 (00:09 +0000)
Currently instructions are folded very aggressively for AArch64 into the memory
operation, which can lead to the use of killed operands:
  %vreg1<def> = ADDXri %vreg0<kill>, 2
  %vreg2<def> = LDRBBui %vreg0, 2
  ... = ... %vreg1 ...

This usually happens when the result is also used by another non-memory
instruction in the same basic block, or any instruction in another basic block.

This fix teaches hasTrivialKill to not only check the LLVM IR that the value has
a single use, but also to check if the register that represents that value has
already been used. This can happen when the instruction with the use was folded
into another instruction (in this particular case a load instruction).

This fixes rdar://problem/18142857.

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

include/llvm/CodeGen/FastISel.h
lib/CodeGen/SelectionDAG/FastISel.cpp
test/CodeGen/AArch64/fast-isel-addressing-modes.ll

index b0503f0391fedc4f7422a17486857d78e26b8dac..ed370c3e67cbfef3e1a930dda7c32bf8fde7f0f3 100644 (file)
@@ -525,7 +525,7 @@ protected:
   bool canFoldAddIntoGEP(const User *GEP, const Value *Add);
 
   /// Test whether the given value has exactly one use.
-  bool hasTrivialKill(const Value *V) const;
+  bool hasTrivialKill(const Value *V);
 
   /// \brief Create a machine mem operand from the given instruction.
   MachineMemOperand *createMachineMemOperandFor(const Instruction *I) const;
index 0a81662e9a3efb53a588491f2c3ddadc4b00cde2..1896c67d17764eb8ce08dc1470720a6a15226b1b 100644 (file)
@@ -131,7 +131,7 @@ void FastISel::flushLocalValueMap() {
   recomputeInsertPt();
 }
 
-bool FastISel::hasTrivialKill(const Value *V) const {
+bool FastISel::hasTrivialKill(const Value *V) {
   // Don't consider constants or arguments to have trivial kills.
   const Instruction *I = dyn_cast<Instruction>(V);
   if (!I)
@@ -143,6 +143,13 @@ bool FastISel::hasTrivialKill(const Value *V) const {
         !hasTrivialKill(Cast->getOperand(0)))
       return false;
 
+  // Even the value might have only one use in the LLVM IR, it is possible that
+  // FastISel might fold the use into another instruction and now there is more
+  // than one use at the Machine Instruction level.
+  unsigned Reg = lookUpRegForValue(V);
+  if (Reg && !MRI.use_empty(Reg))
+    return false;
+
   // GEPs with all zero indices are trivially coalesced by fast-isel.
   if (const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I))
     if (GEP->hasAllZeroIndices() && !hasTrivialKill(GEP->getOperand(0)))
index 750e081d42365e9ed0d704aae3c6acbe54caac00..86755d90c63241666cc263a6cabb3545af61e6d5 100644 (file)
@@ -478,3 +478,13 @@ define i64 @load_breg_sext_shift_offreg_imm1(i32 %a, i64 %b) {
   ret i64 %6
 }
 
+; Test that the kill flag is not set - the machine instruction verifier does that for us.
+define i64 @kill_reg(i64 %a) {
+  %1 = sub i64 %a, 8
+  %2 = add i64 %1, 96
+  %3 = inttoptr i64 %2 to i64*
+  %4 = load i64* %3
+  %5 = add i64 %2, %4
+  ret i64 %5
+}
+