|
| 1 | +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ |
| 2 | +// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ |
| 3 | +// RUN: -o - | FileCheck %s |
| 4 | + |
| 5 | +// CHECK-LABEL: ToTwoInts |
| 6 | +// CHECK: [[splat:%.*]] = insertelement <1 x i32> poison, i32 {{.*}}, i64 0 |
| 7 | +// CHECK: [[vec2:%.*]] = shufflevector <1 x i32> [[splat]], <1 x i32> poison, <2 x i32> zeroinitializer |
| 8 | +// CHECK: ret <2 x i32> [[vec2]] |
| 9 | +int2 ToTwoInts(int V){ |
| 10 | + return V.xx; |
| 11 | +} |
| 12 | + |
| 13 | +// CHECK-LABEL: ToFourFloats |
| 14 | +// [[splat:%.*]] = insertelement <1 x float> poison, float {{.*}}, i64 0 |
| 15 | +// [[vec4:%.*]] = shufflevector <1 x float> [[splat]], <1 x float> poison, <4 x i32> zeroinitializer |
| 16 | +// ret <4 x float> [[vec4]] |
| 17 | +float4 ToFourFloats(float V){ |
| 18 | + return V.rrrr; |
| 19 | +} |
| 20 | + |
| 21 | +// CHECK-LABEL: FillOne |
| 22 | +// CHECK: [[vec1Ptr:%.*]] = alloca <1 x i32>, align 4 |
| 23 | +// CHECK: store <1 x i32> <i32 1>, ptr [[vec1Ptr]], align 4 |
| 24 | +// CHECK: [[vec1:%.*]] = load <1 x i32>, ptr [[vec1Ptr]], align 4 |
| 25 | +// CHECK: [[vec2:%.*]] = shufflevector <1 x i32> [[vec1]], <1 x i32> poison, <2 x i32> zeroinitializer |
| 26 | +// CHECK: ret <2 x i32> [[vec2]] |
| 27 | +int2 FillOne(){ |
| 28 | + return 1.xx; |
| 29 | +} |
| 30 | + |
| 31 | +// CHECK-LABEL: FillOneUnsigned |
| 32 | +// CHECK: [[vec1Ptr:%.*]] = alloca <1 x i32>, align 4 |
| 33 | +// CHECK: store <1 x i32> <i32 1>, ptr [[vec1Ptr]], align 4 |
| 34 | +// CHECK: [[vec1:%.*]] = load <1 x i32>, ptr [[vec1Ptr]], align 4 |
| 35 | +// CHECK: [[vec3:%.*]] = shufflevector <1 x i32> [[vec1]], <1 x i32> poison, <3 x i32> zeroinitializer |
| 36 | +// CHECK: ret <3 x i32> [[vec3]] |
| 37 | +uint3 FillOneUnsigned(){ |
| 38 | + return 1u.xxx; |
| 39 | +} |
| 40 | + |
| 41 | +// CHECK-LABEL: FillOneUnsignedLong |
| 42 | +// CHECK: [[vec1Ptr:%.*]] = alloca <1 x i64>, align 8 |
| 43 | +// CHECK: store <1 x i64> <i64 1>, ptr [[vec1Ptr]], align 8 |
| 44 | +// CHECK: [[vec1:%.*]] = load <1 x i64>, ptr [[vec1Ptr]], align 8 |
| 45 | +// CHECK: [[vec4:%.*]] = shufflevector <1 x i64> [[vec1]], <1 x i64> poison, <4 x i32> zeroinitializer |
| 46 | +// CHECK: ret <4 x i64> [[vec4]] |
| 47 | +vector<uint64_t,4> FillOneUnsignedLong(){ |
| 48 | + return 1ul.xxxx; |
| 49 | +} |
| 50 | + |
| 51 | +// CHECK-LABEL: FillTwoPointFive |
| 52 | +// CHECK: [[vec1Ptr:%.*]] = alloca <1 x double>, align 8 |
| 53 | +// CHECK: store <1 x double> <double 2.500000e+00>, ptr [[vec1Ptr]], align 8 |
| 54 | +// CHECK: [[vec1:%.*]] = load <1 x double>, ptr [[vec1Ptr]], align 8 |
| 55 | +// CHECK: [[vec2:%.*]] = shufflevector <1 x double> [[vec1]], <1 x double> poison, <2 x i32> zeroinitializer |
| 56 | +// CHECK: ret <2 x double> [[vec2]] |
| 57 | +double2 FillTwoPointFive(){ |
| 58 | + return 2.5.rr; |
| 59 | +} |
| 60 | + |
| 61 | +// CHECK-LABEL: FillOneHalf |
| 62 | +// CHECK: [[vec1Ptr:%.*]] = alloca <1 x double>, align 8 |
| 63 | +// CHECK: store <1 x double> <double 5.000000e-01>, ptr [[vec1Ptr]], align 8 |
| 64 | +// CHECK: [[vec1:%.*]] = load <1 x double>, ptr [[vec1Ptr]], align 8 |
| 65 | +// CHECK: [[vec3:%.*]] = shufflevector <1 x double> [[vec1]], <1 x double> poison, <3 x i32> zeroinitializer |
| 66 | +// CHECK: ret <3 x double> [[vec3]] |
| 67 | +double3 FillOneHalf(){ |
| 68 | + return .5.rrr; |
| 69 | +} |
| 70 | + |
| 71 | +// CHECK-LABEL: FillTwoPointFiveFloat |
| 72 | +// CHECK: [[vec1Ptr:%.*]] = alloca <1 x float>, align 4 |
| 73 | +// CHECK: store <1 x float> <float 2.500000e+00>, ptr [[vec1Ptr]], align 4 |
| 74 | +// CHECK: [[vec1:%.*]] = load <1 x float>, ptr [[vec1Ptr]], align 4 |
| 75 | +// CHECK: [[vec4:%.*]] = shufflevector <1 x float> [[vec1]], <1 x float> poison, <4 x i32> zeroinitializer |
| 76 | +// CHECK: ret <4 x float> [[vec4]] |
| 77 | +float4 FillTwoPointFiveFloat(){ |
| 78 | + return 2.5f.rrrr; |
| 79 | +} |
| 80 | + |
| 81 | +// The initial codegen for this case is correct but a bit odd. The IR optimizer |
| 82 | +// cleans this up very nicely. |
| 83 | + |
| 84 | +// CHECK-LABEL: FillOneHalfFloat |
| 85 | +// CHECK: [[vec1Ptr:%.*]] = alloca <1 x float>, align 4 |
| 86 | +// CHECK: store <1 x float> <float 5.000000e-01>, ptr [[vec1Ptr]], align 4 |
| 87 | +// CHECK: [[vec1:%.*]] = load <1 x float>, ptr [[vec1Ptr]], align 4 |
| 88 | +// CHECK: [[vec1Ret:%.*]] = shufflevector <1 x float> [[vec1]], <1 x float> undef, <1 x i32> zeroinitializer |
| 89 | +// CHECK: ret <1 x float> [[vec1Ret]] |
| 90 | +vector<float, 1> FillOneHalfFloat(){ |
| 91 | + return .5f.r; |
| 92 | +} |
| 93 | + |
| 94 | +// The initial codegen for this case is correct but a bit odd. The IR optimizer |
| 95 | +// cleans this up very nicely. |
| 96 | + |
| 97 | +// CHECK-LABEL: HowManyFloats |
| 98 | +// CHECK: [[VAddr:%.*]] = alloca float, align 4 |
| 99 | +// CHECK: [[vec2Ptr:%.*]] = alloca <2 x float>, align 8 |
| 100 | +// CHECK: [[VVal:%.*]] = load float, ptr [[VAddr]], align 4 |
| 101 | +// CHECK: [[splat:%.*]] = insertelement <1 x float> poison, float [[VVal]], i64 0 |
| 102 | +// CHECK: [[vec2:%.*]] = shufflevector <1 x float> [[splat]], <1 x float> poison, <2 x i32> zeroinitializer |
| 103 | +// CHECK: store <2 x float> [[vec2]], ptr [[vec2Ptr]], align 8 |
| 104 | +// CHECK: [[vec2:%.*]] = load <2 x float>, ptr [[vec2Ptr]], align 8 |
| 105 | +// CHECK: [[vec2Res:%.*]] = shufflevector <2 x float> [[vec2]], <2 x float> poison, <2 x i32> zeroinitializer |
| 106 | +// CHECK: ret <2 x float> [[vec2Res]] |
| 107 | +float2 HowManyFloats(float V) { |
| 108 | + return V.rr.rr; |
| 109 | +} |
| 110 | + |
| 111 | +// This codegen is gnarly because `1.` is a double, so this creates double |
| 112 | +// vectors that need to be truncated down to floats. The optimizer cleans this |
| 113 | +// up nicely too. |
| 114 | + |
| 115 | +// CHECK-LABEL: AllRighty |
| 116 | +// CHECK: [[XTmp:%.*]] = alloca <1 x double>, align 8 |
| 117 | +// CHECK: [[YTmp:%.*]] = alloca <1 x double>, align 8 |
| 118 | +// CHECK: [[ZTmp:%.*]] = alloca <1 x double>, align 8 |
| 119 | + |
| 120 | +// CHECK: store <1 x double> <double 1.000000e+00>, ptr [[XTmp]], align 8 |
| 121 | +// CHECK: [[XVec:%.*]] = load <1 x double>, ptr [[XTmp]], align 8 |
| 122 | +// CHECK: [[XVec3:%.*]] = shufflevector <1 x double> [[XVec]], <1 x double> poison, <3 x i32> zeroinitializer |
| 123 | +// CHECK: [[XVal:%.*]] = extractelement <3 x double> [[XVec3]], i32 0 |
| 124 | +// CHECK: [[XValF:%.*]] = fptrunc double [[XVal]] to float |
| 125 | +// CHECK: [[Vec3F1:%.*]] = insertelement <3 x float> undef, float [[XValF]], i32 0 |
| 126 | + |
| 127 | +// CHECK: store <1 x double> <double 1.000000e+00>, ptr [[YTmp]], align 8 |
| 128 | +// CHECK: [[YVec:%.*]] = load <1 x double>, ptr [[YTmp]], align 8 |
| 129 | +// CHECK: [[YVec3:%.*]] = shufflevector <1 x double> [[YVec]], <1 x double> poison, <3 x i32> zeroinitializer |
| 130 | +// CHECK: [[YVal:%.*]] = extractelement <3 x double> [[YVec3]], i32 1 |
| 131 | +// CHECK: [[YValF:%.*]] = fptrunc double [[YVal]] to float |
| 132 | +// CHECK: [[Vec3F2:%.*]] = insertelement <3 x float> [[Vec3F1]], float [[YValF]], i32 1 |
| 133 | + |
| 134 | +// CHECK: store <1 x double> <double 1.000000e+00>, ptr [[ZTmp]], align 8 |
| 135 | +// CHECK: [[ZVec:%.*]] = load <1 x double>, ptr [[ZTmp]], align 8 |
| 136 | +// CHECK: [[ZVec3:%.*]] = shufflevector <1 x double> [[ZVec]], <1 x double> poison, <3 x i32> zeroinitializer |
| 137 | +// CHECK: [[ZVal:%.*]] = extractelement <3 x double> [[ZVec3]], i32 2 |
| 138 | +// CHECK: [[ZValF:%.*]] = fptrunc double [[ZVal]] to float |
| 139 | +// CHECK: [[Vec3F3:%.*]] = insertelement <3 x float> [[Vec3F2]], float [[ZValF]], i32 2 |
| 140 | + |
| 141 | +// ret <3 x float> [[Vec3F3]] |
| 142 | +float3 AllRighty() { |
| 143 | + return 1..rrr; |
| 144 | +} |
| 145 | + |
| 146 | +// CHECK-LABEL: AssignInt |
| 147 | +// CHECK: [[VAddr:%.*]] = alloca i32, align 4 |
| 148 | +// CHECK: [[XAddr:%.*]] = alloca i32, align 4 |
| 149 | + |
| 150 | +// Load V into a vector, then extract V out and store it to X. |
| 151 | +// CHECK: [[V:%.*]] = load i32, ptr [[VAddr]], align 4 |
| 152 | +// CHECK: [[Splat:%.*]] = insertelement <1 x i32> poison, i32 [[V]], i64 0 |
| 153 | +// CHECK: [[VExtVal:%.*]] = extractelement <1 x i32> [[Splat]], i32 0 |
| 154 | +// CHECK: store i32 [[VExtVal]], ptr [[XAddr]], align 4 |
| 155 | + |
| 156 | +// Load V into two separate vectors, then add the extracted X components. |
| 157 | +// CHECK: [[V:%.*]] = load i32, ptr [[VAddr]], align 4 |
| 158 | +// CHECK: [[Splat:%.*]] = insertelement <1 x i32> poison, i32 [[V]], i64 0 |
| 159 | +// CHECK: [[LHS:%.*]] = extractelement <1 x i32> [[Splat]], i32 0 |
| 160 | + |
| 161 | +// CHECK: [[V:%.*]] = load i32, ptr [[VAddr]], align 4 |
| 162 | +// CHECK: [[Splat:%.*]] = insertelement <1 x i32> poison, i32 [[V]], i64 0 |
| 163 | +// CHECK: [[RHS:%.*]] = extractelement <1 x i32> [[Splat]], i32 0 |
| 164 | + |
| 165 | +// CHECK: [[Sum:%.*]] = add nsw i32 [[LHS]], [[RHS]] |
| 166 | +// CHECK: store i32 [[Sum]], ptr [[XAddr]], align 4 |
| 167 | +// CHECK: [[X:%.*]] = load i32, ptr [[XAddr]], align 4 |
| 168 | +// CHECK: ret i32 [[X]] |
| 169 | + |
| 170 | +int AssignInt(int V){ |
| 171 | + int X = V.x; |
| 172 | + X.x = V.x + V.x; |
| 173 | + return X; |
| 174 | +} |
0 commit comments