[PATCH] D46881: [X86][CET] Changing -fcf-protection behavior to comply with gcc (clang part)

2018-05-18 Thread Alexander Ivchenko via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC332704: This patch aims to match the changes introduced 
(authored by aivchenk, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D46881?vs=147292&id=147476#toc

Repository:
  rC Clang

https://reviews.llvm.org/D46881

Files:
  docs/ClangCommandLineReference.rst
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/TargetInfo.h
  include/clang/Driver/Options.td
  lib/Basic/TargetInfo.cpp
  lib/Basic/Targets/X86.cpp
  lib/Basic/Targets/X86.h
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGen/attributes.c
  test/CodeGen/builtins-x86.c
  test/CodeGen/x86-cf-protection.c
  test/Driver/x86-target-features.c
  test/Preprocessor/x86_target_features.c
  test/Sema/attr-nocf_check.c
  test/Sema/attr-nocf_check.cpp

Index: lib/Basic/TargetInfo.cpp
===
--- lib/Basic/TargetInfo.cpp
+++ lib/Basic/TargetInfo.cpp
@@ -14,6 +14,7 @@
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/AddressSpaces.h"
 #include "clang/Basic/CharInfo.h"
+#include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/LangOptions.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/STLExtras.h"
@@ -115,6 +116,18 @@
 // Out of line virtual dtor for TargetInfo.
 TargetInfo::~TargetInfo() {}
 
+bool
+TargetInfo::checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const {
+  Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=branch";
+  return false;
+}
+
+bool
+TargetInfo::checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const {
+  Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=return";
+  return false;
+}
+
 /// getTypeName - Return the user string for the specified integer type enum.
 /// For example, SignedShort -> "short".
 const char *TargetInfo::getTypeName(IntType T) {
Index: lib/Basic/Targets/X86.h
===
--- lib/Basic/Targets/X86.h
+++ lib/Basic/Targets/X86.h
@@ -81,7 +81,6 @@
   bool HasSHA = false;
   bool HasMPX = false;
   bool HasSHSTK = false;
-  bool HasIBT = false;
   bool HasSGX = false;
   bool HasCX16 = false;
   bool HasFXSR = false;
@@ -171,10 +170,15 @@
   bool validateInputSize(StringRef Constraint, unsigned Size) const override;
 
   virtual bool
-  checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const override;
+  checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const override {
+return true;
+  };
 
   virtual bool
-  checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const override;
+  checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const override {
+return true;
+  };
+
 
   virtual bool validateOperandSize(StringRef Constraint, unsigned Size) const;
 
Index: lib/Basic/Targets/X86.cpp
===
--- lib/Basic/Targets/X86.cpp
+++ lib/Basic/Targets/X86.cpp
@@ -102,26 +102,6 @@
   return false;
 }
 
-bool X86TargetInfo::checkCFProtectionReturnSupported(
-DiagnosticsEngine &Diags) const {
-  if (HasSHSTK)
-return true;
-
-  Diags.Report(diag::err_opt_not_valid_without_opt) << "cf-protection=return"
-<< "-mshstk";
-  return false;
-}
-
-bool X86TargetInfo::checkCFProtectionBranchSupported(
-DiagnosticsEngine &Diags) const {
-  if (HasIBT)
-return true;
-
-  Diags.Report(diag::err_opt_not_valid_without_opt) << "cf-protection=branch"
-<< "-mibt";
-  return false;
-}
-
 bool X86TargetInfo::initFeatureMap(
 llvm::StringMap &Features, DiagnosticsEngine &Diags, StringRef CPU,
 const std::vector &FeaturesVec) const {
@@ -781,8 +761,6 @@
   HasMPX = true;
 } else if (Feature == "+shstk") {
   HasSHSTK = true;
-} else if (Feature == "+ibt") {
-  HasIBT = true;
 } else if (Feature == "+movbe") {
   HasMOVBE = true;
 } else if (Feature == "+sgx") {
@@ -1175,8 +1153,6 @@
 Builder.defineMacro("__MPX__");
   if (HasSHSTK)
 Builder.defineMacro("__SHSTK__");
-  if (HasIBT)
-Builder.defineMacro("__IBT__");
   if (HasSGX)
 Builder.defineMacro("__SGX__");
   if (HasPREFETCHWT1)
@@ -1394,7 +1370,6 @@
   .Case("fsgsbase", HasFSGSBASE)
   .Case("fxsr", HasFXSR)
   .Case("gfni", HasGFNI)
-  .Case("ibt", HasIBT)
   .Case("lwp", HasLWP)
   .Case("lzcnt", HasLZCNT)
   .Case("mm3dnow", MMX3DNowLevel >= AMD3DNow)
Index: lib/Frontend/CompilerInvocation.cpp
===
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -2829,6 +2829,17 @@
 }
   }
 
+  // Add the __CET__ macro if a CFProtection option is set.
+  if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
+StringRef Name = A->getValue();
+if (Name == "branch")
+  Opts.addMacroDe

[PATCH] D43016: Fix for #31362 - ms_abi is implemented incorrectly for larger values (>=16 bytes).

2018-02-08 Thread Alexander Ivchenko via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL324594: Fix for #31362 - ms_abi is implemented incorrectly 
for values >=16 bytes. (authored by aivchenk, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D43016

Files:
  cfe/trunk/lib/CodeGen/TargetInfo.cpp
  cfe/trunk/test/CodeGen/ms_abi.c


Index: cfe/trunk/test/CodeGen/ms_abi.c
===
--- cfe/trunk/test/CodeGen/ms_abi.c
+++ cfe/trunk/test/CodeGen/ms_abi.c
@@ -146,3 +146,16 @@
   // WIN64: %[[AP_VAL:.*]] = load i8*, i8** %[[AP]]
   // WIN64-NEXT: store i8* %[[AP_VAL]], i8** %[[AP2:.*]]
 }
+
+// This test checks if structs are passed according to Win64 calling convention
+// when it's enforced by __attribute((ms_abi)).
+struct i128 {
+  unsigned long long a;
+  unsigned long long b;
+};
+
+__attribute__((ms_abi)) struct i128 f7(struct i128 a) {
+  // WIN64: define void @f7(%struct.i128* noalias sret %agg.result, 
%struct.i128* %a)
+  // FREEBSD: define win64cc void @f7(%struct.i128* noalias sret %agg.result, 
%struct.i128* %a)
+  return a;
+}
Index: cfe/trunk/lib/CodeGen/TargetInfo.cpp
===
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp
@@ -3529,7 +3529,17 @@
 
 void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
 
-  bool IsRegCall = FI.getCallingConvention() == llvm::CallingConv::X86_RegCall;
+  const unsigned CallingConv = FI.getCallingConvention();
+  // It is possible to force Win64 calling convention on any x86_64 target by
+  // using __attribute__((ms_abi)). In such case to correctly emit Win64
+  // compatible code delegate this call to WinX86_64ABIInfo::computeInfo.
+  if (CallingConv == llvm::CallingConv::Win64) {
+WinX86_64ABIInfo Win64ABIInfo(CGT);
+Win64ABIInfo.computeInfo(FI);
+return;
+  }
+
+  bool IsRegCall = CallingConv == llvm::CallingConv::X86_RegCall;
 
   // Keep track of the number of assigned registers.
   unsigned FreeIntRegs = IsRegCall ? 11 : 6;


Index: cfe/trunk/test/CodeGen/ms_abi.c
===
--- cfe/trunk/test/CodeGen/ms_abi.c
+++ cfe/trunk/test/CodeGen/ms_abi.c
@@ -146,3 +146,16 @@
   // WIN64: %[[AP_VAL:.*]] = load i8*, i8** %[[AP]]
   // WIN64-NEXT: store i8* %[[AP_VAL]], i8** %[[AP2:.*]]
 }
+
+// This test checks if structs are passed according to Win64 calling convention
+// when it's enforced by __attribute((ms_abi)).
+struct i128 {
+  unsigned long long a;
+  unsigned long long b;
+};
+
+__attribute__((ms_abi)) struct i128 f7(struct i128 a) {
+  // WIN64: define void @f7(%struct.i128* noalias sret %agg.result, %struct.i128* %a)
+  // FREEBSD: define win64cc void @f7(%struct.i128* noalias sret %agg.result, %struct.i128* %a)
+  return a;
+}
Index: cfe/trunk/lib/CodeGen/TargetInfo.cpp
===
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp
@@ -3529,7 +3529,17 @@
 
 void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
 
-  bool IsRegCall = FI.getCallingConvention() == llvm::CallingConv::X86_RegCall;
+  const unsigned CallingConv = FI.getCallingConvention();
+  // It is possible to force Win64 calling convention on any x86_64 target by
+  // using __attribute__((ms_abi)). In such case to correctly emit Win64
+  // compatible code delegate this call to WinX86_64ABIInfo::computeInfo.
+  if (CallingConv == llvm::CallingConv::Win64) {
+WinX86_64ABIInfo Win64ABIInfo(CGT);
+Win64ABIInfo.computeInfo(FI);
+return;
+  }
+
+  bool IsRegCall = CallingConv == llvm::CallingConv::X86_RegCall;
 
   // Keep track of the number of assigned registers.
   unsigned FreeIntRegs = IsRegCall ? 11 : 6;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D43016: Fix for #31362 - ms_abi is implemented incorrectly for larger values (>=16 bytes).

2018-02-08 Thread Alexander Ivchenko via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC324594: Fix for #31362 - ms_abi is implemented incorrectly 
for values >=16 bytes. (authored by aivchenk, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D43016?vs=133198&id=133395#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D43016

Files:
  lib/CodeGen/TargetInfo.cpp
  test/CodeGen/ms_abi.c


Index: test/CodeGen/ms_abi.c
===
--- test/CodeGen/ms_abi.c
+++ test/CodeGen/ms_abi.c
@@ -146,3 +146,16 @@
   // WIN64: %[[AP_VAL:.*]] = load i8*, i8** %[[AP]]
   // WIN64-NEXT: store i8* %[[AP_VAL]], i8** %[[AP2:.*]]
 }
+
+// This test checks if structs are passed according to Win64 calling convention
+// when it's enforced by __attribute((ms_abi)).
+struct i128 {
+  unsigned long long a;
+  unsigned long long b;
+};
+
+__attribute__((ms_abi)) struct i128 f7(struct i128 a) {
+  // WIN64: define void @f7(%struct.i128* noalias sret %agg.result, 
%struct.i128* %a)
+  // FREEBSD: define win64cc void @f7(%struct.i128* noalias sret %agg.result, 
%struct.i128* %a)
+  return a;
+}
Index: lib/CodeGen/TargetInfo.cpp
===
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -3529,7 +3529,17 @@
 
 void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
 
-  bool IsRegCall = FI.getCallingConvention() == llvm::CallingConv::X86_RegCall;
+  const unsigned CallingConv = FI.getCallingConvention();
+  // It is possible to force Win64 calling convention on any x86_64 target by
+  // using __attribute__((ms_abi)). In such case to correctly emit Win64
+  // compatible code delegate this call to WinX86_64ABIInfo::computeInfo.
+  if (CallingConv == llvm::CallingConv::Win64) {
+WinX86_64ABIInfo Win64ABIInfo(CGT);
+Win64ABIInfo.computeInfo(FI);
+return;
+  }
+
+  bool IsRegCall = CallingConv == llvm::CallingConv::X86_RegCall;
 
   // Keep track of the number of assigned registers.
   unsigned FreeIntRegs = IsRegCall ? 11 : 6;


Index: test/CodeGen/ms_abi.c
===
--- test/CodeGen/ms_abi.c
+++ test/CodeGen/ms_abi.c
@@ -146,3 +146,16 @@
   // WIN64: %[[AP_VAL:.*]] = load i8*, i8** %[[AP]]
   // WIN64-NEXT: store i8* %[[AP_VAL]], i8** %[[AP2:.*]]
 }
+
+// This test checks if structs are passed according to Win64 calling convention
+// when it's enforced by __attribute((ms_abi)).
+struct i128 {
+  unsigned long long a;
+  unsigned long long b;
+};
+
+__attribute__((ms_abi)) struct i128 f7(struct i128 a) {
+  // WIN64: define void @f7(%struct.i128* noalias sret %agg.result, %struct.i128* %a)
+  // FREEBSD: define win64cc void @f7(%struct.i128* noalias sret %agg.result, %struct.i128* %a)
+  return a;
+}
Index: lib/CodeGen/TargetInfo.cpp
===
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -3529,7 +3529,17 @@
 
 void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
 
-  bool IsRegCall = FI.getCallingConvention() == llvm::CallingConv::X86_RegCall;
+  const unsigned CallingConv = FI.getCallingConvention();
+  // It is possible to force Win64 calling convention on any x86_64 target by
+  // using __attribute__((ms_abi)). In such case to correctly emit Win64
+  // compatible code delegate this call to WinX86_64ABIInfo::computeInfo.
+  if (CallingConv == llvm::CallingConv::Win64) {
+WinX86_64ABIInfo Win64ABIInfo(CGT);
+Win64ABIInfo.computeInfo(FI);
+return;
+  }
+
+  bool IsRegCall = CallingConv == llvm::CallingConv::X86_RegCall;
 
   // Keep track of the number of assigned registers.
   unsigned FreeIntRegs = IsRegCall ? 11 : 6;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D43814: [x86][CET] Introduce _get_ssp, _inc_ssp intrinsics

2018-03-05 Thread Alexander Ivchenko via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC326689: [x86][CET] Introduce _get_ssp, _inc_ssp intrinsics 
(authored by aivchenk, committed by ).

Repository:
  rC Clang

https://reviews.llvm.org/D43814

Files:
  lib/Headers/cetintrin.h
  test/CodeGen/cetintrin.c


Index: test/CodeGen/cetintrin.c
===
--- test/CodeGen/cetintrin.c
+++ test/CodeGen/cetintrin.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -ffreestanding %s -triple=i386-apple-darwin -target-feature 
+shstk -emit-llvm -o - -Wall -Werror | FileCheck %s
-// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin 
-target-feature +shstk  -emit-llvm -o - -Wall -Werror | FileCheck %s 
--check-prefix=X86_64
+// RUN: %clang_cc1 -ffreestanding %s -triple=i386-apple-darwin -target-feature 
+shstk -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=I386 
--check-prefix=CHECK
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin 
-target-feature +shstk  -emit-llvm -o - -Wall -Werror | FileCheck %s 
--check-prefix=X86_64  --check-prefix=CHECK
 
 #include 
 
@@ -15,6 +15,20 @@
   // X86_64:   call void @llvm.x86.incsspq(i64 %{{[a-z0-9.]+}})
   _incsspq(a);
 }
+
+void test_inc_ssp(unsigned int a) {
+  // X86_64-LABEL: @test_inc_ssp
+  // X86_64:   call void @llvm.x86.incsspq(i64 %{{[a-z0-9.]+}})
+  _inc_ssp(a);
+}
+#else
+
+void test_inc_ssp(unsigned int a) {
+  // I386-LABEL: @test_inc_ssp
+  // I386:   call void @llvm.x86.incsspd(i32 %{{[0-9]+}})
+  _inc_ssp(a);
+}
+
 #endif
 
 unsigned int test_rdsspd(unsigned int a) {
@@ -29,6 +43,21 @@
   // X86_64:   call i64 @llvm.x86.rdsspq(i64 %{{[a-z0-9.]+}})
   return _rdsspq(a);
 }
+
+unsigned long long test_get_ssp(void) {
+  // X86_64-LABEL: @test_get_ssp
+  // X86_64:   call i64 @llvm.x86.rdsspq(i64 0)
+  return _get_ssp();
+}
+
+#else
+
+unsigned int test_get_ssp(void) {
+  // I386-LABEL: @test_get_ssp
+  // I386:   call i32 @llvm.x86.rdsspd(i32 0)
+  return _get_ssp();
+}
+
 #endif
 
 void  test_saveprevssp() {
Index: lib/Headers/cetintrin.h
===
--- lib/Headers/cetintrin.h
+++ lib/Headers/cetintrin.h
@@ -42,6 +42,16 @@
 }
 #endif /* __x86_64__ */
 
+#ifdef __x86_64__
+static __inline__ void __DEFAULT_FN_ATTRS _inc_ssp(unsigned int __a) {
+  __builtin_ia32_incsspq(__a);
+}
+#else /* __x86_64__ */
+static __inline__ void __DEFAULT_FN_ATTRS _inc_ssp(unsigned int __a) {
+  __builtin_ia32_incsspd((int)__a);
+}
+#endif /* __x86_64__ */
+
 static __inline__ unsigned int __DEFAULT_FN_ATTRS _rdsspd(unsigned int __a) {
   return __builtin_ia32_rdsspd(__a);
 }
@@ -52,6 +62,16 @@
 }
 #endif /* __x86_64__ */
 
+#ifdef __x86_64__
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS _get_ssp(void) {
+  return __builtin_ia32_rdsspq(0);
+}
+#else /* __x86_64__ */
+static __inline__ unsigned int __DEFAULT_FN_ATTRS _get_ssp(void) {
+  return __builtin_ia32_rdsspd(0);
+}
+#endif /* __x86_64__ */
+
 static __inline__ void __DEFAULT_FN_ATTRS _saveprevssp() {
   __builtin_ia32_saveprevssp();
 }


Index: test/CodeGen/cetintrin.c
===
--- test/CodeGen/cetintrin.c
+++ test/CodeGen/cetintrin.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -ffreestanding %s -triple=i386-apple-darwin -target-feature +shstk -emit-llvm -o - -Wall -Werror | FileCheck %s
-// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +shstk  -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=X86_64
+// RUN: %clang_cc1 -ffreestanding %s -triple=i386-apple-darwin -target-feature +shstk -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=I386 --check-prefix=CHECK
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +shstk  -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=X86_64  --check-prefix=CHECK
 
 #include 
 
@@ -15,6 +15,20 @@
   // X86_64:   call void @llvm.x86.incsspq(i64 %{{[a-z0-9.]+}})
   _incsspq(a);
 }
+
+void test_inc_ssp(unsigned int a) {
+  // X86_64-LABEL: @test_inc_ssp
+  // X86_64:   call void @llvm.x86.incsspq(i64 %{{[a-z0-9.]+}})
+  _inc_ssp(a);
+}
+#else
+
+void test_inc_ssp(unsigned int a) {
+  // I386-LABEL: @test_inc_ssp
+  // I386:   call void @llvm.x86.incsspd(i32 %{{[0-9]+}})
+  _inc_ssp(a);
+}
+
 #endif
 
 unsigned int test_rdsspd(unsigned int a) {
@@ -29,6 +43,21 @@
   // X86_64:   call i64 @llvm.x86.rdsspq(i64 %{{[a-z0-9.]+}})
   return _rdsspq(a);
 }
+
+unsigned long long test_get_ssp(void) {
+  // X86_64-LABEL: @test_get_ssp
+  // X86_64:   call i64 @llvm.x86.rdsspq(i64 0)
+  return _get_ssp();
+}
+
+#else
+
+unsigned int test_get_ssp(void) {
+  // I386-LABEL: @test_get_ssp
+  // I386:   call i32 @llvm.x86.rdsspd(i32 0)
+  return _get_ssp();
+}
+
 #endif
 
 void  test_saveprevssp() {
Index: lib/Headers/cetintrin.h
===

[PATCH] D44786: Lowering x86 adds/addus/subs/subus intrinsics (clang)

2018-04-19 Thread Alexander Ivchenko via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL330323: Lowering x86 adds/addus/subs/subus intrinsics 
(clang) (authored by aivchenk, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D44786

Files:
  cfe/trunk/lib/CodeGen/CGBuiltin.cpp
  cfe/trunk/test/CodeGen/avx2-builtins.c
  cfe/trunk/test/CodeGen/avx512bw-builtins.c
  cfe/trunk/test/CodeGen/avx512vlbw-builtins.c
  cfe/trunk/test/CodeGen/sse2-builtins.c

Index: cfe/trunk/test/CodeGen/avx2-builtins.c
===
--- cfe/trunk/test/CodeGen/avx2-builtins.c
+++ cfe/trunk/test/CodeGen/avx2-builtins.c
@@ -56,25 +56,53 @@
 
 __m256i test_mm256_adds_epi8(__m256i a, __m256i b) {
   // CHECK-LABEL: test_mm256_adds_epi8
-  // CHECK: call <32 x i8> @llvm.x86.avx2.padds.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
+  // CHECK-NOT: call <32 x i8> @llvm.x86.avx2.padds.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
+  // CHECK: sext <32 x i8> %{{.*}} to <32 x i16>
+  // CHECK: sext <32 x i8> %{{.*}} to <32 x i16>
+  // CHECK: add <32 x i16> %{{.*}}, %{{.*}}
+  // CHECK: icmp sle <32 x i16> %{{.*}}, 
+  // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> 
+  // CHECK: icmp slt <32 x i16> %{{.*}}, 
+  // CHECK: select <32 x i1> %{{.*}}, <32 x i16> , <32 x i16> %{{.*}}
+  // CHECK: trunc <32 x i16> %{{.*}} to <32 x i8>
   return _mm256_adds_epi8(a, b);
 }
 
 __m256i test_mm256_adds_epi16(__m256i a, __m256i b) {
   // CHECK-LABEL: test_mm256_adds_epi16
-  // CHECK: call <16 x i16> @llvm.x86.avx2.padds.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+  // CHECK-NOT: call <16 x i16> @llvm.x86.avx2.padds.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+  // CHECK: sext <16 x i16> %{{.*}} to <16 x i32>
+  // CHECK: sext <16 x i16> %{{.*}} to <16 x i32>
+  // CHECK: add <16 x i32> %{{.*}}, %{{.*}}
+  // CHECK: icmp sle <16 x i32> %{{.*}}, 
+  // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> 
+  // CHECK: icmp slt <16 x i32> %{{.*}}, 
+  // CHECK: select <16 x i1> %{{.*}}, <16 x i32> , <16 x i32> %{{.*}}
+  // CHECK: trunc <16 x i32> %{{.*}} to <16 x i16>
   return _mm256_adds_epi16(a, b);
 }
 
 __m256i test_mm256_adds_epu8(__m256i a, __m256i b) {
   // CHECK-LABEL: test_mm256_adds_epu8
-  // CHECK: call <32 x i8> @llvm.x86.avx2.paddus.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
+  // CHECK-NOT: call <32 x i8> @llvm.x86.avx2.paddus.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
+  // CHECK: zext <32 x i8> %{{.*}} to <32 x i16>
+  // CHECK: zext <32 x i8> %{{.*}} to <32 x i16>
+  // CHECK: add <32 x i16> %{{.*}}, %{{.*}}
+  // CHECK: icmp ule <32 x i16> %{{.*}}, 
+  // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> 
+  // CHECK: trunc <32 x i16> %{{.*}} to <32 x i8>
   return _mm256_adds_epu8(a, b);
 }
 
 __m256i test_mm256_adds_epu16(__m256i a, __m256i b) {
   // CHECK-LABEL: test_mm256_adds_epu16
-  // CHECK: call <16 x i16> @llvm.x86.avx2.paddus.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+  // CHECK-NOT: call <16 x i16> @llvm.x86.avx2.paddus.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+  // CHECK: zext <16 x i16> %{{.*}} to <16 x i32>
+  // CHECK: zext <16 x i16> %{{.*}} to <16 x i32>
+  // CHECK: add <16 x i32> %{{.*}}, %{{.*}}
+  // CHECK: icmp ule <16 x i32> %{{.*}}, 
+  // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> 
+  // CHECK: trunc <16 x i32> %{{.*}} to <16 x i16>
   return _mm256_adds_epu16(a, b);
 }
 
@@ -1171,25 +1199,47 @@
 
 __m256i test_mm256_subs_epi8(__m256i a, __m256i b) {
   // CHECK-LABEL: test_mm256_subs_epi8
-  // CHECK: call <32 x i8> @llvm.x86.avx2.psubs.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
+  // CHECK-NOT: call <32 x i8> @llvm.x86.avx2.psubs.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
+  // CHECK: sext <32 x i8> %{{.*}} to <32 x i16>
+  // CHECK: sext <32 x i8> %{{.*}} to <32 x i16>
+  // CHECK: sub <32 x i16> %{{.*}}, %{{.*}}
+  // CHECK: icmp sle <32 x i16> %{{.*}}, 
+  // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> 
+  // CHECK: icmp slt <32 x i16> %{{.*}}, 
+  // CHECK: select <32 x i1> %{{.*}}, <32 x i16> , <32 x i16> %{{.*}}
+  // CHECK: trunc <32 x i16> %{{.*}} to <32 x i8>
   return _mm256_subs_epi8(a, b);
 }
 
 __m256i test_mm256_subs_epi16(__m256i a, __m256i b) {
   // CHECK-LABEL: test_mm256_subs_epi16
-  // CHECK: call <16 x i16> @llvm.x86.avx2.psubs.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+  // CHECK-NOT: call <16 x i16> @llvm.x86.avx2.psubs.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+  // CHECK: sext <16 x i16> %{{.*}} to <16 x i32>
+  // CHECK: sext <16 x i16> %{{.*}} to <16 x i32>
+  // CHECK: sub <16 x i32> %{{.*}}, %{{.*}}
+  // CHECK: icmp sle <16 x i32> %{{.*}}, 
+  // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> 
+  // CHECK: icmp slt <16 x i32> %{{.*}}, 
+  // CHECK: select <16 x i1> %{{.*}}, <16 x i32> , <16 x i32> %{{.*}}
+  // CHECK: trunc <16 x i32> %{{.*}} to <16 x i16>
   return _mm256_subs_epi16(a, b