Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -3479,6 +3479,13 @@ } } + // Find out if any arguments are required to be integer constant + // expressions. + unsigned ICEArguments = 0; + ASTContext::GetBuiltinTypeError Error; + getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments); + assert(Error == ASTContext::GE_None && "Should not codegen an error"); + SmallVector Ops; llvm::Value *Align = nullptr; for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) { @@ -3541,7 +3548,17 @@ continue; } } - Ops.push_back(EmitScalarExpr(E->getArg(i))); + + if ((ICEArguments & (1 << i)) == 0) { + Ops.push_back(EmitScalarExpr(E->getArg(i))); + } else { + // If this is required to be a constant, constant fold it so that we know + // that the generated intrinsic gets a ConstantInt. + llvm::APSInt Result; + bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result, getContext()); + assert(IsConst && "Constant arg isn't actually constant?"); (void)IsConst; + Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), Result)); + } } switch (BuiltinID) { @@ -4242,9 +4259,27 @@ return Builder.CreateCall(F, {Arg0, Arg1}); } + // Find out if any arguments are required to be integer constant + // expressions. + unsigned ICEArguments = 0; + ASTContext::GetBuiltinTypeError Error; + getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments); + assert(Error == ASTContext::GE_None && "Should not codegen an error"); + llvm::SmallVector Ops; - for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) - Ops.push_back(EmitScalarExpr(E->getArg(i))); + for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) { + if ((ICEArguments & (1 << i)) == 0) { + Ops.push_back(EmitScalarExpr(E->getArg(i))); + } else { + // If this is required to be a constant, constant fold it so that we know + // that the generated intrinsic gets a ConstantInt. + llvm::APSInt Result; + bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result, getContext()); + assert(IsConst && "Constant arg isn't actually constant?"); + (void)IsConst; + Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), Result)); + } + } auto SISDMap = makeArrayRef(AArch64SISDIntrinsicMap); const NeonIntrinsicInfo *Builtin = findNeonIntrinsicInMap( Index: test/CodeGen/neon-immediate-ubsan.c =================================================================== --- /dev/null +++ test/CodeGen/neon-immediate-ubsan.c @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple armv7s-linux-gnu -emit-llvm -O1 -o - %s \ +// RUN: -target-feature +neon -target-cpu cortex-a8 \ +// RUN: -fsanitize=signed-integer-overflow \ +// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=ARMV7 + +// RUN: %clang_cc1 -triple aarch64-unknown-unknown -emit-llvm -O1 -o - %s \ +// RUN: -target-feature +neon -target-cpu cortex-a53 \ +// RUN: -fsanitize=signed-integer-overflow \ +// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=AARCH64 + +// Verify we emit constants for "immediate" builtin arguments. +// Emitting a scalar expression can make the immediate be generated as +// overflow intrinsics, if the overflow sanitizer is enabled. + +// PR23517 + +#include + +int32x2_t test_vqrshrn_n_s64(int64x2_t a) { + // CHECK-LABEL: @test_vqrshrn_n_s64 + // CHECK-AARCH64: call <2 x i32> @llvm.aarch64.neon.sqrshrn.v2i32(<2 x i64> {{.*}}, i32 1) + // CHECK-ARMV7: call <2 x i32> @llvm.arm.neon.vqrshiftns.v2i32(<2 x i64> {{.*}}, <2 x i64> ) + return vqrshrn_n_s64(a, 0 + 1); +} Index: utils/TableGen/NeonEmitter.cpp =================================================================== --- utils/TableGen/NeonEmitter.cpp +++ utils/TableGen/NeonEmitter.cpp @@ -131,7 +131,7 @@ private: TypeSpec TS; - bool Float, Signed, Void, Poly, Constant, Pointer; + bool Float, Signed, Immediate, Void, Poly, Constant, Pointer; // ScalarForMangling and NoManglingQ are really not suited to live here as // they are not related to the type. But they live in the TypeSpec (not the // prototype), so this is really the only place to store them. @@ -140,13 +140,13 @@ public: Type() - : Float(false), Signed(false), Void(true), Poly(false), Constant(false), - Pointer(false), ScalarForMangling(false), NoManglingQ(false), - Bitwidth(0), ElementBitwidth(0), NumVectors(0) {} - - Type(TypeSpec TS, char CharMod) - : TS(TS), Float(false), Signed(false), Void(false), Poly(false), + : Float(false), Signed(false), Immediate(false), Void(true), Poly(false), Constant(false), Pointer(false), ScalarForMangling(false), + NoManglingQ(false), Bitwidth(0), ElementBitwidth(0), NumVectors(0) {} + + Type(TypeSpec TS, char CharMod) + : TS(TS), Float(false), Signed(false), Immediate(false), Void(false), + Poly(false), Constant(false), Pointer(false), ScalarForMangling(false), NoManglingQ(false), Bitwidth(0), ElementBitwidth(0), NumVectors(0) { applyModifier(CharMod); } @@ -167,6 +167,7 @@ bool isFloating() const { return Float; } bool isInteger() const { return !Float && !Poly; } bool isSigned() const { return Signed; } + bool isImmediate() const { return Immediate; } bool isScalar() const { return NumVectors == 0; } bool isVector() const { return NumVectors > 0; } bool isFloat() const { return Float && ElementBitwidth == 32; } @@ -192,6 +193,14 @@ Float = false; Poly = false; Signed = Sign; + Immediate = false; + ElementBitwidth = ElemWidth; + } + void makeImmediate(unsigned ElemWidth) { + Float = false; + Poly = false; + Signed = true; + Immediate = true; ElementBitwidth = ElemWidth; } void makeScalar() { @@ -600,6 +609,12 @@ else if (isInteger() && !Pointer && !Signed) S = "U" + S; + // Constant indices are "int", but have the "constant expression" modifier. + if (isImmediate()) { + assert(isInteger() && isSigned()); + S = "I" + S; + } + if (isScalar()) { if (Constant) S += "C"; if (Pointer) S += "*"; @@ -853,6 +868,7 @@ ElementBitwidth = Bitwidth = 32; NumVectors = 0; Signed = true; + Immediate = true; break; case 'l': Float = false; @@ -860,6 +876,7 @@ ElementBitwidth = Bitwidth = 64; NumVectors = 0; Signed = false; + Immediate = true; break; case 'z': ElementBitwidth /= 2; @@ -1019,9 +1036,8 @@ if (LocalCK == ClassI) T.makeSigned(); - // Constant indices are always just "int". if (hasImmediate() && getImmediateIdx() == I) - T.makeInteger(32, true); + T.makeImmediate(32); S += T.builtin_str(); }