diff options
Diffstat (limited to 'llvm/test/Transforms')
9 files changed, 967 insertions, 179 deletions
diff --git a/llvm/test/Transforms/Coroutines/coro-async.ll b/llvm/test/Transforms/Coroutines/coro-async.ll index e5d2e6c2c42c..331d6a60bed6 100644 --- a/llvm/test/Transforms/Coroutines/coro-async.ll +++ b/llvm/test/Transforms/Coroutines/coro-async.ll @@ -496,6 +496,35 @@ entry: ; CHECK: call void @use(ptr null) ; CHECK: ret +@simpleFuncTu = global <{i32, i32}> <{ + i32 trunc (i64 sub (i64 ptrtoint (ptr @simpleFunc to i64), + i64 ptrtoint (ptr @simpleFuncTu to i64)) to i32), i32 16 }> + +define swifttailcc void @simpleFunc(ptr swiftasync %0) presplitcoroutine { +entry: + %1 = alloca ptr, align 8 + %2 = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr @simpleFuncTu) + %3 = call ptr @llvm.coro.begin(token %2, ptr null) + store ptr %0, ptr %1, align 8 + %4 = load ptr, ptr %1, align 8 + %5 = getelementptr inbounds <{ ptr, ptr }>, ptr %4, i32 0, i32 1 + %6 = load ptr, ptr %5, align 8 + %7 = load ptr, ptr %1, align 8 + %8 = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %3, i1 false, ptr @simpleFunc.0, ptr %6, ptr %7) + unreachable +} + +; CHECK-LABEL: define swifttailcc void @simpleFunc(ptr swiftasync %0) { +; CHECK-NOT: define +; CHECK: [[RESUME:%.*]] = load ptr +; CHECK: musttail call swifttailcc void [[RESUME]] + +define internal swifttailcc void @simpleFunc.0(ptr %0, ptr %1) alwaysinline { +entry: + musttail call swifttailcc void %0(ptr swiftasync %1) + ret void +} + declare { ptr, ptr, ptr, ptr } @llvm.coro.suspend.async.sl_p0i8p0i8p0i8p0i8s(i32, ptr, ptr, ...) declare ptr @llvm.coro.prepare.async(ptr) declare token @llvm.coro.id.async(i32, i32, i32, ptr) diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll index 1a41c1f3e104..cb428097f2ae 100644 --- a/llvm/test/Transforms/InstCombine/icmp-add.ll +++ b/llvm/test/Transforms/InstCombine/icmp-add.ll @@ -3300,3 +3300,149 @@ entry: %cmp = icmp ult i32 %add, 253 ret i1 %cmp } + +; PR 152851 + +define i1 @val_is_aligend_const_pow2(i32 %num) { +; CHECK-LABEL: @val_is_aligend_const_pow2( +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[NUM:%.*]], 4095 +; CHECK-NEXT: [[_0:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[_0]] +; + %num.biased = add i32 %num, 4095 + %num.masked = and i32 %num.biased, -4096 + %_0 = icmp eq i32 %num.masked, %num + ret i1 %_0 +} + +define i1 @val_is_aligend_const_pow2_add_commute(i32 %num) { +; CHECK-LABEL: @val_is_aligend_const_pow2_add_commute( +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[NUM:%.*]], 4095 +; CHECK-NEXT: [[_0:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[_0]] +; + %num.biased = add i32 4095, %num + %num.masked = and i32 %num.biased, -4096 + %_0 = icmp eq i32 %num.masked, %num + ret i1 %_0 +} + +define i1 @val_is_aligend_const_pow2_and_commute(i32 %num) { +; CHECK-LABEL: @val_is_aligend_const_pow2_and_commute( +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[NUM:%.*]], 4095 +; CHECK-NEXT: [[_0:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[_0]] +; + %num.biased = add i32 %num, 4095 + %num.masked = and i32 -4096, %num.biased + %_0 = icmp eq i32 %num.masked, %num + ret i1 %_0 +} + +define i1 @val_is_aligend_const_pow2_icm_commute(i32 %num) { +; CHECK-LABEL: @val_is_aligend_const_pow2_icm_commute( +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[NUM:%.*]], 4095 +; CHECK-NEXT: [[_0:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[_0]] +; + %num.biased = add i32 %num, 4095 + %num.masked = and i32 %num.biased, -4096 + %_0 = icmp eq i32 %num, %num.masked + ret i1 %_0 +} + +; Should not work for non-power-of-two cases +define i1 @val_is_aligend_const_non_pow2(i32 %num) { +; CHECK-LABEL: @val_is_aligend_const_non_pow2( +; CHECK-NEXT: [[NUM_BIASED:%.*]] = add i32 [[NUM:%.*]], 6 +; CHECK-NEXT: [[NUM_MASKED:%.*]] = and i32 [[NUM_BIASED]], -7 +; CHECK-NEXT: [[_0:%.*]] = icmp eq i32 [[NUM_MASKED]], [[NUM]] +; CHECK-NEXT: ret i1 [[_0]] +; + %num.biased = add i32 %num, 6 + %num.masked = and i32 %num.biased, -7 + %_0 = icmp eq i32 %num.masked, %num + ret i1 %_0 +} + +define i1 @val_is_aligend_const_pow2_multiuse(i32 %num) { +; CHECK-LABEL: @val_is_aligend_const_pow2_multiuse( +; CHECK-NEXT: [[NUM_BIASED:%.*]] = add i32 [[NUM:%.*]], 4095 +; CHECK-NEXT: [[NUM_MASKED:%.*]] = and i32 [[NUM_BIASED]], -4096 +; CHECK-NEXT: call void @use(i32 [[NUM_MASKED]]) +; CHECK-NEXT: [[_0:%.*]] = icmp eq i32 [[NUM_MASKED]], [[NUM]] +; CHECK-NEXT: ret i1 [[_0]] +; + %num.biased = add i32 %num, 4095 + %num.masked = and i32 %num.biased, -4096 + call void @use(i32 %num.masked) + %_0 = icmp eq i32 %num.masked, %num + ret i1 %_0 +} + +; Applies since number of instructions do not change +define i1 @val_is_aligend_const_pow2_multiuse1(i32 %num) { +; CHECK-LABEL: @val_is_aligend_const_pow2_multiuse1( +; CHECK-NEXT: [[NUM_BIASED:%.*]] = add i32 [[NUM:%.*]], 4095 +; CHECK-NEXT: call void @use(i32 [[NUM_BIASED]]) +; CHECK-NEXT: [[NUM_MASKED:%.*]] = and i32 [[NUM_BIASED]], -4096 +; CHECK-NEXT: [[_0:%.*]] = icmp eq i32 [[NUM_MASKED]], [[NUM]] +; CHECK-NEXT: ret i1 [[_0]] +; + %num.biased = add i32 %num, 4095 + call void @use(i32 %num.biased) + %num.masked = and i32 %num.biased, -4096 + %_0 = icmp eq i32 %num.masked, %num + ret i1 %_0 +} + +define i1 @val_is_aligend_const_pow2_ne(i32 %num) { +; CHECK-LABEL: @val_is_aligend_const_pow2_ne( +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[NUM:%.*]], 4095 +; CHECK-NEXT: [[_0:%.*]] = icmp ne i32 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[_0]] +; + %num.biased = add i32 %num, 4095 + %num.masked = and i32 %num.biased, -4096 + %_0 = icmp ne i32 %num.masked, %num + ret i1 %_0 +} + +define i1 @val_is_aligend_const_mismatch(i32 %num) { +; CHECK-LABEL: @val_is_aligend_const_mismatch( +; CHECK-NEXT: [[NUM_BIASED:%.*]] = add i32 [[NUM:%.*]], 4095 +; CHECK-NEXT: [[NUM_MASKED:%.*]] = and i32 [[NUM_BIASED]], -4095 +; CHECK-NEXT: [[_0:%.*]] = icmp ne i32 [[NUM_MASKED]], [[NUM]] +; CHECK-NEXT: ret i1 [[_0]] +; + %num.biased = add i32 %num, 4095 + %num.masked = and i32 %num.biased, -4095 + %_0 = icmp ne i32 %num.masked, %num + ret i1 %_0 +} + +define i1 @val_is_aligend_const_mismatch1(i32 %num) { +; CHECK-LABEL: @val_is_aligend_const_mismatch1( +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[NUM:%.*]], -4096 +; CHECK-NEXT: [[NUM_MASKED:%.*]] = add i32 [[TMP1]], 4096 +; CHECK-NEXT: [[_0:%.*]] = icmp ne i32 [[NUM_MASKED]], [[NUM]] +; CHECK-NEXT: ret i1 [[_0]] +; + %num.biased = add i32 %num, 4096 + %num.masked = and i32 %num.biased, -4096 + %_0 = icmp ne i32 %num.masked, %num + ret i1 %_0 +} + +define i1 @val_is_aligend_pred_mismatch(i32 %num) { +; CHECK-LABEL: @val_is_aligend_pred_mismatch( +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[NUM:%.*]], -4096 +; CHECK-NEXT: [[NUM_MASKED:%.*]] = add i32 [[TMP1]], 4096 +; CHECK-NEXT: [[_0:%.*]] = icmp sge i32 [[NUM_MASKED]], [[NUM]] +; CHECK-NEXT: ret i1 [[_0]] +; + %num.biased = add i32 %num, 4096 + %num.masked = and i32 %num.biased, -4096 + %_0 = icmp sge i32 %num.masked, %num + ret i1 %_0 +} diff --git a/llvm/test/Transforms/LICM/hoist-binop.ll b/llvm/test/Transforms/LICM/hoist-binop.ll index 1b1347776fb9..724f45979f6b 100644 --- a/llvm/test/Transforms/LICM/hoist-binop.ll +++ b/llvm/test/Transforms/LICM/hoist-binop.ll @@ -22,6 +22,31 @@ loop: br label %loop } +; Don't hoist ADD if the op has more than one use. +define void @add_two_uses(i64 %c1, i64 %c2) { +; CHECK-LABEL: @add_two_uses( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[STEP_ADD:%.*]] = add i64 [[INDEX]], [[C1:%.*]] +; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) +; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[STEP_ADD]], [[C2:%.*]] +; CHECK-NEXT: call void @use(i64 [[INDEX_NEXT]]) +; CHECK-NEXT: br label [[LOOP]] +; +entry: + br label %loop + +loop: + %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] + %step.add = add i64 %index, %c1 + call void @use(i64 %step.add) + %index.next = add i64 %step.add, %c2 + call void @use(i64 %index.next) + br label %loop +} + ; Hoist MUL and remove old op if unused. define void @mul_one_use(i64 %c1, i64 %c2) { ; CHECK-LABEL: @mul_one_use( @@ -51,8 +76,6 @@ define void @add_nuw(i64 %c1, i64 %c2) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw i64 [[INDEX]], [[C1]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; @@ -62,7 +85,6 @@ entry: loop: %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] %step.add = add nuw i64 %index, %c1 - call void @use(i64 %step.add) %index.next = add nuw i64 %step.add, %c2 br label %loop } @@ -76,8 +98,6 @@ define void @add_nuw_comm(i64 %c1, i64 %c2) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw i64 [[C1]], [[INDEX]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; @@ -87,7 +107,6 @@ entry: loop: %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] %step.add = add nuw i64 %c1, %index - call void @use(i64 %step.add) %index.next = add nuw i64 %step.add, %c2 br label %loop } @@ -101,8 +120,6 @@ define void @add_nuw_comm2(i64 %c1, i64 %c2) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw i64 [[INDEX]], [[C1]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; @@ -112,7 +129,6 @@ entry: loop: %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] %step.add = add nuw i64 %index, %c1 - call void @use(i64 %step.add) %index.next = add nuw i64 %c2, %step.add br label %loop } @@ -126,8 +142,6 @@ define void @add_nuw_comm3(i64 %c1, i64 %c2) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw i64 [[C1]], [[INDEX]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; @@ -137,7 +151,6 @@ entry: loop: %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] %step.add = add nuw i64 %c1, %index - call void @use(i64 %step.add) %index.next = add nuw i64 %c2, %step.add br label %loop } @@ -152,8 +165,6 @@ define void @add_nuw_twobinops(i64 %c1, i64 %c2) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw i64 [[C1]], [[INDEX]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; @@ -163,135 +174,134 @@ entry: loop: %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] %step.add = add nuw i64 %c1, %index - call void @use(i64 %step.add) %c2.plus.2 = add nuw i64 %c2, 2 %index.next = add nuw i64 %step.add, %c2.plus.2 br label %loop } ; Hoist MUL and drop NUW even if both ops have it. -define void @mul_nuw(i64 %c1, i64 %c2) { +define void @mul_nuw(<2 x i64> %c1, <2 x i64> %c2) { ; CHECK-LABEL: @mul_nuw( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]] +; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2:%.*]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw i64 [[INDEX]], [[C1]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) -; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]] +; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw <2 x i64> [[INDEX]], [[C1]] +; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]]) +; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; entry: br label %loop loop: - %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] - %step.add = mul nuw i64 %index, %c1 - call void @use(i64 %step.add) - %index.next = mul nuw i64 %step.add, %c2 + %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ] + %step.add = mul nuw <2 x i64> %index, %c1 + call void @use(<2 x i64> %step.add) + %index.next = mul nuw <2 x i64> %step.add, %c2 br label %loop } ; Hoist MUL and drop NUW even if both ops have it. ; Version where operands are commuted. -define void @mul_nuw_comm(i64 %c1, i64 %c2) { +define void @mul_nuw_comm(<2 x i64> %c1, <2 x i64> %c2) { ; CHECK-LABEL: @mul_nuw_comm( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]] +; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2:%.*]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw i64 [[C1]], [[INDEX]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) -; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]] +; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw <2 x i64> [[C1]], [[INDEX]] +; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]]) +; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; entry: br label %loop loop: - %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] - %step.add = mul nuw i64 %c1, %index - call void @use(i64 %step.add) - %index.next = mul nuw i64 %step.add, %c2 + %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ] + %step.add = mul nuw <2 x i64> %c1, %index + call void @use(<2 x i64> %step.add) + %index.next = mul nuw <2 x i64> %step.add, %c2 br label %loop } ; Hoist MUL and drop NUW even if both ops have it. ; Another version where operands are commuted. -define void @mul_nuw_comm2(i64 %c1, i64 %c2) { +define void @mul_nuw_comm2(<2 x i64> %c1, <2 x i64> %c2) { ; CHECK-LABEL: @mul_nuw_comm2( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]] +; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2:%.*]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw i64 [[INDEX]], [[C1]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) -; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]] +; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw <2 x i64> [[INDEX]], [[C1]] +; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]]) +; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; entry: br label %loop loop: - %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] - %step.add = mul nuw i64 %index, %c1 - call void @use(i64 %step.add) - %index.next = mul nuw i64 %c2, %step.add + %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ] + %step.add = mul nuw <2 x i64> %index, %c1 + call void @use(<2 x i64> %step.add) + %index.next = mul nuw <2 x i64> %c2, %step.add br label %loop } ; Hoist MUL and drop NUW even if both ops have it. ; Another version where operands are commuted. -define void @mul_nuw_comm3(i64 %c1, i64 %c2) { +define void @mul_nuw_comm3(<2 x i64> %c1, <2 x i64> %c2) { ; CHECK-LABEL: @mul_nuw_comm3( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]] +; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2:%.*]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw i64 [[C1]], [[INDEX]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) -; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]] +; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw <2 x i64> [[C1]], [[INDEX]] +; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]]) +; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; entry: br label %loop loop: - %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] - %step.add = mul nuw i64 %c1, %index - call void @use(i64 %step.add) - %index.next = mul nuw i64 %c2, %step.add + %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ] + %step.add = mul nuw <2 x i64> %c1, %index + call void @use(<2 x i64> %step.add) + %index.next = mul nuw <2 x i64> %c2, %step.add br label %loop } ; Hoist MUL and drop NUW even if both ops have it. ; A version where the LHS and RHS of the outer BinOp are BinOps. -define void @mul_nuw_twobinops(i64 %c1, i64 %c2) { +define void @mul_nuw_twobinops(<2 x i64> %c1, <2 x i64> %c2) { ; CHECK-LABEL: @mul_nuw_twobinops( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[C2_PLUS_2:%.*]] = add nuw i64 [[C2:%.*]], 2 -; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2_PLUS_2]] +; CHECK-NEXT: [[C2_PLUS_2:%.*]] = add nuw <2 x i64> [[C2:%.*]], splat (i64 2) +; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2_PLUS_2]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw i64 [[C1]], [[INDEX]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) -; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]] +; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw <2 x i64> [[C1]], [[INDEX]] +; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]]) +; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; entry: br label %loop loop: - %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] - %step.add = mul nuw i64 %c1, %index - call void @use(i64 %step.add) - %c2.plus.2 = add nuw i64 %c2, 2 - %index.next = mul nuw i64 %step.add, %c2.plus.2 + %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ] + %step.add = mul nuw <2 x i64> %c1, %index + call void @use(<2 x i64> %step.add) + %c2.plus.2 = add nuw <2 x i64> %c2, <i64 2, i64 2> + %index.next = mul nuw <2 x i64> %step.add, %c2.plus.2 br label %loop } @@ -303,8 +313,6 @@ define void @add_no_nuw(i64 %c1, i64 %c2) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = add i64 [[INDEX]], [[C1]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; @@ -314,7 +322,6 @@ entry: loop: %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] %step.add = add i64 %index, %c1 - call void @use(i64 %step.add) %index.next = add nuw i64 %step.add, %c2 br label %loop } @@ -327,8 +334,6 @@ define void @add_no_nsw(i64 %c1, i64 %c2) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = add i64 [[INDEX]], [[C1]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; @@ -338,7 +343,6 @@ entry: loop: %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] %step.add = add i64 %index, %c1 - call void @use(i64 %step.add) %index.next = add nsw i64 %step.add, %c2 br label %loop } @@ -351,8 +355,6 @@ define void @add_no_nsw_2(i64 %c1, i64 %c2) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = add nsw i64 [[INDEX]], [[C1]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; @@ -362,7 +364,6 @@ entry: loop: %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] %step.add = add nsw i64 %index, %c1 - call void @use(i64 %step.add) %index.next = add nsw i64 %step.add, %c2 br label %loop } @@ -375,8 +376,6 @@ define void @add_nuw_nsw(i64 %c1, i64 %c2) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw nsw i64 [[INDEX]], [[C1]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw nsw i64 [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; @@ -386,7 +385,6 @@ entry: loop: %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] %step.add = add nuw nsw i64 %index, %c1 - call void @use(i64 %step.add) %index.next = add nuw nsw i64 %step.add, %c2 br label %loop } @@ -398,8 +396,6 @@ define void @add_both_nsw_first_nuw(i64 %c1, i64 %c2) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw nsw i64 [[INDEX]], [[C1]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; @@ -409,7 +405,6 @@ entry: loop: %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] %step.add = add nuw nsw i64 %index, %c1 - call void @use(i64 %step.add) %index.next = add nsw i64 %step.add, %c2 br label %loop } @@ -421,8 +416,6 @@ define void @add_both_nsw_second_nuw(i64 %c1, i64 %c2) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = add nsw i64 [[INDEX]], [[C1]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; @@ -432,33 +425,32 @@ entry: loop: %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] %step.add = add nsw i64 %index, %c1 - call void @use(i64 %step.add) %index.next = add nuw nsw i64 %step.add, %c2 br label %loop } ; ; Hoist MUL and drop NSW even if both ops have it. -define void @mul_no_nsw_2(i64 %c1, i64 %c2) { +define void @mul_no_nsw_2(<2 x i64> %c1, <2 x i64> %c2) { ; CHECK-LABEL: @mul_no_nsw_2( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]] +; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2:%.*]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nsw i64 [[INDEX]], [[C1]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) -; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]] +; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nsw <2 x i64> [[INDEX]], [[C1]] +; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]]) +; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]] ; CHECK-NEXT: br label [[LOOP]] ; entry: br label %loop loop: - %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] - %step.add = mul nsw i64 %index, %c1 - call void @use(i64 %step.add) - %index.next = mul nsw i64 %step.add, %c2 + %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ] + %step.add = mul nsw <2 x i64> %index, %c1 + call void @use(<2 x i64> %step.add) + %index.next = mul nsw <2 x i64> %step.add, %c2 br label %loop } @@ -470,7 +462,6 @@ define void @diff_ops(i64 %c1, i64 %c2) { ; CHECK: loop: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ] ; CHECK-NEXT: [[STEP_ADD:%.*]] = add i64 [[INDEX]], [[C1:%.*]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) ; CHECK-NEXT: [[INDEX_NEXT]] = mul i64 [[STEP_ADD]], [[C2:%.*]] ; CHECK-NEXT: br label [[LOOP]] ; @@ -480,7 +471,6 @@ entry: loop: %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] %step.add = add i64 %index, %c1 - call void @use(i64 %step.add) %index.next = mul i64 %step.add, %c2 br label %loop } @@ -493,7 +483,6 @@ define void @noassoc_ops(i64 %c1, i64 %c2) { ; CHECK: loop: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ] ; CHECK-NEXT: [[STEP_ADD:%.*]] = sub i64 [[INDEX]], [[C1:%.*]] -; CHECK-NEXT: call void @use(i64 [[STEP_ADD]]) ; CHECK-NEXT: [[INDEX_NEXT]] = sub i64 [[STEP_ADD]], [[C2:%.*]] ; CHECK-NEXT: br label [[LOOP]] ; @@ -503,7 +492,6 @@ entry: loop: %index = phi i64 [ 0, %entry ], [ %index.next, %loop ] %step.add = sub i64 %index, %c1 - call void @use(i64 %step.add) %index.next = sub i64 %step.add, %c2 br label %loop } diff --git a/llvm/test/Transforms/LICM/sink-foldable.ll b/llvm/test/Transforms/LICM/sink-foldable.ll index d1cf3de5301b..59dea58a6ade 100644 --- a/llvm/test/Transforms/LICM/sink-foldable.ll +++ b/llvm/test/Transforms/LICM/sink-foldable.ll @@ -97,7 +97,7 @@ define ptr @test2(i32 %j, ptr readonly %P, ptr readnone %Q) { ; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds ptr, ptr [[ADD_PTR]], i64 [[IDX2_EXT]] ; CHECK-NEXT: [[L1:%.*]] = load ptr, ptr [[ARRAYIDX2]], align 8 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt ptr [[L1]], [[Q]] -; CHECK-NEXT: [[ADD_REASS]] = add i32 [[I_ADDR]], 2 +; CHECK-NEXT: [[ADD_REASS]] = add nsw i32 [[ADD_I]], 1 ; CHECK-NEXT: br i1 [[CMP2]], label [[LOOPEXIT2:%.*]], label [[FOR_COND]] ; CHECK: loopexit0: ; CHECK-NEXT: [[P0:%.*]] = phi ptr [ null, [[FOR_COND]] ] diff --git a/llvm/test/Transforms/LICM/update-scev-after-hoist.ll b/llvm/test/Transforms/LICM/update-scev-after-hoist.ll index e303d04ce319..8f9045350813 100644 --- a/llvm/test/Transforms/LICM/update-scev-after-hoist.ll +++ b/llvm/test/Transforms/LICM/update-scev-after-hoist.ll @@ -4,7 +4,7 @@ define i16 @main() { ; SCEV-EXPR-LABEL: 'main' ; SCEV-EXPR-NEXT: Classifying expressions for: @main -; SCEV-EXPR-NEXT: %mul = phi i16 [ 1, %entry ], [ %mul.n.3.reass, %loop ] +; SCEV-EXPR-NEXT: %mul = phi i16 [ 1, %entry ], [ %mul.n.3, %loop ] ; SCEV-EXPR-NEXT: --> %mul U: [0,-15) S: [-32768,32753) Exits: 4096 LoopDispositions: { %loop: Variant } ; SCEV-EXPR-NEXT: %div = phi i16 [ 32767, %entry ], [ %div.n.3, %loop ] ; SCEV-EXPR-NEXT: --> %div U: [-2048,-32768) S: [-2048,-32768) Exits: 7 LoopDispositions: { %loop: Variant } @@ -16,7 +16,7 @@ define i16 @main() { ; SCEV-EXPR-NEXT: --> %div.n.1 U: [-8192,8192) S: [-8192,8192) Exits: 1 LoopDispositions: { %loop: Variant } ; SCEV-EXPR-NEXT: %div.n.2 = sdiv i16 %div.n.1, 2 ; SCEV-EXPR-NEXT: --> %div.n.2 U: [-4096,4096) S: [-4096,4096) Exits: 0 LoopDispositions: { %loop: Variant } -; SCEV-EXPR-NEXT: %mul.n.3.reass = mul i16 %mul, 16 +; SCEV-EXPR-NEXT: %mul.n.3 = mul i16 %mul.n.reass.reass, 2 ; SCEV-EXPR-NEXT: --> (16 * %mul) U: [0,-15) S: [-32768,32753) Exits: 0 LoopDispositions: { %loop: Variant } ; SCEV-EXPR-NEXT: %div.n.3 = sdiv i16 %div.n.2, 2 ; SCEV-EXPR-NEXT: --> %div.n.3 U: [-2048,2048) S: [-2048,2048) Exits: 0 LoopDispositions: { %loop: Variant } diff --git a/llvm/test/Transforms/LoopVectorize/scalable-loop-unpredicated-body-scalar-tail.ll b/llvm/test/Transforms/LoopVectorize/scalable-loop-unpredicated-body-scalar-tail.ll index 901f228c6b67..ee6da8f528dd 100644 --- a/llvm/test/Transforms/LoopVectorize/scalable-loop-unpredicated-body-scalar-tail.ll +++ b/llvm/test/Transforms/LoopVectorize/scalable-loop-unpredicated-body-scalar-tail.ll @@ -1,87 +1,91 @@ -; RUN: opt -S -passes=loop-vectorize,instcombine -force-vector-interleave=1 -force-vector-width=4 -force-target-supports-scalable-vectors=true -scalable-vectorization=on < %s | FileCheck %s --check-prefix=CHECKUF1 -; RUN: opt -S -passes=loop-vectorize,instcombine -force-vector-interleave=2 -force-vector-width=4 -force-target-supports-scalable-vectors=true -scalable-vectorization=on < %s | FileCheck %s --check-prefix=CHECKUF2 +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --filter-out-after "scalar.ph\:" --version 5 +; RUN: opt -S -passes=loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -force-target-supports-scalable-vectors=true -scalable-vectorization=on < %s | FileCheck %s --check-prefix=CHECKUF1 +; RUN: opt -S -passes=loop-vectorize -force-vector-interleave=2 -force-vector-width=4 -force-target-supports-scalable-vectors=true -scalable-vectorization=on < %s | FileCheck %s --check-prefix=CHECKUF2 -; CHECKUF1: for.body.preheader: -; CHECKUF1-DAG: %wide.trip.count = zext nneg i32 %N to i64 -; CHECKUF1-DAG: %[[VSCALE:.*]] = call i64 @llvm.vscale.i64() -; CHECKUF1-DAG: %[[VSCALEX4:.*]] = shl nuw i64 %[[VSCALE]], 2 -; CHECKUF1-DAG: %min.iters.check = icmp ugt i64 %[[VSCALEX4]], %wide.trip.count - -; CHECKUF1: vector.ph: -; CHECKUF1-DAG: %[[VSCALE:.*]] = call i64 @llvm.vscale.i64() -; CHECKUF1-DAG: %[[VSCALEX4:.*]] = shl nuw i64 %[[VSCALE]], 2 -; CHECKUF1-DAG: %n.mod.vf = urem i64 %wide.trip.count, %[[VSCALEX4]] -; CHECKUF1: %n.vec = sub nsw i64 %wide.trip.count, %n.mod.vf - -; CHECKUF1: vector.body: -; CHECKUF1: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ] -; CHECKUF1: %[[IDXB:.*]] = getelementptr inbounds double, ptr %b, i64 %index -; CHECKUF1: %wide.load = load <vscale x 4 x double>, ptr %[[IDXB]], align 8 -; CHECKUF1: %[[FADD:.*]] = fadd <vscale x 4 x double> %wide.load, splat (double 1.000000e+00) -; CHECKUF1: %[[IDXA:.*]] = getelementptr inbounds double, ptr %a, i64 %index -; CHECKUF1: store <vscale x 4 x double> %[[FADD]], ptr %[[IDXA]], align 8 -; CHECKUF1: %index.next = add nuw i64 %index, %[[VSCALEX4]] -; CHECKUF1: %[[CMP:.*]] = icmp eq i64 %index.next, %n.vec -; CHECKUF1: br i1 %[[CMP]], label %middle.block, label %vector.body, !llvm.loop !0 - - -; For an interleave factor of 2, vscale is scaled by 8 instead of 4 (and thus shifted left by 3 instead of 2). +; For an interleave factor of 2, vscale is scaled by 8 instead of 4. ; There is also the increment for the next iteration, e.g. instead of indexing IDXB, it indexes at IDXB + vscale * 4. - -; CHECKUF2: for.body.preheader: -; CHECKUF2-DAG: %wide.trip.count = zext nneg i32 %N to i64 -; CHECKUF2-DAG: %[[VSCALE:.*]] = call i64 @llvm.vscale.i64() -; CHECKUF2-DAG: %[[VSCALEX8:.*]] = shl nuw i64 %[[VSCALE]], 3 -; CHECKUF2-DAG: %min.iters.check = icmp ugt i64 %[[VSCALEX8]], %wide.trip.count - -; CHECKUF2: vector.ph: -; CHECKUF2-DAG: %[[VSCALE:.*]] = call i64 @llvm.vscale.i64() -; CHECKUF2-DAG: %[[VSCALEX8:.*]] = shl nuw i64 %[[VSCALE]], 3 -; CHECKUF2-DAG: %n.mod.vf = urem i64 %wide.trip.count, %[[VSCALEX8]] -; CHECKUF2: %n.vec = sub nsw i64 %wide.trip.count, %n.mod.vf - -; CHECKUF2: vector.body: -; CHECKUF2: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ] -; CHECKUF2: %[[IDXB:.*]] = getelementptr inbounds double, ptr %b, i64 %index -; CHECKUF2: %[[VSCALE:.*]] = call i64 @llvm.vscale.i64() -; CHECKUF2: %[[VSCALE2:.*]] = shl i64 %[[VSCALE]], 5 -; CHECKUF2: %[[IDXB_NEXT:.*]] = getelementptr inbounds i8, ptr %[[IDXB]], i64 %[[VSCALE2]] -; CHECKUF2: %wide.load = load <vscale x 4 x double>, ptr %[[IDXB]], align 8 -; CHECKUF2: %wide.load{{[0-9]+}} = load <vscale x 4 x double>, ptr %[[IDXB_NEXT]], align 8 -; CHECKUF2: %[[FADD:.*]] = fadd <vscale x 4 x double> %wide.load, splat (double 1.000000e+00) -; CHECKUF2: %[[FADD_NEXT:.*]] = fadd <vscale x 4 x double> %wide.load{{[0-9]+}}, splat (double 1.000000e+00) -; CHECKUF2: %[[IDXA:.*]] = getelementptr inbounds double, ptr %a, i64 %index -; CHECKUF2: %[[VSCALE:.*]] = call i64 @llvm.vscale.i64() -; CHECKUF2: %[[VSCALE2:.*]] = shl i64 %[[VSCALE]], 5 -; CHECKUF2: %[[IDXA_NEXT:.*]] = getelementptr inbounds i8, ptr %[[IDXA]], i64 %[[VSCALE2]] -; CHECKUF2: store <vscale x 4 x double> %[[FADD]], ptr %[[IDXA]], align 8 -; CHECKUF2: store <vscale x 4 x double> %[[FADD_NEXT]], ptr %[[IDXA_NEXT]], align 8 -; CHECKUF2: %index.next = add nuw i64 %index, %[[VSCALEX8]] -; CHECKUF2: %[[CMP:.*]] = icmp eq i64 %index.next, %n.vec -; CHECKUF2: br i1 %[[CMP]], label %middle.block, label %vector.body, !llvm.loop !0 - -define void @loop(i32 %N, ptr nocapture %a, ptr nocapture readonly %b) { +define void @loop(i64 %N, ptr noalias %a, ptr noalias %b) { +; CHECKUF1-LABEL: define void @loop( +; CHECKUF1-SAME: i64 [[N:%.*]], ptr noalias [[A:%.*]], ptr noalias [[B:%.*]]) { +; CHECKUF1-NEXT: [[ENTRY:.*:]] +; CHECKUF1-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() +; CHECKUF1-NEXT: [[TMP1:%.*]] = mul nuw i64 [[TMP0]], 4 +; CHECKUF1-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], [[TMP1]] +; CHECKUF1-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; CHECKUF1: [[VECTOR_PH]]: +; CHECKUF1-NEXT: [[TMP5:%.*]] = call i64 @llvm.vscale.i64() +; CHECKUF1-NEXT: [[TMP6:%.*]] = mul nuw i64 [[TMP5]], 4 +; CHECKUF1-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], [[TMP6]] +; CHECKUF1-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]] +; CHECKUF1-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECKUF1: [[VECTOR_BODY]]: +; CHECKUF1-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; CHECKUF1-NEXT: [[TMP7:%.*]] = getelementptr inbounds double, ptr [[B]], i64 [[INDEX]] +; CHECKUF1-NEXT: [[WIDE_LOAD:%.*]] = load <vscale x 4 x double>, ptr [[TMP7]], align 8 +; CHECKUF1-NEXT: [[TMP8:%.*]] = fadd <vscale x 4 x double> [[WIDE_LOAD]], splat (double 1.000000e+00) +; CHECKUF1-NEXT: [[TMP9:%.*]] = getelementptr inbounds double, ptr [[A]], i64 [[INDEX]] +; CHECKUF1-NEXT: store <vscale x 4 x double> [[TMP8]], ptr [[TMP9]], align 8 +; CHECKUF1-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP6]] +; CHECKUF1-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECKUF1-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECKUF1: [[MIDDLE_BLOCK]]: +; CHECKUF1-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]] +; CHECKUF1-NEXT: br i1 [[CMP_N]], [[EXIT:label %.*]], label %[[SCALAR_PH]] +; CHECKUF1: [[SCALAR_PH]]: +; +; CHECKUF2-LABEL: define void @loop( +; CHECKUF2-SAME: i64 [[N:%.*]], ptr noalias [[A:%.*]], ptr noalias [[B:%.*]]) { +; CHECKUF2-NEXT: [[ENTRY:.*:]] +; CHECKUF2-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() +; CHECKUF2-NEXT: [[TMP1:%.*]] = mul nuw i64 [[TMP0]], 8 +; CHECKUF2-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], [[TMP1]] +; CHECKUF2-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; CHECKUF2: [[VECTOR_PH]]: +; CHECKUF2-NEXT: [[TMP5:%.*]] = call i64 @llvm.vscale.i64() +; CHECKUF2-NEXT: [[TMP6:%.*]] = mul nuw i64 [[TMP5]], 8 +; CHECKUF2-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], [[TMP6]] +; CHECKUF2-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]] +; CHECKUF2-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECKUF2: [[VECTOR_BODY]]: +; CHECKUF2-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; CHECKUF2-NEXT: [[TMP7:%.*]] = getelementptr inbounds double, ptr [[B]], i64 [[INDEX]] +; CHECKUF2-NEXT: [[TMP8:%.*]] = call i64 @llvm.vscale.i64() +; CHECKUF2-NEXT: [[TMP16:%.*]] = mul nuw i64 [[TMP8]], 4 +; CHECKUF2-NEXT: [[TMP9:%.*]] = getelementptr inbounds double, ptr [[TMP7]], i64 [[TMP16]] +; CHECKUF2-NEXT: [[WIDE_LOAD:%.*]] = load <vscale x 4 x double>, ptr [[TMP7]], align 8 +; CHECKUF2-NEXT: [[WIDE_LOAD3:%.*]] = load <vscale x 4 x double>, ptr [[TMP9]], align 8 +; CHECKUF2-NEXT: [[TMP10:%.*]] = fadd <vscale x 4 x double> [[WIDE_LOAD]], splat (double 1.000000e+00) +; CHECKUF2-NEXT: [[TMP11:%.*]] = fadd <vscale x 4 x double> [[WIDE_LOAD3]], splat (double 1.000000e+00) +; CHECKUF2-NEXT: [[TMP12:%.*]] = getelementptr inbounds double, ptr [[A]], i64 [[INDEX]] +; CHECKUF2-NEXT: [[TMP13:%.*]] = call i64 @llvm.vscale.i64() +; CHECKUF2-NEXT: [[TMP17:%.*]] = mul nuw i64 [[TMP13]], 4 +; CHECKUF2-NEXT: [[TMP14:%.*]] = getelementptr inbounds double, ptr [[TMP12]], i64 [[TMP17]] +; CHECKUF2-NEXT: store <vscale x 4 x double> [[TMP10]], ptr [[TMP12]], align 8 +; CHECKUF2-NEXT: store <vscale x 4 x double> [[TMP11]], ptr [[TMP14]], align 8 +; CHECKUF2-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP6]] +; CHECKUF2-NEXT: [[TMP15:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECKUF2-NEXT: br i1 [[TMP15]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECKUF2: [[MIDDLE_BLOCK]]: +; CHECKUF2-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]] +; CHECKUF2-NEXT: br i1 [[CMP_N]], [[EXIT:label %.*]], label %[[SCALAR_PH]] +; CHECKUF2: [[SCALAR_PH]]: +; entry: - %cmp7 = icmp sgt i32 %N, 0 - br i1 %cmp7, label %for.body.preheader, label %for.cond.cleanup - -for.body.preheader: ; preds = %entry - %wide.trip.count = zext i32 %N to i64 - br label %for.body - -for.cond.cleanup: ; preds = %for.body, %entry - ret void + br label %loop -for.body: ; preds = %for.body.preheader, %for.body - %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ] - %arrayidx = getelementptr inbounds double, ptr %b, i64 %indvars.iv +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %arrayidx = getelementptr inbounds double, ptr %b, i64 %iv %0 = load double, ptr %arrayidx, align 8 %add = fadd double %0, 1.000000e+00 - %arrayidx2 = getelementptr inbounds double, ptr %a, i64 %indvars.iv + %arrayidx2 = getelementptr inbounds double, ptr %a, i64 %iv store double %add, ptr %arrayidx2, align 8 - %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 - %exitcond.not = icmp eq i64 %indvars.iv.next, %wide.trip.count - br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !llvm.loop !1 + %iv.next = add nuw nsw i64 %iv, 1 + %ec = icmp eq i64 %iv.next, %N + br i1 %ec, label %exit, label %loop, !llvm.loop !1 + +exit: + ret void } !1 = distinct !{!1, !2} diff --git a/llvm/test/Transforms/PhaseOrdering/AArch64/std-find.ll b/llvm/test/Transforms/PhaseOrdering/AArch64/std-find.ll new file mode 100644 index 000000000000..fa25af5f3467 --- /dev/null +++ b/llvm/test/Transforms/PhaseOrdering/AArch64/std-find.ll @@ -0,0 +1,130 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -O3 -S %s | FileCheck %s + +target triple = "arm64-apple-macosx15.0.0" + +define i64 @std_find_i16_constant_offset_with_assumptions(ptr %first.coerce, i16 noundef signext %s) nofree nosync { +; CHECK-LABEL: define i64 @std_find_i16_constant_offset_with_assumptions( +; CHECK-SAME: ptr [[FIRST_COERCE:%.*]], i16 noundef signext [[S:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[FIRST_COERCE]], i64 2) ] +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[FIRST_COERCE]], i64 256) ] +; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[FIRST_COERCE]] to i64 +; CHECK-NEXT: [[COERCE_VAL_PI_I:%.*]] = add i64 [[TMP0]], 256 +; CHECK-NEXT: [[COERCE_VAL_IP:%.*]] = inttoptr i64 [[COERCE_VAL_PI_I]] to ptr +; CHECK-NEXT: [[CMP_NOT6_I_I:%.*]] = icmp eq ptr [[FIRST_COERCE]], [[COERCE_VAL_IP]] +; CHECK-NEXT: br i1 [[CMP_NOT6_I_I]], label %[[RETURN:.*]], label %[[LOOP_HEADER:.*]] +; CHECK: [[LOOP_HEADER]]: +; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[FIRST_COERCE]], %[[ENTRY]] ] +; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[PTR_IV]], align 2 +; CHECK-NEXT: [[CMP2_I_I:%.*]] = icmp eq i16 [[TMP1]], [[S]] +; CHECK-NEXT: br i1 [[CMP2_I_I]], label %[[RETURN_LOOPEXIT:.*]], label %[[LOOP_LATCH]] +; CHECK: [[LOOP_LATCH]]: +; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 2 +; CHECK-NEXT: [[CMP_NOT_I_I:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[COERCE_VAL_IP]] +; CHECK-NEXT: br i1 [[CMP_NOT_I_I]], label %[[RETURN_LOOPEXIT]], label %[[LOOP_HEADER]] +; CHECK: [[RETURN_LOOPEXIT]]: +; CHECK-NEXT: [[MERGE_PH:%.*]] = phi ptr [ [[COERCE_VAL_IP]], %[[LOOP_LATCH]] ], [ [[PTR_IV]], %[[LOOP_HEADER]] ] +; CHECK-NEXT: [[DOTPRE:%.*]] = ptrtoint ptr [[MERGE_PH]] to i64 +; CHECK-NEXT: br label %[[RETURN]] +; CHECK: [[RETURN]]: +; CHECK-NEXT: [[RES_PRE_PHI:%.*]] = phi i64 [ [[DOTPRE]], %[[RETURN_LOOPEXIT]] ], [ [[TMP0]], %[[ENTRY]] ] +; CHECK-NEXT: ret i64 [[RES_PRE_PHI]] +; +entry: + %first = alloca { ptr }, align 8 + %s.addr = alloca i16, align 2 + store ptr %first.coerce, ptr %first, align 8 + store i16 %s, ptr %s.addr, align 2 + %0 = load ptr, ptr %first, align 8 + call void @llvm.assume(i1 true) [ "align"(ptr %0, i64 2) ] + call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %0, i64 256) ] + %start.ptr = load ptr, ptr %first, align 8 + %1 = load i64, ptr %first, align 8 + %coerce.val.pi.i = add i64 %1, 256 + %coerce.val.ip = inttoptr i64 %coerce.val.pi.i to ptr + %cmp.not6.i.i = icmp eq ptr %start.ptr, %coerce.val.ip + br i1 %cmp.not6.i.i, label %return, label %loop.ph + +loop.ph: + %2 = load i16, ptr %s.addr, align 2 + br label %loop.header + +loop.header: + %ptr.iv = phi ptr [ %start.ptr, %loop.ph ], [ %ptr.iv.next, %loop.latch ] + %3 = load i16, ptr %ptr.iv, align 2 + %cmp2.i.i = icmp eq i16 %3, %2 + br i1 %cmp2.i.i, label %return, label %loop.latch + +loop.latch: + %ptr.iv.next = getelementptr inbounds nuw i8, ptr %ptr.iv, i64 2 + %cmp.not.i.i = icmp eq ptr %ptr.iv.next, %coerce.val.ip + br i1 %cmp.not.i.i, label %return, label %loop.header + +return: + %merge = phi ptr [ %start.ptr, %entry ], [ %coerce.val.ip, %loop.latch ], [ %ptr.iv, %loop.header ] + %res = ptrtoint ptr %merge to i64 + ret i64 %res +} + +define i64 @std_find_i16_constant_offset_no_assumptions(ptr %first.coerce, i16 noundef signext %s) nofree nosync { +; CHECK-LABEL: define i64 @std_find_i16_constant_offset_no_assumptions( +; CHECK-SAME: ptr [[FIRST_COERCE:%.*]], i16 noundef signext [[S:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[FIRST_COERCE]] to i64 +; CHECK-NEXT: [[COERCE_VAL_PI_I:%.*]] = add i64 [[TMP0]], 256 +; CHECK-NEXT: [[COERCE_VAL_IP:%.*]] = inttoptr i64 [[COERCE_VAL_PI_I]] to ptr +; CHECK-NEXT: [[CMP_NOT6_I_I:%.*]] = icmp eq ptr [[FIRST_COERCE]], [[COERCE_VAL_IP]] +; CHECK-NEXT: br i1 [[CMP_NOT6_I_I]], label %[[RETURN:.*]], label %[[LOOP_HEADER:.*]] +; CHECK: [[LOOP_HEADER]]: +; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[FIRST_COERCE]], %[[ENTRY]] ] +; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[PTR_IV]], align 2 +; CHECK-NEXT: [[CMP2_I_I:%.*]] = icmp eq i16 [[TMP1]], [[S]] +; CHECK-NEXT: br i1 [[CMP2_I_I]], label %[[RETURN_LOOPEXIT:.*]], label %[[LOOP_LATCH]] +; CHECK: [[LOOP_LATCH]]: +; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 2 +; CHECK-NEXT: [[CMP_NOT_I_I:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[COERCE_VAL_IP]] +; CHECK-NEXT: br i1 [[CMP_NOT_I_I]], label %[[RETURN_LOOPEXIT]], label %[[LOOP_HEADER]] +; CHECK: [[RETURN_LOOPEXIT]]: +; CHECK-NEXT: [[MERGE_PH:%.*]] = phi ptr [ [[COERCE_VAL_IP]], %[[LOOP_LATCH]] ], [ [[PTR_IV]], %[[LOOP_HEADER]] ] +; CHECK-NEXT: [[DOTPRE:%.*]] = ptrtoint ptr [[MERGE_PH]] to i64 +; CHECK-NEXT: br label %[[RETURN]] +; CHECK: [[RETURN]]: +; CHECK-NEXT: [[RES_PRE_PHI:%.*]] = phi i64 [ [[DOTPRE]], %[[RETURN_LOOPEXIT]] ], [ [[TMP0]], %[[ENTRY]] ] +; CHECK-NEXT: ret i64 [[RES_PRE_PHI]] +; +entry: + %first = alloca { ptr }, align 8 + %s.addr = alloca i16, align 2 + store ptr %first.coerce, ptr %first, align 8 + store i16 %s, ptr %s.addr, align 2 + %0 = load ptr, ptr %first, align 8 + %start.ptr = load ptr, ptr %first, align 8 + %1 = load i64, ptr %first, align 8 + %coerce.val.pi.i = add i64 %1, 256 + %coerce.val.ip = inttoptr i64 %coerce.val.pi.i to ptr + %cmp.not6.i.i = icmp eq ptr %start.ptr, %coerce.val.ip + br i1 %cmp.not6.i.i, label %return, label %loop.ph + +loop.ph: + %2 = load i16, ptr %s.addr, align 2 + br label %loop.header + +loop.header: + %ptr.iv = phi ptr [ %start.ptr, %loop.ph ], [ %ptr.iv.next, %loop.latch ] + %3 = load i16, ptr %ptr.iv, align 2 + %cmp2.i.i = icmp eq i16 %3, %2 + br i1 %cmp2.i.i, label %return, label %loop.latch + +loop.latch: + %ptr.iv.next = getelementptr inbounds nuw i8, ptr %ptr.iv, i64 2 + %cmp.not.i.i = icmp eq ptr %ptr.iv.next, %coerce.val.ip + br i1 %cmp.not.i.i, label %return, label %loop.header + +return: + %merge = phi ptr [ %start.ptr, %entry ], [ %coerce.val.ip, %loop.latch ], [ %ptr.iv, %loop.header ] + %res = ptrtoint ptr %merge to i64 + ret i64 %res +} + +declare void @llvm.assume(i1 noundef) diff --git a/llvm/test/Transforms/SLPVectorizer/X86/control-dependent-schedule.ll b/llvm/test/Transforms/SLPVectorizer/X86/control-dependent-schedule.ll new file mode 100644 index 000000000000..8602c256ad8c --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/control-dependent-schedule.ll @@ -0,0 +1,56 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s + +define i32 @test(i32 %0, i32 %1) { +; CHECK-LABEL: define i32 @test( +; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[K:%.*]] = alloca [4 x i32], align 16 +; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[TMP0]], [[TMP1]] +; CHECK-NEXT: [[SUB2:%.*]] = add i32 [[ADD1]], -1 +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 (ptr, ...) @printf(ptr null, i32 [[ADD1]]) +; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[TMP1]], -1 +; CHECK-NEXT: [[SUB3:%.*]] = add i32 [[ADD2]], [[CALL]] +; CHECK-NEXT: [[ADD4:%.*]] = add i32 [[SUB3]], [[TMP0]] +; CHECK-NEXT: store i32 [[ADD4]], ptr [[K]], align 16 +; CHECK-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr i8, ptr [[K]], i64 4 +; CHECK-NEXT: store i32 0, ptr [[ARRAYINIT_ELEMENT]], align 4 +; CHECK-NEXT: [[ARRAYINIT_ELEMENT5:%.*]] = getelementptr i8, ptr [[K]], i64 8 +; CHECK-NEXT: [[ADD7:%.*]] = add i32 [[ADD2]], [[SUB2]] +; CHECK-NEXT: [[SUB8:%.*]] = add i32 [[ADD7]], [[TMP0]] +; CHECK-NEXT: store i32 [[SUB8]], ptr [[ARRAYINIT_ELEMENT5]], align 8 +; CHECK-NEXT: [[ARRAYINIT_ELEMENT9:%.*]] = getelementptr i8, ptr [[K]], i64 12 +; CHECK-NEXT: [[ADD13:%.*]] = add i32 [[TMP1]], 1 +; CHECK-NEXT: [[ADD10:%.*]] = add i32 [[ADD13]], [[TMP0]] +; CHECK-NEXT: [[ADD11:%.*]] = add i32 [[ADD10]], [[ADD1]] +; CHECK-NEXT: [[ADD12:%.*]] = add i32 [[ADD11]], [[TMP0]] +; CHECK-NEXT: store i32 [[ADD12]], ptr [[ARRAYINIT_ELEMENT9]], align 4 +; CHECK-NEXT: [[CALL15:%.*]] = call i32 (ptr, ...) @printf(ptr null, ptr [[K]]) +; CHECK-NEXT: ret i32 [[CALL15]] +; +entry: + %k = alloca [4 x i32], align 16 + %add1 = add i32 %0, %1 + %sub2 = add i32 %add1, -1 + %call = tail call i32 (ptr, ...) @printf(ptr null, i32 %add1) + %add2 = add i32 %1, -1 + %sub3 = add i32 %add2, %call + %add4 = add i32 %sub3, %0 + store i32 %add4, ptr %k, align 16 + %arrayinit.element = getelementptr i8, ptr %k, i64 4 + store i32 0, ptr %arrayinit.element, align 4 + %arrayinit.element5 = getelementptr i8, ptr %k, i64 8 + %add7 = add i32 %add2, %sub2 + %sub8 = add i32 %add7, %0 + store i32 %sub8, ptr %arrayinit.element5, align 8 + %arrayinit.element9 = getelementptr i8, ptr %k, i64 12 + %add13 = add i32 %1, 1 + %add10 = add i32 %add13, %0 + %add11 = add i32 %add10, %add1 + %add12 = add i32 %add11, %0 + store i32 %add12, ptr %arrayinit.element9, align 4 + %call15 = call i32 (ptr, ...) @printf(ptr null, ptr %k) + ret i32 %call15 +} + +declare i32 @printf(ptr, ...) diff --git a/llvm/test/Transforms/SeparateConstOffsetFromGEP/AMDGPU/xor-decompose.ll b/llvm/test/Transforms/SeparateConstOffsetFromGEP/AMDGPU/xor-decompose.ll new file mode 100644 index 000000000000..056f33e5ee36 --- /dev/null +++ b/llvm/test/Transforms/SeparateConstOffsetFromGEP/AMDGPU/xor-decompose.ll @@ -0,0 +1,435 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; Test the xor with constant operand is decomposed in to gep. +; RUN: opt -mtriple=amdgcn-amd-amdhsa -passes=separate-const-offset-from-gep \ +; RUN: -S < %s | FileCheck %s +; Test the gvn pass eliminates the redundant xor instructions from decomposition. +; RUN: opt -mtriple=amdgcn-amd-amdhsa -passes=separate-const-offset-from-gep,gvn \ +; RUN: -S < %s | FileCheck --check-prefix=GVN %s + +; Check that disjoint constants are properly extracted and folded into GEP +; addressing modes and GVN to eliminate redundant computations +define amdgpu_kernel void @test1(i1 %0, ptr addrspace(3) %1) { +; CHECK-LABEL: define amdgpu_kernel void @test1( +; CHECK-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; CHECK-NEXT: [[TMP5:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP6]], i32 8192 +; CHECK-NEXT: [[TMP8:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP8]] +; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP9]], i32 16384 +; CHECK-NEXT: [[TMP11:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP12:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP11]] +; CHECK-NEXT: [[TMP13:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP12]], i32 24576 +; CHECK-NEXT: [[TMP14:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP4]], align 16 +; CHECK-NEXT: [[TMP15:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP7]], align 16 +; CHECK-NEXT: [[TMP16:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP10]], align 16 +; CHECK-NEXT: [[TMP17:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP13]], align 16 +; CHECK-NEXT: [[TMP18:%.*]] = fadd <8 x half> [[TMP14]], [[TMP15]] +; CHECK-NEXT: [[TMP19:%.*]] = fadd <8 x half> [[TMP16]], [[TMP17]] +; CHECK-NEXT: [[TMP20:%.*]] = fadd <8 x half> [[TMP18]], [[TMP19]] +; CHECK-NEXT: store <8 x half> [[TMP20]], ptr addrspace(3) [[TMP1]], align 16 +; CHECK-NEXT: ret void +; +; GVN-LABEL: define amdgpu_kernel void @test1( +; GVN-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; GVN-NEXT: [[ENTRY:.*:]] +; GVN-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; GVN-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; GVN-NEXT: [[TMP4:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; GVN-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP4]], i32 8192 +; GVN-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP4]], i32 16384 +; GVN-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP4]], i32 24576 +; GVN-NEXT: [[TMP8:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP4]], align 16 +; GVN-NEXT: [[TMP9:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP5]], align 16 +; GVN-NEXT: [[TMP10:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP6]], align 16 +; GVN-NEXT: [[TMP11:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP7]], align 16 +; GVN-NEXT: [[TMP12:%.*]] = fadd <8 x half> [[TMP8]], [[TMP9]] +; GVN-NEXT: [[TMP13:%.*]] = fadd <8 x half> [[TMP10]], [[TMP11]] +; GVN-NEXT: [[TMP14:%.*]] = fadd <8 x half> [[TMP12]], [[TMP13]] +; GVN-NEXT: store <8 x half> [[TMP14]], ptr addrspace(3) [[TMP1]], align 16 +; GVN-NEXT: ret void +; +entry: + %2 = select i1 %0, i32 0, i32 288 + %3 = xor i32 %2, 32 + %4 = xor i32 %2, 4128 + %5 = xor i32 %2, 8224 + %6 = xor i32 %2, 12320 + %7 = getelementptr half, ptr addrspace(3) %1, i32 %3 + %8 = getelementptr half, ptr addrspace(3) %1, i32 %4 + %9 = getelementptr half, ptr addrspace(3) %1, i32 %5 + %10 = getelementptr half, ptr addrspace(3) %1, i32 %6 + %11 = load <8 x half>, ptr addrspace(3) %7, align 16 + %12 = load <8 x half>, ptr addrspace(3) %8, align 16 + %13 = load <8 x half>, ptr addrspace(3) %9, align 16 + %14 = load <8 x half>, ptr addrspace(3) %10, align 16 + %15 = fadd <8 x half> %11, %12 + %16 = fadd <8 x half> %13, %14 + %17 = fadd <8 x half> %15, %16 + store <8 x half> %17, ptr addrspace(3) %1, align 16 + ret void +} + +; Check that disjoint constants are properly extracted and folded into GEP +; addressing modes and GVN to eliminate redundant computations +define amdgpu_kernel void @test2(i1 %0, ptr addrspace(3) %1) { +; CHECK-LABEL: define amdgpu_kernel void @test2( +; CHECK-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP4:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP5]], i32 24576 +; CHECK-NEXT: [[TMP7:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP7]] +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP8]], i32 16384 +; CHECK-NEXT: [[TMP10:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP11:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP10]] +; CHECK-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP11]], i32 8192 +; CHECK-NEXT: [[TMP13:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; CHECK-NEXT: [[TMP14:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP6]], align 16 +; CHECK-NEXT: [[TMP15:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP9]], align 16 +; CHECK-NEXT: [[TMP16:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP12]], align 16 +; CHECK-NEXT: [[TMP17:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP13]], align 16 +; CHECK-NEXT: [[TMP18:%.*]] = fadd <8 x half> [[TMP14]], [[TMP15]] +; CHECK-NEXT: [[TMP19:%.*]] = fadd <8 x half> [[TMP16]], [[TMP17]] +; CHECK-NEXT: [[TMP20:%.*]] = fadd <8 x half> [[TMP18]], [[TMP19]] +; CHECK-NEXT: store <8 x half> [[TMP20]], ptr addrspace(3) [[TMP1]], align 16 +; CHECK-NEXT: ret void +; +; GVN-LABEL: define amdgpu_kernel void @test2( +; GVN-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; GVN-NEXT: [[ENTRY:.*:]] +; GVN-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; GVN-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; GVN-NEXT: [[TMP4:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; GVN-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP4]], i32 24576 +; GVN-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP4]], i32 16384 +; GVN-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP4]], i32 8192 +; GVN-NEXT: [[TMP8:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP5]], align 16 +; GVN-NEXT: [[TMP9:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP6]], align 16 +; GVN-NEXT: [[TMP10:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP7]], align 16 +; GVN-NEXT: [[TMP11:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP4]], align 16 +; GVN-NEXT: [[TMP12:%.*]] = fadd <8 x half> [[TMP8]], [[TMP9]] +; GVN-NEXT: [[TMP13:%.*]] = fadd <8 x half> [[TMP10]], [[TMP11]] +; GVN-NEXT: [[TMP14:%.*]] = fadd <8 x half> [[TMP12]], [[TMP13]] +; GVN-NEXT: store <8 x half> [[TMP14]], ptr addrspace(3) [[TMP1]], align 16 +; GVN-NEXT: ret void +; +entry: + %2 = select i1 %0, i32 0, i32 288 + %3 = xor i32 %2, 12320 + %4 = xor i32 %2, 8224 + %5 = xor i32 %2, 4128 + %6 = xor i32 %2, 32 + %7 = getelementptr half, ptr addrspace(3) %1, i32 %3 + %8 = getelementptr half, ptr addrspace(3) %1, i32 %4 + %9 = getelementptr half, ptr addrspace(3) %1, i32 %5 + %10 = getelementptr half, ptr addrspace(3) %1, i32 %6 + %11 = load <8 x half>, ptr addrspace(3) %7, align 16 + %12 = load <8 x half>, ptr addrspace(3) %8, align 16 + %13 = load <8 x half>, ptr addrspace(3) %9, align 16 + %14 = load <8 x half>, ptr addrspace(3) %10, align 16 + %15 = fadd <8 x half> %11, %12 + %16 = fadd <8 x half> %13, %14 + %17 = fadd <8 x half> %15, %16 + store <8 x half> %17, ptr addrspace(3) %1, align 16 + ret void +} + +; Verify that xor instructions with different non-disjoint constants are optimized +define amdgpu_kernel void @test3(i1 %0, ptr addrspace(3) %1) { +; CHECK-LABEL: define amdgpu_kernel void @test3( +; CHECK-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; CHECK-NEXT: [[TMP5:%.*]] = xor i32 [[TMP2]], 288 +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP6]], i32 4096 +; CHECK-NEXT: [[TMP8:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP8]] +; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP9]], i32 8192 +; CHECK-NEXT: [[TMP11:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP4]], align 16 +; CHECK-NEXT: [[TMP12:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP7]], align 16 +; CHECK-NEXT: [[TMP13:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP10]], align 16 +; CHECK-NEXT: [[TMP14:%.*]] = fadd <8 x half> [[TMP11]], [[TMP12]] +; CHECK-NEXT: [[TMP15:%.*]] = fadd <8 x half> [[TMP13]], [[TMP14]] +; CHECK-NEXT: store <8 x half> [[TMP15]], ptr addrspace(3) [[TMP1]], align 16 +; CHECK-NEXT: ret void +; +; GVN-LABEL: define amdgpu_kernel void @test3( +; GVN-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; GVN-NEXT: [[ENTRY:.*:]] +; GVN-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; GVN-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; GVN-NEXT: [[TMP4:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; GVN-NEXT: [[TMP5:%.*]] = xor i32 [[TMP2]], 288 +; GVN-NEXT: [[TMP6:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP5]] +; GVN-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP6]], i32 4096 +; GVN-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP4]], i32 8192 +; GVN-NEXT: [[TMP9:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP4]], align 16 +; GVN-NEXT: [[TMP10:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP7]], align 16 +; GVN-NEXT: [[TMP11:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP8]], align 16 +; GVN-NEXT: [[TMP12:%.*]] = fadd <8 x half> [[TMP9]], [[TMP10]] +; GVN-NEXT: [[TMP13:%.*]] = fadd <8 x half> [[TMP11]], [[TMP12]] +; GVN-NEXT: store <8 x half> [[TMP13]], ptr addrspace(3) [[TMP1]], align 16 +; GVN-NEXT: ret void +; +entry: + %2 = select i1 %0, i32 0, i32 288 + %3 = xor i32 %2, 32 + %4 = xor i32 %2, 2336 + %5 = xor i32 %2, 4128 + %6 = getelementptr half, ptr addrspace(3) %1, i32 %3 + %7 = getelementptr half, ptr addrspace(3) %1, i32 %4 + %8 = getelementptr half, ptr addrspace(3) %1, i32 %5 + %9 = load <8 x half>, ptr addrspace(3) %6, align 16 + %10 = load <8 x half>, ptr addrspace(3) %7, align 16 + %11 = load <8 x half>, ptr addrspace(3) %8, align 16 + %12 = fadd <8 x half> %9, %10 + %13 = fadd <8 x half> %11, %12 + store <8 x half> %13, ptr addrspace(3) %1, align 16 + ret void +} + +; Verify that no optimization occurs when disjoint constants are absent +define amdgpu_kernel void @test4(i1 %0, ptr addrspace(3) %1) { +; CHECK-LABEL: define amdgpu_kernel void @test4( +; CHECK-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP4:%.*]] = xor i32 [[TMP2]], 288 +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP4]] +; CHECK-NEXT: [[TMP7:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP5]], align 16 +; CHECK-NEXT: [[TMP8:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP6]], align 16 +; CHECK-NEXT: [[TMP9:%.*]] = fadd <8 x half> [[TMP7]], [[TMP8]] +; CHECK-NEXT: store <8 x half> [[TMP9]], ptr addrspace(3) [[TMP1]], align 16 +; CHECK-NEXT: ret void +; +; GVN-LABEL: define amdgpu_kernel void @test4( +; GVN-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; GVN-NEXT: [[ENTRY:.*:]] +; GVN-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; GVN-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; GVN-NEXT: [[TMP4:%.*]] = xor i32 [[TMP2]], 288 +; GVN-NEXT: [[TMP5:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; GVN-NEXT: [[TMP6:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP4]] +; GVN-NEXT: [[TMP7:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP5]], align 16 +; GVN-NEXT: [[TMP8:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP6]], align 16 +; GVN-NEXT: [[TMP9:%.*]] = fadd <8 x half> [[TMP7]], [[TMP8]] +; GVN-NEXT: store <8 x half> [[TMP9]], ptr addrspace(3) [[TMP1]], align 16 +; GVN-NEXT: ret void +; +entry: + %2 = select i1 %0, i32 0, i32 288 + %3 = xor i32 %2, 32 + %4 = xor i32 %2, 288 + %5 = getelementptr half, ptr addrspace(3) %1, i32 %3 + %6 = getelementptr half, ptr addrspace(3) %1, i32 %4 + %7 = load <8 x half>, ptr addrspace(3) %5, align 16 + %8 = load <8 x half>, ptr addrspace(3) %6, align 16 + %9 = fadd <8 x half> %7, %8 + store <8 x half> %9, ptr addrspace(3) %1, align 16 + ret void +} + + +; Verify that XOR-BinOp-GEP usage chains are properly optimized +define amdgpu_kernel void @test5(i1 %0, ptr addrspace(3) %1) { +; CHECK-LABEL: define amdgpu_kernel void @test5( +; CHECK-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; CHECK-NEXT: [[TMP5:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP6:%.*]] = add i32 [[TMP5]], 256 +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP7]], i32 8192 +; CHECK-NEXT: [[TMP9:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP4]], align 16 +; CHECK-NEXT: [[TMP10:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP8]], align 16 +; CHECK-NEXT: [[TMP11:%.*]] = fadd <8 x half> [[TMP9]], [[TMP10]] +; CHECK-NEXT: store <8 x half> [[TMP11]], ptr addrspace(3) [[TMP1]], align 16 +; CHECK-NEXT: ret void +; +; GVN-LABEL: define amdgpu_kernel void @test5( +; GVN-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; GVN-NEXT: [[ENTRY:.*:]] +; GVN-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; GVN-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; GVN-NEXT: [[TMP4:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; GVN-NEXT: [[TMP5:%.*]] = add i32 [[TMP3]], 256 +; GVN-NEXT: [[TMP6:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP5]] +; GVN-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP6]], i32 8192 +; GVN-NEXT: [[TMP8:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP4]], align 16 +; GVN-NEXT: [[TMP9:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP7]], align 16 +; GVN-NEXT: [[TMP10:%.*]] = fadd <8 x half> [[TMP8]], [[TMP9]] +; GVN-NEXT: store <8 x half> [[TMP10]], ptr addrspace(3) [[TMP1]], align 16 +; GVN-NEXT: ret void +; +entry: + %2 = select i1 %0, i32 0, i32 288 + %3 = xor i32 %2, 32 + %4 = xor i32 %2, 4128 + %5 = add i32 %4, 256 + %6 = getelementptr half, ptr addrspace(3) %1, i32 %3 + %7 = getelementptr half, ptr addrspace(3) %1, i32 %5 + %8 = load <8 x half>, ptr addrspace(3) %6, align 16 + %9 = load <8 x half>, ptr addrspace(3) %7, align 16 + %10 = fadd <8 x half> %8, %9 + store <8 x half> %10, ptr addrspace(3) %1, align 16 + ret void +} + +; Verify that BinOp-XOR-GEP usage chains are properly optimized. +; In the below test, make sure we stop processing the chain at xor +; and not fold the constant from add instruction in to gep. The +; constant from add can be folded and the future work will cover +; these cases. +define amdgpu_kernel void @test6(i1 %0, ptr addrspace(3) %1) { +; CHECK-LABEL: define amdgpu_kernel void @test6( +; CHECK-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP4:%.*]] = add i32 [[TMP2]], 256 +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = xor i32 [[TMP4]], 32 +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP7]], i32 8192 +; CHECK-NEXT: [[TMP9:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP5]], align 16 +; CHECK-NEXT: [[TMP10:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP8]], align 16 +; CHECK-NEXT: [[TMP11:%.*]] = fadd <8 x half> [[TMP9]], [[TMP10]] +; CHECK-NEXT: store <8 x half> [[TMP11]], ptr addrspace(3) [[TMP1]], align 16 +; CHECK-NEXT: ret void +; +; GVN-LABEL: define amdgpu_kernel void @test6( +; GVN-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; GVN-NEXT: [[ENTRY:.*:]] +; GVN-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; GVN-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; GVN-NEXT: [[TMP4:%.*]] = add i32 [[TMP2]], 256 +; GVN-NEXT: [[TMP5:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; GVN-NEXT: [[TMP6:%.*]] = xor i32 [[TMP4]], 32 +; GVN-NEXT: [[TMP7:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP6]] +; GVN-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr addrspace(3) [[TMP7]], i32 8192 +; GVN-NEXT: [[TMP9:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP5]], align 16 +; GVN-NEXT: [[TMP10:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP8]], align 16 +; GVN-NEXT: [[TMP11:%.*]] = fadd <8 x half> [[TMP9]], [[TMP10]] +; GVN-NEXT: store <8 x half> [[TMP11]], ptr addrspace(3) [[TMP1]], align 16 +; GVN-NEXT: ret void +; +entry: + %2 = select i1 %0, i32 0, i32 288 + %3 = xor i32 %2, 32 + %4 = add i32 %2, 256 + %5 = xor i32 %4, 4128 + %6 = getelementptr half, ptr addrspace(3) %1, i32 %3 + %7 = getelementptr half, ptr addrspace(3) %1, i32 %5 + %8 = load <8 x half>, ptr addrspace(3) %6, align 16 + %9 = load <8 x half>, ptr addrspace(3) %7, align 16 + %10 = fadd <8 x half> %8, %9 + store <8 x half> %10, ptr addrspace(3) %1, align 16 + ret void +} + +; Verify that BinOp-XOR-GEP usage chains with non disjoint xor works as +; intended. +define amdgpu_kernel void @test6a(i1 %0, ptr addrspace(3) %1) { +; CHECK-LABEL: define amdgpu_kernel void @test6a( +; CHECK-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP4:%.*]] = add i32 [[TMP2]], 256 +; CHECK-NEXT: [[TMP5:%.*]] = xor i32 [[TMP4]], 288 +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP5]] +; CHECK-NEXT: [[TMP8:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP6]], align 16 +; CHECK-NEXT: [[TMP9:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP7]], align 16 +; CHECK-NEXT: [[TMP10:%.*]] = fadd <8 x half> [[TMP8]], [[TMP9]] +; CHECK-NEXT: store <8 x half> [[TMP10]], ptr addrspace(3) [[TMP1]], align 16 +; CHECK-NEXT: ret void +; +; GVN-LABEL: define amdgpu_kernel void @test6a( +; GVN-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; GVN-NEXT: [[ENTRY:.*:]] +; GVN-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; GVN-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; GVN-NEXT: [[TMP4:%.*]] = add i32 [[TMP2]], 256 +; GVN-NEXT: [[TMP5:%.*]] = xor i32 [[TMP4]], 288 +; GVN-NEXT: [[TMP6:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; GVN-NEXT: [[TMP7:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP5]] +; GVN-NEXT: [[TMP8:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP6]], align 16 +; GVN-NEXT: [[TMP9:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP7]], align 16 +; GVN-NEXT: [[TMP10:%.*]] = fadd <8 x half> [[TMP8]], [[TMP9]] +; GVN-NEXT: store <8 x half> [[TMP10]], ptr addrspace(3) [[TMP1]], align 16 +; GVN-NEXT: ret void +; +entry: + %2 = select i1 %0, i32 0, i32 288 + %3 = xor i32 %2, 32 + %4 = add i32 %2, 256 + %5 = xor i32 %4, 288 + %6 = getelementptr half, ptr addrspace(3) %1, i32 %3 + %7 = getelementptr half, ptr addrspace(3) %1, i32 %5 + %8 = load <8 x half>, ptr addrspace(3) %6, align 16 + %9 = load <8 x half>, ptr addrspace(3) %7, align 16 + %10 = fadd <8 x half> %8, %9 + store <8 x half> %10, ptr addrspace(3) %1, align 16 + ret void +} + +; Ensure disjoint constants exceeding addressing mode limits (e.g., 32768) are +; not extracted +define amdgpu_kernel void @test7(i1 %0, ptr addrspace(3) %1) { +; CHECK-LABEL: define amdgpu_kernel void @test7( +; CHECK-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; CHECK-NEXT: [[TMP4:%.*]] = xor i32 [[TMP2]], 32800 +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP4]] +; CHECK-NEXT: [[TMP7:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP5]], align 16 +; CHECK-NEXT: [[TMP8:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP6]], align 16 +; CHECK-NEXT: [[TMP9:%.*]] = fadd <8 x half> [[TMP7]], [[TMP8]] +; CHECK-NEXT: store <8 x half> [[TMP9]], ptr addrspace(3) [[TMP1]], align 16 +; CHECK-NEXT: ret void +; +; GVN-LABEL: define amdgpu_kernel void @test7( +; GVN-SAME: i1 [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) { +; GVN-NEXT: [[ENTRY:.*:]] +; GVN-NEXT: [[TMP2:%.*]] = select i1 [[TMP0]], i32 0, i32 288 +; GVN-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 32 +; GVN-NEXT: [[TMP4:%.*]] = xor i32 [[TMP2]], 32800 +; GVN-NEXT: [[TMP5:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP3]] +; GVN-NEXT: [[TMP6:%.*]] = getelementptr half, ptr addrspace(3) [[TMP1]], i32 [[TMP4]] +; GVN-NEXT: [[TMP7:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP5]], align 16 +; GVN-NEXT: [[TMP8:%.*]] = load <8 x half>, ptr addrspace(3) [[TMP6]], align 16 +; GVN-NEXT: [[TMP9:%.*]] = fadd <8 x half> [[TMP7]], [[TMP8]] +; GVN-NEXT: store <8 x half> [[TMP9]], ptr addrspace(3) [[TMP1]], align 16 +; GVN-NEXT: ret void +; +entry: + %2 = select i1 %0, i32 0, i32 288 + %3 = xor i32 %2, 32 + %4 = xor i32 %2, 32800 + %5 = getelementptr half, ptr addrspace(3) %1, i32 %3 + %6 = getelementptr half, ptr addrspace(3) %1, i32 %4 + %7 = load <8 x half>, ptr addrspace(3) %5, align 16 + %8 = load <8 x half>, ptr addrspace(3) %6, align 16 + %9 = fadd <8 x half> %7, %8 + store <8 x half> %9, ptr addrspace(3) %1, align 16 + ret void +} + |
