1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt -p slp-vectorizer -S %s | FileCheck %s 3 4target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" 5target triple = "x86_64-unknown-linux-gnu" 6 7define void @test_2_i24_stores(ptr %A) { 8; CHECK-LABEL: define void @test_2_i24_stores( 9; CHECK-SAME: ptr [[A:%.*]]) { 10; CHECK-NEXT: [[L:%.*]] = load i24, ptr [[A]], align 4 11; CHECK-NEXT: store i24 [[L]], ptr [[A]], align 1 12; CHECK-NEXT: [[GEP:%.*]] = getelementptr i24, ptr [[A]], i64 1 13; CHECK-NEXT: store i24 0, ptr [[GEP]], align 1 14; CHECK-NEXT: ret void 15; 16 %l = load i24, ptr %A 17 store i24 %l, ptr %A, align 1 18 %gep = getelementptr i24, ptr %A, i64 1 19 store i24 0, ptr %gep, align 1 20 ret void 21} 22 23define void @test_2_trunc_i24_to_i8(i24 %x, ptr %A) { 24; CHECK-LABEL: define void @test_2_trunc_i24_to_i8( 25; CHECK-SAME: i24 [[X:%.*]], ptr [[A:%.*]]) { 26; CHECK-NEXT: [[T:%.*]] = trunc i24 [[X]] to i8 27; CHECK-NEXT: store i8 [[T]], ptr [[A]], align 1 28; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[A]], i64 1 29; CHECK-NEXT: store i8 0, ptr [[GEP]], align 1 30; CHECK-NEXT: ret void 31; 32 %t = trunc i24 %x to i8 33 store i8 %t, ptr %A, align 1 34 %gep = getelementptr i8, ptr %A, i64 1 35 store i8 0, ptr %gep, align 1 36 ret void 37} 38 39define void @test_4_trunc_i24_to_i8(i24 %x, ptr %A) { 40; CHECK-LABEL: define void @test_4_trunc_i24_to_i8( 41; CHECK-SAME: i24 [[X:%.*]], ptr [[A:%.*]]) { 42; CHECK-NEXT: [[T:%.*]] = trunc i24 [[X]] to i8 43; CHECK-NEXT: store i8 [[T]], ptr [[A]], align 1 44; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr i8, ptr [[A]], i64 1 45; CHECK-NEXT: store i8 [[T]], ptr [[GEP_1]], align 1 46; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr i8, ptr [[A]], i64 2 47; CHECK-NEXT: store i8 [[T]], ptr [[GEP_2]], align 1 48; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr i8, ptr [[A]], i64 3 49; CHECK-NEXT: store i8 [[T]], ptr [[GEP_3]], align 1 50; CHECK-NEXT: ret void 51; 52 %t = trunc i24 %x to i8 53 store i8 %t, ptr %A, align 1 54 %gep.1 = getelementptr i8, ptr %A, i64 1 55 store i8 %t, ptr %gep.1, align 1 56 %gep.2 = getelementptr i8, ptr %A, i64 2 57 store i8 %t, ptr %gep.2, align 1 58 %gep.3 = getelementptr i8, ptr %A, i64 3 59 store i8 %t, ptr %gep.3, align 1 60 ret void 61} 62 63define void @test_8_trunc_i24_to_i8(i24 %x, ptr %A) { 64; CHECK-LABEL: define void @test_8_trunc_i24_to_i8( 65; CHECK-SAME: i24 [[X:%.*]], ptr [[A:%.*]]) { 66; CHECK-NEXT: [[T:%.*]] = trunc i24 [[X]] to i8 67; CHECK-NEXT: [[TMP1:%.*]] = insertelement <8 x i8> poison, i8 [[T]], i32 0 68; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> poison, <8 x i32> zeroinitializer 69; CHECK-NEXT: store <8 x i8> [[TMP2]], ptr [[A]], align 1 70; CHECK-NEXT: ret void 71; 72 %t = trunc i24 %x to i8 73 store i8 %t, ptr %A, align 1 74 %gep.1 = getelementptr i8, ptr %A, i64 1 75 store i8 %t, ptr %gep.1, align 1 76 %gep.2 = getelementptr i8, ptr %A, i64 2 77 store i8 %t, ptr %gep.2, align 1 78 %gep.3 = getelementptr i8, ptr %A, i64 3 79 store i8 %t, ptr %gep.3, align 1 80 %gep.4 = getelementptr i8, ptr %A, i64 4 81 store i8 %t, ptr %gep.4, align 1 82 %gep.5 = getelementptr i8, ptr %A, i64 5 83 store i8 %t, ptr %gep.5, align 1 84 %gep.6 = getelementptr i8, ptr %A, i64 6 85 store i8 %t, ptr %gep.6, align 1 86 %gep.7 = getelementptr i8, ptr %A, i64 7 87 store i8 %t, ptr %gep.7, align 1 88 ret void 89} 90 91define void @test_4_trunc_i24_to_i16(i24 %x, ptr %A) { 92; CHECK-LABEL: define void @test_4_trunc_i24_to_i16( 93; CHECK-SAME: i24 [[X:%.*]], ptr [[A:%.*]]) { 94; CHECK-NEXT: [[T:%.*]] = trunc i24 [[X]] to i16 95; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i16> poison, i16 [[T]], i32 0 96; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i16> [[TMP1]], <4 x i16> poison, <4 x i32> zeroinitializer 97; CHECK-NEXT: store <4 x i16> [[TMP2]], ptr [[A]], align 1 98; CHECK-NEXT: ret void 99; 100 %t = trunc i24 %x to i16 101 store i16 %t, ptr %A, align 1 102 %gep.1 = getelementptr i16, ptr %A, i64 1 103 store i16 %t, ptr %gep.1, align 1 104 %gep.2 = getelementptr i16, ptr %A, i64 2 105 store i16 %t, ptr %gep.2, align 1 106 %gep.3 = getelementptr i16, ptr %A, i64 3 107 store i16 %t, ptr %gep.3, align 1 108 ret void 109} 110 111%struct.d = type { [3 x i8], [3 x i8], [2 x i8] } 112 113; Test case for https://github.com/llvm/llvm-project/issues/88640. 114define void @test_access_i24_directly(ptr %src, ptr noalias %dst) "target-cpu"="btver2" { 115; CHECK-LABEL: define void @test_access_i24_directly( 116; CHECK-SAME: ptr [[SRC:%.*]], ptr noalias [[DST:%.*]]) #[[ATTR0:[0-9]+]] { 117; CHECK-NEXT: entry: 118; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[SRC]], align 8 119; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[TMP0]] to i24 120; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds [[STRUCT_D:%.*]], ptr [[SRC]], i64 0, i32 1 121; CHECK-NEXT: [[BF_LOAD:%.*]] = load i24, ptr [[GEP_SRC]], align 1 122; CHECK-NEXT: [[BF_VALUE:%.*]] = and i24 [[TMP1]], 8388607 123; CHECK-NEXT: [[BF_CLEAR:%.*]] = and i24 [[BF_LOAD]], -8388608 124; CHECK-NEXT: [[BF_SET:%.*]] = or disjoint i24 [[BF_CLEAR]], [[BF_VALUE]] 125; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds [[STRUCT_D]], ptr [[DST]], i64 0, i32 1 126; CHECK-NEXT: store i24 [[BF_SET]], ptr [[GEP_DST]], align 1 127; CHECK-NEXT: store i24 0, ptr [[DST]], align 8 128; CHECK-NEXT: ret void 129; 130entry: 131 %0 = load i64, ptr %src, align 8 132 %1 = trunc i64 %0 to i24 133 %gep.src = getelementptr inbounds %struct.d, ptr %src, i64 0, i32 1 134 %bf.load = load i24, ptr %gep.src, align 1 135 %bf.value = and i24 %1, 8388607 136 %bf.clear = and i24 %bf.load, -8388608 137 %bf.set = or disjoint i24 %bf.clear, %bf.value 138 %gep.dst = getelementptr inbounds %struct.d, ptr %dst, i64 0, i32 1 139 store i24 %bf.set, ptr %gep.dst, align 1 140 store i24 0, ptr %dst, align 8 141 ret void 142} 143