| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 | |
| ; RUN: opt -S -passes=slp-vectorizer -mtriple=thumbv8.1m.main-none-eabi -mattr=+mve -pass-remarks-output=%t < %s | FileCheck %s | |
| ; RUN: FileCheck --input-file=%t --check-prefix=YAML %s | |
| ; The shift of the top field folds into the reduction add, so the scalar cost | |
| ; credited back for it is 0. | |
| ; YAML: --- !Passed | |
| ; YAML-NEXT: Pass: slp-vectorizer | |
| ; YAML-NEXT: Name: VectorizedHorizontalReduction | |
| ; YAML-NEXT: Function: sum4_bytes_i32 | |
| ; YAML-NEXT: Args: | |
| ; YAML-NEXT: - String: 'Vectorized horizontal reduction with cost ' | |
| ; YAML-NEXT: - Cost: '-3' | |
| ; YAML-NEXT: - String: ' and with tree size ' | |
| ; YAML-NEXT: - TreeSize: '1' | |
| define i32 @sum4_bytes_i32(ptr %p) { | |
| ; CHECK-LABEL: define i32 @sum4_bytes_i32( | |
| ; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR0:[0-9]+]] { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[P]], align 4 | |
| ; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32 [[L]] to <4 x i8> | |
| ; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i32> | |
| ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[TMP1]]) | |
| ; CHECK-NEXT: ret i32 [[TMP2]] | |
| ; | |
| entry: | |
| %l = load i32, ptr %p, align 4 | |
| %b0 = and i32 %l, 255 | |
| %s1 = lshr i32 %l, 8 | |
| %b1 = and i32 %s1, 255 | |
| %s2 = lshr i32 %l, 16 | |
| %b2 = and i32 %s2, 255 | |
| %b3 = lshr i32 %l, 24 | |
| %a1 = add i32 %b0, %b1 | |
| %a2 = add i32 %a1, %b2 | |
| %a3 = add i32 %a2, %b3 | |
| ret i32 %a3 | |
| } | |
| ; The extensions of the extracted fields are not extending loads, so their | |
| ; scalar cost is credited back in full. | |
| ; YAML: --- !Passed | |
| ; YAML-NEXT: Pass: slp-vectorizer | |
| ; YAML-NEXT: Name: VectorizedHorizontalReduction | |
| ; YAML-NEXT: Function: sum4_zext_fields | |
| ; YAML-NEXT: Args: | |
| ; YAML-NEXT: - String: 'Vectorized horizontal reduction with cost ' | |
| ; YAML-NEXT: - Cost: '-5' | |
| ; YAML-NEXT: - String: ' and with tree size ' | |
| ; YAML-NEXT: - TreeSize: '1' | |
| define i16 @sum4_zext_fields(ptr %p) { | |
| ; CHECK-LABEL: define i16 @sum4_zext_fields( | |
| ; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR0]] { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[P]], align 4 | |
| ; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32 [[L]] to <4 x i8> | |
| ; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i16> | |
| ; CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> [[TMP1]]) | |
| ; CHECK-NEXT: ret i16 [[TMP2]] | |
| ; | |
| entry: | |
| %l = load i32, ptr %p, align 4 | |
| %t0 = trunc i32 %l to i8 | |
| %s1 = lshr i32 %l, 8 | |
| %t1 = trunc i32 %s1 to i8 | |
| %s2 = lshr i32 %l, 16 | |
| %t2 = trunc i32 %s2 to i8 | |
| %s3 = lshr i32 %l, 24 | |
| %t3 = trunc i32 %s3 to i8 | |
| %z0 = zext i8 %t0 to i16 | |
| %z1 = zext i8 %t1 to i16 | |
| %z2 = zext i8 %t2 to i16 | |
| %z3 = zext i8 %t3 to i16 | |
| %a1 = add i16 %z0, %z1 | |
| %a2 = add i16 %a1, %z2 | |
| %a3 = add i16 %a2, %z3 | |
| ret i16 %a3 | |
| } |