diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1714,6 +1714,8 @@ cast(ValTy)->getNumElements(); // Load the `iP` storage object (P is the padded vector size). auto *RawIntV = Builder.CreateLoad(Addr, Volatile, "load_bits"); + applyNoundefToLoadInst(CGM.getCodeGenOpts().EnableNoundefLoadAttr, + ClangVecTy->getElementType(), RawIntV); const auto *RawIntTy = RawIntV->getType(); assert(RawIntTy->isIntegerTy() && "compressed iN storage for bitvectors"); // Bitcast iP -->

. @@ -1738,6 +1740,9 @@ Address Cast = Builder.CreateElementBitCast(Addr, vec4Ty, "castToVec4"); // Now load value. llvm::Value *V = Builder.CreateLoad(Cast, Volatile, "loadVec4"); + applyNoundefToLoadInst(CGM.getCodeGenOpts().EnableNoundefLoadAttr, + ClangVecTy->getElementType(), + dyn_cast(V)); // Shuffle vector to get vec3. V = Builder.CreateShuffleVector(V, ArrayRef{0, 1, 2}, "extractVec"); return EmitFromMemory(V, Ty); diff --git a/clang/test/CodeGenCXX/vector-noundef.cpp b/clang/test/CodeGenCXX/vector-noundef.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/vector-noundef.cpp @@ -0,0 +1,84 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -std=c++17 -triple x86_64-gnu-linux -O0 -enable-noundef-load-analysis -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-gnu-linux -O0 -no-enable-noundef-load-analysis -emit-llvm -o - %s | FileCheck %s --check-prefix=DISABLE + +using VecOfFourBools __attribute__((ext_vector_type(4))) = bool; +using VecOfThreeChars __attribute__((ext_vector_type(3))) = char; +using VecOfThreeUChars __attribute__((ext_vector_type(3))) = unsigned char; + +// CHECK-LABEL: @_Z15getElement4BoolRDv4_b( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[LOAD_BITS:%.*]] = load i8, ptr [[TMP0]], align 1, !noundef [[NOUNDEF2:![0-9]+]] +// CHECK-NEXT: [[TMP1:%.*]] = bitcast i8 [[LOAD_BITS]] to <8 x i1> +// CHECK-NEXT: [[EXTRACTVEC:%.*]] = shufflevector <8 x i1> [[TMP1]], <8 x i1> poison, <4 x i32> +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <4 x i1> [[EXTRACTVEC]], i32 0 +// CHECK-NEXT: ret i1 [[VECEXT]] +// +// DISABLE-LABEL: @_Z15getElement4BoolRDv4_b( +// DISABLE-NEXT: entry: +// DISABLE-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// DISABLE-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 +// DISABLE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// DISABLE-NEXT: [[LOAD_BITS:%.*]] = load i8, ptr [[TMP0]], align 1 +// DISABLE-NEXT: [[TMP1:%.*]] = bitcast i8 [[LOAD_BITS]] to <8 x i1> +// DISABLE-NEXT: [[EXTRACTVEC:%.*]] = shufflevector <8 x i1> [[TMP1]], <8 x i1> poison, <4 x i32> +// DISABLE-NEXT: [[VECEXT:%.*]] = extractelement <4 x i1> [[EXTRACTVEC]], i32 0 +// DISABLE-NEXT: ret i1 [[VECEXT]] +// +bool getElement4Bool(VecOfFourBools& a) +{ + return a[0]; +} + +// CHECK-LABEL: @_Z15getElement3CharRDv3_c( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[LOADVEC4:%.*]] = load <4 x i8>, ptr [[TMP0]], align 4, !noundef [[NOUNDEF2]] +// CHECK-NEXT: [[EXTRACTVEC:%.*]] = shufflevector <4 x i8> [[LOADVEC4]], <4 x i8> poison, <3 x i32> +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <3 x i8> [[EXTRACTVEC]], i32 0 +// CHECK-NEXT: ret i8 [[VECEXT]] +// +// DISABLE-LABEL: @_Z15getElement3CharRDv3_c( +// DISABLE-NEXT: entry: +// DISABLE-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// DISABLE-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 +// DISABLE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// DISABLE-NEXT: [[LOADVEC4:%.*]] = load <4 x i8>, ptr [[TMP0]], align 4 +// DISABLE-NEXT: [[EXTRACTVEC:%.*]] = shufflevector <4 x i8> [[LOADVEC4]], <4 x i8> poison, <3 x i32> +// DISABLE-NEXT: [[VECEXT:%.*]] = extractelement <3 x i8> [[EXTRACTVEC]], i32 0 +// DISABLE-NEXT: ret i8 [[VECEXT]] +// +char getElement3Char(VecOfThreeChars& a) +{ + return a[0]; +} + +// CHECK-LABEL: @_Z16getElement3UCharRDv3_h( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[LOADVEC4:%.*]] = load <4 x i8>, ptr [[TMP0]], align 4 +// CHECK-NEXT: [[EXTRACTVEC:%.*]] = shufflevector <4 x i8> [[LOADVEC4]], <4 x i8> poison, <3 x i32> +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <3 x i8> [[EXTRACTVEC]], i32 0 +// CHECK-NEXT: ret i8 [[VECEXT]] +// +// DISABLE-LABEL: @_Z16getElement3UCharRDv3_h( +// DISABLE-NEXT: entry: +// DISABLE-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// DISABLE-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 +// DISABLE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// DISABLE-NEXT: [[LOADVEC4:%.*]] = load <4 x i8>, ptr [[TMP0]], align 4 +// DISABLE-NEXT: [[EXTRACTVEC:%.*]] = shufflevector <4 x i8> [[LOADVEC4]], <4 x i8> poison, <3 x i32> +// DISABLE-NEXT: [[VECEXT:%.*]] = extractelement <3 x i8> [[EXTRACTVEC]], i32 0 +// DISABLE-NEXT: ret i8 [[VECEXT]] +// +char getElement3UChar(VecOfThreeUChars& a) +{ + return a[0]; +}