LiuChen3 created this revision.
Herald added subscribers: dexonsmith, jdoerfert, pengfei.
Herald added a project: All.
LiuChen3 requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.

For now clang will assume the integer parameters have been sign/zero
extended in the caller, which will cause some ABI compatibility issues.
This patch will remove the `signext/zeroext` from the callee so that the
callee will always extend the integer parameters:

1. Adds one new `ConservativeExtend` Kind, which means we shouldn't

make any assumptions about the caller and callee. In this case, we must
do zero/sign extension for integer parameters in caller and callee.

2. Adds `-mconservative-extend/-mno-conservative-extend` options. As

default `-mconservative-extend` is enabled. Use `-mno-conservative-extend`
to get back to the original behavior of clang.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D124435

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/CodeGen/CGFunctionInfo.h
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/TargetInfo.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/CodeGen/2007-06-18-SextAttrAggregate.c
  clang/test/CodeGen/X86/integer_argument_passing.c
  clang/test/CodeGen/X86/x86_32-arguments-darwin.c
  clang/test/CodeGen/X86/x86_32-arguments-linux.c
  clang/test/CodeGen/X86/x86_64-arguments-nacl.c
  clang/test/CodeGen/X86/x86_64-arguments.c
  clang/test/CodeGen/attr-noundef.cpp
  clang/test/CodeGen/builtin-align.c
  clang/test/CodeGen/catch-implicit-integer-sign-changes.c
  clang/test/CodeGen/ext-int-cc.c
  clang/test/CodeGen/function-attributes.c
  clang/test/CodeGen/mangle-windows.c
  clang/test/CodeGen/matrix-type-builtins.c
  clang/test/CodeGen/matrix-type-operators.c
  clang/test/CodeGen/ms-inline-asm.c
  clang/test/CodeGen/regcall.c
  clang/test/CodeGen/vectorcall.c
  clang/test/CodeGenCXX/exceptions.cpp
  clang/test/CodeGenCXX/ext-int.cpp
  clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
  clang/test/CodeGenCXX/new-overflow.cpp
  clang/test/CodeGenCXX/virtual-bases.cpp
  clang/test/CodeGenObjC/property-atomic-bool.m
  clang/test/OpenMP/target_codegen_global_capture.cpp

Index: clang/test/OpenMP/target_codegen_global_capture.cpp
===================================================================
--- clang/test/OpenMP/target_codegen_global_capture.cpp
+++ clang/test/OpenMP/target_codegen_global_capture.cpp
@@ -2051,7 +2051,7 @@
 //
 //
 // CHECK3-LABEL: define {{[^@]+}}@_Z3foossss
-// CHECK3-SAME: (i16 noundef signext [[A:%.*]], i16 noundef signext [[B:%.*]], i16 noundef signext [[C:%.*]], i16 noundef signext [[D:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK3-SAME: (i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]], i16 noundef [[D:%.*]]) #[[ATTR0:[0-9]+]] {
 // CHECK3-NEXT:  entry:
 // CHECK3-NEXT:    [[A_ADDR:%.*]] = alloca i16, align 2
 // CHECK3-NEXT:    [[B_ADDR:%.*]] = alloca i16, align 2
@@ -2335,7 +2335,7 @@
 //
 //
 // CHECK3-LABEL: define {{[^@]+}}@_Z3barssss
-// CHECK3-SAME: (i16 noundef signext [[A:%.*]], i16 noundef signext [[B:%.*]], i16 noundef signext [[C:%.*]], i16 noundef signext [[D:%.*]]) #[[ATTR0]] {
+// CHECK3-SAME: (i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]], i16 noundef [[D:%.*]]) #[[ATTR0]] {
 // CHECK3-NEXT:  entry:
 // CHECK3-NEXT:    [[A_ADDR:%.*]] = alloca i16, align 2
 // CHECK3-NEXT:    [[B_ADDR:%.*]] = alloca i16, align 2
@@ -2642,7 +2642,7 @@
 //
 //
 // CHECK3-LABEL: define {{[^@]+}}@_Z5tbar2ssss
-// CHECK3-SAME: (i16 noundef signext [[A:%.*]], i16 noundef signext [[B:%.*]], i16 noundef signext [[C:%.*]], i16 noundef signext [[D:%.*]]) #[[ATTR0]] {
+// CHECK3-SAME: (i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]], i16 noundef [[D:%.*]]) #[[ATTR0]] {
 // CHECK3-NEXT:  entry:
 // CHECK3-NEXT:    [[A_ADDR:%.*]] = alloca i16, align 2
 // CHECK3-NEXT:    [[B_ADDR:%.*]] = alloca i16, align 2
@@ -2661,7 +2661,7 @@
 //
 //
 // CHECK3-LABEL: define {{[^@]+}}@_Z4tbarIsEiT_S0_S0_S0_
-// CHECK3-SAME: (i16 noundef signext [[A:%.*]], i16 noundef signext [[B:%.*]], i16 noundef signext [[C:%.*]], i16 noundef signext [[D:%.*]]) #[[ATTR0]] comdat {
+// CHECK3-SAME: (i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]], i16 noundef [[D:%.*]]) #[[ATTR0]] comdat {
 // CHECK3-NEXT:  entry:
 // CHECK3-NEXT:    [[A_ADDR:%.*]] = alloca i16, align 2
 // CHECK3-NEXT:    [[B_ADDR:%.*]] = alloca i16, align 2
@@ -2975,7 +2975,7 @@
 //
 //
 // CHECK4-LABEL: define {{[^@]+}}@_Z3foossss
-// CHECK4-SAME: (i16 noundef signext [[A:%.*]], i16 noundef signext [[B:%.*]], i16 noundef signext [[C:%.*]], i16 noundef signext [[D:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK4-SAME: (i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]], i16 noundef [[D:%.*]]) #[[ATTR0:[0-9]+]] {
 // CHECK4-NEXT:  entry:
 // CHECK4-NEXT:    [[A_ADDR:%.*]] = alloca i16, align 2
 // CHECK4-NEXT:    [[B_ADDR:%.*]] = alloca i16, align 2
@@ -3259,7 +3259,7 @@
 //
 //
 // CHECK4-LABEL: define {{[^@]+}}@_Z3barssss
-// CHECK4-SAME: (i16 noundef signext [[A:%.*]], i16 noundef signext [[B:%.*]], i16 noundef signext [[C:%.*]], i16 noundef signext [[D:%.*]]) #[[ATTR0]] {
+// CHECK4-SAME: (i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]], i16 noundef [[D:%.*]]) #[[ATTR0]] {
 // CHECK4-NEXT:  entry:
 // CHECK4-NEXT:    [[A_ADDR:%.*]] = alloca i16, align 2
 // CHECK4-NEXT:    [[B_ADDR:%.*]] = alloca i16, align 2
@@ -3566,7 +3566,7 @@
 //
 //
 // CHECK4-LABEL: define {{[^@]+}}@_Z5tbar2ssss
-// CHECK4-SAME: (i16 noundef signext [[A:%.*]], i16 noundef signext [[B:%.*]], i16 noundef signext [[C:%.*]], i16 noundef signext [[D:%.*]]) #[[ATTR0]] {
+// CHECK4-SAME: (i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]], i16 noundef [[D:%.*]]) #[[ATTR0]] {
 // CHECK4-NEXT:  entry:
 // CHECK4-NEXT:    [[A_ADDR:%.*]] = alloca i16, align 2
 // CHECK4-NEXT:    [[B_ADDR:%.*]] = alloca i16, align 2
@@ -3585,7 +3585,7 @@
 //
 //
 // CHECK4-LABEL: define {{[^@]+}}@_Z4tbarIsEiT_S0_S0_S0_
-// CHECK4-SAME: (i16 noundef signext [[A:%.*]], i16 noundef signext [[B:%.*]], i16 noundef signext [[C:%.*]], i16 noundef signext [[D:%.*]]) #[[ATTR0]] comdat {
+// CHECK4-SAME: (i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]], i16 noundef [[D:%.*]]) #[[ATTR0]] comdat {
 // CHECK4-NEXT:  entry:
 // CHECK4-NEXT:    [[A_ADDR:%.*]] = alloca i16, align 2
 // CHECK4-NEXT:    [[B_ADDR:%.*]] = alloca i16, align 2
Index: clang/test/CodeGenObjC/property-atomic-bool.m
===================================================================
--- clang/test/CodeGenObjC/property-atomic-bool.m
+++ clang/test/CodeGenObjC/property-atomic-bool.m
@@ -5,7 +5,7 @@
 // CHECK:   %[[TOBOOL:.*]] = trunc i8 %[[ATOMIC_LOAD]] to i1
 // CHECK:   ret i1 %[[TOBOOL]]
 
-// CHECK: define internal void @"\01-[A0 setP:]"({{.*}} i1 noundef zeroext {{.*}})
+// CHECK: define internal void @"\01-[A0 setP:]"({{.*}} i1 noundef {{.*}})
 // CHECK:   store atomic i8 %{{.*}}, i8* %{{.*}} seq_cst, align 1
 // CHECK:   ret void
 
@@ -14,7 +14,7 @@
 // CHECK:   %[[TOBOOL:.*]] = trunc i8 %load to i1
 // CHECK:   ret i1 %[[TOBOOL]]
 
-// CHECK: define internal void @"\01-[A1 setP:]"({{.*}} i1 noundef zeroext %p)
+// CHECK: define internal void @"\01-[A1 setP:]"({{.*}} i1 noundef %p)
 // CHECK:   store atomic i8 %{{.*}}, i8* %{{.*}} unordered, align 1
 // CHECK:   ret void
 
Index: clang/test/CodeGenCXX/virtual-bases.cpp
===================================================================
--- clang/test/CodeGenCXX/virtual-bases.cpp
+++ clang/test/CodeGenCXX/virtual-bases.cpp
@@ -20,8 +20,8 @@
   C(bool);
 };
 
-// CHECK-LABEL: define{{.*}} void @_ZN1CC2Eb(%struct.C* {{[^,]*}} %this, i8** noundef %vtt, i1 noundef zeroext %0) unnamed_addr
-// CHECK-LABEL: define{{.*}} void @_ZN1CC1Eb(%struct.C* {{[^,]*}} %this, i1 noundef zeroext %0) unnamed_addr
+// CHECK-LABEL: define{{.*}} void @_ZN1CC2Eb(%struct.C* {{[^,]*}} %this, i8** noundef %vtt, i1 noundef %0) unnamed_addr
+// CHECK-LABEL: define{{.*}} void @_ZN1CC1Eb(%struct.C* {{[^,]*}} %this, i1 noundef %0) unnamed_addr
 C::C(bool) { }
 
 // PR6251
Index: clang/test/CodeGenCXX/new-overflow.cpp
===================================================================
--- clang/test/CodeGenCXX/new-overflow.cpp
+++ clang/test/CodeGenCXX/new-overflow.cpp
@@ -11,7 +11,7 @@
 
   typedef A elt;
 
-  // CHECK:    define{{.*}} [[A:%.*]]* @_ZN5test04testEs(i16 noundef signext
+  // CHECK:    define{{.*}} [[A:%.*]]* @_ZN5test04testEs(i16 noundef
   // CHECK:      [[N:%.*]] = sext i16 {{%.*}} to i32
   // CHECK-NEXT: [[T0:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[N]], i32 4)
   // CHECK-NEXT: [[T1:%.*]] = extractvalue { i32, i1 } [[T0]], 1
@@ -33,7 +33,7 @@
 
   typedef A elt[100];
 
-  // CHECK:    define{{.*}} [100 x [[A:%.*]]]* @_ZN5test14testEs(i16 noundef signext
+  // CHECK:    define{{.*}} [100 x [[A:%.*]]]* @_ZN5test14testEs(i16 noundef
   // CHECK:      [[N:%.*]] = sext i16 {{%.*}} to i32
   // CHECK-NEXT: [[T0:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[N]], i32 400)
   // CHECK-NEXT: [[T1:%.*]] = extractvalue { i32, i1 } [[T0]], 1
@@ -57,7 +57,7 @@
 
   typedef A elt[100];
 
-  // CHECK:    define{{.*}} [100 x [[A:%.*]]]* @_ZN5test24testEs(i16 noundef signext
+  // CHECK:    define{{.*}} [100 x [[A:%.*]]]* @_ZN5test24testEs(i16 noundef
   // CHECK:      [[N:%.*]] = sext i16 {{%.*}} to i32
   // CHECK-NEXT: [[T0:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[N]], i32 400)
   // CHECK-NEXT: [[T1:%.*]] = extractvalue { i32, i1 } [[T0]], 1
@@ -83,7 +83,7 @@
 
   typedef A elt;
 
-  // CHECK:    define{{.*}} [[A:%.*]]* @_ZN5test44testEs(i16 noundef signext
+  // CHECK:    define{{.*}} [[A:%.*]]* @_ZN5test44testEs(i16 noundef
   // CHECK:      [[N:%.*]] = sext i16 {{%.*}} to i32
   // CHECK-NEXT: call noalias noundef nonnull i8* @_Znaj(i32 noundef [[N]])
   // CHECK:      getelementptr inbounds {{.*}}, i32 [[N]]
@@ -118,7 +118,7 @@
 
   typedef A elt;
 
-  // CHECK:    define{{.*}} [[A:%.*]]* @_ZN5test64testEt(i16 noundef zeroext
+  // CHECK:    define{{.*}} [[A:%.*]]* @_ZN5test64testEt(i16 noundef
   // CHECK:      [[N:%.*]] = zext i16 {{%.*}} to i32
   // CHECK-NEXT: [[T0:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[N]], i32 4)
   // CHECK-NEXT: [[T1:%.*]] = extractvalue { i32, i1 } [[T0]], 1
@@ -140,7 +140,7 @@
 
   typedef A elt[100];
 
-  // CHECK:    define{{.*}} [100 x [[A:%.*]]]* @_ZN5test74testEt(i16 noundef zeroext
+  // CHECK:    define{{.*}} [100 x [[A:%.*]]]* @_ZN5test74testEt(i16 noundef
   // CHECK:      [[N:%.*]] = zext i16 {{%.*}} to i32
   // CHECK-NEXT: [[T0:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[N]], i32 400)
   // CHECK-NEXT: [[T1:%.*]] = extractvalue { i32, i1 } [[T0]], 1
Index: clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
===================================================================
--- clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
+++ clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
@@ -94,7 +94,7 @@
   return (cond ? TakesTwo(A(), A()) : CouldThrow());
 }
 
-// WIN32-LABEL: define dso_local noundef i32 @"?HasConditionalCleanup@@YAH_N@Z"(i1 noundef zeroext %{{.*}}) {{.*}} {
+// WIN32-LABEL: define dso_local noundef i32 @"?HasConditionalCleanup@@YAH_N@Z"(i1 noundef %{{.*}}) {{.*}} {
 // WIN32:   store i1 false
 // WIN32:   br i1
 // WIN32:   call i8* @llvm.stacksave()
Index: clang/test/CodeGenCXX/ext-int.cpp
===================================================================
--- clang/test/CodeGenCXX/ext-int.cpp
+++ clang/test/CodeGenCXX/ext-int.cpp
@@ -107,9 +107,9 @@
 };
 
 void UnderlyingTypeUsage(AsEnumUnderlyingType Param) {
-  // LIN: define{{.*}} void @_Z19UnderlyingTypeUsage20AsEnumUnderlyingType(i9 signext %
+  // LIN: define{{.*}} void @_Z19UnderlyingTypeUsage20AsEnumUnderlyingType(i9 %
   // WIN64: define dso_local void @"?UnderlyingTypeUsage@@YAXW4AsEnumUnderlyingType@@@Z"(i9 %
-  // WIN32: define dso_local void @"?UnderlyingTypeUsage@@YAXW4AsEnumUnderlyingType@@@Z"(i9 signext %
+  // WIN32: define dso_local void @"?UnderlyingTypeUsage@@YAXW4AsEnumUnderlyingType@@@Z"(i9 %
   AsEnumUnderlyingType Var;
   // CHECK: alloca i9, align 2
   // CHECK: store i9 %{{.*}}, align 2
Index: clang/test/CodeGenCXX/exceptions.cpp
===================================================================
--- clang/test/CodeGenCXX/exceptions.cpp
+++ clang/test/CodeGenCXX/exceptions.cpp
@@ -225,7 +225,7 @@
   // rdar://problem/8439196
   A *b(bool cond) {
 
-    // CHECK:    define{{( dso_local)?}} [[A:%.*]]* @_ZN5test31bEb(i1 zeroext
+    // CHECK:    define{{( dso_local)?}} [[A:%.*]]* @_ZN5test31bEb(i1
     // CHECK:      [[SAVED0:%.*]] = alloca i8*
     // CHECK-NEXT: [[SAVED1:%.*]] = alloca i8*
     // CHECK-NEXT: [[CLEANUPACTIVE:%.*]] = alloca i1
Index: clang/test/CodeGen/vectorcall.c
===================================================================
--- clang/test/CodeGen/vectorcall.c
+++ clang/test/CodeGen/vectorcall.c
@@ -6,7 +6,7 @@
 // X64: define dso_local x86_vectorcallcc void @"\01v1@@16"(i32 noundef %a, i32 noundef %b)
 
 void __vectorcall v2(char a, char b) {}
-// X32: define dso_local x86_vectorcallcc void @"\01v2@@8"(i8 inreg noundef signext %a, i8 inreg noundef signext %b)
+// X32: define dso_local x86_vectorcallcc void @"\01v2@@8"(i8 inreg noundef %a, i8 inreg noundef %b)
 // X64: define dso_local x86_vectorcallcc void @"\01v2@@16"(i8 noundef %a, i8 noundef %b)
 
 struct Small { int x; };
Index: clang/test/CodeGen/regcall.c
===================================================================
--- clang/test/CodeGen/regcall.c
+++ clang/test/CodeGen/regcall.c
@@ -18,10 +18,10 @@
 // Lin64: define{{.*}} x86_regcallcc void @__regcall3__v1b(i32 noundef %a, i32 noundef %b)
 
 void __regcall v2(char a, char b) {}
-// Win32: define dso_local x86_regcallcc void @__regcall3__v2(i8 inreg noundef signext %a, i8 inreg noundef signext %b)
+// Win32: define dso_local x86_regcallcc void @__regcall3__v2(i8 inreg noundef %a, i8 inreg noundef %b)
 // Win64: define dso_local x86_regcallcc void @__regcall3__v2(i8 noundef %a, i8 noundef %b)
-// Lin32: define{{.*}} x86_regcallcc void @__regcall3__v2(i8 inreg noundef signext %a, i8 inreg noundef signext %b)
-// Lin64: define{{.*}} x86_regcallcc void @__regcall3__v2(i8 noundef signext %a, i8 noundef signext %b)
+// Lin32: define{{.*}} x86_regcallcc void @__regcall3__v2(i8 inreg noundef %a, i8 inreg noundef %b)
+// Lin64: define{{.*}} x86_regcallcc void @__regcall3__v2(i8 noundef %a, i8 noundef %b)
 
 struct Small { int x; };
 void __regcall v3(int a, struct Small b, int c) {}
Index: clang/test/CodeGen/ms-inline-asm.c
===================================================================
--- clang/test/CodeGen/ms-inline-asm.c
+++ clang/test/CodeGen/ms-inline-asm.c
@@ -581,7 +581,7 @@
 }
 
 void t41(unsigned short a) {
-// CHECK-LABEL: define{{.*}} void @t41(i16 noundef zeroext %a)
+// CHECK-LABEL: define{{.*}} void @t41(i16 noundef %a)
   __asm mov cs, a;
 // CHECK: mov cs, $0
   __asm mov ds, a;
Index: clang/test/CodeGen/matrix-type-operators.c
===================================================================
--- clang/test/CodeGen/matrix-type-operators.c
+++ clang/test/CodeGen/matrix-type-operators.c
@@ -272,7 +272,7 @@
 }
 
 void add_matrix_scalar_int_short(ix9x3_t a, short vs) {
-  // CHECK-LABEL: define{{.*}} void @add_matrix_scalar_int_short(<27 x i32> noundef %a, i16 noundef signext %vs)
+  // CHECK-LABEL: define{{.*}} void @add_matrix_scalar_int_short(<27 x i32> noundef %a, i16 noundef %vs)
   // CHECK:        [[MATRIX:%.*]] = load <27 x i32>, <27 x i32>* [[MAT_ADDR:%.*]], align 4
   // CHECK-NEXT:   [[SCALAR:%.*]] = load i16, i16* %vs.addr, align 2
   // CHECK-NEXT:   [[SCALAR_EXT:%.*]] = sext i16 [[SCALAR]] to i32
@@ -285,7 +285,7 @@
 }
 
 void add_compound_matrix_scalar_int_short(ix9x3_t a, short vs) {
-  // CHECK-LABEL: define{{.*}} void @add_compound_matrix_scalar_int_short(<27 x i32> noundef %a, i16 noundef signext %vs)
+  // CHECK-LABEL: define{{.*}} void @add_compound_matrix_scalar_int_short(<27 x i32> noundef %a, i16 noundef %vs)
   // CHECK:       [[SCALAR:%.*]] = load i16, i16* %vs.addr, align 2
   // CHECK-NEXT:  [[SCALAR_EXT:%.*]] = sext i16 [[SCALAR]] to i32
   // CHECK-NEXT:  [[MATRIX:%.*]] = load <27 x i32>, <27 x i32>* %0, align 4
@@ -298,7 +298,7 @@
 }
 
 void subtract_compound_matrix_scalar_int_short(ix9x3_t a, short vs) {
-  // CHECK-LABEL: define{{.*}} void @subtract_compound_matrix_scalar_int_short(<27 x i32> noundef %a, i16 noundef signext %vs)
+  // CHECK-LABEL: define{{.*}} void @subtract_compound_matrix_scalar_int_short(<27 x i32> noundef %a, i16 noundef %vs)
   // CHECK:       [[SCALAR:%.*]] = load i16, i16* %vs.addr, align 2
   // CHECK-NEXT:  [[SCALAR_EXT:%.*]] = sext i16 [[SCALAR]] to i32
   // CHECK-NEXT:  [[MATRIX:%.*]] = load <27 x i32>, <27 x i32>* %0, align 4
@@ -389,7 +389,7 @@
 }
 
 void add_matrix_scalar_long_long_int_short(ullx4x2_t b, short vs) {
-  // CHECK-LABEL: define{{.*}} void @add_matrix_scalar_long_long_int_short(<8 x i64> noundef %b, i16 noundef signext %vs)
+  // CHECK-LABEL: define{{.*}} void @add_matrix_scalar_long_long_int_short(<8 x i64> noundef %b, i16 noundef %vs)
   // CHECK:         [[SCALAR:%.*]] = load i16, i16* %vs.addr, align 2
   // CHECK-NEXT:    [[SCALAR_EXT:%.*]] = sext i16 [[SCALAR]] to i64
   // CHECK-NEXT:    [[MATRIX:%.*]] = load <8 x i64>, <8 x i64>* {{.*}}, align 8
@@ -402,7 +402,7 @@
 }
 
 void add_compound_matrix_scalar_long_long_int_short(ullx4x2_t b, short vs) {
-  // CHECK-LABEL: define{{.*}} void @add_compound_matrix_scalar_long_long_int_short(<8 x i64> noundef %b, i16 noundef signext %vs)
+  // CHECK-LABEL: define{{.*}} void @add_compound_matrix_scalar_long_long_int_short(<8 x i64> noundef %b, i16 noundef %vs)
   // CHECK:       [[SCALAR:%.*]] = load i16, i16* %vs.addr, align 2
   // CHECK-NEXT:  [[SCALAR_EXT:%.*]] = sext i16 [[SCALAR]] to i64
   // CHECK-NEXT:  [[MATRIX:%.*]] = load <8 x i64>, <8 x i64>* %0, align 8
@@ -415,7 +415,7 @@
 }
 
 void subtract_compound_matrix_scalar_long_long_int_short(ullx4x2_t b, short vs) {
-  // CHECK-LABEL: define{{.*}} void @subtract_compound_matrix_scalar_long_long_int_short(<8 x i64> noundef %b, i16 noundef signext %vs)
+  // CHECK-LABEL: define{{.*}} void @subtract_compound_matrix_scalar_long_long_int_short(<8 x i64> noundef %b, i16 noundef %vs)
   // CHECK:       [[SCALAR:%.*]] = load i16, i16* %vs.addr, align 2
   // CHECK-NEXT:  [[SCALAR_EXT:%.*]] = sext i16 [[SCALAR]] to i64
   // CHECK-NEXT:  [[MATRIX:%.*]] = load <8 x i64>, <8 x i64>* %0, align 8
Index: clang/test/CodeGen/matrix-type-builtins.c
===================================================================
--- clang/test/CodeGen/matrix-type-builtins.c
+++ clang/test/CodeGen/matrix-type-builtins.c
@@ -161,7 +161,7 @@
 }
 
 void column_major_load_with_stride_math_s_int(int *Ptr, short S) {
-  // COMMON-LABEL:  define{{.*}} void @column_major_load_with_stride_math_s_int(i32* %Ptr, i16 signext %S)
+  // COMMON-LABEL:  define{{.*}} void @column_major_load_with_stride_math_s_int(i32* %Ptr, i16 %S)
   // COMMON:         [[S:%.*]] = load i16, i16* %S.addr, align 2
   // COMMON-NEXT:    [[S_EXT:%.*]] = sext i16 [[S]] to i32
   // COMMON-NEXT:    [[STRIDE:%.*]] = add nsw i32 [[S_EXT]], 32
@@ -268,7 +268,7 @@
 }
 
 void column_major_store_with_stride_math_s_int(int *Ptr, short S) {
-  // COMMON-LABEL: define{{.*}} void @column_major_store_with_stride_math_s_int(i32* %Ptr, i16 signext %S)
+  // COMMON-LABEL: define{{.*}} void @column_major_store_with_stride_math_s_int(i32* %Ptr, i16 %S)
   // COMMON:         [[M:%.*]] = load <80 x i32>, <80 x i32>* {{.*}}, align 4
   // CHECK32-NEXT:   [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 4
   // CHECK64-NEXT:   [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8
Index: clang/test/CodeGen/mangle-windows.c
===================================================================
--- clang/test/CodeGen/mangle-windows.c
+++ clang/test/CodeGen/mangle-windows.c
@@ -47,7 +47,7 @@
 // X64: define dso_local void @f8(
 
 void __fastcall f9(long long a, char b, char c, short d) {}
-// CHECK: define dso_local x86_fastcallcc void @"\01@f9@20"(i64 noundef %a, i8 noundef signext %b, i8 noundef signext %c, i16 noundef signext %d)
+// CHECK: define dso_local x86_fastcallcc void @"\01@f9@20"(i64 noundef %a, i8 noundef %b, i8 noundef %c, i16 noundef %d)
 // X64: define dso_local void @f9(
 
 void f12(void) {}
Index: clang/test/CodeGen/function-attributes.c
===================================================================
--- clang/test/CodeGen/function-attributes.c
+++ clang/test/CodeGen/function-attributes.c
@@ -3,12 +3,12 @@
 // RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-unknown-unknown -emit-llvm -disable-llvm-passes -Os -std=c99 -o - %s | FileCheck %s
 // CHECK: define{{.*}} signext i8 @f0(i32 noundef %x) [[NUW:#[0-9]+]]
 // CHECK: define{{.*}} zeroext i8 @f1(i32 noundef %x) [[NUW]]
-// CHECK: define{{.*}} void @f2(i8 noundef signext %x) [[NUW]]
-// CHECK: define{{.*}} void @f3(i8 noundef zeroext %x) [[NUW]]
+// CHECK: define{{.*}} void @f2(i8 noundef %x) [[NUW]]
+// CHECK: define{{.*}} void @f3(i8 noundef %x) [[NUW]]
 // CHECK: define{{.*}} signext i16 @f4(i32 noundef %x) [[NUW]]
 // CHECK: define{{.*}} zeroext i16 @f5(i32 noundef %x) [[NUW]]
-// CHECK: define{{.*}} void @f6(i16 noundef signext %x) [[NUW]]
-// CHECK: define{{.*}} void @f7(i16 noundef zeroext %x) [[NUW]]
+// CHECK: define{{.*}} void @f6(i16 noundef %x) [[NUW]]
+// CHECK: define{{.*}} void @f7(i16 noundef %x) [[NUW]]
 
 signed char f0(int x) { return x; }
 
Index: clang/test/CodeGen/ext-int-cc.c
===================================================================
--- clang/test/CodeGen/ext-int-cc.c
+++ clang/test/CodeGen/ext-int-cc.c
@@ -89,10 +89,10 @@
 
 // Make sure we follow the signext rules for promotable integer types.
 void ParamPassing3(_BitInt(15) a, _BitInt(31) b) {}
-// LIN64: define{{.*}} void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}})
+// LIN64: define{{.*}} void @ParamPassing3(i15 %{{.+}}, i31 %{{.+}})
 // WIN64: define dso_local void @ParamPassing3(i15 %{{.+}}, i31 %{{.+}})
-// LIN32: define{{.*}} void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}})
-// WIN32: define dso_local void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}})
+// LIN32: define{{.*}} void @ParamPassing3(i15 %{{.+}}, i31 %{{.+}})
+// WIN32: define dso_local void @ParamPassing3(i15 %{{.+}}, i31 %{{.+}})
 // NACL: define{{.*}} void @ParamPassing3(i15 %{{.+}}, i31 %{{.+}})
 // NVPTX64: define{{.*}} void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}})
 // NVPTX: define{{.*}} void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}})
Index: clang/test/CodeGen/catch-implicit-integer-sign-changes.c
===================================================================
--- clang/test/CodeGen/catch-implicit-integer-sign-changes.c
+++ clang/test/CodeGen/catch-implicit-integer-sign-changes.c
@@ -99,7 +99,7 @@
 // These 3 result (after optimizations) in simple 'icmp sge i8 %src, 0'
 
 // CHECK-LABEL: @signed_char_to_unsigned_char
-// CHECK-SAME: (i8 noundef signext %[[SRC:.*]])
+// CHECK-SAME: (i8 noundef %[[SRC:.*]])
 unsigned char signed_char_to_unsigned_char(signed char src) {
   // CHECK: %[[SRC_ADDR:.*]] = alloca i8
   // CHECK-NEXT: store i8 %[[SRC]], i8* %[[SRC_ADDR]]
@@ -122,7 +122,7 @@
 }
 
 // CHECK-LABEL: @unsigned_char_to_signed_char
-// CHECK-SAME: (i8 noundef zeroext %[[SRC:.*]])
+// CHECK-SAME: (i8 noundef %[[SRC:.*]])
 signed char unsigned_char_to_signed_char(unsigned char src) {
   // CHECK: %[[SRC_ADDR:.*]] = alloca i8
   // CHECK-NEXT: store i8 %[[SRC]], i8* %[[SRC_ADDR]]
@@ -145,7 +145,7 @@
 }
 
 // CHECK-LABEL: @signed_char_to_unsigned_int
-// CHECK-SAME: (i8 noundef signext %[[SRC:.*]])
+// CHECK-SAME: (i8 noundef %[[SRC:.*]])
 unsigned int signed_char_to_unsigned_int(signed char src) {
   // CHECK: %[[SRC_ADDR:.*]] = alloca i8
   // CHECK-NEXT: store i8 %[[SRC]], i8* %[[SRC_ADDR]]
Index: clang/test/CodeGen/builtin-align.c
===================================================================
--- clang/test/CodeGen/builtin-align.c
+++ clang/test/CodeGen/builtin-align.c
@@ -98,7 +98,7 @@
 // CHECK-LONG-NEXT:    ret i1 [[IS_ALIGNED]]
 //
 // CHECK-USHORT-LABEL: define {{[^@]+}}@is_aligned
-// CHECK-USHORT-SAME: (i16 noundef zeroext [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
+// CHECK-USHORT-SAME: (i16 noundef [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
 // CHECK-USHORT-NEXT:  entry:
 // CHECK-USHORT-NEXT:    [[ALIGNMENT:%.*]] = trunc i32 [[ALIGN]] to i16
 // CHECK-USHORT-NEXT:    [[MASK:%.*]] = sub i16 [[ALIGNMENT]], 1
@@ -152,7 +152,7 @@
 // CHECK-LONG-NEXT:    ret i64 [[ALIGNED_RESULT]]
 //
 // CHECK-USHORT-LABEL: define {{[^@]+}}@align_up
-// CHECK-USHORT-SAME: (i16 noundef zeroext [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
+// CHECK-USHORT-SAME: (i16 noundef [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
 // CHECK-USHORT-NEXT:  entry:
 // CHECK-USHORT-NEXT:    [[ALIGNMENT:%.*]] = trunc i32 [[ALIGN]] to i16
 // CHECK-USHORT-NEXT:    [[MASK:%.*]] = sub i16 [[ALIGNMENT]], 1
@@ -204,7 +204,7 @@
 // CHECK-LONG-NEXT:    ret i64 [[ALIGNED_RESULT]]
 //
 // CHECK-USHORT-LABEL: define {{[^@]+}}@align_down
-// CHECK-USHORT-SAME: (i16 noundef zeroext [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
+// CHECK-USHORT-SAME: (i16 noundef [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
 // CHECK-USHORT-NEXT:  entry:
 // CHECK-USHORT-NEXT:    [[ALIGNMENT:%.*]] = trunc i32 [[ALIGN]] to i16
 // CHECK-USHORT-NEXT:    [[MASK:%.*]] = sub i16 [[ALIGNMENT]], 1
Index: clang/test/CodeGen/attr-noundef.cpp
===================================================================
--- clang/test/CodeGen/attr-noundef.cpp
+++ clang/test/CodeGen/attr-noundef.cpp
@@ -161,7 +161,7 @@
 // TODO: for now, ExtInt is only noundef if it is sign/zero-extended
 // CHECK-INTEL: [[DEFINE]] noundef signext i3 @{{.*}}ret_BitInt{{.*}}()
 // CHECK-AARCH: [[DEFINE]] i3 @{{.*}}ret_BitInt{{.*}}()
-// CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_BitInt{{.*}}(i3 noundef signext %
+// CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_BitInt{{.*}}(i3 %
 // CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_BitInt{{.*}}(i3 %
 // CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_large_BitInt{{.*}}(i64 %{{.*}}, i64 %
 // CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_large_BitInt{{.*}}(i127 %
Index: clang/test/CodeGen/X86/x86_64-arguments.c
===================================================================
--- clang/test/CodeGen/X86/x86_64-arguments.c
+++ clang/test/CodeGen/X86/x86_64-arguments.c
@@ -36,7 +36,7 @@
   return 0;
 }
 
-// CHECK-LABEL: define{{.*}} void @f6(i8 noundef signext %a0, i16 noundef signext %a1, i32 noundef %a2, i64 noundef %a3, i8* noundef %a4)
+// CHECK-LABEL: define{{.*}} void @f6(i8 noundef %a0, i16 noundef %a1, i32 noundef %a2, i64 noundef %a3, i8* noundef %a4)
 void f6(char a0, short a1, int a2, long long a3, void *a4) {
 }
 
Index: clang/test/CodeGen/X86/x86_64-arguments-nacl.c
===================================================================
--- clang/test/CodeGen/X86/x86_64-arguments-nacl.c
+++ clang/test/CodeGen/X86/x86_64-arguments-nacl.c
@@ -30,7 +30,7 @@
   return 0;
 }
 
-// CHECK-LABEL: define{{.*}} void @f6(i8 noundef signext %a0, i16 noundef signext %a1, i32 noundef %a2, i64 noundef %a3, i8* noundef %a4)
+// CHECK-LABEL: define{{.*}} void @f6(i8 noundef %a0, i16 noundef %a1, i32 noundef %a2, i64 noundef %a3, i8* noundef %a4)
 void f6(char a0, short a1, int a2, long long a3, void *a4) {
 }
 
Index: clang/test/CodeGen/X86/x86_32-arguments-linux.c
===================================================================
--- clang/test/CodeGen/X86/x86_32-arguments-linux.c
+++ clang/test/CodeGen/X86/x86_32-arguments-linux.c
@@ -2,7 +2,7 @@
 // RUN: FileCheck < %t %s
 
 // CHECK-LABEL: define{{.*}} void @f56(
-// CHECK: i8 noundef signext %a0, %struct.s56_0* noundef byval(%struct.s56_0) align 4 %a1,
+// CHECK: i8 noundef %a0, %struct.s56_0* noundef byval(%struct.s56_0) align 4 %a1,
 // CHECK: i64 noundef %a2.coerce, %struct.s56_1* noundef byval(%struct.s56_1) align 4 %0,
 // CHECK: <1 x double> noundef %a4, %struct.s56_2* noundef byval(%struct.s56_2) align 4 %1,
 // CHECK: <4 x i32> noundef %a6, %struct.s56_3* noundef byval(%struct.s56_3) align 4 %2,
Index: clang/test/CodeGen/X86/x86_32-arguments-darwin.c
===================================================================
--- clang/test/CodeGen/X86/x86_32-arguments-darwin.c
+++ clang/test/CodeGen/X86/x86_32-arguments-darwin.c
@@ -30,7 +30,7 @@
   return 0;
 }
 
-// CHECK-LABEL: define{{.*}} void @f6(i8 noundef signext %a0, i16 noundef signext %a1, i32 noundef %a2, i64 noundef %a3, i8* noundef %a4)
+// CHECK-LABEL: define{{.*}} void @f6(i8 noundef %a0, i16 noundef %a1, i32 noundef %a2, i64 noundef %a3, i8* noundef %a4)
 void f6(char a0, short a1, int a2, long long a3, void *a4) {}
 
 // CHECK-LABEL: define{{.*}} void @f7(i32 noundef %a0)
@@ -228,7 +228,7 @@
 v4i32 f55(v4i32 arg) { return arg+arg; }
 
 // CHECK-LABEL: define{{.*}} void @f56(
-// CHECK: i8 noundef signext %a0, %struct.s56_0* noundef byval(%struct.s56_0) align 4 %a1,
+// CHECK: i8 noundef %a0, %struct.s56_0* noundef byval(%struct.s56_0) align 4 %a1,
 // CHECK: i64 noundef %a2.coerce, %struct.s56_1* noundef byval(%struct.s56_1) align 4 %0,
 // CHECK: i64 noundef %a4.coerce, %struct.s56_2* noundef byval(%struct.s56_2) align 4 %1,
 // CHECK: <4 x i32> noundef %a6, %struct.s56_3* noundef byval(%struct.s56_3) align 16 %a7,
Index: clang/test/CodeGen/X86/integer_argument_passing.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/X86/integer_argument_passing.c
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -O2 -triple -x86_64-linux-gnu %s -emit-llvm -o - | FileCheck %s --check-prefixes=EXTEND,CHECK
+// RUN: %clang_cc1 -O2 -triple -i386-linux-gnu %s -emit-llvm -o - | FileCheck %s --check-prefixes=EXTEND,CHECK
+// RUN: %clang_cc1 -O2 -triple -i386-pc-win32 %s -emit-llvm -o - | FileCheck %s --check-prefixes=EXTEND,CHECK
+// RUN: %clang_cc1 -O2 -mno-conservative-extend -triple -x86_64-linux-gnu %s -emit-llvm -o - | FileCheck %s --check-prefixes=NOCALLEE-EXTEND,CHECK
+// RUN: %clang_cc1 -O2 -mno-conservative-extend -triple -i386-linux-gnu %s -emit-llvm -o - | FileCheck %s --check-prefixes=NOCALLEE-EXTEND,CHECK
+// RUN: %clang_cc1 -O2 -mno-conservative-extend -triple -i386-pc-win32 %s -emit-llvm -o - | FileCheck %s --check-prefixes=NOCALLEE-EXTEND,CHECK
+
+// EXTEND: define{{.*}} i32 @ZeroExtend(i8 noundef %a, i16 noundef %b)
+// NOCALLEE-EXTEND : define{{.*}} i32 @ZeroExtend(i8 noundef zeroext %a, i16 noundef zeroext %b)
+unsigned ZeroExtend(unsigned char a, unsigned short b) {
+  return a*b;
+}
+
+// EXTEND: define{{.*}} i32 @SignExtend(i8 noundef %a, i16 noundef %b)
+// NOCALLEE-EXTEND: define{{.*}} i32 @SignExtend(i8 noundef signext %a, i16 noundef signext %b)
+int SignExtend(char a, short b) {
+  return a*b;
+}
+
+extern void f0(unsigned char x);
+extern void f1(unsigned short x);
+extern void f2(char x);
+extern void f3(short x);
+
+// CHECK: call void @f0(i8 noundef zeroext {{.*}})
+void caller0(unsigned char x) { f0(x); }
+// CHECK: call void @f1(i16 noundef zeroext {{.*}})
+void caller1(unsigned short x) { f1(x); }
+// CHECK: call void @f2(i8 noundef signext {{.*}})
+void caller2(char x) { f2(x); }
+// CHECK: call void @f3(i16 noundef signext {{.*}})
+void caller3(short x) { f3(x); }
Index: clang/test/CodeGen/2007-06-18-SextAttrAggregate.c
===================================================================
--- clang/test/CodeGen/2007-06-18-SextAttrAggregate.c
+++ clang/test/CodeGen/2007-06-18-SextAttrAggregate.c
@@ -1,12 +1,12 @@
 // RUN: %clang_cc1 -no-enable-noundef-analysis %s -o - -emit-llvm | FileCheck %s
-// XFAIL: aarch64, arm64, x86_64-pc-windows-msvc, x86_64-w64-windows-gnu, x86_64-pc-windows-gnu
+// XFAIL: aarch64, arm64, x86_64-pc-windows-msvc, x86_64-w64-windows-gnu, x86_64-pc-windows-gnu, x86_64-linux
 
 // PR1513
 
 // AArch64 ABI actually requires the reverse of what this is testing: the callee
 // does any extensions and remaining bits are unspecified.
 
-// Win64 ABI does expect extensions for type smaller than 64bits.
+// X86_64 ABI does expect extensions for type smaller than 64bits.
 
 // Technically this test wasn't written to test that feature, but it's a
 // valuable check nevertheless.
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -6196,6 +6196,9 @@
   Args.addOptOutFlag(CmdArgs, options::OPT_mstack_arg_probe,
                      options::OPT_mno_stack_arg_probe);
 
+  Args.addOptOutFlag(CmdArgs, options::OPT_mconservative_extend,
+                    options::OPT_mno_conservative_extend);
+
   if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it,
                                options::OPT_mno_restrict_it)) {
     if (A->getOption().matches(options::OPT_mrestrict_it)) {
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -277,6 +277,9 @@
     OS << "CoerceAndExpand Type=";
     getCoerceAndExpandType()->print(OS);
     break;
+  case ConservativeExtend:
+    OS << "ConservativeExtend";
+    break;
   }
   OS << ")\n";
 }
@@ -1925,11 +1928,14 @@
     Ty = EnumTy->getDecl()->getIntegerType();
 
   bool InReg = shouldPrimitiveUseInReg(Ty, State);
+  bool IsConservativeExtend = getCodeGenOpts().ConservativeExtend;
 
   if (isPromotableIntegerTypeForABI(Ty)) {
     if (InReg)
-      return ABIArgInfo::getExtendInReg(Ty);
-    return ABIArgInfo::getExtend(Ty);
+      return IsConservativeExtend ? ABIArgInfo::getConservativeExtendInReg(Ty)
+                                  : ABIArgInfo::getExtendInReg(Ty);
+    return IsConservativeExtend ? ABIArgInfo::getConservativeExtend(Ty)
+                                : ABIArgInfo::getExtend(Ty);
   }
 
   if (const auto *EIT = Ty->getAs<BitIntType>()) {
@@ -2050,6 +2056,7 @@
   case ABIArgInfo::Indirect:
   case ABIArgInfo::Direct:
   case ABIArgInfo::Extend:
+  case ABIArgInfo::ConservativeExtend:
     return !Info.getInReg();
   case ABIArgInfo::Expand:
   case ABIArgInfo::CoerceAndExpand:
@@ -3805,8 +3812,11 @@
         Ty = EnumTy->getDecl()->getIntegerType();
 
       if (Ty->isIntegralOrEnumerationType() &&
-          isPromotableIntegerTypeForABI(Ty))
+          isPromotableIntegerTypeForABI(Ty)) {
+        if (getCodeGenOpts().ConservativeExtend)
+          return ABIArgInfo::getConservativeExtend(Ty);
         return ABIArgInfo::getExtend(Ty);
+      }
     }
 
     break;
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -1510,7 +1510,8 @@
 
     switch (AI.getKind()) {
     case ABIArgInfo::Extend:
-    case ABIArgInfo::Direct: {
+    case ABIArgInfo::Direct:
+    case ABIArgInfo::ConservativeExtend: {
       // FIXME: handle sseregparm someday...
       llvm::StructType *STy = dyn_cast<llvm::StructType>(AI.getCoerceToType());
       if (AI.isDirect() && AI.getCanBeFlattened() && STy) {
@@ -1617,6 +1618,7 @@
 
   case ABIArgInfo::Extend:
   case ABIArgInfo::Direct:
+  case ABIArgInfo::ConservativeExtend:
     resultType = retAI.getCoerceToType();
     break;
 
@@ -1697,7 +1699,8 @@
       break;
     }
     case ABIArgInfo::Extend:
-    case ABIArgInfo::Direct: {
+    case ABIArgInfo::Direct:
+    case ABIArgInfo::ConservativeExtend: {
       // Fast-isel and the optimizer generally like scalar values better than
       // FCAs, so we flatten them if this is safe to do for this argument.
       llvm::Type *argType = ArgInfo.getCoerceToType();
@@ -2310,6 +2313,7 @@
       RetAttrs.addAttribute(llvm::Attribute::ZExt);
     LLVM_FALLTHROUGH;
   case ABIArgInfo::Direct:
+  case ABIArgInfo::ConservativeExtend:
     if (RetAI.getInReg())
       RetAttrs.addAttribute(llvm::Attribute::InReg);
     break;
@@ -2440,10 +2444,16 @@
     // sense to do it here because parameters are so messed up.
     switch (AI.getKind()) {
     case ABIArgInfo::Extend:
-      if (AI.isSignExt())
-        Attrs.addAttribute(llvm::Attribute::SExt);
-      else
-        Attrs.addAttribute(llvm::Attribute::ZExt);
+    case ABIArgInfo::ConservativeExtend:
+      // Always extend the inter argument in callee and caller if the Kind is
+      // ConservativeExtend. In this case, we should only add sext/zext
+      // attribute to the callee.
+      if (AttrOnCallSite || AI.getKind() == ABIArgInfo::Extend) {
+        if (AI.isSignExt())
+          Attrs.addAttribute(llvm::Attribute::SExt);
+        else
+          Attrs.addAttribute(llvm::Attribute::ZExt);
+      }
       LLVM_FALLTHROUGH;
     case ABIArgInfo::Direct:
       if (ArgNo == 0 && FI.isChainCall())
@@ -2786,7 +2796,8 @@
     }
 
     case ABIArgInfo::Extend:
-    case ABIArgInfo::Direct: {
+    case ABIArgInfo::Direct:
+    case ABIArgInfo::ConservativeExtend: {
       auto AI = Fn->getArg(FirstIRArg);
       llvm::Type *LTy = ConvertType(Arg->getType());
 
@@ -3641,6 +3652,7 @@
   }
   case ABIArgInfo::Expand:
   case ABIArgInfo::IndirectAliased:
+  case ABIArgInfo::ConservativeExtend:
     llvm_unreachable("Invalid ABI kind for return argument");
   }
 
@@ -4954,7 +4966,8 @@
       break;
 
     case ABIArgInfo::Extend:
-    case ABIArgInfo::Direct: {
+    case ABIArgInfo::Direct:
+    case ABIArgInfo::ConservativeExtend: {
       if (!isa<llvm::StructType>(ArgInfo.getCoerceToType()) &&
           ArgInfo.getCoerceToType() == ConvertType(info_it->type) &&
           ArgInfo.getDirectOffset() == 0) {
@@ -5557,6 +5570,7 @@
 
     case ABIArgInfo::Expand:
     case ABIArgInfo::IndirectAliased:
+    case ABIArgInfo::ConservativeExtend:
       llvm_unreachable("Invalid ABI kind for return argument");
     }
 
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -3330,6 +3330,12 @@
   NormalizedValues<["Default", "EABI4", "EABI5", "GNU"]>;
 def mtargetos_EQ : Joined<["-"], "mtargetos=">, Group<m_Group>,
   HelpText<"Set the deployment target to be the specified OS and OS version">;
+def mconservative_extend : Flag<["-"], "mconservative-extend">, Group<m_Group>, Flags<[CC1Option]>,
+  HelpText<"Always extend the integer parameter both in the callee and caller."
+           "Do not make any assumptions about the callee and caller">;
+def mno_conservative_extend : Flag<["-"], "mno-conservative-extend">, Group<m_Group>,
+  Flags<[CC1Option]>, MarshallingInfoNegativeFlag<CodeGenOpts<"ConservativeExtend">>,
+  HelpText<"Keep the original integer parameter passing behavior">;
 
 def mno_constant_cfstrings : Flag<["-"], "mno-constant-cfstrings">, Group<m_Group>;
 def mno_global_merge : Flag<["-"], "mno-global-merge">, Group<m_Group>, Flags<[CC1Option]>,
Index: clang/include/clang/CodeGen/CGFunctionInfo.h
===================================================================
--- clang/include/clang/CodeGen/CGFunctionInfo.h
+++ clang/include/clang/CodeGen/CGFunctionInfo.h
@@ -44,6 +44,10 @@
     /// but also emit a zero/sign extension attribute.
     Extend,
 
+    /// ConservativeExtend - Valid only for integer argument types. Same as
+    /// 'Extend' but do not make any assumptions about the caller and callee.
+    ConservativeExtend,
+
     /// Indirect - Pass the argument indirectly via a hidden pointer with the
     /// specified alignment (0 indicates default alignment) and address space.
     Indirect,
@@ -119,7 +123,7 @@
 
   bool canHavePaddingType() const {
     return isDirect() || isExtend() || isIndirect() || isIndirectAliased() ||
-           isExpand();
+           isExpand() || isConservativeExtend();
   }
   void setPaddingType(llvm::Type *T) {
     assert(canHavePaddingType());
@@ -187,6 +191,28 @@
     return getZeroExtend(Ty, T);
   }
 
+  static ABIArgInfo getConservativeExtend(QualType Ty,
+                                          llvm::Type *T = nullptr) {
+    assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
+    auto AI = ABIArgInfo(ConservativeExtend);
+    AI.setCoerceToType(T);
+    AI.setPaddingType(nullptr);
+    AI.setDirectOffset(0);
+    AI.setDirectAlign(0);
+    if (Ty->hasSignedIntegerRepresentation())
+      AI.setSignExt(true);
+    else
+      AI.setSignExt(false);
+    return AI;
+  }
+
+  static ABIArgInfo getConservativeExtendInReg(QualType Ty,
+                                               llvm::Type *T = nullptr) {
+    auto AI = getConservativeExtend(Ty, T);
+    AI.setInReg(true);
+    return AI;
+  }
+
   static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T = nullptr) {
     auto AI = getExtend(Ty, T);
     AI.setInReg(true);
@@ -301,36 +327,42 @@
   bool isIndirectAliased() const { return TheKind == IndirectAliased; }
   bool isExpand() const { return TheKind == Expand; }
   bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
+  bool isConservativeExtend() const { return TheKind == ConservativeExtend; }
 
   bool canHaveCoerceToType() const {
-    return isDirect() || isExtend() || isCoerceAndExpand();
+    return isDirect() || isExtend() || isCoerceAndExpand() ||
+           isConservativeExtend();
   }
 
-  // Direct/Extend accessors
+  // Direct/Extend/ConservativeExtend accessors
   unsigned getDirectOffset() const {
-    assert((isDirect() || isExtend()) && "Not a direct or extend kind");
+    assert((isDirect() || isExtend() || isConservativeExtend()) &&
+           "Invalid kind!");
     return DirectAttr.Offset;
   }
   void setDirectOffset(unsigned Offset) {
-    assert((isDirect() || isExtend()) && "Not a direct or extend kind");
+    assert((isDirect() || isExtend() || isConservativeExtend()) &&
+           "Invalid kind");
     DirectAttr.Offset = Offset;
   }
 
   unsigned getDirectAlign() const {
-    assert((isDirect() || isExtend()) && "Not a direct or extend kind");
+    assert((isDirect() || isExtend() || isConservativeExtend()) &&
+           "Invalid kind");
     return DirectAttr.Align;
   }
   void setDirectAlign(unsigned Align) {
-    assert((isDirect() || isExtend()) && "Not a direct or extend kind");
+    assert((isDirect() || isExtend() || isConservativeExtend()) &&
+           "Invalid kind");
     DirectAttr.Align = Align;
   }
 
   bool isSignExt() const {
-    assert(isExtend() && "Invalid kind!");
+    assert((isExtend() || isConservativeExtend()) && "Invalid kind!");
     return SignExt;
   }
   void setSignExt(bool SExt) {
-    assert(isExtend() && "Invalid kind!");
+    assert((isExtend() || isConservativeExtend()) && "Invalid kind!");
     SignExt = SExt;
   }
 
@@ -376,12 +408,16 @@
   }
 
   bool getInReg() const {
-    assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
+    assert(
+        (isDirect() || isExtend() || isIndirect() || isConservativeExtend()) &&
+        "Invalid kind!");
     return InReg;
   }
 
   void setInReg(bool IR) {
-    assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
+    assert(
+        (isDirect() || isExtend() || isIndirect() || isConservativeExtend()) &&
+        "Invalid kind!");
     InReg = IR;
   }
 
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -472,6 +472,9 @@
 /// Whether to use opaque pointers.
 CODEGENOPT(OpaquePointers, 1, 0)
 
+/// Whether the ingeter parameter should be extended in callee and caller.
+CODEGENOPT(ConservativeExtend, 1, 1)
+
 #undef CODEGENOPT
 #undef ENUM_CODEGENOPT
 #undef VALUE_CODEGENOPT
Index: clang/docs/ClangCommandLineReference.rst
===================================================================
--- clang/docs/ClangCommandLineReference.rst
+++ clang/docs/ClangCommandLineReference.rst
@@ -2985,6 +2985,12 @@
 
 Specify code object ABI version. Allowed values are 2, 3, 4, and 5. Defaults to 4. (AMDGPU only)
 
+.. option:: -mconservative-extend
+Always extend the integer parameter both in the callee and caller.
+
+.. option:: -mno-conservative-extend
+Keep the original integer parameter passing behavior.
+
 .. option:: -mconsole<arg>
 
 .. program:: clang1
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to