CodeGen: Allow function parameters to be rewritten in getNewValue()

When deriving new values for the statements of a SCoP, we assumed that parameter
values are constant within the SCoP and consquently do not need to be rewritten.
For OpenMP code generation this assumption is wrong, as such values are not
available in the OpenMP subfunction and consequently also may need to be
rewritten.

Committed with some changes.

Contributed-By: Johannes Doerfert  <s9jodoer@stud.uni-saarland.de>
llvm-svn: 153838
This commit is contained in:
Tobias Grosser 2012-04-01 16:49:45 +00:00
parent 12af4285d1
commit 89339067b0
3 changed files with 83 additions and 10 deletions

View File

@ -283,12 +283,11 @@ BlockGenerator::BlockGenerator(IRBuilder<> &B, ScopStmt &Stmt, Pass *P):
Value *BlockGenerator::getNewValue(const Value *Old, ValueMapT &BBMap,
ValueMapT &GlobalMap) {
const Instruction *Inst = dyn_cast<Instruction>(Old);
if (!Inst)
// We assume constants never change.
// This avoids map lookups for many calls to this function.
if (isa<Constant>(Old))
return const_cast<Value*>(Old);
// OldOperand was redefined outside of this BasicBlock.
if (GlobalMap.count(Old)) {
Value *New = GlobalMap[Old];
@ -299,17 +298,22 @@ Value *BlockGenerator::getNewValue(const Value *Old, ValueMapT &BBMap,
return New;
}
// OldOperand was recalculated within this BasicBlock.
if (BBMap.count(Old)) {
return BBMap[Old];
}
// OldOperand is SCoP invariant.
if (!Statement.getParent()->getRegion().contains(Inst->getParent()))
return const_cast<Value*>(Old);
// 'Old' is within the original SCoP, but was not rewritten.
//
// Such values appear, if they only calculate information already available in
// the polyhedral description (e.g. an induction variable increment). They
// can be safely ignored.
if (const Instruction *Inst = dyn_cast<Instruction>(Old))
if (Statement.getParent()->getRegion().contains(Inst->getParent()))
return NULL;
// We could not find any valid new operand.
return NULL;
// Everything else is probably a scop-constant value defined as global,
// function parameter or an instruction not within the scop.
return const_cast<Value*>(Old);
}
void BlockGenerator::copyInstScalar(const Instruction *Inst, ValueMapT &BBMap,

View File

@ -0,0 +1,28 @@
/*
* =============================================================================
*
* Filename: 20120330-argument-use.c
*
* Description: Polly OpenMP test case
*
* Test if the OpenMP subfunction uses the argument copy in
* the OpenMP struct not the original one only available in
* the original function.
*
* Run with -polly-codegen -enable-polly-openmp
*
* Author: Johannes Doerfert johannes@jdoerfert.de
*
* Created: 2012-03-30
* Modified: 2012-03-30
*
* =============================================================================
*/
void f(int * restrict A, int * restrict B, int n) {
int i;
for (i = 0; i < n; i++) {
A[i] = B[i] * 2;
}
}

View File

@ -0,0 +1,41 @@
; RUN: opt %loadPolly %defaultOpts -polly-codegen -enable-polly-openmp %s -S | FileCheck %s
; ModuleID = '20120330-argument-lookup.s'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define void @f(i32* noalias %A, i32* noalias %B, i32 %n) nounwind uwtable {
entry:
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
%tmp = trunc i64 %indvars.iv to i32
%cmp = icmp slt i32 %tmp, %n
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
%arrayidx = getelementptr inbounds i32* %B, i64 %indvars.iv
%tmp1 = load i32* %arrayidx, align 4
%mul = shl nsw i32 %tmp1, 1
%arrayidx2 = getelementptr inbounds i32* %A, i64 %indvars.iv
store i32 %mul, i32* %arrayidx2, align 4
br label %for.inc
for.inc: ; preds = %for.body
%indvars.iv.next = add i64 %indvars.iv, 1
br label %for.cond
for.end: ; preds = %for.cond
ret void
}
; CHECK: %omp.userContext1 = bitcast i8* %omp.userContext to { i32, i32, i32*, i32* }*
; CHECK: %0 = getelementptr inbounds { i32, i32, i32*, i32* }* %omp.userContext1, i32 0, i32 0
; CHECK: %1 = load i32* %0
; CHECK: %2 = getelementptr inbounds { i32, i32, i32*, i32* }* %omp.userContext1, i32 0, i32 1
; CHECK: %3 = load i32* %2
; CHECK: %4 = getelementptr inbounds { i32, i32, i32*, i32* }* %omp.userContext1, i32 0, i32 2
; CHECK: %5 = load i32** %4
; CHECK: %6 = getelementptr inbounds { i32, i32, i32*, i32* }* %omp.userContext1, i32 0, i32 3
; CHECK: %7 = load i32** %6