rsmith updated this revision to Diff 261511.
rsmith added a comment.

- The second operand of 'store' is the pointer, not the first.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D79249/new/

https://reviews.llvm.org/D79249

Files:
  clang/lib/CodeGen/CGDecl.cpp
  llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
  llvm/include/llvm/IR/Intrinsics.td
  llvm/lib/CodeGen/CodeGenPrepare.cpp
  llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
  llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
  llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
  llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
  llvm/lib/Transforms/InstCombine/InstCombineInternal.h
  llvm/lib/Transforms/Scalar/LowerConstantIntrinsics.cpp

Index: llvm/lib/Transforms/Scalar/LowerConstantIntrinsics.cpp
===================================================================
--- llvm/lib/Transforms/Scalar/LowerConstantIntrinsics.cpp
+++ llvm/lib/Transforms/Scalar/LowerConstantIntrinsics.cpp
@@ -6,8 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This pass lowers all remaining 'objectsize' 'is.constant' intrinsic calls
-// and provides constant propagation and basic CFG cleanup on the result.
+// This pass lowers all remaining 'objectsize', 'is.constant', and 'trapping'
+// intrinsic calls and provides constant propagation and basic CFG cleanup on
+// the result.
 //
 //===----------------------------------------------------------------------===//
 
@@ -39,6 +40,8 @@
           "Number of 'is.constant' intrinsic calls handled");
 STATISTIC(ObjectSizeIntrinsicsHandled,
           "Number of 'objectsize' intrinsic calls handled");
+STATISTIC(TrappingIntrinsicsHandled,
+          "Number of 'trapping' intrinsic calls handled");
 
 static Value *lowerIsConstantIntrinsic(IntrinsicInst *II) {
   Value *Op = II->getOperand(0);
@@ -99,6 +102,7 @@
         break;
       case Intrinsic::is_constant:
       case Intrinsic::objectsize:
+      case Intrinsic::trapping:
         Worklist.push_back(WeakTrackingVH(&I));
         break;
       }
@@ -125,6 +129,10 @@
       NewValue = lowerObjectSizeCall(II, DL, TLI, true);
       ObjectSizeIntrinsicsHandled++;
       break;
+    case Intrinsic::trapping:
+      NewValue = II->getOperand(0);
+      TrappingIntrinsicsHandled++;
+      break;
     }
     HasDeadBlocks |= replaceConditionalBranchesOnConstant(II, NewValue);
   }
Index: llvm/lib/Transforms/InstCombine/InstCombineInternal.h
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -635,6 +635,8 @@
 
   Instruction *foldIntrinsicWithOverflowCommon(IntrinsicInst *II);
 
+  bool simplifyTrappingUse(Use &U);
+
 public:
   /// Inserts an instruction \p New before instruction \p Old
   ///
Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1846,6 +1846,80 @@
   return nullptr;
 }
 
+static bool canObservePoison(Use &U, Instruction *I) {
+  if (U.getOperandNo() == 0 &&
+      (isa<SwitchInst>(I) || isa<BranchInst>(I) || isa<IndirectBrInst>(I)))
+    return true;
+  if (auto *CB = dyn_cast<CallBase>(I))
+    if (CB->getCalledOperandUse().getOperandNo() == U.getOperandNo())
+      return true;
+  if (auto *LI = dyn_cast<LoadInst>(I))
+    if (LI->getPointerOperandIndex() == U.getOperandNo())
+      return true;
+  if (auto *SI = dyn_cast<StoreInst>(I))
+    if (SI->getPointerOperandIndex() == U.getOperandNo())
+      return true;
+  if (U.getOperandNo() == 1 && I->isIntDivRem())
+    return true;
+  // FIXME: More cases?
+  return false;
+}
+
+/// Simplify a use of @llvm.trapping.<type>(<type> %x)
+///
+/// Return true if we've performed a simplification and the use should be
+/// replaced by %x.
+bool InstCombiner::simplifyTrappingUse(Use &U) {
+  auto *I = dyn_cast<Instruction>(U.getUser());
+
+  // We only care about trapping indicators on instructions.
+  if (!I)
+    return true;
+
+  // FIXME: If all operands are trapping, we can convert to trapping(phi(...)).
+  if (isa<PHINode>(I))
+    return false;
+
+  // The result of select is trapping if its condition is trapping.
+  if (isa<SelectInst>(I) && U.getOperandNo() != 0)
+    return false;
+
+  // trapping(trapping(x)) -> trapping(x).
+  if (auto *II = dyn_cast<IntrinsicInst>(I))
+    if (II->getIntrinsicID() == Intrinsic::trapping)
+      return true;
+
+  // op(trapping(x)) -> @llvm.trap() where possible.
+  if (canObservePoison(U, I)) {
+    CallInst *Trap = CallInst::Create(
+        Intrinsic::getDeclaration(I->getModule(), Intrinsic::trap));
+    InsertNewInstBefore(Trap, *I);
+    return true;
+  }
+
+  // We can't propagate trapping to the result of a void-typed instruction and
+  // a few other cases.
+  if (I->getType()->isVoidTy() || I->getType()->isTokenTy() ||
+      I->isTerminator())
+    return false;
+
+  // Don't propagate through call arguments to the result of the function for
+  // now.
+  if (isa<CallBase>(I))
+    return false;
+
+  // op(trapping(x)) -> trapping(op(x)) otherwise.
+  CallInst *TrappingI =
+      CallInst::Create(Intrinsic::getDeclaration(
+                           I->getModule(), Intrinsic::trapping, {I->getType()}),
+                       {I});
+  TrappingI->insertAfter(I);
+  replaceInstUsesWith(*I, TrappingI);
+  // Undo effect of replaceInstUsesWith on TrappingI itself.
+  TrappingI->setArgOperand(0, I);
+  return true;
+}
+
 /// CallInst simplification. This mostly only handles folding of intrinsic
 /// instructions. For normal calls, it allows visitCallBase to do the heavy
 /// lifting.
@@ -4207,6 +4281,23 @@
     AC.updateAffectedValues(II);
     break;
   }
+  case Intrinsic::trapping: {
+    bool RemovedAllUses = true;
+    // Note, it's not safe to change the uses of II while iterating over the
+    // same list.
+    llvm::SmallVector<Use*, 8> UsesToReplace;
+    for (Use &U : II->uses()) {
+      if (simplifyTrappingUse(U))
+        UsesToReplace.push_back(&U);
+      else
+        RemovedAllUses = false;
+    }
+    for (Use *U : UsesToReplace)
+      *U = II->getOperand(0);
+    if (!RemovedAllUses)
+      return nullptr;
+    return eraseInstFromFunction(*II);
+  }
   case Intrinsic::experimental_gc_relocate: {
     auto &GCR = *cast<GCRelocateInst>(II);
 
Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -6383,6 +6383,9 @@
   case Intrinsic::is_constant:
     llvm_unreachable("llvm.is.constant.* should have been lowered already");
 
+  case Intrinsic::trapping:
+    llvm_unreachable("llvm.trapping.* should have been lowered already");
+
   case Intrinsic::annotation:
   case Intrinsic::ptr_annotation:
   case Intrinsic::launder_invariant_group:
Index: llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -1474,6 +1474,9 @@
   case Intrinsic::is_constant:
     llvm_unreachable("llvm.is.constant.* should have been lowered already");
 
+  case Intrinsic::trapping:
+    llvm_unreachable("llvm.trapping.* should have been lowered already");
+
   case Intrinsic::launder_invariant_group:
   case Intrinsic::strip_invariant_group:
   case Intrinsic::expect: {
Index: llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
===================================================================
--- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -1474,6 +1474,9 @@
   case Intrinsic::is_constant:
     llvm_unreachable("llvm.is.constant.* should have been lowered already");
 
+  case Intrinsic::trapping:
+    llvm_unreachable("llvm.trapping.* should have been lowered already");
+
   case Intrinsic::stackguard:
     getStackGuard(getOrCreateVReg(CI), MIRBuilder);
     return true;
Index: llvm/lib/CodeGen/CodeGenPrepare.cpp
===================================================================
--- llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -1992,6 +1992,8 @@
       llvm_unreachable("llvm.objectsize.* should have been lowered already");
     case Intrinsic::is_constant:
       llvm_unreachable("llvm.is.constant.* should have been lowered already");
+    case Intrinsic::trapping:
+      llvm_unreachable("llvm.trapping.* should have been lowered already");
     case Intrinsic::aarch64_stlxr:
     case Intrinsic::aarch64_stxr: {
       ZExtInst *ExtVal = dyn_cast<ZExtInst>(CI->getArgOperand(0));
Index: llvm/include/llvm/IR/Intrinsics.td
===================================================================
--- llvm/include/llvm/IR/Intrinsics.td
+++ llvm/include/llvm/IR/Intrinsics.td
@@ -1120,6 +1120,8 @@
                GCCBuiltin<"__builtin_trap">;
 def int_debugtrap : Intrinsic<[]>,
                     GCCBuiltin<"__builtin_debugtrap">;
+def int_trapping : Intrinsic<[llvm_any_ty], [LLVMMatchType<0>],
+                             [IntrNoMem, IntrWillReturn, IntrSpeculatable]>;
 
 // Support for dynamic deoptimization (or de-specialization)
 def int_experimental_deoptimize : Intrinsic<[llvm_any_ty], [llvm_vararg_ty],
Index: llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
===================================================================
--- llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -765,6 +765,7 @@
     case Intrinsic::objectsize:
     case Intrinsic::ptr_annotation:
     case Intrinsic::var_annotation:
+    case Intrinsic::trapping:
     case Intrinsic::experimental_gc_result:
     case Intrinsic::experimental_gc_relocate:
     case Intrinsic::coro_alloc:
Index: clang/lib/CodeGen/CGDecl.cpp
===================================================================
--- clang/lib/CodeGen/CGDecl.cpp
+++ clang/lib/CodeGen/CGDecl.cpp
@@ -1148,7 +1148,7 @@
 static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D,
                                   Address Loc, bool isVolatile,
                                   CGBuilderTy &Builder,
-                                  llvm::Constant *constant) {
+                                  llvm::Constant *constant, bool Trapping) {
   auto *Ty = constant->getType();
   uint64_t ConstantSize = CGM.getDataLayout().getTypeAllocSize(Ty);
   if (!ConstantSize)
@@ -1156,8 +1156,17 @@
 
   bool canDoSingleStore = Ty->isIntOrIntVectorTy() ||
                           Ty->isPtrOrPtrVectorTy() || Ty->isFPOrFPVectorTy();
-  if (canDoSingleStore) {
-    Builder.CreateStore(constant, Loc, isVolatile);
+  if (canDoSingleStore || Trapping) {
+    llvm::Value *V = constant;
+
+    // Pass through @llvm.trapping if requested.
+    if (Trapping) {
+      llvm::Function *TrapFn = llvm::Intrinsic::getDeclaration(
+          &CGM.getModule(), llvm::Intrinsic::trapping, {V->getType()});
+      V = Builder.CreateCall(TrapFn, {V});
+    }
+
+    Builder.CreateStore(V, Loc, isVolatile);
     return;
   }
 
@@ -1202,7 +1211,8 @@
           Address EltPtr = Builder.CreateStructGEP(Loc, i);
           emitStoresForConstant(
               CGM, D, EltPtr, isVolatile, Builder,
-              cast<llvm::Constant>(Builder.CreateExtractValue(constant, i)));
+              cast<llvm::Constant>(Builder.CreateExtractValue(constant, i)),
+              Trapping);
         }
         return;
       }
@@ -1213,7 +1223,8 @@
           Address EltPtr = Builder.CreateConstArrayGEP(Loc, i);
           emitStoresForConstant(
               CGM, D, EltPtr, isVolatile, Builder,
-              cast<llvm::Constant>(Builder.CreateExtractValue(constant, i)));
+              cast<llvm::Constant>(Builder.CreateExtractValue(constant, i)),
+              Trapping);
         }
         return;
       }
@@ -1233,7 +1244,7 @@
   llvm::Type *ElTy = Loc.getElementType();
   llvm::Constant *constant =
       constWithPadding(CGM, IsPattern::No, llvm::Constant::getNullValue(ElTy));
-  emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant);
+  emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant, /*FIXME*/true);
 }
 
 static void emitStoresForPatternInit(CodeGenModule &CGM, const VarDecl &D,
@@ -1243,7 +1254,7 @@
   llvm::Constant *constant = constWithPadding(
       CGM, IsPattern::Yes, initializationPatternFor(CGM, ElTy));
   assert(!isa<llvm::UndefValue>(constant));
-  emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant);
+  emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant, /*FIXME*/true);
 }
 
 static bool containsUndef(llvm::Constant *constant) {
@@ -1859,7 +1870,7 @@
   llvm::Type *BP = CGM.Int8Ty->getPointerTo(Loc.getAddressSpace());
   emitStoresForConstant(
       CGM, D, (Loc.getType() == BP) ? Loc : Builder.CreateBitCast(Loc, BP),
-      type.isVolatileQualified(), Builder, constant);
+      type.isVolatileQualified(), Builder, constant, /*Trapping=*/false);
 }
 
 /// Emit an expression as an initializer for an object (variable, field, etc.)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D79249: [... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D792... Richard Smith - zygoloid via Phabricator via cfe-commits

Reply via email to