Index: cfe/trunk/lib/CodeGen/CGBuiltin.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp @@ -3491,6 +3491,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++) { @@ -3553,7 +3560,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) { @@ -4222,9 +4239,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: cfe/trunk/utils/TableGen/NeonEmitter.cpp =================================================================== --- cfe/trunk/utils/TableGen/NeonEmitter.cpp +++ cfe/trunk/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) {} + : 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), Void(false), Poly(false), - Constant(false), Pointer(false), ScalarForMangling(false), + : 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(); }