[LLVMdev] `llvm.$op.with.overflow`, InstCombine and ScalarEvolution
David Majnemer
david.majnemer at gmail.com
Thu Mar 26 15:18:05 PDT 2015
On Thu, Mar 26, 2015 at 2:54 PM, Sanjoy Das <sanjoy at playingwithpointers.com>
wrote:
> I've run into cases where, because not all of LLVM's optimizations
> understand the semantics of the `llvm.$op.with.overflow` intrinsics,
> canonicalizing compares to `llvm.$op.with.overflow` ends up preventing
> optimization.
>
> For instance, running the following snippet through `opt -indvars`
> optimizes `%to.optimize` to `true`, but running it through
> `opt -instcombine -indvars` does not.
>
> ```
> declare void @side_effect(i1)
>
> define void @foo(i8 %x, i8 %y) {
> entry:
> %sum = add i8 %x, %y
> %e = icmp ugt i8 %x, %sum
> br i1 %e, label %exit, label %loop
>
> loop:
> %idx = phi i8 [ %x, %entry ], [ %idx.inc, %loop ]
> %idx.inc = add i8 %idx, 1
> %to.optimize = icmp ule i8 %idx, %sum
> call void @side_effect(i1 %to.optimize)
> %c = icmp ule i8 %idx.inc, %sum
> br i1 %c, label %loop, label %exit
>
> exit:
> ret void
> }
> ```
>
> This happens because `-instcombine` does the following tranform:
>
> ```
> entry:
> %uadd = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %x, i8 %y)
> %0 = extractvalue { i8, i1 } %uadd, 0
> %e = extractvalue { i8, i1 } %uadd, 1
> br i1 %e, label %exit, label %loop.preheader
> ```
>
> and ScalarEvolution can no longer see through the `extractvalue` of
> the call to `llvm.uadd.with.overflow.i8`.
>
> The right way to fix this depends on the intended purpose of the
> `llvm.$op.with.overflow` intrinsics. Three solutions I can think of:
>
> * if they're a convenience useful only for better codegen, can the
> transform that instcombine is doing currently (transforming
> compares to `extractvalue` of a `.with.overflow` intrinsic) be
> moved to CodeGenPrep?
>
Unfortunately, they are not a mere convenience. I've personally spent
effort trying to optimize away overflow checks in InstCombine, it does this
in its InstCombineCalls visitor.
>
> * if they're something more fundamental, then maybe they should to be
> promoted to an instruction? They've been around since at least
> llvm 2.6 as far as I can tell. Personally, I seriously doubt this
> is a good idea, given that the semantics of these intrinsics can be
> completely described by a DAG composed of existing instructions.
>
I think promoting them would be quite disruptive. Most passes don't care
about these operations and can't do much with them.
>
> * add rules to ScalarEvolution to have it understand these intrinsics
> (or maybe even expand them before `-indvars` -- I think
> `-liv-reduce` tries to do this in some cases), but I'd vote for
> keeping this complexity out of ScalarEvolution unless there are
> good reasons why the `.with.overflow` calls need to be introduced
> before codegenprep.
>
If we don't care about trying to optimize out overflow checks in
InstCombine, I'd go with moving the complexity to CGP. However, I think
InstCombine is doing the right thing here by forming these. I think there
are two choices that keep our optimizations:
- Teach SCEV, one way or another, about *_with_overflow.
- Don't form overflow intrinsics in InstCombine but instead teach
ProcessUGT_ADDCST_ADD, et al. to use WillNotOverflowUnsignedAdd, et al. to
optimize away the compare.
The second approach sounds much easier but I don't know what we lose by
doing it.
>
> What do you think?
>
> -- Sanjoy
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150326/2b2138ed/attachment.html>
More information about the llvm-dev
mailing list