forked from OSchip/llvm-project
[CodeGen][NEON] Emit constants for "immediate" intrinsic arguments.
On ARM/AArch64, we currently always use EmitScalarExpr for the immediate builtin arguments, instead of directly emitting the constant. When the overflow sanitizer is enabled, this generates overflow intrinsics instead of constants, breaking assumptions in various places. Instead, use the knowledge of "immediates" to directly emit a constant: - teach the tablegen backend to emit the "immediate" modifiers - use those modifiers in the NEON CodeGen, on ARM and AArch64. Fixes PR23517. Differential Revision: http://reviews.llvm.org/D10045 llvm-svn: 239002
This commit is contained in:
parent
667a7e2a0f
commit
94df730f7d
|
@ -3491,6 +3491,13 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
|
|||
}
|
||||
}
|
||||
|
||||
// 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<Value*, 4> Ops;
|
||||
llvm::Value *Align = nullptr;
|
||||
for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) {
|
||||
|
@ -3553,7 +3560,17 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
|
|||
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 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
|
|||
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<Value*, 4> 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(
|
||||
|
|
|
@ -131,7 +131,7 @@ class Type {
|
|||
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 @@ private:
|
|||
|
||||
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 @@ public:
|
|||
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 @@ public:
|
|||
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 @@ std::string Type::builtin_str() const {
|
|||
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 @@ void Type::applyModifier(char Mod) {
|
|||
ElementBitwidth = Bitwidth = 32;
|
||||
NumVectors = 0;
|
||||
Signed = true;
|
||||
Immediate = true;
|
||||
break;
|
||||
case 'l':
|
||||
Float = false;
|
||||
|
@ -860,6 +876,7 @@ void Type::applyModifier(char Mod) {
|
|||
ElementBitwidth = Bitwidth = 64;
|
||||
NumVectors = 0;
|
||||
Signed = false;
|
||||
Immediate = true;
|
||||
break;
|
||||
case 'z':
|
||||
ElementBitwidth /= 2;
|
||||
|
@ -1019,9 +1036,8 @@ std::string Intrinsic::getBuiltinTypeStr() {
|
|||
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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue