summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Henning <neil.henning@amd.com>2018-10-08 10:32:33 +0000
committerNeil Henning <neil.henning@amd.com>2018-10-08 10:32:33 +0000
commit57f5d0a885cf05d57da946cf5cf13ead2cb077b1 (patch)
tree46aa8539cb9e3adb26ca3ee67197a8c06b3a5b84
parent627d1469987a38cc9efcfbc63556b0b1342f4373 (diff)
downloadbcm5719-llvm-57f5d0a885cf05d57da946cf5cf13ead2cb077b1.tar.gz
bcm5719-llvm-57f5d0a885cf05d57da946cf5cf13ead2cb077b1.zip
[IRBuilder] Fixup CreateIntrinsic to allow specifying Types to Mangle.
The IRBuilder CreateIntrinsic method wouldn't allow you to specify the types that you wanted the intrinsic to be mangled with. To fix this I've: - Added an ArrayRef<Type *> member to both CreateIntrinsic overloads. - Used that array to pass into the Intrinsic::getDeclaration call. - Added a CreateUnaryIntrinsic to replace the most common use of CreateIntrinsic where the type was auto-deduced from operand 0. - Added a bunch more unit tests to test Create*Intrinsic calls that weren't being tested (including the FMF flag that wasn't checked). This was suggested as part of the AMDGPU specific atomic optimizer review (https://reviews.llvm.org/D51969). Differential Revision: https://reviews.llvm.org/D52087 llvm-svn: 343962
-rw-r--r--llvm/include/llvm/IR/IRBuilder.h30
-rw-r--r--llvm/lib/IR/IRBuilder.cpp25
-rw-r--r--llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp8
-rw-r--r--llvm/lib/Target/AMDGPU/AMDGPULowerKernelArguments.cpp4
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp10
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp2
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp4
-rw-r--r--llvm/unittests/IR/IRBuilderTest.cpp48
8 files changed, 90 insertions, 41 deletions
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 70641ba25d2..0af53c5b3f4 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -651,7 +651,7 @@ public:
ArrayRef<Use> DeoptArgs, ArrayRef<Value *> GCArgs,
const Twine &Name = "");
- // Conveninence function for the common case when CallArgs are filled in using
+ // Convenience function for the common case when CallArgs are filled in using
// makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be .get()'ed to
// get the Value *.
InvokeInst *
@@ -675,32 +675,34 @@ public:
Type *ResultType,
const Twine &Name = "");
+ /// Create a call to intrinsic \p ID with 1 operand which is mangled on its
+ /// type.
+ CallInst *CreateUnaryIntrinsic(Intrinsic::ID ID, Value *V,
+ Instruction *FMFSource = nullptr,
+ const Twine &Name = "");
+
/// Create a call to intrinsic \p ID with 2 operands which is mangled on the
/// first type.
- CallInst *CreateBinaryIntrinsic(Intrinsic::ID ID,
- Value *LHS, Value *RHS,
+ CallInst *CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS,
+ Instruction *FMFSource = nullptr,
const Twine &Name = "");
- /// Create a call to intrinsic \p ID with no operands.
- CallInst *CreateIntrinsic(Intrinsic::ID ID,
- Instruction *FMFSource = nullptr,
- const Twine &Name = "");
-
- /// Create a call to intrinsic \p ID with 1 or more operands assuming the
- /// intrinsic and all operands have the same type. If \p FMFSource is
- /// provided, copy fast-math-flags from that instruction to the intrinsic.
- CallInst *CreateIntrinsic(Intrinsic::ID ID, ArrayRef<Value *> Args,
+ /// Create a call to intrinsic \p ID with \p args, mangled using \p Types. If
+ /// \p FMFSource is provided, copy fast-math-flags from that instruction to
+ /// the intrinsic.
+ CallInst *CreateIntrinsic(Intrinsic::ID ID, ArrayRef<Type *> Types,
+ ArrayRef<Value *> Args,
Instruction *FMFSource = nullptr,
const Twine &Name = "");
/// Create call to the minnum intrinsic.
CallInst *CreateMinNum(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, Name);
+ return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, nullptr, Name);
}
/// Create call to the maxnum intrinsic.
CallInst *CreateMaxNum(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateBinaryIntrinsic(Intrinsic::maxnum, LHS, RHS, Name);
+ return CreateBinaryIntrinsic(Intrinsic::maxnum, LHS, RHS, nullptr, Name);
}
private:
diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp
index 91c950da71b..a9818995677 100644
--- a/llvm/lib/IR/IRBuilder.cpp
+++ b/llvm/lib/IR/IRBuilder.cpp
@@ -731,28 +731,29 @@ CallInst *IRBuilderBase::CreateGCRelocate(Instruction *Statepoint,
return createCallHelper(FnGCRelocate, Args, this, Name);
}
-CallInst *IRBuilderBase::CreateBinaryIntrinsic(Intrinsic::ID ID,
- Value *LHS, Value *RHS,
- const Twine &Name) {
+CallInst *IRBuilderBase::CreateUnaryIntrinsic(Intrinsic::ID ID, Value *V,
+ Instruction *FMFSource,
+ const Twine &Name) {
Module *M = BB->getModule();
- Function *Fn = Intrinsic::getDeclaration(M, ID, { LHS->getType() });
- return createCallHelper(Fn, { LHS, RHS }, this, Name);
+ Function *Fn = Intrinsic::getDeclaration(M, ID, {V->getType()});
+ return createCallHelper(Fn, {V}, this, Name, FMFSource);
}
-CallInst *IRBuilderBase::CreateIntrinsic(Intrinsic::ID ID,
- Instruction *FMFSource,
- const Twine &Name) {
+CallInst *IRBuilderBase::CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS,
+ Value *RHS,
+ Instruction *FMFSource,
+ const Twine &Name) {
Module *M = BB->getModule();
- Function *Fn = Intrinsic::getDeclaration(M, ID);
- return createCallHelper(Fn, {}, this, Name);
+ Function *Fn = Intrinsic::getDeclaration(M, ID, { LHS->getType() });
+ return createCallHelper(Fn, {LHS, RHS}, this, Name, FMFSource);
}
CallInst *IRBuilderBase::CreateIntrinsic(Intrinsic::ID ID,
+ ArrayRef<Type *> Types,
ArrayRef<Value *> Args,
Instruction *FMFSource,
const Twine &Name) {
- assert(!Args.empty() && "Expected at least one argument to intrinsic");
Module *M = BB->getModule();
- Function *Fn = Intrinsic::getDeclaration(M, ID, { Args.front()->getType() });
+ Function *Fn = Intrinsic::getDeclaration(M, ID, Types);
return createCallHelper(Fn, Args, this, Name, FMFSource);
}
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp
index 6fcb92efb04..4dc1e67c573 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp
@@ -558,7 +558,7 @@ Value* AMDGPUCodeGenPrepare::expandDivRem24(IRBuilder<> &Builder,
Value *FQM = Builder.CreateFMul(FA, RCP);
// fq = trunc(fqm);
- CallInst* FQ = Builder.CreateIntrinsic(Intrinsic::trunc, { FQM });
+ CallInst *FQ = Builder.CreateUnaryIntrinsic(Intrinsic::trunc, FQM);
FQ->copyFastMathFlags(Builder.getFastMathFlags());
// float fqneg = -fq;
@@ -566,17 +566,17 @@ Value* AMDGPUCodeGenPrepare::expandDivRem24(IRBuilder<> &Builder,
// float fr = mad(fqneg, fb, fa);
Value *FR = Builder.CreateIntrinsic(Intrinsic::amdgcn_fmad_ftz,
- { FQNeg, FB, FA }, FQ);
+ {FQNeg->getType()}, {FQNeg, FB, FA}, FQ);
// int iq = (int)fq;
Value *IQ = IsSigned ? Builder.CreateFPToSI(FQ, I32Ty)
: Builder.CreateFPToUI(FQ, I32Ty);
// fr = fabs(fr);
- FR = Builder.CreateIntrinsic(Intrinsic::fabs, { FR }, FQ);
+ FR = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, FR, FQ);
// fb = fabs(fb);
- FB = Builder.CreateIntrinsic(Intrinsic::fabs, { FB }, FQ);
+ FB = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, FB, FQ);
// int cv = fr >= fb;
Value *CV = Builder.CreateFCmpOGE(FR, FB);
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerKernelArguments.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerKernelArguments.cpp
index 2a25f1afa65..fae1da92337 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULowerKernelArguments.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULowerKernelArguments.cpp
@@ -83,8 +83,8 @@ bool AMDGPULowerKernelArguments::runOnFunction(Function &F) {
return false;
CallInst *KernArgSegment =
- Builder.CreateIntrinsic(Intrinsic::amdgcn_kernarg_segment_ptr, nullptr,
- F.getName() + ".kernarg.segment");
+ Builder.CreateIntrinsic(Intrinsic::amdgcn_kernarg_segment_ptr, {}, {},
+ nullptr, F.getName() + ".kernarg.segment");
KernArgSegment->addAttribute(AttributeList::ReturnIndex, Attribute::NonNull);
KernArgSegment->addAttribute(AttributeList::ReturnIndex,
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index efe41b49274..4e404933a22 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -709,7 +709,7 @@ static Value *simplifyX86round(IntrinsicInst &II,
}
Intrinsic::ID ID = (RoundControl == 2) ? Intrinsic::ceil : Intrinsic::floor;
- Value *Res = Builder.CreateIntrinsic(ID, {Src}, &II);
+ Value *Res = Builder.CreateUnaryIntrinsic(ID, Src, &II);
if (!IsScalar) {
if (auto *C = dyn_cast<Constant>(Mask))
if (C->isAllOnesValue())
@@ -2038,7 +2038,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
// maxnum(-X, -Y) --> -(minnum(X, Y))
Intrinsic::ID NewIID = II->getIntrinsicID() == Intrinsic::maxnum ?
Intrinsic::minnum : Intrinsic::maxnum;
- Value *NewCall = Builder.CreateIntrinsic(NewIID, { X, Y }, II);
+ Value *NewCall = Builder.CreateBinaryIntrinsic(NewIID, X, Y, II);
Instruction *FNeg = BinaryOperator::CreateFNeg(NewCall);
FNeg->copyIRFlags(II);
return FNeg;
@@ -2116,8 +2116,8 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
Value *ExtSrc;
if (match(II->getArgOperand(0), m_OneUse(m_FPExt(m_Value(ExtSrc))))) {
// Narrow the call: intrinsic (fpext x) -> fpext (intrinsic x)
- Value *NarrowII = Builder.CreateIntrinsic(II->getIntrinsicID(),
- { ExtSrc }, II);
+ Value *NarrowII =
+ Builder.CreateUnaryIntrinsic(II->getIntrinsicID(), ExtSrc, II);
return new FPExtInst(NarrowII, II->getType());
}
break;
@@ -2138,7 +2138,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
Value *X;
if (match(II->getArgOperand(0), m_OneUse(m_FNeg(m_Value(X))))) {
// sin(-x) --> -sin(x)
- Value *NewSin = Builder.CreateIntrinsic(Intrinsic::sin, { X }, II);
+ Value *NewSin = Builder.CreateUnaryIntrinsic(Intrinsic::sin, X, II);
Instruction *FNeg = BinaryOperator::CreateFNeg(NewSin);
FNeg->copyFastMathFlags(II);
return FNeg;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index f99dba49cb5..6427c818e02 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -433,7 +433,7 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) {
match(Op0, m_OneUse(m_Intrinsic<Intrinsic::sqrt>(m_Value(X)))) &&
match(Op1, m_OneUse(m_Intrinsic<Intrinsic::sqrt>(m_Value(Y))))) {
Value *XY = Builder.CreateFMulFMF(X, Y, &I);
- Value *Sqrt = Builder.CreateIntrinsic(Intrinsic::sqrt, { XY }, &I);
+ Value *Sqrt = Builder.CreateUnaryIntrinsic(Intrinsic::sqrt, XY, &I);
return replaceInstUsesWith(I, Sqrt);
}
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index f42deff7409..3d346dff2f8 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1751,7 +1751,7 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
match(TrueVal, m_FSub(m_PosZeroFP(), m_Specific(X)))) ||
(X == TrueVal && Pred == FCmpInst::FCMP_OGT &&
match(FalseVal, m_FSub(m_PosZeroFP(), m_Specific(X))))) {
- Value *Fabs = Builder.CreateIntrinsic(Intrinsic::fabs, { X }, FCI);
+ Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, X, FCI);
return replaceInstUsesWith(SI, Fabs);
}
// With nsz:
@@ -1764,7 +1764,7 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
(Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_OLE)) ||
(X == TrueVal && match(FalseVal, m_FNeg(m_Specific(X))) &&
(Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_OGE)))) {
- Value *Fabs = Builder.CreateIntrinsic(Intrinsic::fabs, { X }, FCI);
+ Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, X, FCI);
return replaceInstUsesWith(SI, Fabs);
}
}
diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp
index 720967cb136..42c0393d382 100644
--- a/llvm/unittests/IR/IRBuilderTest.cpp
+++ b/llvm/unittests/IR/IRBuilderTest.cpp
@@ -51,10 +51,14 @@ protected:
TEST_F(IRBuilderTest, Intrinsics) {
IRBuilder<> Builder(BB);
Value *V;
+ Instruction *I;
CallInst *Call;
IntrinsicInst *II;
V = Builder.CreateLoad(GV);
+ I = cast<Instruction>(Builder.CreateFAdd(V, V));
+ I->setHasNoInfs(true);
+ I->setHasNoNaNs(false);
Call = Builder.CreateMinNum(V, V);
II = cast<IntrinsicInst>(Call);
@@ -64,9 +68,51 @@ TEST_F(IRBuilderTest, Intrinsics) {
II = cast<IntrinsicInst>(Call);
EXPECT_EQ(II->getIntrinsicID(), Intrinsic::maxnum);
- Call = Builder.CreateIntrinsic(Intrinsic::readcyclecounter);
+ Call = Builder.CreateIntrinsic(Intrinsic::readcyclecounter, {}, {});
II = cast<IntrinsicInst>(Call);
EXPECT_EQ(II->getIntrinsicID(), Intrinsic::readcyclecounter);
+
+ Call = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, V);
+ II = cast<IntrinsicInst>(Call);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fabs);
+ EXPECT_FALSE(II->hasNoInfs());
+ EXPECT_FALSE(II->hasNoNaNs());
+
+ Call = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, V, I);
+ II = cast<IntrinsicInst>(Call);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fabs);
+ EXPECT_TRUE(II->hasNoInfs());
+ EXPECT_FALSE(II->hasNoNaNs());
+
+ Call = Builder.CreateBinaryIntrinsic(Intrinsic::pow, V, V);
+ II = cast<IntrinsicInst>(Call);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::pow);
+ EXPECT_FALSE(II->hasNoInfs());
+ EXPECT_FALSE(II->hasNoNaNs());
+
+ Call = Builder.CreateBinaryIntrinsic(Intrinsic::pow, V, V, I);
+ II = cast<IntrinsicInst>(Call);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::pow);
+ EXPECT_TRUE(II->hasNoInfs());
+ EXPECT_FALSE(II->hasNoNaNs());
+
+ Call = Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V});
+ II = cast<IntrinsicInst>(Call);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma);
+ EXPECT_FALSE(II->hasNoInfs());
+ EXPECT_FALSE(II->hasNoNaNs());
+
+ Call = Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V}, I);
+ II = cast<IntrinsicInst>(Call);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma);
+ EXPECT_TRUE(II->hasNoInfs());
+ EXPECT_FALSE(II->hasNoNaNs());
+
+ Call = Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V}, I);
+ II = cast<IntrinsicInst>(Call);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma);
+ EXPECT_TRUE(II->hasNoInfs());
+ EXPECT_FALSE(II->hasNoNaNs());
}
TEST_F(IRBuilderTest, Lifetime) {
OpenPOWER on IntegriCloud