[llvm] bb03446 - [memcpyopt] Conservatively handle non-integral pointers
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 1 16:47:09 PDT 2020
Author: Philip Reames
Date: 2020-10-01T16:46:56-07:00
New Revision: bb0344644a656734d707ab9c0baf6eb0533ac905
URL: https://github.com/llvm/llvm-project/commit/bb0344644a656734d707ab9c0baf6eb0533ac905
DIFF: https://github.com/llvm/llvm-project/commit/bb0344644a656734d707ab9c0baf6eb0533ac905.diff
LOG: [memcpyopt] Conservatively handle non-integral pointers
If we allow the non-integral pointers to become memset and memcpy, we loose the ability to reason about pointer propagation. This patch is modeled on changes we've carried downstream for a long time, figured it was worth being equally conservative for other users. There is room to refine the semantics and handling here if anyone is motivated.
Added:
llvm/test/Transforms/MemCpyOpt/non-integral.ll
Modified:
llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 0d66092a7035..01f3c322b1f4 100644
--- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -352,8 +352,15 @@ Instruction *MemCpyOptPass::tryMergingIntoMemset(Instruction *StartInst,
// If this is a store, see if we can merge it in.
if (!NextStore->isSimple()) break;
+ Value *StoredVal = NextStore->getValueOperand();
+
+ // Don't convert stores of non-integral pointer types to memsets (which
+ // stores integers).
+ if (DL.isNonIntegralPointerType(StoredVal->getType()->getScalarType()))
+ break;
+
// Check to see if this stored value is of the same byte-splattable value.
- Value *StoredByte = isBytewiseValue(NextStore->getOperand(0), DL);
+ Value *StoredByte = isBytewiseValue(StoredVal, DL);
if (isa<UndefValue>(ByteVal) && StoredByte)
ByteVal = StoredByte;
if (ByteVal != StoredByte)
@@ -556,8 +563,15 @@ bool MemCpyOptPass::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
const DataLayout &DL = SI->getModule()->getDataLayout();
+ Value *StoredVal = SI->getValueOperand();
+
+ // Not all the transforms below are correct for non-integral pointers, bail
+ // until we've audited the individual pieces.
+ if (DL.isNonIntegralPointerType(StoredVal->getType()->getScalarType()))
+ return false;
+
// Load to store forwarding can be interpreted as memcpy.
- if (LoadInst *LI = dyn_cast<LoadInst>(SI->getOperand(0))) {
+ if (LoadInst *LI = dyn_cast<LoadInst>(StoredVal)) {
if (LI->isSimple() && LI->hasOneUse() &&
LI->getParent() == SI->getParent()) {
diff --git a/llvm/test/Transforms/MemCpyOpt/non-integral.ll b/llvm/test/Transforms/MemCpyOpt/non-integral.ll
new file mode 100644
index 000000000000..eecbea32adb5
--- /dev/null
+++ b/llvm/test/Transforms/MemCpyOpt/non-integral.ll
@@ -0,0 +1,36 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -memcpyopt -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128-ni:1"
+
+define void @illegal_memset(i64 addrspace(1)** %p) {
+; CHECK-LABEL: @illegal_memset(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[P1:%.*]] = bitcast i64 addrspace(1)** [[P:%.*]] to i8*
+; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[P1]], i8 0, i64 8, i1 false)
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64 addrspace(1)*, i64 addrspace(1)** [[P]], i64 1
+; CHECK-NEXT: store i64 addrspace(1)* null, i64 addrspace(1)** [[GEP]], align 8
+; CHECK-NEXT: ret void
+;
+entry:
+ %p1 = bitcast i64 addrspace(1)** %p to i8*
+ call void @llvm.memset.p0i8.i64(i8* %p1, i8 0, i64 8, i32 0, i1 false)
+ %gep = getelementptr i64 addrspace(1)*, i64 addrspace(1)** %p, i64 1
+ store i64 addrspace(1)* null, i64 addrspace(1)** %gep
+ ret void
+}
+
+define void @illegal_memcpy(<2 x i8 addrspace(1)*>* noalias align 16 %a,
+; CHECK-LABEL: @illegal_memcpy(
+; CHECK-NEXT: [[VAL:%.*]] = load <2 x i8 addrspace(1)*>, <2 x i8 addrspace(1)*>* [[A:%.*]], align 16
+; CHECK-NEXT: store <2 x i8 addrspace(1)*> [[VAL]], <2 x i8 addrspace(1)*>* [[B:%.*]], align 16
+; CHECK-NEXT: ret void
+;
+ <2 x i8 addrspace(1)*>* noalias align 16 %b) {
+ %val = load <2 x i8 addrspace(1)*>, <2 x i8 addrspace(1)*>* %a, align 16
+ store <2 x i8 addrspace(1)*> %val, <2 x i8 addrspace(1)*>* %b, align 16
+ ret void
+}
+
+declare void @llvm.memset.p1i8.i64(i8 addrspace(1)*, i8, i64, i32, i1)
+declare void @llvm.memset.p0i8.i64(i8*, i8, i64, i32, i1)
More information about the llvm-commits
mailing list