[llvm] r192432 - XCore target: fix bug in XCoreLowerThreadLocal.cpp

Robert Lytton robert at xmos.com
Fri Oct 11 03:26:49 PDT 2013


Author: rlytton
Date: Fri Oct 11 05:26:48 2013
New Revision: 192432

URL: http://llvm.org/viewvc/llvm-project?rev=192432&view=rev
Log:
XCore target: fix bug in XCoreLowerThreadLocal.cpp

When a ConstantExpr which uses a thread local is part of a PHI node
instruction, the insruction that replaces the ConstantExpr must
be inserted in the predecessor block, in front of the terminator instruction.
If the predecessor block has multiple successors, the edge is first split.

Modified:
    llvm/trunk/lib/Target/XCore/XCoreLowerThreadLocal.cpp
    llvm/trunk/test/CodeGen/XCore/threads.ll

Modified: llvm/trunk/lib/Target/XCore/XCoreLowerThreadLocal.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/XCore/XCoreLowerThreadLocal.cpp?rev=192432&r1=192431&r2=192432&view=diff
==============================================================================
--- llvm/trunk/lib/Target/XCore/XCoreLowerThreadLocal.cpp (original)
+++ llvm/trunk/lib/Target/XCore/XCoreLowerThreadLocal.cpp Fri Oct 11 05:26:48 2013
@@ -24,6 +24,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/NoFolder.h"
 #include "llvm/Support/ValueHandle.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
 
 #define DEBUG_TYPE "xcore-lower-thread-local"
 
@@ -124,32 +125,42 @@ createReplacementInstr(ConstantExpr *CE,
   }
 }
 
-static bool replaceConstantExprOp(ConstantExpr *CE) {
+static bool replaceConstantExprOp(ConstantExpr *CE, Pass *P) {
   do {
     SmallVector<WeakVH,8> WUsers;
     for (Value::use_iterator I = CE->use_begin(), E = CE->use_end();
          I != E; ++I)
       WUsers.push_back(WeakVH(*I));
+    std::sort(WUsers.begin(), WUsers.end());
+    WUsers.erase(std::unique(WUsers.begin(), WUsers.end()), WUsers.end());
     while (!WUsers.empty())
       if (WeakVH WU = WUsers.pop_back_val()) {
-        if (Instruction *Instr = dyn_cast<Instruction>(WU)) {
+        if (PHINode *PN = dyn_cast<PHINode>(WU)) {
+          for (int I = 0, E = PN->getNumIncomingValues(); I < E; ++I)
+            if (PN->getIncomingValue(I) == CE) {
+              BasicBlock *PredBB = PN->getIncomingBlock(I);
+              if (PredBB->getTerminator()->getNumSuccessors() > 1)
+                PredBB = SplitEdge(PredBB, PN->getParent(), P);
+              Instruction *InsertPos = PredBB->getTerminator();
+              Instruction *NewInst = createReplacementInstr(CE, InsertPos);
+              PN->setOperand(I, NewInst);
+            }
+        } else if (Instruction *Instr = dyn_cast<Instruction>(WU)) {
           Instruction *NewInst = createReplacementInstr(CE, Instr);
-          assert(NewInst && "Must build an instruction\n");
-          // If NewInst uses a CE being handled in an earlier recursion the
-          // earlier recursion's do-while-hasNUsesOrMore(1) will run again.
           Instr->replaceUsesOfWith(CE, NewInst);
         } else {
           ConstantExpr *CExpr = dyn_cast<ConstantExpr>(WU);
-          if (!CExpr || !replaceConstantExprOp(CExpr))
+          if (!CExpr || !replaceConstantExprOp(CExpr, P))
             return false;
         }
       }
-  } while (CE->hasNUsesOrMore(1)); // Does a recursion's NewInst use CE?
+  } while (CE->hasNUsesOrMore(1)); // We need to check becasue a recursive
+  // sibbling may have used 'CE' when createReplacementInstr was called.
   CE->destroyConstant();
   return true;
 }
 
-static bool rewriteNonInstructionUses(GlobalVariable *GV) {
+static bool rewriteNonInstructionUses(GlobalVariable *GV, Pass *P) {
   SmallVector<WeakVH,8> WUsers;
   for (Value::use_iterator I = GV->use_begin(), E = GV->use_end(); I != E; ++I)
     if (!isa<Instruction>(*I))
@@ -157,7 +168,7 @@ static bool rewriteNonInstructionUses(Gl
   while (!WUsers.empty())
     if (WeakVH WU = WUsers.pop_back_val()) {
       ConstantExpr *CE = dyn_cast<ConstantExpr>(WU);
-      if (!CE || !replaceConstantExprOp(CE))
+      if (!CE || !replaceConstantExprOp(CE, P))
         return false;
     }
   return true;
@@ -175,7 +186,7 @@ bool XCoreLowerThreadLocal::lowerGlobal(
     return false;
 
   // Skip globals that we can't lower and leave it for the backend to error.
-  if (!rewriteNonInstructionUses(GV) ||
+  if (!rewriteNonInstructionUses(GV, this) ||
       !GV->getType()->isSized() || isZeroLengthArray(GV->getType()))
     return false;
 

Modified: llvm/trunk/test/CodeGen/XCore/threads.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/XCore/threads.ll?rev=192432&r1=192431&r2=192432&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/XCore/threads.ll (original)
+++ llvm/trunk/test/CodeGen/XCore/threads.ll Fri Oct 11 05:26:48 2013
@@ -1,4 +1,5 @@
 ; RUN: llc -march=xcore < %s | FileCheck %s
+; RUN: llc -march=xcore -O=0 < %s | FileCheck %s -check-prefix=PHINODE
 
 declare i8 addrspace(1)* @llvm.xcore.getst.p1i8.p1i8(i8 addrspace(1)* %r)
 declare void @llvm.xcore.msync.p1i8(i8 addrspace(1)* %r)
@@ -102,5 +103,43 @@ define i32 @f_tlExpr () {
       i32 ptrtoint( i32* getelementptr inbounds ([2 x i32]* @tle, i32 0, i32 0) to i32))
 }
 
+define void @phiNode1() {
+; N.B. lowering of duplicate constexpr in a PHI node requires -O=0
+; PHINODE-LABEL: phiNode1:
+; PHINODE: get r11, id
+; PHINODE-LABEL: .LBB11_1:
+; PHINODE: get r11, id
+; PHINODE: bu .LBB11_1
+entry:
+  br label %ConstantExpPhiNode
+ConstantExpPhiNode:
+  %ptr = phi i32* [ getelementptr inbounds ([3 x i32]* @tl, i32 0, i32 0), %entry ],
+                  [ getelementptr inbounds ([3 x i32]* @tl, i32 0, i32 0), %ConstantExpPhiNode ]
+  br label %ConstantExpPhiNode
+exit:
+  ret void
+}
+
+define void @phiNode2( i1 %bool) {
+; N.B. check an extra 'Node_crit_edge' (LBB12_1) is inserted
+; PHINODE-LABEL: phiNode2:
+; PHINODE: bf {{r[0-9]}}, .LBB12_3
+; PHINODE: bu .LBB12_1
+; PHINODE-LABEL: .LBB12_1:
+; PHINODE: get r11, id
+; PHINODE-LABEL: .LBB12_2:
+; PHINODE: get r11, id
+; PHINODE: bu .LBB12_2
+; PHINODE-LABEL: .LBB12_3:
+entry:
+  br i1 %bool, label %ConstantExpPhiNode, label %exit
+ConstantExpPhiNode:
+  %ptr = phi i32* [ getelementptr inbounds ([3 x i32]* @tl, i32 0, i32 0), %entry ],
+                  [ getelementptr inbounds ([3 x i32]* @tl, i32 0, i32 0), %ConstantExpPhiNode ]
+  br label %ConstantExpPhiNode
+exit:
+  ret void
+}
+
 ; CHECK-LABEL: tl:
 ; CHECK: .space  96





More information about the llvm-commits mailing list