| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 | |
| ; RUN: opt -passes=slp-vectorizer -S < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=x86-64-v3 | FileCheck %s | |
| ; The buildvector of the reduced values is emitted in the loop and is executed | |
| ; on every iteration, as the reduction itself. | |
| define i32 @gather_root_xor_reduction(ptr %w, ptr %t) { | |
| ; CHECK-LABEL: define i32 @gather_root_xor_reduction( | |
| ; CHECK-SAME: ptr [[W:%.*]], ptr [[T:%.*]]) #[[ATTR0:[0-9]+]] { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: br label %[[LOOP:.*]] | |
| ; CHECK: [[LOOP]]: | |
| ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] | |
| ; CHECK-NEXT: [[CRC:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[TMP8:%.*]], %[[LOOP]] ] | |
| ; CHECK-NEXT: [[CRC_EXT:%.*]] = zext i32 [[CRC]] to i64 | |
| ; CHECK-NEXT: [[W_P:%.*]] = getelementptr inbounds i64, ptr [[W]], i64 [[IV]] | |
| ; CHECK-NEXT: [[W_V:%.*]] = load i64, ptr [[W_P]], align 8 | |
| ; CHECK-NEXT: [[V:%.*]] = xor i64 [[W_V]], [[CRC_EXT]] | |
| ; CHECK-NEXT: [[I0:%.*]] = and i64 [[V]], 255 | |
| ; CHECK-NEXT: [[S1:%.*]] = lshr i64 [[V]], 8 | |
| ; CHECK-NEXT: [[I1:%.*]] = and i64 [[S1]], 255 | |
| ; CHECK-NEXT: [[S2:%.*]] = lshr i64 [[V]], 16 | |
| ; CHECK-NEXT: [[I2:%.*]] = and i64 [[S2]], 255 | |
| ; CHECK-NEXT: [[S3:%.*]] = lshr i64 [[V]], 24 | |
| ; CHECK-NEXT: [[I3:%.*]] = and i64 [[S3]], 255 | |
| ; CHECK-NEXT: [[S4:%.*]] = lshr i64 [[V]], 32 | |
| ; CHECK-NEXT: [[I4:%.*]] = and i64 [[S4]], 255 | |
| ; CHECK-NEXT: [[S5:%.*]] = lshr i64 [[V]], 40 | |
| ; CHECK-NEXT: [[I5:%.*]] = and i64 [[S5]], 255 | |
| ; CHECK-NEXT: [[S6:%.*]] = lshr i64 [[V]], 48 | |
| ; CHECK-NEXT: [[I6:%.*]] = and i64 [[S6]], 255 | |
| ; CHECK-NEXT: [[I7:%.*]] = lshr i64 [[V]], 56 | |
| ; CHECK-NEXT: [[P0:%.*]] = getelementptr inbounds i32, ptr [[T]], i64 [[I0]] | |
| ; CHECK-NEXT: [[P1:%.*]] = getelementptr inbounds [256 x i32], ptr [[T]], i64 1, i64 [[I1]] | |
| ; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds [256 x i32], ptr [[T]], i64 2, i64 [[I2]] | |
| ; CHECK-NEXT: [[P3:%.*]] = getelementptr inbounds [256 x i32], ptr [[T]], i64 3, i64 [[I3]] | |
| ; CHECK-NEXT: [[P4:%.*]] = getelementptr inbounds [256 x i32], ptr [[T]], i64 4, i64 [[I4]] | |
| ; CHECK-NEXT: [[P5:%.*]] = getelementptr inbounds [256 x i32], ptr [[T]], i64 5, i64 [[I5]] | |
| ; CHECK-NEXT: [[P6:%.*]] = getelementptr inbounds [256 x i32], ptr [[T]], i64 6, i64 [[I6]] | |
| ; CHECK-NEXT: [[P7:%.*]] = getelementptr inbounds [256 x i32], ptr [[T]], i64 7, i64 [[I7]] | |
| ; CHECK-NEXT: [[L0:%.*]] = load i32, ptr [[P0]], align 4 | |
| ; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[P1]], align 4 | |
| ; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[P2]], align 4 | |
| ; CHECK-NEXT: [[L3:%.*]] = load i32, ptr [[P3]], align 4 | |
| ; CHECK-NEXT: [[L4:%.*]] = load i32, ptr [[P4]], align 4 | |
| ; CHECK-NEXT: [[L5:%.*]] = load i32, ptr [[P5]], align 4 | |
| ; CHECK-NEXT: [[L6:%.*]] = load i32, ptr [[P6]], align 4 | |
| ; CHECK-NEXT: [[L7:%.*]] = load i32, ptr [[P7]], align 4 | |
| ; CHECK-NEXT: [[X1:%.*]] = xor i32 [[L1]], [[L0]] | |
| ; CHECK-NEXT: [[X2:%.*]] = xor i32 [[L2]], [[X1]] | |
| ; CHECK-NEXT: [[X3:%.*]] = xor i32 [[L3]], [[X2]] | |
| ; CHECK-NEXT: [[X4:%.*]] = xor i32 [[L4]], [[X3]] | |
| ; CHECK-NEXT: [[X5:%.*]] = xor i32 [[L5]], [[X4]] | |
| ; CHECK-NEXT: [[X6:%.*]] = xor i32 [[L6]], [[X5]] | |
| ; CHECK-NEXT: [[TMP8]] = xor i32 [[L7]], [[X6]] | |
| ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], 1024 | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[LOOP]] | |
| ; CHECK: [[EXIT]]: | |
| ; CHECK-NEXT: ret i32 [[TMP8]] | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] | |
| %crc = phi i32 [ 0, %entry ], [ %x7, %loop ] | |
| %crc.ext = zext i32 %crc to i64 | |
| %w.p = getelementptr inbounds i64, ptr %w, i64 %iv | |
| %w.v = load i64, ptr %w.p, align 8 | |
| %v = xor i64 %w.v, %crc.ext | |
| %i0 = and i64 %v, 255 | |
| %s1 = lshr i64 %v, 8 | |
| %i1 = and i64 %s1, 255 | |
| %s2 = lshr i64 %v, 16 | |
| %i2 = and i64 %s2, 255 | |
| %s3 = lshr i64 %v, 24 | |
| %i3 = and i64 %s3, 255 | |
| %s4 = lshr i64 %v, 32 | |
| %i4 = and i64 %s4, 255 | |
| %s5 = lshr i64 %v, 40 | |
| %i5 = and i64 %s5, 255 | |
| %s6 = lshr i64 %v, 48 | |
| %i6 = and i64 %s6, 255 | |
| %i7 = lshr i64 %v, 56 | |
| %p0 = getelementptr inbounds i32, ptr %t, i64 %i0 | |
| %p1 = getelementptr inbounds [256 x i32], ptr %t, i64 1, i64 %i1 | |
| %p2 = getelementptr inbounds [256 x i32], ptr %t, i64 2, i64 %i2 | |
| %p3 = getelementptr inbounds [256 x i32], ptr %t, i64 3, i64 %i3 | |
| %p4 = getelementptr inbounds [256 x i32], ptr %t, i64 4, i64 %i4 | |
| %p5 = getelementptr inbounds [256 x i32], ptr %t, i64 5, i64 %i5 | |
| %p6 = getelementptr inbounds [256 x i32], ptr %t, i64 6, i64 %i6 | |
| %p7 = getelementptr inbounds [256 x i32], ptr %t, i64 7, i64 %i7 | |
| %l0 = load i32, ptr %p0, align 4 | |
| %l1 = load i32, ptr %p1, align 4 | |
| %l2 = load i32, ptr %p2, align 4 | |
| %l3 = load i32, ptr %p3, align 4 | |
| %l4 = load i32, ptr %p4, align 4 | |
| %l5 = load i32, ptr %p5, align 4 | |
| %l6 = load i32, ptr %p6, align 4 | |
| %l7 = load i32, ptr %p7, align 4 | |
| %x1 = xor i32 %l1, %l0 | |
| %x2 = xor i32 %l2, %x1 | |
| %x3 = xor i32 %l3, %x2 | |
| %x4 = xor i32 %l4, %x3 | |
| %x5 = xor i32 %l5, %x4 | |
| %x6 = xor i32 %l6, %x5 | |
| %x7 = xor i32 %l7, %x6 | |
| %iv.next = add nuw nsw i64 %iv, 1 | |
| %cmp = icmp eq i64 %iv.next, 1024 | |
| br i1 %cmp, label %exit, label %loop | |
| exit: | |
| ret i32 %x7 | |
| } |