[llvm] r331935 - [InstCombine] Widen guards with conditions between
Evgenii Stepanov via llvm-commits
llvm-commits at lists.llvm.org
Wed May 9 16:57:22 PDT 2018
Breaks WERROR,
http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux/builds/11432/steps/bootstrap%20clang/logs/stdio
On Wed, May 9, 2018 at 3:56 PM, Philip Reames via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> Author: reames
> Date: Wed May 9 15:56:32 2018
> New Revision: 331935
>
> URL: http://llvm.org/viewvc/llvm-project?rev=331935&view=rev
> Log:
> [InstCombine] Widen guards with conditions between
>
> The previous handling for guard widening in InstCombine was extremely
> restrictive. In particular, it didn't handle the common case where we had
> two guards separated by a single icmp. Handle this by scanning through a
> small fixed window of instructions to find the next guard if needed.
>
> Differential Revision: https://reviews.llvm.org/D46203
>
>
> Modified:
> llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
> llvm/trunk/test/Transforms/InstCombine/call-guard.ll
>
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> Transforms/InstCombine/InstCombineCalls.cpp?rev=
> 331935&r1=331934&r2=331935&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Wed May 9
> 15:56:32 2018
> @@ -79,6 +79,13 @@ static cl::opt<unsigned> UnfoldElementAt
> cl::desc("Maximum number of elements in atomic memcpy the optimizer
> is "
> "allowed to unfold"));
>
> +static cl::opt<unsigned> GuardWideningWindow(
> + "instcombine-guard-widening-window",
> + cl::init(3),
> + cl::desc("How wide an instruction window to bypass looking for "
> + "another guard"));
> +
> +
> /// Return the specified type promoted as it would be to pass though a
> va_arg
> /// area.
> static Type *getPromotedType(Type *Ty) {
> @@ -3624,8 +3631,16 @@ Instruction *InstCombiner::visitCallInst
> }
>
> case Intrinsic::experimental_guard: {
> - // Is this guard followed by another guard?
> + // Is this guard followed by another guard? We scan forward over a
> small
> + // fixed window of instructions to handle common cases with conditions
> + // computed between guards.
> Instruction *NextInst = II->getNextNode();
> + for (int i = 0; i < GuardWideningWindow; i++) {
> + // Note: Using context-free form to avoid compile time blow up
> + if (!isSafeToSpeculativelyExecute(NextInst))
> + break;
> + NextInst = NextInst->getNextNode();
> + }
> Value *NextCond = nullptr;
> if (match(NextInst,
> m_Intrinsic<Intrinsic::experimental_guard>(m_Value(NextCond))))
> {
> @@ -3636,6 +3651,12 @@ Instruction *InstCombiner::visitCallInst
> return eraseInstFromFunction(*NextInst);
>
> // Otherwise canonicalize guard(a); guard(b) -> guard(a & b).
> + Instruction* MoveI = II->getNextNode();
> + while (MoveI != NextInst) {
> + auto *Temp = MoveI;
> + MoveI = MoveI->getNextNode();
> + Temp->moveBefore(II);
> + }
> II->setArgOperand(0, Builder.CreateAnd(CurrCond, NextCond));
> return eraseInstFromFunction(*NextInst);
> }
>
> Modified: llvm/trunk/test/Transforms/InstCombine/call-guard.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> Transforms/InstCombine/call-guard.ll?rev=331935&r1=331934&
> r2=331935&view=diff
> ============================================================
> ==================
> --- llvm/trunk/test/Transforms/InstCombine/call-guard.ll (original)
> +++ llvm/trunk/test/Transforms/InstCombine/call-guard.ll Wed May 9
> 15:56:32 2018
> @@ -30,3 +30,81 @@ define void @test_guard_adjacent_diff_co
> call void(i1, ...) @llvm.experimental.guard( i1 %C, i32 789 )[
> "deopt"() ]
> ret void
> }
> +
> +; This version tests for the common form where the conditions are
> +; between the guards
> +define void @test_guard_adjacent_diff_cond2(i32 %V1, i32 %V2) {
> +; CHECK-LABEL: @test_guard_adjacent_diff_cond2(
> +; CHECK-NEXT: %1 = and i32 %V1, %V2
> +; CHECK-NEXT: %2 = icmp slt i32 %1, 0
> +; CHECK-NEXT: %and = and i32 %V1, 255
> +; CHECK-NEXT: %C = icmp ult i32 %and, 129
> +; CHECK-NEXT: %3 = and i1 %2, %C
> +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %3, i32
> 123) [ "deopt"() ]
> +; CHECK-NEXT: ret void
> + %A = icmp slt i32 %V1, 0
> + call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[
> "deopt"() ]
> + %B = icmp slt i32 %V2, 0
> + call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[
> "deopt"() ]
> + %and = and i32 %V1, 255
> + %C = icmp sle i32 %and, 128
> + call void(i1, ...) @llvm.experimental.guard( i1 %C, i32 789 )[
> "deopt"() ]
> + ret void
> +}
> +
> +; Might not be legal to hoist the load above the first guard since the
> +; guard might control dereferenceability
> +define void @negative_load(i32 %V1, i32* %P) {
> +; CHECK-LABEL: @negative_load
> +; CHECK: @llvm.experimental.guard
> +; CHECK: @llvm.experimental.guard
> + %A = icmp slt i32 %V1, 0
> + call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[
> "deopt"() ]
> + %V2 = load i32, i32* %P
> + %B = icmp slt i32 %V2, 0
> + call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[
> "deopt"() ]
> + ret void
> +}
> +
> +define void @deref_load(i32 %V1, i32* dereferenceable(4) %P) {
> +; CHECK-LABEL: @deref_load
> +; CHECK-NEXT: %V2 = load i32, i32* %P, align 4
> +; CHECK-NEXT: %1 = and i32 %V2, %V1
> +; CHECK-NEXT: %2 = icmp slt i32 %1, 0
> +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %2, i32
> 123) [ "deopt"() ]
> + %A = icmp slt i32 %V1, 0
> + call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[
> "deopt"() ]
> + %V2 = load i32, i32* %P
> + %B = icmp slt i32 %V2, 0
> + call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[
> "deopt"() ]
> + ret void
> +}
> +
> +; The divide might fault above the guard
> +define void @negative_div(i32 %V1, i32 %D) {
> +; CHECK-LABEL: @negative_div
> +; CHECK: @llvm.experimental.guard
> +; CHECK: @llvm.experimental.guard
> + %A = icmp slt i32 %V1, 0
> + call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[
> "deopt"() ]
> + %V2 = udiv i32 %V1, %D
> + %B = icmp slt i32 %V2, 0
> + call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[
> "deopt"() ]
> + ret void
> +}
> +
> +; Highlight the limit of the window in a case which would otherwise be
> mergable
> +define void @negative_window(i32 %V1, i32 %a, i32 %b, i32 %c, i32 %d) {
> +; CHECK-LABEL: @negative_window
> +; CHECK: @llvm.experimental.guard
> +; CHECK: @llvm.experimental.guard
> + %A = icmp slt i32 %V1, 0
> + call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[
> "deopt"() ]
> + %V2 = add i32 %a, %b
> + %V3 = add i32 %V2, %c
> + %V4 = add i32 %V3, %d
> + %B = icmp slt i32 %V4, 0
> + call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[
> "deopt"() ]
> + ret void
> +}
> +
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180509/99b39a39/attachment.html>
More information about the llvm-commits
mailing list