[PATCH] D83294: [Fixed Point] Add codegen for fixed-point shifts.
This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG577f8b157a03: [Fixed Point] Add codegen for fixed-point shifts. (authored by ebevhan). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D83294/new/ https://reviews.llvm.org/D83294 Files: clang/lib/CodeGen/CGExprScalar.cpp clang/test/Frontend/fixed_point_compound.c clang/test/Frontend/fixed_point_shift.c clang/test/Frontend/fixed_point_shift_const.c Index: clang/test/Frontend/fixed_point_shift_const.c === --- /dev/null +++ clang/test/Frontend/fixed_point_shift_const.c @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED +// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -fpadding-on-unsigned-fixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNSIGNED + +short _Accum sa_const1 = 1.0hk << 2; +// CHECK-DAG: @sa_const1 = {{.*}}global i16 512 +short _Accum sa_const2 = 0.5hk << 2; +// CHECK-DAG: @sa_const2 = {{.*}}global i16 256 +short _Accum sa_const3 = 10.0hk >> 3; +// CHECK-DAG: @sa_const3 = {{.*}}global i16 160 +short _Accum sa_const4 = 0.0546875hk << 8; +// CHECK-DAG: @sa_const4 = {{.*}}global i16 1792 +short _Accum sa_const5 = -1.0hk << 2; +// CHECK-DAG: @sa_const5 = {{.*}}global i16 -512 +short _Accum sa_const6 = -255.0hk >> 8; +// CHECK-DAG: @sa_const6 = {{.*}}global i16 -128 + +_Fract f_const1 = -1.0r >> 5; +// CHECK-DAG: @f_const1 = {{.*}}global i16 -1024 +_Fract f_const2 = 0.0052490234375r >> 3; +// CHECK-DAG: @f_const2 = {{.*}}global i16 21 +_Fract f_const3 = -0.0001r << 5; +// CHECK-DAG: @f_const3 = {{.*}}global i16 -96 +_Fract f_const4 = -0.75r >> 15; +// CHECK-DAG: @f_const4 = {{.*}}global i16 -1 +_Fract f_const5 = 0.078216552734375r << 3; +// CHECK-DAG: @f_const5 = {{.*}}global i16 20504 + +unsigned _Fract uf_const1 = 0.375ur >> 13; +// SIGNED-DAG: @uf_const1 = {{.*}}global i16 3 +// UNSIGNED-DAG: @uf_const1 = {{.*}}global i16 1 +unsigned _Fract uf_const2 = 0.0546875ur << 3; +// SIGNED-DAG: @uf_const2 = {{.*}}global i16 28672 +// UNSIGNED-DAG: @uf_const2 = {{.*}}global i16 14336 + +_Sat short _Accum ssa_const1 = (_Sat short _Accum)31.875hk << 4; +// CHECK-DAG: @ssa_const1 = {{.*}}global i16 32767 +_Sat short _Accum ssa_const2 = (_Sat short _Accum) - 1.0hk << 8; +// CHECK-DAG: @ssa_const2 = {{.*}}global i16 -32768 +_Sat short _Accum ssa_const3 = (_Sat short _Accum)128.0hk << 8; +// CHECK-DAG: @ssa_const3 = {{.*}}global i16 32767 +_Sat short _Fract ssf_const1 = (_Sat short _Fract) - 0.5hr << 3; +// CHECK-DAG: @ssf_const1 = {{.*}}global i8 -128 + +_Sat unsigned _Fract suf_const1 = (_Sat unsigned _Fract)0.5r << 1; +// SIGNED-DAG: @suf_const1 = {{.*}}global i16 -1 +// UNSIGNED-DAG: @suf_const1 = {{.*}}global i16 32767 +_Sat unsigned _Fract suf_const2 = (_Sat unsigned _Fract)0.25r << 1; +// SIGNED-DAG: @suf_const2 = {{.*}}global i16 -32768 +// UNSIGNED-DAG: @suf_const2 = {{.*}}global i16 16384 +_Sat unsigned _Accum sua_const2 = (_Sat unsigned _Accum)128.0uk << 10; +// SIGNED-DAG: @sua_const2 = {{.*}}global i32 -1 +// UNSIGNED-DAG: @sua_const2 = {{.*}}global i32 2147483647 Index: clang/test/Frontend/fixed_point_shift.c === --- clang/test/Frontend/fixed_point_shift.c +++ clang/test/Frontend/fixed_point_shift.c @@ -1,37 +1,580 @@ -// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED -// RUN: %clang_cc1 -ffixed-point -fpadding-on-unsigned-fixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNSIGNED - -short _Accum sa_const1 = 1.0hk << 2; // CHECK-DAG: @sa_const1 = {{.*}}global i16 512 -short _Accum sa_const2 = 0.5hk << 2; // CHECK-DAG: @sa_const2 = {{.*}}global i16 256 -short _Accum sa_const3 = 10.0hk >> 3; // CHECK-DAG: @sa_const3 = {{.*}}global i16 160 -short _Accum sa_const4 = 0.0546875hk << 8; // CHECK-DAG: @sa_const4 = {{.*}}global i16 1792 -short _Accum sa_const5 = -1.0hk << 2; // CHECK-DAG: @sa_const5 = {{.*}}global i16 -512 -short _Accum sa_const6 = -255.0hk >> 8;// CHECK-DAG: @sa_const6 = {{.*}}global i16 -128 - -_Fract f_const1 = -1.0r >> 5; // CHECK-DAG: @f_const1 = {{.*}}global i16 -1024 -_Fract f_const2 = 0.0052490234375r >> 3; // CHECK-DAG: @f_const2 = {{.*}}global i16 21 -_Fract f_const3 = -0.0001r << 5; // CHECK-DAG: @f_const3 = {{.*}}global i16 -96 -_Fract f_const4 = -0.75r >> 15;// CHECK-DAG: @f_const4 = {{.*}}global i16 -1 -_Fract f_const5 = 0.078216552734375r << 3; // CHECK-DAG: @f_const5 = {{.*}}global i16 20504 - -unsigned _Fract uf_const1 = 0.375ur >> 13; -// SIGNED-DAG: @uf_const1 = {{.*}}global i16 3 -// UNSIGNED-DAG: @uf_const1 = {{.*}}global i16 1 -unsigned _Fract uf_const2 =
[PATCH] D83294: [Fixed Point] Add codegen for fixed-point shifts.
ebevhan updated this revision to Diff 286968. ebevhan added a comment. Revamped patch. It's now based on the FixedPointBuilder. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D83294/new/ https://reviews.llvm.org/D83294 Files: clang/lib/CodeGen/CGExprScalar.cpp clang/test/Frontend/fixed_point_compound.c clang/test/Frontend/fixed_point_shift.c clang/test/Frontend/fixed_point_shift_const.c Index: clang/test/Frontend/fixed_point_shift_const.c === --- /dev/null +++ clang/test/Frontend/fixed_point_shift_const.c @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED +// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -fpadding-on-unsigned-fixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNSIGNED + +short _Accum sa_const1 = 1.0hk << 2; +// CHECK-DAG: @sa_const1 = {{.*}}global i16 512 +short _Accum sa_const2 = 0.5hk << 2; +// CHECK-DAG: @sa_const2 = {{.*}}global i16 256 +short _Accum sa_const3 = 10.0hk >> 3; +// CHECK-DAG: @sa_const3 = {{.*}}global i16 160 +short _Accum sa_const4 = 0.0546875hk << 8; +// CHECK-DAG: @sa_const4 = {{.*}}global i16 1792 +short _Accum sa_const5 = -1.0hk << 2; +// CHECK-DAG: @sa_const5 = {{.*}}global i16 -512 +short _Accum sa_const6 = -255.0hk >> 8; +// CHECK-DAG: @sa_const6 = {{.*}}global i16 -128 + +_Fract f_const1 = -1.0r >> 5; +// CHECK-DAG: @f_const1 = {{.*}}global i16 -1024 +_Fract f_const2 = 0.0052490234375r >> 3; +// CHECK-DAG: @f_const2 = {{.*}}global i16 21 +_Fract f_const3 = -0.0001r << 5; +// CHECK-DAG: @f_const3 = {{.*}}global i16 -96 +_Fract f_const4 = -0.75r >> 15; +// CHECK-DAG: @f_const4 = {{.*}}global i16 -1 +_Fract f_const5 = 0.078216552734375r << 3; +// CHECK-DAG: @f_const5 = {{.*}}global i16 20504 + +unsigned _Fract uf_const1 = 0.375ur >> 13; +// SIGNED-DAG: @uf_const1 = {{.*}}global i16 3 +// UNSIGNED-DAG: @uf_const1 = {{.*}}global i16 1 +unsigned _Fract uf_const2 = 0.0546875ur << 3; +// SIGNED-DAG: @uf_const2 = {{.*}}global i16 28672 +// UNSIGNED-DAG: @uf_const2 = {{.*}}global i16 14336 + +_Sat short _Accum ssa_const1 = (_Sat short _Accum)31.875hk << 4; +// CHECK-DAG: @ssa_const1 = {{.*}}global i16 32767 +_Sat short _Accum ssa_const2 = (_Sat short _Accum) - 1.0hk << 8; +// CHECK-DAG: @ssa_const2 = {{.*}}global i16 -32768 +_Sat short _Accum ssa_const3 = (_Sat short _Accum)128.0hk << 8; +// CHECK-DAG: @ssa_const3 = {{.*}}global i16 32767 +_Sat short _Fract ssf_const1 = (_Sat short _Fract) - 0.5hr << 3; +// CHECK-DAG: @ssf_const1 = {{.*}}global i8 -128 + +_Sat unsigned _Fract suf_const1 = (_Sat unsigned _Fract)0.5r << 1; +// SIGNED-DAG: @suf_const1 = {{.*}}global i16 -1 +// UNSIGNED-DAG: @suf_const1 = {{.*}}global i16 32767 +_Sat unsigned _Fract suf_const2 = (_Sat unsigned _Fract)0.25r << 1; +// SIGNED-DAG: @suf_const2 = {{.*}}global i16 -32768 +// UNSIGNED-DAG: @suf_const2 = {{.*}}global i16 16384 +_Sat unsigned _Accum sua_const2 = (_Sat unsigned _Accum)128.0uk << 10; +// SIGNED-DAG: @sua_const2 = {{.*}}global i32 -1 +// UNSIGNED-DAG: @sua_const2 = {{.*}}global i32 2147483647 Index: clang/test/Frontend/fixed_point_shift.c === --- clang/test/Frontend/fixed_point_shift.c +++ clang/test/Frontend/fixed_point_shift.c @@ -1,37 +1,580 @@ -// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED -// RUN: %clang_cc1 -ffixed-point -fpadding-on-unsigned-fixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNSIGNED - -short _Accum sa_const1 = 1.0hk << 2; // CHECK-DAG: @sa_const1 = {{.*}}global i16 512 -short _Accum sa_const2 = 0.5hk << 2; // CHECK-DAG: @sa_const2 = {{.*}}global i16 256 -short _Accum sa_const3 = 10.0hk >> 3; // CHECK-DAG: @sa_const3 = {{.*}}global i16 160 -short _Accum sa_const4 = 0.0546875hk << 8; // CHECK-DAG: @sa_const4 = {{.*}}global i16 1792 -short _Accum sa_const5 = -1.0hk << 2; // CHECK-DAG: @sa_const5 = {{.*}}global i16 -512 -short _Accum sa_const6 = -255.0hk >> 8;// CHECK-DAG: @sa_const6 = {{.*}}global i16 -128 - -_Fract f_const1 = -1.0r >> 5; // CHECK-DAG: @f_const1 = {{.*}}global i16 -1024 -_Fract f_const2 = 0.0052490234375r >> 3; // CHECK-DAG: @f_const2 = {{.*}}global i16 21 -_Fract f_const3 = -0.0001r << 5; // CHECK-DAG: @f_const3 = {{.*}}global i16 -96 -_Fract f_const4 = -0.75r >> 15;// CHECK-DAG: @f_const4 = {{.*}}global i16 -1 -_Fract f_const5 = 0.078216552734375r << 3; // CHECK-DAG: @f_const5 = {{.*}}global i16 20504 - -unsigned _Fract uf_const1 = 0.375ur >> 13; -// SIGNED-DAG: @uf_const1 = {{.*}}global i16 3 -// UNSIGNED-DAG: @uf_const1 = {{.*}}global i16 1 -unsigned _Fract uf_const2 = 0.0546875ur << 3; -// SIGNED-DAG: @uf_const2 = {{.*}}global i16 28672 -// UNSIGNED-DAG: @uf_const2 =
[PATCH] D83294: [Fixed Point] Add codegen for fixed-point shifts.
ebevhan marked an inline comment as done. ebevhan added inline comments. Comment at: clang/lib/CodeGen/CGExprScalar.cpp:3857 + + // TODO: This misses out on the sanitizer check below. + if (Ops.isFixedPointOp()) leonardchan wrote: > I don't suppose you could file a bug for this and CC me on it so we can > remember to do this sometime after this lands? I could do that. I guess the issue is larger than just this; I think other ops do not get proper UBSan checks for fixedpoint. So the ticket would probably entail supporting UBSan for fixedpoint, which is maybe a bit larger in scope. Comment at: clang/test/Frontend/fixed_point_compound.c:388-390 + // UNSIGNED-NEXT: [[TMP7:%.*]] = icmp slt i16 [[TMP6]], 0 + // UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP7]], i16 0, i16 [[TMP6]] + // UNSIGNED-NEXT: store i16 [[SATMIN]], i16* @suf, align 2 leonardchan wrote: > I'm assuming these checks are also a result of D82663? I don't think for the > padding case, we should need to do the compare and select if we're already > using the signed sat intrinsic. But I'm guessing it might make the > implementation more complicated by having to check for this. > > If this codegen comes from the `EmitFixedPointConversion` at the end of > `EmitFixedPointBinOp`, perhaps it might be worthwhile adding a parameter in > `EmitFixedPointConversion` to indicate that we shouldn't emit this. I think > there's some cases in D82663 also where we might not need to do these checks > afterwards with other operations like with: > > ``` > // UNSIGNED-NEXT: [[TMP25:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[TMP22]], > i16 32767) > // UNSIGNED-NEXT: [[TMP26:%.*]] = icmp slt i16 [[TMP25]], 0 > // UNSIGNED-NEXT: [[SATMIN2:%.*]] = select i1 [[TMP26]], i16 0, i16 [[TMP25]] > // UNSIGNED-NEXT: store i16 [[SATMIN2]], i16* @suf, align 2 > ``` Yes, this is correct. And it is also correct that in the case of shift (and other operations) it is not necessary. It was just more elegant to make the common semantic signed and the result semantic unsigned and get the clamp automatically. I think the alternative is to handle the signedness of ops separate from the semantic during codegen and then emit a clamp manually per-operation instead of relying on the result conversion. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D83294/new/ https://reviews.llvm.org/D83294 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D83294: [Fixed Point] Add codegen for fixed-point shifts.
leonardchan added inline comments. Comment at: clang/lib/CodeGen/CGExprScalar.cpp:3857 + + // TODO: This misses out on the sanitizer check below. + if (Ops.isFixedPointOp()) I don't suppose you could file a bug for this and CC me on it so we can remember to do this sometime after this lands? Comment at: clang/test/Frontend/fixed_point_compound.c:384 + // CHECK-NEXT:[[TMP4:%.*]] = load i16, i16* @suf, align 2 + // CHECK-NEXT:[[TMP5:%.*]] = trunc i32 [[TMP3]] to i16 + // SIGNED-NEXT: [[TMP6:%.*]] = call i16 @llvm.ushl.sat.i16(i16 [[TMP4]], i16 [[TMP5]]) ebevhan wrote: > leonardchan wrote: > > This seems very unlikely, but if `i` in this case was a value at least > > 2^16, the upper half would be cut off and we'd potentially shift by an > > improper amount for some values of `i` when we should actually clamp to the > > max value. We should probably still find the common semantics for both > > sides if we're doing a shift. > If the value is so large to be cut off by that truncation then the value is > greater than the bitwidth, which is UB. So I don't think it's an issue. Ah right I forgot that. Comment at: clang/test/Frontend/fixed_point_compound.c:388-390 + // UNSIGNED-NEXT: [[TMP7:%.*]] = icmp slt i16 [[TMP6]], 0 + // UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP7]], i16 0, i16 [[TMP6]] + // UNSIGNED-NEXT: store i16 [[SATMIN]], i16* @suf, align 2 I'm assuming these checks are also a result of D82663? I don't think for the padding case, we should need to do the compare and select if we're already using the signed sat intrinsic. But I'm guessing it might make the implementation more complicated by having to check for this. If this codegen comes from the `EmitFixedPointConversion` at the end of `EmitFixedPointBinOp`, perhaps it might be worthwhile adding a parameter in `EmitFixedPointConversion` to indicate that we shouldn't emit this. I think there's some cases in D82663 also where we might not need to do these checks afterwards with other operations like with: ``` // UNSIGNED-NEXT: [[TMP25:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[TMP22]], i16 32767) // UNSIGNED-NEXT: [[TMP26:%.*]] = icmp slt i16 [[TMP25]], 0 // UNSIGNED-NEXT: [[SATMIN2:%.*]] = select i1 [[TMP26]], i16 0, i16 [[TMP25]] // UNSIGNED-NEXT: store i16 [[SATMIN2]], i16* @suf, align 2 ``` Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D83294/new/ https://reviews.llvm.org/D83294 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D83294: [Fixed Point] Add codegen for fixed-point shifts.
ebevhan marked an inline comment as done. ebevhan added inline comments. Comment at: clang/lib/CodeGen/CGExprScalar.cpp:3603-3604 auto ResultFixedSema = Ctx.getFixedPointSemantics(ResultTy); - auto CommonFixedSema = LHSFixedSema.getCommonSemantics(RHSFixedSema, true); + auto CommonFixedSema = LHSFixedSema.getCommonSemantics( + IsShift ? LHSFixedSema : RHSFixedSema, true); leonardchan wrote: > Could this instead be: > > ``` > auto CommonFixedSema = IsShift ? LHSFixedSema : > LHSFixedSema.getCommonSemantics(RHSFixedSema, true); > ``` > > In theory, yes, but I'm sort of piggybacking off of D82663, and for the signedness to be correct we need to get the 'common' semantic even in the shift case. Comment at: clang/test/Frontend/fixed_point_compound.c:384 + // CHECK-NEXT:[[TMP4:%.*]] = load i16, i16* @suf, align 2 + // CHECK-NEXT:[[TMP5:%.*]] = trunc i32 [[TMP3]] to i16 + // SIGNED-NEXT: [[TMP6:%.*]] = call i16 @llvm.ushl.sat.i16(i16 [[TMP4]], i16 [[TMP5]]) leonardchan wrote: > This seems very unlikely, but if `i` in this case was a value at least 2^16, > the upper half would be cut off and we'd potentially shift by an improper > amount for some values of `i` when we should actually clamp to the max value. > We should probably still find the common semantics for both sides if we're > doing a shift. If the value is so large to be cut off by that truncation then the value is greater than the bitwidth, which is UB. So I don't think it's an issue. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D83294/new/ https://reviews.llvm.org/D83294 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D83294: [Fixed Point] Add codegen for fixed-point shifts.
leonardchan added inline comments. Comment at: clang/lib/CodeGen/CGExprScalar.cpp:3603-3604 auto ResultFixedSema = Ctx.getFixedPointSemantics(ResultTy); - auto CommonFixedSema = LHSFixedSema.getCommonSemantics(RHSFixedSema, true); + auto CommonFixedSema = LHSFixedSema.getCommonSemantics( + IsShift ? LHSFixedSema : RHSFixedSema, true); Could this instead be: ``` auto CommonFixedSema = IsShift ? LHSFixedSema : LHSFixedSema.getCommonSemantics(RHSFixedSema, true); ``` Comment at: clang/test/Frontend/fixed_point_compound.c:384 + // CHECK-NEXT:[[TMP4:%.*]] = load i16, i16* @suf, align 2 + // CHECK-NEXT:[[TMP5:%.*]] = trunc i32 [[TMP3]] to i16 + // SIGNED-NEXT: [[TMP6:%.*]] = call i16 @llvm.ushl.sat.i16(i16 [[TMP4]], i16 [[TMP5]]) This seems very unlikely, but if `i` in this case was a value at least 2^16, the upper half would be cut off and we'd potentially shift by an improper amount for some values of `i` when we should actually clamp to the max value. We should probably still find the common semantics for both sides if we're doing a shift. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D83294/new/ https://reviews.llvm.org/D83294 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D83294: [Fixed Point] Add codegen for fixed-point shifts.
ebevhan created this revision. ebevhan added reviewers: rjmccall, leonardchan, bjope. Herald added a project: clang. Herald added a subscriber: cfe-commits. This patch adds codegen to Clang for fixed-point shift operations. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D83294 Files: clang/lib/CodeGen/CGExprScalar.cpp clang/test/Frontend/fixed_point_compound.c clang/test/Frontend/fixed_point_shift.c Index: clang/test/Frontend/fixed_point_shift.c === --- clang/test/Frontend/fixed_point_shift.c +++ clang/test/Frontend/fixed_point_shift.c @@ -35,3 +35,361 @@ _Sat unsigned _Accum sua_const2 = (_Sat unsigned _Accum)128.0uk << 10; // SIGNED-DAG: @sua_const2 = {{.*}}global i32 -1 // UNSIGNED-DAG: @sua_const2 = {{.*}}global i32 2147483647 + +// CHECK-LABEL: @SignedLeftShift( +void SignedLeftShift() { + short _Accum sa; + _Accum a; + long _Accum la; + + short _Fract sf; + _Fract f; + long _Fract lf; + + int i; + unsigned u; + + // CHECK: [[TMP0:%.*]] = load i16, i16* %sa, align 2 + // CHECK-NEXT:[[TMP1:%.*]] = load i32, i32* %i, align 4 + // CHECK-NEXT:[[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 + // CHECK-NEXT:[[TMP3:%.*]] = shl i16 [[TMP0]], [[TMP2]] + // CHECK-NEXT:store i16 [[TMP3]], i16* %sa, align 2 + sa = sa << i; + + // CHECK: [[TMP4:%.*]] = load i32, i32* %a, align 4 + // CHECK-NEXT:[[TMP5:%.*]] = load i32, i32* %i, align 4 + // CHECK-NEXT:[[TMP6:%.*]] = shl i32 [[TMP4]], [[TMP5]] + // CHECK-NEXT:store i32 [[TMP6]], i32* %a, align 4 + a = a << i; + + // CHECK: [[TMP7:%.*]] = load i64, i64* %la, align 8 + // CHECK-NEXT:[[TMP8:%.*]] = load i32, i32* %i, align 4 + // CHECK-NEXT:[[TMP9:%.*]] = zext i32 [[TMP8]] to i64 + // CHECK-NEXT:[[TMP10:%.*]] = shl i64 [[TMP7]], [[TMP9]] + // CHECK-NEXT:store i64 [[TMP10]], i64* %la, align 8 + la = la << i; + + // CHECK: [[TMP11:%.*]] = load i8, i8* %sf, align 1 + // CHECK-NEXT:[[TMP12:%.*]] = load i32, i32* %i, align 4 + // CHECK-NEXT:[[TMP13:%.*]] = trunc i32 [[TMP12]] to i8 + // CHECK-NEXT:[[TMP14:%.*]] = shl i8 [[TMP11]], [[TMP13]] + // CHECK-NEXT:store i8 [[TMP14]], i8* %sf, align 1 + sf = sf << i; + + // CHECK: [[TMP15:%.*]] = load i16, i16* %f, align 2 + // CHECK-NEXT:[[TMP16:%.*]] = load i32, i32* %i, align 4 + // CHECK-NEXT:[[TMP17:%.*]] = trunc i32 [[TMP16]] to i16 + // CHECK-NEXT:[[TMP18:%.*]] = shl i16 [[TMP15]], [[TMP17]] + // CHECK-NEXT:store i16 [[TMP18]], i16* %f, align 2 + f = f << i; + + // CHECK: [[TMP19:%.*]] = load i32, i32* %lf, align 4 + // CHECK-NEXT:[[TMP20:%.*]] = load i32, i32* %i, align 4 + // CHECK-NEXT:[[TMP21:%.*]] = shl i32 [[TMP19]], [[TMP20]] + // CHECK-NEXT:store i32 [[TMP21]], i32* %lf, align 4 + lf = lf << i; + + // CHECK: [[TMP22:%.*]] = load i32, i32* %a, align 4 + // CHECK-NEXT:[[TMP23:%.*]] = load i32, i32* %u, align 4 + // CHECK-NEXT:[[TMP24:%.*]] = shl i32 [[TMP22]], [[TMP23]] + // CHECK-NEXT:store i32 [[TMP24]], i32* %a, align 4 + a = a << u; + + // CHECK: [[TMP25:%.*]] = load i16, i16* %f, align 2 + // CHECK-NEXT:[[TMP26:%.*]] = load i32, i32* %u, align 4 + // CHECK-NEXT:[[TMP27:%.*]] = trunc i32 [[TMP26]] to i16 + // CHECK-NEXT:[[TMP28:%.*]] = shl i16 [[TMP25]], [[TMP27]] + // CHECK-NEXT:store i16 [[TMP28]], i16* %f, align 2 + f = f << u; +} + +// CHECK-LABEL: @UnsignedLeftShift( +void UnsignedLeftShift() { + unsigned short _Accum usa; + unsigned _Accum ua; + unsigned long _Accum ula; + + unsigned short _Fract usf; + unsigned _Fract uf; + unsigned long _Fract ulf; + + int i; + unsigned u; + + // CHECK: [[TMP0:%.*]] = load i16, i16* %usa, align 2 + // CHECK-NEXT:[[TMP1:%.*]] = load i32, i32* %i, align 4 + // CHECK-NEXT:[[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 + // CHECK-NEXT:[[TMP3:%.*]] = shl i16 [[TMP0]], [[TMP2]] + // CHECK-NEXT:store i16 [[TMP3]], i16* %usa, align 2 + usa = usa << i; + + // CHECK: [[TMP4:%.*]] = load i32, i32* %ua, align 4 + // CHECK-NEXT:[[TMP5:%.*]] = load i32, i32* %i, align 4 + // CHECK-NEXT:[[TMP6:%.*]] = shl i32 [[TMP4]], [[TMP5]] + // CHECK-NEXT:store i32 [[TMP6]], i32* %ua, align 4 + ua = ua << i; + + // CHECK: [[TMP7:%.*]] = load i64, i64* %ula, align 8 + // CHECK-NEXT:[[TMP8:%.*]] = load i32, i32* %i, align 4 + // CHECK-NEXT:[[TMP9:%.*]] = zext i32 [[TMP8]] to i64 + // CHECK-NEXT:[[TMP10:%.*]] = shl i64 [[TMP7]], [[TMP9]] + // CHECK-NEXT:store i64 [[TMP10]], i64* %ula, align 8 + ula = ula << i; + + // CHECK: [[TMP11:%.*]] = load i8, i8* %usf, align 1 + // CHECK-NEXT:[[TMP12:%.*]] = load i32, i32* %i, align 4 + // CHECK-NEXT:[[TMP13:%.*]] = trunc i32 [[TMP12]] to i8 + // CHECK-NEXT:[[TMP14:%.*]] = shl i8 [[TMP11]], [[TMP13]] + // CHECK-NEXT:store i8