ebevhan updated this revision to Diff 275657.
ebevhan added a comment.

Rebased.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D82663

Files:
  clang/include/clang/Basic/FixedPoint.h
  clang/lib/Basic/FixedPoint.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/test/Frontend/fixed_point_add.c
  clang/test/Frontend/fixed_point_comparisons.c
  clang/test/Frontend/fixed_point_compound.c
  clang/test/Frontend/fixed_point_div.c
  clang/test/Frontend/fixed_point_mul.c
  clang/test/Frontend/fixed_point_sub.c
  clang/test/Frontend/fixed_point_unary.c

Index: clang/test/Frontend/fixed_point_unary.c
===================================================================
--- clang/test/Frontend/fixed_point_unary.c
+++ clang/test/Frontend/fixed_point_unary.c
@@ -68,28 +68,28 @@
 // CHECK:         [[TMP18:%.*]] = load i32, i32* @sua, align 4
 // SIGNED-NEXT:   [[TMP19:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[TMP18]], i32 65536)
 // SIGNED-NEXT:   store i32 [[TMP19]], i32* @sua, align 4
-// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i32 [[TMP18]] to i31
-// UNSIGNED-NEXT: [[TMP19:%.*]] = call i31 @llvm.uadd.sat.i31(i31 [[RESIZE]], i31 32768)
-// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i31 [[TMP19]] to i32
-// UNSIGNED-NEXT: store i32 [[RESIZE1]], i32* @sua, align 4
+// UNSIGNED-NEXT: [[TMP19:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[TMP18]], i32 32768)
+// UNSIGNED-NEXT: [[TMP20:%.*]] = icmp slt i32 [[TMP19]], 0
+// UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP20]], i32 0, i32 [[TMP19]]
+// UNSIGNED-NEXT: store i32 [[SATMIN]], i32* @sua, align 4
   sua++;
 
 // CHECK:         [[TMP20:%.*]] = load i16, i16* @susa, align 2
 // SIGNED-NEXT:   [[TMP21:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[TMP20]], i16 256)
 // SIGNED-NEXT:   store i16 [[TMP21]], i16* @susa, align 2
-// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i16 [[TMP20]] to i15
-// UNSIGNED-NEXT: [[TMP21:%.*]] = call i15 @llvm.uadd.sat.i15(i15 [[RESIZE2]], i15 128)
-// UNSIGNED-NEXT: [[RESIZE3:%.*]] = zext i15 [[TMP21]] to i16
-// UNSIGNED-NEXT: store i16 [[RESIZE3]], i16* @susa, align 2
+// UNSIGNED-NEXT: [[TMP22:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[TMP20]], i16 128)
+// UNSIGNED-NEXT: [[TMP23:%.*]] = icmp slt i16 [[TMP22]], 0
+// UNSIGNED-NEXT: [[SATMIN1:%.*]] = select i1 [[TMP23]], i16 0, i16 [[TMP22]]
+// UNSIGNED-NEXT: store i16 [[SATMIN1]], i16* @susa, align 2
   susa++;
 
 // CHECK:         [[TMP22:%.*]] = load i16, i16* @suf, align 2
 // SIGNED-NEXT:   [[TMP23:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[TMP22]], i16 -1)
 // SIGNED-NEXT:   store i16 [[TMP23]], i16* @suf, align 2
-// UNSIGNED-NEXT: [[RESIZE4:%.*]] = trunc i16 [[TMP22]] to i15
-// UNSIGNED-NEXT: [[TMP23:%.*]] = call i15 @llvm.uadd.sat.i15(i15 [[RESIZE4]], i15 -1)
-// UNSIGNED-NEXT: [[RESIZE5:%.*]] = zext i15 [[TMP23]] to i16
-// UNSIGNED-NEXT: store i16 [[RESIZE5]], i16* @suf, align 2
+// 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
   suf++;
 }
 
@@ -146,28 +146,28 @@
 // CHECK:         [[TMP18:%.*]] = load i32, i32* @sua, align 4
 // SIGNED-NEXT:   [[TMP19:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[TMP18]], i32 65536)
 // SIGNED-NEXT:   store i32 [[TMP19]], i32* @sua, align 4
-// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i32 [[TMP18]] to i31
-// UNSIGNED-NEXT: [[TMP19:%.*]] = call i31 @llvm.usub.sat.i31(i31 [[RESIZE]], i31 32768)
-// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i31 [[TMP19]] to i32
-// UNSIGNED-NEXT: store i32 [[RESIZE1]], i32* @sua, align 4
+// UNSIGNED-NEXT: [[TMP19:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[TMP18]], i32 32768)
+// UNSIGNED-NEXT: [[TMP20:%.*]] = icmp slt i32 [[TMP19]], 0
+// UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP20]], i32 0, i32 [[TMP19]]
+// UNSIGNED-NEXT: store i32 [[SATMIN]], i32* @sua, align 4
   sua--;
 
 // CHECK:         [[TMP20:%.*]] = load i16, i16* @susa, align 2
 // SIGNED-NEXT:   [[TMP21:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[TMP20]], i16 256)
 // SIGNED-NEXT:   store i16 [[TMP21]], i16* @susa, align 2
-// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i16 [[TMP20]] to i15
-// UNSIGNED-NEXT: [[TMP21:%.*]] = call i15 @llvm.usub.sat.i15(i15 [[RESIZE2]], i15 128)
-// UNSIGNED-NEXT: [[RESIZE3:%.*]] = zext i15 [[TMP21]] to i16
-// UNSIGNED-NEXT: store i16 [[RESIZE3]], i16* @susa, align 2
+// UNSIGNED-NEXT: [[TMP22:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[TMP20]], i16 128)
+// UNSIGNED-NEXT: [[TMP23:%.*]] = icmp slt i16 [[TMP22]], 0
+// UNSIGNED-NEXT: [[SATMIN1:%.*]] = select i1 [[TMP23]], i16 0, i16 [[TMP22]]
+// UNSIGNED-NEXT: store i16 [[SATMIN1]], i16* @susa, align 2
   susa--;
 
 // CHECK:         [[TMP22:%.*]] = load i16, i16* @suf, align 2
 // SIGNED-NEXT:   [[TMP23:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[TMP22]], i16 -1)
 // SIGNED-NEXT:   store i16 [[TMP23]], i16* @suf, align 2
-// UNSIGNED-NEXT: [[RESIZE4:%.*]] = trunc i16 [[TMP22]] to i15
-// UNSIGNED-NEXT: [[TMP23:%.*]] = call i15 @llvm.usub.sat.i15(i15 [[RESIZE4]], i15 -1)
-// UNSIGNED-NEXT: [[RESIZE5:%.*]] = zext i15 [[TMP23]] to i16
-// UNSIGNED-NEXT: store i16 [[RESIZE5]], i16* @suf, align 2
+// UNSIGNED-NEXT: [[TMP25:%.*]] = call i16 @llvm.ssub.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
   suf--;
 }
 
@@ -206,19 +206,19 @@
 // CHECK:         [[TMP12:%.*]] = load i16, i16* @susa, align 2
 // SIGNED-NEXT:   [[TMP13:%.*]] = call i16 @llvm.usub.sat.i16(i16 0, i16 [[TMP12]])
 // SIGNED-NEXT:   store i16 [[TMP13]], i16* @susa, align 2
-// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP12]] to i15
-// UNSIGNED-NEXT: [[TMP13:%.*]] = call i15 @llvm.usub.sat.i15(i15 0, i15 [[RESIZE]])
-// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i15 [[TMP13]] to i16
-// UNSIGNED-NEXT: store i16 [[RESIZE1]], i16* @susa, align 2
+// UNSIGNED-NEXT: [[TMP13:%.*]] = call i16 @llvm.ssub.sat.i16(i16 0, i16 [[TMP12]])
+// UNSIGNED-NEXT: [[TMP14:%.*]] = icmp slt i16 [[TMP13]], 0
+// UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP14]], i16 0, i16 [[TMP13]]
+// UNSIGNED-NEXT: store i16 [[SATMIN]], i16* @susa, align 2
   susa = -susa;
 
 // CHECK:         [[TMP14:%.*]] = load i16, i16* @suf, align 2
 // SIGNED-NEXT:   [[TMP15:%.*]] = call i16 @llvm.usub.sat.i16(i16 0, i16 [[TMP14]])
 // SIGNED-NEXT:   store i16 [[TMP15]], i16* @suf, align 2
-// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i16 [[TMP14]] to i15
-// UNSIGNED-NEXT: [[TMP15:%.*]] = call i15 @llvm.usub.sat.i15(i15 0, i15 [[RESIZE2]])
-// UNSIGNED-NEXT: [[RESIZE3:%.*]] = zext i15 [[TMP15]] to i16
-// UNSIGNED-NEXT: store i16 [[RESIZE3]], i16* @suf, align 2
+// UNSIGNED-NEXT: [[TMP16:%.*]] = call i16 @llvm.ssub.sat.i16(i16 0, i16 [[TMP14]])
+// UNSIGNED-NEXT: [[TMP17:%.*]] = icmp slt i16 [[TMP16]], 0
+// UNSIGNED-NEXT: [[SATMIN1:%.*]] = select i1 [[TMP17]], i16 0, i16 [[TMP16]]
+// UNSIGNED-NEXT: store i16 [[SATMIN1]], i16* @suf, align 2
   suf = -suf;
 }
 
Index: clang/test/Frontend/fixed_point_sub.c
===================================================================
--- clang/test/Frontend/fixed_point_sub.c
+++ clang/test/Frontend/fixed_point_sub.c
@@ -233,7 +233,8 @@
   // CHECK-NEXT: [[USA:%[a-z0-9]+]] = shl i24 [[USA_EXT]], 8
   // CHECK-NEXT: [[UF_EXT:%[a-z0-9]+]] = zext i16 [[UF]] to i24
   // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i24 [[USA]], [[UF_EXT]]
-  // CHECK-NEXT: [[RES:%[a-z0-9]+]] = lshr i24 [[SUM]], 8
+  // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = lshr i24 [[SUM]], 8
+  // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = ashr i24 [[SUM]], 8
   // CHECK-NEXT: [[RES_TRUNC:%[a-z0-9]+]] = trunc i24 [[RES]] to i16
   // CHECK-NEXT: store i16 [[RES_TRUNC]], i16* %usa, align 2
   usa = usa - uf;
@@ -292,11 +293,11 @@
   // SIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 8
   // SIGNED-NEXT: [[SUM:%[0-9]+]] = sub i40 [[USA_EXT]], [[I]]
   // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16
-  // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i39
-  // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i39
-  // UNSIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
-  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = sub i39 [[USA_EXT]], [[I]]
-  // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SUM]] to i16
+  // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i40
+  // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i40
+  // UNSIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 7
+  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = sub i40 [[USA_EXT]], [[I]]
+  // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16
   // CHECK-NEXT: store i16 [[RES]], i16* %usa, align 2
   usa = usa - ui;
 
@@ -354,11 +355,10 @@
   // CHECK-NEXT: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2
   // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.usub.sat.i16(i16 [[USA]], i16 [[USA_SAT]])
   // SIGNED-NEXT: store i16 [[SUM]], i16* %usa_sat, align 2
-  // UNSIGNED-NEXT: [[USA_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA]] to i15
-  // UNSIGNED-NEXT: [[USA_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA_SAT]] to i15
-  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.usub.sat.i15(i15 [[USA_TRUNC]], i15 [[USA_SAT_TRUNC]])
-  // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
-  // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %usa_sat, align 2
+  // UNSIGNED-NEXT: [[SUM:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[USA]], i16 [[USA_SAT]])
+  // UNSIGNED-NEXT: [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0
+  // UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]]
+  // UNSIGNED-NEXT: store i16 [[SATMIN]], i16* %usa_sat, align 2
   usa_sat = usa - usa_sat;
 
   // CHECK:      [[UA:%[0-9]+]] = load i32, i32* %ua, align 4
@@ -367,12 +367,12 @@
   // SIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i32 [[USA_EXT]], 8
   // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i32 @llvm.usub.sat.i32(i32 [[UA]], i32 [[USA]])
   // SIGNED-NEXT: store i32 [[SUM]], i32* %ua_sat, align 4
-  // UNSIGNED-NEXT: [[UA_TRUNC:%[a-z0-9]+]] = trunc i32 [[UA]] to i31
-  // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i31
-  // UNSIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i31 [[USA_EXT]], 8
-  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i31 @llvm.usub.sat.i31(i31 [[UA_TRUNC]], i31 [[USA]])
-  // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i31 [[SUM]] to i32
-  // UNSIGNED-NEXT: store i32 [[SUM_EXT]], i32* %ua_sat, align 4
+  // UNSIGNED-NEXT:    [[RESIZE:%.*]] = zext i16 [[USA]] to i32
+  // UNSIGNED-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+  // UNSIGNED-NEXT:    [[TMP9:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[UA]], i32 [[UPSCALE]])
+  // UNSIGNED-NEXT:    [[TMP10:%.*]] = icmp slt i32 [[TMP9]], 0
+  // UNSIGNED-NEXT:    [[SATMIN1:%.*]] = select i1 [[TMP10]], i32 0, i32 [[TMP9]]
+  // UNSIGNED-NEXT:    store i32 [[SATMIN1]], i32* %ua_sat, align 4
   ua_sat = ua - usa_sat;
 
   // CHECK:      [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2
@@ -407,11 +407,10 @@
   // CHECK-NEXT: [[UF_SAT2:%[0-9]+]] = load i16, i16* %uf_sat, align 2
   // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.usub.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]])
   // SIGNED-NEXT: store i16 [[SUM]], i16* %uf_sat, align 2
-  // UNSIGNED-NEXT: [[UF_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[UF_SAT]] to i15
-  // UNSIGNED-NEXT: [[UF_SAT_TRUNC2:%[a-z0-9]+]] = trunc i16 [[UF_SAT2]] to i15
-  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.usub.sat.i15(i15 [[UF_SAT_TRUNC]], i15 [[UF_SAT_TRUNC2]])
-  // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
-  // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %uf_sat, align 2
+  // UNSIGNED-NEXT:    [[SUM:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]])
+  // UNSIGNED-NEXT:    [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0
+  // UNSIGNED-NEXT:    [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]]
+  // UNSIGNED-NEXT:    store i16 [[SATMIN]], i16* %uf_sat, align 2
   uf_sat = uf_sat - uf_sat;
 
   // CHECK:      [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2
Index: clang/test/Frontend/fixed_point_mul.c
===================================================================
--- clang/test/Frontend/fixed_point_mul.c
+++ clang/test/Frontend/fixed_point_mul.c
@@ -207,7 +207,7 @@
   // CHECK:         [[TMP0:%.*]] = load i16, i16* %usa, align 2
   // CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* %usa, align 2
   // SIGNED-NEXT:   [[TMP2:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 8)
-  // UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
+  // UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
   // CHECK-NEXT:    store i16 [[TMP2]], i16* %usa, align 2
   usa = usa * usa;
 
@@ -216,7 +216,7 @@
   // CHECK-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP3]] to i32
   // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
   // SIGNED-NEXT:   [[TMP5:%.*]] = call i32 @llvm.umul.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 16)
-  // UNSIGNED-NEXT: [[TMP5:%.*]] = call i32 @llvm.umul.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 15)
+  // UNSIGNED-NEXT: [[TMP5:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 15)
   // CHECK-NEXT:    store i32 [[TMP5]], i32* %ua, align 4
   ua = usa * ua;
 
@@ -224,7 +224,7 @@
   // CHECK-NEXT:    [[TMP7:%.*]] = load i8, i8* %usf, align 1
   // CHECK-NEXT:    [[RESIZE1:%.*]] = zext i8 [[TMP7]] to i16
   // SIGNED-NEXT:   [[TMP8:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 8)
-  // UNSIGNED-NEXT: [[TMP8:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 7)
+  // UNSIGNED-NEXT: [[TMP8:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 7)
   // CHECK-NEXT:    store i16 [[TMP8]], i16* %usa, align 2
   usa = usa * usf;
 
@@ -234,8 +234,9 @@
   // CHECK-NEXT:    [[UPSCALE3:%.*]] = shl i24 [[RESIZE2]], 8
   // CHECK-NEXT:    [[RESIZE4:%.*]] = zext i16 [[TMP10]] to i24
   // SIGNED-NEXT:   [[TMP11:%.*]] = call i24 @llvm.umul.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 16)
-  // UNSIGNED-NEXT: [[TMP11:%.*]] = call i24 @llvm.umul.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 15)
-  // CHECK-NEXT:    [[DOWNSCALE:%.*]] = lshr i24 [[TMP11]], 8
+  // SIGNED-NEXT:   [[DOWNSCALE:%.*]] = lshr i24 [[TMP11]], 8
+  // UNSIGNED-NEXT: [[TMP11:%.*]] = call i24 @llvm.smul.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 15)
+  // UNSIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i24 [[TMP11]], 8
   // CHECK-NEXT:    [[RESIZE5:%.*]] = trunc i24 [[DOWNSCALE]] to i16
   // CHECK-NEXT:    store i16 [[RESIZE5]], i16* %usa, align 2
   usa = usa * uf;
@@ -293,11 +294,11 @@
   // SIGNED-NEXT:   [[UPSCALE13:%.*]] = shl i40 [[RESIZE12]], 8
   // SIGNED-NEXT:   [[TMP11:%.*]] = call i40 @llvm.umul.fix.i40(i40 [[RESIZE11]], i40 [[UPSCALE13]], i32 8)
   // SIGNED-NEXT:   [[RESIZE14:%.*]] = trunc i40 [[TMP11]] to i16
-  // UNSIGNED-NEXT: [[RESIZE11:%.*]] = zext i16 [[TMP9]] to i39
-  // UNSIGNED-NEXT: [[RESIZE12:%.*]] = zext i32 [[TMP10]] to i39
-  // UNSIGNED-NEXT: [[UPSCALE13:%.*]] = shl i39 [[RESIZE12]], 7
-  // UNSIGNED-NEXT: [[TMP11:%.*]] = call i39 @llvm.umul.fix.i39(i39 [[RESIZE11]], i39 [[UPSCALE13]], i32 7)
-  // UNSIGNED-NEXT: [[RESIZE14:%.*]] = trunc i39 [[TMP11]] to i16
+  // UNSIGNED-NEXT: [[RESIZE11:%.*]] = zext i16 [[TMP9]] to i40
+  // UNSIGNED-NEXT: [[RESIZE12:%.*]] = zext i32 [[TMP10]] to i40
+  // UNSIGNED-NEXT: [[UPSCALE13:%.*]] = shl i40 [[RESIZE12]], 7
+  // UNSIGNED-NEXT: [[TMP11:%.*]] = call i40 @llvm.smul.fix.i40(i40 [[RESIZE11]], i40 [[UPSCALE13]], i32 7)
+  // UNSIGNED-NEXT: [[RESIZE14:%.*]] = trunc i40 [[TMP11]] to i16
   // CHECK-NEXT:    store i16 [[RESIZE14]], i16* %usa, align 2
   usa = usa * ui;
 
@@ -340,11 +341,11 @@
   // SIGNED-NEXT:   [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i40
   // SIGNED-NEXT:   [[TMP23:%.*]] = call i40 @llvm.umul.fix.i40(i40 [[UPSCALE28]], i40 [[RESIZE29]], i32 8)
   // SIGNED-NEXT:   [[RESIZE30:%.*]] = trunc i40 [[TMP23]] to i16
-  // UNSIGNED-NEXT: [[RESIZE27:%.*]] = zext i32 [[TMP21]] to i39
-  // UNSIGNED-NEXT: [[UPSCALE28:%.*]] = shl i39 [[RESIZE27]], 7
-  // UNSIGNED-NEXT: [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i39
-  // UNSIGNED-NEXT: [[TMP23:%.*]] = call i39 @llvm.umul.fix.i39(i39 [[UPSCALE28]], i39 [[RESIZE29]], i32 7)
-  // UNSIGNED-NEXT: [[RESIZE30:%.*]] = trunc i39 [[TMP23]] to i16
+  // UNSIGNED-NEXT: [[RESIZE27:%.*]] = zext i32 [[TMP21]] to i40
+  // UNSIGNED-NEXT: [[UPSCALE28:%.*]] = shl i40 [[RESIZE27]], 7
+  // UNSIGNED-NEXT: [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i40
+  // UNSIGNED-NEXT: [[TMP23:%.*]] = call i40 @llvm.smul.fix.i40(i40 [[UPSCALE28]], i40 [[RESIZE29]], i32 7)
+  // UNSIGNED-NEXT: [[RESIZE30:%.*]] = trunc i40 [[TMP23]] to i16
   // CHECK-NEXT:    store i16 [[RESIZE30]], i16* %usa, align 2
   usa = ui * usa;
 
@@ -389,25 +390,22 @@
   // CHECK-NEXT: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2
   // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.umul.fix.sat.i16(i16 [[USA]], i16 [[USA_SAT]], i32 8)
   // SIGNED-NEXT: store i16 [[SUM]], i16* %usa_sat, align 2
-  // UNSIGNED-NEXT: [[USA_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA]] to i15
-  // UNSIGNED-NEXT: [[USA_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA_SAT]] to i15
-  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.umul.fix.sat.i15(i15 [[USA_TRUNC]], i15 [[USA_SAT_TRUNC]], i32 7)
-  // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
-  // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %usa_sat, align 2
+  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.smul.fix.sat.i16(i16 [[USA]], i16 [[USA_SAT]], i32 7)
+  // UNSIGNED-NEXT: [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0
+  // UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]]
+  // UNSIGNED-NEXT: store i16 [[SATMIN]], i16* %usa_sat, align 2
   usa_sat = usa * usa_sat;
 
-  // CHECK:      [[UA:%[0-9]+]] = load i32, i32* %ua, align 4
-  // CHECK-NEXT: [[USA:%[0-9]+]] = load i16, i16* %usa_sat, align 2
-  // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i32
-  // SIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i32 [[USA_EXT]], 8
+  // CHECK:       [[UA:%[0-9]+]] = load i32, i32* %ua, align 4
+  // CHECK-NEXT:  [[USA:%[0-9]+]] = load i16, i16* %usa_sat, align 2
+  // CHECK-NEXT:  [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i32
+  // CHECK-NEXT:  [[USA:%[a-z0-9]+]] = shl i32 [[USA_EXT]], 8
   // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i32 @llvm.umul.fix.sat.i32(i32 [[UA]], i32 [[USA]], i32 16)
   // SIGNED-NEXT: store i32 [[SUM]], i32* %ua_sat, align 4
-  // UNSIGNED-NEXT: [[UA_TRUNC:%[a-z0-9]+]] = trunc i32 [[UA]] to i31
-  // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i31
-  // UNSIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i31 [[USA_EXT]], 8
-  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i31 @llvm.umul.fix.sat.i31(i31 [[UA_TRUNC]], i31 [[USA]], i32 15)
-  // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i31 [[SUM]] to i32
-  // UNSIGNED-NEXT: store i32 [[SUM_EXT]], i32* %ua_sat, align 4
+  // UNSIGNED-NEXT:    [[SUM:%.*]] = call i32 @llvm.smul.fix.sat.i32(i32 [[UA]], i32 [[USA]], i32 15)
+  // UNSIGNED-NEXT:    [[USE_MIN:%.*]] = icmp slt i32 [[SUM]], 0
+  // UNSIGNED-NEXT:    [[SATMIN:%.*]] = select i1 [[USE_MIN]], i32 0, i32 [[SUM]]
+  // UNSIGNED-NEXT:    store i32 [[SATMIN]], i32* %ua_sat, align 4
   ua_sat = ua * usa_sat;
 
   // CHECK:      [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2
@@ -442,11 +440,10 @@
   // CHECK-NEXT: [[UF_SAT2:%[0-9]+]] = load i16, i16* %uf_sat, align 2
   // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.umul.fix.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]], i32 16)
   // SIGNED-NEXT: store i16 [[SUM]], i16* %uf_sat, align 2
-  // UNSIGNED-NEXT: [[UF_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[UF_SAT]] to i15
-  // UNSIGNED-NEXT: [[UF_SAT_TRUNC2:%[a-z0-9]+]] = trunc i16 [[UF_SAT2]] to i15
-  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.umul.fix.sat.i15(i15 [[UF_SAT_TRUNC]], i15 [[UF_SAT_TRUNC2]], i32 15)
-  // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
-  // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %uf_sat, align 2
+  // UNSIGNED-NEXT:    [[SUM:%.*]] = call i16 @llvm.smul.fix.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]], i32 15)
+  // UNSIGNED-NEXT:    [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0
+  // UNSIGNED-NEXT:    [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]]
+  // UNSIGNED-NEXT:    store i16 [[SATMIN]], i16* %uf_sat, align 2
   uf_sat = uf_sat * uf_sat;
 
   // CHECK:      [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2
Index: clang/test/Frontend/fixed_point_div.c
===================================================================
--- clang/test/Frontend/fixed_point_div.c
+++ clang/test/Frontend/fixed_point_div.c
@@ -230,7 +230,7 @@
   // CHECK:         [[TMP0:%.*]] = load i16, i16* %usa, align 2
   // CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* %usa, align 2
   // SIGNED-NEXT:   [[TMP2:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 8)
-  // UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
+  // UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.sdiv.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
   // CHECK-NEXT:    store i16 [[TMP2]], i16* %usa, align 2
   usa = usa / usa;
 
@@ -239,7 +239,7 @@
   // CHECK-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP3]] to i32
   // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
   // SIGNED-NEXT:   [[TMP5:%.*]] = call i32 @llvm.udiv.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 16)
-  // UNSIGNED-NEXT: [[TMP5:%.*]] = call i32 @llvm.udiv.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 15)
+  // UNSIGNED-NEXT: [[TMP5:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 15)
   // CHECK-NEXT:    store i32 [[TMP5]], i32* %ua, align 4
   ua = usa / ua;
 
@@ -247,7 +247,7 @@
   // CHECK-NEXT:    [[TMP7:%.*]] = load i8, i8* %usf, align 1
   // CHECK-NEXT:    [[RESIZE1:%.*]] = zext i8 [[TMP7]] to i16
   // SIGNED-NEXT:   [[TMP8:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 8)
-  // UNSIGNED-NEXT: [[TMP8:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 7)
+  // UNSIGNED-NEXT: [[TMP8:%.*]] = call i16 @llvm.sdiv.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 7)
   // CHECK-NEXT:    store i16 [[TMP8]], i16* %usa, align 2
   usa = usa / usf;
 
@@ -257,8 +257,9 @@
   // CHECK-NEXT:    [[UPSCALE3:%.*]] = shl i24 [[RESIZE2]], 8
   // CHECK-NEXT:    [[RESIZE4:%.*]] = zext i16 [[TMP10]] to i24
   // SIGNED-NEXT:   [[TMP11:%.*]] = call i24 @llvm.udiv.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 16)
-  // UNSIGNED-NEXT: [[TMP11:%.*]] = call i24 @llvm.udiv.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 15)
-  // CHECK-NEXT:    [[DOWNSCALE:%.*]] = lshr i24 [[TMP11]], 8
+  // SIGNED-NEXT:   [[DOWNSCALE:%.*]] = lshr i24 [[TMP11]], 8
+  // UNSIGNED-NEXT: [[TMP11:%.*]] = call i24 @llvm.sdiv.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 15)
+  // UNSIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i24 [[TMP11]], 8
   // CHECK-NEXT:    [[RESIZE5:%.*]] = trunc i24 [[DOWNSCALE]] to i16
   // CHECK-NEXT:    store i16 [[RESIZE5]], i16* %usa, align 2
   usa = usa / uf;
@@ -316,11 +317,11 @@
   // SIGNED-NEXT:   [[UPSCALE13:%.*]] = shl i40 [[RESIZE12]], 8
   // SIGNED-NEXT:   [[TMP11:%.*]] = call i40 @llvm.udiv.fix.i40(i40 [[RESIZE11]], i40 [[UPSCALE13]], i32 8)
   // SIGNED-NEXT:   [[RESIZE14:%.*]] = trunc i40 [[TMP11]] to i16
-  // UNSIGNED-NEXT: [[RESIZE11:%.*]] = zext i16 [[TMP9]] to i39
-  // UNSIGNED-NEXT: [[RESIZE12:%.*]] = zext i32 [[TMP10]] to i39
-  // UNSIGNED-NEXT: [[UPSCALE13:%.*]] = shl i39 [[RESIZE12]], 7
-  // UNSIGNED-NEXT: [[TMP11:%.*]] = call i39 @llvm.udiv.fix.i39(i39 [[RESIZE11]], i39 [[UPSCALE13]], i32 7)
-  // UNSIGNED-NEXT: [[RESIZE14:%.*]] = trunc i39 [[TMP11]] to i16
+  // UNSIGNED-NEXT: [[RESIZE11:%.*]] = zext i16 [[TMP9]] to i40
+  // UNSIGNED-NEXT: [[RESIZE12:%.*]] = zext i32 [[TMP10]] to i40
+  // UNSIGNED-NEXT: [[UPSCALE13:%.*]] = shl i40 [[RESIZE12]], 7
+  // UNSIGNED-NEXT: [[TMP11:%.*]] = call i40 @llvm.sdiv.fix.i40(i40 [[RESIZE11]], i40 [[UPSCALE13]], i32 7)
+  // UNSIGNED-NEXT: [[RESIZE14:%.*]] = trunc i40 [[TMP11]] to i16
   // CHECK-NEXT:    store i16 [[RESIZE14]], i16* %usa, align 2
   usa = usa / ui;
 
@@ -363,11 +364,11 @@
   // SIGNED-NEXT:   [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i40
   // SIGNED-NEXT:   [[TMP23:%.*]] = call i40 @llvm.udiv.fix.i40(i40 [[UPSCALE28]], i40 [[RESIZE29]], i32 8)
   // SIGNED-NEXT:   [[RESIZE30:%.*]] = trunc i40 [[TMP23]] to i16
-  // UNSIGNED-NEXT: [[RESIZE27:%.*]] = zext i32 [[TMP21]] to i39
-  // UNSIGNED-NEXT: [[UPSCALE28:%.*]] = shl i39 [[RESIZE27]], 7
-  // UNSIGNED-NEXT: [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i39
-  // UNSIGNED-NEXT: [[TMP23:%.*]] = call i39 @llvm.udiv.fix.i39(i39 [[UPSCALE28]], i39 [[RESIZE29]], i32 7)
-  // UNSIGNED-NEXT: [[RESIZE30:%.*]] = trunc i39 [[TMP23]] to i16
+  // UNSIGNED-NEXT: [[RESIZE27:%.*]] = zext i32 [[TMP21]] to i40
+  // UNSIGNED-NEXT: [[UPSCALE28:%.*]] = shl i40 [[RESIZE27]], 7
+  // UNSIGNED-NEXT: [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i40
+  // UNSIGNED-NEXT: [[TMP23:%.*]] = call i40 @llvm.sdiv.fix.i40(i40 [[UPSCALE28]], i40 [[RESIZE29]], i32 7)
+  // UNSIGNED-NEXT: [[RESIZE30:%.*]] = trunc i40 [[TMP23]] to i16
   // CHECK-NEXT:    store i16 [[RESIZE30]], i16* %usa, align 2
   usa = ui / usa;
 
@@ -412,11 +413,10 @@
   // CHECK-NEXT: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2
   // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.udiv.fix.sat.i16(i16 [[USA]], i16 [[USA_SAT]], i32 8)
   // SIGNED-NEXT: store i16 [[SUM]], i16* %usa_sat, align 2
-  // UNSIGNED-NEXT: [[USA_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA]] to i15
-  // UNSIGNED-NEXT: [[USA_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA_SAT]] to i15
-  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.udiv.fix.sat.i15(i15 [[USA_TRUNC]], i15 [[USA_SAT_TRUNC]], i32 7)
-  // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
-  // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %usa_sat, align 2
+  // UNSIGNED-NEXT:    [[SUM:%.*]] = call i16 @llvm.sdiv.fix.sat.i16(i16 [[USA]], i16 [[USA_SAT]], i32 7)
+  // UNSIGNED-NEXT:    [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0
+  // UNSIGNED-NEXT:    [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]]
+  // UNSIGNED-NEXT:    store i16 [[SATMIN]], i16* %usa_sat, align 2
   usa_sat = usa / usa_sat;
 
   // CHECK:      [[UA:%[0-9]+]] = load i32, i32* %ua, align 4
@@ -425,12 +425,12 @@
   // SIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i32 [[USA_EXT]], 8
   // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i32 @llvm.udiv.fix.sat.i32(i32 [[UA]], i32 [[USA]], i32 16)
   // SIGNED-NEXT: store i32 [[SUM]], i32* %ua_sat, align 4
-  // UNSIGNED-NEXT: [[UA_TRUNC:%[a-z0-9]+]] = trunc i32 [[UA]] to i31
-  // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i31
-  // UNSIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i31 [[USA_EXT]], 8
-  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i31 @llvm.udiv.fix.sat.i31(i31 [[UA_TRUNC]], i31 [[USA]], i32 15)
-  // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i31 [[SUM]] to i32
-  // UNSIGNED-NEXT: store i32 [[SUM_EXT]], i32* %ua_sat, align 4
+  // UNSIGNED-NEXT:    [[USA_EXT:%.*]] = zext i16 [[USA]] to i32
+  // UNSIGNED-NEXT:    [[USA:%.*]] = shl i32 [[USA_EXT]], 8
+  // UNSIGNED-NEXT:    [[SUM:%.*]] = call i32 @llvm.sdiv.fix.sat.i32(i32 [[UA]], i32 [[USA]], i32 15)
+  // UNSIGNED-NEXT:    [[USE_MIN:%.*]] = icmp slt i32 [[SUM]], 0
+  // UNSIGNED-NEXT:    [[SATMIN:%.*]] = select i1 [[USE_MIN]], i32 0, i32 [[SUM]]
+  // UNSIGNED-NEXT:    store i32 [[SATMIN]], i32* %ua_sat, align 4
   ua_sat = ua / usa_sat;
 
   // CHECK:      [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2
@@ -465,11 +465,10 @@
   // CHECK-NEXT: [[UF_SAT2:%[0-9]+]] = load i16, i16* %uf_sat, align 2
   // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.udiv.fix.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]], i32 16)
   // SIGNED-NEXT: store i16 [[SUM]], i16* %uf_sat, align 2
-  // UNSIGNED-NEXT: [[UF_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[UF_SAT]] to i15
-  // UNSIGNED-NEXT: [[UF_SAT_TRUNC2:%[a-z0-9]+]] = trunc i16 [[UF_SAT2]] to i15
-  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.udiv.fix.sat.i15(i15 [[UF_SAT_TRUNC]], i15 [[UF_SAT_TRUNC2]], i32 15)
-  // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
-  // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %uf_sat, align 2
+  // UNSIGNED-NEXT:    [[SUM:%.*]] = call i16 @llvm.sdiv.fix.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]], i32 15)
+  // UNSIGNED-NEXT:    [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0
+  // UNSIGNED-NEXT:    [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]]
+  // UNSIGNED-NEXT:    store i16 [[SATMIN]], i16* %uf_sat, align 2
   uf_sat = uf_sat / uf_sat;
 
   // CHECK:      [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2
Index: clang/test/Frontend/fixed_point_compound.c
===================================================================
--- clang/test/Frontend/fixed_point_compound.c
+++ clang/test/Frontend/fixed_point_compound.c
@@ -200,12 +200,12 @@
 // SIGNED-NEXT:   [[UPSCALE56:%.*]] = shl i64 [[RESIZE55]], 32
 // SIGNED-NEXT:   [[TMP49:%.*]] = call i64 @llvm.uadd.sat.i64(i64 [[TMP48]], i64 [[UPSCALE56]])
 // SIGNED-NEXT:   store i64 [[TMP49]], i64* @sula, align 8
-// UNSIGNED-NEXT: [[RESIZE39:%.*]] = trunc i64 [[TMP48]] to i63
-// UNSIGNED-NEXT: [[RESIZE40:%.*]] = zext i32 [[TMP47]] to i63
-// UNSIGNED-NEXT: [[UPSCALE41:%.*]] = shl i63 [[RESIZE40]], 31
-// UNSIGNED-NEXT: [[TMP49:%.*]] = call i63 @llvm.uadd.sat.i63(i63 [[RESIZE39]], i63 [[UPSCALE41]])
-// UNSIGNED-NEXT: [[RESIZE42:%.*]] = zext i63 [[TMP49]] to i64
-// UNSIGNED-NEXT: store i64 [[RESIZE42]], i64* @sula, align 8
+// UNSIGNED-NEXT: [[RESIZE40:%.*]] = zext i32 [[TMP47]] to i64
+// UNSIGNED-NEXT: [[UPSCALE41:%.*]] = shl i64 [[RESIZE40]], 31
+// UNSIGNED-NEXT: [[TMP49:%.*]] = call i64 @llvm.sadd.sat.i64(i64 [[TMP48]], i64 [[UPSCALE41]])
+// UNSIGNED-NEXT: [[TMP52:%.*]] = icmp slt i64 [[TMP49]], 0
+// UNSIGNED-NEXT: [[SATMIN48:%.*]] = select i1 [[TMP52]], i64 0, i64 [[TMP49]]
+// UNSIGNED-NEXT: store i64 [[SATMIN48]], i64* @sula, align 8
   sula += u;
 
 // CHECK:         [[TMP50:%.*]] = load i16, i16* @suf, align 2
Index: clang/test/Frontend/fixed_point_comparisons.c
===================================================================
--- clang/test/Frontend/fixed_point_comparisons.c
+++ clang/test/Frontend/fixed_point_comparisons.c
@@ -108,28 +108,32 @@
   // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
   // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
   // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
-  // CHECK-NEXT: {{.*}} = icmp ugt i32 [[UPSCALE_A]], [[A2]]
+  // UNPADDED-NEXT: {{.*}} = icmp ugt i32 [[UPSCALE_A]], [[A2]]
+  // PADDED-NEXT: {{.*}} = icmp sgt i32 [[UPSCALE_A]], [[A2]]
 
   usa >= ua;
   // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
   // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
   // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
   // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
-  // CHECK-NEXT: {{.*}} = icmp uge i32 [[UPSCALE_A]], [[A2]]
+  // UNPADDED-NEXT: {{.*}} = icmp uge i32 [[UPSCALE_A]], [[A2]]
+  // PADDED-NEXT: {{.*}} = icmp sge i32 [[UPSCALE_A]], [[A2]]
 
   usa < ua;
   // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
   // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
   // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
   // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
-  // CHECK-NEXT: {{.*}} = icmp ult i32 [[UPSCALE_A]], [[A2]]
+  // UNPADDED-NEXT: {{.*}} = icmp ult i32 [[UPSCALE_A]], [[A2]]
+  // PADDED-NEXT: {{.*}} = icmp slt i32 [[UPSCALE_A]], [[A2]]
 
   usa <= ua;
   // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
   // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
   // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
   // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
-  // CHECK-NEXT: {{.*}} = icmp ule i32 [[UPSCALE_A]], [[A2]]
+  // UNPADDED-NEXT: {{.*}} = icmp ule i32 [[UPSCALE_A]], [[A2]]
+  // PADDED-NEXT: {{.*}} = icmp sle i32 [[UPSCALE_A]], [[A2]]
 }
 
 void TestIntComparisons() {
@@ -202,10 +206,10 @@
   // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
   // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
   // UNPADDED-NEXT: {{.*}} = icmp ugt i40 [[RESIZE_A]], [[UPSCALE_I]]
-  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
-  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
-  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
-  // PADDED-NEXT: {{.*}} = icmp ugt i39 [[RESIZE_A]], [[UPSCALE_I]]
+  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
+  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
+  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 7
+  // PADDED-NEXT: {{.*}} = icmp sgt i40 [[RESIZE_A]], [[UPSCALE_I]]
 
   usa >= ui;
   // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
@@ -214,10 +218,10 @@
   // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
   // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
   // UNPADDED-NEXT: {{.*}} = icmp uge i40 [[RESIZE_A]], [[UPSCALE_I]]
-  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
-  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
-  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
-  // PADDED-NEXT: {{.*}} = icmp uge i39 [[RESIZE_A]], [[UPSCALE_I]]
+  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
+  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
+  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 7
+  // PADDED-NEXT: {{.*}} = icmp sge i40 [[RESIZE_A]], [[UPSCALE_I]]
 
   usa < ui;
   // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
@@ -226,10 +230,10 @@
   // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
   // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
   // UNPADDED-NEXT: {{.*}} = icmp ult i40 [[RESIZE_A]], [[UPSCALE_I]]
-  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
-  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
-  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
-  // PADDED-NEXT: {{.*}} = icmp ult i39 [[RESIZE_A]], [[UPSCALE_I]]
+  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
+  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
+  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 7
+  // PADDED-NEXT: {{.*}} = icmp slt i40 [[RESIZE_A]], [[UPSCALE_I]]
 
   usa <= ui;
   // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
@@ -238,10 +242,10 @@
   // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
   // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
   // UNPADDED-NEXT: {{.*}} = icmp ule i40 [[RESIZE_A]], [[UPSCALE_I]]
-  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
-  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
-  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
-  // PADDED-NEXT: {{.*}} = icmp ule i39 [[RESIZE_A]], [[UPSCALE_I]]
+  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
+  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
+  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 7
+  // PADDED-NEXT: {{.*}} = icmp sle i40 [[RESIZE_A]], [[UPSCALE_I]]
 
   // Allow for comparisons with other int like types. These are no different
   // from comparing to an int other than varying sizes. The integer types are
@@ -282,10 +286,10 @@
   // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
   // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
   // UNPADDED-NEXT: {{.*}} = icmp eq i40 [[RESIZE_A]], [[UPSCALE_I]]
-  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
-  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
-  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
-  // PADDED-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_I]]
+  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
+  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
+  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 7
+  // PADDED-NEXT: {{.*}} = icmp eq i40 [[RESIZE_A]], [[UPSCALE_I]]
 }
 
 void TestComparisonSignage() {
Index: clang/test/Frontend/fixed_point_add.c
===================================================================
--- clang/test/Frontend/fixed_point_add.c
+++ clang/test/Frontend/fixed_point_add.c
@@ -227,7 +227,8 @@
   // CHECK-NEXT: [[USA:%[a-z0-9]+]] = shl i24 [[USA_EXT]], 8
   // CHECK-NEXT: [[UF_EXT:%[a-z0-9]+]] = zext i16 [[UF]] to i24
   // CHECK-NEXT: [[SUM:%[0-9]+]] = add i24 [[USA]], [[UF_EXT]]
-  // CHECK-NEXT: [[RES:%[a-z0-9]+]] = lshr i24 [[SUM]], 8
+  // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = lshr i24 [[SUM]], 8
+  // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = ashr i24 [[SUM]], 8
   // CHECK-NEXT: [[RES_TRUNC:%[a-z0-9]+]] = trunc i24 [[RES]] to i16
   // CHECK-NEXT: store i16 [[RES_TRUNC]], i16* %usa, align 2
   usa = usa + uf;
@@ -286,11 +287,11 @@
   // SIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 8
   // SIGNED-NEXT: [[SUM:%[0-9]+]] = add i40 [[USA_EXT]], [[I]]
   // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16
-  // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i39
-  // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i39
-  // UNSIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
-  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i39 [[USA_EXT]], [[I]]
-  // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SUM]] to i16
+  // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i40
+  // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i40
+  // UNSIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 7
+  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i40 [[USA_EXT]], [[I]]
+  // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16
   // CHECK-NEXT: store i16 [[RES]], i16* %usa, align 2
   usa = usa + ui;
 
@@ -348,11 +349,10 @@
   // CHECK-NEXT: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2
   // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.uadd.sat.i16(i16 [[USA]], i16 [[USA_SAT]])
   // SIGNED-NEXT: store i16 [[SUM]], i16* %usa_sat, align 2
-  // UNSIGNED-NEXT: [[USA_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA]] to i15
-  // UNSIGNED-NEXT: [[USA_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA_SAT]] to i15
-  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.uadd.sat.i15(i15 [[USA_TRUNC]], i15 [[USA_SAT_TRUNC]])
-  // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
-  // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %usa_sat, align 2
+  // UNSIGNED-NEXT: [[SUM:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[USA]], i16 [[USA_SAT]])
+  // UNSIGNED-NEXT: [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0
+  // UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]]
+  // UNSIGNED-NEXT: store i16 [[SATMIN]], i16* %usa_sat, align 2
   usa_sat = usa + usa_sat;
 
   // CHECK:      [[UA:%[0-9]+]] = load i32, i32* %ua, align 4
@@ -361,12 +361,12 @@
   // SIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i32 [[USA_EXT]], 8
   // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i32 @llvm.uadd.sat.i32(i32 [[UA]], i32 [[USA]])
   // SIGNED-NEXT: store i32 [[SUM]], i32* %ua_sat, align 4
-  // UNSIGNED-NEXT: [[UA_TRUNC:%[a-z0-9]+]] = trunc i32 [[UA]] to i31
-  // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i31
-  // UNSIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i31 [[USA_EXT]], 8
-  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i31 @llvm.uadd.sat.i31(i31 [[UA_TRUNC]], i31 [[USA]])
-  // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i31 [[SUM]] to i32
-  // UNSIGNED-NEXT: store i32 [[SUM_EXT]], i32* %ua_sat, align 4
+  // UNSIGNED-NEXT:    [[RESIZE:%.*]] = zext i16 [[USA]] to i32
+  // UNSIGNED-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+  // UNSIGNED-NEXT:    [[TMP9:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[UA]], i32 [[UPSCALE]])
+  // UNSIGNED-NEXT:    [[TMP10:%.*]] = icmp slt i32 [[TMP9]], 0
+  // UNSIGNED-NEXT:    [[SATMIN1:%.*]] = select i1 [[TMP10]], i32 0, i32 [[TMP9]]
+  // UNSIGNED-NEXT:    store i32 [[SATMIN1]], i32* %ua_sat, align 4
   ua_sat = ua + usa_sat;
 
   // CHECK:      [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2
@@ -401,11 +401,10 @@
   // CHECK-NEXT: [[UF_SAT2:%[0-9]+]] = load i16, i16* %uf_sat, align 2
   // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.uadd.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]])
   // SIGNED-NEXT: store i16 [[SUM]], i16* %uf_sat, align 2
-  // UNSIGNED-NEXT: [[UF_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[UF_SAT]] to i15
-  // UNSIGNED-NEXT: [[UF_SAT_TRUNC2:%[a-z0-9]+]] = trunc i16 [[UF_SAT2]] to i15
-  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.uadd.sat.i15(i15 [[UF_SAT_TRUNC]], i15 [[UF_SAT_TRUNC2]])
-  // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
-  // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %uf_sat, align 2
+  // UNSIGNED-NEXT:    [[SUM:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]])
+  // UNSIGNED-NEXT:    [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0
+  // UNSIGNED-NEXT:    [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]]
+  // UNSIGNED-NEXT:    store i16 [[SATMIN]], i16* %uf_sat, align 2
   uf_sat = uf_sat + uf_sat;
 
   // CHECK:      [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2
Index: clang/lib/CodeGen/CGExprScalar.cpp
===================================================================
--- clang/lib/CodeGen/CGExprScalar.cpp
+++ clang/lib/CodeGen/CGExprScalar.cpp
@@ -3595,7 +3595,7 @@
   auto LHSFixedSema = Ctx.getFixedPointSemantics(LHSTy);
   auto RHSFixedSema = Ctx.getFixedPointSemantics(RHSTy);
   auto ResultFixedSema = Ctx.getFixedPointSemantics(ResultTy);
-  auto CommonFixedSema = LHSFixedSema.getCommonSemantics(RHSFixedSema);
+  auto CommonFixedSema = LHSFixedSema.getCommonSemantics(RHSFixedSema, true);
 
   // Convert the operands to the full precision type.
   Value *FullLHS = EmitFixedPointConversion(LHS, LHSFixedSema, CommonFixedSema,
Index: clang/lib/Basic/FixedPoint.cpp
===================================================================
--- clang/lib/Basic/FixedPoint.cpp
+++ clang/lib/Basic/FixedPoint.cpp
@@ -124,8 +124,9 @@
   return APFixedPoint(Val, Sema);
 }
 
-FixedPointSemantics FixedPointSemantics::getCommonSemantics(
-    const FixedPointSemantics &Other) const {
+FixedPointSemantics
+FixedPointSemantics::getCommonSemantics(const FixedPointSemantics &Other,
+                                        bool UnsignedPaddingIsSigned) const {
   unsigned CommonScale = std::max(getScale(), Other.getScale());
   unsigned CommonWidth =
       std::max(getIntegralBits(), Other.getIntegralBits()) + CommonScale;
@@ -139,6 +140,23 @@
                                Other.hasUnsignedPadding() && !ResultIsSaturated;
   }
 
+  // For codegen purposes, make unsigned with padding semantics signed instead.
+  // This means that we will generate signed operations. The result from these
+  // operations is defined, since ending up with a negative result is undefined
+  // for nonsaturating semantics, and for saturating semantics we will
+  // perform a clamp-to-zero in the last conversion to result semantics (since
+  // we are going from saturating signed to saturating unsigned).
+  //
+  // This codegen is beneficial for targets which want to use unsigned padding,
+  // since such targets likely do not have native instructions which can
+  // implement the wider scale of unpadded unsigned and would prefer to reuse
+  // their signed operations for this.
+  if (UnsignedPaddingIsSigned && !ResultIsSigned &&
+      (hasUnsignedPadding() || Other.hasUnsignedPadding())) {
+    ResultIsSigned = true;
+    ResultHasUnsignedPadding = false;
+  }
+
   // If the result is signed, add an extra bit for the sign. Otherwise, if it is
   // unsigned and has unsigned padding, we only need to add the extra padding
   // bit back if we are not saturating.
Index: clang/include/clang/Basic/FixedPoint.h
===================================================================
--- clang/include/clang/Basic/FixedPoint.h
+++ clang/include/clang/Basic/FixedPoint.h
@@ -63,8 +63,12 @@
   /// precision semantic that can precisely represent the precision and ranges
   /// of both input values. This does not compute the resulting semantics for a
   /// given binary operation.
+  /// Is UnsignedPaddingIsSigned is true, unsigned semantics which would
+  /// otherwise have been unsigned will be signed instead. This is for codegen
+  /// purposes.
   FixedPointSemantics
-  getCommonSemantics(const FixedPointSemantics &Other) const;
+  getCommonSemantics(const FixedPointSemantics &Other,
+                     bool UnsignedPaddingIsSigned = false) const;
 
   /// Return the FixedPointSemantics for an integer type.
   static FixedPointSemantics GetIntegerSemantics(unsigned Width,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to