summaryrefslogtreecommitdiffstats
path: root/polly
diff options
context:
space:
mode:
authorTobias Grosser <tobias@grosser.es>2016-06-11 19:26:08 +0000
committerTobias Grosser <tobias@grosser.es>2016-06-11 19:26:08 +0000
commit423642a59701ce381d9d4120929e5cc8c27f8489 (patch)
tree1710b8192563b06074c9d27fb4cb033542e24185 /polly
parent3fc09f7be672dd1adf4e0d939aa86badcdfd5df8 (diff)
downloadbcm5719-llvm-423642a59701ce381d9d4120929e5cc8c27f8489.tar.gz
bcm5719-llvm-423642a59701ce381d9d4120929e5cc8c27f8489.zip
Recommit: "Look through IntToPtr & PtrToInt instructions"
IntToPtr and PtrToInt instructions are basically no-ops that we can handle as such. In order to generate them properly as parameters we had to improve the ScopExpander, though the change is the first in the direction of a more aggressive scalar synthetization. This patch was originally contributed by Johannes Doerfert in r271888, but was in conflict with the revert in r272483. This is a recommit with some minor adjustment to the test cases to take care of differing instruction names. llvm-svn: 272485
Diffstat (limited to 'polly')
-rw-r--r--polly/lib/Support/SCEVAffinator.cpp4
-rw-r--r--polly/lib/Support/SCEVValidator.cpp4
-rw-r--r--polly/lib/Support/ScopHelper.cpp29
-rw-r--r--polly/test/Isl/CodeGen/inner_scev_sdiv_2.ll5
-rw-r--r--polly/test/Isl/CodeGen/ptrtoint_as_parameter.ll34
-rw-r--r--polly/test/ScopInfo/int2ptr_ptr2int.ll71
-rw-r--r--polly/test/ScopInfo/int2ptr_ptr2int_2.ll72
7 files changed, 210 insertions, 9 deletions
diff --git a/polly/lib/Support/SCEVAffinator.cpp b/polly/lib/Support/SCEVAffinator.cpp
index bff074761e0..347c12f60fd 100644
--- a/polly/lib/Support/SCEVAffinator.cpp
+++ b/polly/lib/Support/SCEVAffinator.cpp
@@ -565,6 +565,10 @@ __isl_give PWACtx SCEVAffinator::visitSRemInstruction(Instruction *SRem) {
__isl_give PWACtx SCEVAffinator::visitUnknown(const SCEVUnknown *Expr) {
if (Instruction *I = dyn_cast<Instruction>(Expr->getValue())) {
switch (I->getOpcode()) {
+ case Instruction::IntToPtr:
+ return visit(SE.getSCEVAtScope(I->getOperand(0), getScope()));
+ case Instruction::PtrToInt:
+ return visit(SE.getSCEVAtScope(I->getOperand(0), getScope()));
case Instruction::SDiv:
return visitSDivInstruction(I);
case Instruction::SRem:
diff --git a/polly/lib/Support/SCEVValidator.cpp b/polly/lib/Support/SCEVValidator.cpp
index 85bf815a21d..4b8516338e6 100644
--- a/polly/lib/Support/SCEVValidator.cpp
+++ b/polly/lib/Support/SCEVValidator.cpp
@@ -368,6 +368,10 @@ public:
if (Instruction *I = dyn_cast<Instruction>(Expr->getValue())) {
switch (I->getOpcode()) {
+ case Instruction::IntToPtr:
+ return visit(SE.getSCEVAtScope(I->getOperand(0), Scope));
+ case Instruction::PtrToInt:
+ return visit(SE.getSCEVAtScope(I->getOperand(0), Scope));
case Instruction::Load:
return visitLoadInstruction(I, Expr);
case Instruction::SDiv:
diff --git a/polly/lib/Support/ScopHelper.cpp b/polly/lib/Support/ScopHelper.cpp
index 8e7fb1edfff..d2c544d098d 100644
--- a/polly/lib/Support/ScopHelper.cpp
+++ b/polly/lib/Support/ScopHelper.cpp
@@ -246,6 +246,27 @@ private:
const Region &R;
ValueMapT *VMap;
+ const SCEV *visitGenericInst(const SCEVUnknown *E, Instruction *Inst,
+ Instruction *IP) {
+ if (!Inst || !R.contains(Inst))
+ return E;
+
+ assert(!Inst->mayThrow() && !Inst->mayReadOrWriteMemory() &&
+ !isa<PHINode>(Inst));
+
+ auto *InstClone = Inst->clone();
+ for (auto &Op : Inst->operands()) {
+ assert(SE.isSCEVable(Op->getType()));
+ auto *OpSCEV = SE.getSCEV(Op);
+ auto *OpClone = expandCodeFor(OpSCEV, Op->getType(), IP);
+ InstClone->replaceUsesOfWith(Op, OpClone);
+ }
+
+ InstClone->setName(Name + Inst->getName());
+ InstClone->insertBefore(IP);
+ return SE.getSCEV(InstClone);
+ }
+
const SCEV *visitUnknown(const SCEVUnknown *E) {
// If a value mapping was given try if the underlying value is remapped.
@@ -259,15 +280,11 @@ private:
return visit(NewE);
}
+ Instruction *StartIP = R.getEnteringBlock()->getTerminator();
Instruction *Inst = dyn_cast<Instruction>(E->getValue());
if (!Inst || (Inst->getOpcode() != Instruction::SRem &&
Inst->getOpcode() != Instruction::SDiv))
- return E;
-
- if (!R.contains(Inst))
- return E;
-
- Instruction *StartIP = R.getEnteringBlock()->getTerminator();
+ return visitGenericInst(E, Inst, StartIP);
const SCEV *LHSScev = SE.getSCEV(Inst->getOperand(0));
const SCEV *RHSScev = SE.getSCEV(Inst->getOperand(1));
diff --git a/polly/test/Isl/CodeGen/inner_scev_sdiv_2.ll b/polly/test/Isl/CodeGen/inner_scev_sdiv_2.ll
index b98846a469e..9b925443300 100644
--- a/polly/test/Isl/CodeGen/inner_scev_sdiv_2.ll
+++ b/polly/test/Isl/CodeGen/inner_scev_sdiv_2.ll
@@ -3,10 +3,9 @@
; The SCEV expression in this test case refers to a sequence of sdiv
; instructions, which are part of different bbs in the SCoP. When code
; generating the parameter expressions, the code that is generated by the SCEV
-; expander has still references to the in-scop instructions, which is invalid.
+; expander has still references to the in-scop instructions, which was invalid.
;
-; CHECK: polly.split_new_and_old:
-; CHECK-NOT: = sdiv i64 0, -4
+; CHECK: polly.start
;
target triple = "x86_64-unknown-linux-gnu"
diff --git a/polly/test/Isl/CodeGen/ptrtoint_as_parameter.ll b/polly/test/Isl/CodeGen/ptrtoint_as_parameter.ll
new file mode 100644
index 00000000000..1bbb9dd27ff
--- /dev/null
+++ b/polly/test/Isl/CodeGen/ptrtoint_as_parameter.ll
@@ -0,0 +1,34 @@
+; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s
+;
+; CHECK: polly.split_new_and_old:
+; CHECK-NEXT: %pollysub.ptr.lhs.cast263 = ptrtoint i8* inttoptr (i64 1 to i8*) to i64
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; Function Attrs: nounwind uwtable
+define void @XS_MIME__QuotedPrint_encode_qp() {
+entry:
+ %Perl_sv_len = alloca i64, align 8
+ br label %if.end
+
+if.end: ; preds = %entry
+ br label %while.cond
+
+while.cond: ; preds = %cond.true270, %if.then260, %if.end
+ %p.0 = phi i8* [ null, %if.end ], [ %p.4, %if.then260 ], [ %p.4, %cond.true270 ]
+ br i1 undef, label %if.then260, label %while.body210
+
+while.body210: ; preds = %while.cond
+ unreachable
+
+if.then260: ; preds = %while.cond
+ %p.4 = getelementptr inbounds i8, i8* null, i64 1
+ %sub.ptr.lhs.cast263 = ptrtoint i8* %p.4 to i64
+ %sub.ptr.sub265 = sub i64 %sub.ptr.lhs.cast263, 0
+ %div = udiv i64 0, %sub.ptr.sub265
+ %cmp268 = icmp ult i64 0, %div
+ br i1 %cmp268, label %cond.true270, label %while.cond
+
+cond.true270: ; preds = %if.then260
+ br label %while.cond
+}
diff --git a/polly/test/ScopInfo/int2ptr_ptr2int.ll b/polly/test/ScopInfo/int2ptr_ptr2int.ll
new file mode 100644
index 00000000000..0979ebaebba
--- /dev/null
+++ b/polly/test/ScopInfo/int2ptr_ptr2int.ll
@@ -0,0 +1,71 @@
+; RUN: opt %loadPolly -analyze -polly-scops < %s | FileCheck %s
+; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s --check-prefix=IR
+;
+; void f(long *A, long *ptr, long val) {
+; for (long i = 0; i < 100; i++) {
+; long ptrV = ((long)(ptr + 1)) + 1;
+; long valP = (long)(((long *)(val + 1)) + 1);
+; A[ptrV] += A[valP];
+; }
+; }
+;
+; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT: [val, ptr] -> { Stmt_for_body[i0] -> MemRef_A[9 + val] };
+; CHECK-NEXT: ReadAccess := [Reduction Type: +] [Scalar: 0]
+; CHECK-NEXT: [val, ptr] -> { Stmt_for_body[i0] -> MemRef_A[9 + ptr] };
+; CHECK-NEXT: MustWriteAccess := [Reduction Type: +] [Scalar: 0]
+; CHECK-NEXT: [val, ptr] -> { Stmt_for_body[i0] -> MemRef_A[9 + ptr] };
+;
+; IR: polly.stmt.for.body:
+; IR-NEXT: %p_tmp = ptrtoint i64* %scevgep to i64
+; IR-NEXT: %p_add = add nsw i64 %p_tmp, 1
+; IR-NEXT: %p_tmp1 = inttoptr i64 %10 to i64*
+; IR-NEXT: %p_add.ptr2 = getelementptr inbounds i64, i64* %p_tmp1, i64 1
+; IR-NEXT: %p_tmp2 = ptrtoint i64* %p_add.ptr2 to i64
+; IR-NEXT: %p_arrayidx = getelementptr inbounds i64, i64* %A, i64 %p_tmp2
+; IR-NEXT: %tmp3_p_scalar_ = load i64, i64* %p_arrayidx
+; IR-NEXT: %p_arrayidx3 = getelementptr inbounds i64, i64* %A, i64 %p_add
+; IR-NEXT: %tmp4_p_scalar_ = load i64, i64* %p_arrayidx3
+; IR-NEXT: %p_add4 = add nsw i64 %tmp4_p_scalar_, %tmp3_p_scalar_
+; IR-NEXT: store i64 %p_add4, i64* %p_arrayidx3
+;
+; IR: polly.loop_preheader:
+; IR-NEXT: %scevgep = getelementptr i64, i64* %ptr, i64 1
+; IR-NEXT: %10 = add i64 %val, 1
+; IR-NEXT: br label %polly.loop_header
+;
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i64* %A, i64* %ptr, i64 %val) {
+entry:
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %i.0 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
+ %exitcond = icmp ne i64 %i.0, 100
+ br i1 %exitcond, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %add.ptr = getelementptr inbounds i64, i64* %ptr, i64 1
+ %tmp = ptrtoint i64* %add.ptr to i64
+ %add = add nsw i64 %tmp, 1
+ %add1 = add nsw i64 %val, 1
+ %tmp1 = inttoptr i64 %add1 to i64*
+ %add.ptr2 = getelementptr inbounds i64, i64* %tmp1, i64 1
+ %tmp2 = ptrtoint i64* %add.ptr2 to i64
+ %arrayidx = getelementptr inbounds i64, i64* %A, i64 %tmp2
+ %tmp3 = load i64, i64* %arrayidx
+ %arrayidx3 = getelementptr inbounds i64, i64* %A, i64 %add
+ %tmp4 = load i64, i64* %arrayidx3
+ %add4 = add nsw i64 %tmp4, %tmp3
+ store i64 %add4, i64* %arrayidx3
+ br label %for.inc
+
+for.inc: ; preds = %for.body
+ %inc = add nuw nsw i64 %i.0, 1
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+}
diff --git a/polly/test/ScopInfo/int2ptr_ptr2int_2.ll b/polly/test/ScopInfo/int2ptr_ptr2int_2.ll
new file mode 100644
index 00000000000..e47e181c97b
--- /dev/null
+++ b/polly/test/ScopInfo/int2ptr_ptr2int_2.ll
@@ -0,0 +1,72 @@
+; RUN: opt %loadPolly -analyze -polly-scops < %s | FileCheck %s
+; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s --check-prefix=IR
+;
+; void f(long *A, long *B, long *ptr, long val) {
+; for (long i = 0; i < 100; i++) {
+; long ptrV = ((long)(ptr + 1)) + 1;
+; long valP = (long)(((long *)(val + 1)) + 1);
+; A[ptrV] += B[valP];
+; }
+; }
+;
+; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT: [val, ptr] -> { Stmt_for_body[i0] -> MemRef_B[9 + val] };
+; CHECK-NEXT: Execution Context: [val, ptr] -> { : val <= 9223372036854775806 }
+;
+; CHECK: ReadAccess := [Reduction Type: +] [Scalar: 0]
+; CHECK-NEXT: [val, ptr] -> { Stmt_for_body[i0] -> MemRef_A[9 + ptr] };
+; CHECK-NEXT: MustWriteAccess := [Reduction Type: +] [Scalar: 0]
+; CHECK-NEXT: [val, ptr] -> { Stmt_for_body[i0] -> MemRef_A[9 + ptr] };
+;
+; IR: polly.stmt.for.body:
+; IR-NEXT: %p_tmp = ptrtoint i64* %scevgep to i64
+; IR-NEXT: %p_add = add nsw i64 %p_tmp, 1
+; IR-NEXT: %p_tmp1 = inttoptr i64 %26 to i64*
+; IR-NEXT: %p_add.ptr2 = getelementptr inbounds i64, i64* %p_tmp1, i64 1
+; IR-NEXT: %p_tmp2 = ptrtoint i64* %p_add.ptr2 to i64
+; IR-NEXT: %p_arrayidx = getelementptr inbounds i64, i64* %B, i64 %p_tmp2
+; IR-NEXT: %p_arrayidx3 = getelementptr inbounds i64, i64* %A, i64 %p_add
+; IR-NEXT: %tmp4_p_scalar_ = load i64, i64* %p_arrayidx3
+; IR-NEXT: %p_add4 = add nsw i64 %tmp4_p_scalar_, %polly.preload.tmp3.merge
+; IR-NEXT: store i64 %p_add4, i64* %p_arrayidx3
+;
+; IR: polly.loop_preheader:
+; IR-NEXT: %scevgep = getelementptr i64, i64* %ptr, i64 1
+; IR-NEXT: %26 = add i64 %val, 1
+; IR-NEXT: br label %polly.loop_header
+;
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i64* %A, i64* %B, i64* %ptr, i64 %val) {
+entry:
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %i.0 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
+ %exitcond = icmp ne i64 %i.0, 100
+ br i1 %exitcond, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %add.ptr = getelementptr inbounds i64, i64* %ptr, i64 1
+ %tmp = ptrtoint i64* %add.ptr to i64
+ %add = add nsw i64 %tmp, 1
+ %add1 = add nsw i64 %val, 1
+ %tmp1 = inttoptr i64 %add1 to i64*
+ %add.ptr2 = getelementptr inbounds i64, i64* %tmp1, i64 1
+ %tmp2 = ptrtoint i64* %add.ptr2 to i64
+ %arrayidx = getelementptr inbounds i64, i64* %B, i64 %tmp2
+ %tmp3 = load i64, i64* %arrayidx
+ %arrayidx3 = getelementptr inbounds i64, i64* %A, i64 %add
+ %tmp4 = load i64, i64* %arrayidx3
+ %add4 = add nsw i64 %tmp4, %tmp3
+ store i64 %add4, i64* %arrayidx3
+ br label %for.inc
+
+for.inc: ; preds = %for.body
+ %inc = add nuw nsw i64 %i.0, 1
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+}
OpenPOWER on IntegriCloud