[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-01-24 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: rjmccall, bjope, ebevhan.
leonardchan added a project: clang.
leonardchan added a parent revision: D46917: [Fixed Point Arithmetic] 
Comparison and Unary Operations for Fixed Point Types.

This patch implements fixed point comparisons with other fixed point types and 
integers. This also provides constant expression evaluation for them.


Repository:
  rC Clang

https://reviews.llvm.org/D57219

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/test/Frontend/fixed_point_comparisons.c

Index: clang/test/Frontend/fixed_point_comparisons.c
===
--- /dev/null
+++ clang/test/Frontend/fixed_point_comparisons.c
@@ -0,0 +1,344 @@
+// 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
+
+// Fixed point against other fixed point
+_Bool b_eq_true = 2.5hk == 2.5uhk;  // CHECK-DAG: @b_eq_true  = {{.*}}global i8 1, align 1
+_Bool b_eq_false = 2.5hk == 2.4uhk; // CHECK-DAG: @b_eq_false = {{.*}}global i8 0, align 1
+
+_Bool b_ne_true = 2.5hk != 2.4uhk;  // CHECK-DAG: @b_ne_true  = {{.*}}global i8 1, align 1
+_Bool b_ne_false = 2.5hk != 2.5uhk; // CHECK-DAG: @b_ne_false = {{.*}}global i8 0, align 1
+
+_Bool b_lt_true = 2.5hk < 2.75uhk; // CHECK-DAG: @b_lt_true  = {{.*}}global i8 1, align 1
+_Bool b_lt_false = 2.5hk < 2.5uhk; // CHECK-DAG: @b_lt_false = {{.*}}global i8 0, align 1
+
+_Bool b_le_true = 2.5hk <= 2.75uhk; // CHECK-DAG: @b_le_true  = {{.*}}global i8 1, align 1
+_Bool b_le_true2 = 2.5hk <= 2.5uhk; // CHECK-DAG: @b_le_true2 = {{.*}}global i8 1, align 1
+_Bool b_le_false = 2.5hk <= 2.4uhk; // CHECK-DAG: @b_le_false = {{.*}}global i8 0, align 1
+
+_Bool b_gt_true = 2.75hk > 2.5uhk;   // CHECK-DAG: @b_gt_true  = {{.*}}global i8 1, align 1
+_Bool b_gt_false = 2.75hk > 2.75uhk; // CHECK-DAG: @b_gt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ge_true = 2.75hk >= 2.5uhk;   // CHECK-DAG: @b_ge_true  = {{.*}}global i8 1, align 1
+_Bool b_ge_true2 = 2.75hk >= 2.75uhk; // CHECK-DAG: @b_ge_true2 = {{.*}}global i8 1, align 1
+_Bool b_ge_false = 2.5hk >= 2.75uhk;  // CHECK-DAG: @b_ge_false = {{.*}}global i8 0, align 1
+
+// Fixed point against int
+_Bool b_ieq_true = 2.0hk == 2;  // CHECK-DAG: @b_ieq_true  = {{.*}}global i8 1, align 1
+_Bool b_ieq_false = 2.0hk == 3; // CHECK-DAG: @b_ieq_false = {{.*}}global i8 0, align 1
+
+_Bool b_ine_true = 2.0hk != 3;  // CHECK-DAG: @b_ine_true  = {{.*}}global i8 1, align 1
+_Bool b_ine_false = 2.0hk != 2; // CHECK-DAG: @b_ine_false = {{.*}}global i8 0, align 1
+
+_Bool b_ilt_true = 2.0hk < 3;  // CHECK-DAG: @b_ilt_true  = {{.*}}global i8 1, align 1
+_Bool b_ilt_false = 2.0hk < 2; // CHECK-DAG: @b_ilt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ile_true = 2.0hk <= 3;  // CHECK-DAG: @b_ile_true  = {{.*}}global i8 1, align 1
+_Bool b_ile_true2 = 2.0hk <= 2; // CHECK-DAG: @b_ile_true2 = {{.*}}global i8 1, align 1
+_Bool b_ile_false = 2.0hk <= 1; // CHECK-DAG: @b_ile_false = {{.*}}global i8 0, align 1
+
+_Bool b_igt_true = 2.0hk > 1;  // CHECK-DAG: @b_igt_true  = {{.*}}global i8 1, align 1
+_Bool b_igt_false = 2.0hk > 2; // CHECK-DAG: @b_igt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ige_true = 2.0hk >= 1;  // CHECK-DAG: @b_ige_true  = {{.*}}global i8 1, align 1
+_Bool b_ige_true2 = 2.0hk >= 2; // CHECK-DAG: @b_ige_true2 = {{.*}}global i8 1, align 1
+_Bool b_ige_false = 2.0hk >= 3; // CHECK-DAG: @b_ige_false = {{.*}}global i8 0, align 1
+
+// Different signage
+// Since we can have different precisions, non powers of 2 fractions may have
+// different actual values when being compared.
+_Bool b_sne_true = 2.6hk != 2.6uhk;
+// SIGNED-DAG:   @b_sne_true = {{.*}}global i8 1, align 1
+// UNSIGNED-DAG: @b_sne_true = {{.*}}global i8 0, align 1
+
+_Bool b_seq_true = 2.0hk == 2u;  // CHECK-DAG: @b_seq_true  = {{.*}}global i8 1, align 1
+_Bool b_seq_true2 = 2.0uhk == 2; // CHECK-DAG: @b_seq_true2 = {{.*}}global i8 1, align 1
+
+void TestComparisons() {
+  short _Accum sa;
+  _Accum a;
+  unsigned short _Accum usa;
+  unsigned _Accum ua;
+
+  // Each of these should be a fixed point conversion followed by the actual
+  // comparison operation.
+  sa == a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+  // CHECK-NEXT: {{.*}} = icmp eq i32 [[UPSCALE_A]], [[A2]]
+
+  sa != a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+  // CHECK-NEXT: {{.*}}

[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-01-25 Thread Bevin Hansson via Phabricator via cfe-commits
ebevhan added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:141
+ (RHSType->isFixedPointType() &&
+  LHSType->isFixedPointOrIntegerType());
+}

Can't it just be `LHSType->isFixedPointType() || RHSType->isFixedPointType()`?

I don't think there are cases where one is a fixed-point type and the other is 
not an integer or another fixed-point type, so if one is fixed-point then you 
already know it's a fixed-point operation.



Comment at: clang/test/Frontend/fixed_point_comparisons.c:56
+
+void TestComparisons() {
+  short _Accum sa;

Missing saturating and saturating/non-saturating comparisons. I'd like to see 
the differences between unsigned padding and not there, if there are any.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-01-25 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:141
+ (RHSType->isFixedPointType() &&
+  LHSType->isFixedPointOrIntegerType());
+}

ebevhan wrote:
> Can't it just be `LHSType->isFixedPointType() || RHSType->isFixedPointType()`?
> 
> I don't think there are cases where one is a fixed-point type and the other 
> is not an integer or another fixed-point type, so if one is fixed-point then 
> you already know it's a fixed-point operation.
Ah you're right.



Comment at: clang/test/Frontend/fixed_point_comparisons.c:56
+
+void TestComparisons() {
+  short _Accum sa;

ebevhan wrote:
> Missing saturating and saturating/non-saturating comparisons. I'd like to see 
> the differences between unsigned padding and not there, if there are any.
I don't think there should be since we compare by converting to a common type 
that should fit both operands, but it does help to have tests that also confirm 
this. Added some saturation cases under `TestSaturationComparisons`.

As for padding, `TestSaturationComparisons` have cases comparing signed with 
unsigned types, and there are other cases in `TestComparisons` and 
`TestIntComparisons` that deal with unsigned comparisons. The way the lit tests 
are organized, lines marked with `CHECK` mean that those lines are produced for 
both the padding and no padding cases whereas `SIGNED` or `UNSIGNED` are 
produced exclusively for no padding and padding cases, respectively.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-01-25 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 183629.
leonardchan marked 4 inline comments as done.

Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/test/Frontend/fixed_point_comparisons.c

Index: clang/test/Frontend/fixed_point_comparisons.c
===
--- /dev/null
+++ clang/test/Frontend/fixed_point_comparisons.c
@@ -0,0 +1,368 @@
+// 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
+
+// Fixed point against other fixed point
+_Bool b_eq_true = 2.5hk == 2.5uhk;  // CHECK-DAG: @b_eq_true  = {{.*}}global i8 1, align 1
+_Bool b_eq_false = 2.5hk == 2.4uhk; // CHECK-DAG: @b_eq_false = {{.*}}global i8 0, align 1
+
+_Bool b_ne_true = 2.5hk != 2.4uhk;  // CHECK-DAG: @b_ne_true  = {{.*}}global i8 1, align 1
+_Bool b_ne_false = 2.5hk != 2.5uhk; // CHECK-DAG: @b_ne_false = {{.*}}global i8 0, align 1
+
+_Bool b_lt_true = 2.5hk < 2.75uhk; // CHECK-DAG: @b_lt_true  = {{.*}}global i8 1, align 1
+_Bool b_lt_false = 2.5hk < 2.5uhk; // CHECK-DAG: @b_lt_false = {{.*}}global i8 0, align 1
+
+_Bool b_le_true = 2.5hk <= 2.75uhk; // CHECK-DAG: @b_le_true  = {{.*}}global i8 1, align 1
+_Bool b_le_true2 = 2.5hk <= 2.5uhk; // CHECK-DAG: @b_le_true2 = {{.*}}global i8 1, align 1
+_Bool b_le_false = 2.5hk <= 2.4uhk; // CHECK-DAG: @b_le_false = {{.*}}global i8 0, align 1
+
+_Bool b_gt_true = 2.75hk > 2.5uhk;   // CHECK-DAG: @b_gt_true  = {{.*}}global i8 1, align 1
+_Bool b_gt_false = 2.75hk > 2.75uhk; // CHECK-DAG: @b_gt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ge_true = 2.75hk >= 2.5uhk;   // CHECK-DAG: @b_ge_true  = {{.*}}global i8 1, align 1
+_Bool b_ge_true2 = 2.75hk >= 2.75uhk; // CHECK-DAG: @b_ge_true2 = {{.*}}global i8 1, align 1
+_Bool b_ge_false = 2.5hk >= 2.75uhk;  // CHECK-DAG: @b_ge_false = {{.*}}global i8 0, align 1
+
+// Fixed point against int
+_Bool b_ieq_true = 2.0hk == 2;  // CHECK-DAG: @b_ieq_true  = {{.*}}global i8 1, align 1
+_Bool b_ieq_false = 2.0hk == 3; // CHECK-DAG: @b_ieq_false = {{.*}}global i8 0, align 1
+
+_Bool b_ine_true = 2.0hk != 3;  // CHECK-DAG: @b_ine_true  = {{.*}}global i8 1, align 1
+_Bool b_ine_false = 2.0hk != 2; // CHECK-DAG: @b_ine_false = {{.*}}global i8 0, align 1
+
+_Bool b_ilt_true = 2.0hk < 3;  // CHECK-DAG: @b_ilt_true  = {{.*}}global i8 1, align 1
+_Bool b_ilt_false = 2.0hk < 2; // CHECK-DAG: @b_ilt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ile_true = 2.0hk <= 3;  // CHECK-DAG: @b_ile_true  = {{.*}}global i8 1, align 1
+_Bool b_ile_true2 = 2.0hk <= 2; // CHECK-DAG: @b_ile_true2 = {{.*}}global i8 1, align 1
+_Bool b_ile_false = 2.0hk <= 1; // CHECK-DAG: @b_ile_false = {{.*}}global i8 0, align 1
+
+_Bool b_igt_true = 2.0hk > 1;  // CHECK-DAG: @b_igt_true  = {{.*}}global i8 1, align 1
+_Bool b_igt_false = 2.0hk > 2; // CHECK-DAG: @b_igt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ige_true = 2.0hk >= 1;  // CHECK-DAG: @b_ige_true  = {{.*}}global i8 1, align 1
+_Bool b_ige_true2 = 2.0hk >= 2; // CHECK-DAG: @b_ige_true2 = {{.*}}global i8 1, align 1
+_Bool b_ige_false = 2.0hk >= 3; // CHECK-DAG: @b_ige_false = {{.*}}global i8 0, align 1
+
+// Different signage
+// Since we can have different precisions, non powers of 2 fractions may have
+// different actual values when being compared.
+_Bool b_sne_true = 2.6hk != 2.6uhk;
+// SIGNED-DAG:   @b_sne_true = {{.*}}global i8 1, align 1
+// UNSIGNED-DAG: @b_sne_true = {{.*}}global i8 0, align 1
+
+_Bool b_seq_true = 2.0hk == 2u;  // CHECK-DAG: @b_seq_true  = {{.*}}global i8 1, align 1
+_Bool b_seq_true2 = 2.0uhk == 2; // CHECK-DAG: @b_seq_true2 = {{.*}}global i8 1, align 1
+
+void TestComparisons() {
+  short _Accum sa;
+  _Accum a;
+  unsigned short _Accum usa;
+  unsigned _Accum ua;
+
+  // Each of these should be a fixed point conversion followed by the actual
+  // comparison operation.
+  sa == a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+  // CHECK-NEXT: {{.*}} = icmp eq i32 [[UPSCALE_A]], [[A2]]
+
+  sa != a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+  // CHECK-NEXT: {{.*}} = icmp ne i32 [[UPSCALE_A]], [[A2]]
+
+  sa > a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+ 

[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-01-28 Thread Bevin Hansson via Phabricator via cfe-commits
ebevhan added inline comments.



Comment at: clang/test/Frontend/fixed_point_comparisons.c:56
+
+void TestComparisons() {
+  short _Accum sa;

leonardchan wrote:
> ebevhan wrote:
> > Missing saturating and saturating/non-saturating comparisons. I'd like to 
> > see the differences between unsigned padding and not there, if there are 
> > any.
> I don't think there should be since we compare by converting to a common type 
> that should fit both operands, but it does help to have tests that also 
> confirm this. Added some saturation cases under `TestSaturationComparisons`.
> 
> As for padding, `TestSaturationComparisons` have cases comparing signed with 
> unsigned types, and there are other cases in `TestComparisons` and 
> `TestIntComparisons` that deal with unsigned comparisons. The way the lit 
> tests are organized, lines marked with `CHECK` mean that those lines are 
> produced for both the padding and no padding cases whereas `SIGNED` or 
> `UNSIGNED` are produced exclusively for no padding and padding cases, 
> respectively.
There is a difference between saturating signed types and saturating unsigned 
types, though; the common type of two of the same saturating unsigned type is 
one bit less due to padding.

Unless there is something in the type commoning that I've missed?


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-01-28 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 183980.
leonardchan marked 2 inline comments as done.

Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/test/Frontend/fixed_point_comparisons.c

Index: clang/test/Frontend/fixed_point_comparisons.c
===
--- /dev/null
+++ clang/test/Frontend/fixed_point_comparisons.c
@@ -0,0 +1,378 @@
+// 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
+
+// Fixed point against other fixed point
+_Bool b_eq_true = 2.5hk == 2.5uhk;  // CHECK-DAG: @b_eq_true  = {{.*}}global i8 1, align 1
+_Bool b_eq_false = 2.5hk == 2.4uhk; // CHECK-DAG: @b_eq_false = {{.*}}global i8 0, align 1
+
+_Bool b_ne_true = 2.5hk != 2.4uhk;  // CHECK-DAG: @b_ne_true  = {{.*}}global i8 1, align 1
+_Bool b_ne_false = 2.5hk != 2.5uhk; // CHECK-DAG: @b_ne_false = {{.*}}global i8 0, align 1
+
+_Bool b_lt_true = 2.5hk < 2.75uhk; // CHECK-DAG: @b_lt_true  = {{.*}}global i8 1, align 1
+_Bool b_lt_false = 2.5hk < 2.5uhk; // CHECK-DAG: @b_lt_false = {{.*}}global i8 0, align 1
+
+_Bool b_le_true = 2.5hk <= 2.75uhk; // CHECK-DAG: @b_le_true  = {{.*}}global i8 1, align 1
+_Bool b_le_true2 = 2.5hk <= 2.5uhk; // CHECK-DAG: @b_le_true2 = {{.*}}global i8 1, align 1
+_Bool b_le_false = 2.5hk <= 2.4uhk; // CHECK-DAG: @b_le_false = {{.*}}global i8 0, align 1
+
+_Bool b_gt_true = 2.75hk > 2.5uhk;   // CHECK-DAG: @b_gt_true  = {{.*}}global i8 1, align 1
+_Bool b_gt_false = 2.75hk > 2.75uhk; // CHECK-DAG: @b_gt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ge_true = 2.75hk >= 2.5uhk;   // CHECK-DAG: @b_ge_true  = {{.*}}global i8 1, align 1
+_Bool b_ge_true2 = 2.75hk >= 2.75uhk; // CHECK-DAG: @b_ge_true2 = {{.*}}global i8 1, align 1
+_Bool b_ge_false = 2.5hk >= 2.75uhk;  // CHECK-DAG: @b_ge_false = {{.*}}global i8 0, align 1
+
+// Fixed point against int
+_Bool b_ieq_true = 2.0hk == 2;  // CHECK-DAG: @b_ieq_true  = {{.*}}global i8 1, align 1
+_Bool b_ieq_false = 2.0hk == 3; // CHECK-DAG: @b_ieq_false = {{.*}}global i8 0, align 1
+
+_Bool b_ine_true = 2.0hk != 3;  // CHECK-DAG: @b_ine_true  = {{.*}}global i8 1, align 1
+_Bool b_ine_false = 2.0hk != 2; // CHECK-DAG: @b_ine_false = {{.*}}global i8 0, align 1
+
+_Bool b_ilt_true = 2.0hk < 3;  // CHECK-DAG: @b_ilt_true  = {{.*}}global i8 1, align 1
+_Bool b_ilt_false = 2.0hk < 2; // CHECK-DAG: @b_ilt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ile_true = 2.0hk <= 3;  // CHECK-DAG: @b_ile_true  = {{.*}}global i8 1, align 1
+_Bool b_ile_true2 = 2.0hk <= 2; // CHECK-DAG: @b_ile_true2 = {{.*}}global i8 1, align 1
+_Bool b_ile_false = 2.0hk <= 1; // CHECK-DAG: @b_ile_false = {{.*}}global i8 0, align 1
+
+_Bool b_igt_true = 2.0hk > 1;  // CHECK-DAG: @b_igt_true  = {{.*}}global i8 1, align 1
+_Bool b_igt_false = 2.0hk > 2; // CHECK-DAG: @b_igt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ige_true = 2.0hk >= 1;  // CHECK-DAG: @b_ige_true  = {{.*}}global i8 1, align 1
+_Bool b_ige_true2 = 2.0hk >= 2; // CHECK-DAG: @b_ige_true2 = {{.*}}global i8 1, align 1
+_Bool b_ige_false = 2.0hk >= 3; // CHECK-DAG: @b_ige_false = {{.*}}global i8 0, align 1
+
+// Different signage
+// Since we can have different precisions, non powers of 2 fractions may have
+// different actual values when being compared.
+_Bool b_sne_true = 2.6hk != 2.6uhk;
+// SIGNED-DAG:   @b_sne_true = {{.*}}global i8 1, align 1
+// UNSIGNED-DAG: @b_sne_true = {{.*}}global i8 0, align 1
+
+_Bool b_seq_true = 2.0hk == 2u;  // CHECK-DAG: @b_seq_true  = {{.*}}global i8 1, align 1
+_Bool b_seq_true2 = 2.0uhk == 2; // CHECK-DAG: @b_seq_true2 = {{.*}}global i8 1, align 1
+
+void TestComparisons() {
+  short _Accum sa;
+  _Accum a;
+  unsigned short _Accum usa;
+  unsigned _Accum ua;
+
+  // Each of these should be a fixed point conversion followed by the actual
+  // comparison operation.
+  sa == a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+  // CHECK-NEXT: {{.*}} = icmp eq i32 [[UPSCALE_A]], [[A2]]
+
+  sa != a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+  // CHECK-NEXT: {{.*}} = icmp ne i32 [[UPSCALE_A]], [[A2]]
+
+  sa > a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+ 

[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-01-28 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added inline comments.



Comment at: clang/test/Frontend/fixed_point_comparisons.c:56
+
+void TestComparisons() {
+  short _Accum sa;

ebevhan wrote:
> leonardchan wrote:
> > ebevhan wrote:
> > > Missing saturating and saturating/non-saturating comparisons. I'd like to 
> > > see the differences between unsigned padding and not there, if there are 
> > > any.
> > I don't think there should be since we compare by converting to a common 
> > type that should fit both operands, but it does help to have tests that 
> > also confirm this. Added some saturation cases under 
> > `TestSaturationComparisons`.
> > 
> > As for padding, `TestSaturationComparisons` have cases comparing signed 
> > with unsigned types, and there are other cases in `TestComparisons` and 
> > `TestIntComparisons` that deal with unsigned comparisons. The way the lit 
> > tests are organized, lines marked with `CHECK` mean that those lines are 
> > produced for both the padding and no padding cases whereas `SIGNED` or 
> > `UNSIGNED` are produced exclusively for no padding and padding cases, 
> > respectively.
> There is a difference between saturating signed types and saturating unsigned 
> types, though; the common type of two of the same saturating unsigned type is 
> one bit less due to padding.
> 
> Unless there is something in the type commoning that I've missed?
You're right. It's just that when comparing values, we care about padding and 
not saturation since we aren't "writing" a value, so a comparison between a 
`_Sat short _Accum` and `_Sat unsigned short _Accum` should be the same as one 
for a `short _Accum` and `unsigned short _Accum`. With unsigned padding, both 
operations should not result in any resizing/scaling since they're already the 
same size and scale.

Added a test case for this under `TestSaturationComparisons`.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-01-30 Thread Bjorn Pettersson via Phabricator via cfe-commits
bjope added inline comments.



Comment at: clang/test/Frontend/fixed_point_comparisons.c:2
+// 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
+

I think it is easier to understand the checks if you for example use 
UNPADDED/PADDED (or STUDDED/PADDED or something like that) instead of 
SIGNED/UNSIGNED.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-01-31 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:3444
   case BO_NE:
+return Builder.CreateICmpNE(FullLHS, FullRHS);
+  case BO_Mul:

Are padding bits guaranteed zero or unspecified?  Or are we just not really 
supporting padding bits all the way to IRGen at this time?


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-01-31 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 184612.
leonardchan marked 3 inline comments as done.

Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/test/Frontend/fixed_point_comparisons.c

Index: clang/test/Frontend/fixed_point_comparisons.c
===
--- /dev/null
+++ clang/test/Frontend/fixed_point_comparisons.c
@@ -0,0 +1,378 @@
+// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNPADDED
+// 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,PADDED
+
+// Fixed point against other fixed point
+_Bool b_eq_true = 2.5hk == 2.5uhk;  // CHECK-DAG: @b_eq_true  = {{.*}}global i8 1, align 1
+_Bool b_eq_false = 2.5hk == 2.4uhk; // CHECK-DAG: @b_eq_false = {{.*}}global i8 0, align 1
+
+_Bool b_ne_true = 2.5hk != 2.4uhk;  // CHECK-DAG: @b_ne_true  = {{.*}}global i8 1, align 1
+_Bool b_ne_false = 2.5hk != 2.5uhk; // CHECK-DAG: @b_ne_false = {{.*}}global i8 0, align 1
+
+_Bool b_lt_true = 2.5hk < 2.75uhk; // CHECK-DAG: @b_lt_true  = {{.*}}global i8 1, align 1
+_Bool b_lt_false = 2.5hk < 2.5uhk; // CHECK-DAG: @b_lt_false = {{.*}}global i8 0, align 1
+
+_Bool b_le_true = 2.5hk <= 2.75uhk; // CHECK-DAG: @b_le_true  = {{.*}}global i8 1, align 1
+_Bool b_le_true2 = 2.5hk <= 2.5uhk; // CHECK-DAG: @b_le_true2 = {{.*}}global i8 1, align 1
+_Bool b_le_false = 2.5hk <= 2.4uhk; // CHECK-DAG: @b_le_false = {{.*}}global i8 0, align 1
+
+_Bool b_gt_true = 2.75hk > 2.5uhk;   // CHECK-DAG: @b_gt_true  = {{.*}}global i8 1, align 1
+_Bool b_gt_false = 2.75hk > 2.75uhk; // CHECK-DAG: @b_gt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ge_true = 2.75hk >= 2.5uhk;   // CHECK-DAG: @b_ge_true  = {{.*}}global i8 1, align 1
+_Bool b_ge_true2 = 2.75hk >= 2.75uhk; // CHECK-DAG: @b_ge_true2 = {{.*}}global i8 1, align 1
+_Bool b_ge_false = 2.5hk >= 2.75uhk;  // CHECK-DAG: @b_ge_false = {{.*}}global i8 0, align 1
+
+// Fixed point against int
+_Bool b_ieq_true = 2.0hk == 2;  // CHECK-DAG: @b_ieq_true  = {{.*}}global i8 1, align 1
+_Bool b_ieq_false = 2.0hk == 3; // CHECK-DAG: @b_ieq_false = {{.*}}global i8 0, align 1
+
+_Bool b_ine_true = 2.0hk != 3;  // CHECK-DAG: @b_ine_true  = {{.*}}global i8 1, align 1
+_Bool b_ine_false = 2.0hk != 2; // CHECK-DAG: @b_ine_false = {{.*}}global i8 0, align 1
+
+_Bool b_ilt_true = 2.0hk < 3;  // CHECK-DAG: @b_ilt_true  = {{.*}}global i8 1, align 1
+_Bool b_ilt_false = 2.0hk < 2; // CHECK-DAG: @b_ilt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ile_true = 2.0hk <= 3;  // CHECK-DAG: @b_ile_true  = {{.*}}global i8 1, align 1
+_Bool b_ile_true2 = 2.0hk <= 2; // CHECK-DAG: @b_ile_true2 = {{.*}}global i8 1, align 1
+_Bool b_ile_false = 2.0hk <= 1; // CHECK-DAG: @b_ile_false = {{.*}}global i8 0, align 1
+
+_Bool b_igt_true = 2.0hk > 1;  // CHECK-DAG: @b_igt_true  = {{.*}}global i8 1, align 1
+_Bool b_igt_false = 2.0hk > 2; // CHECK-DAG: @b_igt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ige_true = 2.0hk >= 1;  // CHECK-DAG: @b_ige_true  = {{.*}}global i8 1, align 1
+_Bool b_ige_true2 = 2.0hk >= 2; // CHECK-DAG: @b_ige_true2 = {{.*}}global i8 1, align 1
+_Bool b_ige_false = 2.0hk >= 3; // CHECK-DAG: @b_ige_false = {{.*}}global i8 0, align 1
+
+// Different signage
+// Since we can have different precisions, non powers of 2 fractions may have
+// different actual values when being compared.
+_Bool b_sne_true = 2.6hk != 2.6uhk;
+// UNPADDED-DAG:   @b_sne_true = {{.*}}global i8 1, align 1
+// PADDED-DAG: @b_sne_true = {{.*}}global i8 0, align 1
+
+_Bool b_seq_true = 2.0hk == 2u;  // CHECK-DAG: @b_seq_true  = {{.*}}global i8 1, align 1
+_Bool b_seq_true2 = 2.0uhk == 2; // CHECK-DAG: @b_seq_true2 = {{.*}}global i8 1, align 1
+
+void TestComparisons() {
+  short _Accum sa;
+  _Accum a;
+  unsigned short _Accum usa;
+  unsigned _Accum ua;
+
+  // Each of these should be a fixed point conversion followed by the actual
+  // comparison operation.
+  sa == a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+  // CHECK-NEXT: {{.*}} = icmp eq i32 [[UPSCALE_A]], [[A2]]
+
+  sa != a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+  // CHECK-NEXT: {{.*}} = icmp ne i32 [[UPSCALE_A]], [[A2]]
+
+  sa > a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+ 

[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-01-31 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:3444
   case BO_NE:
+return Builder.CreateICmpNE(FullLHS, FullRHS);
+  case BO_Mul:

rjmccall wrote:
> Are padding bits guaranteed zero or unspecified?  Or are we just not really 
> supporting padding bits all the way to IRGen at this time?
I believe the consensus was leaving them unspecified, so operations that can 
cause overflow into them would result in undefined behavior.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-01-31 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:3444
   case BO_NE:
+return Builder.CreateICmpNE(FullLHS, FullRHS);
+  case BO_Mul:

leonardchan wrote:
> rjmccall wrote:
> > Are padding bits guaranteed zero or unspecified?  Or are we just not really 
> > supporting padding bits all the way to IRGen at this time?
> I believe the consensus was leaving them unspecified, so operations that can 
> cause overflow into them would result in undefined behavior.
If I'm understanding you correctly, you're saying that (1) we are assuming that 
inputs are zero-padded and (2) we are taking advantage of the 
non-saturating-overflow-is-UB rule to avoid clearing the padding bits after 
arithmetic.  That's actually what I meant by "guaranteed zero", so we have our 
labels reversed, but at least we understand each other now.

(I suppose you're thinking of this as "unspecified" because non-saturating 
arithmetic can leave an unspecified value there.  I think of this as a 
"guarantee" because it's basically a representational invariant: it's a 
precondition for correctness that the bit is zero, and all operations guarantee 
that the bit will be zero in their well-defined cases (but overflow is not 
well-defined).  Just a difference in perspective, I guess.)

Is this written down somewhere?  Are there targets that use the opposite ABI 
rule that we might need to support someday?

At any rate, I think it's worth adding a short comment here explaining why it's 
okay to do a normal comparison despite the possibility of padding bits.  Along 
those lines, is there any value in communicating to the backend that 
padded-unsigned comparisons could reasonably be done with either a signed or 
unsigned comparison?  Are there interesting targets where one or the other is 
cheaper?


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-02-01 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 184886.
leonardchan marked an inline comment as done.

Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/test/Frontend/fixed_point_comparisons.c

Index: clang/test/Frontend/fixed_point_comparisons.c
===
--- /dev/null
+++ clang/test/Frontend/fixed_point_comparisons.c
@@ -0,0 +1,378 @@
+// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNPADDED
+// 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,PADDED
+
+// Fixed point against other fixed point
+_Bool b_eq_true = 2.5hk == 2.5uhk;  // CHECK-DAG: @b_eq_true  = {{.*}}global i8 1, align 1
+_Bool b_eq_false = 2.5hk == 2.4uhk; // CHECK-DAG: @b_eq_false = {{.*}}global i8 0, align 1
+
+_Bool b_ne_true = 2.5hk != 2.4uhk;  // CHECK-DAG: @b_ne_true  = {{.*}}global i8 1, align 1
+_Bool b_ne_false = 2.5hk != 2.5uhk; // CHECK-DAG: @b_ne_false = {{.*}}global i8 0, align 1
+
+_Bool b_lt_true = 2.5hk < 2.75uhk; // CHECK-DAG: @b_lt_true  = {{.*}}global i8 1, align 1
+_Bool b_lt_false = 2.5hk < 2.5uhk; // CHECK-DAG: @b_lt_false = {{.*}}global i8 0, align 1
+
+_Bool b_le_true = 2.5hk <= 2.75uhk; // CHECK-DAG: @b_le_true  = {{.*}}global i8 1, align 1
+_Bool b_le_true2 = 2.5hk <= 2.5uhk; // CHECK-DAG: @b_le_true2 = {{.*}}global i8 1, align 1
+_Bool b_le_false = 2.5hk <= 2.4uhk; // CHECK-DAG: @b_le_false = {{.*}}global i8 0, align 1
+
+_Bool b_gt_true = 2.75hk > 2.5uhk;   // CHECK-DAG: @b_gt_true  = {{.*}}global i8 1, align 1
+_Bool b_gt_false = 2.75hk > 2.75uhk; // CHECK-DAG: @b_gt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ge_true = 2.75hk >= 2.5uhk;   // CHECK-DAG: @b_ge_true  = {{.*}}global i8 1, align 1
+_Bool b_ge_true2 = 2.75hk >= 2.75uhk; // CHECK-DAG: @b_ge_true2 = {{.*}}global i8 1, align 1
+_Bool b_ge_false = 2.5hk >= 2.75uhk;  // CHECK-DAG: @b_ge_false = {{.*}}global i8 0, align 1
+
+// Fixed point against int
+_Bool b_ieq_true = 2.0hk == 2;  // CHECK-DAG: @b_ieq_true  = {{.*}}global i8 1, align 1
+_Bool b_ieq_false = 2.0hk == 3; // CHECK-DAG: @b_ieq_false = {{.*}}global i8 0, align 1
+
+_Bool b_ine_true = 2.0hk != 3;  // CHECK-DAG: @b_ine_true  = {{.*}}global i8 1, align 1
+_Bool b_ine_false = 2.0hk != 2; // CHECK-DAG: @b_ine_false = {{.*}}global i8 0, align 1
+
+_Bool b_ilt_true = 2.0hk < 3;  // CHECK-DAG: @b_ilt_true  = {{.*}}global i8 1, align 1
+_Bool b_ilt_false = 2.0hk < 2; // CHECK-DAG: @b_ilt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ile_true = 2.0hk <= 3;  // CHECK-DAG: @b_ile_true  = {{.*}}global i8 1, align 1
+_Bool b_ile_true2 = 2.0hk <= 2; // CHECK-DAG: @b_ile_true2 = {{.*}}global i8 1, align 1
+_Bool b_ile_false = 2.0hk <= 1; // CHECK-DAG: @b_ile_false = {{.*}}global i8 0, align 1
+
+_Bool b_igt_true = 2.0hk > 1;  // CHECK-DAG: @b_igt_true  = {{.*}}global i8 1, align 1
+_Bool b_igt_false = 2.0hk > 2; // CHECK-DAG: @b_igt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ige_true = 2.0hk >= 1;  // CHECK-DAG: @b_ige_true  = {{.*}}global i8 1, align 1
+_Bool b_ige_true2 = 2.0hk >= 2; // CHECK-DAG: @b_ige_true2 = {{.*}}global i8 1, align 1
+_Bool b_ige_false = 2.0hk >= 3; // CHECK-DAG: @b_ige_false = {{.*}}global i8 0, align 1
+
+// Different signage
+// Since we can have different precisions, non powers of 2 fractions may have
+// different actual values when being compared.
+_Bool b_sne_true = 2.6hk != 2.6uhk;
+// UNPADDED-DAG:   @b_sne_true = {{.*}}global i8 1, align 1
+// PADDED-DAG: @b_sne_true = {{.*}}global i8 0, align 1
+
+_Bool b_seq_true = 2.0hk == 2u;  // CHECK-DAG: @b_seq_true  = {{.*}}global i8 1, align 1
+_Bool b_seq_true2 = 2.0uhk == 2; // CHECK-DAG: @b_seq_true2 = {{.*}}global i8 1, align 1
+
+void TestComparisons() {
+  short _Accum sa;
+  _Accum a;
+  unsigned short _Accum usa;
+  unsigned _Accum ua;
+
+  // Each of these should be a fixed point conversion followed by the actual
+  // comparison operation.
+  sa == a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+  // CHECK-NEXT: {{.*}} = icmp eq i32 [[UPSCALE_A]], [[A2]]
+
+  sa != a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+  // CHECK-NEXT: {{.*}} = icmp ne i32 [[UPSCALE_A]], [[A2]]
+
+  sa > a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+ 

[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-02-01 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:3444
   case BO_NE:
+return Builder.CreateICmpNE(FullLHS, FullRHS);
+  case BO_Mul:

rjmccall wrote:
> leonardchan wrote:
> > rjmccall wrote:
> > > Are padding bits guaranteed zero or unspecified?  Or are we just not 
> > > really supporting padding bits all the way to IRGen at this time?
> > I believe the consensus was leaving them unspecified, so operations that 
> > can cause overflow into them would result in undefined behavior.
> If I'm understanding you correctly, you're saying that (1) we are assuming 
> that inputs are zero-padded and (2) we are taking advantage of the 
> non-saturating-overflow-is-UB rule to avoid clearing the padding bits after 
> arithmetic.  That's actually what I meant by "guaranteed zero", so we have 
> our labels reversed, but at least we understand each other now.
> 
> (I suppose you're thinking of this as "unspecified" because non-saturating 
> arithmetic can leave an unspecified value there.  I think of this as a 
> "guarantee" because it's basically a representational invariant: it's a 
> precondition for correctness that the bit is zero, and all operations 
> guarantee that the bit will be zero in their well-defined cases (but overflow 
> is not well-defined).  Just a difference in perspective, I guess.)
> 
> Is this written down somewhere?  Are there targets that use the opposite ABI 
> rule that we might need to support someday?
> 
> At any rate, I think it's worth adding a short comment here explaining why 
> it's okay to do a normal comparison despite the possibility of padding bits.  
> Along those lines, is there any value in communicating to the backend that 
> padded-unsigned comparisons could reasonably be done with either a signed or 
> unsigned comparison?  Are there interesting targets where one or the other is 
> cheaper?
Yes. We assume inputs are zero padded, and that non-saturating overflow is 
undefined so we do not need to clear the padding after writing a new value. 
Sorry for the misunderstanding. I see what you mean by guaranteed zero.

Overflow in general is controlled by the `FX_FRACT_OVERFLOW` and 
`FX_ACCUM_OVERFLOW` pragmas, where if these are set to `DEFAULT`, operations 
that can overflow with these types is undefined according to the standard 
(4.1.3). In terms of padding bits, clause 6.2.6.3 mentions that the values of 
padding bits are "unspecified". I imagine this means that we can assume the 
value to be whatever we want it to, so we can assume that these values are a 
guaranteed zero.

I believe @ebevhan requested this being added since his downstream 
implementation used padding to match the scales of signed and unsigned types, 
so he may be able to offer more information on targets with different ABIs. We 
don't plan to use any special hardware, so we're following the "typical desktop 
processor" layout that uses the whole underlying int and no padding (mentioned 
in Annex 3).

In the same section, the standard also mentions types for other targets that 
may have padding, so there could be some value in indicating to the backend 
that for these particular targets, this part of the operand is padding, so 
select an appropriate operation that performs a comparison on this size type. 
But I don't know much about these processors and would just be guessing at how 
they work.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-02-04 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:3444
   case BO_NE:
+return Builder.CreateICmpNE(FullLHS, FullRHS);
+  case BO_Mul:

leonardchan wrote:
> rjmccall wrote:
> > leonardchan wrote:
> > > rjmccall wrote:
> > > > Are padding bits guaranteed zero or unspecified?  Or are we just not 
> > > > really supporting padding bits all the way to IRGen at this time?
> > > I believe the consensus was leaving them unspecified, so operations that 
> > > can cause overflow into them would result in undefined behavior.
> > If I'm understanding you correctly, you're saying that (1) we are assuming 
> > that inputs are zero-padded and (2) we are taking advantage of the 
> > non-saturating-overflow-is-UB rule to avoid clearing the padding bits after 
> > arithmetic.  That's actually what I meant by "guaranteed zero", so we have 
> > our labels reversed, but at least we understand each other now.
> > 
> > (I suppose you're thinking of this as "unspecified" because non-saturating 
> > arithmetic can leave an unspecified value there.  I think of this as a 
> > "guarantee" because it's basically a representational invariant: it's a 
> > precondition for correctness that the bit is zero, and all operations 
> > guarantee that the bit will be zero in their well-defined cases (but 
> > overflow is not well-defined).  Just a difference in perspective, I guess.)
> > 
> > Is this written down somewhere?  Are there targets that use the opposite 
> > ABI rule that we might need to support someday?
> > 
> > At any rate, I think it's worth adding a short comment here explaining why 
> > it's okay to do a normal comparison despite the possibility of padding 
> > bits.  Along those lines, is there any value in communicating to the 
> > backend that padded-unsigned comparisons could reasonably be done with 
> > either a signed or unsigned comparison?  Are there interesting targets 
> > where one or the other is cheaper?
> Yes. We assume inputs are zero padded, and that non-saturating overflow is 
> undefined so we do not need to clear the padding after writing a new value. 
> Sorry for the misunderstanding. I see what you mean by guaranteed zero.
> 
> Overflow in general is controlled by the `FX_FRACT_OVERFLOW` and 
> `FX_ACCUM_OVERFLOW` pragmas, where if these are set to `DEFAULT`, operations 
> that can overflow with these types is undefined according to the standard 
> (4.1.3). In terms of padding bits, clause 6.2.6.3 mentions that the values of 
> padding bits are "unspecified". I imagine this means that we can assume the 
> value to be whatever we want it to, so we can assume that these values are a 
> guaranteed zero.
> 
> I believe @ebevhan requested this being added since his downstream 
> implementation used padding to match the scales of signed and unsigned types, 
> so he may be able to offer more information on targets with different ABIs. 
> We don't plan to use any special hardware, so we're following the "typical 
> desktop processor" layout that uses the whole underlying int and no padding 
> (mentioned in Annex 3).
> 
> In the same section, the standard also mentions types for other targets that 
> may have padding, so there could be some value in indicating to the backend 
> that for these particular targets, this part of the operand is padding, so 
> select an appropriate operation that performs a comparison on this size type. 
> But I don't know much about these processors and would just be guessing at 
> how they work.
Okay.  If we ever have a target that uses an ABI that (1) includes padding but 
(2) considers it to be "unspecified" in the sense of "it can validly be 
non-zero", we'll have to change this code, but I agree it's the right move to 
not preemptively generalize to cover that possibility.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-02-07 Thread Bevin Hansson via Phabricator via cfe-commits
ebevhan added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:3444
   case BO_NE:
+return Builder.CreateICmpNE(FullLHS, FullRHS);
+  case BO_Mul:

rjmccall wrote:
> leonardchan wrote:
> > rjmccall wrote:
> > > Are padding bits guaranteed zero or unspecified?  Or are we just not 
> > > really supporting padding bits all the way to IRGen at this time?
> > I believe the consensus was leaving them unspecified, so operations that 
> > can cause overflow into them would result in undefined behavior.
> If I'm understanding you correctly, you're saying that (1) we are assuming 
> that inputs are zero-padded and (2) we are taking advantage of the 
> non-saturating-overflow-is-UB rule to avoid clearing the padding bits after 
> arithmetic.  That's actually what I meant by "guaranteed zero", so we have 
> our labels reversed, but at least we understand each other now.
> 
> (I suppose you're thinking of this as "unspecified" because non-saturating 
> arithmetic can leave an unspecified value there.  I think of this as a 
> "guarantee" because it's basically a representational invariant: it's a 
> precondition for correctness that the bit is zero, and all operations 
> guarantee that the bit will be zero in their well-defined cases (but overflow 
> is not well-defined).  Just a difference in perspective, I guess.)
> 
> Is this written down somewhere?  Are there targets that use the opposite ABI 
> rule that we might need to support someday?
> 
> At any rate, I think it's worth adding a short comment here explaining why 
> it's okay to do a normal comparison despite the possibility of padding bits.  
> Along those lines, is there any value in communicating to the backend that 
> padded-unsigned comparisons could reasonably be done with either a signed or 
> unsigned comparison?  Are there interesting targets where one or the other is 
> cheaper?
> Is this written down somewhere? Are there targets that use the opposite ABI 
> rule that we might need to support someday?

What exactly do you mean by 'opposite'? That the padding is cleared after every 
operation?

It was (and still is) the case in our downstream implementation that all 
unsigned operations explicitly clear the padding bit after every operation, 
leading to defined behavior on overflow for such types.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:3444
   case BO_NE:
+return Builder.CreateICmpNE(FullLHS, FullRHS);
+  case BO_Mul:

rjmccall wrote:
> leonardchan wrote:
> > ebevhan wrote:
> > > rjmccall wrote:
> > > > leonardchan wrote:
> > > > > rjmccall wrote:
> > > > > > Are padding bits guaranteed zero or unspecified?  Or are we just 
> > > > > > not really supporting padding bits all the way to IRGen at this 
> > > > > > time?
> > > > > I believe the consensus was leaving them unspecified, so operations 
> > > > > that can cause overflow into them would result in undefined behavior.
> > > > If I'm understanding you correctly, you're saying that (1) we are 
> > > > assuming that inputs are zero-padded and (2) we are taking advantage of 
> > > > the non-saturating-overflow-is-UB rule to avoid clearing the padding 
> > > > bits after arithmetic.  That's actually what I meant by "guaranteed 
> > > > zero", so we have our labels reversed, but at least we understand each 
> > > > other now.
> > > > 
> > > > (I suppose you're thinking of this as "unspecified" because 
> > > > non-saturating arithmetic can leave an unspecified value there.  I 
> > > > think of this as a "guarantee" because it's basically a 
> > > > representational invariant: it's a precondition for correctness that 
> > > > the bit is zero, and all operations guarantee that the bit will be zero 
> > > > in their well-defined cases (but overflow is not well-defined).  Just a 
> > > > difference in perspective, I guess.)
> > > > 
> > > > Is this written down somewhere?  Are there targets that use the 
> > > > opposite ABI rule that we might need to support someday?
> > > > 
> > > > At any rate, I think it's worth adding a short comment here explaining 
> > > > why it's okay to do a normal comparison despite the possibility of 
> > > > padding bits.  Along those lines, is there any value in communicating 
> > > > to the backend that padded-unsigned comparisons could reasonably be 
> > > > done with either a signed or unsigned comparison?  Are there 
> > > > interesting targets where one or the other is cheaper?
> > > > Is this written down somewhere? Are there targets that use the opposite 
> > > > ABI rule that we might need to support someday?
> > > 
> > > What exactly do you mean by 'opposite'? That the padding is cleared after 
> > > every operation?
> > > 
> > > It was (and still is) the case in our downstream implementation that all 
> > > unsigned operations explicitly clear the padding bit after every 
> > > operation, leading to defined behavior on overflow for such types.
> > Yes. We assume inputs

[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-02-07 Thread Bevin Hansson via Phabricator via cfe-commits
ebevhan added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:3444
   case BO_NE:
+return Builder.CreateICmpNE(FullLHS, FullRHS);
+  case BO_Mul:

ebevhan wrote:
> rjmccall wrote:
> > leonardchan wrote:
> > > ebevhan wrote:
> > > > rjmccall wrote:
> > > > > leonardchan wrote:
> > > > > > rjmccall wrote:
> > > > > > > Are padding bits guaranteed zero or unspecified?  Or are we just 
> > > > > > > not really supporting padding bits all the way to IRGen at this 
> > > > > > > time?
> > > > > > I believe the consensus was leaving them unspecified, so operations 
> > > > > > that can cause overflow into them would result in undefined 
> > > > > > behavior.
> > > > > If I'm understanding you correctly, you're saying that (1) we are 
> > > > > assuming that inputs are zero-padded and (2) we are taking advantage 
> > > > > of the non-saturating-overflow-is-UB rule to avoid clearing the 
> > > > > padding bits after arithmetic.  That's actually what I meant by 
> > > > > "guaranteed zero", so we have our labels reversed, but at least we 
> > > > > understand each other now.
> > > > > 
> > > > > (I suppose you're thinking of this as "unspecified" because 
> > > > > non-saturating arithmetic can leave an unspecified value there.  I 
> > > > > think of this as a "guarantee" because it's basically a 
> > > > > representational invariant: it's a precondition for correctness that 
> > > > > the bit is zero, and all operations guarantee that the bit will be 
> > > > > zero in their well-defined cases (but overflow is not well-defined).  
> > > > > Just a difference in perspective, I guess.)
> > > > > 
> > > > > Is this written down somewhere?  Are there targets that use the 
> > > > > opposite ABI rule that we might need to support someday?
> > > > > 
> > > > > At any rate, I think it's worth adding a short comment here 
> > > > > explaining why it's okay to do a normal comparison despite the 
> > > > > possibility of padding bits.  Along those lines, is there any value 
> > > > > in communicating to the backend that padded-unsigned comparisons 
> > > > > could reasonably be done with either a signed or unsigned comparison? 
> > > > >  Are there interesting targets where one or the other is cheaper?
> > > > > Is this written down somewhere? Are there targets that use the 
> > > > > opposite ABI rule that we might need to support someday?
> > > > 
> > > > What exactly do you mean by 'opposite'? That the padding is cleared 
> > > > after every operation?
> > > > 
> > > > It was (and still is) the case in our downstream implementation that 
> > > > all unsigned operations explicitly clear the padding bit after every 
> > > > operation, leading to defined behavior on overflow for such types.
> > > Yes. We assume inputs are zero padded, and that non-saturating overflow 
> > > is undefined so we do not need to clear the padding after writing a new 
> > > value. Sorry for the misunderstanding. I see what you mean by guaranteed 
> > > zero.
> > > 
> > > Overflow in general is controlled by the `FX_FRACT_OVERFLOW` and 
> > > `FX_ACCUM_OVERFLOW` pragmas, where if these are set to `DEFAULT`, 
> > > operations that can overflow with these types is undefined according to 
> > > the standard (4.1.3). In terms of padding bits, clause 6.2.6.3 mentions 
> > > that the values of padding bits are "unspecified". I imagine this means 
> > > that we can assume the value to be whatever we want it to, so we can 
> > > assume that these values are a guaranteed zero.
> > > 
> > > I believe @ebevhan requested this being added since his downstream 
> > > implementation used padding to match the scales of signed and unsigned 
> > > types, so he may be able to offer more information on targets with 
> > > different ABIs. We don't plan to use any special hardware, so we're 
> > > following the "typical desktop processor" layout that uses the whole 
> > > underlying int and no padding (mentioned in Annex 3).
> > > 
> > > In the same section, the standard also mentions types for other targets 
> > > that may have padding, so there could be some value in indicating to the 
> > > backend that for these particular targets, this part of the operand is 
> > > padding, so select an appropriate operation that performs a comparison on 
> > > this size type. But I don't know much about these processors and would 
> > > just be guessing at how they work.
> > Okay.  If we ever have a target that uses an ABI that (1) includes padding 
> > but (2) considers it to be "unspecified" in the sense of "it can validly be 
> > non-zero", we'll have to change this code, but I agree it's the right move 
> > to not preemptively generalize to cover that possibility.
> To clarify on our use case, we have the padding on the unsigned types mostly 
> to harmonize the behavior of unsigned and signed types. The only real native 
> support is for signed types, but if the unsigned types are padded and then 
> use signed operations t

[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-02-07 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:3444
   case BO_NE:
+return Builder.CreateICmpNE(FullLHS, FullRHS);
+  case BO_Mul:

ebevhan wrote:
> ebevhan wrote:
> > rjmccall wrote:
> > > leonardchan wrote:
> > > > ebevhan wrote:
> > > > > rjmccall wrote:
> > > > > > leonardchan wrote:
> > > > > > > rjmccall wrote:
> > > > > > > > Are padding bits guaranteed zero or unspecified?  Or are we 
> > > > > > > > just not really supporting padding bits all the way to IRGen at 
> > > > > > > > this time?
> > > > > > > I believe the consensus was leaving them unspecified, so 
> > > > > > > operations that can cause overflow into them would result in 
> > > > > > > undefined behavior.
> > > > > > If I'm understanding you correctly, you're saying that (1) we are 
> > > > > > assuming that inputs are zero-padded and (2) we are taking 
> > > > > > advantage of the non-saturating-overflow-is-UB rule to avoid 
> > > > > > clearing the padding bits after arithmetic.  That's actually what I 
> > > > > > meant by "guaranteed zero", so we have our labels reversed, but at 
> > > > > > least we understand each other now.
> > > > > > 
> > > > > > (I suppose you're thinking of this as "unspecified" because 
> > > > > > non-saturating arithmetic can leave an unspecified value there.  I 
> > > > > > think of this as a "guarantee" because it's basically a 
> > > > > > representational invariant: it's a precondition for correctness 
> > > > > > that the bit is zero, and all operations guarantee that the bit 
> > > > > > will be zero in their well-defined cases (but overflow is not 
> > > > > > well-defined).  Just a difference in perspective, I guess.)
> > > > > > 
> > > > > > Is this written down somewhere?  Are there targets that use the 
> > > > > > opposite ABI rule that we might need to support someday?
> > > > > > 
> > > > > > At any rate, I think it's worth adding a short comment here 
> > > > > > explaining why it's okay to do a normal comparison despite the 
> > > > > > possibility of padding bits.  Along those lines, is there any value 
> > > > > > in communicating to the backend that padded-unsigned comparisons 
> > > > > > could reasonably be done with either a signed or unsigned 
> > > > > > comparison?  Are there interesting targets where one or the other 
> > > > > > is cheaper?
> > > > > > Is this written down somewhere? Are there targets that use the 
> > > > > > opposite ABI rule that we might need to support someday?
> > > > > 
> > > > > What exactly do you mean by 'opposite'? That the padding is cleared 
> > > > > after every operation?
> > > > > 
> > > > > It was (and still is) the case in our downstream implementation that 
> > > > > all unsigned operations explicitly clear the padding bit after every 
> > > > > operation, leading to defined behavior on overflow for such types.
> > > > Yes. We assume inputs are zero padded, and that non-saturating overflow 
> > > > is undefined so we do not need to clear the padding after writing a new 
> > > > value. Sorry for the misunderstanding. I see what you mean by 
> > > > guaranteed zero.
> > > > 
> > > > Overflow in general is controlled by the `FX_FRACT_OVERFLOW` and 
> > > > `FX_ACCUM_OVERFLOW` pragmas, where if these are set to `DEFAULT`, 
> > > > operations that can overflow with these types is undefined according to 
> > > > the standard (4.1.3). In terms of padding bits, clause 6.2.6.3 mentions 
> > > > that the values of padding bits are "unspecified". I imagine this means 
> > > > that we can assume the value to be whatever we want it to, so we can 
> > > > assume that these values are a guaranteed zero.
> > > > 
> > > > I believe @ebevhan requested this being added since his downstream 
> > > > implementation used padding to match the scales of signed and unsigned 
> > > > types, so he may be able to offer more information on targets with 
> > > > different ABIs. We don't plan to use any special hardware, so we're 
> > > > following the "typical desktop processor" layout that uses the whole 
> > > > underlying int and no padding (mentioned in Annex 3).
> > > > 
> > > > In the same section, the standard also mentions types for other targets 
> > > > that may have padding, so there could be some value in indicating to 
> > > > the backend that for these particular targets, this part of the operand 
> > > > is padding, so select an appropriate operation that performs a 
> > > > comparison on this size type. But I don't know much about these 
> > > > processors and would just be guessing at how they work.
> > > Okay.  If we ever have a target that uses an ABI that (1) includes 
> > > padding but (2) considers it to be "unspecified" in the sense of "it can 
> > > validly be non-zero", we'll have to change this code, but I agree it's 
> > > the right move to not preemptively generalize to cover that possibility.
> > To clarify on our use case, we have the padding on the unsigned types 
> > mos

[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-02-21 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added a subscriber: bevinh.
leonardchan added a comment.
Herald added a subscriber: jdoerfert.

*ping* @bevinh @rjmccall @bjope Any other comments on this patch?


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-02-21 Thread John McCall via Phabricator via cfe-commits
rjmccall accepted this revision.
rjmccall added a comment.
This revision is now accepted and ready to land.

No, this LGTM.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57219: [Fixed Point Arithmetic] Fixed Point Comparisons

2019-02-21 Thread Leonard Chan via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC354621: [Fixed Point Arithmetic] Fixed Point Comparisons 
(authored by leonardchan, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D57219?vs=184886&id=187847#toc

Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57219/new/

https://reviews.llvm.org/D57219

Files:
  lib/AST/ExprConstant.cpp
  lib/CodeGen/CGExprScalar.cpp
  test/Frontend/fixed_point_comparisons.c

Index: test/Frontend/fixed_point_comparisons.c
===
--- test/Frontend/fixed_point_comparisons.c
+++ test/Frontend/fixed_point_comparisons.c
@@ -0,0 +1,378 @@
+// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNPADDED
+// 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,PADDED
+
+// Fixed point against other fixed point
+_Bool b_eq_true = 2.5hk == 2.5uhk;  // CHECK-DAG: @b_eq_true  = {{.*}}global i8 1, align 1
+_Bool b_eq_false = 2.5hk == 2.4uhk; // CHECK-DAG: @b_eq_false = {{.*}}global i8 0, align 1
+
+_Bool b_ne_true = 2.5hk != 2.4uhk;  // CHECK-DAG: @b_ne_true  = {{.*}}global i8 1, align 1
+_Bool b_ne_false = 2.5hk != 2.5uhk; // CHECK-DAG: @b_ne_false = {{.*}}global i8 0, align 1
+
+_Bool b_lt_true = 2.5hk < 2.75uhk; // CHECK-DAG: @b_lt_true  = {{.*}}global i8 1, align 1
+_Bool b_lt_false = 2.5hk < 2.5uhk; // CHECK-DAG: @b_lt_false = {{.*}}global i8 0, align 1
+
+_Bool b_le_true = 2.5hk <= 2.75uhk; // CHECK-DAG: @b_le_true  = {{.*}}global i8 1, align 1
+_Bool b_le_true2 = 2.5hk <= 2.5uhk; // CHECK-DAG: @b_le_true2 = {{.*}}global i8 1, align 1
+_Bool b_le_false = 2.5hk <= 2.4uhk; // CHECK-DAG: @b_le_false = {{.*}}global i8 0, align 1
+
+_Bool b_gt_true = 2.75hk > 2.5uhk;   // CHECK-DAG: @b_gt_true  = {{.*}}global i8 1, align 1
+_Bool b_gt_false = 2.75hk > 2.75uhk; // CHECK-DAG: @b_gt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ge_true = 2.75hk >= 2.5uhk;   // CHECK-DAG: @b_ge_true  = {{.*}}global i8 1, align 1
+_Bool b_ge_true2 = 2.75hk >= 2.75uhk; // CHECK-DAG: @b_ge_true2 = {{.*}}global i8 1, align 1
+_Bool b_ge_false = 2.5hk >= 2.75uhk;  // CHECK-DAG: @b_ge_false = {{.*}}global i8 0, align 1
+
+// Fixed point against int
+_Bool b_ieq_true = 2.0hk == 2;  // CHECK-DAG: @b_ieq_true  = {{.*}}global i8 1, align 1
+_Bool b_ieq_false = 2.0hk == 3; // CHECK-DAG: @b_ieq_false = {{.*}}global i8 0, align 1
+
+_Bool b_ine_true = 2.0hk != 3;  // CHECK-DAG: @b_ine_true  = {{.*}}global i8 1, align 1
+_Bool b_ine_false = 2.0hk != 2; // CHECK-DAG: @b_ine_false = {{.*}}global i8 0, align 1
+
+_Bool b_ilt_true = 2.0hk < 3;  // CHECK-DAG: @b_ilt_true  = {{.*}}global i8 1, align 1
+_Bool b_ilt_false = 2.0hk < 2; // CHECK-DAG: @b_ilt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ile_true = 2.0hk <= 3;  // CHECK-DAG: @b_ile_true  = {{.*}}global i8 1, align 1
+_Bool b_ile_true2 = 2.0hk <= 2; // CHECK-DAG: @b_ile_true2 = {{.*}}global i8 1, align 1
+_Bool b_ile_false = 2.0hk <= 1; // CHECK-DAG: @b_ile_false = {{.*}}global i8 0, align 1
+
+_Bool b_igt_true = 2.0hk > 1;  // CHECK-DAG: @b_igt_true  = {{.*}}global i8 1, align 1
+_Bool b_igt_false = 2.0hk > 2; // CHECK-DAG: @b_igt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ige_true = 2.0hk >= 1;  // CHECK-DAG: @b_ige_true  = {{.*}}global i8 1, align 1
+_Bool b_ige_true2 = 2.0hk >= 2; // CHECK-DAG: @b_ige_true2 = {{.*}}global i8 1, align 1
+_Bool b_ige_false = 2.0hk >= 3; // CHECK-DAG: @b_ige_false = {{.*}}global i8 0, align 1
+
+// Different signage
+// Since we can have different precisions, non powers of 2 fractions may have
+// different actual values when being compared.
+_Bool b_sne_true = 2.6hk != 2.6uhk;
+// UNPADDED-DAG:   @b_sne_true = {{.*}}global i8 1, align 1
+// PADDED-DAG: @b_sne_true = {{.*}}global i8 0, align 1
+
+_Bool b_seq_true = 2.0hk == 2u;  // CHECK-DAG: @b_seq_true  = {{.*}}global i8 1, align 1
+_Bool b_seq_true2 = 2.0uhk == 2; // CHECK-DAG: @b_seq_true2 = {{.*}}global i8 1, align 1
+
+void TestComparisons() {
+  short _Accum sa;
+  _Accum a;
+  unsigned short _Accum usa;
+  unsigned _Accum ua;
+
+  // Each of these should be a fixed point conversion followed by the actual
+  // comparison operation.
+  sa == a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+  // CHECK-NEXT: {{.*}} = icmp eq i32 [[UPSCALE_A]], [[A2]]
+
+  sa != a;
+  // CHECK:  [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+  // CHECK-NEXT: {