llvm.org GIT mirror llvm / d329c79
Reapply r206732. This time without optimization of branches. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206749 91177308-0d34-0410-b5e6-96231b3b80d8 Michael Zolotukhin 6 years ago
9 changed file(s) with 729 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
443443 [LLVMMatchType<0>, LLVMMatchType<0>],
444444 [IntrNoMem]>;
445445
446 def int_safe_udiv : Intrinsic<[llvm_anyint_ty, llvm_i1_ty],
447 [LLVMMatchType<0>, LLVMMatchType<0>],
448 [IntrNoMem]>;
449 def int_safe_urem : Intrinsic<[llvm_anyint_ty, llvm_i1_ty],
450 [LLVMMatchType<0>, LLVMMatchType<0>],
451 [IntrNoMem]>;
452 def int_safe_sdiv : Intrinsic<[llvm_anyint_ty, llvm_i1_ty],
453 [LLVMMatchType<0>, LLVMMatchType<0>],
454 [IntrNoMem]>;
455 def int_safe_srem : Intrinsic<[llvm_anyint_ty, llvm_i1_ty],
456 [LLVMMatchType<0>, LLVMMatchType<0>],
457 [IntrNoMem]>;
458
446459 //===------------------------- Memory Use Markers -------------------------===//
447460 //
448461 def int_lifetime_start : Intrinsic<[],
216216
217217 /// Return true if pow2 div is cheaper than a chain of srl/add/sra.
218218 bool isPow2DivCheap() const { return Pow2DivIsCheap; }
219
220 /// Return true if Div never traps, returns 0 when div by 0 and return TMin,
221 /// when sdiv TMin by -1.
222 bool isDivWellDefined() const { return DivIsWellDefined; }
219223
220224 /// Return true if Flow Control is an expensive operation that should be
221225 /// avoided.
10251029 /// signed divide by power of two, and let the target handle it.
10261030 void setPow2DivIsCheap(bool isCheap = true) { Pow2DivIsCheap = isCheap; }
10271031
1032 /// Tells the code-generator that it is safe to execute sdiv/udiv/srem/urem
1033 /// even when RHS is 0. It is also safe to execute sdiv/srem when LHS is
1034 /// SignedMinValue and RHS is -1.
1035 void setDivIsWellDefined (bool isWellDefined = true) {
1036 DivIsWellDefined = isWellDefined;
1037 }
1038
10281039 /// Add the specified register class as an available regclass for the
10291040 /// specified value type. This indicates the selector can handle values of
10301041 /// that class natively.
14401451 /// signed divide by power of two, and let the target handle it.
14411452 bool Pow2DivIsCheap;
14421453
1454 /// Tells the code-generator that it is safe to execute sdiv/udiv/srem/urem
1455 /// even when RHS is 0. It is also safe to execute sdiv/srem when LHS is
1456 /// SignedMinValue and RHS is -1.
1457 bool DivIsWellDefined;
1458
14431459 /// Tells the code generator that it shouldn't generate extra flow control
14441460 /// instructions and should attempt to combine flow control instructions via
14451461 /// predication.
687687 }
688688 return true;
689689 }
690 // Lower all uses of llvm.safe.[us]{div|rem}...
691 if (II &&
692 (II->getIntrinsicID() == Intrinsic::safe_sdiv ||
693 II->getIntrinsicID() == Intrinsic::safe_udiv ||
694 II->getIntrinsicID() == Intrinsic::safe_srem ||
695 II->getIntrinsicID() == Intrinsic::safe_urem)) {
696 // Given
697 // result_struct = type {iN, i1}
698 // %R = call result_struct llvm.safe.sdiv.iN(iN %x, iN %y)
699 // Expand it to actual IR, which produces result to the same variable %R.
700 // First element of the result %R.1 is the result of division, second
701 // element shows whether the division was correct or not.
702 // If %y is 0, %R.1 is 0, %R.2 is 1. (1)
703 // If %x is minSignedValue and %y is -1, %R.1 is %x, %R.2 is 1. (2)
704 // In other cases %R.1 is (sdiv %x, %y), %R.2 is 0. (3)
705 //
706 // Similar applies to srem, udiv, and urem builtins, except that in unsigned
707 // variants we don't check condition (2).
708
709 bool IsSigned;
710 BinaryOperator::BinaryOps Op;
711 switch (II->getIntrinsicID()) {
712 case Intrinsic::safe_sdiv:
713 IsSigned = true;
714 Op = Instruction::SDiv;
715 break;
716 case Intrinsic::safe_udiv:
717 IsSigned = false;
718 Op = Instruction::UDiv;
719 break;
720 case Intrinsic::safe_srem:
721 IsSigned = true;
722 Op = Instruction::SRem;
723 break;
724 case Intrinsic::safe_urem:
725 IsSigned = false;
726 Op = Instruction::URem;
727 break;
728 default:
729 llvm_unreachable("Only Div/Rem intrinsics are handled here.");
730 }
731
732 Value *LHS = II->getOperand(0), *RHS = II->getOperand(1);
733 bool DivWellDefined = TLI && TLI->isDivWellDefined();
734
735 bool ResultNeeded[2] = {false, false};
736 SmallVector ResultsUsers[2];
737 bool BadCase = false;
738 for (User *U: II->users()) {
739 ExtractValueInst *EVI = dyn_cast(U);
740 if (!EVI || EVI->getNumIndices() > 1 || EVI->getIndices()[0] > 1) {
741 BadCase = true;
742 break;
743 }
744 ResultNeeded[EVI->getIndices()[0]] = true;
745 ResultsUsers[EVI->getIndices()[0]].push_back(U);
746 }
747 // Behave conservatively, if there is an unusual user of the results.
748 if (BadCase)
749 ResultNeeded[0] = ResultNeeded[1] = true;
750
751 // Early exit if non of the results is ever used.
752 if (!ResultNeeded[0] && !ResultNeeded[1]) {
753 II->eraseFromParent();
754 return true;
755 }
756
757 // Early exit if the second result (flag) isn't used and target
758 // div-instruction computes exactly what we want to get as the first result
759 // and never traps.
760 if (ResultNeeded[0] && !ResultNeeded[1] && DivWellDefined) {
761 BinaryOperator *Div = BinaryOperator::Create(Op, LHS, RHS);
762 Div->insertAfter(II);
763 for (User *U: ResultsUsers[0]) {
764 Instruction *UserInst = dyn_cast(U);
765 assert(UserInst && "Unexpected null-instruction");
766 UserInst->replaceAllUsesWith(Div);
767 UserInst->eraseFromParent();
768 }
769 II->eraseFromParent();
770 CurInstIterator = Div;
771 ModifiedDT = true;
772 return true;
773 }
774
775 Value *MinusOne = Constant::getAllOnesValue(LHS->getType());
776 Value *Zero = Constant::getNullValue(LHS->getType());
777
778 // Split the original BB and create other basic blocks that will be used
779 // for checks.
780 BasicBlock *StartBB = II->getParent();
781 BasicBlock::iterator SplitPt = ++(BasicBlock::iterator(II));
782 BasicBlock *NextBB = StartBB->splitBasicBlock(SplitPt, "div.end");
783
784 BasicBlock *DivByZeroBB;
785 DivByZeroBB = BasicBlock::Create(II->getContext(), "div.divz",
786 NextBB->getParent(), NextBB);
787 BranchInst::Create(NextBB, DivByZeroBB);
788 BasicBlock *DivBB = BasicBlock::Create(II->getContext(), "div.div",
789 NextBB->getParent(), NextBB);
790 BranchInst::Create(NextBB, DivBB);
791
792 // For signed variants, check the condition (2):
793 // LHS == SignedMinValue, RHS == -1.
794 Value *CmpMinusOne;
795 Value *CmpMinValue;
796 BasicBlock *ChkDivMinBB;
797 BasicBlock *DivMinBB;
798 Value *MinValue;
799 if (IsSigned) {
800 APInt SignedMinValue =
801 APInt::getSignedMinValue(LHS->getType()->getPrimitiveSizeInBits());
802 MinValue = Constant::getIntegerValue(LHS->getType(), SignedMinValue);
803 ChkDivMinBB = BasicBlock::Create(II->getContext(), "div.chkdivmin",
804 NextBB->getParent(), NextBB);
805 BranchInst::Create(NextBB, ChkDivMinBB);
806 DivMinBB = BasicBlock::Create(II->getContext(), "div.divmin",
807 NextBB->getParent(), NextBB);
808 BranchInst::Create(NextBB, DivMinBB);
809 CmpMinusOne = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ,
810 RHS, MinusOne, "cmp.rhs.minus.one",
811 ChkDivMinBB->getTerminator());
812 CmpMinValue = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ,
813 LHS, MinValue, "cmp.lhs.signed.min",
814 ChkDivMinBB->getTerminator());
815 BinaryOperator *CmpSignedOvf = BinaryOperator::Create(Instruction::And,
816 CmpMinusOne,
817 CmpMinValue);
818 // Here we're interested in the case when both %x is TMin and %y is -1.
819 // In this case the result will overflow.
820 // If that's not the case, we can perform usual division. These blocks
821 // will be inserted after DivByZero, so the division will be safe.
822 CmpSignedOvf->insertBefore(ChkDivMinBB->getTerminator());
823 BranchInst::Create(DivMinBB, DivBB, CmpSignedOvf,
824 ChkDivMinBB->getTerminator());
825 ChkDivMinBB->getTerminator()->eraseFromParent();
826 }
827
828 // Check the condition (1):
829 // RHS == 0.
830 Value *CmpDivZero = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ,
831 RHS, Zero, "cmp.rhs.zero",
832 StartBB->getTerminator());
833
834 // If RHS != 0, we want to check condition (2) in signed case, or proceed
835 // to usual division in unsigned case.
836 BranchInst::Create(DivByZeroBB, IsSigned ? ChkDivMinBB : DivBB, CmpDivZero,
837 StartBB->getTerminator());
838 StartBB->getTerminator()->eraseFromParent();
839
840 // At the moment we have all the control flow created. We just need to
841 // insert DIV and PHI (if needed) to get the result value.
842 Instruction *DivRes, *FlagRes;
843 Instruction *InsPoint = nullptr;
844 if (ResultNeeded[0]) {
845 BinaryOperator *Div = BinaryOperator::Create(Op, LHS, RHS);
846 if (DivWellDefined) {
847 // The result value is the result of DIV operation placed right at the
848 // original place of the intrinsic.
849 Div->insertAfter(II);
850 DivRes = Div;
851 } else {
852 // The result is a PHI-node.
853 Div->insertBefore(DivBB->getTerminator());
854 PHINode *DivResPN =
855 PHINode::Create(LHS->getType(), IsSigned ? 3 : 2, "div.res.phi",
856 NextBB->begin());
857 DivResPN->addIncoming(Div, DivBB);
858 DivResPN->addIncoming(Zero, DivByZeroBB);
859 if (IsSigned)
860 DivResPN->addIncoming(MinValue, DivMinBB);
861 DivRes = DivResPN;
862 InsPoint = DivResPN;
863 }
864 }
865
866 // Prepare a value for the second result (flag) if it is needed.
867 if (ResultNeeded[1]) {
868 Type *FlagTy = II->getType()->getStructElementType(1);
869 PHINode *FlagResPN =
870 PHINode::Create(FlagTy, IsSigned ? 3 : 2, "div.flag.phi",
871 NextBB->begin());
872 FlagResPN->addIncoming(Constant::getNullValue(FlagTy), DivBB);
873 FlagResPN->addIncoming(Constant::getAllOnesValue(FlagTy), DivByZeroBB);
874 if (IsSigned)
875 FlagResPN->addIncoming(Constant::getAllOnesValue(FlagTy), DivMinBB);
876 FlagRes = FlagResPN;
877 if (!InsPoint)
878 InsPoint = FlagRes;
879 }
880
881 // If possible, propagate the results to the user. Otherwise, create alloca,
882 // and create a struct with the results on stack.
883 if (!BadCase) {
884 if (ResultNeeded[0]) {
885 for (User *U: ResultsUsers[0]) {
886 Instruction *UserInst = dyn_cast(U);
887 assert(UserInst && "Unexpected null-instruction");
888 UserInst->replaceAllUsesWith(DivRes);
889 UserInst->eraseFromParent();
890 }
891 }
892 if (ResultNeeded[1]) {
893 for (User *FlagU: ResultsUsers[1]) {
894 Instruction *FlagUInst = dyn_cast(FlagU);
895 FlagUInst->replaceAllUsesWith(FlagRes);
896 FlagUInst->eraseFromParent();
897 }
898 }
899 } else {
900 // Create alloca, store our new values to it, and then load the final
901 // result from it.
902 Constant *Idx0 = ConstantInt::get(Type::getInt32Ty(II->getContext()), 0);
903 Constant *Idx1 = ConstantInt::get(Type::getInt32Ty(II->getContext()), 1);
904 Value *Idxs_DivRes[2] = {Idx0, Idx0};
905 Value *Idxs_FlagRes[2] = {Idx0, Idx1};
906 Value *NewRes = new llvm::AllocaInst(II->getType(), 0, "div.res.ptr", II);
907 Instruction *ResDivAddr = GetElementPtrInst::Create(NewRes, Idxs_DivRes);
908 Instruction *ResFlagAddr =
909 GetElementPtrInst::Create(NewRes, Idxs_FlagRes);
910 ResDivAddr->insertAfter(InsPoint);
911 ResFlagAddr->insertAfter(ResDivAddr);
912 StoreInst *StoreResDiv = new StoreInst(DivRes, ResDivAddr);
913 StoreInst *StoreResFlag = new StoreInst(FlagRes, ResFlagAddr);
914 StoreResDiv->insertAfter(ResFlagAddr);
915 StoreResFlag->insertAfter(StoreResDiv);
916 LoadInst *LoadRes = new LoadInst(NewRes, "div.res");
917 LoadRes->insertAfter(StoreResFlag);
918 II->replaceAllUsesWith(LoadRes);
919 }
920
921 II->eraseFromParent();
922 CurInstIterator = StartBB->end();
923 ModifiedDT = true;
924 return true;
925 }
690926
691927 if (II && TLI) {
692928 SmallVector PtrOps;
681681 HasMultipleConditionRegisters = false;
682682 IntDivIsCheap = false;
683683 Pow2DivIsCheap = false;
684 DivIsWellDefined = false;
684685 JumpIsExpensive = false;
685686 PredictableSelectIsExpensive = false;
686687 MaskAndBranchFoldingIsLegal = false;
433433 MaskAndBranchFoldingIsLegal = true;
434434
435435 setMinFunctionAlignment(2);
436
437 setDivIsWellDefined(true);
436438
437439 RequireStrictAlign = StrictAlign;
438440 }
0 ; RUN: llc < %s -march=arm64 | FileCheck %s
1 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
2
3 %divovf32 = type { i32, i1 }
4
5 declare %divovf32 @llvm.safe.sdiv.i32(i32, i32) nounwind readnone
6 declare %divovf32 @llvm.safe.udiv.i32(i32, i32) nounwind readnone
7
8 ; CHECK-LABEL: sdiv32_results_unused
9 ; CHECK: entry
10 ; CHECK-NEXT: ret
11 define void @sdiv32_results_unused(i32 %x, i32 %y) {
12 entry:
13 %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
14 ret void
15 }
16
17 ; CHECK-LABEL: sdiv32_div_result_unused
18 ; CHECK-NOT: sdiv{{[ ]}}
19 define i1 @sdiv32_div_result_unused(i32 %x, i32 %y) {
20 entry:
21 %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
22 %bit = extractvalue %divovf32 %divr, 1
23 ret i1 %bit
24 }
25
26 ; CHECK-LABEL: sdiv32_flag_result_unused
27 ; CHECK-NOT: cb
28 ; CHECK: sdiv{{[ ]}}
29 define i32 @sdiv32_flag_result_unused(i32 %x, i32 %y) {
30 entry:
31 %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
32 %div = extractvalue %divovf32 %divr, 0
33 ret i32 %div
34 }
35
36 ; CHECK-LABEL: sdiv32_result_returned
37 ; CHECK: sdiv{{[ ]}}
38 define %divovf32 @sdiv32_result_returned(i32 %x, i32 %y) {
39 entry:
40 %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
41 ret %divovf32 %divr
42 }
43
44 ; CHECK-LABEL: udiv32_results_unused
45 ; CHECK: entry
46 ; CHECK-NEXT: ret
47 define void @udiv32_results_unused(i32 %x, i32 %y) {
48 entry:
49 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
50 ret void
51 }
52
53 ; CHECK-LABEL: udiv32_div_result_unused
54 ; CHECK-NOT: udiv{{[ ]}}
55 define i1 @udiv32_div_result_unused(i32 %x, i32 %y) {
56 entry:
57 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
58 %bit = extractvalue %divovf32 %divr, 1
59 ret i1 %bit
60 }
61
62 ; CHECK-LABEL: udiv32_flag_result_unused
63 ; CHECK-NOT: cb
64 ; CHECK: udiv{{[ ]}}
65 define i32 @udiv32_flag_result_unused(i32 %x, i32 %y) {
66 entry:
67 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
68 %div = extractvalue %divovf32 %divr, 0
69 ret i32 %div
70 }
71
72 ; CHECK-LABEL: udiv32_result_returned
73 ; CHECK: udiv{{[ ]}}
74 define %divovf32 @udiv32_result_returned(i32 %x, i32 %y) {
75 entry:
76 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
77 ret %divovf32 %divr
78 }
79
80 !llvm.ident = !{!0}
81
82 !0 = metadata !{metadata !"clang version 3.5.0 "}
0 ; RUN: llc < %s -march=arm64 | FileCheck %s
1 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
2
3 %divovf8 = type { i8, i1 }
4 %divovf16 = type { i16, i1 }
5 %divovf32 = type { i32, i1 }
6 %divovf64 = type { i64, i1 }
7
8 declare %divovf8 @llvm.safe.sdiv.i8(i8, i8) nounwind readnone
9 declare %divovf16 @llvm.safe.sdiv.i16(i16, i16) nounwind readnone
10 declare %divovf32 @llvm.safe.sdiv.i32(i32, i32) nounwind readnone
11 declare %divovf64 @llvm.safe.sdiv.i64(i64, i64) nounwind readnone
12
13 declare %divovf8 @llvm.safe.srem.i8(i8, i8) nounwind readnone
14 declare %divovf16 @llvm.safe.srem.i16(i16, i16) nounwind readnone
15 declare %divovf32 @llvm.safe.srem.i32(i32, i32) nounwind readnone
16 declare %divovf64 @llvm.safe.srem.i64(i64, i64) nounwind readnone
17
18 declare %divovf8 @llvm.safe.udiv.i8(i8, i8) nounwind readnone
19 declare %divovf16 @llvm.safe.udiv.i16(i16, i16) nounwind readnone
20 declare %divovf32 @llvm.safe.udiv.i32(i32, i32) nounwind readnone
21 declare %divovf64 @llvm.safe.udiv.i64(i64, i64) nounwind readnone
22
23 declare %divovf8 @llvm.safe.urem.i8(i8, i8) nounwind readnone
24 declare %divovf16 @llvm.safe.urem.i16(i16, i16) nounwind readnone
25 declare %divovf32 @llvm.safe.urem.i32(i32, i32) nounwind readnone
26 declare %divovf64 @llvm.safe.urem.i64(i64, i64) nounwind readnone
27
28 ; CHECK-LABEL: sdiv8
29 ; CHECK: sdiv{{[ ]}}
30 define %divovf8 @sdiv8(i8 %x, i8 %y) {
31 entry:
32 %divr = call %divovf8 @llvm.safe.sdiv.i8(i8 %x, i8 %y)
33 ret %divovf8 %divr
34 }
35 ; CHECK-LABEL: sdiv16
36 ; CHECK: sdiv{{[ ]}}
37 define %divovf16 @sdiv16(i16 %x, i16 %y) {
38 entry:
39 %divr = call %divovf16 @llvm.safe.sdiv.i16(i16 %x, i16 %y)
40 ret %divovf16 %divr
41 }
42 ; CHECK-LABEL: sdiv32
43 ; CHECK: sdiv{{[ ]}}
44 define %divovf32 @sdiv32(i32 %x, i32 %y) {
45 entry:
46 %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
47 ret %divovf32 %divr
48 }
49 ; CHECK-LABEL: sdiv64
50 ; CHECK: sdiv{{[ ]}}
51 define %divovf64 @sdiv64(i64 %x, i64 %y) {
52 entry:
53 %divr = call %divovf64 @llvm.safe.sdiv.i64(i64 %x, i64 %y)
54 ret %divovf64 %divr
55 }
56 ; CHECK-LABEL: udiv8
57 ; CHECK: udiv{{[ ]}}
58 define %divovf8 @udiv8(i8 %x, i8 %y) {
59 entry:
60 %divr = call %divovf8 @llvm.safe.udiv.i8(i8 %x, i8 %y)
61 ret %divovf8 %divr
62 }
63 ; CHECK-LABEL: udiv16
64 ; CHECK: udiv{{[ ]}}
65 define %divovf16 @udiv16(i16 %x, i16 %y) {
66 entry:
67 %divr = call %divovf16 @llvm.safe.udiv.i16(i16 %x, i16 %y)
68 ret %divovf16 %divr
69 }
70 ; CHECK-LABEL: udiv32
71 ; CHECK: udiv{{[ ]}}
72 define %divovf32 @udiv32(i32 %x, i32 %y) {
73 entry:
74 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
75 ret %divovf32 %divr
76 }
77 ; CHECK-LABEL: udiv64
78 ; CHECK: udiv{{[ ]}}
79 define %divovf64 @udiv64(i64 %x, i64 %y) {
80 entry:
81 %divr = call %divovf64 @llvm.safe.udiv.i64(i64 %x, i64 %y)
82 ret %divovf64 %divr
83 }
84 ; CHECK-LABEL: srem8
85 ; CHECK: sdiv{{[ ]}}
86 ; CHECK: msub{{[ ]}}
87 define %divovf8 @srem8(i8 %x, i8 %y) {
88 entry:
89 %remr = call %divovf8 @llvm.safe.srem.i8(i8 %x, i8 %y)
90 ret %divovf8 %remr
91 }
92 ; CHECK-LABEL: srem16
93 ; CHECK: sdiv{{[ ]}}
94 ; CHECK: msub{{[ ]}}
95 define %divovf16 @srem16(i16 %x, i16 %y) {
96 entry:
97 %remr = call %divovf16 @llvm.safe.srem.i16(i16 %x, i16 %y)
98 ret %divovf16 %remr
99 }
100 ; CHECK-LABEL: srem32
101 ; CHECK: sdiv{{[ ]}}
102 ; CHECK: msub{{[ ]}}
103 define %divovf32 @srem32(i32 %x, i32 %y) {
104 entry:
105 %remr = call %divovf32 @llvm.safe.srem.i32(i32 %x, i32 %y)
106 ret %divovf32 %remr
107 }
108 ; CHECK-LABEL: srem64
109 ; CHECK: sdiv{{[ ]}}
110 ; CHECK: msub{{[ ]}}
111 define %divovf64 @srem64(i64 %x, i64 %y) {
112 entry:
113 %remr = call %divovf64 @llvm.safe.srem.i64(i64 %x, i64 %y)
114 ret %divovf64 %remr
115 }
116 ; CHECK-LABEL: urem8
117 ; CHECK: udiv{{[ ]}}
118 ; CHECK: msub{{[ ]}}
119 define %divovf8 @urem8(i8 %x, i8 %y) {
120 entry:
121 %remr = call %divovf8 @llvm.safe.urem.i8(i8 %x, i8 %y)
122 ret %divovf8 %remr
123 }
124 ; CHECK-LABEL: urem16
125 ; CHECK: udiv{{[ ]}}
126 ; CHECK: msub{{[ ]}}
127 define %divovf16 @urem16(i16 %x, i16 %y) {
128 entry:
129 %remr = call %divovf16 @llvm.safe.urem.i16(i16 %x, i16 %y)
130 ret %divovf16 %remr
131 }
132 ; CHECK-LABEL: urem32
133 ; CHECK: udiv{{[ ]}}
134 ; CHECK: msub{{[ ]}}
135 define %divovf32 @urem32(i32 %x, i32 %y) {
136 entry:
137 %remr = call %divovf32 @llvm.safe.urem.i32(i32 %x, i32 %y)
138 ret %divovf32 %remr
139 }
140 ; CHECK-LABEL: urem64
141 ; CHECK: udiv{{[ ]}}
142 ; CHECK: msub{{[ ]}}
143 define %divovf64 @urem64(i64 %x, i64 %y) {
144 entry:
145 %remr = call %divovf64 @llvm.safe.urem.i64(i64 %x, i64 %y)
146 ret %divovf64 %remr
147 }
148
149 !llvm.ident = !{!0}
150
151 !0 = metadata !{metadata !"clang version 3.5.0 "}
0 ; RUN: llc < %s -march=x86-64 | FileCheck %s
1 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
2
3 %divovf32 = type { i32, i1 }
4
5 declare %divovf32 @llvm.safe.sdiv.i32(i32, i32) nounwind readnone
6 declare %divovf32 @llvm.safe.udiv.i32(i32, i32) nounwind readnone
7
8 ; CHECK-LABEL: sdiv32_results_unused
9 ; CHECK: entry
10 ; CHECK-NEXT: ret
11 define void @sdiv32_results_unused(i32 %x, i32 %y) {
12 entry:
13 %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
14 ret void
15 }
16
17 ; CHECK-LABEL: sdiv32_div_result_unused
18 ; CHECK-NOT: idiv
19 define i1 @sdiv32_div_result_unused(i32 %x, i32 %y) {
20 entry:
21 %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
22 %bit = extractvalue %divovf32 %divr, 1
23 ret i1 %bit
24 }
25
26 ; CHECK-LABEL: sdiv32_flag_result_unused
27 ; CHECK: idiv
28 define i32 @sdiv32_flag_result_unused(i32 %x, i32 %y) {
29 entry:
30 %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
31 %div = extractvalue %divovf32 %divr, 0
32 ret i32 %div
33 }
34
35 ; CHECK-LABEL: sdiv32_result_returned
36 ; CHECK: idiv
37 define %divovf32 @sdiv32_result_returned(i32 %x, i32 %y) {
38 entry:
39 %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
40 ret %divovf32 %divr
41 }
42
43 ; CHECK-LABEL: udiv32_results_unused
44 ; CHECK: entry
45 ; CHECK-NEXT: ret
46 define void @udiv32_results_unused(i32 %x, i32 %y) {
47 entry:
48 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
49 ret void
50 }
51
52 ; CHECK-LABEL: udiv32_div_result_unused
53 ; CHECK-NOT: udiv{{[ ]}}
54 define i1 @udiv32_div_result_unused(i32 %x, i32 %y) {
55 entry:
56 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
57 %bit = extractvalue %divovf32 %divr, 1
58 ret i1 %bit
59 }
60
61 ; CHECK-LABEL: udiv32_flag_result_unused
62 ; CHECK-NOT: cb
63 ; CHECK: {{[ ]}}div
64 define i32 @udiv32_flag_result_unused(i32 %x, i32 %y) {
65 entry:
66 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
67 %div = extractvalue %divovf32 %divr, 0
68 ret i32 %div
69 }
70
71 ; CHECK-LABEL: udiv32_result_returned
72 ; CHECK: {{[ ]}}div
73 define %divovf32 @udiv32_result_returned(i32 %x, i32 %y) {
74 entry:
75 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
76 ret %divovf32 %divr
77 }
78
79 !llvm.ident = !{!0}
80
81 !0 = metadata !{metadata !"clang version 3.5.0 "}
0 ; RUN: llc < %s -march=x86-64 | FileCheck %s
1 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
2
3 %divovf8 = type { i8, i1 }
4 %divovf16 = type { i16, i1 }
5 %divovf32 = type { i32, i1 }
6 %divovf64 = type { i64, i1 }
7
8 declare %divovf8 @llvm.safe.sdiv.i8(i8, i8) nounwind readnone
9 declare %divovf16 @llvm.safe.sdiv.i16(i16, i16) nounwind readnone
10 declare %divovf32 @llvm.safe.sdiv.i32(i32, i32) nounwind readnone
11 declare %divovf64 @llvm.safe.sdiv.i64(i64, i64) nounwind readnone
12
13 declare %divovf8 @llvm.safe.srem.i8(i8, i8) nounwind readnone
14 declare %divovf16 @llvm.safe.srem.i16(i16, i16) nounwind readnone
15 declare %divovf32 @llvm.safe.srem.i32(i32, i32) nounwind readnone
16 declare %divovf64 @llvm.safe.srem.i64(i64, i64) nounwind readnone
17
18 declare %divovf8 @llvm.safe.udiv.i8(i8, i8) nounwind readnone
19 declare %divovf16 @llvm.safe.udiv.i16(i16, i16) nounwind readnone
20 declare %divovf32 @llvm.safe.udiv.i32(i32, i32) nounwind readnone
21 declare %divovf64 @llvm.safe.udiv.i64(i64, i64) nounwind readnone
22
23 declare %divovf8 @llvm.safe.urem.i8(i8, i8) nounwind readnone
24 declare %divovf16 @llvm.safe.urem.i16(i16, i16) nounwind readnone
25 declare %divovf32 @llvm.safe.urem.i32(i32, i32) nounwind readnone
26 declare %divovf64 @llvm.safe.urem.i64(i64, i64) nounwind readnone
27
28 ; CHECK-LABEL: sdiv8
29 ; CHECK: idivb{{[ ]}}
30 define %divovf8 @sdiv8(i8 %x, i8 %y) {
31 entry:
32 %divr = call %divovf8 @llvm.safe.sdiv.i8(i8 %x, i8 %y)
33 ret %divovf8 %divr
34 }
35 ; CHECK-LABEL: sdiv16
36 ; CHECK: idivw{{[ ]}}
37 define %divovf16 @sdiv16(i16 %x, i16 %y) {
38 entry:
39 %divr = call %divovf16 @llvm.safe.sdiv.i16(i16 %x, i16 %y)
40 ret %divovf16 %divr
41 }
42 ; CHECK-LABEL: sdiv32
43 ; CHECK: idivl{{[ ]}}
44 define %divovf32 @sdiv32(i32 %x, i32 %y) {
45 entry:
46 %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
47 ret %divovf32 %divr
48 }
49 ; CHECK-LABEL: sdiv64
50 ; CHECK: idivq{{[ ]}}
51 define %divovf64 @sdiv64(i64 %x, i64 %y) {
52 entry:
53 %divr = call %divovf64 @llvm.safe.sdiv.i64(i64 %x, i64 %y)
54 ret %divovf64 %divr
55 }
56 ; CHECK-LABEL: udiv8
57 ; CHECK: {{[ ]}}divb{{[ ]}}
58 define %divovf8 @udiv8(i8 %x, i8 %y) {
59 entry:
60 %divr = call %divovf8 @llvm.safe.udiv.i8(i8 %x, i8 %y)
61 ret %divovf8 %divr
62 }
63 ; CHECK-LABEL: udiv16
64 ; CHECK: {{[ ]}}divw{{[ ]}}
65 define %divovf16 @udiv16(i16 %x, i16 %y) {
66 entry:
67 %divr = call %divovf16 @llvm.safe.udiv.i16(i16 %x, i16 %y)
68 ret %divovf16 %divr
69 }
70 ; CHECK-LABEL: udiv32
71 ; CHECK: {{[ ]}}divl{{[ ]}}
72 define %divovf32 @udiv32(i32 %x, i32 %y) {
73 entry:
74 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
75 ret %divovf32 %divr
76 }
77 ; CHECK-LABEL: udiv64
78 ; CHECK: {{[ ]}}divq{{[ ]}}
79 define %divovf64 @udiv64(i64 %x, i64 %y) {
80 entry:
81 %divr = call %divovf64 @llvm.safe.udiv.i64(i64 %x, i64 %y)
82 ret %divovf64 %divr
83 }
84 ; CHECK-LABEL: srem8
85 ; CHECK: idivb{{[ ]}}
86 define %divovf8 @srem8(i8 %x, i8 %y) {
87 entry:
88 %remr = call %divovf8 @llvm.safe.srem.i8(i8 %x, i8 %y)
89 ret %divovf8 %remr
90 }
91 ; CHECK-LABEL: srem16
92 ; CHECK: idivw{{[ ]}}
93 define %divovf16 @srem16(i16 %x, i16 %y) {
94 entry:
95 %remr = call %divovf16 @llvm.safe.srem.i16(i16 %x, i16 %y)
96 ret %divovf16 %remr
97 }
98 ; CHECK-LABEL: srem32
99 ; CHECK: idivl{{[ ]}}
100 define %divovf32 @srem32(i32 %x, i32 %y) {
101 entry:
102 %remr = call %divovf32 @llvm.safe.srem.i32(i32 %x, i32 %y)
103 ret %divovf32 %remr
104 }
105 ; CHECK-LABEL: srem64
106 ; CHECK: idivq{{[ ]}}
107 define %divovf64 @srem64(i64 %x, i64 %y) {
108 entry:
109 %remr = call %divovf64 @llvm.safe.srem.i64(i64 %x, i64 %y)
110 ret %divovf64 %remr
111 }
112 ; CHECK-LABEL: urem8
113 ; CHECK: {{[ ]}}divb{{[ ]}}
114 define %divovf8 @urem8(i8 %x, i8 %y) {
115 entry:
116 %remr = call %divovf8 @llvm.safe.urem.i8(i8 %x, i8 %y)
117 ret %divovf8 %remr
118 }
119 ; CHECK-LABEL: urem16
120 ; CHECK: {{[ ]}}divw{{[ ]}}
121 define %divovf16 @urem16(i16 %x, i16 %y) {
122 entry:
123 %remr = call %divovf16 @llvm.safe.urem.i16(i16 %x, i16 %y)
124 ret %divovf16 %remr
125 }
126 ; CHECK-LABEL: urem32
127 ; CHECK: {{[ ]}}divl{{[ ]}}
128 define %divovf32 @urem32(i32 %x, i32 %y) {
129 entry:
130 %remr = call %divovf32 @llvm.safe.urem.i32(i32 %x, i32 %y)
131 ret %divovf32 %remr
132 }
133 ; CHECK-LABEL: urem64
134 ; CHECK: {{[ ]}}divq{{[ ]}}
135 define %divovf64 @urem64(i64 %x, i64 %y) {
136 entry:
137 %remr = call %divovf64 @llvm.safe.urem.i64(i64 %x, i64 %y)
138 ret %divovf64 %remr
139 }
140
141 !llvm.ident = !{!0}
142
143 !0 = metadata !{metadata !"clang version 3.5.0 "}