This is an archive of the discontinued LLVM Phabricator instance.

[Polly] Workaround for SDiv/SRem referenced from SCEVExpander
AbandonedPublic

Authored by Meinersbur on Aug 15 2015, 3:47 PM.

Details

Reviewers
grosser
jdoerfert
Summary

polly::SCEVValidator extends the notion of ScalarEvolution values by allowing SDiv and SRem instructions in them. These are handled by polly::SCEVAffinator, but not by llvm::SCEVExpander. SCEVExpander instead references the original values that might be defined only afterwards.

This patch is a workaround by copying those referenceable SDivs/SRems to the polly.start block where the SCEV is expanded and can use the copied instructions. This pessimistically copies values even if not used by any SCoP parameter to avoid making SCEVExpander generate illegal code and recursivity.

Ideally, one introduces SCEVSDiv and SCEVSRem classes to get rid of this and other such workarounds in Polly.

Diff Detail

Event Timeline

Meinersbur updated this revision to Diff 32223.Aug 15 2015, 3:47 PM
Meinersbur retitled this revision from to [Polly] Workaround for SDiv/SRem referenced from SCEVExpander.
Meinersbur updated this object.
Meinersbur added reviewers: grosser, jdoerfert.
Meinersbur added a project: Restricted Project.
Meinersbur added subscribers: pollydev, llvm-commits.
jdoerfert edited edge metadata.Aug 16 2015, 5:55 AM

Some initial questions to get an idea of this patch.

lib/CodeGen/IslNodeBuilder.cpp
58

Why do we need this?

724

What type does Inst have if not Instruction &?

731

How can we look at an instruction twice (if we always copy the instruction as noted below)?

737

Can we just copy it without all the checks if we can move it?

Note that I I hope this is a temporary workaround and we can get LLVM to implement SCEVSRemExpr and SCEVSDivExpr.

lib/CodeGen/IslNodeBuilder.cpp
58

LLVM defines SDivOperator, but not SRemOperator

724

The worklist push below is of type llvm::User*, but it might indeed be unnecessary here (and below since the cast has already been done)

731

If used in operands of two instructions?!? I obviously don't understand your question.

737

The move in the comment is outdated. I tried to move it in an previous implementation and found that moving doesn't come without problems.

There is still nothing to do if SCEVValidator rejected it.

Some comments and a proposal.

lib/CodeGen/IslNodeBuilder.cpp
58

Why don't you cast to SRem and SDiv instructions instead of operators?

724

I do not see anything of type User between 720 and 727 but as long as we agree that the cast is not necessary I don't care.

737

Wait, moving doesn't come with problems or does? If the latter, which problems?

My proposal is not to move instructions at all but copy the SDiv and SRem instructions including the operands trees to the new location. Can you comment on that?

grosser edited edge metadata.Aug 16 2015, 1:04 PM

Hi Michael,

I just committed another test case (test/Isl/CodeGen/inner_scev_2.ll) that has a similar problem, but unfortunately still fails with this patch applied.

In general, I think your approach of moving the relevant instructions out of the scop is a good one, but just seems to be a little incomplete.

One very similar approach could be to go

codgenSCEV(SCEV S)

  1. Scan S for SCEV Unknowns X that refer to instructions in SCoP
  2. for each operand Op of X: a) get SCEV of Op b) codegenSCEV(SCEV of Op) c) create new instruction that uses the newly code generated operands as input
  3. Replace all X with new instructions
  4. Only now SCEVExpand the SCEV (after we know it has no problematic SCEUnknowns any more)

Maybe this gives you some inspiration of how to go ahead.

Best,
Tobias

codgenSCEV(SCEV S)

  1. Scan S for SCEV Unknowns X that refer to instructions in SCoP
  2. for each operand Op of X: a) get SCEV of Op b) codegenSCEV(SCEV of Op) c) create new instruction that uses the newly code generated operands as input
  3. Replace all X with new instructions
  4. Only now SCEVExpand the SCEV (after we know it has no problematic SCEUnknowns any more)

Maybe this gives you some inspiration of how to go ahead.

I was actually thinking something similar and apperently it works for the two test cases at hand and regardless where (in which kind of SCEV) the SDiv/SRem are hiding. See: http://reviews.llvm.org/D12066

lib/CodeGen/IslNodeBuilder.cpp
58

I got it,.. you would need to use the opcode instead.

Very cool, I think this makes sense.

Michael, as you had a close look into this already, I would be interested what you think
about this approach?

Best,
Tobias

jdoerfert added a comment.

In http://reviews.llvm.org/D12053#225339, @grosser wrote:

codgenSCEV(SCEV S)

  1. Scan S for SCEV Unknowns X that refer to instructions in SCoP
  2. for each operand Op of X: a) get SCEV of Op b) codegenSCEV(SCEV of Op) c) create new instruction that uses the newly code generated operands as input
  3. Replace all X with new instructions
  4. Only now SCEVExpand the SCEV (after we know it has no problematic SCEUnknowns any more)

    Maybe this gives you some inspiration of how to go ahead.

I was actually thinking something similar and apperently it works for the two test cases at hand and regardless where (in which kind of SCEV) the SDiv/SRem are hiding. See: http://reviews.llvm.org/D12066

Comment at: lib/CodeGen/IslNodeBuilder.cpp:58
@@ -53,1 +57,3 @@
+}
+

__isl_give isl_ast_expr *

jdoerfert wrote:

Meinersbur wrote:

jdoerfert wrote:

Why do we need this?

LLVM defines SDivOperator, but not SRemOperator

Why don't you cast to SRem and SDiv instructions instead of operators?

I got it,.. you would need to use the opcode instead.

http://reviews.llvm.org/D12053

Meinersbur abandoned this revision.Aug 17 2015, 9:03 AM

Abandoned in favor of D12066 or some more general solution in ScalarEvolution itself.