summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Doerfert <doerfert@cs.uni-saarland.de>2016-06-06 12:12:27 +0000
committerJohannes Doerfert <doerfert@cs.uni-saarland.de>2016-06-06 12:12:27 +0000
commitdedb7693ec2d6c37f7d6c36f13b562fd63903cca (patch)
tree9e89730169a9c42e17494e7ccc226eebc3f8f6c4
parentf21beb2c7461b3fb483a50ddfd4f92e29113887d (diff)
downloadbcm5719-llvm-dedb7693ec2d6c37f7d6c36f13b562fd63903cca.tar.gz
bcm5719-llvm-dedb7693ec2d6c37f7d6c36f13b562fd63903cca.zip
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. llvm-svn: 271888
-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 2f53227d70d..73e3a00ed2c 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..c4deab0ee48
--- /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 %9 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: %9 = 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..faebb10ac0c
--- /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 %25 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: %25 = 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