llvm.org GIT mirror llvm / 7465597
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@343962 91177308-0d34-0410-b5e6-96231b3b80d8 Neil Henning 2 years ago
8 changed file(s) with 92 addition(s) and 43 deletion(s). Raw diff Collapse all Expand all
650650 ArrayRef DeoptArgs, ArrayRef GCArgs,
651651 const Twine &Name = "");
652652
653 // Conveninence function for the common case when CallArgs are filled in using
653 // Convenience function for the common case when CallArgs are filled in using
654654 // makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be .get()'ed to
655655 // get the Value *.
656656 InvokeInst *
674674 Type *ResultType,
675675 const Twine &Name = "");
676676
677 /// Create a call to intrinsic \p ID with 1 operand which is mangled on its
678 /// type.
679 CallInst *CreateUnaryIntrinsic(Intrinsic::ID ID, Value *V,
680 Instruction *FMFSource = nullptr,
681 const Twine &Name = "");
682
677683 /// Create a call to intrinsic \p ID with 2 operands which is mangled on the
678684 /// first type.
679 CallInst *CreateBinaryIntrinsic(Intrinsic::ID ID,
680 Value *LHS, Value *RHS,
685 CallInst *CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS,
686 Instruction *FMFSource = nullptr,
681687 const Twine &Name = "");
682688
683 /// Create a call to intrinsic \p ID with no operands.
684 CallInst *CreateIntrinsic(Intrinsic::ID ID,
689 /// Create a call to intrinsic \p ID with \p args, mangled using \p Types. If
690 /// \p FMFSource is provided, copy fast-math-flags from that instruction to
691 /// the intrinsic.
692 CallInst *CreateIntrinsic(Intrinsic::ID ID, ArrayRef Types,
693 ArrayRef Args,
685694 Instruction *FMFSource = nullptr,
686695 const Twine &Name = "");
687696
688 /// Create a call to intrinsic \p ID with 1 or more operands assuming the
689 /// intrinsic and all operands have the same type. If \p FMFSource is
690 /// provided, copy fast-math-flags from that instruction to the intrinsic.
691 CallInst *CreateIntrinsic(Intrinsic::ID ID, ArrayRef Args,
692 Instruction *FMFSource = nullptr,
693 const Twine &Name = "");
694
695697 /// Create call to the minnum intrinsic.
696698 CallInst *CreateMinNum(Value *LHS, Value *RHS, const Twine &Name = "") {
697 return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, Name);
699 return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, nullptr, Name);
698700 }
699701
700702 /// Create call to the maxnum intrinsic.
701703 CallInst *CreateMaxNum(Value *LHS, Value *RHS, const Twine &Name = "") {
702 return CreateBinaryIntrinsic(Intrinsic::maxnum, LHS, RHS, Name);
704 return CreateBinaryIntrinsic(Intrinsic::maxnum, LHS, RHS, nullptr, Name);
703705 }
704706
705707 private:
730730 return createCallHelper(FnGCRelocate, Args, this, Name);
731731 }
732732
733 CallInst *IRBuilderBase::CreateBinaryIntrinsic(Intrinsic::ID ID,
734 Value *LHS, Value *RHS,
733 CallInst *IRBuilderBase::CreateUnaryIntrinsic(Intrinsic::ID ID, Value *V,
734 Instruction *FMFSource,
735 const Twine &Name) {
736 Module *M = BB->getModule();
737 Function *Fn = Intrinsic::getDeclaration(M, ID, {V->getType()});
738 return createCallHelper(Fn, {V}, this, Name, FMFSource);
739 }
740
741 CallInst *IRBuilderBase::CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS,
742 Value *RHS,
743 Instruction *FMFSource,
735744 const Twine &Name) {
736745 Module *M = BB->getModule();
737746 Function *Fn = Intrinsic::getDeclaration(M, ID, { LHS->getType() });
738 return createCallHelper(Fn, { LHS, RHS }, this, Name);
747 return createCallHelper(Fn, {LHS, RHS}, this, Name, FMFSource);
739748 }
740749
741750 CallInst *IRBuilderBase::CreateIntrinsic(Intrinsic::ID ID,
751 ArrayRef Types,
752 ArrayRef Args,
742753 Instruction *FMFSource,
743754 const Twine &Name) {
744755 Module *M = BB->getModule();
745 Function *Fn = Intrinsic::getDeclaration(M, ID);
746 return createCallHelper(Fn, {}, this, Name);
747 }
748
749 CallInst *IRBuilderBase::CreateIntrinsic(Intrinsic::ID ID,
750 ArrayRef Args,
751 Instruction *FMFSource,
752 const Twine &Name) {
753 assert(!Args.empty() && "Expected at least one argument to intrinsic");
754 Module *M = BB->getModule();
755 Function *Fn = Intrinsic::getDeclaration(M, ID, { Args.front()->getType() });
756 Function *Fn = Intrinsic::getDeclaration(M, ID, Types);
756757 return createCallHelper(Fn, Args, this, Name, FMFSource);
757758 }
557557 Value *FQM = Builder.CreateFMul(FA, RCP);
558558
559559 // fq = trunc(fqm);
560 CallInst* FQ = Builder.CreateIntrinsic(Intrinsic::trunc, { FQM });
560 CallInst *FQ = Builder.CreateUnaryIntrinsic(Intrinsic::trunc, FQM);
561561 FQ->copyFastMathFlags(Builder.getFastMathFlags());
562562
563563 // float fqneg = -fq;
565565
566566 // float fr = mad(fqneg, fb, fa);
567567 Value *FR = Builder.CreateIntrinsic(Intrinsic::amdgcn_fmad_ftz,
568 { FQNeg, FB, FA }, FQ);
568 {FQNeg->getType()}, {FQNeg, FB, FA}, FQ);
569569
570570 // int iq = (int)fq;
571571 Value *IQ = IsSigned ? Builder.CreateFPToSI(FQ, I32Ty)
572572 : Builder.CreateFPToUI(FQ, I32Ty);
573573
574574 // fr = fabs(fr);
575 FR = Builder.CreateIntrinsic(Intrinsic::fabs, { FR }, FQ);
575 FR = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, FR, FQ);
576576
577577 // fb = fabs(fb);
578 FB = Builder.CreateIntrinsic(Intrinsic::fabs, { FB }, FQ);
578 FB = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, FB, FQ);
579579
580580 // int cv = fr >= fb;
581581 Value *CV = Builder.CreateFCmpOGE(FR, FB);
8282 return false;
8383
8484 CallInst *KernArgSegment =
85 Builder.CreateIntrinsic(Intrinsic::amdgcn_kernarg_segment_ptr, nullptr,
86 F.getName() + ".kernarg.segment");
85 Builder.CreateIntrinsic(Intrinsic::amdgcn_kernarg_segment_ptr, {}, {},
86 nullptr, F.getName() + ".kernarg.segment");
8787
8888 KernArgSegment->addAttribute(AttributeList::ReturnIndex, Attribute::NonNull);
8989 KernArgSegment->addAttribute(AttributeList::ReturnIndex,
708708 }
709709
710710 Intrinsic::ID ID = (RoundControl == 2) ? Intrinsic::ceil : Intrinsic::floor;
711 Value *Res = Builder.CreateIntrinsic(ID, {Src}, &II);
711 Value *Res = Builder.CreateUnaryIntrinsic(ID, Src, &II);
712712 if (!IsScalar) {
713713 if (auto *C = dyn_cast(Mask))
714714 if (C->isAllOnesValue())
20372037 // maxnum(-X, -Y) --> -(minnum(X, Y))
20382038 Intrinsic::ID NewIID = II->getIntrinsicID() == Intrinsic::maxnum ?
20392039 Intrinsic::minnum : Intrinsic::maxnum;
2040 Value *NewCall = Builder.CreateIntrinsic(NewIID, { X, Y }, II);
2040 Value *NewCall = Builder.CreateBinaryIntrinsic(NewIID, X, Y, II);
20412041 Instruction *FNeg = BinaryOperator::CreateFNeg(NewCall);
20422042 FNeg->copyIRFlags(II);
20432043 return FNeg;
21152115 Value *ExtSrc;
21162116 if (match(II->getArgOperand(0), m_OneUse(m_FPExt(m_Value(ExtSrc))))) {
21172117 // Narrow the call: intrinsic (fpext x) -> fpext (intrinsic x)
2118 Value *NarrowII = Builder.CreateIntrinsic(II->getIntrinsicID(),
2119 { ExtSrc }, II);
2118 Value *NarrowII =
2119 Builder.CreateUnaryIntrinsic(II->getIntrinsicID(), ExtSrc, II);
21202120 return new FPExtInst(NarrowII, II->getType());
21212121 }
21222122 break;
21372137 Value *X;
21382138 if (match(II->getArgOperand(0), m_OneUse(m_FNeg(m_Value(X))))) {
21392139 // sin(-x) --> -sin(x)
2140 Value *NewSin = Builder.CreateIntrinsic(Intrinsic::sin, { X }, II);
2140 Value *NewSin = Builder.CreateUnaryIntrinsic(Intrinsic::sin, X, II);
21412141 Instruction *FNeg = BinaryOperator::CreateFNeg(NewSin);
21422142 FNeg->copyFastMathFlags(II);
21432143 return FNeg;
432432 match(Op0, m_OneUse(m_Intrinsic(m_Value(X)))) &&
433433 match(Op1, m_OneUse(m_Intrinsic(m_Value(Y))))) {
434434 Value *XY = Builder.CreateFMulFMF(X, Y, &I);
435 Value *Sqrt = Builder.CreateIntrinsic(Intrinsic::sqrt, { XY }, &I);
435 Value *Sqrt = Builder.CreateUnaryIntrinsic(Intrinsic::sqrt, XY, &I);
436436 return replaceInstUsesWith(I, Sqrt);
437437 }
438438
17501750 match(TrueVal, m_FSub(m_PosZeroFP(), m_Specific(X)))) ||
17511751 (X == TrueVal && Pred == FCmpInst::FCMP_OGT &&
17521752 match(FalseVal, m_FSub(m_PosZeroFP(), m_Specific(X))))) {
1753 Value *Fabs = Builder.CreateIntrinsic(Intrinsic::fabs, { X }, FCI);
1753 Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, X, FCI);
17541754 return replaceInstUsesWith(SI, Fabs);
17551755 }
17561756 // With nsz:
17631763 (Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_OLE)) ||
17641764 (X == TrueVal && match(FalseVal, m_FNeg(m_Specific(X))) &&
17651765 (Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_OGE)))) {
1766 Value *Fabs = Builder.CreateIntrinsic(Intrinsic::fabs, { X }, FCI);
1766 Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, X, FCI);
17671767 return replaceInstUsesWith(SI, Fabs);
17681768 }
17691769 }
5050 TEST_F(IRBuilderTest, Intrinsics) {
5151 IRBuilder<> Builder(BB);
5252 Value *V;
53 Instruction *I;
5354 CallInst *Call;
5455 IntrinsicInst *II;
5556
5657 V = Builder.CreateLoad(GV);
58 I = cast(Builder.CreateFAdd(V, V));
59 I->setHasNoInfs(true);
60 I->setHasNoNaNs(false);
5761
5862 Call = Builder.CreateMinNum(V, V);
5963 II = cast(Call);
6367 II = cast(Call);
6468 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::maxnum);
6569
66 Call = Builder.CreateIntrinsic(Intrinsic::readcyclecounter);
70 Call = Builder.CreateIntrinsic(Intrinsic::readcyclecounter, {}, {});
6771 II = cast(Call);
6872 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::readcyclecounter);
73
74 Call = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, V);
75 II = cast(Call);
76 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fabs);
77 EXPECT_FALSE(II->hasNoInfs());
78 EXPECT_FALSE(II->hasNoNaNs());
79
80 Call = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, V, I);
81 II = cast(Call);
82 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fabs);
83 EXPECT_TRUE(II->hasNoInfs());
84 EXPECT_FALSE(II->hasNoNaNs());
85
86 Call = Builder.CreateBinaryIntrinsic(Intrinsic::pow, V, V);
87 II = cast(Call);
88 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::pow);
89 EXPECT_FALSE(II->hasNoInfs());
90 EXPECT_FALSE(II->hasNoNaNs());
91
92 Call = Builder.CreateBinaryIntrinsic(Intrinsic::pow, V, V, I);
93 II = cast(Call);
94 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::pow);
95 EXPECT_TRUE(II->hasNoInfs());
96 EXPECT_FALSE(II->hasNoNaNs());
97
98 Call = Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V});
99 II = cast(Call);
100 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma);
101 EXPECT_FALSE(II->hasNoInfs());
102 EXPECT_FALSE(II->hasNoNaNs());
103
104 Call = Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V}, I);
105 II = cast(Call);
106 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma);
107 EXPECT_TRUE(II->hasNoInfs());
108 EXPECT_FALSE(II->hasNoNaNs());
109
110 Call = Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V}, I);
111 II = cast(Call);
112 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma);
113 EXPECT_TRUE(II->hasNoInfs());
114 EXPECT_FALSE(II->hasNoNaNs());
69115 }
70116
71117 TEST_F(IRBuilderTest, Lifetime) {