This is an archive of the discontinued LLVM Phabricator instance.

[SimplifyCFG] try branch-to-branch simplification sooner
Needs ReviewPublic

Authored by spatel on Mar 13 2020, 1:04 PM.

Details

Summary

The order that we try various folds within SimplifyCFG can affect the result as shown by this patch that only moves a block of code.

But I'm not sure if the existing code or the diff in the motivating case from PR32078 is valid. Is it safe to convert this chain of branches into bitwise logic? What if the branch conditions are poison?

If this is ok, then we should be able to turn the entire sequence into logic ops rather than select at the end. I haven't looked to see why that still happens. If this is not ok, then we already have a bug in SimplifyCFG.

Diff Detail

Event Timeline

spatel created this revision.Mar 13 2020, 1:04 PM

Branching on poison is UB, while performing bitmath on poison will only result in poison, which is less bad i think.
So i think *those* folds are okay.

It isn't obvious to me why the order matters? The commit message and comments in the code don't really explain.

Is it safe to convert this chain of branches into bitwise logic?

I think the way Alive2 currently defines poison, it's safe to transform a branch to a bool select, but transforming a bool select to bitwise logic requires freeze.

I think the way Alive2 currently defines poison, it's safe to transform a branch to a bool select, but transforming a bool select to bitwise logic requires freeze.

Err, I meant, it's safe to transform a chain of branches to a chain of bool selects.

Branching on poison is UB, while performing bitmath on poison will only result in poison, which is less bad i think.

The question is what happens if you have a chain of conditional branches... i.e. you're potentially transforming code that uses value in dead code to code that uses that value in live code.

As you concerned, in theory the transformation may introduce more undefinedness in target: http://volta.cs.utah.edu:8080/z/wygrrr
(Right now there was a slight issue with vector function input in Alive2 so I unpacked it into individual scalar inputs)
I think converting it into select rather than and/or is a safer approach. It clearly preserves which condition should be considered first.

Right now, making SimplifyCFG add freeze would block many optimization because analysis for redundant freeze removal isn't mature enough.
However, we can assess its effect to backend by updating transformations that are similar with this and happening at very late pipeline.
What I've found was llvm/test/Transforms/CodeGenPrepare/X86/select.ll . it converts select into br in certain cases (fdiv_true_sink).
What do you think about making the branch condition freezed? It will be a good start for having actual freeze in IR.

uenoku added a subscriber: uenoku.Mar 14 2020, 1:32 AM
spatel added a subscriber: regehr.Mar 14 2020, 7:50 AM

As you concerned, in theory the transformation may introduce more undefinedness in target: http://volta.cs.utah.edu:8080/z/wygrrr
(Right now there was a slight issue with vector function input in Alive2 so I unpacked it into individual scalar inputs)
I think converting it into select rather than and/or is a safer approach. It clearly preserves which condition should be considered first.

Thanks - and very grateful for the online alive2 explorer! cc @regehr
That's going to be fun. :)

So we have a chain of bugs here...

  1. SimplifyCFG can directly turn branches into logic - creates more poison.
  2. SimplifyCFG can turn branches into select - this is ok by itself, but...
  3. InstCombine turns those selects into logic as seen in https://reviews.llvm.org/D72396#1810460

I need to review 'freeze'...and see what (if anything) can be done.

It isn't obvious to me why the order matters? The commit message and comments in the code don't really explain.

Sorry, missed this question initially. Order matters because SimplifyCFG doesn't run to fix-point. It's a curated set of transforms gated by requestResimplify() and a 'Changed' flag. I don't think that can be changed without major surgery. For example, if we speculatively hoist instructions using the cost model, then we don't want to re-run that transform without marking the already hoisted instructions as changed by SimplifyCFG itself.

But then again, we run this pass multiple times in the normal opt pipeline, so we must be layering cost-based speculations on top of one another...unless I'm missing something that prevents that.

so this works but seems heavy-handed:
http://volta.cs.utah.edu:8080/z/w-L7Jw

Freezing arguments will work if whole expressions are purely relying on function arguments. This can be done by a cascade of transformations like freeze(icmp p, q) -> icmp (freeze p), (freeze q) and freeze (bop x y) -> bop (freeze x) (freeze y) (where bop is guaranteed to return non-undef/poison if both operands are non-undef/poison).
If a value x is never undef or poison, freeze x can be optimized to x. I have a few patches which is under reviewed for this direction: D76010 and D75808.

But then again, we run this pass multiple times in the normal opt pipeline, so we must be layering cost-based speculations on top of one another...unless I'm missing something that prevents that.

The SimplifyCFG pass (lib/Transforms/Scalar/SimplifyCFGPass.cpp) iterates until it can't make any more changes; we shouldn't be depending on any data recorded off to the side. I'm pretty sure the issue is really some sort of transform ordering issue; I'm mostly interested in knowing which specific transforms are involved.

aqjune added a comment.EditedMar 17 2020, 2:25 AM

I guess in C it is UB to pass the value of uninitialized variable to a function argument:

void f(int);

int x;
f(x); // UB

Then can we say that function arguments are never undef/poison?
It may not be true in IR, then we can introduce the attribute that is discussed at nonnull thread previously, which was nonpoison (or I think frozen is good as well; nonpoison seems to imply poison only. But I don't stick to my choice)

lebedev.ri resigned from this revision.Jan 12 2023, 5:18 PM

This review seems to be stuck/dead, consider abandoning if no longer relevant.

Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptJan 12 2023, 5:18 PM
Herald added a subscriber: StephenFan. · View Herald Transcript