Don't taint relaxed loads that immediately comes before an AcqRel read-modify-write op
[oota-llvm.git] / lib / CodeGen / CodeGenPrepare.cpp
index 5f22c14f90fbb79e8f649e50a3d26f2032c46947..1837ba2bd5d4678d3f5132aaf421f6c9ac4a25bd 100644 (file)
@@ -328,7 +328,15 @@ Value* createCast(IRBuilder<true, NoFolder>& Builder, Value* DepVal,
   Instruction::CastOps CastOp = Instruction::BitCast;
   switch (DepVal->getType()->getTypeID()) {
     case Type::IntegerTyID: {
-      CastOp = Instruction::SExt;
+      assert(TargetIntegerType->getTypeID() == Type::IntegerTyID);
+      auto* FromType = dyn_cast<IntegerType>(DepVal->getType());
+      auto* ToType = dyn_cast<IntegerType>(TargetIntegerType);
+      assert(FromType && ToType);
+      if (FromType->getBitWidth() <= ToType->getBitWidth()) {
+        CastOp = Instruction::ZExt;
+      } else {
+        CastOp = Instruction::Trunc;
+      }
       break;
     }
     case Type::FloatTyID:
@@ -729,6 +737,28 @@ Instruction* findFirstStoreCondBranchInst(LoadInst* LI, Vector* ChainedBB) {
   }
 }
 
+// XXX-update: Find the next node of the last relaxed load from 'FromInst' to
+// 'ToInst'. If none, return 'ToInst'.
+Instruction* findLastLoadNext(Instruction* FromInst, Instruction* ToInst) {
+  if (FromInst == ToInst) {
+    return ToInst;
+  }
+  Instruction* LastLoad = ToInst;
+  auto* BB = FromInst->getParent();
+  auto BE = BB->end();
+  auto BBI = BasicBlock::iterator(FromInst);
+  BBI++;
+  for (; BBI != BE && &*BBI != ToInst; BBI++) {
+    auto* LI = dyn_cast<LoadInst>(&*BBI);
+    if (LI == nullptr || !LI->isAtomic() || LI->getOrdering() != Monotonic) {
+      continue;
+    }
+    LastLoad = LI;
+    LastLoad = LastLoad->getNextNode();
+  }
+  return LastLoad;
+}
+
 // XXX-comment: Returns whether the code has been changed.
 bool taintMonotonicLoads(const SmallVector<LoadInst*, 1>& MonotonicLoadInsts) {
   bool Changed = false;
@@ -791,21 +821,16 @@ void TaintRelaxedLoads(Instruction* UsageInst, Instruction* InsertPoint) {
   auto* BB = UsageInst->getParent();
   if (InsertPoint == nullptr) {
     InsertPoint = UsageInst->getNextNode();
-    while (dyn_cast<PHINode>(InsertPoint)) {
-      InsertPoint = InsertPoint->getNextNode();
-    }
+  }
+  // Insert instructions after PHI nodes.
+  while (dyn_cast<PHINode>(InsertPoint)) {
+    InsertPoint = InsertPoint->getNextNode();
   }
   // First thing is to cast 'UsageInst' to an integer type if necessary.
   Value* AndTarget = nullptr;
-  if (IntegerType::classof(UsageInst->getType())) {
-    AndTarget = UsageInst;
-  } else {
-    Type* TargetIntegerType = IntegerType::get(
-        UsageInst->getContext(),
-        BB->getModule()->getDataLayout().getPointerSizeInBits());
-    IRBuilder<true, NoFolder> Builder(UsageInst->getNextNode());
-    AndTarget = createCast(Builder, UsageInst, TargetIntegerType);
-  }
+  Type* TargetIntegerType =
+      IntegerType::get(UsageInst->getContext(),
+                       BB->getModule()->getDataLayout().getPointerSizeInBits());
 
   // Check whether InsertPoint is a added fake conditional branch.
   BranchInst* BI = nullptr;
@@ -830,6 +855,11 @@ void TaintRelaxedLoads(Instruction* UsageInst, Instruction* InsertPoint) {
           // Now we have a previously added fake cond branch.
           auto* Op00 = Op0->getOperand(0);
           IRBuilder<true, NoFolder> Builder(CmpInst);
+          if (Op00->getType() == UsageInst->getType()) {
+            AndTarget = UsageInst;
+          } else {
+            AndTarget = createCast(Builder, UsageInst, Op00->getType());
+          }
           AndTarget = Builder.CreateAnd(Op00, AndTarget);
           auto* AndZero = dyn_cast<Instruction>(Builder.CreateAnd(
               AndTarget, Constant::getNullValue(AndTarget->getType())));
@@ -841,6 +871,11 @@ void TaintRelaxedLoads(Instruction* UsageInst, Instruction* InsertPoint) {
   }
 
   IRBuilder<true, NoFolder> Builder(InsertPoint);
+  if (IntegerType::classof(UsageInst->getType())) {
+    AndTarget = UsageInst;
+  } else {
+    AndTarget = createCast(Builder, UsageInst, TargetIntegerType);
+  }
   auto* AndZero = dyn_cast<Instruction>(
       Builder.CreateAnd(AndTarget, Constant::getNullValue(AndTarget->getType())));
   auto* FakeCondition = dyn_cast<Instruction>(Builder.CreateICmp(
@@ -1378,7 +1413,8 @@ bool CodeGenPrepare::runOnFunction(Function &F) {
       switch (I->getOpcode()) {
         case Instruction::Load: {
           auto* LI = dyn_cast<LoadInst>(&*I);
-          if (LI->getOrdering() == Monotonic) {
+          if (LI->getOrdering() == Monotonic &&
+              !LI->getHasSubsequentAcqlRMW()) {
             MonotonicLoadInsts.insert(LI);
           }
           break;