llvm.org GIT mirror llvm / 7d5100d
Implement builtins for safe division: safe.sdiv.iN, safe.udiv.iN, safe.srem.iN, safe.urem.iN (iN = i8, i16, i32, or i64). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206732 91177308-0d34-0410-b5e6-96231b3b80d8 Michael Zolotukhin 6 years ago
9 changed file(s) with 837 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 // Check if the flag is used to jump out to a 'trap' block
776 // If it's the case, we want to use this block directly when we create
777 // branches after comparing with 0 and comparing with -1 (signed case).
778 // We can do it only iff we can track all the uses of the flag, i.e. the
779 // only users are EXTRACTVALUE-insns, and their users are conditional
780 // branches, targeting the same 'trap' basic block.
781 BasicBlock *TrapBB = nullptr;
782 bool DoRelinkTrap = true;
783 for (User *FlagU: ResultsUsers[1]) {
784 for (User *U: FlagU->users()) {
785 BranchInst *TrapBranch = dyn_cast(U);
786 // If the user isn't a branch-insn, or it jumps to another BB, don't
787 // try to use TrapBB in the lowering.
788 if (!TrapBranch || (TrapBB && TrapBB != TrapBranch->getSuccessor(0))) {
789 DoRelinkTrap = false;
790 break;
791 }
792 TrapBB = TrapBranch->getSuccessor(0);
793 }
794 }
795 if (!TrapBB)
796 DoRelinkTrap = false;
797 // We want to reuse TrapBB if possible, because in that case we can avoid
798 // creating new basic blocks and thus overcomplicating the IR. However, if
799 // DIV instruction isn't well defined, we still need those blocks to model
800 // well-defined behaviour. Thus, we can't reuse TrapBB in this case.
801 if (!DivWellDefined)
802 DoRelinkTrap = false;
803
804 Value *MinusOne = Constant::getAllOnesValue(LHS->getType());
805 Value *Zero = Constant::getNullValue(LHS->getType());
806
807 // Split the original BB and create other basic blocks that will be used
808 // for checks.
809 BasicBlock *StartBB = II->getParent();
810 BasicBlock::iterator SplitPt = ++(BasicBlock::iterator(II));
811 BasicBlock *NextBB = StartBB->splitBasicBlock(SplitPt, "div.end");
812
813 BasicBlock *DivByZeroBB;
814 if (!DoRelinkTrap) {
815 DivByZeroBB = BasicBlock::Create(II->getContext(), "div.divz",
816 NextBB->getParent(), NextBB);
817 BranchInst::Create(NextBB, DivByZeroBB);
818 }
819 BasicBlock *DivBB = BasicBlock::Create(II->getContext(), "div.div",
820 NextBB->getParent(), NextBB);
821 BranchInst::Create(NextBB, DivBB);
822
823 // For signed variants, check the condition (2):
824 // LHS == SignedMinValue, RHS == -1.
825 Value *CmpMinusOne;
826 Value *CmpMinValue;
827 BasicBlock *ChkDivMinBB;
828 BasicBlock *DivMinBB;
829 Value *MinValue;
830 if (IsSigned) {
831 APInt SignedMinValue =
832 APInt::getSignedMinValue(LHS->getType()->getPrimitiveSizeInBits());
833 MinValue = Constant::getIntegerValue(LHS->getType(), SignedMinValue);
834 ChkDivMinBB = BasicBlock::Create(II->getContext(), "div.chkdivmin",
835 NextBB->getParent(), NextBB);
836 BranchInst::Create(NextBB, ChkDivMinBB);
837 if (!DoRelinkTrap) {
838 DivMinBB = BasicBlock::Create(II->getContext(), "div.divmin",
839 NextBB->getParent(), NextBB);
840 BranchInst::Create(NextBB, DivMinBB);
841 }
842 CmpMinusOne = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ,
843 RHS, MinusOne, "cmp.rhs.minus.one",
844 ChkDivMinBB->getTerminator());
845 CmpMinValue = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ,
846 LHS, MinValue, "cmp.lhs.signed.min",
847 ChkDivMinBB->getTerminator());
848 BinaryOperator *CmpSignedOvf = BinaryOperator::Create(Instruction::And,
849 CmpMinusOne,
850 CmpMinValue);
851 // Here we're interested in the case when both %x is TMin and %y is -1.
852 // In this case the result will overflow.
853 // If that's not the case, we can perform usual division. These blocks
854 // will be inserted after DivByZero, so the division will be safe.
855 CmpSignedOvf->insertBefore(ChkDivMinBB->getTerminator());
856 BranchInst::Create(DoRelinkTrap ? TrapBB : DivMinBB, DivBB, CmpSignedOvf,
857 ChkDivMinBB->getTerminator());
858 ChkDivMinBB->getTerminator()->eraseFromParent();
859 }
860
861 // Check the condition (1):
862 // RHS == 0.
863 Value *CmpDivZero = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ,
864 RHS, Zero, "cmp.rhs.zero",
865 StartBB->getTerminator());
866
867 // If RHS != 0, we want to check condition (2) in signed case, or proceed
868 // to usual division in unsigned case.
869 BranchInst::Create(DoRelinkTrap ? TrapBB : DivByZeroBB,
870 IsSigned ? ChkDivMinBB : DivBB, CmpDivZero,
871 StartBB->getTerminator());
872 StartBB->getTerminator()->eraseFromParent();
873
874 // At the moment we have all the control flow created. We just need to
875 // insert DIV and PHI (if needed) to get the result value.
876 Instruction *DivRes, *FlagRes;
877 Instruction *InsPoint = nullptr;
878 if (ResultNeeded[0]) {
879 BinaryOperator *Div = BinaryOperator::Create(Op, LHS, RHS);
880 if (DivWellDefined) {
881 // The result value is the result of DIV operation placed right at the
882 // original place of the intrinsic.
883 Div->insertAfter(II);
884 DivRes = Div;
885 } else {
886 // The result is a PHI-node.
887 Div->insertBefore(DivBB->getTerminator());
888 PHINode *DivResPN =
889 PHINode::Create(LHS->getType(), IsSigned ? 3 : 2, "div.res.phi",
890 NextBB->begin());
891 DivResPN->addIncoming(Div, DivBB);
892 DivResPN->addIncoming(Zero, DivByZeroBB);
893 if (IsSigned)
894 DivResPN->addIncoming(MinValue, DivMinBB);
895 DivRes = DivResPN;
896 InsPoint = DivResPN;
897 }
898 }
899
900 // Prepare a value for the second result (flag) if it is needed.
901 if (ResultNeeded[1] && !DoRelinkTrap) {
902 Type *FlagTy = II->getType()->getStructElementType(1);
903 PHINode *FlagResPN =
904 PHINode::Create(FlagTy, IsSigned ? 3 : 2, "div.flag.phi",
905 NextBB->begin());
906 FlagResPN->addIncoming(Constant::getNullValue(FlagTy), DivBB);
907 FlagResPN->addIncoming(Constant::getAllOnesValue(FlagTy), DivByZeroBB);
908 if (IsSigned)
909 FlagResPN->addIncoming(Constant::getAllOnesValue(FlagTy), DivMinBB);
910 FlagRes = FlagResPN;
911 if (!InsPoint)
912 InsPoint = FlagRes;
913 }
914
915 // If possible, propagate the results to the user. Otherwise, create alloca,
916 // and create a struct with the results on stack.
917 if (!BadCase) {
918 if (ResultNeeded[0]) {
919 for (User *U: ResultsUsers[0]) {
920 Instruction *UserInst = dyn_cast(U);
921 assert(UserInst && "Unexpected null-instruction");
922 UserInst->replaceAllUsesWith(DivRes);
923 UserInst->eraseFromParent();
924 }
925 }
926 if (ResultNeeded[1]) {
927 for (User *FlagU: ResultsUsers[1]) {
928 Instruction *FlagUInst = dyn_cast(FlagU);
929 if (DoRelinkTrap) {
930 // Replace
931 // %flag = extractvalue %intrinsic.res, 1
932 // br i1 %flag, label %trap.bb, label %other.bb
933 // With
934 // br label %other.bb
935 // We've already created checks that are pointing to %trap.bb, there
936 // is no need to have the same checks here.
937 for (User *U: FlagUInst->users()) {
938 BranchInst *TrapBranch = dyn_cast(U);
939 BasicBlock *CurBB = TrapBranch->getParent();
940 BasicBlock *SuccessorBB = TrapBranch->getSuccessor(1);
941 CurBB->getTerminator()->eraseFromParent();
942 BranchInst::Create(SuccessorBB, CurBB);
943 }
944 } else {
945 FlagUInst->replaceAllUsesWith(FlagRes);
946 }
947 dyn_cast(FlagUInst)->eraseFromParent();
948 }
949 }
950 } else {
951 // Create alloca, store our new values to it, and then load the final
952 // result from it.
953 Constant *Idx0 = ConstantInt::get(Type::getInt32Ty(II->getContext()), 0);
954 Constant *Idx1 = ConstantInt::get(Type::getInt32Ty(II->getContext()), 1);
955 Value *Idxs_DivRes[2] = {Idx0, Idx0};
956 Value *Idxs_FlagRes[2] = {Idx0, Idx1};
957 Value *NewRes = new llvm::AllocaInst(II->getType(), 0, "div.res.ptr", II);
958 Instruction *ResDivAddr = GetElementPtrInst::Create(NewRes, Idxs_DivRes);
959 Instruction *ResFlagAddr =
960 GetElementPtrInst::Create(NewRes, Idxs_FlagRes);
961 ResDivAddr->insertAfter(InsPoint);
962 ResFlagAddr->insertAfter(ResDivAddr);
963 StoreInst *StoreResDiv = new StoreInst(DivRes, ResDivAddr);
964 StoreInst *StoreResFlag = new StoreInst(FlagRes, ResFlagAddr);
965 StoreResDiv->insertAfter(ResFlagAddr);
966 StoreResFlag->insertAfter(StoreResDiv);
967 LoadInst *LoadRes = new LoadInst(NewRes, "div.res");
968 LoadRes->insertAfter(StoreResFlag);
969 II->replaceAllUsesWith(LoadRes);
970 }
971
972 II->eraseFromParent();
973 CurInstIterator = StartBB->end();
974 ModifiedDT = true;
975 return true;
976 }
690977
691978 if (II && TLI) {
692979 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: sdiv32_trap_relinked
45 ; CHECK-NOT: %div.divmin
46 ; CHECK-NOT: %div.divz
47 define i32 @sdiv32_trap_relinked(i32 %x, i32 %y) {
48 entry:
49 %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
50 %div = extractvalue %divovf32 %divr, 0
51 %bit = extractvalue %divovf32 %divr, 1
52 br i1 %bit, label %trap.bb, label %ok.bb
53 trap.bb:
54 ret i32 7
55 ok.bb:
56 ret i32 %div
57 }
58
59 ; CHECK-LABEL: udiv32_results_unused
60 ; CHECK: entry
61 ; CHECK-NEXT: ret
62 define void @udiv32_results_unused(i32 %x, i32 %y) {
63 entry:
64 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
65 ret void
66 }
67
68 ; CHECK-LABEL: udiv32_div_result_unused
69 ; CHECK-NOT: udiv{{[ ]}}
70 define i1 @udiv32_div_result_unused(i32 %x, i32 %y) {
71 entry:
72 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
73 %bit = extractvalue %divovf32 %divr, 1
74 ret i1 %bit
75 }
76
77 ; CHECK-LABEL: udiv32_flag_result_unused
78 ; CHECK-NOT: cb
79 ; CHECK: udiv{{[ ]}}
80 define i32 @udiv32_flag_result_unused(i32 %x, i32 %y) {
81 entry:
82 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
83 %div = extractvalue %divovf32 %divr, 0
84 ret i32 %div
85 }
86
87 ; CHECK-LABEL: udiv32_result_returned
88 ; CHECK: udiv{{[ ]}}
89 define %divovf32 @udiv32_result_returned(i32 %x, i32 %y) {
90 entry:
91 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
92 ret %divovf32 %divr
93 }
94
95 ; CHECK-LABEL: udiv32_trap_relinked
96 ; CHECK-NOT: %div.divz
97 define i32 @udiv32_trap_relinked(i32 %x, i32 %y) {
98 entry:
99 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
100 %div = extractvalue %divovf32 %divr, 0
101 %bit = extractvalue %divovf32 %divr, 1
102 br i1 %bit, label %trap.bb, label %ok.bb
103 trap.bb:
104 ret i32 7
105 ok.bb:
106 ret i32 %div
107 }
108
109 !llvm.ident = !{!0}
110
111 !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 | 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: sdiv32_trap_relinked
44 ; CHECK: %div.div{{min|z}}
45 define i32 @sdiv32_trap_relinked(i32 %x, i32 %y) {
46 entry:
47 %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
48 %div = extractvalue %divovf32 %divr, 0
49 %bit = extractvalue %divovf32 %divr, 1
50 br i1 %bit, label %trap.bb, label %ok.bb
51 trap.bb:
52 ret i32 7
53 ok.bb:
54 ret i32 %div
55 }
56
57 ; CHECK-LABEL: udiv32_results_unused
58 ; CHECK: entry
59 ; CHECK-NEXT: ret
60 define void @udiv32_results_unused(i32 %x, i32 %y) {
61 entry:
62 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
63 ret void
64 }
65
66 ; CHECK-LABEL: udiv32_div_result_unused
67 ; CHECK-NOT: udiv{{[ ]}}
68 define i1 @udiv32_div_result_unused(i32 %x, i32 %y) {
69 entry:
70 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
71 %bit = extractvalue %divovf32 %divr, 1
72 ret i1 %bit
73 }
74
75 ; CHECK-LABEL: udiv32_flag_result_unused
76 ; CHECK-NOT: cb
77 ; CHECK: {{[ ]}}div
78 define i32 @udiv32_flag_result_unused(i32 %x, i32 %y) {
79 entry:
80 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
81 %div = extractvalue %divovf32 %divr, 0
82 ret i32 %div
83 }
84
85 ; CHECK-LABEL: udiv32_result_returned
86 ; CHECK: {{[ ]}}div
87 define %divovf32 @udiv32_result_returned(i32 %x, i32 %y) {
88 entry:
89 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
90 ret %divovf32 %divr
91 }
92
93 ; CHECK-LABEL: udiv32_trap_relinked
94 ; CHECK: %div.divz
95 define i32 @udiv32_trap_relinked(i32 %x, i32 %y) {
96 entry:
97 %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
98 %div = extractvalue %divovf32 %divr, 0
99 %bit = extractvalue %divovf32 %divr, 1
100 br i1 %bit, label %trap.bb, label %ok.bb
101 trap.bb:
102 ret i32 7
103 ok.bb:
104 ret i32 %div
105 }
106
107 !llvm.ident = !{!0}
108
109 !0 = metadata !{metadata !"clang version 3.5.0 "}
0 ; RUN: llc < %s | 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 "}