[polly] r252701 - [FIX] Create empty invariant equivalence classes
Johannes Doerfert via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 10 20:30:07 PST 2015
Author: jdoerfert
Date: Tue Nov 10 22:30:07 2015
New Revision: 252701
URL: http://llvm.org/viewvc/llvm-project?rev=252701&view=rev
Log:
[FIX] Create empty invariant equivalence classes
We now create all invariant equivalence classes for required invariant loads
instead of creating them on-demand. This way we can check if a parameter
references an invariant load that is actually not executed and was therefor
not materialized. If that happens the parameter is not materialized either.
This fixes bug 25469.
Added:
polly/trunk/test/Isl/CodeGen/invariant_load_not_executed_but_in_parameters.ll
Modified:
polly/trunk/lib/Analysis/ScopInfo.cpp
polly/trunk/lib/CodeGen/IslNodeBuilder.cpp
polly/trunk/test/ScopInfo/invariant_loads_complicated_dependences.ll
Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=252701&r1=252700&r2=252701&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Tue Nov 10 22:30:07 2015
@@ -1637,10 +1637,14 @@ void Scop::buildInvariantEquivalenceClas
const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand());
LoadInst *&ClassRep = EquivClasses[PointerSCEV];
- if (!ClassRep)
- ClassRep = LInst;
- else
+ if (ClassRep) {
InvEquivClassVMap[LInst] = ClassRep;
+ continue;
+ }
+
+ ClassRep = LInst;
+ InvariantEquivClasses.emplace_back(PointerSCEV, MemoryAccessList(),
+ nullptr);
}
}
@@ -2656,8 +2660,11 @@ void Scop::addInvariantLoads(ScopStmt &S
// Unify the execution context of the class and this statement.
isl_set *&IAClassDomainCtx = std::get<2>(IAClass);
- IAClassDomainCtx = isl_set_coalesce(
- isl_set_union(IAClassDomainCtx, isl_set_copy(DomainCtx)));
+ if (IAClassDomainCtx)
+ IAClassDomainCtx = isl_set_coalesce(
+ isl_set_union(IAClassDomainCtx, isl_set_copy(DomainCtx)));
+ else
+ IAClassDomainCtx = isl_set_copy(DomainCtx);
break;
}
@@ -2760,9 +2767,6 @@ void Scop::hoistInvariantLoads() {
}
isl_union_map_free(Writes);
- if (!InvariantEquivClasses.empty())
- IsOptimized = true;
-
auto &ScopRIL = *SD.getRequiredInvariantLoads(&getRegion());
// Check required invariant loads that were tagged during SCoP detection.
for (LoadInst *LI : ScopRIL) {
Modified: polly/trunk/lib/CodeGen/IslNodeBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/IslNodeBuilder.cpp?rev=252701&r1=252700&r2=252701&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/IslNodeBuilder.cpp (original)
+++ polly/trunk/lib/CodeGen/IslNodeBuilder.cpp Tue Nov 10 22:30:07 2015
@@ -819,6 +819,7 @@ bool IslNodeBuilder::materializeValue(is
// If the Id is already mapped, skip it.
if (!IDToValue.count(Id)) {
auto *ParamSCEV = (const SCEV *)isl_id_get_user(Id);
+ Value *V = nullptr;
// Parameters could refere to invariant loads that need to be
// preloaded before we can generate code for the parameter. Thus,
@@ -827,13 +828,22 @@ bool IslNodeBuilder::materializeValue(is
SetVector<Value *> Values;
findValues(ParamSCEV, Values);
for (auto *Val : Values)
- if (const auto *IAClass = S.lookupInvariantEquivClass(Val))
+ if (const auto *IAClass = S.lookupInvariantEquivClass(Val)) {
+
+ // Check if this invariant access class is empty, hence if we never
+ // actually added a loads instruction to it. In that case it has no
+ // (meaningful) users and we should not try to code generate it.
+ if (std::get<1>(*IAClass).empty())
+ V = UndefValue::get(ParamSCEV->getType());
+
if (!preloadInvariantEquivClass(*IAClass)) {
isl_id_free(Id);
return false;
}
+ }
- auto *V = generateSCEV(ParamSCEV);
+ if (!V)
+ V = generateSCEV(ParamSCEV);
IDToValue[Id] = V;
}
@@ -947,7 +957,9 @@ bool IslNodeBuilder::preloadInvariantEqu
// elements of the class to the one preloaded load as they are referenced
// during the code generation and therefor need to be mapped.
const MemoryAccessList &MAs = std::get<1>(IAClass);
- assert(!MAs.empty());
+ if (MAs.empty())
+ return true;
+
MemoryAccess *MA = MAs.front();
assert(MA->isExplicit() && MA->isRead());
Added: polly/trunk/test/Isl/CodeGen/invariant_load_not_executed_but_in_parameters.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/CodeGen/invariant_load_not_executed_but_in_parameters.ll?rev=252701&view=auto
==============================================================================
--- polly/trunk/test/Isl/CodeGen/invariant_load_not_executed_but_in_parameters.ll (added)
+++ polly/trunk/test/Isl/CodeGen/invariant_load_not_executed_but_in_parameters.ll Tue Nov 10 22:30:07 2015
@@ -0,0 +1,115 @@
+; RUN: opt %loadPolly -polly-codegen -analyze < %s
+;
+; Check that this does not crash as the invariant load is not executed (thus
+; not preloaded) but still referenced by one of the parameters.
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+%struct.Exp.204.248.358 = type { %struct.Exp_.200.244.354*, i32, i32, i32, %struct.Exp.204.248.358*, %struct.Exp.204.248.358*, %union.anon.2.201.245.355, %union.anon.3.202.246.356, %union.anon.4.203.247.357 }
+%struct.Exp_.200.244.354 = type { i32, i32, i32, i32, %struct.Id.199.243.353* }
+%struct.Id.199.243.353 = type { i8*, i32, i32, i32, %union.anon.1.198.242.352 }
+%union.anon.1.198.242.352 = type { [2 x i64] }
+%union.anon.2.201.245.355 = type { %struct.Exp.204.248.358* }
+%union.anon.3.202.246.356 = type { i32 }
+%union.anon.4.203.247.357 = type { %struct.Exp.204.248.358** }
+%struct.Classfile.218.262.372 = type { %struct._IO_FILE.206.250.360*, %struct._IO_FILE.206.250.360*, i32, i32, i32, %struct.ClassVersion.207.251.361, %struct.ConstPool.210.254.364, %struct.AccessFlags.211.255.365, i16, i8*, i8*, i16, i8*, i16, i16*, i16, %struct.field_info.212.256.366**, i16, %struct.method_info.217.261.371**, i8*, i16, i8**, i8* }
+%struct._IO_FILE.206.250.360 = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker.205.249.359*, %struct._IO_FILE.206.250.360*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] }
+%struct._IO_marker.205.249.359 = type { %struct._IO_marker.205.249.359*, %struct._IO_FILE.206.250.360*, i32 }
+%struct.ClassVersion.207.251.361 = type { i16, i16 }
+%struct.ConstPool.210.254.364 = type { i16, %struct.cp_info.209.253.363* }
+%struct.cp_info.209.253.363 = type { i8, %union.anon.208.252.362 }
+%union.anon.208.252.362 = type { i64 }
+%struct.AccessFlags.211.255.365 = type { i16 }
+%struct.field_info.212.256.366 = type <{ %struct.AccessFlags.211.255.365, [6 x i8], i8*, i8*, i32, i16, [2 x i8] }>
+%struct.method_info.217.261.371 = type { %struct.AccessFlags.211.255.365, i8*, i8*, i8, i8, i32, i8*, i16, %struct.Block.214.258.368*, i16, %struct.LineNumberTableEntry.215.259.369*, i16, %struct.LocalVariableTableEntry.216.260.370*, i8**, i8**, i32*, i32*, i8*, i32, i32, i32* }
+%struct.Block.214.258.368 = type { i32, i16, i16, %union.anon.0.213.257.367, i16, %struct.Exp.204.248.358* }
+%union.anon.0.213.257.367 = type { i32 }
+%struct.LineNumberTableEntry.215.259.369 = type { i16, i16 }
+%struct.LocalVariableTableEntry.216.260.370 = type { i16, i16, i16, i16, i16 }
+%struct.Case.219.263.373 = type { i64, i64 }
+
+ at currpc = external global i32, align 4
+ at bufflength = external global i32, align 4
+ at inbuff = external global i8*, align 8
+ at stkptr = external global %struct.Exp.204.248.358**, align 8
+ at donestkptr = external global %struct.Exp.204.248.358**, align 8
+
+; Function Attrs: uwtable
+define i32 @_Z13dotableswitchP9Classfile(%struct.Classfile.218.262.372* %c) #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+ br label %entry.split
+
+entry.split: ; preds = %entry
+ %sub = add i32 0, -1
+ %tobool.5 = icmp eq i32 0, 0
+ br i1 %tobool.5, label %while.end, label %while.body.lr.ph
+
+while.body.lr.ph: ; preds = %entry.split
+ br label %while.body
+
+while.body: ; preds = %while.body, %while.body.lr.ph
+ %0 = load i32, i32* @currpc, align 4
+ %rem = and i32 %0, 3
+ %tobool = icmp eq i32 %rem, 0
+ br i1 %tobool, label %while.cond.while.end_crit_edge, label %while.body
+
+while.cond.while.end_crit_edge: ; preds = %while.body
+ br label %while.end
+
+while.end: ; preds = %while.cond.while.end_crit_edge, %entry.split
+ invoke void @_ZN3ExpC2Ejj7Exptype4Type2OpPS_jjP4Case(%struct.Exp.204.248.358* nonnull undef, i32 %sub, i32 undef, i32 9, i32 0, i32 39, %struct.Exp.204.248.358* undef, i32 undef, i32 undef, %struct.Case.219.263.373* nonnull undef)
+ to label %invoke.cont unwind label %lpad
+
+invoke.cont: ; preds = %while.end
+ br i1 undef, label %for.end, label %for.body.lr.ph
+
+for.body.lr.ph: ; preds = %invoke.cont
+ br label %for.body
+
+for.body: ; preds = %for.body, %for.body.lr.ph
+ br i1 undef, label %for.cond.for.end_crit_edge, label %for.body
+
+lpad: ; preds = %while.end
+ %1 = landingpad { i8*, i32 }
+ cleanup
+ resume { i8*, i32 } undef
+
+for.cond.for.end_crit_edge: ; preds = %for.body
+ br label %for.end
+
+for.end: ; preds = %for.cond.for.end_crit_edge, %invoke.cont
+ ret i32 0
+}
+
+; Function Attrs: nounwind readnone
+declare { i64, i1 } @llvm.umul.with.overflow.i64(i64, i64) #1
+
+; Function Attrs: nobuiltin
+declare noalias i8* @_Znam(i64) #2
+
+; Function Attrs: nobuiltin
+declare noalias i8* @_Znwm(i64) #2
+
+; Function Attrs: uwtable
+declare void @_ZN3ExpC2Ejj7Exptype4Type2OpPS_jjP4Case(%struct.Exp.204.248.358*, i32, i32, i32, i32, i32, %struct.Exp.204.248.358*, i32, i32, %struct.Case.219.263.373*) unnamed_addr #0 align 2
+
+declare i32 @__gxx_personality_v0(...)
+
+; Function Attrs: nobuiltin nounwind
+declare void @_ZdlPv(i8*) #3
+
+; Function Attrs: uwtable
+declare i32 @_Z10doluswitchP9Classfile(%struct.Classfile.218.262.372*) #0
+
+; Function Attrs: nounwind uwtable
+declare void @_ZN4Exp_C2E7Exptype4Type2Op(%struct.Exp_.200.244.354*, i32, i32, i32) unnamed_addr #4 align 2
+
+attributes #0 = { uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+attributes #2 = { nobuiltin "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #3 = { nobuiltin nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #4 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 3.8.0 (http://llvm.org/git/clang.git 02f36bd65b1133fbfa8bf1470105c02d9bda35e7) (http://llvm.org/git/llvm.git 01eac645064dde04ea609a8a742b1b996ef79179)"}
Modified: polly/trunk/test/ScopInfo/invariant_loads_complicated_dependences.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/invariant_loads_complicated_dependences.ll?rev=252701&r1=252700&r2=252701&view=diff
==============================================================================
--- polly/trunk/test/ScopInfo/invariant_loads_complicated_dependences.ll (original)
+++ polly/trunk/test/ScopInfo/invariant_loads_complicated_dependences.ll Tue Nov 10 22:30:07 2015
@@ -5,14 +5,14 @@
; CHECK-NEXT: [LB, UB] -> { Stmt_for_body[i0] -> MemRef_LBptr[0] };
; CHECK-NEXT: Execution Context: [LB, UB] -> { : }
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT: [LB, UB] -> { Stmt_do_cond[i0, i1] -> MemRef_UBptr[0] };
+; CHECK-NEXT: Execution Context: [LB, UB] -> { : }
+; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: [LB, UB] -> { Stmt_if_then[i0, i1] -> MemRef_V[0] };
; CHECK-NEXT: Execution Context: [LB, UB] -> { : (UB >= 1 + LB and UB >= 6) or LB >= 6 }
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: [LB, UB] -> { Stmt_if_else[i0, i1] -> MemRef_U[0] };
; CHECK-NEXT: Execution Context: [LB, UB] -> { : LB <= 5 }
-; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
-; CHECK-NEXT: [LB, UB] -> { Stmt_do_cond[i0, i1] -> MemRef_UBptr[0] };
-; CHECK-NEXT: Execution Context: [LB, UB] -> { : }
; CHECK-NEXT: }
;
; void f(int *restrict A, int *restrict V, int *restrict U, int *restrict UB,
More information about the llvm-commits
mailing list